@aomi-labs/react 0.3.5 → 0.3.7
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 +426 -619
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -57
- package/dist/index.d.ts +58 -57
- package/dist/index.js +443 -646
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17,6 +17,19 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __restKey = (key) => typeof key === "symbol" ? key : key + "";
|
|
21
|
+
var __objRest = (source, exclude) => {
|
|
22
|
+
var target = {};
|
|
23
|
+
for (var prop in source)
|
|
24
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
if (source != null && __getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
}
|
|
31
|
+
return target;
|
|
32
|
+
};
|
|
20
33
|
|
|
21
34
|
// packages/react/src/index.ts
|
|
22
35
|
import { AomiClient as AomiClient2 } from "@aomi-labs/client";
|
|
@@ -210,6 +223,25 @@ var ThreadStore = class {
|
|
|
210
223
|
// packages/react/src/contexts/control-context.tsx
|
|
211
224
|
import { jsx } from "react/jsx-runtime";
|
|
212
225
|
var API_KEY_STORAGE_KEY = "aomi_api_key";
|
|
226
|
+
var CLIENT_ID_STORAGE_KEY = "aomi_client_id";
|
|
227
|
+
var PROVIDER_KEYS_STORAGE_KEY = "aomi_provider_keys";
|
|
228
|
+
var PROVIDER_KEY_SECRET_PREFIX = "PROVIDER_KEY:";
|
|
229
|
+
function getOrCreateClientId() {
|
|
230
|
+
var _a, _b, _c, _d, _e;
|
|
231
|
+
try {
|
|
232
|
+
const storedClientId = (_a = globalThis.localStorage) == null ? void 0 : _a.getItem(CLIENT_ID_STORAGE_KEY);
|
|
233
|
+
if (storedClientId && storedClientId.trim().length > 0) {
|
|
234
|
+
return storedClientId;
|
|
235
|
+
}
|
|
236
|
+
} catch (e) {
|
|
237
|
+
}
|
|
238
|
+
const clientId = (_d = (_c = (_b = globalThis.crypto) == null ? void 0 : _b.randomUUID) == null ? void 0 : _c.call(_b)) != null ? _d : `client-${Date.now()}`;
|
|
239
|
+
try {
|
|
240
|
+
(_e = globalThis.localStorage) == null ? void 0 : _e.setItem(CLIENT_ID_STORAGE_KEY, clientId);
|
|
241
|
+
} catch (e) {
|
|
242
|
+
}
|
|
243
|
+
return clientId;
|
|
244
|
+
}
|
|
213
245
|
function getDefaultApp(apps) {
|
|
214
246
|
var _a;
|
|
215
247
|
return apps.includes("default") ? "default" : (_a = apps[0]) != null ? _a : null;
|
|
@@ -239,11 +271,12 @@ function ControlContextProvider({
|
|
|
239
271
|
var _a, _b;
|
|
240
272
|
const [state, setStateInternal] = useState(() => ({
|
|
241
273
|
apiKey: null,
|
|
242
|
-
clientId:
|
|
274
|
+
clientId: getOrCreateClientId(),
|
|
243
275
|
availableModels: [],
|
|
244
276
|
authorizedApps: [],
|
|
245
277
|
defaultModel: null,
|
|
246
|
-
defaultApp: null
|
|
278
|
+
defaultApp: null,
|
|
279
|
+
providerKeys: {}
|
|
247
280
|
}));
|
|
248
281
|
const stateRef = useRef(state);
|
|
249
282
|
stateRef.current = state;
|
|
@@ -261,10 +294,14 @@ function ControlContextProvider({
|
|
|
261
294
|
const currentThreadMetadata = getThreadMetadata(sessionId);
|
|
262
295
|
const isProcessing = (_b = (_a = currentThreadMetadata == null ? void 0 : currentThreadMetadata.control) == null ? void 0 : _a.isProcessing) != null ? _b : false;
|
|
263
296
|
useEffect(() => {
|
|
264
|
-
var _a2
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
297
|
+
var _a2;
|
|
298
|
+
try {
|
|
299
|
+
if (state.clientId) {
|
|
300
|
+
(_a2 = globalThis.localStorage) == null ? void 0 : _a2.setItem(CLIENT_ID_STORAGE_KEY, state.clientId);
|
|
301
|
+
}
|
|
302
|
+
} catch (e) {
|
|
303
|
+
}
|
|
304
|
+
}, [state.clientId]);
|
|
268
305
|
useEffect(() => {
|
|
269
306
|
var _a2, _b2;
|
|
270
307
|
try {
|
|
@@ -275,6 +312,17 @@ function ControlContextProvider({
|
|
|
275
312
|
} catch (e) {
|
|
276
313
|
}
|
|
277
314
|
}, []);
|
|
315
|
+
useEffect(() => {
|
|
316
|
+
var _a2;
|
|
317
|
+
try {
|
|
318
|
+
const raw = (_a2 = globalThis.localStorage) == null ? void 0 : _a2.getItem(PROVIDER_KEYS_STORAGE_KEY);
|
|
319
|
+
if (raw) {
|
|
320
|
+
const parsed = JSON.parse(raw);
|
|
321
|
+
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), { providerKeys: parsed }));
|
|
322
|
+
}
|
|
323
|
+
} catch (e) {
|
|
324
|
+
}
|
|
325
|
+
}, []);
|
|
278
326
|
useEffect(() => {
|
|
279
327
|
var _a2, _b2;
|
|
280
328
|
try {
|
|
@@ -286,6 +334,33 @@ function ControlContextProvider({
|
|
|
286
334
|
} catch (e) {
|
|
287
335
|
}
|
|
288
336
|
}, [state.apiKey]);
|
|
337
|
+
useEffect(() => {
|
|
338
|
+
var _a2, _b2;
|
|
339
|
+
try {
|
|
340
|
+
const keys = state.providerKeys;
|
|
341
|
+
if (Object.keys(keys).length > 0) {
|
|
342
|
+
(_a2 = globalThis.localStorage) == null ? void 0 : _a2.setItem(
|
|
343
|
+
PROVIDER_KEYS_STORAGE_KEY,
|
|
344
|
+
JSON.stringify(keys)
|
|
345
|
+
);
|
|
346
|
+
} else {
|
|
347
|
+
(_b2 = globalThis.localStorage) == null ? void 0 : _b2.removeItem(PROVIDER_KEYS_STORAGE_KEY);
|
|
348
|
+
}
|
|
349
|
+
} catch (e) {
|
|
350
|
+
}
|
|
351
|
+
}, [state.providerKeys]);
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
if (!state.clientId) return;
|
|
354
|
+
const keys = stateRef.current.providerKeys;
|
|
355
|
+
if (Object.keys(keys).length === 0) return;
|
|
356
|
+
const secrets = {};
|
|
357
|
+
for (const [provider, entry] of Object.entries(keys)) {
|
|
358
|
+
secrets[`${PROVIDER_KEY_SECRET_PREFIX}${provider}`] = entry.apiKey;
|
|
359
|
+
}
|
|
360
|
+
void aomiClientRef.current.ingestSecrets(state.clientId, secrets).catch((err) => {
|
|
361
|
+
console.error("Failed to auto-ingest provider keys:", err);
|
|
362
|
+
});
|
|
363
|
+
}, [state.clientId, state.providerKeys]);
|
|
289
364
|
useEffect(() => {
|
|
290
365
|
const fetchApps = async () => {
|
|
291
366
|
var _a2;
|
|
@@ -356,6 +431,65 @@ function ControlContextProvider({
|
|
|
356
431
|
if (!clientId) return;
|
|
357
432
|
await ((_b2 = (_a2 = aomiClientRef.current).clearSecrets) == null ? void 0 : _b2.call(_a2, clientId));
|
|
358
433
|
}, []);
|
|
434
|
+
const setProviderKey = useCallback(
|
|
435
|
+
async (provider, apiKey, label) => {
|
|
436
|
+
const trimmed = apiKey.trim();
|
|
437
|
+
if (!trimmed) return;
|
|
438
|
+
const entry = {
|
|
439
|
+
apiKey: trimmed,
|
|
440
|
+
keyPrefix: trimmed.slice(0, 7),
|
|
441
|
+
label
|
|
442
|
+
};
|
|
443
|
+
setStateInternal((prev) => {
|
|
444
|
+
const next = __spreadProps(__spreadValues({}, prev), {
|
|
445
|
+
providerKeys: __spreadProps(__spreadValues({}, prev.providerKeys), { [provider]: entry })
|
|
446
|
+
});
|
|
447
|
+
callbacks.current.forEach((cb) => cb(next));
|
|
448
|
+
return next;
|
|
449
|
+
});
|
|
450
|
+
const clientId = stateRef.current.clientId;
|
|
451
|
+
if (clientId) {
|
|
452
|
+
try {
|
|
453
|
+
await aomiClientRef.current.ingestSecrets(clientId, {
|
|
454
|
+
[`${PROVIDER_KEY_SECRET_PREFIX}${provider}`]: trimmed
|
|
455
|
+
});
|
|
456
|
+
} catch (err) {
|
|
457
|
+
console.error("Failed to ingest provider key:", err);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
[]
|
|
462
|
+
);
|
|
463
|
+
const removeProviderKey = useCallback(
|
|
464
|
+
async (provider) => {
|
|
465
|
+
const clientId = stateRef.current.clientId;
|
|
466
|
+
if (clientId) {
|
|
467
|
+
await aomiClientRef.current.deleteSecret(
|
|
468
|
+
clientId,
|
|
469
|
+
`${PROVIDER_KEY_SECRET_PREFIX}${provider}`
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
setStateInternal((prev) => {
|
|
473
|
+
const _a2 = prev.providerKeys, { [provider]: _ } = _a2, rest = __objRest(_a2, [__restKey(provider)]);
|
|
474
|
+
const next = __spreadProps(__spreadValues({}, prev), { providerKeys: rest });
|
|
475
|
+
callbacks.current.forEach((cb) => cb(next));
|
|
476
|
+
return next;
|
|
477
|
+
});
|
|
478
|
+
},
|
|
479
|
+
[]
|
|
480
|
+
);
|
|
481
|
+
const getProviderKeys = useCallback(
|
|
482
|
+
() => stateRef.current.providerKeys,
|
|
483
|
+
[]
|
|
484
|
+
);
|
|
485
|
+
const hasProviderKey = useCallback(
|
|
486
|
+
(provider) => {
|
|
487
|
+
const keys = stateRef.current.providerKeys;
|
|
488
|
+
if (provider) return provider in keys;
|
|
489
|
+
return Object.keys(keys).length > 0;
|
|
490
|
+
},
|
|
491
|
+
[]
|
|
492
|
+
);
|
|
359
493
|
const getAvailableModels = useCallback(async () => {
|
|
360
494
|
try {
|
|
361
495
|
const models = await aomiClientRef.current.getModels(
|
|
@@ -414,7 +548,7 @@ function ControlContextProvider({
|
|
|
414
548
|
)) != null ? _c : "default";
|
|
415
549
|
}, []);
|
|
416
550
|
const onModelSelect = useCallback(async (model) => {
|
|
417
|
-
var _a2, _b2, _c, _d;
|
|
551
|
+
var _a2, _b2, _c, _d, _e;
|
|
418
552
|
const threadId = sessionIdRef.current;
|
|
419
553
|
const currentControl = (_b2 = (_a2 = getThreadMetadataRef.current(threadId)) == null ? void 0 : _a2.control) != null ? _b2 : initThreadControl();
|
|
420
554
|
const isProcessing2 = currentControl.isProcessing;
|
|
@@ -455,7 +589,11 @@ function ControlContextProvider({
|
|
|
455
589
|
const result = await aomiClientRef.current.setModel(
|
|
456
590
|
threadId,
|
|
457
591
|
model,
|
|
458
|
-
{
|
|
592
|
+
{
|
|
593
|
+
app,
|
|
594
|
+
apiKey: (_d = stateRef.current.apiKey) != null ? _d : void 0,
|
|
595
|
+
clientId: (_e = stateRef.current.clientId) != null ? _e : void 0
|
|
596
|
+
}
|
|
459
597
|
);
|
|
460
598
|
console.log("[control-context] onModelSelect backend result", result);
|
|
461
599
|
} catch (err) {
|
|
@@ -538,6 +676,10 @@ function ControlContextProvider({
|
|
|
538
676
|
setApiKey,
|
|
539
677
|
ingestSecrets,
|
|
540
678
|
clearSecrets,
|
|
679
|
+
setProviderKey,
|
|
680
|
+
removeProviderKey,
|
|
681
|
+
getProviderKeys,
|
|
682
|
+
hasProviderKey,
|
|
541
683
|
getAvailableModels,
|
|
542
684
|
getAuthorizedApps,
|
|
543
685
|
getCurrentThreadControl,
|
|
@@ -560,62 +702,8 @@ import {
|
|
|
560
702
|
createContext as createContext2,
|
|
561
703
|
useCallback as useCallback2,
|
|
562
704
|
useContext as useContext2,
|
|
563
|
-
|
|
564
|
-
useRef as useRef2,
|
|
565
|
-
useState as useState2
|
|
705
|
+
useRef as useRef2
|
|
566
706
|
} 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
707
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
620
708
|
var EventContextState = createContext2(null);
|
|
621
709
|
function useEventContext() {
|
|
@@ -632,52 +720,32 @@ function EventContextProvider({
|
|
|
632
720
|
aomiClient,
|
|
633
721
|
sessionId
|
|
634
722
|
}) {
|
|
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(
|
|
723
|
+
const subscribersRef = useRef2(/* @__PURE__ */ new Map());
|
|
724
|
+
const subscribe = useCallback2(
|
|
676
725
|
(type, callback) => {
|
|
677
|
-
|
|
726
|
+
const subs = subscribersRef.current;
|
|
727
|
+
if (!subs.has(type)) {
|
|
728
|
+
subs.set(type, /* @__PURE__ */ new Set());
|
|
729
|
+
}
|
|
730
|
+
subs.get(type).add(callback);
|
|
731
|
+
return () => {
|
|
732
|
+
var _a;
|
|
733
|
+
(_a = subs.get(type)) == null ? void 0 : _a.delete(callback);
|
|
734
|
+
};
|
|
678
735
|
},
|
|
679
|
-
[
|
|
736
|
+
[]
|
|
680
737
|
);
|
|
738
|
+
const dispatchEvent = useCallback2((event) => {
|
|
739
|
+
const subs = subscribersRef.current;
|
|
740
|
+
const typeSubs = subs.get(event.type);
|
|
741
|
+
if (typeSubs) {
|
|
742
|
+
for (const cb of typeSubs) cb(event);
|
|
743
|
+
}
|
|
744
|
+
const wildcardSubs = subs.get("*");
|
|
745
|
+
if (wildcardSubs) {
|
|
746
|
+
for (const cb of wildcardSubs) cb(event);
|
|
747
|
+
}
|
|
748
|
+
}, []);
|
|
681
749
|
const sendOutbound = useCallback2(
|
|
682
750
|
async (event) => {
|
|
683
751
|
try {
|
|
@@ -692,50 +760,14 @@ function EventContextProvider({
|
|
|
692
760
|
},
|
|
693
761
|
[aomiClient]
|
|
694
762
|
);
|
|
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
763
|
const contextValue = {
|
|
735
|
-
subscribe
|
|
764
|
+
subscribe,
|
|
765
|
+
dispatch: dispatchEvent,
|
|
736
766
|
sendOutboundSystem: sendOutbound,
|
|
737
|
-
|
|
738
|
-
|
|
767
|
+
// SSE is managed by ClientSession now — status is always "connected"
|
|
768
|
+
// when sessions are active. Individual session status can be queried
|
|
769
|
+
// from the session manager if needed.
|
|
770
|
+
sseStatus: "connected"
|
|
739
771
|
};
|
|
740
772
|
return /* @__PURE__ */ jsx2(EventContextState.Provider, { value: contextValue, children });
|
|
741
773
|
}
|
|
@@ -745,7 +777,7 @@ import {
|
|
|
745
777
|
createContext as createContext3,
|
|
746
778
|
useCallback as useCallback3,
|
|
747
779
|
useContext as useContext3,
|
|
748
|
-
useState as
|
|
780
|
+
useState as useState2
|
|
749
781
|
} from "react";
|
|
750
782
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
751
783
|
var NotificationContext = createContext3(null);
|
|
@@ -765,7 +797,7 @@ function generateId() {
|
|
|
765
797
|
function NotificationContextProvider({
|
|
766
798
|
children
|
|
767
799
|
}) {
|
|
768
|
-
const [notifications, setNotifications] =
|
|
800
|
+
const [notifications, setNotifications] = useState2([]);
|
|
769
801
|
const showNotification = useCallback3((params) => {
|
|
770
802
|
const id = generateId();
|
|
771
803
|
const notification = __spreadProps(__spreadValues({}, params), {
|
|
@@ -846,7 +878,7 @@ import {
|
|
|
846
878
|
useCallback as useCallback4,
|
|
847
879
|
useContext as useContext5,
|
|
848
880
|
useRef as useRef4,
|
|
849
|
-
useState as
|
|
881
|
+
useState as useState3
|
|
850
882
|
} from "react";
|
|
851
883
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
852
884
|
var UserContext = createContext5(void 0);
|
|
@@ -865,7 +897,7 @@ function useUser() {
|
|
|
865
897
|
};
|
|
866
898
|
}
|
|
867
899
|
function UserContextProvider({ children }) {
|
|
868
|
-
const [user, setUserState] =
|
|
900
|
+
const [user, setUserState] = useState3({
|
|
869
901
|
isConnected: false,
|
|
870
902
|
address: void 0,
|
|
871
903
|
chainId: void 0,
|
|
@@ -943,14 +975,48 @@ function UserContextProvider({ children }) {
|
|
|
943
975
|
}
|
|
944
976
|
|
|
945
977
|
// packages/react/src/runtime/core.tsx
|
|
946
|
-
import { useCallback as useCallback7, useEffect as
|
|
978
|
+
import { useCallback as useCallback7, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef7 } from "react";
|
|
947
979
|
import {
|
|
948
980
|
AssistantRuntimeProvider,
|
|
949
981
|
useExternalStoreRuntime
|
|
950
982
|
} from "@assistant-ui/react";
|
|
951
983
|
|
|
952
984
|
// packages/react/src/runtime/orchestrator.ts
|
|
953
|
-
import { useCallback as useCallback5, useRef as useRef5, useState as
|
|
985
|
+
import { useCallback as useCallback5, useEffect as useEffect2, useRef as useRef5, useState as useState4 } from "react";
|
|
986
|
+
|
|
987
|
+
// packages/react/src/runtime/session-manager.ts
|
|
988
|
+
import { Session as ClientSession } from "@aomi-labs/client";
|
|
989
|
+
var SessionManager = class {
|
|
990
|
+
constructor(clientFactory) {
|
|
991
|
+
this.clientFactory = clientFactory;
|
|
992
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
993
|
+
}
|
|
994
|
+
getOrCreate(threadId, opts) {
|
|
995
|
+
let session = this.sessions.get(threadId);
|
|
996
|
+
if (session) return session;
|
|
997
|
+
session = new ClientSession(this.clientFactory(), __spreadProps(__spreadValues({}, opts), {
|
|
998
|
+
sessionId: threadId
|
|
999
|
+
}));
|
|
1000
|
+
this.sessions.set(threadId, session);
|
|
1001
|
+
return session;
|
|
1002
|
+
}
|
|
1003
|
+
get(threadId) {
|
|
1004
|
+
return this.sessions.get(threadId);
|
|
1005
|
+
}
|
|
1006
|
+
close(threadId) {
|
|
1007
|
+
const session = this.sessions.get(threadId);
|
|
1008
|
+
if (session) {
|
|
1009
|
+
session.close();
|
|
1010
|
+
this.sessions.delete(threadId);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
closeAll() {
|
|
1014
|
+
for (const [threadId, session] of this.sessions) {
|
|
1015
|
+
session.close();
|
|
1016
|
+
}
|
|
1017
|
+
this.sessions.clear();
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
954
1020
|
|
|
955
1021
|
// packages/react/src/runtime/utils.ts
|
|
956
1022
|
import { clsx } from "clsx";
|
|
@@ -1054,194 +1120,6 @@ var SUPPORTED_CHAINS = [
|
|
|
1054
1120
|
];
|
|
1055
1121
|
var getChainInfo = (chainId) => chainId === void 0 ? void 0 : SUPPORTED_CHAINS.find((c) => c.id === chainId);
|
|
1056
1122
|
|
|
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
1123
|
// packages/react/src/runtime/orchestrator.ts
|
|
1246
1124
|
function useRuntimeOrchestrator(aomiClient, options) {
|
|
1247
1125
|
const threadContext = useThreadContext();
|
|
@@ -1249,90 +1127,160 @@ function useRuntimeOrchestrator(aomiClient, options) {
|
|
|
1249
1127
|
threadContextRef.current = threadContext;
|
|
1250
1128
|
const aomiClientRef = useRef5(aomiClient);
|
|
1251
1129
|
aomiClientRef.current = aomiClient;
|
|
1252
|
-
const
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1130
|
+
const [isRunning, setIsRunning] = useState4(false);
|
|
1131
|
+
const sessionManagerRef = useRef5(null);
|
|
1132
|
+
if (!sessionManagerRef.current) {
|
|
1133
|
+
sessionManagerRef.current = new SessionManager(() => aomiClientRef.current);
|
|
1134
|
+
}
|
|
1256
1135
|
const pendingFetches = useRef5(/* @__PURE__ */ new Set());
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1136
|
+
const listenerCleanups = useRef5(/* @__PURE__ */ new Map());
|
|
1137
|
+
const getSession = useCallback5(
|
|
1138
|
+
(threadId) => {
|
|
1139
|
+
var _a, _b, _c, _d, _e;
|
|
1140
|
+
const manager = sessionManagerRef.current;
|
|
1141
|
+
const existing = manager.get(threadId);
|
|
1142
|
+
if (existing) return existing;
|
|
1143
|
+
const session = manager.getOrCreate(threadId, {
|
|
1144
|
+
app: options.getApp(),
|
|
1145
|
+
publicKey: (_a = options.getPublicKey) == null ? void 0 : _a.call(options),
|
|
1146
|
+
apiKey: (_c = (_b = options.getApiKey) == null ? void 0 : _b.call(options)) != null ? _c : void 0,
|
|
1147
|
+
clientId: (_d = options.getClientId) == null ? void 0 : _d.call(options),
|
|
1148
|
+
userState: (_e = options.getUserState) == null ? void 0 : _e.call(options)
|
|
1149
|
+
});
|
|
1150
|
+
const cleanups = [];
|
|
1151
|
+
cleanups.push(
|
|
1152
|
+
session.on("messages", (msgs) => {
|
|
1153
|
+
const threadMessages = [];
|
|
1154
|
+
for (const msg of msgs) {
|
|
1155
|
+
const converted = toInboundMessage(msg);
|
|
1156
|
+
if (converted) threadMessages.push(converted);
|
|
1157
|
+
}
|
|
1158
|
+
threadContextRef.current.setThreadMessages(threadId, threadMessages);
|
|
1159
|
+
})
|
|
1160
|
+
);
|
|
1161
|
+
cleanups.push(
|
|
1162
|
+
session.on("processing_start", () => {
|
|
1163
|
+
if (threadContextRef.current.currentThreadId === threadId) {
|
|
1164
|
+
setIsRunning(true);
|
|
1165
|
+
}
|
|
1166
|
+
})
|
|
1167
|
+
);
|
|
1168
|
+
cleanups.push(
|
|
1169
|
+
session.on("processing_end", () => {
|
|
1170
|
+
if (threadContextRef.current.currentThreadId === threadId) {
|
|
1171
|
+
setIsRunning(false);
|
|
1172
|
+
}
|
|
1173
|
+
})
|
|
1174
|
+
);
|
|
1175
|
+
cleanups.push(
|
|
1176
|
+
session.on("wallet_tx_request", (req) => {
|
|
1177
|
+
var _a2;
|
|
1178
|
+
return (_a2 = options.onWalletRequest) == null ? void 0 : _a2.call(options, req);
|
|
1179
|
+
})
|
|
1180
|
+
);
|
|
1181
|
+
cleanups.push(
|
|
1182
|
+
session.on("wallet_eip712_request", (req) => {
|
|
1183
|
+
var _a2;
|
|
1184
|
+
return (_a2 = options.onWalletRequest) == null ? void 0 : _a2.call(options, req);
|
|
1185
|
+
})
|
|
1186
|
+
);
|
|
1187
|
+
cleanups.push(
|
|
1188
|
+
session.on("title_changed", ({ title }) => {
|
|
1189
|
+
threadContextRef.current.updateThreadMetadata(threadId, { title });
|
|
1190
|
+
})
|
|
1191
|
+
);
|
|
1192
|
+
const forwardEvent = (type) => session.on(type, (payload) => {
|
|
1193
|
+
var _a2;
|
|
1194
|
+
(_a2 = options.onEvent) == null ? void 0 : _a2.call(options, { type, payload, sessionId: threadId });
|
|
1195
|
+
});
|
|
1196
|
+
cleanups.push(forwardEvent("tool_update"));
|
|
1197
|
+
cleanups.push(forwardEvent("tool_complete"));
|
|
1198
|
+
cleanups.push(forwardEvent("system_notice"));
|
|
1199
|
+
cleanups.push(forwardEvent("system_error"));
|
|
1200
|
+
cleanups.push(forwardEvent("async_callback"));
|
|
1201
|
+
listenerCleanups.current.set(threadId, () => {
|
|
1202
|
+
for (const cleanup of cleanups) cleanup();
|
|
1203
|
+
});
|
|
1204
|
+
return session;
|
|
1205
|
+
},
|
|
1206
|
+
// Stable deps — option getters are refs
|
|
1207
|
+
[]
|
|
1208
|
+
);
|
|
1209
|
+
const ensureInitialState = useCallback5(
|
|
1210
|
+
async (threadId) => {
|
|
1211
|
+
var _a;
|
|
1212
|
+
if (pendingFetches.current.has(threadId)) return;
|
|
1213
|
+
pendingFetches.current.add(threadId);
|
|
1214
|
+
try {
|
|
1215
|
+
const session = getSession(threadId);
|
|
1216
|
+
const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
|
|
1217
|
+
if (userState) session.resolveUserState(userState);
|
|
1218
|
+
await session.fetchCurrentState();
|
|
1269
1219
|
if (threadContextRef.current.currentThreadId === threadId) {
|
|
1270
|
-
setIsRunning(
|
|
1220
|
+
setIsRunning(session.getIsProcessing());
|
|
1271
1221
|
}
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1222
|
+
} catch (error) {
|
|
1223
|
+
console.error("Failed to fetch initial state:", error);
|
|
1274
1224
|
if (threadContextRef.current.currentThreadId === threadId) {
|
|
1275
1225
|
setIsRunning(false);
|
|
1276
1226
|
}
|
|
1227
|
+
} finally {
|
|
1228
|
+
pendingFetches.current.delete(threadId);
|
|
1277
1229
|
}
|
|
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 {
|
|
1230
|
+
},
|
|
1231
|
+
[getSession]
|
|
1232
|
+
);
|
|
1233
|
+
const sendMessage = useCallback5(
|
|
1234
|
+
async (text, threadId) => {
|
|
1235
|
+
var _a;
|
|
1236
|
+
const session = getSession(threadId);
|
|
1301
1237
|
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
|
-
|
|
1238
|
+
if (userState) session.resolveUserState(userState);
|
|
1239
|
+
const existingMessages = threadContextRef.current.getThreadMessages(threadId);
|
|
1240
|
+
const userMessage = {
|
|
1241
|
+
role: "user",
|
|
1242
|
+
content: [{ type: "text", text }],
|
|
1243
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
1244
|
+
};
|
|
1245
|
+
threadContextRef.current.setThreadMessages(threadId, [
|
|
1246
|
+
...existingMessages,
|
|
1247
|
+
userMessage
|
|
1248
|
+
]);
|
|
1249
|
+
threadContextRef.current.updateThreadMetadata(threadId, {
|
|
1250
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1251
|
+
});
|
|
1252
|
+
await session.sendAsync(text);
|
|
1253
|
+
},
|
|
1254
|
+
[getSession]
|
|
1255
|
+
);
|
|
1256
|
+
const cancelGeneration = useCallback5(
|
|
1257
|
+
async (threadId) => {
|
|
1258
|
+
var _a;
|
|
1259
|
+
const session = (_a = sessionManagerRef.current) == null ? void 0 : _a.get(threadId);
|
|
1260
|
+
if (session) {
|
|
1261
|
+
await session.interrupt();
|
|
1319
1262
|
}
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1263
|
+
},
|
|
1264
|
+
[]
|
|
1265
|
+
);
|
|
1266
|
+
useEffect2(() => {
|
|
1267
|
+
return () => {
|
|
1268
|
+
var _a;
|
|
1269
|
+
(_a = sessionManagerRef.current) == null ? void 0 : _a.closeAll();
|
|
1270
|
+
for (const cleanup of listenerCleanups.current.values()) {
|
|
1271
|
+
cleanup();
|
|
1324
1272
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
}
|
|
1273
|
+
listenerCleanups.current.clear();
|
|
1274
|
+
};
|
|
1328
1275
|
}, []);
|
|
1329
1276
|
return {
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
messageController: messageControllerRef.current,
|
|
1277
|
+
sessionManager: sessionManagerRef.current,
|
|
1278
|
+
getSession,
|
|
1333
1279
|
isRunning,
|
|
1334
1280
|
setIsRunning,
|
|
1335
1281
|
ensureInitialState,
|
|
1282
|
+
sendMessage,
|
|
1283
|
+
cancelGeneration,
|
|
1336
1284
|
aomiClientRef
|
|
1337
1285
|
};
|
|
1338
1286
|
}
|
|
@@ -1484,154 +1432,49 @@ function useAomiRuntime() {
|
|
|
1484
1432
|
}
|
|
1485
1433
|
|
|
1486
1434
|
// 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
|
|
1435
|
+
import { useCallback as useCallback6, useRef as useRef6, useState as useState5 } from "react";
|
|
1524
1436
|
function useWalletHandler({
|
|
1525
|
-
|
|
1526
|
-
onRequestComplete
|
|
1437
|
+
getSession
|
|
1527
1438
|
}) {
|
|
1528
|
-
const
|
|
1529
|
-
const
|
|
1530
|
-
const
|
|
1531
|
-
|
|
1532
|
-
setPendingRequests(
|
|
1439
|
+
const [pendingRequests, setPendingRequests] = useState5([]);
|
|
1440
|
+
const requestsRef = useRef6([]);
|
|
1441
|
+
const enqueueRequest = useCallback6((request) => {
|
|
1442
|
+
requestsRef.current = [...requestsRef.current, request];
|
|
1443
|
+
setPendingRequests(requestsRef.current);
|
|
1533
1444
|
}, []);
|
|
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
1445
|
const resolveRequest = useCallback6(
|
|
1569
1446
|
(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
|
-
});
|
|
1447
|
+
const session = getSession();
|
|
1448
|
+
if (!session) {
|
|
1449
|
+
console.error("[wallet-handler] No session available to resolve request");
|
|
1450
|
+
return;
|
|
1595
1451
|
}
|
|
1596
|
-
|
|
1597
|
-
|
|
1452
|
+
requestsRef.current = requestsRef.current.filter((r) => r.id !== id);
|
|
1453
|
+
setPendingRequests(requestsRef.current);
|
|
1454
|
+
void session.resolve(id, result).catch((err) => {
|
|
1455
|
+
console.error("[wallet-handler] Failed to resolve request:", err);
|
|
1456
|
+
});
|
|
1598
1457
|
},
|
|
1599
|
-
[
|
|
1458
|
+
[getSession]
|
|
1600
1459
|
);
|
|
1601
1460
|
const rejectRequest = useCallback6(
|
|
1602
1461
|
(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
|
-
});
|
|
1462
|
+
const session = getSession();
|
|
1463
|
+
if (!session) {
|
|
1464
|
+
console.error("[wallet-handler] No session available to reject request");
|
|
1465
|
+
return;
|
|
1626
1466
|
}
|
|
1627
|
-
|
|
1628
|
-
|
|
1467
|
+
requestsRef.current = requestsRef.current.filter((r) => r.id !== id);
|
|
1468
|
+
setPendingRequests(requestsRef.current);
|
|
1469
|
+
void session.reject(id, error).catch((err) => {
|
|
1470
|
+
console.error("[wallet-handler] Failed to reject request:", err);
|
|
1471
|
+
});
|
|
1629
1472
|
},
|
|
1630
|
-
[
|
|
1473
|
+
[getSession]
|
|
1631
1474
|
);
|
|
1632
1475
|
return {
|
|
1633
1476
|
pendingRequests,
|
|
1634
|
-
|
|
1477
|
+
enqueueRequest,
|
|
1635
1478
|
resolveRequest,
|
|
1636
1479
|
rejectRequest
|
|
1637
1480
|
};
|
|
@@ -1646,19 +1489,25 @@ function AomiRuntimeCore({
|
|
|
1646
1489
|
const threadContext = useThreadContext();
|
|
1647
1490
|
const eventContext = useEventContext();
|
|
1648
1491
|
const notificationContext = useNotification();
|
|
1649
|
-
const { dispatchInboundSystem: dispatchSystemEvents } = eventContext;
|
|
1650
1492
|
const { user, onUserStateChange, getUserState } = useUser();
|
|
1651
1493
|
const { getControlState, getCurrentThreadApp, clearSecrets } = useControl();
|
|
1494
|
+
const sessionManagerRef = useRef7(null);
|
|
1495
|
+
const walletHandler = useWalletHandler({
|
|
1496
|
+
getSession: () => {
|
|
1497
|
+
var _a;
|
|
1498
|
+
return (_a = sessionManagerRef.current) == null ? void 0 : _a.get(threadContext.currentThreadId);
|
|
1499
|
+
}
|
|
1500
|
+
});
|
|
1652
1501
|
const {
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
messageController,
|
|
1502
|
+
sessionManager,
|
|
1503
|
+
getSession,
|
|
1656
1504
|
isRunning,
|
|
1657
1505
|
setIsRunning,
|
|
1658
1506
|
ensureInitialState,
|
|
1507
|
+
sendMessage: orchestratorSendMessage,
|
|
1508
|
+
cancelGeneration: orchestratorCancel,
|
|
1659
1509
|
aomiClientRef
|
|
1660
1510
|
} = useRuntimeOrchestrator(aomiClient, {
|
|
1661
|
-
onSyncEvents: dispatchSystemEvents,
|
|
1662
1511
|
getPublicKey: () => getUserState().address,
|
|
1663
1512
|
getUserState,
|
|
1664
1513
|
getApp: getCurrentThreadApp,
|
|
@@ -1666,8 +1515,11 @@ function AomiRuntimeCore({
|
|
|
1666
1515
|
getClientId: () => {
|
|
1667
1516
|
var _a;
|
|
1668
1517
|
return (_a = getControlState().clientId) != null ? _a : void 0;
|
|
1669
|
-
}
|
|
1518
|
+
},
|
|
1519
|
+
onWalletRequest: (request) => walletHandler.enqueueRequest(request),
|
|
1520
|
+
onEvent: (event) => eventContext.dispatch(event)
|
|
1670
1521
|
});
|
|
1522
|
+
sessionManagerRef.current = sessionManager;
|
|
1671
1523
|
const walletSnapshot = useCallback7(
|
|
1672
1524
|
(nextUser) => ({
|
|
1673
1525
|
address: nextUser.address,
|
|
@@ -1678,7 +1530,7 @@ function AomiRuntimeCore({
|
|
|
1678
1530
|
[getUserState]
|
|
1679
1531
|
);
|
|
1680
1532
|
const lastWalletStateRef = useRef7(walletSnapshot(getUserState()));
|
|
1681
|
-
|
|
1533
|
+
useEffect3(() => {
|
|
1682
1534
|
lastWalletStateRef.current = walletSnapshot(getUserState());
|
|
1683
1535
|
const unsubscribe = onUserStateChange(async (newUser) => {
|
|
1684
1536
|
const nextWalletState = walletSnapshot(newUser);
|
|
@@ -1705,17 +1557,10 @@ function AomiRuntimeCore({
|
|
|
1705
1557
|
const threadContextRef = useRef7(threadContext);
|
|
1706
1558
|
threadContextRef.current = threadContext;
|
|
1707
1559
|
const currentThreadIdRef = useRef7(threadContext.currentThreadId);
|
|
1708
|
-
|
|
1560
|
+
useEffect3(() => {
|
|
1709
1561
|
currentThreadIdRef.current = threadContext.currentThreadId;
|
|
1710
1562
|
}, [threadContext.currentThreadId]);
|
|
1711
|
-
|
|
1712
|
-
polling.start(currentThreadIdRef.current);
|
|
1713
|
-
}, [polling]);
|
|
1714
|
-
const walletHandler = useWalletHandler({
|
|
1715
|
-
sessionId: threadContext.currentThreadId,
|
|
1716
|
-
onRequestComplete: onWalletRequestComplete
|
|
1717
|
-
});
|
|
1718
|
-
useEffect4(() => {
|
|
1563
|
+
useEffect3(() => {
|
|
1719
1564
|
const unsubscribe = eventContext.subscribe(
|
|
1720
1565
|
"user_state_request",
|
|
1721
1566
|
() => {
|
|
@@ -1728,14 +1573,10 @@ function AomiRuntimeCore({
|
|
|
1728
1573
|
);
|
|
1729
1574
|
return unsubscribe;
|
|
1730
1575
|
}, [eventContext, threadContext.currentThreadId, getUserState]);
|
|
1731
|
-
|
|
1576
|
+
useEffect3(() => {
|
|
1732
1577
|
void ensureInitialState(threadContext.currentThreadId);
|
|
1733
1578
|
}, [ensureInitialState, threadContext.currentThreadId]);
|
|
1734
|
-
|
|
1735
|
-
const threadId = threadContext.currentThreadId;
|
|
1736
|
-
setIsRunning(isThreadRunning(backendStateRef.current, threadId));
|
|
1737
|
-
}, [backendStateRef, setIsRunning, threadContext.currentThreadId]);
|
|
1738
|
-
useEffect4(() => {
|
|
1579
|
+
useEffect3(() => {
|
|
1739
1580
|
const threadId = threadContext.currentThreadId;
|
|
1740
1581
|
const currentMeta = threadContext.getThreadMetadata(threadId);
|
|
1741
1582
|
if (currentMeta && currentMeta.control.isProcessing !== isRunning) {
|
|
@@ -1749,7 +1590,7 @@ function AomiRuntimeCore({
|
|
|
1749
1590
|
const currentMessages = threadContext.getThreadMessages(
|
|
1750
1591
|
threadContext.currentThreadId
|
|
1751
1592
|
);
|
|
1752
|
-
|
|
1593
|
+
useEffect3(() => {
|
|
1753
1594
|
const userAddress = user.address;
|
|
1754
1595
|
if (!userAddress) return;
|
|
1755
1596
|
const fetchThreadList = async () => {
|
|
@@ -1790,66 +1631,19 @@ function AomiRuntimeCore({
|
|
|
1790
1631
|
}, [user.address, aomiClientRef]);
|
|
1791
1632
|
const threadListAdapter = useMemo2(
|
|
1792
1633
|
() => buildThreadListAdapter({
|
|
1793
|
-
backendStateRef,
|
|
1794
1634
|
aomiClientRef,
|
|
1795
1635
|
threadContext,
|
|
1796
|
-
|
|
1797
|
-
polling,
|
|
1798
|
-
userAddress: user.address,
|
|
1799
|
-
setIsRunning,
|
|
1800
|
-
getApp: getCurrentThreadApp,
|
|
1801
|
-
getApiKey: () => getControlState().apiKey,
|
|
1802
|
-
getUserState
|
|
1636
|
+
setIsRunning
|
|
1803
1637
|
}),
|
|
1804
1638
|
[
|
|
1805
1639
|
aomiClientRef,
|
|
1806
|
-
polling,
|
|
1807
|
-
user.address,
|
|
1808
|
-
backendStateRef,
|
|
1809
1640
|
setIsRunning,
|
|
1810
1641
|
threadContext,
|
|
1811
1642
|
threadContext.currentThreadId,
|
|
1812
|
-
threadContext.allThreadsMetadata
|
|
1813
|
-
getControlState,
|
|
1814
|
-
getCurrentThreadApp,
|
|
1815
|
-
getUserState
|
|
1643
|
+
threadContext.allThreadsMetadata
|
|
1816
1644
|
]
|
|
1817
1645
|
);
|
|
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(() => {
|
|
1646
|
+
useEffect3(() => {
|
|
1853
1647
|
const showToolNotification = (eventType) => (event) => {
|
|
1854
1648
|
const payload = event.payload;
|
|
1855
1649
|
const toolName = typeof (payload == null ? void 0 : payload.tool_name) === "string" ? payload.tool_name : void 0;
|
|
@@ -1874,10 +1668,8 @@ function AomiRuntimeCore({
|
|
|
1874
1668
|
unsubscribeComplete();
|
|
1875
1669
|
};
|
|
1876
1670
|
}, [eventContext, notificationContext]);
|
|
1877
|
-
|
|
1878
|
-
const unsubscribe = eventContext.subscribe("system_notice", (
|
|
1879
|
-
const payload = event.payload;
|
|
1880
|
-
const message = payload == null ? void 0 : payload.message;
|
|
1671
|
+
useEffect3(() => {
|
|
1672
|
+
const unsubscribe = eventContext.subscribe("system_notice", (_event) => {
|
|
1881
1673
|
});
|
|
1882
1674
|
return unsubscribe;
|
|
1883
1675
|
}, [eventContext, notificationContext]);
|
|
@@ -1885,34 +1677,36 @@ function AomiRuntimeCore({
|
|
|
1885
1677
|
messages: currentMessages,
|
|
1886
1678
|
setMessages: (msgs) => threadContext.setThreadMessages(threadContext.currentThreadId, [...msgs]),
|
|
1887
1679
|
isRunning,
|
|
1888
|
-
onNew: (message) =>
|
|
1889
|
-
|
|
1680
|
+
onNew: async (message) => {
|
|
1681
|
+
const text = message.content.filter(
|
|
1682
|
+
(part) => part.type === "text"
|
|
1683
|
+
).map((part) => part.text).join("\n");
|
|
1684
|
+
if (text) {
|
|
1685
|
+
await orchestratorSendMessage(text, threadContext.currentThreadId);
|
|
1686
|
+
}
|
|
1687
|
+
},
|
|
1688
|
+
onCancel: async () => {
|
|
1689
|
+
await orchestratorCancel(threadContext.currentThreadId);
|
|
1690
|
+
},
|
|
1890
1691
|
convertMessage: (msg) => msg,
|
|
1891
1692
|
adapters: { threadList: threadListAdapter }
|
|
1892
1693
|
});
|
|
1893
|
-
|
|
1694
|
+
useEffect3(() => {
|
|
1894
1695
|
return () => {
|
|
1895
|
-
|
|
1696
|
+
sessionManager.closeAll();
|
|
1896
1697
|
void clearSecrets();
|
|
1897
1698
|
};
|
|
1898
|
-
}, [
|
|
1699
|
+
}, [sessionManager, clearSecrets]);
|
|
1899
1700
|
const userContext = useUser();
|
|
1900
1701
|
const sendMessage = useCallback7(
|
|
1901
1702
|
async (text) => {
|
|
1902
|
-
|
|
1903
|
-
role: "user",
|
|
1904
|
-
content: [{ type: "text", text }]
|
|
1905
|
-
};
|
|
1906
|
-
await messageController.outbound(
|
|
1907
|
-
appendMessage,
|
|
1908
|
-
threadContext.currentThreadId
|
|
1909
|
-
);
|
|
1703
|
+
await orchestratorSendMessage(text, threadContext.currentThreadId);
|
|
1910
1704
|
},
|
|
1911
|
-
[
|
|
1705
|
+
[orchestratorSendMessage, threadContext.currentThreadId]
|
|
1912
1706
|
);
|
|
1913
1707
|
const cancelGeneration = useCallback7(() => {
|
|
1914
|
-
|
|
1915
|
-
}, [
|
|
1708
|
+
void orchestratorCancel(threadContext.currentThreadId);
|
|
1709
|
+
}, [orchestratorCancel, threadContext.currentThreadId]);
|
|
1916
1710
|
const getMessages = useCallback7(
|
|
1917
1711
|
(threadId) => {
|
|
1918
1712
|
const id = threadId != null ? threadId : threadContext.currentThreadId;
|
|
@@ -1926,9 +1720,10 @@ function AomiRuntimeCore({
|
|
|
1926
1720
|
}, [threadListAdapter]);
|
|
1927
1721
|
const deleteThread = useCallback7(
|
|
1928
1722
|
async (threadId) => {
|
|
1723
|
+
sessionManager.close(threadId);
|
|
1929
1724
|
await threadListAdapter.onDelete(threadId);
|
|
1930
1725
|
},
|
|
1931
|
-
[threadListAdapter]
|
|
1726
|
+
[threadListAdapter, sessionManager]
|
|
1932
1727
|
);
|
|
1933
1728
|
const renameThread = useCallback7(
|
|
1934
1729
|
async (threadId, title) => {
|
|
@@ -1983,7 +1778,9 @@ function AomiRuntimeCore({
|
|
|
1983
1778
|
clearAllNotifications: notificationContext.clearAll,
|
|
1984
1779
|
// Wallet API
|
|
1985
1780
|
pendingWalletRequests: walletHandler.pendingRequests,
|
|
1986
|
-
startWalletRequest:
|
|
1781
|
+
startWalletRequest: () => {
|
|
1782
|
+
},
|
|
1783
|
+
// No-op: ClientSession manages processing state
|
|
1987
1784
|
resolveWalletRequest: walletHandler.resolveRequest,
|
|
1988
1785
|
rejectWalletRequest: walletHandler.rejectRequest,
|
|
1989
1786
|
// Event API
|
|
@@ -2051,7 +1848,7 @@ function AomiRuntimeInner({
|
|
|
2051
1848
|
}
|
|
2052
1849
|
|
|
2053
1850
|
// packages/react/src/handlers/notification-handler.ts
|
|
2054
|
-
import { useCallback as useCallback8, useEffect as
|
|
1851
|
+
import { useCallback as useCallback8, useEffect as useEffect4, useState as useState6 } from "react";
|
|
2055
1852
|
var notificationIdCounter2 = 0;
|
|
2056
1853
|
function generateNotificationId() {
|
|
2057
1854
|
return `notif-${Date.now()}-${++notificationIdCounter2}`;
|
|
@@ -2059,10 +1856,10 @@ function generateNotificationId() {
|
|
|
2059
1856
|
function useNotificationHandler({
|
|
2060
1857
|
onNotification
|
|
2061
1858
|
} = {}) {
|
|
2062
|
-
const { subscribe
|
|
2063
|
-
const [notifications, setNotifications] =
|
|
2064
|
-
|
|
2065
|
-
const unsubscribe =
|
|
1859
|
+
const { subscribe } = useEventContext();
|
|
1860
|
+
const [notifications, setNotifications] = useState6([]);
|
|
1861
|
+
useEffect4(() => {
|
|
1862
|
+
const unsubscribe = subscribe("notification", (event) => {
|
|
2066
1863
|
var _a, _b;
|
|
2067
1864
|
const payload = event.payload;
|
|
2068
1865
|
const notification = {
|
|
@@ -2071,14 +1868,14 @@ function useNotificationHandler({
|
|
|
2071
1868
|
title: (_b = payload.title) != null ? _b : "Notification",
|
|
2072
1869
|
body: payload.body,
|
|
2073
1870
|
handled: false,
|
|
2074
|
-
timestamp:
|
|
1871
|
+
timestamp: Date.now(),
|
|
2075
1872
|
sessionId: event.sessionId
|
|
2076
1873
|
};
|
|
2077
1874
|
setNotifications((prev) => [notification, ...prev]);
|
|
2078
1875
|
onNotification == null ? void 0 : onNotification(notification);
|
|
2079
1876
|
});
|
|
2080
1877
|
return unsubscribe;
|
|
2081
|
-
}, [
|
|
1878
|
+
}, [subscribe, onNotification]);
|
|
2082
1879
|
const unhandledCount = notifications.filter((n) => !n.handled).length;
|
|
2083
1880
|
const markHandled = useCallback8((id) => {
|
|
2084
1881
|
setNotifications(
|