@aomi-labs/react 0.2.4 → 0.3.1
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 +142 -0
- package/dist/index.cjs +415 -944
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -183
- package/dist/index.d.ts +94 -183
- package/dist/index.js +410 -932
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -18,438 +18,12 @@ var __spreadValues = (a, b) => {
|
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
20
|
|
|
21
|
-
// packages/react/src/
|
|
22
|
-
|
|
23
|
-
const dataLines = rawEvent.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart());
|
|
24
|
-
if (!dataLines.length) return null;
|
|
25
|
-
return dataLines.join("\n");
|
|
26
|
-
}
|
|
27
|
-
async function readSseStream(stream, signal, onMessage) {
|
|
28
|
-
const reader = stream.getReader();
|
|
29
|
-
const decoder = new TextDecoder();
|
|
30
|
-
let buffer = "";
|
|
31
|
-
try {
|
|
32
|
-
while (!signal.aborted) {
|
|
33
|
-
const { value, done } = await reader.read();
|
|
34
|
-
if (done) break;
|
|
35
|
-
buffer += decoder.decode(value, { stream: true });
|
|
36
|
-
buffer = buffer.replace(/\r/g, "");
|
|
37
|
-
let separatorIndex = buffer.indexOf("\n\n");
|
|
38
|
-
while (separatorIndex >= 0) {
|
|
39
|
-
const rawEvent = buffer.slice(0, separatorIndex);
|
|
40
|
-
buffer = buffer.slice(separatorIndex + 2);
|
|
41
|
-
const data = extractSseData(rawEvent);
|
|
42
|
-
if (data) {
|
|
43
|
-
onMessage(data);
|
|
44
|
-
}
|
|
45
|
-
separatorIndex = buffer.indexOf("\n\n");
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
} finally {
|
|
49
|
-
reader.releaseLock();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function createSseSubscriber({
|
|
53
|
-
backendUrl,
|
|
54
|
-
getHeaders,
|
|
55
|
-
shouldLog = process.env.NODE_ENV !== "production"
|
|
56
|
-
}) {
|
|
57
|
-
const subscriptions = /* @__PURE__ */ new Map();
|
|
58
|
-
const subscribe2 = (sessionId, onUpdate, onError) => {
|
|
59
|
-
const existing = subscriptions.get(sessionId);
|
|
60
|
-
const listener = { onUpdate, onError };
|
|
61
|
-
if (existing) {
|
|
62
|
-
existing.listeners.add(listener);
|
|
63
|
-
if (shouldLog) {
|
|
64
|
-
console.debug("[aomi][sse] listener added", {
|
|
65
|
-
sessionId,
|
|
66
|
-
listeners: existing.listeners.size
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
return () => {
|
|
70
|
-
existing.listeners.delete(listener);
|
|
71
|
-
if (shouldLog) {
|
|
72
|
-
console.debug("[aomi][sse] listener removed", {
|
|
73
|
-
sessionId,
|
|
74
|
-
listeners: existing.listeners.size
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
if (existing.listeners.size === 0) {
|
|
78
|
-
existing.stop("unsubscribe");
|
|
79
|
-
if (subscriptions.get(sessionId) === existing) {
|
|
80
|
-
subscriptions.delete(sessionId);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
const subscription = {
|
|
86
|
-
abortController: null,
|
|
87
|
-
retries: 0,
|
|
88
|
-
retryTimer: null,
|
|
89
|
-
stopped: false,
|
|
90
|
-
listeners: /* @__PURE__ */ new Set([listener]),
|
|
91
|
-
stop: (reason) => {
|
|
92
|
-
var _a;
|
|
93
|
-
subscription.stopped = true;
|
|
94
|
-
if (subscription.retryTimer) {
|
|
95
|
-
clearTimeout(subscription.retryTimer);
|
|
96
|
-
subscription.retryTimer = null;
|
|
97
|
-
}
|
|
98
|
-
(_a = subscription.abortController) == null ? void 0 : _a.abort();
|
|
99
|
-
subscription.abortController = null;
|
|
100
|
-
if (shouldLog) {
|
|
101
|
-
console.debug("[aomi][sse] stop", {
|
|
102
|
-
sessionId,
|
|
103
|
-
reason,
|
|
104
|
-
retries: subscription.retries
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const scheduleRetry = () => {
|
|
110
|
-
if (subscription.stopped) return;
|
|
111
|
-
subscription.retries += 1;
|
|
112
|
-
const delayMs = Math.min(500 * 2 ** (subscription.retries - 1), 1e4);
|
|
113
|
-
if (shouldLog) {
|
|
114
|
-
console.debug("[aomi][sse] retry scheduled", {
|
|
115
|
-
sessionId,
|
|
116
|
-
delayMs,
|
|
117
|
-
retries: subscription.retries
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
subscription.retryTimer = setTimeout(() => {
|
|
121
|
-
void open();
|
|
122
|
-
}, delayMs);
|
|
123
|
-
};
|
|
124
|
-
const open = async () => {
|
|
125
|
-
var _a;
|
|
126
|
-
if (subscription.stopped) return;
|
|
127
|
-
if (subscription.retryTimer) {
|
|
128
|
-
clearTimeout(subscription.retryTimer);
|
|
129
|
-
subscription.retryTimer = null;
|
|
130
|
-
}
|
|
131
|
-
const controller = new AbortController();
|
|
132
|
-
subscription.abortController = controller;
|
|
133
|
-
const openedAt = Date.now();
|
|
134
|
-
try {
|
|
135
|
-
const response = await fetch(`${backendUrl}/api/updates`, {
|
|
136
|
-
headers: getHeaders(sessionId),
|
|
137
|
-
signal: controller.signal
|
|
138
|
-
});
|
|
139
|
-
if (!response.ok) {
|
|
140
|
-
throw new Error(
|
|
141
|
-
`SSE HTTP ${response.status}: ${response.statusText}`
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
if (!response.body) {
|
|
145
|
-
throw new Error("SSE response missing body");
|
|
146
|
-
}
|
|
147
|
-
subscription.retries = 0;
|
|
148
|
-
await readSseStream(response.body, controller.signal, (data) => {
|
|
149
|
-
var _a2, _b;
|
|
150
|
-
let parsed;
|
|
151
|
-
try {
|
|
152
|
-
parsed = JSON.parse(data);
|
|
153
|
-
} catch (error) {
|
|
154
|
-
for (const item of subscription.listeners) {
|
|
155
|
-
(_a2 = item.onError) == null ? void 0 : _a2.call(item, error);
|
|
156
|
-
}
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
for (const item of subscription.listeners) {
|
|
160
|
-
try {
|
|
161
|
-
item.onUpdate(parsed);
|
|
162
|
-
} catch (error) {
|
|
163
|
-
(_b = item.onError) == null ? void 0 : _b.call(item, error);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
if (shouldLog) {
|
|
168
|
-
console.debug("[aomi][sse] stream ended", {
|
|
169
|
-
sessionId,
|
|
170
|
-
aborted: controller.signal.aborted,
|
|
171
|
-
stopped: subscription.stopped,
|
|
172
|
-
durationMs: Date.now() - openedAt
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
} catch (error) {
|
|
176
|
-
if (!controller.signal.aborted && !subscription.stopped) {
|
|
177
|
-
for (const item of subscription.listeners) {
|
|
178
|
-
(_a = item.onError) == null ? void 0 : _a.call(item, error);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (!subscription.stopped) {
|
|
183
|
-
scheduleRetry();
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
subscriptions.set(sessionId, subscription);
|
|
187
|
-
void open();
|
|
188
|
-
return () => {
|
|
189
|
-
subscription.listeners.delete(listener);
|
|
190
|
-
if (shouldLog) {
|
|
191
|
-
console.debug("[aomi][sse] listener removed", {
|
|
192
|
-
sessionId,
|
|
193
|
-
listeners: subscription.listeners.size
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
if (subscription.listeners.size === 0) {
|
|
197
|
-
subscription.stop("unsubscribe");
|
|
198
|
-
if (subscriptions.get(sessionId) === subscription) {
|
|
199
|
-
subscriptions.delete(sessionId);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
};
|
|
204
|
-
return { subscribe: subscribe2 };
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// packages/react/src/backend/client.ts
|
|
208
|
-
var SESSION_ID_HEADER = "X-Session-Id";
|
|
209
|
-
var API_KEY_HEADER = "X-API-Key";
|
|
210
|
-
function toQueryString(payload) {
|
|
211
|
-
const params = new URLSearchParams();
|
|
212
|
-
for (const [key, value] of Object.entries(payload)) {
|
|
213
|
-
if (value === void 0 || value === null) continue;
|
|
214
|
-
params.set(key, String(value));
|
|
215
|
-
}
|
|
216
|
-
const qs = params.toString();
|
|
217
|
-
return qs ? `?${qs}` : "";
|
|
218
|
-
}
|
|
219
|
-
function withSessionHeader(sessionId, init) {
|
|
220
|
-
const headers = new Headers(init);
|
|
221
|
-
headers.set(SESSION_ID_HEADER, sessionId);
|
|
222
|
-
return headers;
|
|
223
|
-
}
|
|
224
|
-
async function postState(backendUrl, path, payload, sessionId, apiKey) {
|
|
225
|
-
const query = toQueryString(payload);
|
|
226
|
-
const url = `${backendUrl}${path}${query}`;
|
|
227
|
-
const headers = new Headers(withSessionHeader(sessionId));
|
|
228
|
-
if (apiKey) {
|
|
229
|
-
headers.set(API_KEY_HEADER, apiKey);
|
|
230
|
-
}
|
|
231
|
-
const response = await fetch(url, {
|
|
232
|
-
method: "POST",
|
|
233
|
-
headers
|
|
234
|
-
});
|
|
235
|
-
if (!response.ok) {
|
|
236
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
237
|
-
}
|
|
238
|
-
return await response.json();
|
|
239
|
-
}
|
|
240
|
-
var BackendApi = class {
|
|
241
|
-
constructor(backendUrl) {
|
|
242
|
-
this.backendUrl = backendUrl;
|
|
243
|
-
this.sseSubscriber = createSseSubscriber({
|
|
244
|
-
backendUrl,
|
|
245
|
-
getHeaders: (sessionId) => withSessionHeader(sessionId, { Accept: "text/event-stream" })
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
async fetchState(sessionId, userState) {
|
|
249
|
-
const url = new URL("/api/state", this.backendUrl);
|
|
250
|
-
if (userState) {
|
|
251
|
-
url.searchParams.set("user_state", JSON.stringify(userState));
|
|
252
|
-
}
|
|
253
|
-
const response = await fetch(url.toString(), {
|
|
254
|
-
headers: withSessionHeader(sessionId)
|
|
255
|
-
});
|
|
256
|
-
if (!response.ok) {
|
|
257
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
258
|
-
}
|
|
259
|
-
return await response.json();
|
|
260
|
-
}
|
|
261
|
-
async postChatMessage(sessionId, message, namespace, publicKey, apiKey, userState) {
|
|
262
|
-
const payload = { message, namespace };
|
|
263
|
-
if (publicKey) {
|
|
264
|
-
payload.public_key = publicKey;
|
|
265
|
-
}
|
|
266
|
-
if (userState) {
|
|
267
|
-
payload.user_state = JSON.stringify(userState);
|
|
268
|
-
}
|
|
269
|
-
return postState(
|
|
270
|
-
this.backendUrl,
|
|
271
|
-
"/api/chat",
|
|
272
|
-
payload,
|
|
273
|
-
sessionId,
|
|
274
|
-
apiKey
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
async postSystemMessage(sessionId, message) {
|
|
278
|
-
return postState(
|
|
279
|
-
this.backendUrl,
|
|
280
|
-
"/api/system",
|
|
281
|
-
{
|
|
282
|
-
message
|
|
283
|
-
},
|
|
284
|
-
sessionId
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
async postInterrupt(sessionId) {
|
|
288
|
-
return postState(
|
|
289
|
-
this.backendUrl,
|
|
290
|
-
"/api/interrupt",
|
|
291
|
-
{},
|
|
292
|
-
sessionId
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Subscribe to SSE updates for a session.
|
|
297
|
-
* Uses fetch streaming and reconnects on disconnects.
|
|
298
|
-
* Returns an unsubscribe function.
|
|
299
|
-
*/
|
|
300
|
-
subscribeSSE(sessionId, onUpdate, onError) {
|
|
301
|
-
return this.sseSubscriber.subscribe(sessionId, onUpdate, onError);
|
|
302
|
-
}
|
|
303
|
-
async fetchThreads(publicKey) {
|
|
304
|
-
const url = `${this.backendUrl}/api/sessions?public_key=${encodeURIComponent(publicKey)}`;
|
|
305
|
-
const response = await fetch(url);
|
|
306
|
-
if (!response.ok) {
|
|
307
|
-
throw new Error(`Failed to fetch threads: HTTP ${response.status}`);
|
|
308
|
-
}
|
|
309
|
-
return await response.json();
|
|
310
|
-
}
|
|
311
|
-
async fetchThread(sessionId) {
|
|
312
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
|
|
313
|
-
const response = await fetch(url, {
|
|
314
|
-
headers: withSessionHeader(sessionId)
|
|
315
|
-
});
|
|
316
|
-
if (!response.ok) {
|
|
317
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
318
|
-
}
|
|
319
|
-
return await response.json();
|
|
320
|
-
}
|
|
321
|
-
async createThread(threadId, publicKey) {
|
|
322
|
-
const body = {};
|
|
323
|
-
if (publicKey) body.public_key = publicKey;
|
|
324
|
-
const url = `${this.backendUrl}/api/sessions`;
|
|
325
|
-
const response = await fetch(url, {
|
|
326
|
-
method: "POST",
|
|
327
|
-
headers: withSessionHeader(threadId, {
|
|
328
|
-
"Content-Type": "application/json"
|
|
329
|
-
}),
|
|
330
|
-
body: JSON.stringify(body)
|
|
331
|
-
});
|
|
332
|
-
if (!response.ok) {
|
|
333
|
-
throw new Error(`Failed to create thread: HTTP ${response.status}`);
|
|
334
|
-
}
|
|
335
|
-
return await response.json();
|
|
336
|
-
}
|
|
337
|
-
async archiveThread(sessionId) {
|
|
338
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}/archive`;
|
|
339
|
-
const response = await fetch(url, {
|
|
340
|
-
method: "POST",
|
|
341
|
-
headers: withSessionHeader(sessionId)
|
|
342
|
-
});
|
|
343
|
-
if (!response.ok) {
|
|
344
|
-
throw new Error(`Failed to archive thread: HTTP ${response.status}`);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
async unarchiveThread(sessionId) {
|
|
348
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}/unarchive`;
|
|
349
|
-
const response = await fetch(url, {
|
|
350
|
-
method: "POST",
|
|
351
|
-
headers: withSessionHeader(sessionId)
|
|
352
|
-
});
|
|
353
|
-
if (!response.ok) {
|
|
354
|
-
throw new Error(`Failed to unarchive thread: HTTP ${response.status}`);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
async deleteThread(sessionId) {
|
|
358
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
|
|
359
|
-
const response = await fetch(url, {
|
|
360
|
-
method: "DELETE",
|
|
361
|
-
headers: withSessionHeader(sessionId)
|
|
362
|
-
});
|
|
363
|
-
if (!response.ok) {
|
|
364
|
-
throw new Error(`Failed to delete thread: HTTP ${response.status}`);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async renameThread(sessionId, newTitle) {
|
|
368
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
|
|
369
|
-
const response = await fetch(url, {
|
|
370
|
-
method: "PATCH",
|
|
371
|
-
headers: withSessionHeader(sessionId, {
|
|
372
|
-
"Content-Type": "application/json"
|
|
373
|
-
}),
|
|
374
|
-
body: JSON.stringify({ title: newTitle })
|
|
375
|
-
});
|
|
376
|
-
if (!response.ok) {
|
|
377
|
-
throw new Error(`Failed to rename thread: HTTP ${response.status}`);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
async getSystemEvents(sessionId, count) {
|
|
381
|
-
const url = new URL("/api/events", this.backendUrl);
|
|
382
|
-
if (count !== void 0) {
|
|
383
|
-
url.searchParams.set("count", String(count));
|
|
384
|
-
}
|
|
385
|
-
const response = await fetch(url.toString(), {
|
|
386
|
-
headers: withSessionHeader(sessionId)
|
|
387
|
-
});
|
|
388
|
-
if (!response.ok) {
|
|
389
|
-
if (response.status === 404) return [];
|
|
390
|
-
throw new Error(`Failed to get system events: HTTP ${response.status}`);
|
|
391
|
-
}
|
|
392
|
-
return await response.json();
|
|
393
|
-
}
|
|
394
|
-
// ===========================================================================
|
|
395
|
-
// Control API
|
|
396
|
-
// ===========================================================================
|
|
397
|
-
/**
|
|
398
|
-
* Get allowed namespaces for the current request context.
|
|
399
|
-
*/
|
|
400
|
-
async getNamespaces(sessionId, publicKey, apiKey) {
|
|
401
|
-
const url = new URL("/api/control/namespaces", this.backendUrl);
|
|
402
|
-
if (publicKey) {
|
|
403
|
-
url.searchParams.set("public_key", publicKey);
|
|
404
|
-
}
|
|
405
|
-
console.log("[BackendApi.getNamespaces]", {
|
|
406
|
-
backendUrl: this.backendUrl,
|
|
407
|
-
fullUrl: url.toString(),
|
|
408
|
-
sessionId,
|
|
409
|
-
publicKey
|
|
410
|
-
});
|
|
411
|
-
const headers = new Headers(withSessionHeader(sessionId));
|
|
412
|
-
if (apiKey) {
|
|
413
|
-
headers.set(API_KEY_HEADER, apiKey);
|
|
414
|
-
}
|
|
415
|
-
const response = await fetch(url.toString(), { headers });
|
|
416
|
-
if (!response.ok) {
|
|
417
|
-
throw new Error(`Failed to get namespaces: HTTP ${response.status}`);
|
|
418
|
-
}
|
|
419
|
-
return await response.json();
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Get available models.
|
|
423
|
-
*/
|
|
424
|
-
async getModels(sessionId) {
|
|
425
|
-
const url = new URL("/api/control/models", this.backendUrl);
|
|
426
|
-
console.log("[BackendApi.getModels]", {
|
|
427
|
-
backendUrl: this.backendUrl,
|
|
428
|
-
fullUrl: url.toString(),
|
|
429
|
-
sessionId
|
|
430
|
-
});
|
|
431
|
-
const response = await fetch(url.toString(), {
|
|
432
|
-
headers: withSessionHeader(sessionId)
|
|
433
|
-
});
|
|
434
|
-
if (!response.ok) {
|
|
435
|
-
throw new Error(`Failed to get models: HTTP ${response.status}`);
|
|
436
|
-
}
|
|
437
|
-
return await response.json();
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Set the model selection for a session.
|
|
441
|
-
*/
|
|
442
|
-
async setModel(sessionId, rig, namespace, apiKey) {
|
|
443
|
-
const payload = { rig };
|
|
444
|
-
if (namespace) {
|
|
445
|
-
payload.namespace = namespace;
|
|
446
|
-
}
|
|
447
|
-
return postState(this.backendUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
448
|
-
}
|
|
449
|
-
};
|
|
21
|
+
// packages/react/src/index.ts
|
|
22
|
+
import { AomiClient as AomiClient2 } from "@aomi-labs/client";
|
|
450
23
|
|
|
451
24
|
// packages/react/src/runtime/aomi-runtime.tsx
|
|
452
25
|
import { useMemo as useMemo3 } from "react";
|
|
26
|
+
import { AomiClient } from "@aomi-labs/client";
|
|
453
27
|
|
|
454
28
|
// packages/react/src/contexts/control-context.tsx
|
|
455
29
|
import {
|
|
@@ -489,7 +63,7 @@ var logThreadMetadataChange = (source, threadId, prev, next) => {
|
|
|
489
63
|
function initThreadControl() {
|
|
490
64
|
return {
|
|
491
65
|
model: null,
|
|
492
|
-
|
|
66
|
+
app: null,
|
|
493
67
|
controlDirty: false,
|
|
494
68
|
isProcessing: false
|
|
495
69
|
};
|
|
@@ -573,7 +147,7 @@ var ThreadStore = class {
|
|
|
573
147
|
initialThreadId,
|
|
574
148
|
{
|
|
575
149
|
title: "New Chat",
|
|
576
|
-
status: "
|
|
150
|
+
status: "regular",
|
|
577
151
|
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
578
152
|
control: initThreadControl()
|
|
579
153
|
}
|
|
@@ -645,7 +219,7 @@ function useControl() {
|
|
|
645
219
|
}
|
|
646
220
|
function ControlContextProvider({
|
|
647
221
|
children,
|
|
648
|
-
|
|
222
|
+
aomiClient,
|
|
649
223
|
sessionId,
|
|
650
224
|
publicKey,
|
|
651
225
|
getThreadMetadata,
|
|
@@ -655,14 +229,14 @@ function ControlContextProvider({
|
|
|
655
229
|
const [state, setStateInternal] = useState(() => ({
|
|
656
230
|
apiKey: null,
|
|
657
231
|
availableModels: [],
|
|
658
|
-
|
|
232
|
+
authorizedApps: [],
|
|
659
233
|
defaultModel: null,
|
|
660
|
-
|
|
234
|
+
defaultApp: null
|
|
661
235
|
}));
|
|
662
236
|
const stateRef = useRef(state);
|
|
663
237
|
stateRef.current = state;
|
|
664
|
-
const
|
|
665
|
-
|
|
238
|
+
const aomiClientRef = useRef(aomiClient);
|
|
239
|
+
aomiClientRef.current = aomiClient;
|
|
666
240
|
const sessionIdRef = useRef(sessionId);
|
|
667
241
|
sessionIdRef.current = sessionId;
|
|
668
242
|
const publicKeyRef = useRef(publicKey);
|
|
@@ -696,33 +270,32 @@ function ControlContextProvider({
|
|
|
696
270
|
}
|
|
697
271
|
}, [state.apiKey]);
|
|
698
272
|
useEffect(() => {
|
|
699
|
-
const
|
|
273
|
+
const fetchApps = async () => {
|
|
700
274
|
var _a2, _b2;
|
|
701
275
|
try {
|
|
702
|
-
const
|
|
276
|
+
const apps = await aomiClientRef.current.getApps(
|
|
703
277
|
sessionIdRef.current,
|
|
704
|
-
publicKeyRef.current,
|
|
705
|
-
(_a2 = stateRef.current.apiKey) != null ? _a2 : void 0
|
|
278
|
+
{ publicKey: publicKeyRef.current, apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0 }
|
|
706
279
|
);
|
|
707
|
-
const
|
|
280
|
+
const defaultApp = apps.includes("default") ? "default" : (_b2 = apps[0]) != null ? _b2 : null;
|
|
708
281
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
709
|
-
|
|
710
|
-
|
|
282
|
+
authorizedApps: apps,
|
|
283
|
+
defaultApp
|
|
711
284
|
}));
|
|
712
285
|
} catch (error) {
|
|
713
|
-
console.error("Failed to fetch
|
|
286
|
+
console.error("Failed to fetch apps:", error);
|
|
714
287
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
715
|
-
|
|
716
|
-
|
|
288
|
+
authorizedApps: ["default"],
|
|
289
|
+
defaultApp: "default"
|
|
717
290
|
}));
|
|
718
291
|
}
|
|
719
292
|
};
|
|
720
|
-
void
|
|
293
|
+
void fetchApps();
|
|
721
294
|
}, [state.apiKey]);
|
|
722
295
|
useEffect(() => {
|
|
723
296
|
const fetchModels = async () => {
|
|
724
297
|
try {
|
|
725
|
-
const models = await
|
|
298
|
+
const models = await aomiClientRef.current.getModels(
|
|
726
299
|
sessionIdRef.current
|
|
727
300
|
);
|
|
728
301
|
setStateInternal((prev) => {
|
|
@@ -747,7 +320,7 @@ function ControlContextProvider({
|
|
|
747
320
|
}, []);
|
|
748
321
|
const getAvailableModels = useCallback(async () => {
|
|
749
322
|
try {
|
|
750
|
-
const models = await
|
|
323
|
+
const models = await aomiClientRef.current.getModels(
|
|
751
324
|
sessionIdRef.current
|
|
752
325
|
);
|
|
753
326
|
setStateInternal((prev) => {
|
|
@@ -763,25 +336,24 @@ function ControlContextProvider({
|
|
|
763
336
|
return [];
|
|
764
337
|
}
|
|
765
338
|
}, []);
|
|
766
|
-
const
|
|
339
|
+
const getAuthorizedApps = useCallback(async () => {
|
|
767
340
|
var _a2, _b2;
|
|
768
341
|
try {
|
|
769
|
-
const
|
|
342
|
+
const apps = await aomiClientRef.current.getApps(
|
|
770
343
|
sessionIdRef.current,
|
|
771
|
-
publicKeyRef.current,
|
|
772
|
-
(_a2 = stateRef.current.apiKey) != null ? _a2 : void 0
|
|
344
|
+
{ publicKey: publicKeyRef.current, apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0 }
|
|
773
345
|
);
|
|
774
|
-
const
|
|
346
|
+
const defaultApp = apps.includes("default") ? "default" : (_b2 = apps[0]) != null ? _b2 : null;
|
|
775
347
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
776
|
-
|
|
777
|
-
|
|
348
|
+
authorizedApps: apps,
|
|
349
|
+
defaultApp
|
|
778
350
|
}));
|
|
779
|
-
return
|
|
351
|
+
return apps;
|
|
780
352
|
} catch (error) {
|
|
781
|
-
console.error("Failed to fetch
|
|
353
|
+
console.error("Failed to fetch apps:", error);
|
|
782
354
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
783
|
-
|
|
784
|
-
|
|
355
|
+
authorizedApps: ["default"],
|
|
356
|
+
defaultApp: "default"
|
|
785
357
|
}));
|
|
786
358
|
return ["default"];
|
|
787
359
|
}
|
|
@@ -805,32 +377,31 @@ function ControlContextProvider({
|
|
|
805
377
|
console.warn("[control-context] Cannot switch model while processing");
|
|
806
378
|
return;
|
|
807
379
|
}
|
|
808
|
-
const
|
|
380
|
+
const app = (_d = (_c = currentControl.app) != null ? _c : stateRef.current.defaultApp) != null ? _d : "default";
|
|
809
381
|
console.log("[control-context] onModelSelect updating metadata", {
|
|
810
382
|
threadId,
|
|
811
383
|
model,
|
|
812
|
-
|
|
384
|
+
app,
|
|
813
385
|
currentControl
|
|
814
386
|
});
|
|
815
387
|
updateThreadMetadataRef.current(threadId, {
|
|
816
388
|
control: __spreadProps(__spreadValues({}, currentControl), {
|
|
817
389
|
model,
|
|
818
|
-
|
|
390
|
+
app,
|
|
819
391
|
controlDirty: true
|
|
820
392
|
})
|
|
821
393
|
});
|
|
822
394
|
console.log("[control-context] onModelSelect calling backend setModel", {
|
|
823
395
|
threadId,
|
|
824
396
|
model,
|
|
825
|
-
|
|
826
|
-
backendUrl:
|
|
397
|
+
app,
|
|
398
|
+
backendUrl: aomiClientRef.current
|
|
827
399
|
});
|
|
828
400
|
try {
|
|
829
|
-
const result = await
|
|
401
|
+
const result = await aomiClientRef.current.setModel(
|
|
830
402
|
threadId,
|
|
831
403
|
model,
|
|
832
|
-
|
|
833
|
-
(_e = stateRef.current.apiKey) != null ? _e : void 0
|
|
404
|
+
{ app, apiKey: (_e = stateRef.current.apiKey) != null ? _e : void 0 }
|
|
834
405
|
);
|
|
835
406
|
console.log("[control-context] onModelSelect backend result", result);
|
|
836
407
|
} catch (err) {
|
|
@@ -838,34 +409,34 @@ function ControlContextProvider({
|
|
|
838
409
|
throw err;
|
|
839
410
|
}
|
|
840
411
|
}, []);
|
|
841
|
-
const
|
|
412
|
+
const onAppSelect = useCallback((app) => {
|
|
842
413
|
var _a2, _b2;
|
|
843
414
|
const threadId = sessionIdRef.current;
|
|
844
415
|
const currentControl = (_b2 = (_a2 = getThreadMetadataRef.current(threadId)) == null ? void 0 : _a2.control) != null ? _b2 : initThreadControl();
|
|
845
416
|
const isProcessing2 = currentControl.isProcessing;
|
|
846
|
-
console.log("[control-context]
|
|
847
|
-
|
|
417
|
+
console.log("[control-context] onAppSelect called", {
|
|
418
|
+
app,
|
|
848
419
|
isProcessing: isProcessing2,
|
|
849
420
|
threadId
|
|
850
421
|
});
|
|
851
422
|
if (isProcessing2) {
|
|
852
423
|
console.warn(
|
|
853
|
-
"[control-context] Cannot switch
|
|
424
|
+
"[control-context] Cannot switch app while processing"
|
|
854
425
|
);
|
|
855
426
|
return;
|
|
856
427
|
}
|
|
857
|
-
console.log("[control-context]
|
|
428
|
+
console.log("[control-context] onAppSelect updating metadata", {
|
|
858
429
|
threadId,
|
|
859
|
-
|
|
430
|
+
app,
|
|
860
431
|
currentControl
|
|
861
432
|
});
|
|
862
433
|
updateThreadMetadataRef.current(threadId, {
|
|
863
434
|
control: __spreadProps(__spreadValues({}, currentControl), {
|
|
864
|
-
|
|
435
|
+
app,
|
|
865
436
|
controlDirty: true
|
|
866
437
|
})
|
|
867
438
|
});
|
|
868
|
-
console.log("[control-context]
|
|
439
|
+
console.log("[control-context] onAppSelect metadata updated");
|
|
869
440
|
}, []);
|
|
870
441
|
const markControlSynced = useCallback(() => {
|
|
871
442
|
var _a2, _b2;
|
|
@@ -895,11 +466,11 @@ function ControlContextProvider({
|
|
|
895
466
|
if ("apiKey" in updates) {
|
|
896
467
|
setApiKey((_a2 = updates.apiKey) != null ? _a2 : null);
|
|
897
468
|
}
|
|
898
|
-
if ("
|
|
899
|
-
|
|
469
|
+
if ("app" in updates && updates.app !== void 0 && updates.app !== null) {
|
|
470
|
+
onAppSelect(updates.app);
|
|
900
471
|
}
|
|
901
472
|
},
|
|
902
|
-
[setApiKey,
|
|
473
|
+
[setApiKey, onAppSelect]
|
|
903
474
|
);
|
|
904
475
|
return /* @__PURE__ */ jsx(
|
|
905
476
|
ControlContext.Provider,
|
|
@@ -908,10 +479,10 @@ function ControlContextProvider({
|
|
|
908
479
|
state,
|
|
909
480
|
setApiKey,
|
|
910
481
|
getAvailableModels,
|
|
911
|
-
|
|
482
|
+
getAuthorizedApps,
|
|
912
483
|
getCurrentThreadControl,
|
|
913
484
|
onModelSelect,
|
|
914
|
-
|
|
485
|
+
onAppSelect,
|
|
915
486
|
isProcessing,
|
|
916
487
|
markControlSynced,
|
|
917
488
|
getControlState,
|
|
@@ -932,20 +503,12 @@ import {
|
|
|
932
503
|
useRef as useRef2,
|
|
933
504
|
useState as useState2
|
|
934
505
|
} from "react";
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
return "SystemNotice" in event;
|
|
942
|
-
}
|
|
943
|
-
function isSystemError(event) {
|
|
944
|
-
return "SystemError" in event;
|
|
945
|
-
}
|
|
946
|
-
function isAsyncCallback(event) {
|
|
947
|
-
return "AsyncCallback" in event;
|
|
948
|
-
}
|
|
506
|
+
import {
|
|
507
|
+
isInlineCall,
|
|
508
|
+
isSystemNotice,
|
|
509
|
+
isSystemError,
|
|
510
|
+
isAsyncCallback
|
|
511
|
+
} from "@aomi-labs/client";
|
|
949
512
|
|
|
950
513
|
// packages/react/src/state/event-buffer.ts
|
|
951
514
|
function createEventBuffer() {
|
|
@@ -1005,7 +568,7 @@ function useEventContext() {
|
|
|
1005
568
|
}
|
|
1006
569
|
function EventContextProvider({
|
|
1007
570
|
children,
|
|
1008
|
-
|
|
571
|
+
aomiClient,
|
|
1009
572
|
sessionId
|
|
1010
573
|
}) {
|
|
1011
574
|
const bufferRef = useRef2(null);
|
|
@@ -1017,7 +580,7 @@ function EventContextProvider({
|
|
|
1017
580
|
useEffect2(() => {
|
|
1018
581
|
setSSEStatus(buffer, "connecting");
|
|
1019
582
|
setSseStatus("connecting");
|
|
1020
|
-
const unsubscribe =
|
|
583
|
+
const unsubscribe = aomiClient.subscribeSSE(
|
|
1021
584
|
sessionId,
|
|
1022
585
|
(event) => {
|
|
1023
586
|
enqueueInbound(buffer, {
|
|
@@ -1047,7 +610,7 @@ function EventContextProvider({
|
|
|
1047
610
|
setSSEStatus(buffer, "disconnected");
|
|
1048
611
|
setSseStatus("disconnected");
|
|
1049
612
|
};
|
|
1050
|
-
}, [
|
|
613
|
+
}, [aomiClient, sessionId, buffer]);
|
|
1051
614
|
const subscribeCallback = useCallback2(
|
|
1052
615
|
(type, callback) => {
|
|
1053
616
|
return subscribe(buffer, type, callback);
|
|
@@ -1061,12 +624,12 @@ function EventContextProvider({
|
|
|
1061
624
|
type: event.type,
|
|
1062
625
|
payload: event.payload
|
|
1063
626
|
});
|
|
1064
|
-
await
|
|
627
|
+
await aomiClient.sendSystemMessage(event.sessionId, message);
|
|
1065
628
|
} catch (error) {
|
|
1066
629
|
console.error("Failed to send outbound event:", error);
|
|
1067
630
|
}
|
|
1068
631
|
},
|
|
1069
|
-
[
|
|
632
|
+
[aomiClient]
|
|
1070
633
|
);
|
|
1071
634
|
const dispatchSystemEvents = useCallback2(
|
|
1072
635
|
(sessionId2, events) => {
|
|
@@ -1284,7 +847,7 @@ function UserContextProvider({ children }) {
|
|
|
1284
847
|
}
|
|
1285
848
|
|
|
1286
849
|
// packages/react/src/runtime/core.tsx
|
|
1287
|
-
import { useCallback as
|
|
850
|
+
import { useCallback as useCallback7, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef7 } from "react";
|
|
1288
851
|
import {
|
|
1289
852
|
AssistantRuntimeProvider,
|
|
1290
853
|
useExternalStoreRuntime
|
|
@@ -1398,28 +961,12 @@ var getChainInfo = (chainId) => chainId === void 0 ? void 0 : SUPPORTED_CHAINS.f
|
|
|
1398
961
|
// packages/react/src/state/backend-state.ts
|
|
1399
962
|
function createBackendState() {
|
|
1400
963
|
return {
|
|
1401
|
-
|
|
1402
|
-
pendingChat: /* @__PURE__ */ new Map(),
|
|
1403
|
-
runningThreads: /* @__PURE__ */ new Set(),
|
|
1404
|
-
creatingThreadId: null,
|
|
1405
|
-
createThreadPromise: null
|
|
964
|
+
runningThreads: /* @__PURE__ */ new Set()
|
|
1406
965
|
};
|
|
1407
966
|
}
|
|
1408
|
-
function resolveThreadId(
|
|
967
|
+
function resolveThreadId(_state, threadId) {
|
|
1409
968
|
return threadId;
|
|
1410
969
|
}
|
|
1411
|
-
function isThreadReady(state, threadId) {
|
|
1412
|
-
return state.creatingThreadId !== threadId;
|
|
1413
|
-
}
|
|
1414
|
-
function markSkipInitialFetch(state, threadId) {
|
|
1415
|
-
state.skipInitialFetch.add(threadId);
|
|
1416
|
-
}
|
|
1417
|
-
function shouldSkipInitialFetch(state, threadId) {
|
|
1418
|
-
return state.skipInitialFetch.has(threadId);
|
|
1419
|
-
}
|
|
1420
|
-
function clearSkipInitialFetch(state, threadId) {
|
|
1421
|
-
state.skipInitialFetch.delete(threadId);
|
|
1422
|
-
}
|
|
1423
970
|
function setThreadRunning(state, threadId, running) {
|
|
1424
971
|
if (running) {
|
|
1425
972
|
state.runningThreads.add(threadId);
|
|
@@ -1430,21 +977,6 @@ function setThreadRunning(state, threadId, running) {
|
|
|
1430
977
|
function isThreadRunning(state, threadId) {
|
|
1431
978
|
return state.runningThreads.has(threadId);
|
|
1432
979
|
}
|
|
1433
|
-
function enqueuePendingChat(state, threadId, text) {
|
|
1434
|
-
var _a;
|
|
1435
|
-
const existing = (_a = state.pendingChat.get(threadId)) != null ? _a : [];
|
|
1436
|
-
state.pendingChat.set(threadId, [...existing, text]);
|
|
1437
|
-
}
|
|
1438
|
-
function dequeuePendingChat(state, threadId) {
|
|
1439
|
-
var _a;
|
|
1440
|
-
const pending = (_a = state.pendingChat.get(threadId)) != null ? _a : [];
|
|
1441
|
-
state.pendingChat.delete(threadId);
|
|
1442
|
-
return pending;
|
|
1443
|
-
}
|
|
1444
|
-
function hasPendingChat(state, threadId) {
|
|
1445
|
-
var _a, _b;
|
|
1446
|
-
return ((_b = (_a = state.pendingChat.get(threadId)) == null ? void 0 : _a.length) != null ? _b : 0) > 0;
|
|
1447
|
-
}
|
|
1448
980
|
|
|
1449
981
|
// packages/react/src/runtime/message-controller.ts
|
|
1450
982
|
var MessageController = class {
|
|
@@ -1452,11 +984,7 @@ var MessageController = class {
|
|
|
1452
984
|
this.config = config;
|
|
1453
985
|
}
|
|
1454
986
|
inbound(threadId, msgs) {
|
|
1455
|
-
const backendState = this.config.backendStateRef.current;
|
|
1456
987
|
if (!msgs) return;
|
|
1457
|
-
if (hasPendingChat(backendState, threadId)) {
|
|
1458
|
-
return;
|
|
1459
|
-
}
|
|
1460
988
|
const threadMessages = [];
|
|
1461
989
|
for (const msg of msgs) {
|
|
1462
990
|
const threadMessage = toInboundMessage(msg);
|
|
@@ -1486,25 +1014,17 @@ var MessageController = class {
|
|
|
1486
1014
|
threadState.updateThreadMetadata(threadId, {
|
|
1487
1015
|
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1488
1016
|
});
|
|
1489
|
-
if (!isThreadReady(backendState, threadId)) {
|
|
1490
|
-
this.markRunning(threadId, true);
|
|
1491
|
-
enqueuePendingChat(backendState, threadId, text);
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
1017
|
const backendThreadId = resolveThreadId(backendState, threadId);
|
|
1495
|
-
const
|
|
1018
|
+
const app = this.config.getApp();
|
|
1496
1019
|
const publicKey = (_b = (_a = this.config).getPublicKey) == null ? void 0 : _b.call(_a);
|
|
1497
1020
|
const apiKey = (_e = (_d = (_c = this.config).getApiKey) == null ? void 0 : _d.call(_c)) != null ? _e : void 0;
|
|
1498
1021
|
const userState = (_g = (_f = this.config).getUserState) == null ? void 0 : _g.call(_f);
|
|
1499
1022
|
try {
|
|
1500
1023
|
this.markRunning(threadId, true);
|
|
1501
|
-
const response = await this.config.
|
|
1024
|
+
const response = await this.config.aomiClientRef.current.sendMessage(
|
|
1502
1025
|
backendThreadId,
|
|
1503
1026
|
text,
|
|
1504
|
-
|
|
1505
|
-
publicKey,
|
|
1506
|
-
apiKey,
|
|
1507
|
-
userState
|
|
1027
|
+
{ app, publicKey, apiKey, userState }
|
|
1508
1028
|
);
|
|
1509
1029
|
if (response == null ? void 0 : response.messages) {
|
|
1510
1030
|
this.inbound(threadId, response.messages);
|
|
@@ -1522,40 +1042,13 @@ var MessageController = class {
|
|
|
1522
1042
|
this.markRunning(threadId, false);
|
|
1523
1043
|
}
|
|
1524
1044
|
}
|
|
1525
|
-
async flushPendingChat(threadId) {
|
|
1526
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1527
|
-
const backendState = this.config.backendStateRef.current;
|
|
1528
|
-
const pending = dequeuePendingChat(backendState, threadId);
|
|
1529
|
-
if (!pending.length) return;
|
|
1530
|
-
const backendThreadId = resolveThreadId(backendState, threadId);
|
|
1531
|
-
const namespace = this.config.getNamespace();
|
|
1532
|
-
const publicKey = (_b = (_a = this.config).getPublicKey) == null ? void 0 : _b.call(_a);
|
|
1533
|
-
const apiKey = (_e = (_d = (_c = this.config).getApiKey) == null ? void 0 : _d.call(_c)) != null ? _e : void 0;
|
|
1534
|
-
const userState = (_g = (_f = this.config).getUserState) == null ? void 0 : _g.call(_f);
|
|
1535
|
-
for (const text of pending) {
|
|
1536
|
-
try {
|
|
1537
|
-
await this.config.backendApiRef.current.postChatMessage(
|
|
1538
|
-
backendThreadId,
|
|
1539
|
-
text,
|
|
1540
|
-
namespace,
|
|
1541
|
-
publicKey,
|
|
1542
|
-
apiKey,
|
|
1543
|
-
userState
|
|
1544
|
-
);
|
|
1545
|
-
} catch (error) {
|
|
1546
|
-
console.error("Failed to send queued message:", error);
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
this.config.polling.start(threadId);
|
|
1550
|
-
}
|
|
1551
1045
|
async cancel(threadId) {
|
|
1552
1046
|
var _a;
|
|
1553
|
-
const backendState = this.config.backendStateRef.current;
|
|
1554
|
-
if (!isThreadReady(backendState, threadId)) return;
|
|
1555
1047
|
this.config.polling.stop(threadId);
|
|
1048
|
+
const backendState = this.config.backendStateRef.current;
|
|
1556
1049
|
const backendThreadId = resolveThreadId(backendState, threadId);
|
|
1557
1050
|
try {
|
|
1558
|
-
const response = await this.config.
|
|
1051
|
+
const response = await this.config.aomiClientRef.current.interrupt(backendThreadId);
|
|
1559
1052
|
if (response == null ? void 0 : response.messages) {
|
|
1560
1053
|
this.inbound(threadId, response.messages);
|
|
1561
1054
|
}
|
|
@@ -1591,7 +1084,6 @@ var PollingController = class {
|
|
|
1591
1084
|
start(threadId) {
|
|
1592
1085
|
var _a, _b;
|
|
1593
1086
|
const backendState = this.config.backendStateRef.current;
|
|
1594
|
-
if (!isThreadReady(backendState, threadId)) return;
|
|
1595
1087
|
if (this.intervals.has(threadId)) return;
|
|
1596
1088
|
const backendThreadId = resolveThreadId(backendState, threadId);
|
|
1597
1089
|
setThreadRunning(backendState, threadId, true);
|
|
@@ -1604,7 +1096,7 @@ var PollingController = class {
|
|
|
1604
1096
|
threadId
|
|
1605
1097
|
);
|
|
1606
1098
|
const userState = (_b2 = (_a2 = this.config).getUserState) == null ? void 0 : _b2.call(_a2);
|
|
1607
|
-
const state = await this.config.
|
|
1099
|
+
const state = await this.config.aomiClientRef.current.fetchState(
|
|
1608
1100
|
backendThreadId,
|
|
1609
1101
|
userState
|
|
1610
1102
|
);
|
|
@@ -1652,12 +1144,12 @@ var PollingController = class {
|
|
|
1652
1144
|
};
|
|
1653
1145
|
|
|
1654
1146
|
// packages/react/src/runtime/orchestrator.ts
|
|
1655
|
-
function useRuntimeOrchestrator(
|
|
1147
|
+
function useRuntimeOrchestrator(aomiClient, options) {
|
|
1656
1148
|
const threadContext = useThreadContext();
|
|
1657
1149
|
const threadContextRef = useRef5(threadContext);
|
|
1658
1150
|
threadContextRef.current = threadContext;
|
|
1659
|
-
const
|
|
1660
|
-
|
|
1151
|
+
const aomiClientRef = useRef5(aomiClient);
|
|
1152
|
+
aomiClientRef.current = aomiClient;
|
|
1661
1153
|
const backendStateRef = useRef5(createBackendState());
|
|
1662
1154
|
const [isRunning, setIsRunning] = useState5(false);
|
|
1663
1155
|
const messageControllerRef = useRef5(null);
|
|
@@ -1665,7 +1157,7 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1665
1157
|
const pendingFetches = useRef5(/* @__PURE__ */ new Set());
|
|
1666
1158
|
if (!pollingRef.current) {
|
|
1667
1159
|
pollingRef.current = new PollingController({
|
|
1668
|
-
|
|
1160
|
+
aomiClientRef,
|
|
1669
1161
|
backendStateRef,
|
|
1670
1162
|
applyMessages: (threadId, msgs) => {
|
|
1671
1163
|
var _a;
|
|
@@ -1687,13 +1179,13 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1687
1179
|
}
|
|
1688
1180
|
if (!messageControllerRef.current) {
|
|
1689
1181
|
messageControllerRef.current = new MessageController({
|
|
1690
|
-
|
|
1182
|
+
aomiClientRef,
|
|
1691
1183
|
backendStateRef,
|
|
1692
1184
|
threadContextRef,
|
|
1693
1185
|
polling: pollingRef.current,
|
|
1694
1186
|
setGlobalIsRunning: setIsRunning,
|
|
1695
1187
|
getPublicKey: options.getPublicKey,
|
|
1696
|
-
|
|
1188
|
+
getApp: options.getApp,
|
|
1697
1189
|
getApiKey: options.getApiKey,
|
|
1698
1190
|
getUserState: options.getUserState,
|
|
1699
1191
|
onSyncEvents: options.onSyncEvents
|
|
@@ -1701,26 +1193,12 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1701
1193
|
}
|
|
1702
1194
|
const ensureInitialState = useCallback5(async (threadId) => {
|
|
1703
1195
|
var _a, _b, _c, _d;
|
|
1704
|
-
const backendState = backendStateRef.current;
|
|
1705
|
-
if (shouldSkipInitialFetch(backendState, threadId)) {
|
|
1706
|
-
clearSkipInitialFetch(backendState, threadId);
|
|
1707
|
-
if (threadContextRef.current.currentThreadId === threadId) {
|
|
1708
|
-
setIsRunning(false);
|
|
1709
|
-
}
|
|
1710
|
-
return;
|
|
1711
|
-
}
|
|
1712
|
-
if (!isThreadReady(backendState, threadId)) {
|
|
1713
|
-
if (threadContextRef.current.currentThreadId === threadId) {
|
|
1714
|
-
setIsRunning(false);
|
|
1715
|
-
}
|
|
1716
|
-
return;
|
|
1717
|
-
}
|
|
1718
1196
|
if (pendingFetches.current.has(threadId)) return;
|
|
1719
|
-
const backendThreadId = resolveThreadId(
|
|
1197
|
+
const backendThreadId = resolveThreadId(backendStateRef.current, threadId);
|
|
1720
1198
|
pendingFetches.current.add(threadId);
|
|
1721
1199
|
try {
|
|
1722
1200
|
const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
|
|
1723
|
-
const state = await
|
|
1201
|
+
const state = await aomiClientRef.current.fetchState(
|
|
1724
1202
|
backendThreadId,
|
|
1725
1203
|
userState
|
|
1726
1204
|
);
|
|
@@ -1752,7 +1230,7 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1752
1230
|
isRunning,
|
|
1753
1231
|
setIsRunning,
|
|
1754
1232
|
ensureInitialState,
|
|
1755
|
-
|
|
1233
|
+
aomiClientRef
|
|
1756
1234
|
};
|
|
1757
1235
|
}
|
|
1758
1236
|
|
|
@@ -1783,151 +1261,35 @@ function buildThreadLists(threadMetadata) {
|
|
|
1783
1261
|
return { regularThreads, archivedThreads };
|
|
1784
1262
|
}
|
|
1785
1263
|
function buildThreadListAdapter({
|
|
1786
|
-
|
|
1787
|
-
backendApiRef,
|
|
1264
|
+
aomiClientRef,
|
|
1788
1265
|
threadContext,
|
|
1789
|
-
|
|
1790
|
-
polling,
|
|
1791
|
-
userAddress,
|
|
1792
|
-
setIsRunning,
|
|
1793
|
-
getNamespace,
|
|
1794
|
-
getApiKey,
|
|
1795
|
-
getUserState
|
|
1266
|
+
setIsRunning
|
|
1796
1267
|
}) {
|
|
1797
|
-
const backendState = backendStateRef.current;
|
|
1798
1268
|
const { regularThreads, archivedThreads } = buildThreadLists(
|
|
1799
1269
|
threadContext.allThreadsMetadata
|
|
1800
1270
|
);
|
|
1801
|
-
const preparePendingThread = (threadId) => {
|
|
1802
|
-
const previousPendingId = backendState.creatingThreadId;
|
|
1803
|
-
if (previousPendingId && previousPendingId !== threadId) {
|
|
1804
|
-
threadContext.setThreadMetadata((prev) => {
|
|
1805
|
-
const next = new Map(prev);
|
|
1806
|
-
next.delete(previousPendingId);
|
|
1807
|
-
return next;
|
|
1808
|
-
});
|
|
1809
|
-
threadContext.setThreads((prev) => {
|
|
1810
|
-
const next = new Map(prev);
|
|
1811
|
-
next.delete(previousPendingId);
|
|
1812
|
-
return next;
|
|
1813
|
-
});
|
|
1814
|
-
backendState.pendingChat.delete(previousPendingId);
|
|
1815
|
-
backendState.skipInitialFetch.delete(previousPendingId);
|
|
1816
|
-
}
|
|
1817
|
-
backendState.creatingThreadId = threadId;
|
|
1818
|
-
backendState.pendingChat.delete(threadId);
|
|
1819
|
-
threadContext.setThreadMetadata(
|
|
1820
|
-
(prev) => new Map(prev).set(threadId, {
|
|
1821
|
-
title: "New Chat",
|
|
1822
|
-
status: "pending",
|
|
1823
|
-
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1824
|
-
control: initThreadControl()
|
|
1825
|
-
})
|
|
1826
|
-
);
|
|
1827
|
-
threadContext.setThreadMessages(threadId, []);
|
|
1828
|
-
threadContext.setCurrentThreadId(threadId);
|
|
1829
|
-
setIsRunning(false);
|
|
1830
|
-
threadContext.bumpThreadViewKey();
|
|
1831
|
-
};
|
|
1832
|
-
const findPendingThreadId = () => {
|
|
1833
|
-
if (backendState.creatingThreadId) return backendState.creatingThreadId;
|
|
1834
|
-
for (const [id, meta] of threadContext.allThreadsMetadata.entries()) {
|
|
1835
|
-
if (meta.status === "pending") return id;
|
|
1836
|
-
}
|
|
1837
|
-
return null;
|
|
1838
|
-
};
|
|
1839
1271
|
return {
|
|
1840
1272
|
threadId: threadContext.currentThreadId,
|
|
1841
1273
|
threads: regularThreads,
|
|
1842
1274
|
archivedThreads,
|
|
1843
|
-
onSwitchToNewThread:
|
|
1844
|
-
var _a;
|
|
1845
|
-
const pendingId = findPendingThreadId();
|
|
1846
|
-
if (pendingId) {
|
|
1847
|
-
preparePendingThread(pendingId);
|
|
1848
|
-
return;
|
|
1849
|
-
}
|
|
1850
|
-
if (backendState.createThreadPromise) {
|
|
1851
|
-
preparePendingThread((_a = backendState.creatingThreadId) != null ? _a : generateUUID());
|
|
1852
|
-
return;
|
|
1853
|
-
}
|
|
1275
|
+
onSwitchToNewThread: () => {
|
|
1854
1276
|
const threadId = generateUUID();
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
threadContext.setThreadMetadata((prev) => {
|
|
1868
|
-
var _a3, _b2, _c;
|
|
1869
|
-
const next = new Map(prev);
|
|
1870
|
-
const existing = next.get(uiThreadId);
|
|
1871
|
-
const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
|
|
1872
|
-
next.set(uiThreadId, {
|
|
1873
|
-
title: (_a3 = existing == null ? void 0 : existing.title) != null ? _a3 : "New Chat",
|
|
1874
|
-
status: nextStatus,
|
|
1875
|
-
lastActiveAt: (_b2 = existing == null ? void 0 : existing.lastActiveAt) != null ? _b2 : (/* @__PURE__ */ new Date()).toISOString(),
|
|
1876
|
-
control: (_c = existing == null ? void 0 : existing.control) != null ? _c : initThreadControl()
|
|
1877
|
-
});
|
|
1878
|
-
return next;
|
|
1879
|
-
});
|
|
1880
|
-
if (backendState.creatingThreadId === uiThreadId) {
|
|
1881
|
-
backendState.creatingThreadId = null;
|
|
1882
|
-
}
|
|
1883
|
-
const pendingMessages = backendState.pendingChat.get(uiThreadId);
|
|
1884
|
-
if (pendingMessages == null ? void 0 : pendingMessages.length) {
|
|
1885
|
-
backendState.pendingChat.delete(uiThreadId);
|
|
1886
|
-
const namespace = getNamespace();
|
|
1887
|
-
const apiKey = (_b = getApiKey == null ? void 0 : getApiKey()) != null ? _b : void 0;
|
|
1888
|
-
const userState = getUserState == null ? void 0 : getUserState();
|
|
1889
|
-
for (const text of pendingMessages) {
|
|
1890
|
-
try {
|
|
1891
|
-
await backendApiRef.current.postChatMessage(
|
|
1892
|
-
backendId,
|
|
1893
|
-
text,
|
|
1894
|
-
namespace,
|
|
1895
|
-
userAddress,
|
|
1896
|
-
apiKey,
|
|
1897
|
-
userState
|
|
1898
|
-
);
|
|
1899
|
-
} catch (error) {
|
|
1900
|
-
console.error("Failed to send queued message:", error);
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
if (currentThreadIdRef.current === uiThreadId) {
|
|
1904
|
-
polling == null ? void 0 : polling.start(uiThreadId);
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
}).catch((error) => {
|
|
1908
|
-
var _a2;
|
|
1909
|
-
console.error("Failed to create new thread:", error);
|
|
1910
|
-
const failedId = (_a2 = backendState.creatingThreadId) != null ? _a2 : threadId;
|
|
1911
|
-
threadContext.setThreadMetadata((prev) => {
|
|
1912
|
-
const next = new Map(prev);
|
|
1913
|
-
next.delete(failedId);
|
|
1914
|
-
return next;
|
|
1915
|
-
});
|
|
1916
|
-
threadContext.setThreads((prev) => {
|
|
1917
|
-
const next = new Map(prev);
|
|
1918
|
-
next.delete(failedId);
|
|
1919
|
-
return next;
|
|
1920
|
-
});
|
|
1921
|
-
if (backendState.creatingThreadId === failedId) {
|
|
1922
|
-
backendState.creatingThreadId = null;
|
|
1923
|
-
}
|
|
1924
|
-
}).finally(() => {
|
|
1925
|
-
backendState.createThreadPromise = null;
|
|
1926
|
-
});
|
|
1927
|
-
backendState.createThreadPromise = createPromise;
|
|
1277
|
+
threadContext.setThreadMetadata(
|
|
1278
|
+
(prev) => new Map(prev).set(threadId, {
|
|
1279
|
+
title: "New Chat",
|
|
1280
|
+
status: "regular",
|
|
1281
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1282
|
+
control: initThreadControl()
|
|
1283
|
+
})
|
|
1284
|
+
);
|
|
1285
|
+
threadContext.setThreadMessages(threadId, []);
|
|
1286
|
+
threadContext.setCurrentThreadId(threadId);
|
|
1287
|
+
setIsRunning(false);
|
|
1288
|
+
threadContext.bumpThreadViewKey();
|
|
1928
1289
|
},
|
|
1929
1290
|
onSwitchToThread: (threadId) => {
|
|
1930
1291
|
threadContext.setCurrentThreadId(threadId);
|
|
1292
|
+
threadContext.bumpThreadViewKey();
|
|
1931
1293
|
},
|
|
1932
1294
|
onRename: async (threadId, newTitle) => {
|
|
1933
1295
|
var _a, _b;
|
|
@@ -1937,7 +1299,7 @@ function buildThreadListAdapter({
|
|
|
1937
1299
|
title: normalizedTitle
|
|
1938
1300
|
});
|
|
1939
1301
|
try {
|
|
1940
|
-
await
|
|
1302
|
+
await aomiClientRef.current.renameThread(threadId, newTitle);
|
|
1941
1303
|
} catch (error) {
|
|
1942
1304
|
console.error("Failed to rename thread:", error);
|
|
1943
1305
|
threadContext.updateThreadMetadata(threadId, {
|
|
@@ -1948,7 +1310,7 @@ function buildThreadListAdapter({
|
|
|
1948
1310
|
onArchive: async (threadId) => {
|
|
1949
1311
|
threadContext.updateThreadMetadata(threadId, { status: "archived" });
|
|
1950
1312
|
try {
|
|
1951
|
-
await
|
|
1313
|
+
await aomiClientRef.current.archiveThread(threadId);
|
|
1952
1314
|
} catch (error) {
|
|
1953
1315
|
console.error("Failed to archive thread:", error);
|
|
1954
1316
|
threadContext.updateThreadMetadata(threadId, { status: "regular" });
|
|
@@ -1957,7 +1319,7 @@ function buildThreadListAdapter({
|
|
|
1957
1319
|
onUnarchive: async (threadId) => {
|
|
1958
1320
|
threadContext.updateThreadMetadata(threadId, { status: "regular" });
|
|
1959
1321
|
try {
|
|
1960
|
-
await
|
|
1322
|
+
await aomiClientRef.current.unarchiveThread(threadId);
|
|
1961
1323
|
} catch (error) {
|
|
1962
1324
|
console.error("Failed to unarchive thread:", error);
|
|
1963
1325
|
threadContext.updateThreadMetadata(threadId, { status: "archived" });
|
|
@@ -1965,7 +1327,7 @@ function buildThreadListAdapter({
|
|
|
1965
1327
|
},
|
|
1966
1328
|
onDelete: async (threadId) => {
|
|
1967
1329
|
try {
|
|
1968
|
-
await
|
|
1330
|
+
await aomiClientRef.current.deleteThread(threadId);
|
|
1969
1331
|
threadContext.setThreadMetadata((prev) => {
|
|
1970
1332
|
const next = new Map(prev);
|
|
1971
1333
|
next.delete(threadId);
|
|
@@ -1976,12 +1338,6 @@ function buildThreadListAdapter({
|
|
|
1976
1338
|
next.delete(threadId);
|
|
1977
1339
|
return next;
|
|
1978
1340
|
});
|
|
1979
|
-
backendState.pendingChat.delete(threadId);
|
|
1980
|
-
backendState.skipInitialFetch.delete(threadId);
|
|
1981
|
-
backendState.runningThreads.delete(threadId);
|
|
1982
|
-
if (backendState.creatingThreadId === threadId) {
|
|
1983
|
-
backendState.creatingThreadId = null;
|
|
1984
|
-
}
|
|
1985
1341
|
if (threadContext.currentThreadId === threadId) {
|
|
1986
1342
|
const firstRegularThread = Array.from(
|
|
1987
1343
|
threadContext.allThreadsMetadata.entries()
|
|
@@ -2024,11 +1380,223 @@ function useAomiRuntime() {
|
|
|
2024
1380
|
return context;
|
|
2025
1381
|
}
|
|
2026
1382
|
|
|
1383
|
+
// packages/react/src/handlers/wallet-handler.ts
|
|
1384
|
+
import { useCallback as useCallback6, useEffect as useEffect3, useRef as useRef6, useState as useState6 } from "react";
|
|
1385
|
+
|
|
1386
|
+
// packages/react/src/state/wallet-buffer.ts
|
|
1387
|
+
function createWalletBuffer() {
|
|
1388
|
+
return { queue: [], nextId: 1 };
|
|
1389
|
+
}
|
|
1390
|
+
function enqueue(buffer, kind, payload) {
|
|
1391
|
+
const request = {
|
|
1392
|
+
id: `wreq-${buffer.nextId++}`,
|
|
1393
|
+
kind,
|
|
1394
|
+
payload,
|
|
1395
|
+
status: "pending",
|
|
1396
|
+
timestamp: Date.now()
|
|
1397
|
+
};
|
|
1398
|
+
buffer.queue.push(request);
|
|
1399
|
+
return request;
|
|
1400
|
+
}
|
|
1401
|
+
function dequeue(buffer, id) {
|
|
1402
|
+
const index = buffer.queue.findIndex((r) => r.id === id);
|
|
1403
|
+
if (index === -1) return null;
|
|
1404
|
+
return buffer.queue.splice(index, 1)[0];
|
|
1405
|
+
}
|
|
1406
|
+
function markProcessing(buffer, id) {
|
|
1407
|
+
const request = buffer.queue.find((r) => r.id === id);
|
|
1408
|
+
if (!request || request.status !== "pending") return false;
|
|
1409
|
+
request.status = "processing";
|
|
1410
|
+
return true;
|
|
1411
|
+
}
|
|
1412
|
+
function getAll(buffer) {
|
|
1413
|
+
return [...buffer.queue];
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// 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
|
+
function useWalletHandler({
|
|
1480
|
+
sessionId,
|
|
1481
|
+
onRequestComplete
|
|
1482
|
+
}) {
|
|
1483
|
+
const { subscribe: subscribe2, sendOutboundSystem: sendOutbound } = useEventContext();
|
|
1484
|
+
const bufferRef = useRef6(createWalletBuffer());
|
|
1485
|
+
const [pendingRequests, setPendingRequests] = useState6([]);
|
|
1486
|
+
const syncState = useCallback6(() => {
|
|
1487
|
+
setPendingRequests(getAll(bufferRef.current));
|
|
1488
|
+
}, []);
|
|
1489
|
+
useEffect3(() => {
|
|
1490
|
+
const unsubscribe = subscribe2(
|
|
1491
|
+
"wallet_tx_request",
|
|
1492
|
+
(event) => {
|
|
1493
|
+
const payload = normalizeTxPayload(event.payload);
|
|
1494
|
+
if (!payload) {
|
|
1495
|
+
console.warn("[aomi][wallet] Ignoring tx request with invalid payload", event.payload);
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
enqueue(bufferRef.current, "transaction", payload);
|
|
1499
|
+
syncState();
|
|
1500
|
+
}
|
|
1501
|
+
);
|
|
1502
|
+
return unsubscribe;
|
|
1503
|
+
}, [subscribe2, syncState]);
|
|
1504
|
+
useEffect3(() => {
|
|
1505
|
+
const unsubscribe = subscribe2(
|
|
1506
|
+
"wallet_eip712_request",
|
|
1507
|
+
(event) => {
|
|
1508
|
+
var _a;
|
|
1509
|
+
const payload = normalizeEip712Payload((_a = event.payload) != null ? _a : {});
|
|
1510
|
+
enqueue(bufferRef.current, "eip712_sign", payload);
|
|
1511
|
+
syncState();
|
|
1512
|
+
}
|
|
1513
|
+
);
|
|
1514
|
+
return unsubscribe;
|
|
1515
|
+
}, [subscribe2, syncState]);
|
|
1516
|
+
const startProcessingCb = useCallback6(
|
|
1517
|
+
(id) => {
|
|
1518
|
+
markProcessing(bufferRef.current, id);
|
|
1519
|
+
syncState();
|
|
1520
|
+
},
|
|
1521
|
+
[syncState]
|
|
1522
|
+
);
|
|
1523
|
+
const resolveRequest = useCallback6(
|
|
1524
|
+
(id, result) => {
|
|
1525
|
+
var _a;
|
|
1526
|
+
const removed = dequeue(bufferRef.current, id);
|
|
1527
|
+
if (!removed) return;
|
|
1528
|
+
let outbound;
|
|
1529
|
+
if (removed.kind === "transaction") {
|
|
1530
|
+
outbound = sendOutbound({
|
|
1531
|
+
type: "wallet:tx_complete",
|
|
1532
|
+
sessionId,
|
|
1533
|
+
payload: {
|
|
1534
|
+
txHash: (_a = result.txHash) != null ? _a : "",
|
|
1535
|
+
status: "success",
|
|
1536
|
+
amount: result.amount
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
} else {
|
|
1540
|
+
const eip712Payload = removed.payload;
|
|
1541
|
+
outbound = sendOutbound({
|
|
1542
|
+
type: "wallet_eip712_response",
|
|
1543
|
+
sessionId,
|
|
1544
|
+
payload: {
|
|
1545
|
+
status: "success",
|
|
1546
|
+
signature: result.signature,
|
|
1547
|
+
description: eip712Payload.description
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
outbound.then(() => onRequestComplete == null ? void 0 : onRequestComplete());
|
|
1552
|
+
syncState();
|
|
1553
|
+
},
|
|
1554
|
+
[sendOutbound, sessionId, syncState, onRequestComplete]
|
|
1555
|
+
);
|
|
1556
|
+
const rejectRequest = useCallback6(
|
|
1557
|
+
(id, error) => {
|
|
1558
|
+
const removed = dequeue(bufferRef.current, id);
|
|
1559
|
+
if (!removed) return;
|
|
1560
|
+
let outbound;
|
|
1561
|
+
if (removed.kind === "transaction") {
|
|
1562
|
+
outbound = sendOutbound({
|
|
1563
|
+
type: "wallet:tx_complete",
|
|
1564
|
+
sessionId,
|
|
1565
|
+
payload: {
|
|
1566
|
+
txHash: "",
|
|
1567
|
+
status: "failed"
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
} else {
|
|
1571
|
+
const eip712Payload = removed.payload;
|
|
1572
|
+
outbound = sendOutbound({
|
|
1573
|
+
type: "wallet_eip712_response",
|
|
1574
|
+
sessionId,
|
|
1575
|
+
payload: {
|
|
1576
|
+
status: "failed",
|
|
1577
|
+
error: error != null ? error : "EIP-712 signing failed",
|
|
1578
|
+
description: eip712Payload.description
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1582
|
+
outbound.then(() => onRequestComplete == null ? void 0 : onRequestComplete());
|
|
1583
|
+
syncState();
|
|
1584
|
+
},
|
|
1585
|
+
[sendOutbound, sessionId, syncState, onRequestComplete]
|
|
1586
|
+
);
|
|
1587
|
+
return {
|
|
1588
|
+
pendingRequests,
|
|
1589
|
+
startProcessing: startProcessingCb,
|
|
1590
|
+
resolveRequest,
|
|
1591
|
+
rejectRequest
|
|
1592
|
+
};
|
|
1593
|
+
}
|
|
1594
|
+
|
|
2027
1595
|
// packages/react/src/runtime/core.tsx
|
|
2028
1596
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2029
1597
|
function AomiRuntimeCore({
|
|
2030
1598
|
children,
|
|
2031
|
-
|
|
1599
|
+
aomiClient
|
|
2032
1600
|
}) {
|
|
2033
1601
|
const threadContext = useThreadContext();
|
|
2034
1602
|
const eventContext = useEventContext();
|
|
@@ -2043,18 +1611,18 @@ function AomiRuntimeCore({
|
|
|
2043
1611
|
isRunning,
|
|
2044
1612
|
setIsRunning,
|
|
2045
1613
|
ensureInitialState,
|
|
2046
|
-
|
|
2047
|
-
} = useRuntimeOrchestrator(
|
|
1614
|
+
aomiClientRef
|
|
1615
|
+
} = useRuntimeOrchestrator(aomiClient, {
|
|
2048
1616
|
onSyncEvents: dispatchSystemEvents,
|
|
2049
1617
|
getPublicKey: () => getUserState().address,
|
|
2050
1618
|
getUserState,
|
|
2051
|
-
|
|
1619
|
+
getApp: () => {
|
|
2052
1620
|
var _a, _b;
|
|
2053
|
-
return (_b = (_a = getCurrentThreadControl().
|
|
1621
|
+
return (_b = (_a = getCurrentThreadControl().app) != null ? _a : getControlState().defaultApp) != null ? _b : "default";
|
|
2054
1622
|
},
|
|
2055
1623
|
getApiKey: () => getControlState().apiKey
|
|
2056
1624
|
});
|
|
2057
|
-
|
|
1625
|
+
useEffect4(() => {
|
|
2058
1626
|
const unsubscribe = onUserStateChange(async (newUser) => {
|
|
2059
1627
|
const sessionId = threadContext.currentThreadId;
|
|
2060
1628
|
const message = JSON.stringify({
|
|
@@ -2066,24 +1634,44 @@ function AomiRuntimeCore({
|
|
|
2066
1634
|
ensName: newUser.ensName
|
|
2067
1635
|
}
|
|
2068
1636
|
});
|
|
2069
|
-
await
|
|
1637
|
+
await aomiClientRef.current.sendSystemMessage(sessionId, message);
|
|
2070
1638
|
});
|
|
2071
1639
|
return unsubscribe;
|
|
2072
|
-
}, [onUserStateChange,
|
|
2073
|
-
const threadContextRef =
|
|
1640
|
+
}, [onUserStateChange, aomiClientRef, threadContext.currentThreadId]);
|
|
1641
|
+
const threadContextRef = useRef7(threadContext);
|
|
2074
1642
|
threadContextRef.current = threadContext;
|
|
2075
|
-
const currentThreadIdRef =
|
|
2076
|
-
|
|
1643
|
+
const currentThreadIdRef = useRef7(threadContext.currentThreadId);
|
|
1644
|
+
useEffect4(() => {
|
|
2077
1645
|
currentThreadIdRef.current = threadContext.currentThreadId;
|
|
2078
1646
|
}, [threadContext.currentThreadId]);
|
|
2079
|
-
|
|
1647
|
+
const onWalletRequestComplete = useCallback7(() => {
|
|
1648
|
+
polling.start(currentThreadIdRef.current);
|
|
1649
|
+
}, [polling]);
|
|
1650
|
+
const walletHandler = useWalletHandler({
|
|
1651
|
+
sessionId: threadContext.currentThreadId,
|
|
1652
|
+
onRequestComplete: onWalletRequestComplete
|
|
1653
|
+
});
|
|
1654
|
+
useEffect4(() => {
|
|
1655
|
+
const unsubscribe = eventContext.subscribe(
|
|
1656
|
+
"user_state_request",
|
|
1657
|
+
() => {
|
|
1658
|
+
eventContext.sendOutboundSystem({
|
|
1659
|
+
type: "user_state_response",
|
|
1660
|
+
sessionId: threadContext.currentThreadId,
|
|
1661
|
+
payload: getUserState()
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
);
|
|
1665
|
+
return unsubscribe;
|
|
1666
|
+
}, [eventContext, threadContext.currentThreadId, getUserState]);
|
|
1667
|
+
useEffect4(() => {
|
|
2080
1668
|
void ensureInitialState(threadContext.currentThreadId);
|
|
2081
1669
|
}, [ensureInitialState, threadContext.currentThreadId]);
|
|
2082
|
-
|
|
1670
|
+
useEffect4(() => {
|
|
2083
1671
|
const threadId = threadContext.currentThreadId;
|
|
2084
1672
|
setIsRunning(isThreadRunning(backendStateRef.current, threadId));
|
|
2085
1673
|
}, [backendStateRef, setIsRunning, threadContext.currentThreadId]);
|
|
2086
|
-
|
|
1674
|
+
useEffect4(() => {
|
|
2087
1675
|
const threadId = threadContext.currentThreadId;
|
|
2088
1676
|
const currentMeta = threadContext.getThreadMetadata(threadId);
|
|
2089
1677
|
if (currentMeta && currentMeta.control.isProcessing !== isRunning) {
|
|
@@ -2097,21 +1685,13 @@ function AomiRuntimeCore({
|
|
|
2097
1685
|
const currentMessages = threadContext.getThreadMessages(
|
|
2098
1686
|
threadContext.currentThreadId
|
|
2099
1687
|
);
|
|
2100
|
-
|
|
2101
|
-
() => resolveThreadId(backendStateRef.current, threadContext.currentThreadId),
|
|
2102
|
-
[
|
|
2103
|
-
backendStateRef,
|
|
2104
|
-
threadContext.currentThreadId,
|
|
2105
|
-
threadContext.allThreadsMetadata
|
|
2106
|
-
]
|
|
2107
|
-
);
|
|
2108
|
-
useEffect3(() => {
|
|
1688
|
+
useEffect4(() => {
|
|
2109
1689
|
const userAddress = user.address;
|
|
2110
1690
|
if (!userAddress) return;
|
|
2111
1691
|
const fetchThreadList = async () => {
|
|
2112
1692
|
var _a, _b, _c;
|
|
2113
1693
|
try {
|
|
2114
|
-
const threadList = await
|
|
1694
|
+
const threadList = await aomiClientRef.current.listThreads(userAddress);
|
|
2115
1695
|
const currentContext = threadContextRef.current;
|
|
2116
1696
|
const newMetadata = new Map(currentContext.allThreadsMetadata);
|
|
2117
1697
|
let maxChatNum = currentContext.threadCnt;
|
|
@@ -2143,25 +1723,25 @@ function AomiRuntimeCore({
|
|
|
2143
1723
|
}
|
|
2144
1724
|
};
|
|
2145
1725
|
void fetchThreadList();
|
|
2146
|
-
}, [user.address,
|
|
1726
|
+
}, [user.address, aomiClientRef]);
|
|
2147
1727
|
const threadListAdapter = useMemo2(
|
|
2148
1728
|
() => buildThreadListAdapter({
|
|
2149
1729
|
backendStateRef,
|
|
2150
|
-
|
|
1730
|
+
aomiClientRef,
|
|
2151
1731
|
threadContext,
|
|
2152
1732
|
currentThreadIdRef,
|
|
2153
1733
|
polling,
|
|
2154
1734
|
userAddress: user.address,
|
|
2155
1735
|
setIsRunning,
|
|
2156
|
-
|
|
1736
|
+
getApp: () => {
|
|
2157
1737
|
var _a, _b;
|
|
2158
|
-
return (_b = (_a = getCurrentThreadControl().
|
|
1738
|
+
return (_b = (_a = getCurrentThreadControl().app) != null ? _a : getControlState().defaultApp) != null ? _b : "default";
|
|
2159
1739
|
},
|
|
2160
1740
|
getApiKey: () => getControlState().apiKey,
|
|
2161
1741
|
getUserState
|
|
2162
1742
|
}),
|
|
2163
1743
|
[
|
|
2164
|
-
|
|
1744
|
+
aomiClientRef,
|
|
2165
1745
|
polling,
|
|
2166
1746
|
user.address,
|
|
2167
1747
|
backendStateRef,
|
|
@@ -2173,70 +1753,41 @@ function AomiRuntimeCore({
|
|
|
2173
1753
|
getUserState
|
|
2174
1754
|
]
|
|
2175
1755
|
);
|
|
2176
|
-
|
|
1756
|
+
useEffect4(() => {
|
|
2177
1757
|
const backendState = backendStateRef.current;
|
|
2178
|
-
const
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
const targetThreadId = resolveThreadId(backendState, sessionId);
|
|
2194
|
-
const normalizedTitle = isPlaceholderTitle(newTitle) ? "" : newTitle;
|
|
2195
|
-
if (process.env.NODE_ENV !== "production") {
|
|
2196
|
-
console.debug("[aomi][sse] title_changed", {
|
|
2197
|
-
sessionId,
|
|
2198
|
-
newTitle,
|
|
2199
|
-
normalizedTitle,
|
|
2200
|
-
currentThreadId: threadContextRef.current.currentThreadId,
|
|
2201
|
-
targetThreadId,
|
|
2202
|
-
hasMapping: sessionId !== targetThreadId,
|
|
2203
|
-
creatingThreadId: backendState.creatingThreadId
|
|
2204
|
-
});
|
|
2205
|
-
}
|
|
2206
|
-
threadContextRef.current.setThreadMetadata((prev) => {
|
|
2207
|
-
var _a, _b;
|
|
2208
|
-
const next = new Map(prev);
|
|
2209
|
-
const existing = next.get(targetThreadId);
|
|
2210
|
-
const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
|
|
2211
|
-
next.set(targetThreadId, {
|
|
2212
|
-
title: normalizedTitle,
|
|
2213
|
-
status: nextStatus,
|
|
2214
|
-
lastActiveAt: (_a = existing == null ? void 0 : existing.lastActiveAt) != null ? _a : (/* @__PURE__ */ new Date()).toISOString(),
|
|
2215
|
-
control: (_b = existing == null ? void 0 : existing.control) != null ? _b : initThreadControl()
|
|
2216
|
-
});
|
|
2217
|
-
return next;
|
|
2218
|
-
});
|
|
2219
|
-
if (!isPlaceholderTitle(newTitle) && backendState.creatingThreadId === targetThreadId) {
|
|
2220
|
-
backendState.creatingThreadId = null;
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
1758
|
+
const unsubscribe = eventContext.subscribe("title_changed", (event) => {
|
|
1759
|
+
const sessionId = event.sessionId;
|
|
1760
|
+
const payload = event.payload;
|
|
1761
|
+
const newTitle = payload == null ? void 0 : payload.new_title;
|
|
1762
|
+
if (typeof newTitle !== "string") return;
|
|
1763
|
+
const targetThreadId = resolveThreadId(backendState, sessionId);
|
|
1764
|
+
const normalizedTitle = isPlaceholderTitle(newTitle) ? "" : newTitle;
|
|
1765
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1766
|
+
console.debug("[aomi][sse] title_changed", {
|
|
1767
|
+
sessionId,
|
|
1768
|
+
newTitle,
|
|
1769
|
+
normalizedTitle,
|
|
1770
|
+
currentThreadId: threadContextRef.current.currentThreadId,
|
|
1771
|
+
targetThreadId
|
|
1772
|
+
});
|
|
2223
1773
|
}
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
1774
|
+
threadContextRef.current.setThreadMetadata((prev) => {
|
|
1775
|
+
var _a, _b;
|
|
1776
|
+
const next = new Map(prev);
|
|
1777
|
+
const existing = next.get(targetThreadId);
|
|
1778
|
+
const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
|
|
1779
|
+
next.set(targetThreadId, {
|
|
1780
|
+
title: normalizedTitle,
|
|
1781
|
+
status: nextStatus,
|
|
1782
|
+
lastActiveAt: (_a = existing == null ? void 0 : existing.lastActiveAt) != null ? _a : (/* @__PURE__ */ new Date()).toISOString(),
|
|
1783
|
+
control: (_b = existing == null ? void 0 : existing.control) != null ? _b : initThreadControl()
|
|
1784
|
+
});
|
|
1785
|
+
return next;
|
|
1786
|
+
});
|
|
1787
|
+
});
|
|
1788
|
+
return unsubscribe;
|
|
1789
|
+
}, [eventContext, backendStateRef]);
|
|
1790
|
+
useEffect4(() => {
|
|
2240
1791
|
const showToolNotification = (eventType) => (event) => {
|
|
2241
1792
|
const payload = event.payload;
|
|
2242
1793
|
const toolName = typeof (payload == null ? void 0 : payload.tool_name) === "string" ? payload.tool_name : void 0;
|
|
@@ -2261,7 +1812,7 @@ function AomiRuntimeCore({
|
|
|
2261
1812
|
unsubscribeComplete();
|
|
2262
1813
|
};
|
|
2263
1814
|
}, [eventContext, notificationContext]);
|
|
2264
|
-
|
|
1815
|
+
useEffect4(() => {
|
|
2265
1816
|
const unsubscribe = eventContext.subscribe("system_notice", (event) => {
|
|
2266
1817
|
const payload = event.payload;
|
|
2267
1818
|
const message = payload == null ? void 0 : payload.message;
|
|
@@ -2277,13 +1828,13 @@ function AomiRuntimeCore({
|
|
|
2277
1828
|
convertMessage: (msg) => msg,
|
|
2278
1829
|
adapters: { threadList: threadListAdapter }
|
|
2279
1830
|
});
|
|
2280
|
-
|
|
1831
|
+
useEffect4(() => {
|
|
2281
1832
|
return () => {
|
|
2282
1833
|
polling.stopAll();
|
|
2283
1834
|
};
|
|
2284
1835
|
}, [polling]);
|
|
2285
1836
|
const userContext = useUser();
|
|
2286
|
-
const sendMessage =
|
|
1837
|
+
const sendMessage = useCallback7(
|
|
2287
1838
|
async (text) => {
|
|
2288
1839
|
const appendMessage = {
|
|
2289
1840
|
role: "user",
|
|
@@ -2296,39 +1847,39 @@ function AomiRuntimeCore({
|
|
|
2296
1847
|
},
|
|
2297
1848
|
[messageController, threadContext.currentThreadId]
|
|
2298
1849
|
);
|
|
2299
|
-
const cancelGeneration =
|
|
1850
|
+
const cancelGeneration = useCallback7(() => {
|
|
2300
1851
|
messageController.cancel(threadContext.currentThreadId);
|
|
2301
1852
|
}, [messageController, threadContext.currentThreadId]);
|
|
2302
|
-
const getMessages =
|
|
1853
|
+
const getMessages = useCallback7(
|
|
2303
1854
|
(threadId) => {
|
|
2304
1855
|
const id = threadId != null ? threadId : threadContext.currentThreadId;
|
|
2305
1856
|
return threadContext.getThreadMessages(id);
|
|
2306
1857
|
},
|
|
2307
1858
|
[threadContext]
|
|
2308
1859
|
);
|
|
2309
|
-
const createThread =
|
|
1860
|
+
const createThread = useCallback7(async () => {
|
|
2310
1861
|
await threadListAdapter.onSwitchToNewThread();
|
|
2311
1862
|
return threadContextRef.current.currentThreadId;
|
|
2312
1863
|
}, [threadListAdapter]);
|
|
2313
|
-
const deleteThread =
|
|
1864
|
+
const deleteThread = useCallback7(
|
|
2314
1865
|
async (threadId) => {
|
|
2315
1866
|
await threadListAdapter.onDelete(threadId);
|
|
2316
1867
|
},
|
|
2317
1868
|
[threadListAdapter]
|
|
2318
1869
|
);
|
|
2319
|
-
const renameThread =
|
|
1870
|
+
const renameThread = useCallback7(
|
|
2320
1871
|
async (threadId, title) => {
|
|
2321
1872
|
await threadListAdapter.onRename(threadId, title);
|
|
2322
1873
|
},
|
|
2323
1874
|
[threadListAdapter]
|
|
2324
1875
|
);
|
|
2325
|
-
const archiveThread =
|
|
1876
|
+
const archiveThread = useCallback7(
|
|
2326
1877
|
async (threadId) => {
|
|
2327
1878
|
await threadListAdapter.onArchive(threadId);
|
|
2328
1879
|
},
|
|
2329
1880
|
[threadListAdapter]
|
|
2330
1881
|
);
|
|
2331
|
-
const selectThread =
|
|
1882
|
+
const selectThread = useCallback7(
|
|
2332
1883
|
(threadId) => {
|
|
2333
1884
|
if (threadContext.allThreadsMetadata.has(threadId)) {
|
|
2334
1885
|
threadListAdapter.onSwitchToThread(threadId);
|
|
@@ -2365,6 +1916,11 @@ function AomiRuntimeCore({
|
|
|
2365
1916
|
showNotification: notificationContext.showNotification,
|
|
2366
1917
|
dismissNotification: notificationContext.dismissNotification,
|
|
2367
1918
|
clearAllNotifications: notificationContext.clearAll,
|
|
1919
|
+
// Wallet API
|
|
1920
|
+
pendingWalletRequests: walletHandler.pendingRequests,
|
|
1921
|
+
startWalletRequest: walletHandler.startProcessing,
|
|
1922
|
+
resolveWalletRequest: walletHandler.resolveRequest,
|
|
1923
|
+
rejectWalletRequest: walletHandler.rejectRequest,
|
|
2368
1924
|
// Event API
|
|
2369
1925
|
subscribe: eventContext.subscribe,
|
|
2370
1926
|
sendSystemCommand: eventContext.sendOutboundSystem,
|
|
@@ -2386,6 +1942,7 @@ function AomiRuntimeCore({
|
|
|
2386
1942
|
sendMessage,
|
|
2387
1943
|
cancelGeneration,
|
|
2388
1944
|
notificationContext,
|
|
1945
|
+
walletHandler,
|
|
2389
1946
|
eventContext
|
|
2390
1947
|
]
|
|
2391
1948
|
);
|
|
@@ -2398,12 +1955,12 @@ function AomiRuntimeProvider({
|
|
|
2398
1955
|
children,
|
|
2399
1956
|
backendUrl = "http://localhost:8080"
|
|
2400
1957
|
}) {
|
|
2401
|
-
const
|
|
2402
|
-
return /* @__PURE__ */ jsx7(ThreadContextProvider, { children: /* @__PURE__ */ jsx7(NotificationContextProvider, { children: /* @__PURE__ */ jsx7(UserContextProvider, { children: /* @__PURE__ */ jsx7(AomiRuntimeInner, {
|
|
1958
|
+
const aomiClient = useMemo3(() => new AomiClient({ baseUrl: backendUrl }), [backendUrl]);
|
|
1959
|
+
return /* @__PURE__ */ jsx7(ThreadContextProvider, { children: /* @__PURE__ */ jsx7(NotificationContextProvider, { children: /* @__PURE__ */ jsx7(UserContextProvider, { children: /* @__PURE__ */ jsx7(AomiRuntimeInner, { aomiClient, children }) }) }) });
|
|
2403
1960
|
}
|
|
2404
1961
|
function AomiRuntimeInner({
|
|
2405
1962
|
children,
|
|
2406
|
-
|
|
1963
|
+
aomiClient
|
|
2407
1964
|
}) {
|
|
2408
1965
|
var _a;
|
|
2409
1966
|
const threadContext = useThreadContext();
|
|
@@ -2411,7 +1968,7 @@ function AomiRuntimeInner({
|
|
|
2411
1968
|
return /* @__PURE__ */ jsx7(
|
|
2412
1969
|
ControlContextProvider,
|
|
2413
1970
|
{
|
|
2414
|
-
|
|
1971
|
+
aomiClient,
|
|
2415
1972
|
sessionId: threadContext.currentThreadId,
|
|
2416
1973
|
publicKey: (_a = user.address) != null ? _a : void 0,
|
|
2417
1974
|
getThreadMetadata: threadContext.getThreadMetadata,
|
|
@@ -2419,94 +1976,15 @@ function AomiRuntimeInner({
|
|
|
2419
1976
|
children: /* @__PURE__ */ jsx7(
|
|
2420
1977
|
EventContextProvider,
|
|
2421
1978
|
{
|
|
2422
|
-
|
|
1979
|
+
aomiClient,
|
|
2423
1980
|
sessionId: threadContext.currentThreadId,
|
|
2424
|
-
children: /* @__PURE__ */ jsx7(AomiRuntimeCore, {
|
|
1981
|
+
children: /* @__PURE__ */ jsx7(AomiRuntimeCore, { aomiClient, children })
|
|
2425
1982
|
}
|
|
2426
1983
|
)
|
|
2427
1984
|
}
|
|
2428
1985
|
);
|
|
2429
1986
|
}
|
|
2430
1987
|
|
|
2431
|
-
// packages/react/src/handlers/wallet-handler.ts
|
|
2432
|
-
import { useCallback as useCallback7, useEffect as useEffect4, useState as useState6 } from "react";
|
|
2433
|
-
function useWalletHandler({
|
|
2434
|
-
sessionId,
|
|
2435
|
-
onTxRequest
|
|
2436
|
-
}) {
|
|
2437
|
-
const { subscribe: subscribe2, sendOutboundSystem: sendOutbound } = useEventContext();
|
|
2438
|
-
const { setUser, getUserState } = useUser();
|
|
2439
|
-
const [pendingTxRequests, setPendingTxRequests] = useState6(
|
|
2440
|
-
[]
|
|
2441
|
-
);
|
|
2442
|
-
useEffect4(() => {
|
|
2443
|
-
const unsubscribe = subscribe2(
|
|
2444
|
-
"wallet_tx_request",
|
|
2445
|
-
(event) => {
|
|
2446
|
-
const request = event.payload;
|
|
2447
|
-
setPendingTxRequests((prev) => [...prev, request]);
|
|
2448
|
-
onTxRequest == null ? void 0 : onTxRequest(request);
|
|
2449
|
-
}
|
|
2450
|
-
);
|
|
2451
|
-
return unsubscribe;
|
|
2452
|
-
}, [subscribe2, onTxRequest]);
|
|
2453
|
-
useEffect4(() => {
|
|
2454
|
-
const unsubscribe = subscribe2(
|
|
2455
|
-
"user_state_request",
|
|
2456
|
-
(event) => {
|
|
2457
|
-
sendOutbound({
|
|
2458
|
-
type: "user_state_response",
|
|
2459
|
-
sessionId,
|
|
2460
|
-
payload: getUserState()
|
|
2461
|
-
});
|
|
2462
|
-
}
|
|
2463
|
-
);
|
|
2464
|
-
return unsubscribe;
|
|
2465
|
-
}, [subscribe2, onTxRequest]);
|
|
2466
|
-
const sendTxComplete = useCallback7(
|
|
2467
|
-
(tx) => {
|
|
2468
|
-
sendOutbound({
|
|
2469
|
-
type: "wallet:tx_complete",
|
|
2470
|
-
sessionId,
|
|
2471
|
-
payload: tx
|
|
2472
|
-
});
|
|
2473
|
-
},
|
|
2474
|
-
[sendOutbound, sessionId]
|
|
2475
|
-
);
|
|
2476
|
-
const sendConnectionChange = useCallback7(
|
|
2477
|
-
(status, address, chainId) => {
|
|
2478
|
-
if (status === "connected") {
|
|
2479
|
-
setUser({
|
|
2480
|
-
isConnected: true,
|
|
2481
|
-
address,
|
|
2482
|
-
chainId
|
|
2483
|
-
});
|
|
2484
|
-
} else {
|
|
2485
|
-
setUser({
|
|
2486
|
-
isConnected: false,
|
|
2487
|
-
address: void 0,
|
|
2488
|
-
chainId: void 0
|
|
2489
|
-
});
|
|
2490
|
-
}
|
|
2491
|
-
sendOutbound({
|
|
2492
|
-
type: status === "connected" ? "wallet:connected" : "wallet:disconnected",
|
|
2493
|
-
sessionId,
|
|
2494
|
-
payload: { status, address }
|
|
2495
|
-
});
|
|
2496
|
-
},
|
|
2497
|
-
[setUser, sendOutbound, sessionId]
|
|
2498
|
-
);
|
|
2499
|
-
const clearTxRequest = useCallback7((index) => {
|
|
2500
|
-
setPendingTxRequests((prev) => prev.filter((_, i) => i !== index));
|
|
2501
|
-
}, []);
|
|
2502
|
-
return {
|
|
2503
|
-
sendTxComplete,
|
|
2504
|
-
sendConnectionChange,
|
|
2505
|
-
pendingTxRequests,
|
|
2506
|
-
clearTxRequest
|
|
2507
|
-
};
|
|
2508
|
-
}
|
|
2509
|
-
|
|
2510
1988
|
// packages/react/src/handlers/notification-handler.ts
|
|
2511
1989
|
import { useCallback as useCallback8, useEffect as useEffect5, useState as useState7 } from "react";
|
|
2512
1990
|
var notificationIdCounter2 = 0;
|
|
@@ -2549,8 +2027,8 @@ function useNotificationHandler({
|
|
|
2549
2027
|
};
|
|
2550
2028
|
}
|
|
2551
2029
|
export {
|
|
2030
|
+
AomiClient2 as AomiClient,
|
|
2552
2031
|
AomiRuntimeProvider,
|
|
2553
|
-
BackendApi,
|
|
2554
2032
|
ControlContextProvider,
|
|
2555
2033
|
EventContextProvider,
|
|
2556
2034
|
NotificationContextProvider,
|