@xpert-ai/chatkit-web-shared 0.0.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/LICENSE +201 -0
- package/README.md +2 -0
- package/dist/index.d.ts +205 -0
- package/dist/index.js +819 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,819 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
var _a, _b;
|
|
5
|
+
class EventEmitter {
|
|
6
|
+
constructor() {
|
|
7
|
+
__publicField(this, "callbacks", /* @__PURE__ */ new Map());
|
|
8
|
+
}
|
|
9
|
+
on(event, callback) {
|
|
10
|
+
if (!this.callbacks.has(event)) {
|
|
11
|
+
this.callbacks.set(event, /* @__PURE__ */ new Set());
|
|
12
|
+
}
|
|
13
|
+
this.callbacks.get(event).add(callback);
|
|
14
|
+
}
|
|
15
|
+
emit(event, ...args) {
|
|
16
|
+
var _a2;
|
|
17
|
+
const data = args[0];
|
|
18
|
+
(_a2 = this.callbacks.get(event)) == null ? void 0 : _a2.forEach((callback) => callback(data));
|
|
19
|
+
}
|
|
20
|
+
off(event, callback) {
|
|
21
|
+
var _a2;
|
|
22
|
+
if (!callback) {
|
|
23
|
+
this.callbacks.delete(event);
|
|
24
|
+
} else {
|
|
25
|
+
(_a2 = this.callbacks.get(event)) == null ? void 0 : _a2.delete(callback);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
allOff() {
|
|
29
|
+
this.callbacks.clear();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function getBytes(stream, onChunk) {
|
|
33
|
+
const reader = stream.getReader();
|
|
34
|
+
let result;
|
|
35
|
+
while (!(result = await reader.read()).done) {
|
|
36
|
+
onChunk(result.value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function getLines(onLine) {
|
|
40
|
+
let buffer;
|
|
41
|
+
let position;
|
|
42
|
+
let fieldLength;
|
|
43
|
+
let discardTrailingNewline = false;
|
|
44
|
+
return function onChunk(arr) {
|
|
45
|
+
if (buffer === void 0) {
|
|
46
|
+
buffer = arr;
|
|
47
|
+
position = 0;
|
|
48
|
+
fieldLength = -1;
|
|
49
|
+
} else {
|
|
50
|
+
buffer = concat(buffer, arr);
|
|
51
|
+
}
|
|
52
|
+
const bufLength = buffer.length;
|
|
53
|
+
let lineStart = 0;
|
|
54
|
+
while (position < bufLength) {
|
|
55
|
+
if (discardTrailingNewline) {
|
|
56
|
+
if (buffer[position] === 10) {
|
|
57
|
+
lineStart = ++position;
|
|
58
|
+
}
|
|
59
|
+
discardTrailingNewline = false;
|
|
60
|
+
}
|
|
61
|
+
let lineEnd = -1;
|
|
62
|
+
for (; position < bufLength && lineEnd === -1; ++position) {
|
|
63
|
+
switch (buffer[position]) {
|
|
64
|
+
case 58:
|
|
65
|
+
if (fieldLength === -1) {
|
|
66
|
+
fieldLength = position - lineStart;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case 13:
|
|
70
|
+
discardTrailingNewline = true;
|
|
71
|
+
case 10:
|
|
72
|
+
lineEnd = position;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (lineEnd === -1) {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
onLine(buffer.subarray(lineStart, lineEnd), fieldLength);
|
|
80
|
+
lineStart = position;
|
|
81
|
+
fieldLength = -1;
|
|
82
|
+
}
|
|
83
|
+
if (lineStart === bufLength) {
|
|
84
|
+
buffer = void 0;
|
|
85
|
+
} else if (lineStart !== 0) {
|
|
86
|
+
buffer = buffer.subarray(lineStart);
|
|
87
|
+
position -= lineStart;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function getMessages(onId, onRetry, onMessage) {
|
|
92
|
+
let message = newMessage();
|
|
93
|
+
const decoder = new TextDecoder();
|
|
94
|
+
return function onLine(line, fieldLength) {
|
|
95
|
+
if (line.length === 0) {
|
|
96
|
+
onMessage === null || onMessage === void 0 ? void 0 : onMessage(message);
|
|
97
|
+
message = newMessage();
|
|
98
|
+
} else if (fieldLength > 0) {
|
|
99
|
+
const field = decoder.decode(line.subarray(0, fieldLength));
|
|
100
|
+
const valueOffset = fieldLength + (line[fieldLength + 1] === 32 ? 2 : 1);
|
|
101
|
+
const value = decoder.decode(line.subarray(valueOffset));
|
|
102
|
+
switch (field) {
|
|
103
|
+
case "data":
|
|
104
|
+
message.data = message.data ? message.data + "\n" + value : value;
|
|
105
|
+
break;
|
|
106
|
+
case "event":
|
|
107
|
+
message.event = value;
|
|
108
|
+
break;
|
|
109
|
+
case "id":
|
|
110
|
+
onId(message.id = value);
|
|
111
|
+
break;
|
|
112
|
+
case "retry":
|
|
113
|
+
const retry = parseInt(value, 10);
|
|
114
|
+
if (!isNaN(retry)) {
|
|
115
|
+
onRetry(message.retry = retry);
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function concat(a, b) {
|
|
123
|
+
const res = new Uint8Array(a.length + b.length);
|
|
124
|
+
res.set(a);
|
|
125
|
+
res.set(b, a.length);
|
|
126
|
+
return res;
|
|
127
|
+
}
|
|
128
|
+
function newMessage() {
|
|
129
|
+
return {
|
|
130
|
+
data: "",
|
|
131
|
+
event: "",
|
|
132
|
+
id: "",
|
|
133
|
+
retry: void 0
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
var __rest = function(s, e) {
|
|
137
|
+
var t = {};
|
|
138
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
139
|
+
t[p] = s[p];
|
|
140
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
141
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
142
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
143
|
+
t[p[i]] = s[p[i]];
|
|
144
|
+
}
|
|
145
|
+
return t;
|
|
146
|
+
};
|
|
147
|
+
const EventStreamContentType = "text/event-stream";
|
|
148
|
+
const DefaultRetryInterval = 1e3;
|
|
149
|
+
const LastEventId = "last-event-id";
|
|
150
|
+
function fetchEventSource(input, _a2) {
|
|
151
|
+
var { signal: inputSignal, headers: inputHeaders, onopen: inputOnOpen, onmessage, onclose, onerror, openWhenHidden, fetch: inputFetch } = _a2, rest = __rest(_a2, ["signal", "headers", "onopen", "onmessage", "onclose", "onerror", "openWhenHidden", "fetch"]);
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const headers = Object.assign({}, inputHeaders);
|
|
154
|
+
if (!headers.accept) {
|
|
155
|
+
headers.accept = EventStreamContentType;
|
|
156
|
+
}
|
|
157
|
+
let curRequestController;
|
|
158
|
+
function onVisibilityChange() {
|
|
159
|
+
curRequestController.abort();
|
|
160
|
+
if (!document.hidden) {
|
|
161
|
+
create();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!openWhenHidden) {
|
|
165
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
166
|
+
}
|
|
167
|
+
let retryInterval = DefaultRetryInterval;
|
|
168
|
+
let retryTimer = 0;
|
|
169
|
+
function dispose() {
|
|
170
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
171
|
+
window.clearTimeout(retryTimer);
|
|
172
|
+
curRequestController.abort();
|
|
173
|
+
}
|
|
174
|
+
inputSignal === null || inputSignal === void 0 ? void 0 : inputSignal.addEventListener("abort", () => {
|
|
175
|
+
dispose();
|
|
176
|
+
resolve();
|
|
177
|
+
});
|
|
178
|
+
const fetch = inputFetch !== null && inputFetch !== void 0 ? inputFetch : window.fetch;
|
|
179
|
+
const onopen = inputOnOpen !== null && inputOnOpen !== void 0 ? inputOnOpen : defaultOnOpen;
|
|
180
|
+
async function create() {
|
|
181
|
+
var _a3;
|
|
182
|
+
curRequestController = new AbortController();
|
|
183
|
+
try {
|
|
184
|
+
const response = await fetch(input, Object.assign(Object.assign({}, rest), { headers, signal: curRequestController.signal }));
|
|
185
|
+
await onopen(response);
|
|
186
|
+
await getBytes(response.body, getLines(getMessages((id) => {
|
|
187
|
+
if (id) {
|
|
188
|
+
headers[LastEventId] = id;
|
|
189
|
+
} else {
|
|
190
|
+
delete headers[LastEventId];
|
|
191
|
+
}
|
|
192
|
+
}, (retry) => {
|
|
193
|
+
retryInterval = retry;
|
|
194
|
+
}, onmessage)));
|
|
195
|
+
onclose === null || onclose === void 0 ? void 0 : onclose();
|
|
196
|
+
dispose();
|
|
197
|
+
resolve();
|
|
198
|
+
} catch (err) {
|
|
199
|
+
if (!curRequestController.signal.aborted) {
|
|
200
|
+
try {
|
|
201
|
+
const interval = (_a3 = onerror === null || onerror === void 0 ? void 0 : onerror(err)) !== null && _a3 !== void 0 ? _a3 : retryInterval;
|
|
202
|
+
window.clearTimeout(retryTimer);
|
|
203
|
+
retryTimer = window.setTimeout(create, interval);
|
|
204
|
+
} catch (innerErr) {
|
|
205
|
+
dispose();
|
|
206
|
+
reject(innerErr);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
create();
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
function defaultOnOpen(response) {
|
|
215
|
+
const contentType = response.headers.get("content-type");
|
|
216
|
+
if (!(contentType === null || contentType === void 0 ? void 0 : contentType.startsWith(EventStreamContentType))) {
|
|
217
|
+
throw new Error(`Expected content-type to be ${EventStreamContentType}, Actual: ${contentType}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const FRAME_SAFE_ERROR_KEY = "__chatkit_error__";
|
|
221
|
+
class HttpError extends Error {
|
|
222
|
+
constructor(message, res, metadata) {
|
|
223
|
+
super(message);
|
|
224
|
+
__publicField(this, "status");
|
|
225
|
+
__publicField(this, "statusText");
|
|
226
|
+
__publicField(this, "metadata");
|
|
227
|
+
this.name = "HttpError";
|
|
228
|
+
this.statusText = res.statusText;
|
|
229
|
+
this.status = res.status;
|
|
230
|
+
this.metadata = metadata;
|
|
231
|
+
}
|
|
232
|
+
static fromPossibleFrameSafeError(error) {
|
|
233
|
+
if (error instanceof HttpError) {
|
|
234
|
+
return error;
|
|
235
|
+
}
|
|
236
|
+
if (error && typeof error === "object" && FRAME_SAFE_ERROR_KEY in error && error[FRAME_SAFE_ERROR_KEY] === "HttpError") {
|
|
237
|
+
const safeError = error;
|
|
238
|
+
const parsedError = new HttpError(
|
|
239
|
+
safeError.message,
|
|
240
|
+
{
|
|
241
|
+
status: safeError.status,
|
|
242
|
+
statusText: safeError.statusText
|
|
243
|
+
},
|
|
244
|
+
safeError.metadata
|
|
245
|
+
);
|
|
246
|
+
parsedError.stack = safeError.stack;
|
|
247
|
+
return parsedError;
|
|
248
|
+
}
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
_a = FRAME_SAFE_ERROR_KEY;
|
|
253
|
+
const _FrameSafeHttpError = class _FrameSafeHttpError {
|
|
254
|
+
constructor(message, res, metadata) {
|
|
255
|
+
__publicField(this, _a, "HttpError");
|
|
256
|
+
__publicField(this, "message");
|
|
257
|
+
__publicField(this, "stack");
|
|
258
|
+
__publicField(this, "status");
|
|
259
|
+
__publicField(this, "statusText");
|
|
260
|
+
__publicField(this, "metadata");
|
|
261
|
+
this.message = message;
|
|
262
|
+
this.stack = new Error(message).stack;
|
|
263
|
+
this.status = res.status;
|
|
264
|
+
this.statusText = res.statusText;
|
|
265
|
+
this.metadata = metadata;
|
|
266
|
+
}
|
|
267
|
+
static fromHttpError(error) {
|
|
268
|
+
return new _FrameSafeHttpError(
|
|
269
|
+
error.message,
|
|
270
|
+
{
|
|
271
|
+
status: error.status,
|
|
272
|
+
statusText: error.statusText
|
|
273
|
+
},
|
|
274
|
+
error.metadata
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
let FrameSafeHttpError = _FrameSafeHttpError;
|
|
279
|
+
const BASE_RETRY_DELAY_MS = 1e3;
|
|
280
|
+
const MAX_RETRY_DELAY_MS = 1e4;
|
|
281
|
+
const MAX_RETRY_ATTEMPTS = 5;
|
|
282
|
+
const nextDelay = (attempt, maxRetryDelay = MAX_RETRY_DELAY_MS, baseDelayMs = BASE_RETRY_DELAY_MS) => {
|
|
283
|
+
const max = Math.min(maxRetryDelay, baseDelayMs * 2 ** attempt);
|
|
284
|
+
return Math.floor(max * (0.5 + Math.random() * 0.5));
|
|
285
|
+
};
|
|
286
|
+
class RetryableError extends Error {
|
|
287
|
+
constructor(cause) {
|
|
288
|
+
super();
|
|
289
|
+
this.cause = cause;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const fetchEventSourceWithRetry = async (url, params) => {
|
|
293
|
+
let retryAttempt = 0;
|
|
294
|
+
const { onopen, ...restParams } = params;
|
|
295
|
+
await fetchEventSource(url, {
|
|
296
|
+
...restParams,
|
|
297
|
+
onopen: async (res) => {
|
|
298
|
+
var _a2;
|
|
299
|
+
onopen == null ? void 0 : onopen(res);
|
|
300
|
+
if (res.ok && ((_a2 = res.headers.get("content-type")) == null ? void 0 : _a2.startsWith("text/event-stream"))) {
|
|
301
|
+
retryAttempt = 0;
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const httpError = new FrameSafeHttpError(`Streaming failed: ${res.statusText}`, res);
|
|
305
|
+
if (res.status >= 400 && res.status < 500) {
|
|
306
|
+
throw httpError;
|
|
307
|
+
} else {
|
|
308
|
+
throw new RetryableError(httpError);
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
onerror: (error) => {
|
|
312
|
+
if (error instanceof RetryableError) {
|
|
313
|
+
if (retryAttempt >= MAX_RETRY_ATTEMPTS) {
|
|
314
|
+
throw error.cause;
|
|
315
|
+
}
|
|
316
|
+
retryAttempt += 1;
|
|
317
|
+
return nextDelay(retryAttempt);
|
|
318
|
+
}
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
let IntegrationError$1 = class IntegrationError extends Error {
|
|
324
|
+
constructor(message) {
|
|
325
|
+
super(message);
|
|
326
|
+
__publicField(this, "_name");
|
|
327
|
+
this.name = "IntegrationError";
|
|
328
|
+
this._name = this.name;
|
|
329
|
+
}
|
|
330
|
+
static fromPossibleFrameSafeError(error) {
|
|
331
|
+
if (error && typeof error === "object" && FRAME_SAFE_ERROR_KEY in error && error[FRAME_SAFE_ERROR_KEY] === "IntegrationError") {
|
|
332
|
+
const safeError = error;
|
|
333
|
+
const parsedError = new IntegrationError(safeError.message);
|
|
334
|
+
parsedError.stack = safeError.stack;
|
|
335
|
+
return parsedError;
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
_b = FRAME_SAFE_ERROR_KEY;
|
|
341
|
+
class FrameSafeIntegrationError {
|
|
342
|
+
constructor(message) {
|
|
343
|
+
__publicField(this, _b, "IntegrationError");
|
|
344
|
+
__publicField(this, "message");
|
|
345
|
+
__publicField(this, "stack");
|
|
346
|
+
this.message = message;
|
|
347
|
+
this.stack = new Error(message).stack;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
class BaseMessenger {
|
|
351
|
+
constructor({
|
|
352
|
+
handlers,
|
|
353
|
+
target,
|
|
354
|
+
targetOrigin,
|
|
355
|
+
fetch = window.fetch
|
|
356
|
+
}) {
|
|
357
|
+
__publicField(this, "targetOrigin");
|
|
358
|
+
__publicField(this, "target");
|
|
359
|
+
__publicField(this, "commandHandlers");
|
|
360
|
+
__publicField(this, "_fetch");
|
|
361
|
+
__publicField(this, "emitter", new EventEmitter());
|
|
362
|
+
__publicField(this, "handlers", /* @__PURE__ */ new Map());
|
|
363
|
+
__publicField(this, "fetchEventSourceHandlers", /* @__PURE__ */ new Map());
|
|
364
|
+
__publicField(this, "abortControllers", /* @__PURE__ */ new Map());
|
|
365
|
+
__publicField(this, "commands", new Proxy(
|
|
366
|
+
{},
|
|
367
|
+
{
|
|
368
|
+
get: (_, command) => {
|
|
369
|
+
return (data, transfer) => {
|
|
370
|
+
return new Promise((resolve, reject) => {
|
|
371
|
+
const nonce = crypto.randomUUID();
|
|
372
|
+
this.handlers.set(nonce, { resolve, reject, stack: new Error().stack || "" });
|
|
373
|
+
this.sendMessage(
|
|
374
|
+
{
|
|
375
|
+
type: "command",
|
|
376
|
+
nonce,
|
|
377
|
+
command: `on${command.charAt(0).toUpperCase()}${command.slice(1)}`,
|
|
378
|
+
data
|
|
379
|
+
},
|
|
380
|
+
transfer
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
));
|
|
387
|
+
__publicField(this, "handleMessage", async (event) => {
|
|
388
|
+
var _a2, _b2, _c, _d;
|
|
389
|
+
console.log("Received message", event.data, event.origin, this.targetOrigin, event.source, this.target());
|
|
390
|
+
if (!event.data || event.data.__xpaiChatKit !== true || event.origin !== this.targetOrigin || event.source !== this.target()) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const data = event.data;
|
|
394
|
+
switch (data.type) {
|
|
395
|
+
case "event": {
|
|
396
|
+
this.emitter.emit(data.event, data.data);
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
case "fetch": {
|
|
400
|
+
try {
|
|
401
|
+
if (data.formData) {
|
|
402
|
+
const formData = new FormData();
|
|
403
|
+
for (const [key, value] of Object.entries(data.formData)) {
|
|
404
|
+
formData.append(key, value);
|
|
405
|
+
}
|
|
406
|
+
data.params.body = formData;
|
|
407
|
+
}
|
|
408
|
+
const controller = new AbortController();
|
|
409
|
+
this.abortControllers.set(data.nonce, controller);
|
|
410
|
+
data.params.signal = controller.signal;
|
|
411
|
+
const res = await this._fetch(data.url, data.params);
|
|
412
|
+
if (!res.ok) {
|
|
413
|
+
const message = await res.json().then((json2) => json2.message || res.statusText).catch(() => res.statusText);
|
|
414
|
+
throw new FrameSafeHttpError(message, res);
|
|
415
|
+
}
|
|
416
|
+
const json = await res.json().catch(() => ({}));
|
|
417
|
+
this.sendMessage({
|
|
418
|
+
type: "response",
|
|
419
|
+
response: json,
|
|
420
|
+
nonce: data.nonce
|
|
421
|
+
});
|
|
422
|
+
} catch (error) {
|
|
423
|
+
this.sendMessage({
|
|
424
|
+
type: "response",
|
|
425
|
+
error,
|
|
426
|
+
nonce: data.nonce
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
case "fetchEventSource": {
|
|
432
|
+
try {
|
|
433
|
+
const controller = new AbortController();
|
|
434
|
+
this.abortControllers.set(data.nonce, controller);
|
|
435
|
+
await fetchEventSourceWithRetry(data.url, {
|
|
436
|
+
...data.params,
|
|
437
|
+
signal: controller.signal,
|
|
438
|
+
fetch: this._fetch,
|
|
439
|
+
onmessage: (message) => {
|
|
440
|
+
this.sendMessage({
|
|
441
|
+
type: "fetchEventSourceMessage",
|
|
442
|
+
message,
|
|
443
|
+
nonce: data.nonce
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
this.sendMessage({
|
|
448
|
+
type: "response",
|
|
449
|
+
response: void 0,
|
|
450
|
+
nonce: data.nonce
|
|
451
|
+
});
|
|
452
|
+
} catch (error) {
|
|
453
|
+
this.sendMessage({
|
|
454
|
+
type: "response",
|
|
455
|
+
error,
|
|
456
|
+
nonce: data.nonce
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
case "command": {
|
|
462
|
+
console.log("Received command", data.command, data.data);
|
|
463
|
+
if (!this.canReceiveCommand(data.command)) {
|
|
464
|
+
this.sendMessage({
|
|
465
|
+
type: "response",
|
|
466
|
+
error: new FrameSafeIntegrationError(`Command ${data.command} not supported`),
|
|
467
|
+
nonce: data.nonce
|
|
468
|
+
});
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
try {
|
|
472
|
+
const response = await ((_b2 = (_a2 = this.commandHandlers)[data.command]) == null ? void 0 : _b2.call(_a2, data.data));
|
|
473
|
+
this.sendMessage({
|
|
474
|
+
type: "response",
|
|
475
|
+
response,
|
|
476
|
+
nonce: data.nonce
|
|
477
|
+
});
|
|
478
|
+
} catch (error) {
|
|
479
|
+
this.sendMessage({
|
|
480
|
+
type: "response",
|
|
481
|
+
error,
|
|
482
|
+
nonce: data.nonce
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
case "response": {
|
|
488
|
+
const handler = this.handlers.get(data.nonce);
|
|
489
|
+
if (!handler) {
|
|
490
|
+
console.error("No handler found for nonce", data.nonce);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (data.error) {
|
|
494
|
+
const integrationError = IntegrationError$1.fromPossibleFrameSafeError(data.error);
|
|
495
|
+
const httpError = HttpError.fromPossibleFrameSafeError(data.error);
|
|
496
|
+
if (integrationError) {
|
|
497
|
+
integrationError.stack = handler.stack;
|
|
498
|
+
handler.reject(integrationError);
|
|
499
|
+
} else if (httpError) {
|
|
500
|
+
handler.reject(httpError);
|
|
501
|
+
} else {
|
|
502
|
+
handler.reject(data.error);
|
|
503
|
+
}
|
|
504
|
+
} else {
|
|
505
|
+
handler.resolve(data.response);
|
|
506
|
+
}
|
|
507
|
+
this.handlers.delete(data.nonce);
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
case "fetchEventSourceMessage": {
|
|
511
|
+
const handler = this.fetchEventSourceHandlers.get(data.nonce);
|
|
512
|
+
if (!handler) {
|
|
513
|
+
console.error("No handler found for nonce", data.nonce);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
(_d = (_c = this.fetchEventSourceHandlers.get(data.nonce)) == null ? void 0 : _c.onmessage) == null ? void 0 : _d.call(_c, data.message);
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
case "abortSignal": {
|
|
520
|
+
const controller = this.abortControllers.get(data.nonce);
|
|
521
|
+
if (controller) {
|
|
522
|
+
controller.abort(data.reason);
|
|
523
|
+
this.abortControllers.delete(data.nonce);
|
|
524
|
+
}
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
this.commandHandlers = handlers;
|
|
530
|
+
this.target = target;
|
|
531
|
+
this.targetOrigin = targetOrigin;
|
|
532
|
+
this._fetch = (...args) => fetch(...args);
|
|
533
|
+
}
|
|
534
|
+
sendMessage(data, transfer) {
|
|
535
|
+
var _a2;
|
|
536
|
+
const message = {
|
|
537
|
+
__xpaiChatKit: true,
|
|
538
|
+
...data
|
|
539
|
+
};
|
|
540
|
+
(_a2 = this.target()) == null ? void 0 : _a2.postMessage(message, this.targetOrigin, transfer);
|
|
541
|
+
}
|
|
542
|
+
connect() {
|
|
543
|
+
window.addEventListener("message", this.handleMessage);
|
|
544
|
+
}
|
|
545
|
+
disconnect() {
|
|
546
|
+
window.removeEventListener("message", this.handleMessage);
|
|
547
|
+
}
|
|
548
|
+
fetch(url, params) {
|
|
549
|
+
return new Promise((resolve, reject) => {
|
|
550
|
+
const nonce = crypto.randomUUID();
|
|
551
|
+
this.handlers.set(nonce, { resolve, reject, stack: new Error().stack || "" });
|
|
552
|
+
let formData;
|
|
553
|
+
if (params.body instanceof FormData) {
|
|
554
|
+
formData = {};
|
|
555
|
+
for (const [key, value] of params.body.entries()) {
|
|
556
|
+
formData[key] = value;
|
|
557
|
+
}
|
|
558
|
+
params.body = void 0;
|
|
559
|
+
}
|
|
560
|
+
if (params.signal) {
|
|
561
|
+
params.signal.addEventListener("abort", () => {
|
|
562
|
+
var _a2;
|
|
563
|
+
this.sendMessage({
|
|
564
|
+
type: "abortSignal",
|
|
565
|
+
nonce,
|
|
566
|
+
reason: (_a2 = params.signal) == null ? void 0 : _a2.reason
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
params.signal = void 0;
|
|
570
|
+
}
|
|
571
|
+
this.sendMessage({ type: "fetch", nonce, params, formData, url });
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
// Supporting onopen would require a good way for us to serialize the Response object
|
|
575
|
+
// across the iframe boundary, which is not trivial and also not really necessary.
|
|
576
|
+
fetchEventSource(url, params) {
|
|
577
|
+
return new Promise((resolve, reject) => {
|
|
578
|
+
const { onmessage, signal, ...rest } = params;
|
|
579
|
+
const nonce = crypto.randomUUID();
|
|
580
|
+
this.handlers.set(nonce, { resolve, reject, stack: new Error().stack || "" });
|
|
581
|
+
this.fetchEventSourceHandlers.set(nonce, {
|
|
582
|
+
onmessage
|
|
583
|
+
});
|
|
584
|
+
if (signal) {
|
|
585
|
+
signal.addEventListener("abort", () => {
|
|
586
|
+
this.sendMessage({
|
|
587
|
+
type: "abortSignal",
|
|
588
|
+
nonce,
|
|
589
|
+
reason: signal.reason
|
|
590
|
+
});
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
this.sendMessage({ type: "fetchEventSource", nonce, params: rest, url });
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
emit(...[event, data, transfer]) {
|
|
597
|
+
this.sendMessage(
|
|
598
|
+
{
|
|
599
|
+
type: "event",
|
|
600
|
+
event,
|
|
601
|
+
data
|
|
602
|
+
},
|
|
603
|
+
transfer
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
on(...[event, callback]) {
|
|
607
|
+
this.emitter.on(event, callback);
|
|
608
|
+
}
|
|
609
|
+
destroy() {
|
|
610
|
+
window.removeEventListener("message", this.handleMessage);
|
|
611
|
+
this.emitter.allOff();
|
|
612
|
+
this.handlers.clear();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
const toUrlBase64 = (bin) => btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
616
|
+
const fromUrlBase64 = (b64) => atob(b64.replace(/-/g, "+").replace(/_/g, "/"));
|
|
617
|
+
const encodeBase64 = (value) => {
|
|
618
|
+
if (value === void 0) {
|
|
619
|
+
throw new TypeError(
|
|
620
|
+
"encodeBase64: `undefined` cannot be encoded to valid JSON. Pass null instead."
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
const json = JSON.stringify(value);
|
|
624
|
+
const bytes = new TextEncoder().encode(json);
|
|
625
|
+
let bin = "";
|
|
626
|
+
for (const b of bytes) bin += String.fromCharCode(b);
|
|
627
|
+
return toUrlBase64(bin);
|
|
628
|
+
};
|
|
629
|
+
const decodeBase64 = (b64) => {
|
|
630
|
+
const bin = fromUrlBase64(b64);
|
|
631
|
+
const bytes = Uint8Array.from(bin, (c) => c.charCodeAt(0));
|
|
632
|
+
const json = new TextDecoder().decode(bytes);
|
|
633
|
+
return JSON.parse(json);
|
|
634
|
+
};
|
|
635
|
+
class IntegrationError2 extends Error {
|
|
636
|
+
}
|
|
637
|
+
function fromPossibleFrameSafeError(err) {
|
|
638
|
+
return err.message;
|
|
639
|
+
}
|
|
640
|
+
const BASE_CAPABILITY_ALLOWLIST = [
|
|
641
|
+
// commands
|
|
642
|
+
"command.setOptions",
|
|
643
|
+
"command.sendUserMessage",
|
|
644
|
+
"command.setComposerValue",
|
|
645
|
+
"command.setThreadId",
|
|
646
|
+
"command.focusComposer",
|
|
647
|
+
"command.fetchUpdates",
|
|
648
|
+
"command.sendCustomAction",
|
|
649
|
+
"command.showHistory",
|
|
650
|
+
"command.hideHistory",
|
|
651
|
+
// events
|
|
652
|
+
"event.ready",
|
|
653
|
+
"event.error",
|
|
654
|
+
"event.log",
|
|
655
|
+
"event.response.start",
|
|
656
|
+
"event.response.end",
|
|
657
|
+
"event.response.stop",
|
|
658
|
+
"event.thread.change",
|
|
659
|
+
"event.tool.change",
|
|
660
|
+
"event.thread.load.start",
|
|
661
|
+
"event.thread.load.end",
|
|
662
|
+
"event.deeplink",
|
|
663
|
+
"event.effect",
|
|
664
|
+
// errors
|
|
665
|
+
"error.StreamError",
|
|
666
|
+
"error.StreamEventParsingError",
|
|
667
|
+
"error.WidgetItemError",
|
|
668
|
+
"error.InitialThreadLoadError",
|
|
669
|
+
"error.FileAttachmentError",
|
|
670
|
+
"error.HistoryViewError",
|
|
671
|
+
"error.FatalAppError",
|
|
672
|
+
"error.IntegrationError",
|
|
673
|
+
"error.EntitySearchError",
|
|
674
|
+
"error.DomainVerificationRequestError",
|
|
675
|
+
// backend
|
|
676
|
+
"backend.threads.get_by_id",
|
|
677
|
+
"backend.threads.list",
|
|
678
|
+
"backend.threads.update",
|
|
679
|
+
"backend.threads.delete",
|
|
680
|
+
"backend.threads.create",
|
|
681
|
+
"backend.threads.add_user_message",
|
|
682
|
+
"backend.threads.add_client_tool_output",
|
|
683
|
+
"backend.threads.retry_after_item",
|
|
684
|
+
"backend.threads.custom_action",
|
|
685
|
+
"backend.attachments.create",
|
|
686
|
+
"backend.attachments.get_preview",
|
|
687
|
+
"backend.attachments.delete",
|
|
688
|
+
"backend.items.list",
|
|
689
|
+
"backend.items.feedback",
|
|
690
|
+
// thread item types
|
|
691
|
+
"thread.item.generated_image",
|
|
692
|
+
"thread.item.user_message",
|
|
693
|
+
"thread.item.assistant_message",
|
|
694
|
+
"thread.item.client_tool_call",
|
|
695
|
+
"thread.item.widget",
|
|
696
|
+
"thread.item.task",
|
|
697
|
+
"thread.item.workflow",
|
|
698
|
+
"thread.item.end_of_turn",
|
|
699
|
+
"thread.item.image_generation",
|
|
700
|
+
// widgets
|
|
701
|
+
"widget.Basic",
|
|
702
|
+
"widget.Card",
|
|
703
|
+
"widget.ListView",
|
|
704
|
+
"widget.ListViewItem",
|
|
705
|
+
"widget.Badge",
|
|
706
|
+
"widget.Box",
|
|
707
|
+
"widget.Row",
|
|
708
|
+
"widget.Col",
|
|
709
|
+
"widget.Button",
|
|
710
|
+
"widget.Caption",
|
|
711
|
+
"widget.Chart",
|
|
712
|
+
"widget.Checkbox",
|
|
713
|
+
"widget.DatePicker",
|
|
714
|
+
"widget.Divider",
|
|
715
|
+
"widget.Form",
|
|
716
|
+
"widget.Icon",
|
|
717
|
+
"widget.Image",
|
|
718
|
+
"widget.Input",
|
|
719
|
+
"widget.Label",
|
|
720
|
+
"widget.Markdown",
|
|
721
|
+
"widget.RadioGroup",
|
|
722
|
+
"widget.Select",
|
|
723
|
+
"widget.Spacer",
|
|
724
|
+
"widget.Text",
|
|
725
|
+
"widget.Textarea",
|
|
726
|
+
"widget.Title",
|
|
727
|
+
"widget.Transition"
|
|
728
|
+
];
|
|
729
|
+
const BASE_CAPABILITY_DENYLIST = [
|
|
730
|
+
// --- commands
|
|
731
|
+
"command.shareThread",
|
|
732
|
+
"command.setTrainingOptOut",
|
|
733
|
+
// --- events
|
|
734
|
+
"event.thread.restore",
|
|
735
|
+
"event.message.share",
|
|
736
|
+
"event.image.download",
|
|
737
|
+
"event.history.open",
|
|
738
|
+
"event.history.close",
|
|
739
|
+
"event.log.chatgpt",
|
|
740
|
+
// --- errors
|
|
741
|
+
// These errors considered internal and are not exposed to the user by default.
|
|
742
|
+
"error.HttpError",
|
|
743
|
+
"error.NetworkError",
|
|
744
|
+
"error.UnhandledError",
|
|
745
|
+
"error.UnhandledPromiseRejectionError",
|
|
746
|
+
"error.StreamEventHandlingError",
|
|
747
|
+
"error.StreamStopError",
|
|
748
|
+
"error.ThreadRenderingError",
|
|
749
|
+
"error.IntlError",
|
|
750
|
+
"error.AppError",
|
|
751
|
+
// --- backend
|
|
752
|
+
"backend.threads.stop",
|
|
753
|
+
"backend.threads.share",
|
|
754
|
+
"backend.threads.create_from_shared",
|
|
755
|
+
"backend.threads.init",
|
|
756
|
+
"backend.attachments.process",
|
|
757
|
+
// widgets
|
|
758
|
+
"widget.CardCarousel",
|
|
759
|
+
"widget.Favicon",
|
|
760
|
+
"widget.CardLinkItem",
|
|
761
|
+
"widget.Map"
|
|
762
|
+
];
|
|
763
|
+
const PROFILE_TO_RULES = {
|
|
764
|
+
"chatkit": {
|
|
765
|
+
allow: [...BASE_CAPABILITY_ALLOWLIST, "thread.item.image_generation"],
|
|
766
|
+
deny: BASE_CAPABILITY_DENYLIST
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
const getCapabilities = (profile) => {
|
|
770
|
+
const rules = PROFILE_TO_RULES[profile];
|
|
771
|
+
const effective = new Set(rules.allow);
|
|
772
|
+
for (const capability of rules.deny ?? []) {
|
|
773
|
+
effective.delete(capability);
|
|
774
|
+
}
|
|
775
|
+
const commands = /* @__PURE__ */ new Set();
|
|
776
|
+
const events = /* @__PURE__ */ new Set();
|
|
777
|
+
const backend = /* @__PURE__ */ new Set();
|
|
778
|
+
const threadItems = /* @__PURE__ */ new Set();
|
|
779
|
+
const errors = /* @__PURE__ */ new Set();
|
|
780
|
+
const widgets = /* @__PURE__ */ new Set();
|
|
781
|
+
for (const capability of effective) {
|
|
782
|
+
if (capability.startsWith("command.")) {
|
|
783
|
+
commands.add(capability.slice("command.".length));
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
if (capability.startsWith("event.")) {
|
|
787
|
+
events.add(capability.slice("event.".length));
|
|
788
|
+
continue;
|
|
789
|
+
}
|
|
790
|
+
if (capability.startsWith("backend.")) {
|
|
791
|
+
backend.add(capability.slice("backend.".length));
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
if (capability.startsWith("thread.item.")) {
|
|
795
|
+
threadItems.add(capability.slice("thread.item.".length));
|
|
796
|
+
}
|
|
797
|
+
if (capability.startsWith("error.")) {
|
|
798
|
+
errors.add(capability.slice("error.".length));
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
801
|
+
if (capability.startsWith("widget.")) {
|
|
802
|
+
widgets.add(capability.slice("widget.".length));
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
return { commands, events, backend, threadItems, errors, widgets };
|
|
807
|
+
};
|
|
808
|
+
export {
|
|
809
|
+
BASE_CAPABILITY_ALLOWLIST,
|
|
810
|
+
BASE_CAPABILITY_DENYLIST,
|
|
811
|
+
BaseMessenger,
|
|
812
|
+
IntegrationError2 as IntegrationError,
|
|
813
|
+
PROFILE_TO_RULES,
|
|
814
|
+
decodeBase64,
|
|
815
|
+
encodeBase64,
|
|
816
|
+
fromPossibleFrameSafeError,
|
|
817
|
+
getCapabilities
|
|
818
|
+
};
|
|
819
|
+
//# sourceMappingURL=index.js.map
|