@liveblocks/core 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +698 -642
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +615 -559
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
var PKG_NAME = "@liveblocks/core";
|
|
9
|
-
var PKG_VERSION = "3.
|
|
9
|
+
var PKG_VERSION = "3.3.0";
|
|
10
10
|
var PKG_FORMAT = "esm";
|
|
11
11
|
|
|
12
12
|
// src/dupe-detection.ts
|
|
@@ -52,151 +52,101 @@ function detectDupes(pkgName, pkgVersion, pkgFormat) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// src/
|
|
56
|
-
function
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
createdAt: new Date(reaction.createdAt)
|
|
62
|
-
}));
|
|
63
|
-
if (data.body) {
|
|
64
|
-
return {
|
|
65
|
-
...data,
|
|
66
|
-
reactions,
|
|
67
|
-
createdAt,
|
|
68
|
-
editedAt
|
|
69
|
-
};
|
|
70
|
-
} else {
|
|
71
|
-
const deletedAt = new Date(data.deletedAt);
|
|
72
|
-
return {
|
|
73
|
-
...data,
|
|
74
|
-
reactions,
|
|
75
|
-
createdAt,
|
|
76
|
-
editedAt,
|
|
77
|
-
deletedAt
|
|
78
|
-
};
|
|
55
|
+
// src/lib/EventSource.ts
|
|
56
|
+
function makeEventSource() {
|
|
57
|
+
const _observers = /* @__PURE__ */ new Set();
|
|
58
|
+
function subscribe(callback) {
|
|
59
|
+
_observers.add(callback);
|
|
60
|
+
return () => _observers.delete(callback);
|
|
79
61
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}));
|
|
108
|
-
return {
|
|
109
|
-
...data,
|
|
110
|
-
notifiedAt,
|
|
111
|
-
readAt,
|
|
112
|
-
activities
|
|
113
|
-
};
|
|
62
|
+
function subscribeOnce(callback) {
|
|
63
|
+
const unsub = subscribe((event) => {
|
|
64
|
+
unsub();
|
|
65
|
+
return callback(event);
|
|
66
|
+
});
|
|
67
|
+
return unsub;
|
|
68
|
+
}
|
|
69
|
+
async function waitUntil(predicate) {
|
|
70
|
+
let unsub;
|
|
71
|
+
return new Promise((res) => {
|
|
72
|
+
unsub = subscribe((event) => {
|
|
73
|
+
if (predicate === void 0 || predicate(event)) {
|
|
74
|
+
res(event);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}).finally(() => unsub?.());
|
|
78
|
+
}
|
|
79
|
+
function notify(event) {
|
|
80
|
+
let called = false;
|
|
81
|
+
for (const callback of _observers) {
|
|
82
|
+
callback(event);
|
|
83
|
+
called = true;
|
|
84
|
+
}
|
|
85
|
+
return called;
|
|
86
|
+
}
|
|
87
|
+
function count() {
|
|
88
|
+
return _observers.size;
|
|
114
89
|
}
|
|
115
90
|
return {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
...data,
|
|
132
|
-
createdAt
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
function convertToThreadDeleteInfo(data) {
|
|
136
|
-
const deletedAt = new Date(data.deletedAt);
|
|
137
|
-
return {
|
|
138
|
-
...data,
|
|
139
|
-
deletedAt
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function convertToInboxNotificationDeleteInfo(data) {
|
|
143
|
-
const deletedAt = new Date(data.deletedAt);
|
|
144
|
-
return {
|
|
145
|
-
...data,
|
|
146
|
-
deletedAt
|
|
91
|
+
// Private/internal control over event emission
|
|
92
|
+
notify,
|
|
93
|
+
subscribe,
|
|
94
|
+
subscribeOnce,
|
|
95
|
+
count,
|
|
96
|
+
waitUntil,
|
|
97
|
+
dispose() {
|
|
98
|
+
_observers.clear();
|
|
99
|
+
},
|
|
100
|
+
// Publicly exposable subscription API
|
|
101
|
+
observable: {
|
|
102
|
+
subscribe,
|
|
103
|
+
subscribeOnce,
|
|
104
|
+
waitUntil
|
|
105
|
+
}
|
|
147
106
|
};
|
|
148
107
|
}
|
|
149
|
-
function
|
|
150
|
-
const
|
|
108
|
+
function makeBufferableEventSource() {
|
|
109
|
+
const eventSource2 = makeEventSource();
|
|
110
|
+
let _buffer = null;
|
|
111
|
+
function pause() {
|
|
112
|
+
_buffer = [];
|
|
113
|
+
}
|
|
114
|
+
function unpause() {
|
|
115
|
+
if (_buffer === null) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
for (const event of _buffer) {
|
|
119
|
+
eventSource2.notify(event);
|
|
120
|
+
}
|
|
121
|
+
_buffer = null;
|
|
122
|
+
}
|
|
123
|
+
function notifyOrBuffer(event) {
|
|
124
|
+
if (_buffer !== null) {
|
|
125
|
+
_buffer.push(event);
|
|
126
|
+
return false;
|
|
127
|
+
} else {
|
|
128
|
+
return eventSource2.notify(event);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
151
131
|
return {
|
|
152
|
-
...
|
|
153
|
-
|
|
132
|
+
...eventSource2,
|
|
133
|
+
notify: notifyOrBuffer,
|
|
134
|
+
pause,
|
|
135
|
+
unpause,
|
|
136
|
+
dispose() {
|
|
137
|
+
eventSource2.dispose();
|
|
138
|
+
if (_buffer !== null) {
|
|
139
|
+
_buffer.length = 0;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
154
142
|
};
|
|
155
143
|
}
|
|
156
144
|
|
|
157
|
-
// src/lib/
|
|
158
|
-
var
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
warn: () => warn,
|
|
163
|
-
warnWithTitle: () => warnWithTitle
|
|
164
|
-
});
|
|
165
|
-
var badge = "background:#0e0d12;border-radius:9999px;color:#fff;padding:3px 7px;font-family:sans-serif;font-weight:600;";
|
|
166
|
-
var bold = "font-weight:600";
|
|
167
|
-
function wrap(method) {
|
|
168
|
-
return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (
|
|
169
|
-
/* istanbul ignore next */
|
|
170
|
-
(message, ...args) => console[method]("%cLiveblocks", badge, message, ...args)
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
var warn = wrap("warn");
|
|
174
|
-
var error2 = wrap("error");
|
|
175
|
-
function wrapWithTitle(method) {
|
|
176
|
-
return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (
|
|
177
|
-
/* istanbul ignore next */
|
|
178
|
-
(title, message, ...args) => console[method](
|
|
179
|
-
`%cLiveblocks%c ${title}`,
|
|
180
|
-
badge,
|
|
181
|
-
bold,
|
|
182
|
-
message,
|
|
183
|
-
...args
|
|
184
|
-
)
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
var warnWithTitle = wrapWithTitle("warn");
|
|
188
|
-
var errorWithTitle = wrapWithTitle("error");
|
|
189
|
-
|
|
190
|
-
// src/lib/guards.ts
|
|
191
|
-
function isDefined(value) {
|
|
192
|
-
return value !== null && value !== void 0;
|
|
193
|
-
}
|
|
194
|
-
function isPlainObject(blob) {
|
|
195
|
-
return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
|
|
196
|
-
}
|
|
197
|
-
function isStartsWithOperator(blob) {
|
|
198
|
-
return isPlainObject(blob) && typeof blob.startsWith === "string";
|
|
199
|
-
}
|
|
145
|
+
// src/lib/freeze.ts
|
|
146
|
+
var freeze = process.env.NODE_ENV === "production" ? (
|
|
147
|
+
/* istanbul ignore next */
|
|
148
|
+
(x) => x
|
|
149
|
+
) : Object.freeze;
|
|
200
150
|
|
|
201
151
|
// src/lib/utils.ts
|
|
202
152
|
function raise(msg) {
|
|
@@ -294,201 +244,22 @@ function memoizeOnSuccess(factoryFn) {
|
|
|
294
244
|
};
|
|
295
245
|
}
|
|
296
246
|
|
|
297
|
-
// src/lib/
|
|
298
|
-
var
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
247
|
+
// src/lib/signals.ts
|
|
248
|
+
var kSinks = Symbol("kSinks");
|
|
249
|
+
var kTrigger = Symbol("kTrigger");
|
|
250
|
+
var signalsToTrigger = null;
|
|
251
|
+
var trackedReads = null;
|
|
252
|
+
function batch(callback) {
|
|
253
|
+
if (signalsToTrigger !== null) {
|
|
254
|
+
callback();
|
|
255
|
+
return;
|
|
306
256
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const bodyAsJson = bodyAsText ? tryParseJson(bodyAsText) : void 0;
|
|
314
|
-
let bodyAsJsonObject;
|
|
315
|
-
if (isPlainObject(bodyAsJson)) {
|
|
316
|
-
bodyAsJsonObject = bodyAsJson;
|
|
317
|
-
}
|
|
318
|
-
let message = "";
|
|
319
|
-
message ||= typeof bodyAsJsonObject?.message === "string" ? bodyAsJsonObject.message : "";
|
|
320
|
-
message ||= typeof bodyAsJsonObject?.error === "string" ? bodyAsJsonObject.error : "";
|
|
321
|
-
if (bodyAsJson === void 0) {
|
|
322
|
-
message ||= bodyAsText || "";
|
|
323
|
-
}
|
|
324
|
-
message ||= response.statusText;
|
|
325
|
-
let path;
|
|
326
|
-
try {
|
|
327
|
-
path = new URL(response.url).pathname;
|
|
328
|
-
} catch {
|
|
329
|
-
}
|
|
330
|
-
message += path !== void 0 ? ` (got status ${response.status} from ${path})` : ` (got status ${response.status})`;
|
|
331
|
-
const details = bodyAsJsonObject;
|
|
332
|
-
return new _HttpError(message, response, details);
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Convenience accessor for response.status.
|
|
336
|
-
*/
|
|
337
|
-
get status() {
|
|
338
|
-
return this.response.status;
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
var DONT_RETRY_4XX = (x) => x instanceof HttpError && x.status >= 400 && x.status < 500;
|
|
342
|
-
async function autoRetry(promiseFn, maxTries, backoff, shouldStopRetrying = DONT_RETRY_4XX) {
|
|
343
|
-
const fallbackBackoff = backoff.length > 0 ? backoff[backoff.length - 1] : 0;
|
|
344
|
-
let attempt = 0;
|
|
345
|
-
while (true) {
|
|
346
|
-
attempt++;
|
|
347
|
-
try {
|
|
348
|
-
return await promiseFn();
|
|
349
|
-
} catch (err) {
|
|
350
|
-
if (shouldStopRetrying(err)) {
|
|
351
|
-
throw err;
|
|
352
|
-
}
|
|
353
|
-
if (attempt >= maxTries) {
|
|
354
|
-
throw new Error(`Failed after ${maxTries} attempts: ${String(err)}`);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
const delay = backoff[attempt - 1] ?? fallbackBackoff;
|
|
358
|
-
warn(
|
|
359
|
-
`Attempt ${attempt} was unsuccessful. Retrying in ${delay} milliseconds.`
|
|
360
|
-
);
|
|
361
|
-
await wait(delay);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// src/lib/controlledPromise.ts
|
|
366
|
-
function controlledPromise() {
|
|
367
|
-
let resolve;
|
|
368
|
-
let reject;
|
|
369
|
-
const promise = new Promise((res, rej) => {
|
|
370
|
-
resolve = res;
|
|
371
|
-
reject = rej;
|
|
372
|
-
});
|
|
373
|
-
return [promise, resolve, reject];
|
|
374
|
-
}
|
|
375
|
-
function Promise_withResolvers() {
|
|
376
|
-
const [promise, resolve, reject] = controlledPromise();
|
|
377
|
-
return { promise, resolve, reject };
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// src/lib/EventSource.ts
|
|
381
|
-
function makeEventSource() {
|
|
382
|
-
const _observers = /* @__PURE__ */ new Set();
|
|
383
|
-
function subscribe(callback) {
|
|
384
|
-
_observers.add(callback);
|
|
385
|
-
return () => _observers.delete(callback);
|
|
386
|
-
}
|
|
387
|
-
function subscribeOnce(callback) {
|
|
388
|
-
const unsub = subscribe((event) => {
|
|
389
|
-
unsub();
|
|
390
|
-
return callback(event);
|
|
391
|
-
});
|
|
392
|
-
return unsub;
|
|
393
|
-
}
|
|
394
|
-
async function waitUntil(predicate) {
|
|
395
|
-
let unsub;
|
|
396
|
-
return new Promise((res) => {
|
|
397
|
-
unsub = subscribe((event) => {
|
|
398
|
-
if (predicate === void 0 || predicate(event)) {
|
|
399
|
-
res(event);
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
}).finally(() => unsub?.());
|
|
403
|
-
}
|
|
404
|
-
function notify(event) {
|
|
405
|
-
let called = false;
|
|
406
|
-
for (const callback of _observers) {
|
|
407
|
-
callback(event);
|
|
408
|
-
called = true;
|
|
409
|
-
}
|
|
410
|
-
return called;
|
|
411
|
-
}
|
|
412
|
-
function count() {
|
|
413
|
-
return _observers.size;
|
|
414
|
-
}
|
|
415
|
-
return {
|
|
416
|
-
// Private/internal control over event emission
|
|
417
|
-
notify,
|
|
418
|
-
subscribe,
|
|
419
|
-
subscribeOnce,
|
|
420
|
-
count,
|
|
421
|
-
waitUntil,
|
|
422
|
-
dispose() {
|
|
423
|
-
_observers.clear();
|
|
424
|
-
},
|
|
425
|
-
// Publicly exposable subscription API
|
|
426
|
-
observable: {
|
|
427
|
-
subscribe,
|
|
428
|
-
subscribeOnce,
|
|
429
|
-
waitUntil
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
function makeBufferableEventSource() {
|
|
434
|
-
const eventSource2 = makeEventSource();
|
|
435
|
-
let _buffer = null;
|
|
436
|
-
function pause() {
|
|
437
|
-
_buffer = [];
|
|
438
|
-
}
|
|
439
|
-
function unpause() {
|
|
440
|
-
if (_buffer === null) {
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
for (const event of _buffer) {
|
|
444
|
-
eventSource2.notify(event);
|
|
445
|
-
}
|
|
446
|
-
_buffer = null;
|
|
447
|
-
}
|
|
448
|
-
function notifyOrBuffer(event) {
|
|
449
|
-
if (_buffer !== null) {
|
|
450
|
-
_buffer.push(event);
|
|
451
|
-
return false;
|
|
452
|
-
} else {
|
|
453
|
-
return eventSource2.notify(event);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
return {
|
|
457
|
-
...eventSource2,
|
|
458
|
-
notify: notifyOrBuffer,
|
|
459
|
-
pause,
|
|
460
|
-
unpause,
|
|
461
|
-
dispose() {
|
|
462
|
-
eventSource2.dispose();
|
|
463
|
-
if (_buffer !== null) {
|
|
464
|
-
_buffer.length = 0;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// src/lib/freeze.ts
|
|
471
|
-
var freeze = process.env.NODE_ENV === "production" ? (
|
|
472
|
-
/* istanbul ignore next */
|
|
473
|
-
(x) => x
|
|
474
|
-
) : Object.freeze;
|
|
475
|
-
|
|
476
|
-
// src/lib/signals.ts
|
|
477
|
-
var kSinks = Symbol("kSinks");
|
|
478
|
-
var kTrigger = Symbol("kTrigger");
|
|
479
|
-
var signalsToTrigger = null;
|
|
480
|
-
var trackedReads = null;
|
|
481
|
-
function batch(callback) {
|
|
482
|
-
if (signalsToTrigger !== null) {
|
|
483
|
-
callback();
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
signalsToTrigger = /* @__PURE__ */ new Set();
|
|
487
|
-
try {
|
|
488
|
-
callback();
|
|
489
|
-
} finally {
|
|
490
|
-
for (const signal of signalsToTrigger) {
|
|
491
|
-
signal[kTrigger]();
|
|
257
|
+
signalsToTrigger = /* @__PURE__ */ new Set();
|
|
258
|
+
try {
|
|
259
|
+
callback();
|
|
260
|
+
} finally {
|
|
261
|
+
for (const signal of signalsToTrigger) {
|
|
262
|
+
signal[kTrigger]();
|
|
492
263
|
}
|
|
493
264
|
signalsToTrigger = null;
|
|
494
265
|
}
|
|
@@ -695,64 +466,510 @@ var DerivedSignal = class _DerivedSignal extends AbstractSignal {
|
|
|
695
466
|
this.#dirty = true;
|
|
696
467
|
this.markSinksDirty();
|
|
697
468
|
}
|
|
698
|
-
}
|
|
699
|
-
get() {
|
|
700
|
-
if (this.#dirty) {
|
|
701
|
-
this.#recompute();
|
|
469
|
+
}
|
|
470
|
+
get() {
|
|
471
|
+
if (this.#dirty) {
|
|
472
|
+
this.#recompute();
|
|
473
|
+
}
|
|
474
|
+
trackedReads?.add(this);
|
|
475
|
+
return this.#prevValue;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Called by the Signal system if one or more of the dependent signals have
|
|
479
|
+
* changed. In the case of a DerivedSignal, we'll only want to re-evaluate
|
|
480
|
+
* the actual value if it's being watched, or any of their sinks are being
|
|
481
|
+
* watched actively.
|
|
482
|
+
*/
|
|
483
|
+
[kTrigger]() {
|
|
484
|
+
if (!this.hasWatchers) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
const updated = this.#recompute();
|
|
488
|
+
if (updated) {
|
|
489
|
+
super[kTrigger]();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
var MutableSignal = class extends AbstractSignal {
|
|
494
|
+
#state;
|
|
495
|
+
constructor(initialState) {
|
|
496
|
+
super();
|
|
497
|
+
this.#state = initialState;
|
|
498
|
+
}
|
|
499
|
+
dispose() {
|
|
500
|
+
super.dispose();
|
|
501
|
+
this.#state = "(disposed)";
|
|
502
|
+
}
|
|
503
|
+
get() {
|
|
504
|
+
trackedReads?.add(this);
|
|
505
|
+
return this.#state;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Invokes a callback function that is allowed to mutate the given state
|
|
509
|
+
* value. Do not change the value outside of the callback.
|
|
510
|
+
*
|
|
511
|
+
* If the callback explicitly returns `false`, it's assumed that the state
|
|
512
|
+
* was not changed.
|
|
513
|
+
*/
|
|
514
|
+
mutate(callback) {
|
|
515
|
+
batch(() => {
|
|
516
|
+
const result = callback ? callback(this.#state) : true;
|
|
517
|
+
if (result !== null && typeof result === "object" && "then" in result) {
|
|
518
|
+
raise("MutableSignal.mutate() does not support async callbacks");
|
|
519
|
+
}
|
|
520
|
+
if (result !== false) {
|
|
521
|
+
this.markSinksDirty();
|
|
522
|
+
enqueueTrigger(this);
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
// src/lib/SortedList.ts
|
|
529
|
+
function bisectRight(arr, x, lt) {
|
|
530
|
+
let lo = 0;
|
|
531
|
+
let hi = arr.length;
|
|
532
|
+
while (lo < hi) {
|
|
533
|
+
const mid = lo + (hi - lo >> 1);
|
|
534
|
+
if (lt(x, arr[mid])) {
|
|
535
|
+
hi = mid;
|
|
536
|
+
} else {
|
|
537
|
+
lo = mid + 1;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
return lo;
|
|
541
|
+
}
|
|
542
|
+
var SortedList = class _SortedList {
|
|
543
|
+
#data;
|
|
544
|
+
#lt;
|
|
545
|
+
constructor(alreadySortedList, lt) {
|
|
546
|
+
this.#lt = lt;
|
|
547
|
+
this.#data = alreadySortedList;
|
|
548
|
+
}
|
|
549
|
+
static with(lt) {
|
|
550
|
+
return _SortedList.fromAlreadySorted([], lt);
|
|
551
|
+
}
|
|
552
|
+
static from(arr, lt) {
|
|
553
|
+
const sorted = new _SortedList([], lt);
|
|
554
|
+
for (const item of arr) {
|
|
555
|
+
sorted.add(item);
|
|
556
|
+
}
|
|
557
|
+
return sorted;
|
|
558
|
+
}
|
|
559
|
+
static fromAlreadySorted(alreadySorted, lt) {
|
|
560
|
+
return new _SortedList(alreadySorted, lt);
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Clones the sorted list to a new instance.
|
|
564
|
+
*/
|
|
565
|
+
clone() {
|
|
566
|
+
return new _SortedList(this.#data.slice(), this.#lt);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Adds a new item to the sorted list, such that it remains sorted.
|
|
570
|
+
*/
|
|
571
|
+
add(value) {
|
|
572
|
+
const idx = bisectRight(this.#data, value, this.#lt);
|
|
573
|
+
this.#data.splice(idx, 0, value);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Removes all values from the sorted list, making it empty again.
|
|
577
|
+
* Returns whether the list was mutated or not.
|
|
578
|
+
*/
|
|
579
|
+
clear() {
|
|
580
|
+
const hadData = this.#data.length > 0;
|
|
581
|
+
this.#data.length = 0;
|
|
582
|
+
return hadData;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Removes the first value matching the predicate.
|
|
586
|
+
* Returns whether the list was mutated or not.
|
|
587
|
+
*/
|
|
588
|
+
removeBy(predicate, limit = Number.POSITIVE_INFINITY) {
|
|
589
|
+
let deleted = 0;
|
|
590
|
+
for (let i = 0; i < this.#data.length; i++) {
|
|
591
|
+
if (predicate(this.#data[i])) {
|
|
592
|
+
this.#data.splice(i, 1);
|
|
593
|
+
deleted++;
|
|
594
|
+
if (deleted >= limit) {
|
|
595
|
+
break;
|
|
596
|
+
} else {
|
|
597
|
+
i--;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return deleted > 0;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Removes the given value from the sorted list, if it exists. The given
|
|
605
|
+
* value must be `===` to one of the list items. Only the first entry will be
|
|
606
|
+
* removed if the element exists in the sorted list multiple times.
|
|
607
|
+
*
|
|
608
|
+
* Returns whether the list was mutated or not.
|
|
609
|
+
*/
|
|
610
|
+
remove(value) {
|
|
611
|
+
const idx = this.#data.indexOf(value);
|
|
612
|
+
if (idx >= 0) {
|
|
613
|
+
this.#data.splice(idx, 1);
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
at(index) {
|
|
619
|
+
return this.#data[index];
|
|
620
|
+
}
|
|
621
|
+
get length() {
|
|
622
|
+
return this.#data.length;
|
|
623
|
+
}
|
|
624
|
+
*filter(predicate) {
|
|
625
|
+
for (const item of this.#data) {
|
|
626
|
+
if (predicate(item)) {
|
|
627
|
+
yield item;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
// XXXX If we keep this, add unit tests. Or remove it.
|
|
632
|
+
*findAllRight(predicate) {
|
|
633
|
+
for (let i = this.#data.length - 1; i >= 0; i--) {
|
|
634
|
+
const item = this.#data[i];
|
|
635
|
+
if (predicate(item, i)) {
|
|
636
|
+
yield item;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
[Symbol.iterator]() {
|
|
641
|
+
return this.#data[Symbol.iterator]();
|
|
642
|
+
}
|
|
643
|
+
*iterReversed() {
|
|
644
|
+
for (let i = this.#data.length - 1; i >= 0; i--) {
|
|
645
|
+
yield this.#data[i];
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
/** Finds the leftmost item that matches the predicate. */
|
|
649
|
+
find(predicate, start) {
|
|
650
|
+
const idx = this.findIndex(predicate, start);
|
|
651
|
+
return idx > -1 ? this.#data.at(idx) : void 0;
|
|
652
|
+
}
|
|
653
|
+
/** Finds the leftmost index that matches the predicate. */
|
|
654
|
+
findIndex(predicate, start = 0) {
|
|
655
|
+
for (let i = Math.max(0, start); i < this.#data.length; i++) {
|
|
656
|
+
if (predicate(this.#data[i], i)) {
|
|
657
|
+
return i;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return -1;
|
|
661
|
+
}
|
|
662
|
+
/** Finds the rightmost item that matches the predicate. */
|
|
663
|
+
findRight(predicate, start) {
|
|
664
|
+
const idx = this.findIndexRight(predicate, start);
|
|
665
|
+
return idx > -1 ? this.#data.at(idx) : void 0;
|
|
666
|
+
}
|
|
667
|
+
/** Finds the rightmost index that matches the predicate. */
|
|
668
|
+
findIndexRight(predicate, start = this.#data.length - 1) {
|
|
669
|
+
for (let i = Math.min(start, this.#data.length - 1); i >= 0; i--) {
|
|
670
|
+
if (predicate(this.#data[i], i)) {
|
|
671
|
+
return i;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return -1;
|
|
675
|
+
}
|
|
676
|
+
get rawArray() {
|
|
677
|
+
return this.#data;
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
// src/AiChatDB.ts
|
|
682
|
+
var AiChatDB = class {
|
|
683
|
+
#byId;
|
|
684
|
+
// A map of chat id to chat details
|
|
685
|
+
#chats;
|
|
686
|
+
// Sorted list of non-deleted chats, most recent first
|
|
687
|
+
signal;
|
|
688
|
+
constructor() {
|
|
689
|
+
this.#byId = /* @__PURE__ */ new Map();
|
|
690
|
+
this.#chats = SortedList.from([], (c1, c2) => {
|
|
691
|
+
const d2 = c2.lastMessageAt ?? c2.createdAt;
|
|
692
|
+
const d1 = c1.lastMessageAt ?? c1.createdAt;
|
|
693
|
+
return d2 < d1 ? true : d2 === d1 ? c2.id < c1.id : false;
|
|
694
|
+
});
|
|
695
|
+
this.signal = new MutableSignal(this);
|
|
696
|
+
}
|
|
697
|
+
getEvenIfDeleted(chatId) {
|
|
698
|
+
return this.#byId.get(chatId);
|
|
699
|
+
}
|
|
700
|
+
markDeleted(chatId) {
|
|
701
|
+
const chat = this.#byId.get(chatId);
|
|
702
|
+
if (chat === void 0 || chat.deletedAt !== void 0) return;
|
|
703
|
+
this.upsert({
|
|
704
|
+
...chat,
|
|
705
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
upsert(chat) {
|
|
709
|
+
this.signal.mutate(() => {
|
|
710
|
+
const existingThread = this.#byId.get(chat.id);
|
|
711
|
+
if (existingThread !== void 0) {
|
|
712
|
+
if (existingThread.deletedAt !== void 0) return false;
|
|
713
|
+
this.#chats.remove(existingThread);
|
|
714
|
+
this.#byId.delete(existingThread.id);
|
|
715
|
+
}
|
|
716
|
+
if (chat.deletedAt === void 0) {
|
|
717
|
+
this.#chats.add(chat);
|
|
718
|
+
}
|
|
719
|
+
this.#byId.set(chat.id, chat);
|
|
720
|
+
return true;
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
findMany(query) {
|
|
724
|
+
return Array.from(
|
|
725
|
+
this.#chats.filter((chat) => {
|
|
726
|
+
if (query.metadata === void 0) return true;
|
|
727
|
+
for (const [key, value] of Object.entries(query.metadata)) {
|
|
728
|
+
if (value === null) {
|
|
729
|
+
if (key in chat.metadata) return false;
|
|
730
|
+
} else if (typeof value === "string") {
|
|
731
|
+
if (chat.metadata[key] !== value) return false;
|
|
732
|
+
} else {
|
|
733
|
+
const chatValue = chat.metadata[key];
|
|
734
|
+
if (!Array.isArray(chatValue) || !value.every((v) => chatValue.includes(v))) {
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return true;
|
|
740
|
+
})
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
// src/convert-plain-data.ts
|
|
746
|
+
function convertToCommentData(data) {
|
|
747
|
+
const editedAt = data.editedAt ? new Date(data.editedAt) : void 0;
|
|
748
|
+
const createdAt = new Date(data.createdAt);
|
|
749
|
+
const reactions = data.reactions.map((reaction) => ({
|
|
750
|
+
...reaction,
|
|
751
|
+
createdAt: new Date(reaction.createdAt)
|
|
752
|
+
}));
|
|
753
|
+
if (data.body) {
|
|
754
|
+
return {
|
|
755
|
+
...data,
|
|
756
|
+
reactions,
|
|
757
|
+
createdAt,
|
|
758
|
+
editedAt
|
|
759
|
+
};
|
|
760
|
+
} else {
|
|
761
|
+
const deletedAt = new Date(data.deletedAt);
|
|
762
|
+
return {
|
|
763
|
+
...data,
|
|
764
|
+
reactions,
|
|
765
|
+
createdAt,
|
|
766
|
+
editedAt,
|
|
767
|
+
deletedAt
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
function convertToThreadData(data) {
|
|
772
|
+
const createdAt = new Date(data.createdAt);
|
|
773
|
+
const updatedAt = new Date(data.updatedAt);
|
|
774
|
+
const comments = data.comments.map(
|
|
775
|
+
(comment) => convertToCommentData(comment)
|
|
776
|
+
);
|
|
777
|
+
return {
|
|
778
|
+
...data,
|
|
779
|
+
createdAt,
|
|
780
|
+
updatedAt,
|
|
781
|
+
comments
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
function convertToCommentUserReaction(data) {
|
|
785
|
+
return {
|
|
786
|
+
...data,
|
|
787
|
+
createdAt: new Date(data.createdAt)
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
function convertToInboxNotificationData(data) {
|
|
791
|
+
const notifiedAt = new Date(data.notifiedAt);
|
|
792
|
+
const readAt = data.readAt ? new Date(data.readAt) : null;
|
|
793
|
+
if ("activities" in data) {
|
|
794
|
+
const activities = data.activities.map((activity) => ({
|
|
795
|
+
...activity,
|
|
796
|
+
createdAt: new Date(activity.createdAt)
|
|
797
|
+
}));
|
|
798
|
+
return {
|
|
799
|
+
...data,
|
|
800
|
+
notifiedAt,
|
|
801
|
+
readAt,
|
|
802
|
+
activities
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
return {
|
|
806
|
+
...data,
|
|
807
|
+
notifiedAt,
|
|
808
|
+
readAt
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
function convertToSubscriptionData(data) {
|
|
812
|
+
const createdAt = new Date(data.createdAt);
|
|
813
|
+
return {
|
|
814
|
+
...data,
|
|
815
|
+
createdAt
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function convertToUserSubscriptionData(data) {
|
|
819
|
+
const createdAt = new Date(data.createdAt);
|
|
820
|
+
return {
|
|
821
|
+
...data,
|
|
822
|
+
createdAt
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
function convertToThreadDeleteInfo(data) {
|
|
826
|
+
const deletedAt = new Date(data.deletedAt);
|
|
827
|
+
return {
|
|
828
|
+
...data,
|
|
829
|
+
deletedAt
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function convertToInboxNotificationDeleteInfo(data) {
|
|
833
|
+
const deletedAt = new Date(data.deletedAt);
|
|
834
|
+
return {
|
|
835
|
+
...data,
|
|
836
|
+
deletedAt
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
function convertToSubscriptionDeleteInfo(data) {
|
|
840
|
+
const deletedAt = new Date(data.deletedAt);
|
|
841
|
+
return {
|
|
842
|
+
...data,
|
|
843
|
+
deletedAt
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// src/lib/fancy-console.ts
|
|
848
|
+
var fancy_console_exports = {};
|
|
849
|
+
__export(fancy_console_exports, {
|
|
850
|
+
error: () => error2,
|
|
851
|
+
errorWithTitle: () => errorWithTitle,
|
|
852
|
+
warn: () => warn,
|
|
853
|
+
warnWithTitle: () => warnWithTitle
|
|
854
|
+
});
|
|
855
|
+
var badge = "background:#0e0d12;border-radius:9999px;color:#fff;padding:3px 7px;font-family:sans-serif;font-weight:600;";
|
|
856
|
+
var bold = "font-weight:600";
|
|
857
|
+
function wrap(method) {
|
|
858
|
+
return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (
|
|
859
|
+
/* istanbul ignore next */
|
|
860
|
+
(message, ...args) => console[method]("%cLiveblocks", badge, message, ...args)
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
var warn = wrap("warn");
|
|
864
|
+
var error2 = wrap("error");
|
|
865
|
+
function wrapWithTitle(method) {
|
|
866
|
+
return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (
|
|
867
|
+
/* istanbul ignore next */
|
|
868
|
+
(title, message, ...args) => console[method](
|
|
869
|
+
`%cLiveblocks%c ${title}`,
|
|
870
|
+
badge,
|
|
871
|
+
bold,
|
|
872
|
+
message,
|
|
873
|
+
...args
|
|
874
|
+
)
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
var warnWithTitle = wrapWithTitle("warn");
|
|
878
|
+
var errorWithTitle = wrapWithTitle("error");
|
|
879
|
+
|
|
880
|
+
// src/lib/guards.ts
|
|
881
|
+
function isDefined(value) {
|
|
882
|
+
return value !== null && value !== void 0;
|
|
883
|
+
}
|
|
884
|
+
function isPlainObject(blob) {
|
|
885
|
+
return blob !== null && typeof blob === "object" && Object.prototype.toString.call(blob) === "[object Object]";
|
|
886
|
+
}
|
|
887
|
+
function isStartsWithOperator(blob) {
|
|
888
|
+
return isPlainObject(blob) && typeof blob.startsWith === "string";
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// src/lib/autoRetry.ts
|
|
892
|
+
var HttpError = class _HttpError extends Error {
|
|
893
|
+
response;
|
|
894
|
+
details;
|
|
895
|
+
constructor(message, response, details) {
|
|
896
|
+
super(message);
|
|
897
|
+
this.name = "HttpError";
|
|
898
|
+
this.response = response;
|
|
899
|
+
this.details = details;
|
|
900
|
+
}
|
|
901
|
+
static async fromResponse(response) {
|
|
902
|
+
let bodyAsText;
|
|
903
|
+
try {
|
|
904
|
+
bodyAsText = await response.text();
|
|
905
|
+
} catch {
|
|
906
|
+
}
|
|
907
|
+
const bodyAsJson = bodyAsText ? tryParseJson(bodyAsText) : void 0;
|
|
908
|
+
let bodyAsJsonObject;
|
|
909
|
+
if (isPlainObject(bodyAsJson)) {
|
|
910
|
+
bodyAsJsonObject = bodyAsJson;
|
|
911
|
+
}
|
|
912
|
+
let message = "";
|
|
913
|
+
message ||= typeof bodyAsJsonObject?.message === "string" ? bodyAsJsonObject.message : "";
|
|
914
|
+
message ||= typeof bodyAsJsonObject?.error === "string" ? bodyAsJsonObject.error : "";
|
|
915
|
+
if (bodyAsJson === void 0) {
|
|
916
|
+
message ||= bodyAsText || "";
|
|
917
|
+
}
|
|
918
|
+
message ||= response.statusText;
|
|
919
|
+
let path;
|
|
920
|
+
try {
|
|
921
|
+
path = new URL(response.url).pathname;
|
|
922
|
+
} catch {
|
|
702
923
|
}
|
|
703
|
-
|
|
704
|
-
|
|
924
|
+
message += path !== void 0 ? ` (got status ${response.status} from ${path})` : ` (got status ${response.status})`;
|
|
925
|
+
const details = bodyAsJsonObject;
|
|
926
|
+
return new _HttpError(message, response, details);
|
|
705
927
|
}
|
|
706
928
|
/**
|
|
707
|
-
*
|
|
708
|
-
* changed. In the case of a DerivedSignal, we'll only want to re-evaluate
|
|
709
|
-
* the actual value if it's being watched, or any of their sinks are being
|
|
710
|
-
* watched actively.
|
|
929
|
+
* Convenience accessor for response.status.
|
|
711
930
|
*/
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
const updated = this.#recompute();
|
|
717
|
-
if (updated) {
|
|
718
|
-
super[kTrigger]();
|
|
719
|
-
}
|
|
931
|
+
get status() {
|
|
932
|
+
return this.response.status;
|
|
720
933
|
}
|
|
721
934
|
};
|
|
722
|
-
var
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
trackedReads?.add(this);
|
|
734
|
-
return this.#state;
|
|
735
|
-
}
|
|
736
|
-
/**
|
|
737
|
-
* Invokes a callback function that is allowed to mutate the given state
|
|
738
|
-
* value. Do not change the value outside of the callback.
|
|
739
|
-
*
|
|
740
|
-
* If the callback explicitly returns `false`, it's assumed that the state
|
|
741
|
-
* was not changed.
|
|
742
|
-
*/
|
|
743
|
-
mutate(callback) {
|
|
744
|
-
batch(() => {
|
|
745
|
-
const result = callback ? callback(this.#state) : true;
|
|
746
|
-
if (result !== null && typeof result === "object" && "then" in result) {
|
|
747
|
-
raise("MutableSignal.mutate() does not support async callbacks");
|
|
935
|
+
var DONT_RETRY_4XX = (x) => x instanceof HttpError && x.status >= 400 && x.status < 500;
|
|
936
|
+
async function autoRetry(promiseFn, maxTries, backoff, shouldStopRetrying = DONT_RETRY_4XX) {
|
|
937
|
+
const fallbackBackoff = backoff.length > 0 ? backoff[backoff.length - 1] : 0;
|
|
938
|
+
let attempt = 0;
|
|
939
|
+
while (true) {
|
|
940
|
+
attempt++;
|
|
941
|
+
try {
|
|
942
|
+
return await promiseFn();
|
|
943
|
+
} catch (err) {
|
|
944
|
+
if (shouldStopRetrying(err)) {
|
|
945
|
+
throw err;
|
|
748
946
|
}
|
|
749
|
-
if (
|
|
750
|
-
|
|
751
|
-
enqueueTrigger(this);
|
|
947
|
+
if (attempt >= maxTries) {
|
|
948
|
+
throw new Error(`Failed after ${maxTries} attempts: ${String(err)}`);
|
|
752
949
|
}
|
|
753
|
-
}
|
|
950
|
+
}
|
|
951
|
+
const delay = backoff[attempt - 1] ?? fallbackBackoff;
|
|
952
|
+
warn(
|
|
953
|
+
`Attempt ${attempt} was unsuccessful. Retrying in ${delay} milliseconds.`
|
|
954
|
+
);
|
|
955
|
+
await wait(delay);
|
|
754
956
|
}
|
|
755
|
-
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// src/lib/controlledPromise.ts
|
|
960
|
+
function controlledPromise() {
|
|
961
|
+
let resolve;
|
|
962
|
+
let reject;
|
|
963
|
+
const promise = new Promise((res, rej) => {
|
|
964
|
+
resolve = res;
|
|
965
|
+
reject = rej;
|
|
966
|
+
});
|
|
967
|
+
return [promise, resolve, reject];
|
|
968
|
+
}
|
|
969
|
+
function Promise_withResolvers() {
|
|
970
|
+
const [promise, resolve, reject] = controlledPromise();
|
|
971
|
+
return { promise, resolve, reject };
|
|
972
|
+
}
|
|
756
973
|
|
|
757
974
|
// src/lib/stringify.ts
|
|
758
975
|
function replacer(_key, value) {
|
|
@@ -3398,159 +3615,6 @@ function shallow2(a, b) {
|
|
|
3398
3615
|
);
|
|
3399
3616
|
}
|
|
3400
3617
|
|
|
3401
|
-
// src/lib/SortedList.ts
|
|
3402
|
-
function bisectRight(arr, x, lt) {
|
|
3403
|
-
let lo = 0;
|
|
3404
|
-
let hi = arr.length;
|
|
3405
|
-
while (lo < hi) {
|
|
3406
|
-
const mid = lo + (hi - lo >> 1);
|
|
3407
|
-
if (lt(x, arr[mid])) {
|
|
3408
|
-
hi = mid;
|
|
3409
|
-
} else {
|
|
3410
|
-
lo = mid + 1;
|
|
3411
|
-
}
|
|
3412
|
-
}
|
|
3413
|
-
return lo;
|
|
3414
|
-
}
|
|
3415
|
-
var SortedList = class _SortedList {
|
|
3416
|
-
#data;
|
|
3417
|
-
#lt;
|
|
3418
|
-
constructor(alreadySortedList, lt) {
|
|
3419
|
-
this.#lt = lt;
|
|
3420
|
-
this.#data = alreadySortedList;
|
|
3421
|
-
}
|
|
3422
|
-
static with(lt) {
|
|
3423
|
-
return _SortedList.fromAlreadySorted([], lt);
|
|
3424
|
-
}
|
|
3425
|
-
static from(arr, lt) {
|
|
3426
|
-
const sorted = new _SortedList([], lt);
|
|
3427
|
-
for (const item of arr) {
|
|
3428
|
-
sorted.add(item);
|
|
3429
|
-
}
|
|
3430
|
-
return sorted;
|
|
3431
|
-
}
|
|
3432
|
-
static fromAlreadySorted(alreadySorted, lt) {
|
|
3433
|
-
return new _SortedList(alreadySorted, lt);
|
|
3434
|
-
}
|
|
3435
|
-
/**
|
|
3436
|
-
* Clones the sorted list to a new instance.
|
|
3437
|
-
*/
|
|
3438
|
-
clone() {
|
|
3439
|
-
return new _SortedList(this.#data.slice(), this.#lt);
|
|
3440
|
-
}
|
|
3441
|
-
/**
|
|
3442
|
-
* Adds a new item to the sorted list, such that it remains sorted.
|
|
3443
|
-
*/
|
|
3444
|
-
add(value) {
|
|
3445
|
-
const idx = bisectRight(this.#data, value, this.#lt);
|
|
3446
|
-
this.#data.splice(idx, 0, value);
|
|
3447
|
-
}
|
|
3448
|
-
/**
|
|
3449
|
-
* Removes all values from the sorted list, making it empty again.
|
|
3450
|
-
* Returns whether the list was mutated or not.
|
|
3451
|
-
*/
|
|
3452
|
-
clear() {
|
|
3453
|
-
const hadData = this.#data.length > 0;
|
|
3454
|
-
this.#data.length = 0;
|
|
3455
|
-
return hadData;
|
|
3456
|
-
}
|
|
3457
|
-
/**
|
|
3458
|
-
* Removes the first value matching the predicate.
|
|
3459
|
-
* Returns whether the list was mutated or not.
|
|
3460
|
-
*/
|
|
3461
|
-
removeBy(predicate, limit = Number.POSITIVE_INFINITY) {
|
|
3462
|
-
let deleted = 0;
|
|
3463
|
-
for (let i = 0; i < this.#data.length; i++) {
|
|
3464
|
-
if (predicate(this.#data[i])) {
|
|
3465
|
-
this.#data.splice(i, 1);
|
|
3466
|
-
deleted++;
|
|
3467
|
-
if (deleted >= limit) {
|
|
3468
|
-
break;
|
|
3469
|
-
} else {
|
|
3470
|
-
i--;
|
|
3471
|
-
}
|
|
3472
|
-
}
|
|
3473
|
-
}
|
|
3474
|
-
return deleted > 0;
|
|
3475
|
-
}
|
|
3476
|
-
/**
|
|
3477
|
-
* Removes the given value from the sorted list, if it exists. The given
|
|
3478
|
-
* value must be `===` to one of the list items. Only the first entry will be
|
|
3479
|
-
* removed if the element exists in the sorted list multiple times.
|
|
3480
|
-
*
|
|
3481
|
-
* Returns whether the list was mutated or not.
|
|
3482
|
-
*/
|
|
3483
|
-
remove(value) {
|
|
3484
|
-
const idx = this.#data.indexOf(value);
|
|
3485
|
-
if (idx >= 0) {
|
|
3486
|
-
this.#data.splice(idx, 1);
|
|
3487
|
-
return true;
|
|
3488
|
-
}
|
|
3489
|
-
return false;
|
|
3490
|
-
}
|
|
3491
|
-
at(index) {
|
|
3492
|
-
return this.#data[index];
|
|
3493
|
-
}
|
|
3494
|
-
get length() {
|
|
3495
|
-
return this.#data.length;
|
|
3496
|
-
}
|
|
3497
|
-
*filter(predicate) {
|
|
3498
|
-
for (const item of this.#data) {
|
|
3499
|
-
if (predicate(item)) {
|
|
3500
|
-
yield item;
|
|
3501
|
-
}
|
|
3502
|
-
}
|
|
3503
|
-
}
|
|
3504
|
-
// XXXX If we keep this, add unit tests. Or remove it.
|
|
3505
|
-
*findAllRight(predicate) {
|
|
3506
|
-
for (let i = this.#data.length - 1; i >= 0; i--) {
|
|
3507
|
-
const item = this.#data[i];
|
|
3508
|
-
if (predicate(item, i)) {
|
|
3509
|
-
yield item;
|
|
3510
|
-
}
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
[Symbol.iterator]() {
|
|
3514
|
-
return this.#data[Symbol.iterator]();
|
|
3515
|
-
}
|
|
3516
|
-
*iterReversed() {
|
|
3517
|
-
for (let i = this.#data.length - 1; i >= 0; i--) {
|
|
3518
|
-
yield this.#data[i];
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
/** Finds the leftmost item that matches the predicate. */
|
|
3522
|
-
find(predicate, start) {
|
|
3523
|
-
const idx = this.findIndex(predicate, start);
|
|
3524
|
-
return idx > -1 ? this.#data.at(idx) : void 0;
|
|
3525
|
-
}
|
|
3526
|
-
/** Finds the leftmost index that matches the predicate. */
|
|
3527
|
-
findIndex(predicate, start = 0) {
|
|
3528
|
-
for (let i = Math.max(0, start); i < this.#data.length; i++) {
|
|
3529
|
-
if (predicate(this.#data[i], i)) {
|
|
3530
|
-
return i;
|
|
3531
|
-
}
|
|
3532
|
-
}
|
|
3533
|
-
return -1;
|
|
3534
|
-
}
|
|
3535
|
-
/** Finds the rightmost item that matches the predicate. */
|
|
3536
|
-
findRight(predicate, start) {
|
|
3537
|
-
const idx = this.findIndexRight(predicate, start);
|
|
3538
|
-
return idx > -1 ? this.#data.at(idx) : void 0;
|
|
3539
|
-
}
|
|
3540
|
-
/** Finds the rightmost index that matches the predicate. */
|
|
3541
|
-
findIndexRight(predicate, start = this.#data.length - 1) {
|
|
3542
|
-
for (let i = Math.min(start, this.#data.length - 1); i >= 0; i--) {
|
|
3543
|
-
if (predicate(this.#data[i], i)) {
|
|
3544
|
-
return i;
|
|
3545
|
-
}
|
|
3546
|
-
}
|
|
3547
|
-
return -1;
|
|
3548
|
-
}
|
|
3549
|
-
get rawArray() {
|
|
3550
|
-
return this.#data;
|
|
3551
|
-
}
|
|
3552
|
-
};
|
|
3553
|
-
|
|
3554
3618
|
// src/lib/TreePool.ts
|
|
3555
3619
|
var TreePool = class {
|
|
3556
3620
|
#_items;
|
|
@@ -4151,39 +4215,29 @@ function createStore_forChatMessages(toolsStore, setToolResultFn) {
|
|
|
4151
4215
|
};
|
|
4152
4216
|
}
|
|
4153
4217
|
function createStore_forUserAiChats() {
|
|
4154
|
-
const
|
|
4155
|
-
SortedList.with((x, y) => y.createdAt < x.createdAt)
|
|
4156
|
-
);
|
|
4157
|
-
const nonDeletedChats\u03A3 = DerivedSignal.from(
|
|
4158
|
-
() => Array.from(allChatsInclDeleted\u03A3.get()).filter((c) => !c.deletedAt)
|
|
4159
|
-
);
|
|
4218
|
+
const chatsDB = new AiChatDB();
|
|
4160
4219
|
function upsertMany(chats) {
|
|
4161
|
-
|
|
4220
|
+
batch(() => {
|
|
4162
4221
|
for (const chat of chats) {
|
|
4163
|
-
|
|
4164
|
-
list.add(chat);
|
|
4222
|
+
chatsDB.upsert(chat);
|
|
4165
4223
|
}
|
|
4166
4224
|
});
|
|
4167
4225
|
}
|
|
4168
4226
|
function upsert(chat) {
|
|
4169
|
-
|
|
4227
|
+
chatsDB.upsert(chat);
|
|
4170
4228
|
}
|
|
4171
4229
|
function markDeleted(chatId) {
|
|
4172
|
-
|
|
4173
|
-
const chat = list.find((c) => c.id === chatId);
|
|
4174
|
-
if (!chat) return false;
|
|
4175
|
-
upsert({ ...chat, deletedAt: now() });
|
|
4176
|
-
return void 0;
|
|
4177
|
-
});
|
|
4230
|
+
chatsDB.markDeleted(chatId);
|
|
4178
4231
|
}
|
|
4179
4232
|
function getChatById(chatId) {
|
|
4180
|
-
return
|
|
4181
|
-
|
|
4182
|
-
|
|
4233
|
+
return chatsDB.getEvenIfDeleted(chatId);
|
|
4234
|
+
}
|
|
4235
|
+
function findMany(query) {
|
|
4236
|
+
return chatsDB.signal.get().findMany(query);
|
|
4183
4237
|
}
|
|
4184
4238
|
return {
|
|
4185
|
-
chats\u03A3: nonDeletedChats\u03A3,
|
|
4186
4239
|
getChatById,
|
|
4240
|
+
findMany,
|
|
4187
4241
|
// Mutations
|
|
4188
4242
|
upsert,
|
|
4189
4243
|
upsertMany,
|
|
@@ -4396,7 +4450,8 @@ function createAi(config) {
|
|
|
4396
4450
|
function getChats(options = {}) {
|
|
4397
4451
|
return sendClientMsgWithResponse({
|
|
4398
4452
|
cmd: "get-chats",
|
|
4399
|
-
cursor: options.cursor
|
|
4453
|
+
cursor: options.cursor,
|
|
4454
|
+
query: options.query
|
|
4400
4455
|
});
|
|
4401
4456
|
}
|
|
4402
4457
|
function getOrCreateChat(id, options) {
|
|
@@ -4461,7 +4516,9 @@ function createAi(config) {
|
|
|
4461
4516
|
deleteMessage: (chatId, messageId) => sendClientMsgWithResponse({ cmd: "delete-message", chatId, messageId }),
|
|
4462
4517
|
clearChat: (chatId) => sendClientMsgWithResponse({ cmd: "clear-chat", chatId }),
|
|
4463
4518
|
askUserMessageInChat: async (chatId, userMessage, targetMessageId, options) => {
|
|
4464
|
-
const
|
|
4519
|
+
const globalKnowledge = context.knowledge.get();
|
|
4520
|
+
const requestKnowledge = options?.knowledge || [];
|
|
4521
|
+
const combinedKnowledge = [...globalKnowledge, ...requestKnowledge];
|
|
4465
4522
|
const tools = context.toolsStore.getToolDescriptions(chatId);
|
|
4466
4523
|
const resp = await sendClientMsgWithResponse({
|
|
4467
4524
|
cmd: "ask-in-chat",
|
|
@@ -4472,9 +4529,8 @@ function createAi(config) {
|
|
|
4472
4529
|
copilotId: options?.copilotId,
|
|
4473
4530
|
stream: options?.stream,
|
|
4474
4531
|
timeout: options?.timeout,
|
|
4475
|
-
//
|
|
4476
|
-
|
|
4477
|
-
knowledge: knowledge.length > 0 ? knowledge : void 0,
|
|
4532
|
+
// Combine global knowledge with request-specific knowledge
|
|
4533
|
+
knowledge: combinedKnowledge.length > 0 ? combinedKnowledge : void 0,
|
|
4478
4534
|
tools: tools.length > 0 ? tools : void 0
|
|
4479
4535
|
}
|
|
4480
4536
|
});
|
|
@@ -4485,11 +4541,11 @@ function createAi(config) {
|
|
|
4485
4541
|
setToolResult,
|
|
4486
4542
|
getStatus: () => managedSocket.getStatus(),
|
|
4487
4543
|
signals: {
|
|
4488
|
-
chats\u03A3: context.chatsStore.chats\u03A3,
|
|
4489
4544
|
getChatMessagesForBranch\u03A3: context.messagesStore.getChatMessagesForBranch\u03A3,
|
|
4490
4545
|
getTool\u03A3: context.toolsStore.getTool\u03A3
|
|
4491
4546
|
},
|
|
4492
4547
|
getChatById: context.chatsStore.getChatById,
|
|
4548
|
+
queryChats: context.chatsStore.findMany,
|
|
4493
4549
|
registerKnowledgeLayer,
|
|
4494
4550
|
deregisterKnowledgeLayer,
|
|
4495
4551
|
updateKnowledge,
|