@aomi-labs/react 0.3.0 → 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 +199 -607
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -151
- package/dist/index.d.ts +26 -151
- package/dist/index.js +200 -601
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.cjs
CHANGED
|
@@ -37,8 +37,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
37
37
|
// packages/react/src/index.ts
|
|
38
38
|
var index_exports = {};
|
|
39
39
|
__export(index_exports, {
|
|
40
|
+
AomiClient: () => import_client3.AomiClient,
|
|
40
41
|
AomiRuntimeProvider: () => AomiRuntimeProvider,
|
|
41
|
-
BackendApi: () => BackendApi,
|
|
42
42
|
ControlContextProvider: () => ControlContextProvider,
|
|
43
43
|
EventContextProvider: () => EventContextProvider,
|
|
44
44
|
NotificationContextProvider: () => NotificationContextProvider,
|
|
@@ -62,439 +62,11 @@ __export(index_exports, {
|
|
|
62
62
|
useWalletHandler: () => useWalletHandler
|
|
63
63
|
});
|
|
64
64
|
module.exports = __toCommonJS(index_exports);
|
|
65
|
-
|
|
66
|
-
// packages/react/src/backend/sse.ts
|
|
67
|
-
function extractSseData(rawEvent) {
|
|
68
|
-
const dataLines = rawEvent.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart());
|
|
69
|
-
if (!dataLines.length) return null;
|
|
70
|
-
return dataLines.join("\n");
|
|
71
|
-
}
|
|
72
|
-
async function readSseStream(stream, signal, onMessage) {
|
|
73
|
-
const reader = stream.getReader();
|
|
74
|
-
const decoder = new TextDecoder();
|
|
75
|
-
let buffer = "";
|
|
76
|
-
try {
|
|
77
|
-
while (!signal.aborted) {
|
|
78
|
-
const { value, done } = await reader.read();
|
|
79
|
-
if (done) break;
|
|
80
|
-
buffer += decoder.decode(value, { stream: true });
|
|
81
|
-
buffer = buffer.replace(/\r/g, "");
|
|
82
|
-
let separatorIndex = buffer.indexOf("\n\n");
|
|
83
|
-
while (separatorIndex >= 0) {
|
|
84
|
-
const rawEvent = buffer.slice(0, separatorIndex);
|
|
85
|
-
buffer = buffer.slice(separatorIndex + 2);
|
|
86
|
-
const data = extractSseData(rawEvent);
|
|
87
|
-
if (data) {
|
|
88
|
-
onMessage(data);
|
|
89
|
-
}
|
|
90
|
-
separatorIndex = buffer.indexOf("\n\n");
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
} finally {
|
|
94
|
-
reader.releaseLock();
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
function createSseSubscriber({
|
|
98
|
-
backendUrl,
|
|
99
|
-
getHeaders,
|
|
100
|
-
shouldLog = process.env.NODE_ENV !== "production"
|
|
101
|
-
}) {
|
|
102
|
-
const subscriptions = /* @__PURE__ */ new Map();
|
|
103
|
-
const subscribe2 = (sessionId, onUpdate, onError) => {
|
|
104
|
-
const existing = subscriptions.get(sessionId);
|
|
105
|
-
const listener = { onUpdate, onError };
|
|
106
|
-
if (existing) {
|
|
107
|
-
existing.listeners.add(listener);
|
|
108
|
-
if (shouldLog) {
|
|
109
|
-
console.debug("[aomi][sse] listener added", {
|
|
110
|
-
sessionId,
|
|
111
|
-
listeners: existing.listeners.size
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
return () => {
|
|
115
|
-
existing.listeners.delete(listener);
|
|
116
|
-
if (shouldLog) {
|
|
117
|
-
console.debug("[aomi][sse] listener removed", {
|
|
118
|
-
sessionId,
|
|
119
|
-
listeners: existing.listeners.size
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
if (existing.listeners.size === 0) {
|
|
123
|
-
existing.stop("unsubscribe");
|
|
124
|
-
if (subscriptions.get(sessionId) === existing) {
|
|
125
|
-
subscriptions.delete(sessionId);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
const subscription = {
|
|
131
|
-
abortController: null,
|
|
132
|
-
retries: 0,
|
|
133
|
-
retryTimer: null,
|
|
134
|
-
stopped: false,
|
|
135
|
-
listeners: /* @__PURE__ */ new Set([listener]),
|
|
136
|
-
stop: (reason) => {
|
|
137
|
-
var _a;
|
|
138
|
-
subscription.stopped = true;
|
|
139
|
-
if (subscription.retryTimer) {
|
|
140
|
-
clearTimeout(subscription.retryTimer);
|
|
141
|
-
subscription.retryTimer = null;
|
|
142
|
-
}
|
|
143
|
-
(_a = subscription.abortController) == null ? void 0 : _a.abort();
|
|
144
|
-
subscription.abortController = null;
|
|
145
|
-
if (shouldLog) {
|
|
146
|
-
console.debug("[aomi][sse] stop", {
|
|
147
|
-
sessionId,
|
|
148
|
-
reason,
|
|
149
|
-
retries: subscription.retries
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
const scheduleRetry = () => {
|
|
155
|
-
if (subscription.stopped) return;
|
|
156
|
-
subscription.retries += 1;
|
|
157
|
-
const delayMs = Math.min(500 * 2 ** (subscription.retries - 1), 1e4);
|
|
158
|
-
if (shouldLog) {
|
|
159
|
-
console.debug("[aomi][sse] retry scheduled", {
|
|
160
|
-
sessionId,
|
|
161
|
-
delayMs,
|
|
162
|
-
retries: subscription.retries
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
subscription.retryTimer = setTimeout(() => {
|
|
166
|
-
void open();
|
|
167
|
-
}, delayMs);
|
|
168
|
-
};
|
|
169
|
-
const open = async () => {
|
|
170
|
-
var _a;
|
|
171
|
-
if (subscription.stopped) return;
|
|
172
|
-
if (subscription.retryTimer) {
|
|
173
|
-
clearTimeout(subscription.retryTimer);
|
|
174
|
-
subscription.retryTimer = null;
|
|
175
|
-
}
|
|
176
|
-
const controller = new AbortController();
|
|
177
|
-
subscription.abortController = controller;
|
|
178
|
-
const openedAt = Date.now();
|
|
179
|
-
try {
|
|
180
|
-
const response = await fetch(`${backendUrl}/api/updates`, {
|
|
181
|
-
headers: getHeaders(sessionId),
|
|
182
|
-
signal: controller.signal
|
|
183
|
-
});
|
|
184
|
-
if (!response.ok) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
`SSE HTTP ${response.status}: ${response.statusText}`
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
if (!response.body) {
|
|
190
|
-
throw new Error("SSE response missing body");
|
|
191
|
-
}
|
|
192
|
-
subscription.retries = 0;
|
|
193
|
-
await readSseStream(response.body, controller.signal, (data) => {
|
|
194
|
-
var _a2, _b;
|
|
195
|
-
let parsed;
|
|
196
|
-
try {
|
|
197
|
-
parsed = JSON.parse(data);
|
|
198
|
-
} catch (error) {
|
|
199
|
-
for (const item of subscription.listeners) {
|
|
200
|
-
(_a2 = item.onError) == null ? void 0 : _a2.call(item, error);
|
|
201
|
-
}
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
for (const item of subscription.listeners) {
|
|
205
|
-
try {
|
|
206
|
-
item.onUpdate(parsed);
|
|
207
|
-
} catch (error) {
|
|
208
|
-
(_b = item.onError) == null ? void 0 : _b.call(item, error);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
if (shouldLog) {
|
|
213
|
-
console.debug("[aomi][sse] stream ended", {
|
|
214
|
-
sessionId,
|
|
215
|
-
aborted: controller.signal.aborted,
|
|
216
|
-
stopped: subscription.stopped,
|
|
217
|
-
durationMs: Date.now() - openedAt
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
} catch (error) {
|
|
221
|
-
if (!controller.signal.aborted && !subscription.stopped) {
|
|
222
|
-
for (const item of subscription.listeners) {
|
|
223
|
-
(_a = item.onError) == null ? void 0 : _a.call(item, error);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (!subscription.stopped) {
|
|
228
|
-
scheduleRetry();
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
subscriptions.set(sessionId, subscription);
|
|
232
|
-
void open();
|
|
233
|
-
return () => {
|
|
234
|
-
subscription.listeners.delete(listener);
|
|
235
|
-
if (shouldLog) {
|
|
236
|
-
console.debug("[aomi][sse] listener removed", {
|
|
237
|
-
sessionId,
|
|
238
|
-
listeners: subscription.listeners.size
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
if (subscription.listeners.size === 0) {
|
|
242
|
-
subscription.stop("unsubscribe");
|
|
243
|
-
if (subscriptions.get(sessionId) === subscription) {
|
|
244
|
-
subscriptions.delete(sessionId);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
};
|
|
249
|
-
return { subscribe: subscribe2 };
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// packages/react/src/backend/client.ts
|
|
253
|
-
var SESSION_ID_HEADER = "X-Session-Id";
|
|
254
|
-
var API_KEY_HEADER = "X-API-Key";
|
|
255
|
-
function toQueryString(payload) {
|
|
256
|
-
const params = new URLSearchParams();
|
|
257
|
-
for (const [key, value] of Object.entries(payload)) {
|
|
258
|
-
if (value === void 0 || value === null) continue;
|
|
259
|
-
params.set(key, String(value));
|
|
260
|
-
}
|
|
261
|
-
const qs = params.toString();
|
|
262
|
-
return qs ? `?${qs}` : "";
|
|
263
|
-
}
|
|
264
|
-
function withSessionHeader(sessionId, init) {
|
|
265
|
-
const headers = new Headers(init);
|
|
266
|
-
headers.set(SESSION_ID_HEADER, sessionId);
|
|
267
|
-
return headers;
|
|
268
|
-
}
|
|
269
|
-
async function postState(backendUrl, path, payload, sessionId, apiKey) {
|
|
270
|
-
const query = toQueryString(payload);
|
|
271
|
-
const url = `${backendUrl}${path}${query}`;
|
|
272
|
-
const headers = new Headers(withSessionHeader(sessionId));
|
|
273
|
-
if (apiKey) {
|
|
274
|
-
headers.set(API_KEY_HEADER, apiKey);
|
|
275
|
-
}
|
|
276
|
-
const response = await fetch(url, {
|
|
277
|
-
method: "POST",
|
|
278
|
-
headers
|
|
279
|
-
});
|
|
280
|
-
if (!response.ok) {
|
|
281
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
282
|
-
}
|
|
283
|
-
return await response.json();
|
|
284
|
-
}
|
|
285
|
-
var BackendApi = class {
|
|
286
|
-
constructor(backendUrl) {
|
|
287
|
-
this.backendUrl = backendUrl;
|
|
288
|
-
this.sseSubscriber = createSseSubscriber({
|
|
289
|
-
backendUrl,
|
|
290
|
-
getHeaders: (sessionId) => withSessionHeader(sessionId, { Accept: "text/event-stream" })
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
async fetchState(sessionId, userState) {
|
|
294
|
-
const url = new URL("/api/state", this.backendUrl);
|
|
295
|
-
if (userState) {
|
|
296
|
-
url.searchParams.set("user_state", JSON.stringify(userState));
|
|
297
|
-
}
|
|
298
|
-
const response = await fetch(url.toString(), {
|
|
299
|
-
headers: withSessionHeader(sessionId)
|
|
300
|
-
});
|
|
301
|
-
if (!response.ok) {
|
|
302
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
303
|
-
}
|
|
304
|
-
return await response.json();
|
|
305
|
-
}
|
|
306
|
-
async postChatMessage(sessionId, message, namespace, publicKey, apiKey, userState) {
|
|
307
|
-
const payload = { message, namespace };
|
|
308
|
-
if (publicKey) {
|
|
309
|
-
payload.public_key = publicKey;
|
|
310
|
-
}
|
|
311
|
-
if (userState) {
|
|
312
|
-
payload.user_state = JSON.stringify(userState);
|
|
313
|
-
}
|
|
314
|
-
return postState(
|
|
315
|
-
this.backendUrl,
|
|
316
|
-
"/api/chat",
|
|
317
|
-
payload,
|
|
318
|
-
sessionId,
|
|
319
|
-
apiKey
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
async postSystemMessage(sessionId, message) {
|
|
323
|
-
return postState(
|
|
324
|
-
this.backendUrl,
|
|
325
|
-
"/api/system",
|
|
326
|
-
{
|
|
327
|
-
message
|
|
328
|
-
},
|
|
329
|
-
sessionId
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
async postInterrupt(sessionId) {
|
|
333
|
-
return postState(
|
|
334
|
-
this.backendUrl,
|
|
335
|
-
"/api/interrupt",
|
|
336
|
-
{},
|
|
337
|
-
sessionId
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
/**
|
|
341
|
-
* Subscribe to SSE updates for a session.
|
|
342
|
-
* Uses fetch streaming and reconnects on disconnects.
|
|
343
|
-
* Returns an unsubscribe function.
|
|
344
|
-
*/
|
|
345
|
-
subscribeSSE(sessionId, onUpdate, onError) {
|
|
346
|
-
return this.sseSubscriber.subscribe(sessionId, onUpdate, onError);
|
|
347
|
-
}
|
|
348
|
-
async fetchThreads(publicKey) {
|
|
349
|
-
const url = `${this.backendUrl}/api/sessions?public_key=${encodeURIComponent(publicKey)}`;
|
|
350
|
-
const response = await fetch(url);
|
|
351
|
-
if (!response.ok) {
|
|
352
|
-
throw new Error(`Failed to fetch threads: HTTP ${response.status}`);
|
|
353
|
-
}
|
|
354
|
-
return await response.json();
|
|
355
|
-
}
|
|
356
|
-
async fetchThread(sessionId) {
|
|
357
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
|
|
358
|
-
const response = await fetch(url, {
|
|
359
|
-
headers: withSessionHeader(sessionId)
|
|
360
|
-
});
|
|
361
|
-
if (!response.ok) {
|
|
362
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
363
|
-
}
|
|
364
|
-
return await response.json();
|
|
365
|
-
}
|
|
366
|
-
async createThread(threadId, publicKey) {
|
|
367
|
-
const body = {};
|
|
368
|
-
if (publicKey) body.public_key = publicKey;
|
|
369
|
-
const url = `${this.backendUrl}/api/sessions`;
|
|
370
|
-
const response = await fetch(url, {
|
|
371
|
-
method: "POST",
|
|
372
|
-
headers: withSessionHeader(threadId, {
|
|
373
|
-
"Content-Type": "application/json"
|
|
374
|
-
}),
|
|
375
|
-
body: JSON.stringify(body)
|
|
376
|
-
});
|
|
377
|
-
if (!response.ok) {
|
|
378
|
-
throw new Error(`Failed to create thread: HTTP ${response.status}`);
|
|
379
|
-
}
|
|
380
|
-
return await response.json();
|
|
381
|
-
}
|
|
382
|
-
async archiveThread(sessionId) {
|
|
383
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}/archive`;
|
|
384
|
-
const response = await fetch(url, {
|
|
385
|
-
method: "POST",
|
|
386
|
-
headers: withSessionHeader(sessionId)
|
|
387
|
-
});
|
|
388
|
-
if (!response.ok) {
|
|
389
|
-
throw new Error(`Failed to archive thread: HTTP ${response.status}`);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
async unarchiveThread(sessionId) {
|
|
393
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}/unarchive`;
|
|
394
|
-
const response = await fetch(url, {
|
|
395
|
-
method: "POST",
|
|
396
|
-
headers: withSessionHeader(sessionId)
|
|
397
|
-
});
|
|
398
|
-
if (!response.ok) {
|
|
399
|
-
throw new Error(`Failed to unarchive thread: HTTP ${response.status}`);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
async deleteThread(sessionId) {
|
|
403
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
|
|
404
|
-
const response = await fetch(url, {
|
|
405
|
-
method: "DELETE",
|
|
406
|
-
headers: withSessionHeader(sessionId)
|
|
407
|
-
});
|
|
408
|
-
if (!response.ok) {
|
|
409
|
-
throw new Error(`Failed to delete thread: HTTP ${response.status}`);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
async renameThread(sessionId, newTitle) {
|
|
413
|
-
const url = `${this.backendUrl}/api/sessions/${encodeURIComponent(sessionId)}`;
|
|
414
|
-
const response = await fetch(url, {
|
|
415
|
-
method: "PATCH",
|
|
416
|
-
headers: withSessionHeader(sessionId, {
|
|
417
|
-
"Content-Type": "application/json"
|
|
418
|
-
}),
|
|
419
|
-
body: JSON.stringify({ title: newTitle })
|
|
420
|
-
});
|
|
421
|
-
if (!response.ok) {
|
|
422
|
-
throw new Error(`Failed to rename thread: HTTP ${response.status}`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
async getSystemEvents(sessionId, count) {
|
|
426
|
-
const url = new URL("/api/events", this.backendUrl);
|
|
427
|
-
if (count !== void 0) {
|
|
428
|
-
url.searchParams.set("count", String(count));
|
|
429
|
-
}
|
|
430
|
-
const response = await fetch(url.toString(), {
|
|
431
|
-
headers: withSessionHeader(sessionId)
|
|
432
|
-
});
|
|
433
|
-
if (!response.ok) {
|
|
434
|
-
if (response.status === 404) return [];
|
|
435
|
-
throw new Error(`Failed to get system events: HTTP ${response.status}`);
|
|
436
|
-
}
|
|
437
|
-
return await response.json();
|
|
438
|
-
}
|
|
439
|
-
// ===========================================================================
|
|
440
|
-
// Control API
|
|
441
|
-
// ===========================================================================
|
|
442
|
-
/**
|
|
443
|
-
* Get allowed namespaces for the current request context.
|
|
444
|
-
*/
|
|
445
|
-
async getNamespaces(sessionId, publicKey, apiKey) {
|
|
446
|
-
const url = new URL("/api/control/namespaces", this.backendUrl);
|
|
447
|
-
if (publicKey) {
|
|
448
|
-
url.searchParams.set("public_key", publicKey);
|
|
449
|
-
}
|
|
450
|
-
console.log("[BackendApi.getNamespaces]", {
|
|
451
|
-
backendUrl: this.backendUrl,
|
|
452
|
-
fullUrl: url.toString(),
|
|
453
|
-
sessionId,
|
|
454
|
-
publicKey
|
|
455
|
-
});
|
|
456
|
-
const headers = new Headers(withSessionHeader(sessionId));
|
|
457
|
-
if (apiKey) {
|
|
458
|
-
headers.set(API_KEY_HEADER, apiKey);
|
|
459
|
-
}
|
|
460
|
-
const response = await fetch(url.toString(), { headers });
|
|
461
|
-
if (!response.ok) {
|
|
462
|
-
throw new Error(`Failed to get namespaces: HTTP ${response.status}`);
|
|
463
|
-
}
|
|
464
|
-
return await response.json();
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Get available models.
|
|
468
|
-
*/
|
|
469
|
-
async getModels(sessionId) {
|
|
470
|
-
const url = new URL("/api/control/models", this.backendUrl);
|
|
471
|
-
console.log("[BackendApi.getModels]", {
|
|
472
|
-
backendUrl: this.backendUrl,
|
|
473
|
-
fullUrl: url.toString(),
|
|
474
|
-
sessionId
|
|
475
|
-
});
|
|
476
|
-
const response = await fetch(url.toString(), {
|
|
477
|
-
headers: withSessionHeader(sessionId)
|
|
478
|
-
});
|
|
479
|
-
if (!response.ok) {
|
|
480
|
-
throw new Error(`Failed to get models: HTTP ${response.status}`);
|
|
481
|
-
}
|
|
482
|
-
return await response.json();
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Set the model selection for a session.
|
|
486
|
-
*/
|
|
487
|
-
async setModel(sessionId, rig, namespace, apiKey) {
|
|
488
|
-
const payload = { rig };
|
|
489
|
-
if (namespace) {
|
|
490
|
-
payload.namespace = namespace;
|
|
491
|
-
}
|
|
492
|
-
return postState(this.backendUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
493
|
-
}
|
|
494
|
-
};
|
|
65
|
+
var import_client3 = require("@aomi-labs/client");
|
|
495
66
|
|
|
496
67
|
// packages/react/src/runtime/aomi-runtime.tsx
|
|
497
68
|
var import_react11 = require("react");
|
|
69
|
+
var import_client2 = require("@aomi-labs/client");
|
|
498
70
|
|
|
499
71
|
// packages/react/src/contexts/control-context.tsx
|
|
500
72
|
var import_react = require("react");
|
|
@@ -527,7 +99,7 @@ var logThreadMetadataChange = (source, threadId, prev, next) => {
|
|
|
527
99
|
function initThreadControl() {
|
|
528
100
|
return {
|
|
529
101
|
model: null,
|
|
530
|
-
|
|
102
|
+
app: null,
|
|
531
103
|
controlDirty: false,
|
|
532
104
|
isProcessing: false
|
|
533
105
|
};
|
|
@@ -683,7 +255,7 @@ function useControl() {
|
|
|
683
255
|
}
|
|
684
256
|
function ControlContextProvider({
|
|
685
257
|
children,
|
|
686
|
-
|
|
258
|
+
aomiClient,
|
|
687
259
|
sessionId,
|
|
688
260
|
publicKey,
|
|
689
261
|
getThreadMetadata,
|
|
@@ -693,14 +265,14 @@ function ControlContextProvider({
|
|
|
693
265
|
const [state, setStateInternal] = (0, import_react.useState)(() => ({
|
|
694
266
|
apiKey: null,
|
|
695
267
|
availableModels: [],
|
|
696
|
-
|
|
268
|
+
authorizedApps: [],
|
|
697
269
|
defaultModel: null,
|
|
698
|
-
|
|
270
|
+
defaultApp: null
|
|
699
271
|
}));
|
|
700
272
|
const stateRef = (0, import_react.useRef)(state);
|
|
701
273
|
stateRef.current = state;
|
|
702
|
-
const
|
|
703
|
-
|
|
274
|
+
const aomiClientRef = (0, import_react.useRef)(aomiClient);
|
|
275
|
+
aomiClientRef.current = aomiClient;
|
|
704
276
|
const sessionIdRef = (0, import_react.useRef)(sessionId);
|
|
705
277
|
sessionIdRef.current = sessionId;
|
|
706
278
|
const publicKeyRef = (0, import_react.useRef)(publicKey);
|
|
@@ -734,33 +306,32 @@ function ControlContextProvider({
|
|
|
734
306
|
}
|
|
735
307
|
}, [state.apiKey]);
|
|
736
308
|
(0, import_react.useEffect)(() => {
|
|
737
|
-
const
|
|
309
|
+
const fetchApps = async () => {
|
|
738
310
|
var _a2, _b2;
|
|
739
311
|
try {
|
|
740
|
-
const
|
|
312
|
+
const apps = await aomiClientRef.current.getApps(
|
|
741
313
|
sessionIdRef.current,
|
|
742
|
-
publicKeyRef.current,
|
|
743
|
-
(_a2 = stateRef.current.apiKey) != null ? _a2 : void 0
|
|
314
|
+
{ publicKey: publicKeyRef.current, apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0 }
|
|
744
315
|
);
|
|
745
|
-
const
|
|
316
|
+
const defaultApp = apps.includes("default") ? "default" : (_b2 = apps[0]) != null ? _b2 : null;
|
|
746
317
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
747
|
-
|
|
748
|
-
|
|
318
|
+
authorizedApps: apps,
|
|
319
|
+
defaultApp
|
|
749
320
|
}));
|
|
750
321
|
} catch (error) {
|
|
751
|
-
console.error("Failed to fetch
|
|
322
|
+
console.error("Failed to fetch apps:", error);
|
|
752
323
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
753
|
-
|
|
754
|
-
|
|
324
|
+
authorizedApps: ["default"],
|
|
325
|
+
defaultApp: "default"
|
|
755
326
|
}));
|
|
756
327
|
}
|
|
757
328
|
};
|
|
758
|
-
void
|
|
329
|
+
void fetchApps();
|
|
759
330
|
}, [state.apiKey]);
|
|
760
331
|
(0, import_react.useEffect)(() => {
|
|
761
332
|
const fetchModels = async () => {
|
|
762
333
|
try {
|
|
763
|
-
const models = await
|
|
334
|
+
const models = await aomiClientRef.current.getModels(
|
|
764
335
|
sessionIdRef.current
|
|
765
336
|
);
|
|
766
337
|
setStateInternal((prev) => {
|
|
@@ -785,7 +356,7 @@ function ControlContextProvider({
|
|
|
785
356
|
}, []);
|
|
786
357
|
const getAvailableModels = (0, import_react.useCallback)(async () => {
|
|
787
358
|
try {
|
|
788
|
-
const models = await
|
|
359
|
+
const models = await aomiClientRef.current.getModels(
|
|
789
360
|
sessionIdRef.current
|
|
790
361
|
);
|
|
791
362
|
setStateInternal((prev) => {
|
|
@@ -801,25 +372,24 @@ function ControlContextProvider({
|
|
|
801
372
|
return [];
|
|
802
373
|
}
|
|
803
374
|
}, []);
|
|
804
|
-
const
|
|
375
|
+
const getAuthorizedApps = (0, import_react.useCallback)(async () => {
|
|
805
376
|
var _a2, _b2;
|
|
806
377
|
try {
|
|
807
|
-
const
|
|
378
|
+
const apps = await aomiClientRef.current.getApps(
|
|
808
379
|
sessionIdRef.current,
|
|
809
|
-
publicKeyRef.current,
|
|
810
|
-
(_a2 = stateRef.current.apiKey) != null ? _a2 : void 0
|
|
380
|
+
{ publicKey: publicKeyRef.current, apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0 }
|
|
811
381
|
);
|
|
812
|
-
const
|
|
382
|
+
const defaultApp = apps.includes("default") ? "default" : (_b2 = apps[0]) != null ? _b2 : null;
|
|
813
383
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
814
|
-
|
|
815
|
-
|
|
384
|
+
authorizedApps: apps,
|
|
385
|
+
defaultApp
|
|
816
386
|
}));
|
|
817
|
-
return
|
|
387
|
+
return apps;
|
|
818
388
|
} catch (error) {
|
|
819
|
-
console.error("Failed to fetch
|
|
389
|
+
console.error("Failed to fetch apps:", error);
|
|
820
390
|
setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
821
|
-
|
|
822
|
-
|
|
391
|
+
authorizedApps: ["default"],
|
|
392
|
+
defaultApp: "default"
|
|
823
393
|
}));
|
|
824
394
|
return ["default"];
|
|
825
395
|
}
|
|
@@ -843,32 +413,31 @@ function ControlContextProvider({
|
|
|
843
413
|
console.warn("[control-context] Cannot switch model while processing");
|
|
844
414
|
return;
|
|
845
415
|
}
|
|
846
|
-
const
|
|
416
|
+
const app = (_d = (_c = currentControl.app) != null ? _c : stateRef.current.defaultApp) != null ? _d : "default";
|
|
847
417
|
console.log("[control-context] onModelSelect updating metadata", {
|
|
848
418
|
threadId,
|
|
849
419
|
model,
|
|
850
|
-
|
|
420
|
+
app,
|
|
851
421
|
currentControl
|
|
852
422
|
});
|
|
853
423
|
updateThreadMetadataRef.current(threadId, {
|
|
854
424
|
control: __spreadProps(__spreadValues({}, currentControl), {
|
|
855
425
|
model,
|
|
856
|
-
|
|
426
|
+
app,
|
|
857
427
|
controlDirty: true
|
|
858
428
|
})
|
|
859
429
|
});
|
|
860
430
|
console.log("[control-context] onModelSelect calling backend setModel", {
|
|
861
431
|
threadId,
|
|
862
432
|
model,
|
|
863
|
-
|
|
864
|
-
backendUrl:
|
|
433
|
+
app,
|
|
434
|
+
backendUrl: aomiClientRef.current
|
|
865
435
|
});
|
|
866
436
|
try {
|
|
867
|
-
const result = await
|
|
437
|
+
const result = await aomiClientRef.current.setModel(
|
|
868
438
|
threadId,
|
|
869
439
|
model,
|
|
870
|
-
|
|
871
|
-
(_e = stateRef.current.apiKey) != null ? _e : void 0
|
|
440
|
+
{ app, apiKey: (_e = stateRef.current.apiKey) != null ? _e : void 0 }
|
|
872
441
|
);
|
|
873
442
|
console.log("[control-context] onModelSelect backend result", result);
|
|
874
443
|
} catch (err) {
|
|
@@ -876,34 +445,34 @@ function ControlContextProvider({
|
|
|
876
445
|
throw err;
|
|
877
446
|
}
|
|
878
447
|
}, []);
|
|
879
|
-
const
|
|
448
|
+
const onAppSelect = (0, import_react.useCallback)((app) => {
|
|
880
449
|
var _a2, _b2;
|
|
881
450
|
const threadId = sessionIdRef.current;
|
|
882
451
|
const currentControl = (_b2 = (_a2 = getThreadMetadataRef.current(threadId)) == null ? void 0 : _a2.control) != null ? _b2 : initThreadControl();
|
|
883
452
|
const isProcessing2 = currentControl.isProcessing;
|
|
884
|
-
console.log("[control-context]
|
|
885
|
-
|
|
453
|
+
console.log("[control-context] onAppSelect called", {
|
|
454
|
+
app,
|
|
886
455
|
isProcessing: isProcessing2,
|
|
887
456
|
threadId
|
|
888
457
|
});
|
|
889
458
|
if (isProcessing2) {
|
|
890
459
|
console.warn(
|
|
891
|
-
"[control-context] Cannot switch
|
|
460
|
+
"[control-context] Cannot switch app while processing"
|
|
892
461
|
);
|
|
893
462
|
return;
|
|
894
463
|
}
|
|
895
|
-
console.log("[control-context]
|
|
464
|
+
console.log("[control-context] onAppSelect updating metadata", {
|
|
896
465
|
threadId,
|
|
897
|
-
|
|
466
|
+
app,
|
|
898
467
|
currentControl
|
|
899
468
|
});
|
|
900
469
|
updateThreadMetadataRef.current(threadId, {
|
|
901
470
|
control: __spreadProps(__spreadValues({}, currentControl), {
|
|
902
|
-
|
|
471
|
+
app,
|
|
903
472
|
controlDirty: true
|
|
904
473
|
})
|
|
905
474
|
});
|
|
906
|
-
console.log("[control-context]
|
|
475
|
+
console.log("[control-context] onAppSelect metadata updated");
|
|
907
476
|
}, []);
|
|
908
477
|
const markControlSynced = (0, import_react.useCallback)(() => {
|
|
909
478
|
var _a2, _b2;
|
|
@@ -933,11 +502,11 @@ function ControlContextProvider({
|
|
|
933
502
|
if ("apiKey" in updates) {
|
|
934
503
|
setApiKey((_a2 = updates.apiKey) != null ? _a2 : null);
|
|
935
504
|
}
|
|
936
|
-
if ("
|
|
937
|
-
|
|
505
|
+
if ("app" in updates && updates.app !== void 0 && updates.app !== null) {
|
|
506
|
+
onAppSelect(updates.app);
|
|
938
507
|
}
|
|
939
508
|
},
|
|
940
|
-
[setApiKey,
|
|
509
|
+
[setApiKey, onAppSelect]
|
|
941
510
|
);
|
|
942
511
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
943
512
|
ControlContext.Provider,
|
|
@@ -946,10 +515,10 @@ function ControlContextProvider({
|
|
|
946
515
|
state,
|
|
947
516
|
setApiKey,
|
|
948
517
|
getAvailableModels,
|
|
949
|
-
|
|
518
|
+
getAuthorizedApps,
|
|
950
519
|
getCurrentThreadControl,
|
|
951
520
|
onModelSelect,
|
|
952
|
-
|
|
521
|
+
onAppSelect,
|
|
953
522
|
isProcessing,
|
|
954
523
|
markControlSynced,
|
|
955
524
|
getControlState,
|
|
@@ -963,20 +532,7 @@ function ControlContextProvider({
|
|
|
963
532
|
|
|
964
533
|
// packages/react/src/contexts/event-context.tsx
|
|
965
534
|
var import_react2 = require("react");
|
|
966
|
-
|
|
967
|
-
// packages/react/src/backend/types.ts
|
|
968
|
-
function isInlineCall(event) {
|
|
969
|
-
return "InlineCall" in event;
|
|
970
|
-
}
|
|
971
|
-
function isSystemNotice(event) {
|
|
972
|
-
return "SystemNotice" in event;
|
|
973
|
-
}
|
|
974
|
-
function isSystemError(event) {
|
|
975
|
-
return "SystemError" in event;
|
|
976
|
-
}
|
|
977
|
-
function isAsyncCallback(event) {
|
|
978
|
-
return "AsyncCallback" in event;
|
|
979
|
-
}
|
|
535
|
+
var import_client = require("@aomi-labs/client");
|
|
980
536
|
|
|
981
537
|
// packages/react/src/state/event-buffer.ts
|
|
982
538
|
function createEventBuffer() {
|
|
@@ -1036,7 +592,7 @@ function useEventContext() {
|
|
|
1036
592
|
}
|
|
1037
593
|
function EventContextProvider({
|
|
1038
594
|
children,
|
|
1039
|
-
|
|
595
|
+
aomiClient,
|
|
1040
596
|
sessionId
|
|
1041
597
|
}) {
|
|
1042
598
|
const bufferRef = (0, import_react2.useRef)(null);
|
|
@@ -1048,7 +604,7 @@ function EventContextProvider({
|
|
|
1048
604
|
(0, import_react2.useEffect)(() => {
|
|
1049
605
|
setSSEStatus(buffer, "connecting");
|
|
1050
606
|
setSseStatus("connecting");
|
|
1051
|
-
const unsubscribe =
|
|
607
|
+
const unsubscribe = aomiClient.subscribeSSE(
|
|
1052
608
|
sessionId,
|
|
1053
609
|
(event) => {
|
|
1054
610
|
enqueueInbound(buffer, {
|
|
@@ -1078,7 +634,7 @@ function EventContextProvider({
|
|
|
1078
634
|
setSSEStatus(buffer, "disconnected");
|
|
1079
635
|
setSseStatus("disconnected");
|
|
1080
636
|
};
|
|
1081
|
-
}, [
|
|
637
|
+
}, [aomiClient, sessionId, buffer]);
|
|
1082
638
|
const subscribeCallback = (0, import_react2.useCallback)(
|
|
1083
639
|
(type, callback) => {
|
|
1084
640
|
return subscribe(buffer, type, callback);
|
|
@@ -1092,12 +648,12 @@ function EventContextProvider({
|
|
|
1092
648
|
type: event.type,
|
|
1093
649
|
payload: event.payload
|
|
1094
650
|
});
|
|
1095
|
-
await
|
|
651
|
+
await aomiClient.sendSystemMessage(event.sessionId, message);
|
|
1096
652
|
} catch (error) {
|
|
1097
653
|
console.error("Failed to send outbound event:", error);
|
|
1098
654
|
}
|
|
1099
655
|
},
|
|
1100
|
-
[
|
|
656
|
+
[aomiClient]
|
|
1101
657
|
);
|
|
1102
658
|
const dispatchSystemEvents = (0, import_react2.useCallback)(
|
|
1103
659
|
(sessionId2, events) => {
|
|
@@ -1105,16 +661,16 @@ function EventContextProvider({
|
|
|
1105
661
|
for (const event of events) {
|
|
1106
662
|
let eventType;
|
|
1107
663
|
let payload;
|
|
1108
|
-
if (isInlineCall(event)) {
|
|
664
|
+
if ((0, import_client.isInlineCall)(event)) {
|
|
1109
665
|
eventType = event.InlineCall.type;
|
|
1110
666
|
payload = (_a = event.InlineCall.payload) != null ? _a : event.InlineCall;
|
|
1111
|
-
} else if (isSystemNotice(event)) {
|
|
667
|
+
} else if ((0, import_client.isSystemNotice)(event)) {
|
|
1112
668
|
eventType = "system_notice";
|
|
1113
669
|
payload = { message: event.SystemNotice };
|
|
1114
|
-
} else if (isSystemError(event)) {
|
|
670
|
+
} else if ((0, import_client.isSystemError)(event)) {
|
|
1115
671
|
eventType = "system_error";
|
|
1116
672
|
payload = { message: event.SystemError };
|
|
1117
|
-
} else if (isAsyncCallback(event)) {
|
|
673
|
+
} else if ((0, import_client.isAsyncCallback)(event)) {
|
|
1118
674
|
eventType = "async_callback";
|
|
1119
675
|
payload = event.AsyncCallback;
|
|
1120
676
|
} else {
|
|
@@ -1463,19 +1019,16 @@ var MessageController = class {
|
|
|
1463
1019
|
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1464
1020
|
});
|
|
1465
1021
|
const backendThreadId = resolveThreadId(backendState, threadId);
|
|
1466
|
-
const
|
|
1022
|
+
const app = this.config.getApp();
|
|
1467
1023
|
const publicKey = (_b = (_a = this.config).getPublicKey) == null ? void 0 : _b.call(_a);
|
|
1468
1024
|
const apiKey = (_e = (_d = (_c = this.config).getApiKey) == null ? void 0 : _d.call(_c)) != null ? _e : void 0;
|
|
1469
1025
|
const userState = (_g = (_f = this.config).getUserState) == null ? void 0 : _g.call(_f);
|
|
1470
1026
|
try {
|
|
1471
1027
|
this.markRunning(threadId, true);
|
|
1472
|
-
const response = await this.config.
|
|
1028
|
+
const response = await this.config.aomiClientRef.current.sendMessage(
|
|
1473
1029
|
backendThreadId,
|
|
1474
1030
|
text,
|
|
1475
|
-
|
|
1476
|
-
publicKey,
|
|
1477
|
-
apiKey,
|
|
1478
|
-
userState
|
|
1031
|
+
{ app, publicKey, apiKey, userState }
|
|
1479
1032
|
);
|
|
1480
1033
|
if (response == null ? void 0 : response.messages) {
|
|
1481
1034
|
this.inbound(threadId, response.messages);
|
|
@@ -1499,7 +1052,7 @@ var MessageController = class {
|
|
|
1499
1052
|
const backendState = this.config.backendStateRef.current;
|
|
1500
1053
|
const backendThreadId = resolveThreadId(backendState, threadId);
|
|
1501
1054
|
try {
|
|
1502
|
-
const response = await this.config.
|
|
1055
|
+
const response = await this.config.aomiClientRef.current.interrupt(backendThreadId);
|
|
1503
1056
|
if (response == null ? void 0 : response.messages) {
|
|
1504
1057
|
this.inbound(threadId, response.messages);
|
|
1505
1058
|
}
|
|
@@ -1547,7 +1100,7 @@ var PollingController = class {
|
|
|
1547
1100
|
threadId
|
|
1548
1101
|
);
|
|
1549
1102
|
const userState = (_b2 = (_a2 = this.config).getUserState) == null ? void 0 : _b2.call(_a2);
|
|
1550
|
-
const state = await this.config.
|
|
1103
|
+
const state = await this.config.aomiClientRef.current.fetchState(
|
|
1551
1104
|
backendThreadId,
|
|
1552
1105
|
userState
|
|
1553
1106
|
);
|
|
@@ -1595,12 +1148,12 @@ var PollingController = class {
|
|
|
1595
1148
|
};
|
|
1596
1149
|
|
|
1597
1150
|
// packages/react/src/runtime/orchestrator.ts
|
|
1598
|
-
function useRuntimeOrchestrator(
|
|
1151
|
+
function useRuntimeOrchestrator(aomiClient, options) {
|
|
1599
1152
|
const threadContext = useThreadContext();
|
|
1600
1153
|
const threadContextRef = (0, import_react6.useRef)(threadContext);
|
|
1601
1154
|
threadContextRef.current = threadContext;
|
|
1602
|
-
const
|
|
1603
|
-
|
|
1155
|
+
const aomiClientRef = (0, import_react6.useRef)(aomiClient);
|
|
1156
|
+
aomiClientRef.current = aomiClient;
|
|
1604
1157
|
const backendStateRef = (0, import_react6.useRef)(createBackendState());
|
|
1605
1158
|
const [isRunning, setIsRunning] = (0, import_react6.useState)(false);
|
|
1606
1159
|
const messageControllerRef = (0, import_react6.useRef)(null);
|
|
@@ -1608,7 +1161,7 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1608
1161
|
const pendingFetches = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
|
|
1609
1162
|
if (!pollingRef.current) {
|
|
1610
1163
|
pollingRef.current = new PollingController({
|
|
1611
|
-
|
|
1164
|
+
aomiClientRef,
|
|
1612
1165
|
backendStateRef,
|
|
1613
1166
|
applyMessages: (threadId, msgs) => {
|
|
1614
1167
|
var _a;
|
|
@@ -1630,13 +1183,13 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1630
1183
|
}
|
|
1631
1184
|
if (!messageControllerRef.current) {
|
|
1632
1185
|
messageControllerRef.current = new MessageController({
|
|
1633
|
-
|
|
1186
|
+
aomiClientRef,
|
|
1634
1187
|
backendStateRef,
|
|
1635
1188
|
threadContextRef,
|
|
1636
1189
|
polling: pollingRef.current,
|
|
1637
1190
|
setGlobalIsRunning: setIsRunning,
|
|
1638
1191
|
getPublicKey: options.getPublicKey,
|
|
1639
|
-
|
|
1192
|
+
getApp: options.getApp,
|
|
1640
1193
|
getApiKey: options.getApiKey,
|
|
1641
1194
|
getUserState: options.getUserState,
|
|
1642
1195
|
onSyncEvents: options.onSyncEvents
|
|
@@ -1649,7 +1202,7 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1649
1202
|
pendingFetches.current.add(threadId);
|
|
1650
1203
|
try {
|
|
1651
1204
|
const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
|
|
1652
|
-
const state = await
|
|
1205
|
+
const state = await aomiClientRef.current.fetchState(
|
|
1653
1206
|
backendThreadId,
|
|
1654
1207
|
userState
|
|
1655
1208
|
);
|
|
@@ -1681,7 +1234,7 @@ function useRuntimeOrchestrator(backendApi, options) {
|
|
|
1681
1234
|
isRunning,
|
|
1682
1235
|
setIsRunning,
|
|
1683
1236
|
ensureInitialState,
|
|
1684
|
-
|
|
1237
|
+
aomiClientRef
|
|
1685
1238
|
};
|
|
1686
1239
|
}
|
|
1687
1240
|
|
|
@@ -1712,7 +1265,7 @@ function buildThreadLists(threadMetadata) {
|
|
|
1712
1265
|
return { regularThreads, archivedThreads };
|
|
1713
1266
|
}
|
|
1714
1267
|
function buildThreadListAdapter({
|
|
1715
|
-
|
|
1268
|
+
aomiClientRef,
|
|
1716
1269
|
threadContext,
|
|
1717
1270
|
setIsRunning
|
|
1718
1271
|
}) {
|
|
@@ -1740,6 +1293,7 @@ function buildThreadListAdapter({
|
|
|
1740
1293
|
},
|
|
1741
1294
|
onSwitchToThread: (threadId) => {
|
|
1742
1295
|
threadContext.setCurrentThreadId(threadId);
|
|
1296
|
+
threadContext.bumpThreadViewKey();
|
|
1743
1297
|
},
|
|
1744
1298
|
onRename: async (threadId, newTitle) => {
|
|
1745
1299
|
var _a, _b;
|
|
@@ -1749,7 +1303,7 @@ function buildThreadListAdapter({
|
|
|
1749
1303
|
title: normalizedTitle
|
|
1750
1304
|
});
|
|
1751
1305
|
try {
|
|
1752
|
-
await
|
|
1306
|
+
await aomiClientRef.current.renameThread(threadId, newTitle);
|
|
1753
1307
|
} catch (error) {
|
|
1754
1308
|
console.error("Failed to rename thread:", error);
|
|
1755
1309
|
threadContext.updateThreadMetadata(threadId, {
|
|
@@ -1760,7 +1314,7 @@ function buildThreadListAdapter({
|
|
|
1760
1314
|
onArchive: async (threadId) => {
|
|
1761
1315
|
threadContext.updateThreadMetadata(threadId, { status: "archived" });
|
|
1762
1316
|
try {
|
|
1763
|
-
await
|
|
1317
|
+
await aomiClientRef.current.archiveThread(threadId);
|
|
1764
1318
|
} catch (error) {
|
|
1765
1319
|
console.error("Failed to archive thread:", error);
|
|
1766
1320
|
threadContext.updateThreadMetadata(threadId, { status: "regular" });
|
|
@@ -1769,7 +1323,7 @@ function buildThreadListAdapter({
|
|
|
1769
1323
|
onUnarchive: async (threadId) => {
|
|
1770
1324
|
threadContext.updateThreadMetadata(threadId, { status: "regular" });
|
|
1771
1325
|
try {
|
|
1772
|
-
await
|
|
1326
|
+
await aomiClientRef.current.unarchiveThread(threadId);
|
|
1773
1327
|
} catch (error) {
|
|
1774
1328
|
console.error("Failed to unarchive thread:", error);
|
|
1775
1329
|
threadContext.updateThreadMetadata(threadId, { status: "archived" });
|
|
@@ -1777,7 +1331,7 @@ function buildThreadListAdapter({
|
|
|
1777
1331
|
},
|
|
1778
1332
|
onDelete: async (threadId) => {
|
|
1779
1333
|
try {
|
|
1780
|
-
await
|
|
1334
|
+
await aomiClientRef.current.deleteThread(threadId);
|
|
1781
1335
|
threadContext.setThreadMetadata((prev) => {
|
|
1782
1336
|
const next = new Map(prev);
|
|
1783
1337
|
next.delete(threadId);
|
|
@@ -1864,6 +1418,68 @@ function getAll(buffer) {
|
|
|
1864
1418
|
}
|
|
1865
1419
|
|
|
1866
1420
|
// packages/react/src/handlers/wallet-handler.ts
|
|
1421
|
+
function asRecord(value) {
|
|
1422
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
1423
|
+
return value;
|
|
1424
|
+
}
|
|
1425
|
+
function getToolArgs(payload) {
|
|
1426
|
+
const root = asRecord(payload);
|
|
1427
|
+
const nestedArgs = asRecord(root == null ? void 0 : root.args);
|
|
1428
|
+
return nestedArgs != null ? nestedArgs : root != null ? root : {};
|
|
1429
|
+
}
|
|
1430
|
+
function parseChainId(value) {
|
|
1431
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
1432
|
+
if (typeof value !== "string") return void 0;
|
|
1433
|
+
const trimmed = value.trim();
|
|
1434
|
+
if (!trimmed) return void 0;
|
|
1435
|
+
if (trimmed.startsWith("0x")) {
|
|
1436
|
+
const parsedHex = Number.parseInt(trimmed.slice(2), 16);
|
|
1437
|
+
return Number.isFinite(parsedHex) ? parsedHex : void 0;
|
|
1438
|
+
}
|
|
1439
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
1440
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
1441
|
+
}
|
|
1442
|
+
function normalizeTxPayload(payload) {
|
|
1443
|
+
var _a, _b, _c;
|
|
1444
|
+
const root = asRecord(payload);
|
|
1445
|
+
const args = getToolArgs(payload);
|
|
1446
|
+
const ctx = asRecord(root == null ? void 0 : root.ctx);
|
|
1447
|
+
const to = typeof args.to === "string" ? args.to : void 0;
|
|
1448
|
+
if (!to) return null;
|
|
1449
|
+
const valueRaw = args.value;
|
|
1450
|
+
const value = typeof valueRaw === "string" ? valueRaw : typeof valueRaw === "number" && Number.isFinite(valueRaw) ? String(Math.trunc(valueRaw)) : void 0;
|
|
1451
|
+
const data = typeof args.data === "string" ? args.data : void 0;
|
|
1452
|
+
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);
|
|
1453
|
+
return {
|
|
1454
|
+
to,
|
|
1455
|
+
value,
|
|
1456
|
+
data,
|
|
1457
|
+
chainId
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
function normalizeEip712Payload(payload) {
|
|
1461
|
+
var _a;
|
|
1462
|
+
const args = getToolArgs(payload);
|
|
1463
|
+
const typedDataRaw = (_a = args.typed_data) != null ? _a : args.typedData;
|
|
1464
|
+
let typedData;
|
|
1465
|
+
if (typeof typedDataRaw === "string") {
|
|
1466
|
+
try {
|
|
1467
|
+
const parsed = JSON.parse(typedDataRaw);
|
|
1468
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1469
|
+
typedData = parsed;
|
|
1470
|
+
}
|
|
1471
|
+
} catch (e) {
|
|
1472
|
+
typedData = void 0;
|
|
1473
|
+
}
|
|
1474
|
+
} else if (typedDataRaw && typeof typedDataRaw === "object" && !Array.isArray(typedDataRaw)) {
|
|
1475
|
+
typedData = typedDataRaw;
|
|
1476
|
+
}
|
|
1477
|
+
const description = typeof args.description === "string" ? args.description : void 0;
|
|
1478
|
+
return {
|
|
1479
|
+
typed_data: typedData,
|
|
1480
|
+
description
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1867
1483
|
function useWalletHandler({
|
|
1868
1484
|
sessionId,
|
|
1869
1485
|
onRequestComplete
|
|
@@ -1878,7 +1494,11 @@ function useWalletHandler({
|
|
|
1878
1494
|
const unsubscribe = subscribe2(
|
|
1879
1495
|
"wallet_tx_request",
|
|
1880
1496
|
(event) => {
|
|
1881
|
-
const payload = event.payload;
|
|
1497
|
+
const payload = normalizeTxPayload(event.payload);
|
|
1498
|
+
if (!payload) {
|
|
1499
|
+
console.warn("[aomi][wallet] Ignoring tx request with invalid payload", event.payload);
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1882
1502
|
enqueue(bufferRef.current, "transaction", payload);
|
|
1883
1503
|
syncState();
|
|
1884
1504
|
}
|
|
@@ -1890,7 +1510,7 @@ function useWalletHandler({
|
|
|
1890
1510
|
"wallet_eip712_request",
|
|
1891
1511
|
(event) => {
|
|
1892
1512
|
var _a;
|
|
1893
|
-
const payload = (_a = event.payload) != null ? _a : {};
|
|
1513
|
+
const payload = normalizeEip712Payload((_a = event.payload) != null ? _a : {});
|
|
1894
1514
|
enqueue(bufferRef.current, "eip712_sign", payload);
|
|
1895
1515
|
syncState();
|
|
1896
1516
|
}
|
|
@@ -1980,7 +1600,7 @@ function useWalletHandler({
|
|
|
1980
1600
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1981
1601
|
function AomiRuntimeCore({
|
|
1982
1602
|
children,
|
|
1983
|
-
|
|
1603
|
+
aomiClient
|
|
1984
1604
|
}) {
|
|
1985
1605
|
const threadContext = useThreadContext();
|
|
1986
1606
|
const eventContext = useEventContext();
|
|
@@ -1995,14 +1615,14 @@ function AomiRuntimeCore({
|
|
|
1995
1615
|
isRunning,
|
|
1996
1616
|
setIsRunning,
|
|
1997
1617
|
ensureInitialState,
|
|
1998
|
-
|
|
1999
|
-
} = useRuntimeOrchestrator(
|
|
1618
|
+
aomiClientRef
|
|
1619
|
+
} = useRuntimeOrchestrator(aomiClient, {
|
|
2000
1620
|
onSyncEvents: dispatchSystemEvents,
|
|
2001
1621
|
getPublicKey: () => getUserState().address,
|
|
2002
1622
|
getUserState,
|
|
2003
|
-
|
|
1623
|
+
getApp: () => {
|
|
2004
1624
|
var _a, _b;
|
|
2005
|
-
return (_b = (_a = getCurrentThreadControl().
|
|
1625
|
+
return (_b = (_a = getCurrentThreadControl().app) != null ? _a : getControlState().defaultApp) != null ? _b : "default";
|
|
2006
1626
|
},
|
|
2007
1627
|
getApiKey: () => getControlState().apiKey
|
|
2008
1628
|
});
|
|
@@ -2018,10 +1638,10 @@ function AomiRuntimeCore({
|
|
|
2018
1638
|
ensName: newUser.ensName
|
|
2019
1639
|
}
|
|
2020
1640
|
});
|
|
2021
|
-
await
|
|
1641
|
+
await aomiClientRef.current.sendSystemMessage(sessionId, message);
|
|
2022
1642
|
});
|
|
2023
1643
|
return unsubscribe;
|
|
2024
|
-
}, [onUserStateChange,
|
|
1644
|
+
}, [onUserStateChange, aomiClientRef, threadContext.currentThreadId]);
|
|
2025
1645
|
const threadContextRef = (0, import_react9.useRef)(threadContext);
|
|
2026
1646
|
threadContextRef.current = threadContext;
|
|
2027
1647
|
const currentThreadIdRef = (0, import_react9.useRef)(threadContext.currentThreadId);
|
|
@@ -2069,21 +1689,13 @@ function AomiRuntimeCore({
|
|
|
2069
1689
|
const currentMessages = threadContext.getThreadMessages(
|
|
2070
1690
|
threadContext.currentThreadId
|
|
2071
1691
|
);
|
|
2072
|
-
const resolvedSessionId = (0, import_react9.useMemo)(
|
|
2073
|
-
() => resolveThreadId(backendStateRef.current, threadContext.currentThreadId),
|
|
2074
|
-
[
|
|
2075
|
-
backendStateRef,
|
|
2076
|
-
threadContext.currentThreadId,
|
|
2077
|
-
threadContext.allThreadsMetadata
|
|
2078
|
-
]
|
|
2079
|
-
);
|
|
2080
1692
|
(0, import_react9.useEffect)(() => {
|
|
2081
1693
|
const userAddress = user.address;
|
|
2082
1694
|
if (!userAddress) return;
|
|
2083
1695
|
const fetchThreadList = async () => {
|
|
2084
1696
|
var _a, _b, _c;
|
|
2085
1697
|
try {
|
|
2086
|
-
const threadList = await
|
|
1698
|
+
const threadList = await aomiClientRef.current.listThreads(userAddress);
|
|
2087
1699
|
const currentContext = threadContextRef.current;
|
|
2088
1700
|
const newMetadata = new Map(currentContext.allThreadsMetadata);
|
|
2089
1701
|
let maxChatNum = currentContext.threadCnt;
|
|
@@ -2115,25 +1727,25 @@ function AomiRuntimeCore({
|
|
|
2115
1727
|
}
|
|
2116
1728
|
};
|
|
2117
1729
|
void fetchThreadList();
|
|
2118
|
-
}, [user.address,
|
|
1730
|
+
}, [user.address, aomiClientRef]);
|
|
2119
1731
|
const threadListAdapter = (0, import_react9.useMemo)(
|
|
2120
1732
|
() => buildThreadListAdapter({
|
|
2121
1733
|
backendStateRef,
|
|
2122
|
-
|
|
1734
|
+
aomiClientRef,
|
|
2123
1735
|
threadContext,
|
|
2124
1736
|
currentThreadIdRef,
|
|
2125
1737
|
polling,
|
|
2126
1738
|
userAddress: user.address,
|
|
2127
1739
|
setIsRunning,
|
|
2128
|
-
|
|
1740
|
+
getApp: () => {
|
|
2129
1741
|
var _a, _b;
|
|
2130
|
-
return (_b = (_a = getCurrentThreadControl().
|
|
1742
|
+
return (_b = (_a = getCurrentThreadControl().app) != null ? _a : getControlState().defaultApp) != null ? _b : "default";
|
|
2131
1743
|
},
|
|
2132
1744
|
getApiKey: () => getControlState().apiKey,
|
|
2133
1745
|
getUserState
|
|
2134
1746
|
}),
|
|
2135
1747
|
[
|
|
2136
|
-
|
|
1748
|
+
aomiClientRef,
|
|
2137
1749
|
polling,
|
|
2138
1750
|
user.address,
|
|
2139
1751
|
backendStateRef,
|
|
@@ -2147,58 +1759,38 @@ function AomiRuntimeCore({
|
|
|
2147
1759
|
);
|
|
2148
1760
|
(0, import_react9.useEffect)(() => {
|
|
2149
1761
|
const backendState = backendStateRef.current;
|
|
2150
|
-
const
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
const targetThreadId = resolveThreadId(backendState, sessionId);
|
|
2166
|
-
const normalizedTitle = isPlaceholderTitle(newTitle) ? "" : newTitle;
|
|
2167
|
-
if (process.env.NODE_ENV !== "production") {
|
|
2168
|
-
console.debug("[aomi][sse] title_changed", {
|
|
2169
|
-
sessionId,
|
|
2170
|
-
newTitle,
|
|
2171
|
-
normalizedTitle,
|
|
2172
|
-
currentThreadId: threadContextRef.current.currentThreadId,
|
|
2173
|
-
targetThreadId,
|
|
2174
|
-
hasMapping: sessionId !== targetThreadId
|
|
2175
|
-
});
|
|
2176
|
-
}
|
|
2177
|
-
threadContextRef.current.setThreadMetadata((prev) => {
|
|
2178
|
-
var _a, _b;
|
|
2179
|
-
const next = new Map(prev);
|
|
2180
|
-
const existing = next.get(targetThreadId);
|
|
2181
|
-
const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
|
|
2182
|
-
next.set(targetThreadId, {
|
|
2183
|
-
title: normalizedTitle,
|
|
2184
|
-
status: nextStatus,
|
|
2185
|
-
lastActiveAt: (_a = existing == null ? void 0 : existing.lastActiveAt) != null ? _a : (/* @__PURE__ */ new Date()).toISOString(),
|
|
2186
|
-
control: (_b = existing == null ? void 0 : existing.control) != null ? _b : initThreadControl()
|
|
2187
|
-
});
|
|
2188
|
-
return next;
|
|
2189
|
-
});
|
|
2190
|
-
}
|
|
1762
|
+
const unsubscribe = eventContext.subscribe("title_changed", (event) => {
|
|
1763
|
+
const sessionId = event.sessionId;
|
|
1764
|
+
const payload = event.payload;
|
|
1765
|
+
const newTitle = payload == null ? void 0 : payload.new_title;
|
|
1766
|
+
if (typeof newTitle !== "string") return;
|
|
1767
|
+
const targetThreadId = resolveThreadId(backendState, sessionId);
|
|
1768
|
+
const normalizedTitle = isPlaceholderTitle(newTitle) ? "" : newTitle;
|
|
1769
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1770
|
+
console.debug("[aomi][sse] title_changed", {
|
|
1771
|
+
sessionId,
|
|
1772
|
+
newTitle,
|
|
1773
|
+
normalizedTitle,
|
|
1774
|
+
currentThreadId: threadContextRef.current.currentThreadId,
|
|
1775
|
+
targetThreadId
|
|
1776
|
+
});
|
|
2191
1777
|
}
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
1778
|
+
threadContextRef.current.setThreadMetadata((prev) => {
|
|
1779
|
+
var _a, _b;
|
|
1780
|
+
const next = new Map(prev);
|
|
1781
|
+
const existing = next.get(targetThreadId);
|
|
1782
|
+
const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
|
|
1783
|
+
next.set(targetThreadId, {
|
|
1784
|
+
title: normalizedTitle,
|
|
1785
|
+
status: nextStatus,
|
|
1786
|
+
lastActiveAt: (_a = existing == null ? void 0 : existing.lastActiveAt) != null ? _a : (/* @__PURE__ */ new Date()).toISOString(),
|
|
1787
|
+
control: (_b = existing == null ? void 0 : existing.control) != null ? _b : initThreadControl()
|
|
1788
|
+
});
|
|
1789
|
+
return next;
|
|
1790
|
+
});
|
|
1791
|
+
});
|
|
1792
|
+
return unsubscribe;
|
|
1793
|
+
}, [eventContext, backendStateRef]);
|
|
2202
1794
|
(0, import_react9.useEffect)(() => {
|
|
2203
1795
|
const showToolNotification = (eventType) => (event) => {
|
|
2204
1796
|
const payload = event.payload;
|
|
@@ -2367,12 +1959,12 @@ function AomiRuntimeProvider({
|
|
|
2367
1959
|
children,
|
|
2368
1960
|
backendUrl = "http://localhost:8080"
|
|
2369
1961
|
}) {
|
|
2370
|
-
const
|
|
2371
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThreadContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NotificationContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UserContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AomiRuntimeInner, {
|
|
1962
|
+
const aomiClient = (0, import_react11.useMemo)(() => new import_client2.AomiClient({ baseUrl: backendUrl }), [backendUrl]);
|
|
1963
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThreadContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NotificationContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UserContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AomiRuntimeInner, { aomiClient, children }) }) }) });
|
|
2372
1964
|
}
|
|
2373
1965
|
function AomiRuntimeInner({
|
|
2374
1966
|
children,
|
|
2375
|
-
|
|
1967
|
+
aomiClient
|
|
2376
1968
|
}) {
|
|
2377
1969
|
var _a;
|
|
2378
1970
|
const threadContext = useThreadContext();
|
|
@@ -2380,7 +1972,7 @@ function AomiRuntimeInner({
|
|
|
2380
1972
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2381
1973
|
ControlContextProvider,
|
|
2382
1974
|
{
|
|
2383
|
-
|
|
1975
|
+
aomiClient,
|
|
2384
1976
|
sessionId: threadContext.currentThreadId,
|
|
2385
1977
|
publicKey: (_a = user.address) != null ? _a : void 0,
|
|
2386
1978
|
getThreadMetadata: threadContext.getThreadMetadata,
|
|
@@ -2388,9 +1980,9 @@ function AomiRuntimeInner({
|
|
|
2388
1980
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2389
1981
|
EventContextProvider,
|
|
2390
1982
|
{
|
|
2391
|
-
|
|
1983
|
+
aomiClient,
|
|
2392
1984
|
sessionId: threadContext.currentThreadId,
|
|
2393
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AomiRuntimeCore, {
|
|
1985
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AomiRuntimeCore, { aomiClient, children })
|
|
2394
1986
|
}
|
|
2395
1987
|
)
|
|
2396
1988
|
}
|
|
@@ -2440,8 +2032,8 @@ function useNotificationHandler({
|
|
|
2440
2032
|
}
|
|
2441
2033
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2442
2034
|
0 && (module.exports = {
|
|
2035
|
+
AomiClient,
|
|
2443
2036
|
AomiRuntimeProvider,
|
|
2444
|
-
BackendApi,
|
|
2445
2037
|
ControlContextProvider,
|
|
2446
2038
|
EventContextProvider,
|
|
2447
2039
|
NotificationContextProvider,
|