@aikaara/chat-sdk 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/aikaara-chat.iife.js +45 -19
- package/dist/{headless-CXRux2Q-.mjs → headless-BhsiNVQj.mjs} +185 -199
- package/dist/headless-CrgIWcf7.cjs +1 -0
- package/dist/headless.cjs +1 -1
- package/dist/headless.d.ts +3 -0
- package/dist/headless.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +1 -1
- package/dist/ui.cjs +45 -19
- package/dist/ui.d.ts +2 -0
- package/dist/ui.mjs +216 -210
- package/package.json +2 -2
- package/dist/headless-DDmLD-ag.cjs +0 -1
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
class p {
|
|
2
|
+
identifier;
|
|
3
|
+
callbacks = {};
|
|
4
|
+
sendFn;
|
|
5
5
|
constructor(t, e) {
|
|
6
|
-
o(this, "identifier");
|
|
7
|
-
o(this, "callbacks", {});
|
|
8
|
-
o(this, "sendFn");
|
|
9
6
|
this.identifier = t, this.sendFn = e;
|
|
10
7
|
}
|
|
11
8
|
onReceived(t) {
|
|
@@ -25,32 +22,28 @@ class S {
|
|
|
25
22
|
}
|
|
26
23
|
/** @internal */
|
|
27
24
|
_notifyReceived(t) {
|
|
28
|
-
|
|
29
|
-
(s = (e = this.callbacks).received) == null || s.call(e, t);
|
|
25
|
+
this.callbacks.received?.(t);
|
|
30
26
|
}
|
|
31
27
|
/** @internal */
|
|
32
28
|
_notifyConnected() {
|
|
33
|
-
|
|
34
|
-
(e = (t = this.callbacks).connected) == null || e.call(t);
|
|
29
|
+
this.callbacks.connected?.();
|
|
35
30
|
}
|
|
36
31
|
/** @internal */
|
|
37
32
|
_notifyDisconnected() {
|
|
38
|
-
|
|
39
|
-
(e = (t = this.callbacks).disconnected) == null || e.call(t);
|
|
33
|
+
this.callbacks.disconnected?.();
|
|
40
34
|
}
|
|
41
35
|
/** @internal */
|
|
42
36
|
_notifyRejected() {
|
|
43
|
-
|
|
44
|
-
(e = (t = this.callbacks).rejected) == null || e.call(t);
|
|
37
|
+
this.callbacks.rejected?.();
|
|
45
38
|
}
|
|
46
39
|
}
|
|
47
|
-
class
|
|
40
|
+
class g {
|
|
41
|
+
ws = null;
|
|
42
|
+
url;
|
|
43
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
44
|
+
welcomePromise = null;
|
|
45
|
+
pendingSubscriptions = /* @__PURE__ */ new Map();
|
|
48
46
|
constructor(t) {
|
|
49
|
-
o(this, "ws", null);
|
|
50
|
-
o(this, "url");
|
|
51
|
-
o(this, "subscriptions", /* @__PURE__ */ new Map());
|
|
52
|
-
o(this, "welcomePromise", null);
|
|
53
|
-
o(this, "pendingSubscriptions", /* @__PURE__ */ new Map());
|
|
54
47
|
this.url = t;
|
|
55
48
|
}
|
|
56
49
|
connect() {
|
|
@@ -59,9 +52,8 @@ class f {
|
|
|
59
52
|
}, this.ws.onmessage = (s) => {
|
|
60
53
|
this.handleMessage(s);
|
|
61
54
|
}, this.ws.onerror = () => {
|
|
62
|
-
var n;
|
|
63
55
|
const s = new Error("WebSocket connection error");
|
|
64
|
-
|
|
56
|
+
this.welcomePromise?.reject(s), this.welcomePromise = null;
|
|
65
57
|
}, this.ws.onclose = () => {
|
|
66
58
|
this.subscriptions.forEach((s) => s._notifyDisconnected());
|
|
67
59
|
};
|
|
@@ -71,7 +63,7 @@ class f {
|
|
|
71
63
|
this.ws && (this.ws.onclose = null, this.ws.close(), this.ws = null), this.subscriptions.forEach((t) => t._notifyDisconnected()), this.subscriptions.clear();
|
|
72
64
|
}
|
|
73
65
|
subscribe(t) {
|
|
74
|
-
const e = JSON.stringify(t), s = new
|
|
66
|
+
const e = JSON.stringify(t), s = new p(e, (n) => {
|
|
75
67
|
this.send({
|
|
76
68
|
command: "message",
|
|
77
69
|
identifier: e,
|
|
@@ -108,15 +100,12 @@ class f {
|
|
|
108
100
|
});
|
|
109
101
|
}
|
|
110
102
|
get isConnected() {
|
|
111
|
-
|
|
112
|
-
return ((t = this.ws) == null ? void 0 : t.readyState) === WebSocket.OPEN;
|
|
103
|
+
return this.ws?.readyState === WebSocket.OPEN;
|
|
113
104
|
}
|
|
114
105
|
send(t) {
|
|
115
|
-
|
|
116
|
-
((e = this.ws) == null ? void 0 : e.readyState) === WebSocket.OPEN && this.ws.send(JSON.stringify(t));
|
|
106
|
+
this.ws?.readyState === WebSocket.OPEN && this.ws.send(JSON.stringify(t));
|
|
117
107
|
}
|
|
118
108
|
handleMessage(t) {
|
|
119
|
-
var s;
|
|
120
109
|
let e;
|
|
121
110
|
try {
|
|
122
111
|
e = JSON.parse(t.data);
|
|
@@ -125,55 +114,48 @@ class f {
|
|
|
125
114
|
}
|
|
126
115
|
switch (e.type) {
|
|
127
116
|
case "welcome":
|
|
128
|
-
|
|
117
|
+
this.welcomePromise?.resolve(), this.welcomePromise = null;
|
|
129
118
|
break;
|
|
130
119
|
case "ping":
|
|
131
120
|
break;
|
|
132
121
|
case "confirm_subscription": {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
122
|
+
const s = e.identifier;
|
|
123
|
+
this.subscriptions.get(s)?._notifyConnected();
|
|
124
|
+
const i = this.pendingSubscriptions.get(s);
|
|
125
|
+
i && (i.resolve(), this.pendingSubscriptions.delete(s));
|
|
137
126
|
break;
|
|
138
127
|
}
|
|
139
128
|
case "reject_subscription": {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
129
|
+
const s = e.identifier;
|
|
130
|
+
this.subscriptions.get(s)?._notifyRejected(), this.subscriptions.delete(s);
|
|
131
|
+
const i = this.pendingSubscriptions.get(s);
|
|
132
|
+
i && (i.reject(new Error(`Subscription rejected: ${s}`)), this.pendingSubscriptions.delete(s));
|
|
144
133
|
break;
|
|
145
134
|
}
|
|
146
135
|
case "disconnect":
|
|
147
|
-
this.subscriptions.forEach((
|
|
136
|
+
this.subscriptions.forEach((s) => s._notifyDisconnected());
|
|
148
137
|
break;
|
|
149
138
|
default: {
|
|
150
|
-
|
|
151
|
-
const n = this.subscriptions.get(e.identifier);
|
|
152
|
-
n == null || n._notifyReceived(e.message);
|
|
153
|
-
}
|
|
139
|
+
e.identifier && e.message !== void 0 && this.subscriptions.get(e.identifier)?._notifyReceived(e.message);
|
|
154
140
|
break;
|
|
155
141
|
}
|
|
156
142
|
}
|
|
157
143
|
}
|
|
158
144
|
}
|
|
159
|
-
class
|
|
160
|
-
|
|
161
|
-
o(this, "handlers", /* @__PURE__ */ new Map());
|
|
162
|
-
}
|
|
145
|
+
class m {
|
|
146
|
+
handlers = /* @__PURE__ */ new Map();
|
|
163
147
|
on(t, e) {
|
|
164
148
|
return this.handlers.has(t) || this.handlers.set(t, /* @__PURE__ */ new Set()), this.handlers.get(t).add(e), () => this.off(t, e);
|
|
165
149
|
}
|
|
166
150
|
off(t, e) {
|
|
167
|
-
|
|
168
|
-
(s = this.handlers.get(t)) == null || s.delete(e);
|
|
151
|
+
this.handlers.get(t)?.delete(e);
|
|
169
152
|
}
|
|
170
153
|
emit(t, e) {
|
|
171
|
-
|
|
172
|
-
(s = this.handlers.get(t)) == null || s.forEach((n) => {
|
|
154
|
+
this.handlers.get(t)?.forEach((s) => {
|
|
173
155
|
try {
|
|
174
|
-
|
|
175
|
-
} catch (
|
|
176
|
-
console.error(`Error in event handler for "${t}":`,
|
|
156
|
+
s(e);
|
|
157
|
+
} catch (n) {
|
|
158
|
+
console.error(`Error in event handler for "${t}":`, n);
|
|
177
159
|
}
|
|
178
160
|
});
|
|
179
161
|
}
|
|
@@ -181,91 +163,94 @@ class _ {
|
|
|
181
163
|
this.handlers.clear();
|
|
182
164
|
}
|
|
183
165
|
}
|
|
184
|
-
const
|
|
185
|
-
class
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
this.
|
|
194
|
-
|
|
195
|
-
this.client = new f(s);
|
|
166
|
+
const f = 1e3, b = 10, y = 400, I = 600, k = "#6366f1", E = 12, T = "system-ui, -apple-system, sans-serif", C = "Type a message...", M = "bottom-right", A = "light", O = { x: 20, y: 20 }, d = "aikaara_conversation_id";
|
|
167
|
+
class _ extends m {
|
|
168
|
+
client;
|
|
169
|
+
config;
|
|
170
|
+
state = "disconnected";
|
|
171
|
+
reconnectAttempt = 0;
|
|
172
|
+
reconnectTimer = null;
|
|
173
|
+
constructor(t) {
|
|
174
|
+
super(), this.config = t;
|
|
175
|
+
const e = this.buildWsUrl(t.baseUrl, t.userToken);
|
|
176
|
+
this.client = new g(e);
|
|
196
177
|
}
|
|
197
178
|
async connect() {
|
|
198
179
|
this.setState("connecting");
|
|
199
180
|
try {
|
|
200
181
|
await this.client.connect(), this.setState("connected"), this.reconnectAttempt = 0;
|
|
201
|
-
} catch (
|
|
182
|
+
} catch (t) {
|
|
202
183
|
if (this.setState("disconnected"), this.config.reconnect !== !1)
|
|
203
184
|
this.scheduleReconnect();
|
|
204
185
|
else
|
|
205
|
-
throw
|
|
186
|
+
throw t;
|
|
206
187
|
}
|
|
207
188
|
}
|
|
208
189
|
async disconnect() {
|
|
209
190
|
this.clearReconnectTimer(), this.client.disconnect(), this.setState("disconnected");
|
|
210
191
|
}
|
|
211
|
-
subscribeToConversation(
|
|
192
|
+
subscribeToConversation(t) {
|
|
212
193
|
return this.client.subscribeAsync({
|
|
213
194
|
channel: "ConversationChannel",
|
|
214
|
-
conversation_id:
|
|
195
|
+
conversation_id: t
|
|
215
196
|
});
|
|
216
197
|
}
|
|
217
|
-
sendMessage(
|
|
218
|
-
const
|
|
198
|
+
sendMessage(t, e) {
|
|
199
|
+
const s = JSON.stringify({
|
|
219
200
|
channel: "ConversationChannel",
|
|
220
|
-
conversation_id:
|
|
201
|
+
conversation_id: t
|
|
221
202
|
});
|
|
222
|
-
this.client.perform(
|
|
203
|
+
this.client.perform(s, "send_message", { content: e });
|
|
223
204
|
}
|
|
224
|
-
sendUserEvent(e, s, n
|
|
225
|
-
const
|
|
205
|
+
sendUserEvent(t, e, s, n) {
|
|
206
|
+
const i = JSON.stringify({
|
|
226
207
|
channel: "ConversationChannel",
|
|
227
|
-
conversation_id:
|
|
208
|
+
conversation_id: t
|
|
228
209
|
});
|
|
229
|
-
this.client.perform(
|
|
230
|
-
event_key:
|
|
231
|
-
...
|
|
232
|
-
...
|
|
210
|
+
this.client.perform(i, "send_user_event", {
|
|
211
|
+
event_key: e,
|
|
212
|
+
...s && { value: s },
|
|
213
|
+
...n && { source: n }
|
|
233
214
|
});
|
|
234
215
|
}
|
|
235
216
|
get connectionState() {
|
|
236
217
|
return this.state;
|
|
237
218
|
}
|
|
238
|
-
setState(
|
|
239
|
-
this.state !==
|
|
219
|
+
setState(t) {
|
|
220
|
+
this.state !== t && (this.state = t, this.emit("connection:state", t));
|
|
240
221
|
}
|
|
241
222
|
scheduleReconnect() {
|
|
242
|
-
const
|
|
243
|
-
if (this.reconnectAttempt >=
|
|
223
|
+
const t = this.config.maxReconnectAttempts ?? b;
|
|
224
|
+
if (this.reconnectAttempt >= t) {
|
|
244
225
|
this.emit("error", new Error("Max reconnection attempts reached"));
|
|
245
226
|
return;
|
|
246
227
|
}
|
|
247
228
|
this.setState("reconnecting");
|
|
248
|
-
const
|
|
229
|
+
const s = (this.config.reconnectInterval ?? f) * Math.pow(2, this.reconnectAttempt);
|
|
249
230
|
this.reconnectAttempt++, this.reconnectTimer = setTimeout(async () => {
|
|
250
231
|
try {
|
|
251
|
-
const
|
|
252
|
-
this.client = new
|
|
232
|
+
const n = this.buildWsUrl(this.config.baseUrl, this.config.userToken);
|
|
233
|
+
this.client = new g(n), await this.connect();
|
|
253
234
|
} catch {
|
|
254
235
|
}
|
|
255
|
-
},
|
|
236
|
+
}, s);
|
|
256
237
|
}
|
|
257
238
|
clearReconnectTimer() {
|
|
258
239
|
this.reconnectTimer && (clearTimeout(this.reconnectTimer), this.reconnectTimer = null);
|
|
259
240
|
}
|
|
260
|
-
buildWsUrl(
|
|
261
|
-
|
|
241
|
+
buildWsUrl(t, e) {
|
|
242
|
+
if (this.config.wsUrl) {
|
|
243
|
+
const n = this.config.wsUrl.includes("?") ? "&" : "?";
|
|
244
|
+
return `${this.config.wsUrl}${n}token=${e}`;
|
|
245
|
+
}
|
|
246
|
+
return `${t.replace(/^http/, "ws")}/cable?token=${e}`;
|
|
262
247
|
}
|
|
263
248
|
}
|
|
264
|
-
class
|
|
249
|
+
class S {
|
|
250
|
+
baseUrl;
|
|
251
|
+
apiKey;
|
|
252
|
+
userToken;
|
|
265
253
|
constructor(t, e, s) {
|
|
266
|
-
o(this, "baseUrl");
|
|
267
|
-
o(this, "apiKey");
|
|
268
|
-
o(this, "userToken");
|
|
269
254
|
this.baseUrl = t, this.userToken = e, this.apiKey = s;
|
|
270
255
|
}
|
|
271
256
|
async createConversation(t) {
|
|
@@ -286,16 +271,15 @@ class k {
|
|
|
286
271
|
)).map(this.mapMessage);
|
|
287
272
|
}
|
|
288
273
|
mapMessage(t) {
|
|
289
|
-
var e;
|
|
290
274
|
return {
|
|
291
275
|
id: String(t.id),
|
|
292
276
|
conversationId: String(t.conversation_id),
|
|
293
277
|
role: t.role,
|
|
294
278
|
content: t.content || "",
|
|
295
|
-
toolCalls:
|
|
296
|
-
id:
|
|
297
|
-
type:
|
|
298
|
-
function:
|
|
279
|
+
toolCalls: t.tool_calls?.map((e) => ({
|
|
280
|
+
id: e.id,
|
|
281
|
+
type: e.type,
|
|
282
|
+
function: e.function
|
|
299
283
|
})),
|
|
300
284
|
toolCallResults: t.tool_call_results,
|
|
301
285
|
tokensInput: t.tokens_input,
|
|
@@ -311,34 +295,32 @@ class k {
|
|
|
311
295
|
Accept: "application/json"
|
|
312
296
|
};
|
|
313
297
|
this.apiKey && (n["X-Api-Key"] = this.apiKey);
|
|
314
|
-
const i = `${this.baseUrl}${e}`,
|
|
315
|
-
s && (
|
|
316
|
-
const
|
|
317
|
-
if (!
|
|
318
|
-
const
|
|
319
|
-
let
|
|
298
|
+
const i = `${this.baseUrl}${e}`, l = { method: t, headers: n };
|
|
299
|
+
s && (l.body = JSON.stringify(s));
|
|
300
|
+
const c = await fetch(i, l);
|
|
301
|
+
if (!c.ok) {
|
|
302
|
+
const a = await c.text();
|
|
303
|
+
let h;
|
|
320
304
|
try {
|
|
321
|
-
const
|
|
322
|
-
|
|
305
|
+
const u = JSON.parse(a);
|
|
306
|
+
h = u.error || u.message || a;
|
|
323
307
|
} catch {
|
|
324
|
-
|
|
308
|
+
h = a;
|
|
325
309
|
}
|
|
326
|
-
throw new Error(`API error ${
|
|
310
|
+
throw new Error(`API error ${c.status}: ${h}`);
|
|
327
311
|
}
|
|
328
|
-
const
|
|
329
|
-
if (
|
|
330
|
-
if (!
|
|
331
|
-
throw new Error(`API error: ${
|
|
332
|
-
return
|
|
312
|
+
const r = await c.json();
|
|
313
|
+
if (r && typeof r == "object" && "success" in r) {
|
|
314
|
+
if (!r.success)
|
|
315
|
+
throw new Error(`API error: ${r.message || "Request failed"}`);
|
|
316
|
+
return r.data;
|
|
333
317
|
}
|
|
334
|
-
return
|
|
318
|
+
return r;
|
|
335
319
|
}
|
|
336
320
|
}
|
|
337
|
-
class
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
o(this, "optimisticCounter", 0);
|
|
341
|
-
}
|
|
321
|
+
class v {
|
|
322
|
+
_messages = [];
|
|
323
|
+
optimisticCounter = 0;
|
|
342
324
|
get messages() {
|
|
343
325
|
return [...this._messages];
|
|
344
326
|
}
|
|
@@ -372,6 +354,13 @@ class E {
|
|
|
372
354
|
const e = this._messages.findLast((s) => s.status === "streaming");
|
|
373
355
|
e && (e.content = t);
|
|
374
356
|
}
|
|
357
|
+
appendToStreaming(t) {
|
|
358
|
+
const e = this._messages.findLast((s) => s.status === "streaming");
|
|
359
|
+
e && (e.content += t);
|
|
360
|
+
}
|
|
361
|
+
get streamingContent() {
|
|
362
|
+
return this._messages.findLast((e) => e.status === "streaming")?.content || "";
|
|
363
|
+
}
|
|
375
364
|
finalizeStreaming(t) {
|
|
376
365
|
const e = this._messages.findLast((s) => s.status === "streaming");
|
|
377
366
|
return e && (e.status = "complete", t && (e.tokensInput = t.tokensInput, e.tokensOutput = t.tokensOutput)), e;
|
|
@@ -386,10 +375,10 @@ class E {
|
|
|
386
375
|
this._messages = [];
|
|
387
376
|
}
|
|
388
377
|
}
|
|
389
|
-
class
|
|
378
|
+
class w {
|
|
379
|
+
_conversationId;
|
|
380
|
+
persist;
|
|
390
381
|
constructor(t, e = !0) {
|
|
391
|
-
o(this, "_conversationId");
|
|
392
|
-
o(this, "persist");
|
|
393
382
|
this.persist = e, this._conversationId = t || this.loadFromStorage();
|
|
394
383
|
}
|
|
395
384
|
get conversationId() {
|
|
@@ -401,77 +390,73 @@ class T {
|
|
|
401
390
|
clear() {
|
|
402
391
|
if (this._conversationId = null, this.persist)
|
|
403
392
|
try {
|
|
404
|
-
localStorage.removeItem(
|
|
393
|
+
localStorage.removeItem(d);
|
|
405
394
|
} catch {
|
|
406
395
|
}
|
|
407
396
|
}
|
|
408
397
|
loadFromStorage() {
|
|
409
398
|
if (!this.persist) return null;
|
|
410
399
|
try {
|
|
411
|
-
return localStorage.getItem(
|
|
400
|
+
return localStorage.getItem(d);
|
|
412
401
|
} catch {
|
|
413
402
|
return null;
|
|
414
403
|
}
|
|
415
404
|
}
|
|
416
405
|
saveToStorage(t) {
|
|
417
406
|
try {
|
|
418
|
-
localStorage.setItem(
|
|
407
|
+
localStorage.setItem(d, t);
|
|
419
408
|
} catch {
|
|
420
409
|
}
|
|
421
410
|
}
|
|
422
411
|
}
|
|
423
|
-
class
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
this.emit("
|
|
435
|
-
}), this.connection.on("error", (s) => {
|
|
436
|
-
var n, i;
|
|
437
|
-
this.emit("error", s), (i = (n = this.config).onError) == null || i.call(n, s);
|
|
412
|
+
class U extends m {
|
|
413
|
+
connection;
|
|
414
|
+
api;
|
|
415
|
+
messageStore;
|
|
416
|
+
conversationManager;
|
|
417
|
+
subscription = null;
|
|
418
|
+
config;
|
|
419
|
+
constructor(t) {
|
|
420
|
+
super(), this.config = t, this.connection = new _(t), this.api = new S(t.baseUrl, t.userToken, t.apiKey), this.messageStore = new v(), this.conversationManager = new w(t.conversationId), this.connection.on("connection:state", (e) => {
|
|
421
|
+
this.emit("connection:state", e), this.config.onConnectionStateChange?.(e);
|
|
422
|
+
}), this.connection.on("error", (e) => {
|
|
423
|
+
this.emit("error", e), this.config.onError?.(e);
|
|
438
424
|
});
|
|
439
425
|
}
|
|
440
426
|
async connect() {
|
|
441
427
|
if (await this.connection.connect(), !this.conversationManager.conversationId) {
|
|
442
|
-
const
|
|
428
|
+
const t = await this.api.createConversation({
|
|
443
429
|
systemPromptId: this.config.systemPromptId,
|
|
444
430
|
channel: this.config.channel || "widget",
|
|
445
431
|
extUid: this.config.extUid
|
|
446
432
|
});
|
|
447
|
-
this.conversationManager.conversationId = String(
|
|
433
|
+
this.conversationManager.conversationId = String(t.id);
|
|
448
434
|
}
|
|
449
435
|
this.subscription = await this.connection.subscribeToConversation(
|
|
450
436
|
this.conversationManager.conversationId
|
|
451
|
-
), this.subscription.onReceived((
|
|
452
|
-
this.handleBroadcast(
|
|
437
|
+
), this.subscription.onReceived((t) => {
|
|
438
|
+
this.handleBroadcast(t);
|
|
453
439
|
}), await this.loadHistory();
|
|
454
440
|
}
|
|
455
|
-
async sendMessage(
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
if (!s)
|
|
441
|
+
async sendMessage(t) {
|
|
442
|
+
const e = this.conversationManager.conversationId;
|
|
443
|
+
if (!e)
|
|
459
444
|
throw new Error("No active conversation");
|
|
460
|
-
const
|
|
461
|
-
this.emit("message:sent",
|
|
445
|
+
const s = this.messageStore.addOptimistic("user", t, e);
|
|
446
|
+
this.emit("message:sent", s), this.config.onMessage?.(s), this.connection.sendMessage(e, t);
|
|
462
447
|
}
|
|
463
|
-
async sendUserEvent(e, s
|
|
464
|
-
const
|
|
465
|
-
if (!
|
|
448
|
+
async sendUserEvent(t, e, s) {
|
|
449
|
+
const n = this.conversationManager.conversationId;
|
|
450
|
+
if (!n)
|
|
466
451
|
throw new Error("No active conversation");
|
|
467
|
-
this.connection.sendUserEvent(
|
|
452
|
+
this.connection.sendUserEvent(n, t, e, s);
|
|
468
453
|
}
|
|
469
454
|
async loadHistory() {
|
|
470
|
-
const
|
|
471
|
-
if (!
|
|
455
|
+
const t = this.conversationManager.conversationId;
|
|
456
|
+
if (!t) return [];
|
|
472
457
|
try {
|
|
473
|
-
const
|
|
474
|
-
return this.messageStore.setMessages(
|
|
458
|
+
const e = await this.api.getMessages(t);
|
|
459
|
+
return this.messageStore.setMessages(e), e;
|
|
475
460
|
} catch {
|
|
476
461
|
return [];
|
|
477
462
|
}
|
|
@@ -488,45 +473,46 @@ class L extends _ {
|
|
|
488
473
|
async disconnect() {
|
|
489
474
|
this.subscription && (this.subscription = null), await this.connection.disconnect();
|
|
490
475
|
}
|
|
491
|
-
handleBroadcast(
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
switch (e.type) {
|
|
476
|
+
handleBroadcast(t) {
|
|
477
|
+
const e = this.conversationManager.conversationId;
|
|
478
|
+
switch (t.type) {
|
|
495
479
|
case "status": {
|
|
496
|
-
const
|
|
497
|
-
this.emit("status",
|
|
480
|
+
const s = t.status;
|
|
481
|
+
this.emit("status", s), this.config.onStatusChange?.(s), s === "processing" && this.emit("typing:start", void 0);
|
|
498
482
|
break;
|
|
499
483
|
}
|
|
500
484
|
case "error": {
|
|
501
|
-
const
|
|
502
|
-
this.emit("error",
|
|
485
|
+
const s = new Error(t.message || "Unknown error");
|
|
486
|
+
this.emit("error", s), this.config.onError?.(s);
|
|
503
487
|
break;
|
|
504
488
|
}
|
|
505
489
|
case "message_start": {
|
|
506
|
-
if (
|
|
507
|
-
const
|
|
508
|
-
this.emit("stream:start", { messageId:
|
|
490
|
+
if (t.role === "assistant") {
|
|
491
|
+
const s = this.messageStore.addStreamingMessage(e);
|
|
492
|
+
this.emit("stream:start", { messageId: s.id }), this.emit("typing:start", void 0);
|
|
509
493
|
}
|
|
510
494
|
break;
|
|
511
495
|
}
|
|
512
496
|
case "message_update": {
|
|
513
|
-
const
|
|
514
|
-
this.messageStore.updateStreaming(
|
|
497
|
+
const s = t.delta || "", n = t.content || "";
|
|
498
|
+
n ? this.messageStore.updateStreaming(n) : s && this.messageStore.appendToStreaming(s);
|
|
499
|
+
const i = this.messageStore.streamingContent;
|
|
500
|
+
this.emit("stream:update", { delta: s, content: i }), this.config.onStreamUpdate?.(s, i);
|
|
515
501
|
break;
|
|
516
502
|
}
|
|
517
503
|
case "message_end": {
|
|
518
|
-
const
|
|
519
|
-
|
|
504
|
+
const s = t.usage, n = this.messageStore.finalizeStreaming(
|
|
505
|
+
s ? { tokensInput: s.tokens_input || 0, tokensOutput: s.tokens_output || 0 } : void 0
|
|
520
506
|
);
|
|
521
|
-
this.emit("typing:stop", void 0),
|
|
522
|
-
messageId:
|
|
523
|
-
usage:
|
|
524
|
-
}), this.emit("message:received",
|
|
507
|
+
this.emit("typing:stop", void 0), n && (this.emit("stream:end", {
|
|
508
|
+
messageId: n.id,
|
|
509
|
+
usage: s ? { tokensInput: s.tokens_input || 0, tokensOutput: s.tokens_output || 0 } : void 0
|
|
510
|
+
}), this.emit("message:received", n), this.config.onMessage?.(n));
|
|
525
511
|
break;
|
|
526
512
|
}
|
|
527
513
|
case "message_queued": {
|
|
528
|
-
const
|
|
529
|
-
|
|
514
|
+
const s = this.messageStore.messages.findLast((n) => n.status === "sending");
|
|
515
|
+
s && this.messageStore.confirmOptimistic(s.id);
|
|
530
516
|
break;
|
|
531
517
|
}
|
|
532
518
|
case "tool_execution_start":
|
|
@@ -539,27 +525,27 @@ class L extends _ {
|
|
|
539
525
|
case "auto_retry_start":
|
|
540
526
|
case "auto_retry_end":
|
|
541
527
|
case "cancelled":
|
|
542
|
-
this.emit("status",
|
|
528
|
+
this.emit("status", t.type);
|
|
543
529
|
break;
|
|
544
530
|
}
|
|
545
531
|
}
|
|
546
532
|
}
|
|
547
533
|
export {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
534
|
+
g as A,
|
|
535
|
+
p as C,
|
|
536
|
+
O as D,
|
|
537
|
+
m as E,
|
|
538
|
+
v as M,
|
|
539
|
+
U as a,
|
|
540
|
+
S as b,
|
|
541
|
+
_ as c,
|
|
542
|
+
w as d,
|
|
543
|
+
C as e,
|
|
544
|
+
E as f,
|
|
545
|
+
T as g,
|
|
546
|
+
I as h,
|
|
547
|
+
y as i,
|
|
548
|
+
M as j,
|
|
549
|
+
k,
|
|
550
|
+
A as l
|
|
565
551
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";class p{identifier;callbacks={};sendFn;constructor(t,e){this.identifier=t,this.sendFn=e}onReceived(t){return this.callbacks.received=t,this}onConnected(t){return this.callbacks.connected=t,this}onDisconnected(t){return this.callbacks.disconnected=t,this}onRejected(t){return this.callbacks.rejected=t,this}perform(t,e={}){this.sendFn({action:t,...e})}_notifyReceived(t){this.callbacks.received?.(t)}_notifyConnected(){this.callbacks.connected?.()}_notifyDisconnected(){this.callbacks.disconnected?.()}_notifyRejected(){this.callbacks.rejected?.()}}class l{ws=null;url;subscriptions=new Map;welcomePromise=null;pendingSubscriptions=new Map;constructor(t){this.url=t}connect(){return new Promise((t,e)=>{this.welcomePromise={resolve:t,reject:e},this.ws=new WebSocket(this.url),this.ws.onopen=()=>{},this.ws.onmessage=s=>{this.handleMessage(s)},this.ws.onerror=()=>{const s=new Error("WebSocket connection error");this.welcomePromise?.reject(s),this.welcomePromise=null},this.ws.onclose=()=>{this.subscriptions.forEach(s=>s._notifyDisconnected())}})}disconnect(){this.ws&&(this.ws.onclose=null,this.ws.close(),this.ws=null),this.subscriptions.forEach(t=>t._notifyDisconnected()),this.subscriptions.clear()}subscribe(t){const e=JSON.stringify(t),s=new p(e,n=>{this.send({command:"message",identifier:e,data:JSON.stringify(n)})});return this.subscriptions.set(e,s),this.send({command:"subscribe",identifier:e}),s}subscribeAsync(t){const e=this.subscribe(t),s=e.identifier;return new Promise((n,i)=>{this.pendingSubscriptions.set(s,{resolve:()=>n(e),reject:i}),setTimeout(()=>{this.pendingSubscriptions.has(s)&&(this.pendingSubscriptions.delete(s),i(new Error(`Subscription timeout for ${s}`)))},1e4)})}unsubscribe(t){this.send({command:"unsubscribe",identifier:t}),this.subscriptions.delete(t)}perform(t,e,s={}){this.send({command:"message",identifier:t,data:JSON.stringify({action:e,...s})})}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}send(t){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(t))}handleMessage(t){let e;try{e=JSON.parse(t.data)}catch{return}switch(e.type){case"welcome":this.welcomePromise?.resolve(),this.welcomePromise=null;break;case"ping":break;case"confirm_subscription":{const s=e.identifier;this.subscriptions.get(s)?._notifyConnected();const i=this.pendingSubscriptions.get(s);i&&(i.resolve(),this.pendingSubscriptions.delete(s));break}case"reject_subscription":{const s=e.identifier;this.subscriptions.get(s)?._notifyRejected(),this.subscriptions.delete(s);const i=this.pendingSubscriptions.get(s);i&&(i.reject(new Error(`Subscription rejected: ${s}`)),this.pendingSubscriptions.delete(s));break}case"disconnect":this.subscriptions.forEach(s=>s._notifyDisconnected());break;default:{e.identifier&&e.message!==void 0&&this.subscriptions.get(e.identifier)?._notifyReceived(e.message);break}}}}class u{handlers=new Map;on(t,e){return this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t).add(e),()=>this.off(t,e)}off(t,e){this.handlers.get(t)?.delete(e)}emit(t,e){this.handlers.get(t)?.forEach(s=>{try{s(e)}catch(n){console.error(`Error in event handler for "${t}":`,n)}})}removeAllListeners(){this.handlers.clear()}}const v=1e3,w=10,y=400,E=600,T="#6366f1",I=12,A="system-ui, -apple-system, sans-serif",k="Type a message...",C="bottom-right",M="light",U={x:20,y:20},d="aikaara_conversation_id";class f extends u{client;config;state="disconnected";reconnectAttempt=0;reconnectTimer=null;constructor(t){super(),this.config=t;const e=this.buildWsUrl(t.baseUrl,t.userToken);this.client=new l(e)}async connect(){this.setState("connecting");try{await this.client.connect(),this.setState("connected"),this.reconnectAttempt=0}catch(t){if(this.setState("disconnected"),this.config.reconnect!==!1)this.scheduleReconnect();else throw t}}async disconnect(){this.clearReconnectTimer(),this.client.disconnect(),this.setState("disconnected")}subscribeToConversation(t){return this.client.subscribeAsync({channel:"ConversationChannel",conversation_id:t})}sendMessage(t,e){const s=JSON.stringify({channel:"ConversationChannel",conversation_id:t});this.client.perform(s,"send_message",{content:e})}sendUserEvent(t,e,s,n){const i=JSON.stringify({channel:"ConversationChannel",conversation_id:t});this.client.perform(i,"send_user_event",{event_key:e,...s&&{value:s},...n&&{source:n}})}get connectionState(){return this.state}setState(t){this.state!==t&&(this.state=t,this.emit("connection:state",t))}scheduleReconnect(){const t=this.config.maxReconnectAttempts??w;if(this.reconnectAttempt>=t){this.emit("error",new Error("Max reconnection attempts reached"));return}this.setState("reconnecting");const s=(this.config.reconnectInterval??v)*Math.pow(2,this.reconnectAttempt);this.reconnectAttempt++,this.reconnectTimer=setTimeout(async()=>{try{const n=this.buildWsUrl(this.config.baseUrl,this.config.userToken);this.client=new l(n),await this.connect()}catch{}},s)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}buildWsUrl(t,e){if(this.config.wsUrl){const n=this.config.wsUrl.includes("?")?"&":"?";return`${this.config.wsUrl}${n}token=${e}`}return`${t.replace(/^http/,"ws")}/cable?token=${e}`}}class _{baseUrl;apiKey;userToken;constructor(t,e,s){this.baseUrl=t,this.userToken=e,this.apiKey=s}async createConversation(t){const e={conversation:{...t.extUid&&{ext_uid:t.extUid},...t.systemPromptId&&{system_prompt_id:t.systemPromptId},...t.channel&&{channel:t.channel},...t.title&&{title:t.title}}};return this.request("POST","/api/v1/conversations",e)}async getMessages(t){return(await this.request("GET",`/api/v1/conversations/${t}/messages`)).map(this.mapMessage)}mapMessage(t){return{id:String(t.id),conversationId:String(t.conversation_id),role:t.role,content:t.content||"",toolCalls:t.tool_calls?.map(e=>({id:e.id,type:e.type,function:e.function})),toolCallResults:t.tool_call_results,tokensInput:t.tokens_input,tokensOutput:t.tokens_output,metadata:t.metadata,createdAt:t.created_at,status:"complete"}}async request(t,e,s){const n={"Content-Type":"application/json",Accept:"application/json"};this.apiKey&&(n["X-Api-Key"]=this.apiKey);const i=`${this.baseUrl}${e}`,g={method:t,headers:n};s&&(g.body=JSON.stringify(s));const c=await fetch(i,g);if(!c.ok){const a=await c.text();let h;try{const m=JSON.parse(a);h=m.error||m.message||a}catch{h=a}throw new Error(`API error ${c.status}: ${h}`)}const r=await c.json();if(r&&typeof r=="object"&&"success"in r){if(!r.success)throw new Error(`API error: ${r.message||"Request failed"}`);return r.data}return r}}class b{_messages=[];optimisticCounter=0;get messages(){return[...this._messages]}addOptimistic(t,e,s){const n={id:`optimistic_${++this.optimisticCounter}`,conversationId:s,role:t,content:e,createdAt:new Date().toISOString(),status:"sending"};return this._messages.push(n),n}confirmOptimistic(t){const e=this._messages.find(s=>s.id===t);e&&(e.status="sent")}addStreamingMessage(t){const e={id:`streaming_${Date.now()}`,conversationId:t,role:"assistant",content:"",createdAt:new Date().toISOString(),status:"streaming"};return this._messages.push(e),e}updateStreaming(t){const e=this._messages.findLast(s=>s.status==="streaming");e&&(e.content=t)}appendToStreaming(t){const e=this._messages.findLast(s=>s.status==="streaming");e&&(e.content+=t)}get streamingContent(){return this._messages.findLast(e=>e.status==="streaming")?.content||""}finalizeStreaming(t){const e=this._messages.findLast(s=>s.status==="streaming");return e&&(e.status="complete",t&&(e.tokensInput=t.tokensInput,e.tokensOutput=t.tokensOutput)),e}addMessage(t){this._messages.push(t)}setMessages(t){this._messages=[...t]}clear(){this._messages=[]}}class S{_conversationId;persist;constructor(t,e=!0){this.persist=e,this._conversationId=t||this.loadFromStorage()}get conversationId(){return this._conversationId}set conversationId(t){this._conversationId=t,this.persist&&t&&this.saveToStorage(t)}clear(){if(this._conversationId=null,this.persist)try{localStorage.removeItem(d)}catch{}}loadFromStorage(){if(!this.persist)return null;try{return localStorage.getItem(d)}catch{return null}}saveToStorage(t){try{localStorage.setItem(d,t)}catch{}}}class O extends u{connection;api;messageStore;conversationManager;subscription=null;config;constructor(t){super(),this.config=t,this.connection=new f(t),this.api=new _(t.baseUrl,t.userToken,t.apiKey),this.messageStore=new b,this.conversationManager=new S(t.conversationId),this.connection.on("connection:state",e=>{this.emit("connection:state",e),this.config.onConnectionStateChange?.(e)}),this.connection.on("error",e=>{this.emit("error",e),this.config.onError?.(e)})}async connect(){if(await this.connection.connect(),!this.conversationManager.conversationId){const t=await this.api.createConversation({systemPromptId:this.config.systemPromptId,channel:this.config.channel||"widget",extUid:this.config.extUid});this.conversationManager.conversationId=String(t.id)}this.subscription=await this.connection.subscribeToConversation(this.conversationManager.conversationId),this.subscription.onReceived(t=>{this.handleBroadcast(t)}),await this.loadHistory()}async sendMessage(t){const e=this.conversationManager.conversationId;if(!e)throw new Error("No active conversation");const s=this.messageStore.addOptimistic("user",t,e);this.emit("message:sent",s),this.config.onMessage?.(s),this.connection.sendMessage(e,t)}async sendUserEvent(t,e,s){const n=this.conversationManager.conversationId;if(!n)throw new Error("No active conversation");this.connection.sendUserEvent(n,t,e,s)}async loadHistory(){const t=this.conversationManager.conversationId;if(!t)return[];try{const e=await this.api.getMessages(t);return this.messageStore.setMessages(e),e}catch{return[]}}get messages(){return this.messageStore.messages}get conversationId(){return this.conversationManager.conversationId}get isConnected(){return this.connection.connectionState==="connected"}async disconnect(){this.subscription&&(this.subscription=null),await this.connection.disconnect()}handleBroadcast(t){const e=this.conversationManager.conversationId;switch(t.type){case"status":{const s=t.status;this.emit("status",s),this.config.onStatusChange?.(s),s==="processing"&&this.emit("typing:start",void 0);break}case"error":{const s=new Error(t.message||"Unknown error");this.emit("error",s),this.config.onError?.(s);break}case"message_start":{if(t.role==="assistant"){const s=this.messageStore.addStreamingMessage(e);this.emit("stream:start",{messageId:s.id}),this.emit("typing:start",void 0)}break}case"message_update":{const s=t.delta||"",n=t.content||"";n?this.messageStore.updateStreaming(n):s&&this.messageStore.appendToStreaming(s);const i=this.messageStore.streamingContent;this.emit("stream:update",{delta:s,content:i}),this.config.onStreamUpdate?.(s,i);break}case"message_end":{const s=t.usage,n=this.messageStore.finalizeStreaming(s?{tokensInput:s.tokens_input||0,tokensOutput:s.tokens_output||0}:void 0);this.emit("typing:stop",void 0),n&&(this.emit("stream:end",{messageId:n.id,usage:s?{tokensInput:s.tokens_input||0,tokensOutput:s.tokens_output||0}:void 0}),this.emit("message:received",n),this.config.onMessage?.(n));break}case"message_queued":{const s=this.messageStore.messages.findLast(n=>n.status==="sending");s&&this.messageStore.confirmOptimistic(s.id);break}case"tool_execution_start":case"tool_execution_update":case"tool_execution_end":case"agent_start":case"agent_end":case"turn_start":case"turn_end":case"auto_retry_start":case"auto_retry_end":case"cancelled":this.emit("status",t.type);break}}}exports.ActionCableClient=l;exports.AikaaraChatClient=O;exports.ApiClient=_;exports.ChannelSubscription=p;exports.ConnectionManager=f;exports.ConversationManager=S;exports.DEFAULT_BORDER_RADIUS=I;exports.DEFAULT_FONT_FAMILY=A;exports.DEFAULT_OFFSET=U;exports.DEFAULT_PLACEHOLDER=k;exports.DEFAULT_POSITION=C;exports.DEFAULT_PRIMARY_COLOR=T;exports.DEFAULT_THEME=M;exports.DEFAULT_WIDGET_HEIGHT=E;exports.DEFAULT_WIDGET_WIDTH=y;exports.EventEmitter=u;exports.MessageStore=b;
|