conversationalist 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -30
- package/dist/adapters/anthropic/index.d.ts.map +1 -1
- package/dist/adapters/anthropic/index.js +255 -2
- package/dist/adapters/anthropic/index.js.map +8 -4
- package/dist/adapters/gemini/index.d.ts.map +1 -1
- package/dist/adapters/gemini/index.js +255 -3
- package/dist/adapters/gemini/index.js.map +8 -4
- package/dist/adapters/openai/index.d.ts.map +1 -1
- package/dist/adapters/openai/index.js +247 -3
- package/dist/adapters/openai/index.js.map +8 -4
- package/dist/context.d.ts +6 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/conversation/append.d.ts +5 -0
- package/dist/conversation/append.d.ts.map +1 -1
- package/dist/conversation/create.d.ts +9 -0
- package/dist/conversation/create.d.ts.map +1 -1
- package/dist/conversation/index.d.ts +8 -3
- package/dist/conversation/index.d.ts.map +1 -1
- package/dist/conversation/integrity.d.ts +16 -0
- package/dist/conversation/integrity.d.ts.map +1 -0
- package/dist/conversation/modify.d.ts +8 -2
- package/dist/conversation/modify.d.ts.map +1 -1
- package/dist/conversation/serialization.d.ts +0 -17
- package/dist/conversation/serialization.d.ts.map +1 -1
- package/dist/conversation/system-messages.d.ts.map +1 -1
- package/dist/conversation/tool-interactions.d.ts +45 -0
- package/dist/conversation/tool-interactions.d.ts.map +1 -0
- package/dist/conversation/transform.d.ts.map +1 -1
- package/dist/conversation/validation.d.ts +8 -0
- package/dist/conversation/validation.d.ts.map +1 -0
- package/dist/errors.d.ts +6 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/export/index.js +249 -12
- package/dist/export/index.js.map +10 -6
- package/dist/guards.d.ts +13 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/history.d.ts +21 -8
- package/dist/history.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2212 -259
- package/dist/index.js.map +26 -13
- package/dist/markdown/index.js +2169 -253
- package/dist/markdown/index.js.map +23 -12
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +38 -22
- package/dist/schemas/index.js.map +3 -3
- package/dist/schemas.d.ts +17 -37
- package/dist/schemas.d.ts.map +1 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities/index.d.ts +0 -1
- package/dist/utilities/index.d.ts.map +1 -1
- package/dist/utilities/markdown.d.ts.map +1 -1
- package/dist/utilities/tool-calls.d.ts +2 -6
- package/dist/utilities/tool-calls.d.ts.map +1 -1
- package/dist/utilities/tool-results.d.ts.map +1 -1
- package/dist/utilities/transient.d.ts.map +1 -1
- package/dist/utilities.d.ts +0 -1
- package/dist/utilities.d.ts.map +1 -1
- package/dist/versioning/index.d.ts +0 -1
- package/dist/versioning/index.d.ts.map +1 -1
- package/dist/versioning/index.js +1 -52
- package/dist/versioning/index.js.map +4 -5
- package/dist/with-conversation.d.ts +4 -1
- package/dist/with-conversation.d.ts.map +1 -1
- package/package.json +7 -4
- package/dist/conversation.d.ts +0 -109
- package/dist/conversation.d.ts.map +0 -1
package/dist/markdown/index.js
CHANGED
|
@@ -2630,16 +2630,16 @@ var require_dumper = __commonJS((exports, module) => {
|
|
|
2630
2630
|
this.usedDuplicates = null;
|
|
2631
2631
|
}
|
|
2632
2632
|
function indentString(string, spaces) {
|
|
2633
|
-
var ind = common.repeat(" ", spaces), position = 0,
|
|
2633
|
+
var ind = common.repeat(" ", spaces), position = 0, next2 = -1, result = "", line, length = string.length;
|
|
2634
2634
|
while (position < length) {
|
|
2635
|
-
|
|
2635
|
+
next2 = string.indexOf(`
|
|
2636
2636
|
`, position);
|
|
2637
|
-
if (
|
|
2637
|
+
if (next2 === -1) {
|
|
2638
2638
|
line = string.slice(position);
|
|
2639
2639
|
position = length;
|
|
2640
2640
|
} else {
|
|
2641
|
-
line = string.slice(position,
|
|
2642
|
-
position =
|
|
2641
|
+
line = string.slice(position, next2 + 1);
|
|
2642
|
+
position = next2 + 1;
|
|
2643
2643
|
}
|
|
2644
2644
|
if (line.length && line !== `
|
|
2645
2645
|
`)
|
|
@@ -2800,17 +2800,17 @@ var require_dumper = __commonJS((exports, module) => {
|
|
|
2800
2800
|
return line;
|
|
2801
2801
|
var breakRe = / [^ ]/g;
|
|
2802
2802
|
var match;
|
|
2803
|
-
var start = 0, end, curr = 0,
|
|
2803
|
+
var start = 0, end, curr = 0, next2 = 0;
|
|
2804
2804
|
var result = "";
|
|
2805
2805
|
while (match = breakRe.exec(line)) {
|
|
2806
|
-
|
|
2807
|
-
if (
|
|
2808
|
-
end = curr > start ? curr :
|
|
2806
|
+
next2 = match.index;
|
|
2807
|
+
if (next2 - start > width) {
|
|
2808
|
+
end = curr > start ? curr : next2;
|
|
2809
2809
|
result += `
|
|
2810
2810
|
` + line.slice(start, end);
|
|
2811
2811
|
start = end + 1;
|
|
2812
2812
|
}
|
|
2813
|
-
curr =
|
|
2813
|
+
curr = next2;
|
|
2814
2814
|
}
|
|
2815
2815
|
result += `
|
|
2816
2816
|
`;
|
|
@@ -3491,6 +3491,1773 @@ var require_gray_matter = __commonJS((exports, module) => {
|
|
|
3491
3491
|
module.exports = matter;
|
|
3492
3492
|
});
|
|
3493
3493
|
|
|
3494
|
+
// node_modules/event-emission/dist/index.js
|
|
3495
|
+
var SymbolObservable = typeof Symbol === "function" && Symbol.observable || Symbol.for("@@observable");
|
|
3496
|
+
if (typeof Symbol === "function") {
|
|
3497
|
+
Symbol.observable = SymbolObservable;
|
|
3498
|
+
}
|
|
3499
|
+
function getMethod(obj, key) {
|
|
3500
|
+
if (obj === null || obj === undefined)
|
|
3501
|
+
return;
|
|
3502
|
+
const value = obj[key];
|
|
3503
|
+
if (value == null)
|
|
3504
|
+
return;
|
|
3505
|
+
if (typeof value !== "function") {
|
|
3506
|
+
throw new TypeError(value + " is not a function");
|
|
3507
|
+
}
|
|
3508
|
+
return value;
|
|
3509
|
+
}
|
|
3510
|
+
function hostReportError(e) {
|
|
3511
|
+
if (typeof queueMicrotask === "function") {
|
|
3512
|
+
queueMicrotask(() => {
|
|
3513
|
+
throw e;
|
|
3514
|
+
});
|
|
3515
|
+
} else {
|
|
3516
|
+
setTimeout(() => {
|
|
3517
|
+
throw e;
|
|
3518
|
+
});
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
function SubscriptionObserverImpl(subscription) {
|
|
3522
|
+
this._subscription = subscription;
|
|
3523
|
+
}
|
|
3524
|
+
SubscriptionObserverImpl.prototype = Object.create(Object.prototype);
|
|
3525
|
+
Object.defineProperties(SubscriptionObserverImpl.prototype, {
|
|
3526
|
+
constructor: { value: Object, configurable: true, writable: true },
|
|
3527
|
+
closed: {
|
|
3528
|
+
get() {
|
|
3529
|
+
return this._subscription._closed;
|
|
3530
|
+
},
|
|
3531
|
+
configurable: true
|
|
3532
|
+
},
|
|
3533
|
+
next: {
|
|
3534
|
+
value: function next(value) {
|
|
3535
|
+
const subscription = this._subscription;
|
|
3536
|
+
if (subscription._closed)
|
|
3537
|
+
return;
|
|
3538
|
+
const observer = subscription._observer;
|
|
3539
|
+
try {
|
|
3540
|
+
const m = getMethod(observer, "next");
|
|
3541
|
+
if (!m)
|
|
3542
|
+
return;
|
|
3543
|
+
return m.call(observer, value);
|
|
3544
|
+
} catch (e) {
|
|
3545
|
+
try {
|
|
3546
|
+
this.error(e);
|
|
3547
|
+
} catch (err) {
|
|
3548
|
+
hostReportError(err);
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
},
|
|
3552
|
+
configurable: true,
|
|
3553
|
+
writable: true
|
|
3554
|
+
},
|
|
3555
|
+
error: {
|
|
3556
|
+
value: function error(errorValue) {
|
|
3557
|
+
const subscription = this._subscription;
|
|
3558
|
+
if (subscription._closed)
|
|
3559
|
+
throw errorValue;
|
|
3560
|
+
subscription._closed = true;
|
|
3561
|
+
const observer = subscription._observer;
|
|
3562
|
+
try {
|
|
3563
|
+
const m = getMethod(observer, "error");
|
|
3564
|
+
if (m) {
|
|
3565
|
+
return m.call(observer, errorValue);
|
|
3566
|
+
}
|
|
3567
|
+
throw errorValue;
|
|
3568
|
+
} finally {
|
|
3569
|
+
subscription._cleanup();
|
|
3570
|
+
}
|
|
3571
|
+
},
|
|
3572
|
+
configurable: true,
|
|
3573
|
+
writable: true
|
|
3574
|
+
},
|
|
3575
|
+
complete: {
|
|
3576
|
+
value: function complete(value) {
|
|
3577
|
+
const subscription = this._subscription;
|
|
3578
|
+
if (subscription._closed)
|
|
3579
|
+
return;
|
|
3580
|
+
subscription._closed = true;
|
|
3581
|
+
const observer = subscription._observer;
|
|
3582
|
+
try {
|
|
3583
|
+
const m = getMethod(observer, "complete");
|
|
3584
|
+
if (m) {
|
|
3585
|
+
return m.call(observer, value);
|
|
3586
|
+
}
|
|
3587
|
+
return;
|
|
3588
|
+
} finally {
|
|
3589
|
+
subscription._cleanup();
|
|
3590
|
+
}
|
|
3591
|
+
},
|
|
3592
|
+
configurable: true,
|
|
3593
|
+
writable: true
|
|
3594
|
+
}
|
|
3595
|
+
});
|
|
3596
|
+
Object.defineProperty(SubscriptionObserverImpl.prototype.next, "length", { value: 1 });
|
|
3597
|
+
Object.defineProperty(SubscriptionObserverImpl.prototype.error, "length", { value: 1 });
|
|
3598
|
+
Object.defineProperty(SubscriptionObserverImpl.prototype.complete, "length", {
|
|
3599
|
+
value: 1
|
|
3600
|
+
});
|
|
3601
|
+
function Subscription(observer, subscriber) {
|
|
3602
|
+
this._observer = observer;
|
|
3603
|
+
this._cleanupFn = undefined;
|
|
3604
|
+
this._closed = false;
|
|
3605
|
+
const subscriptionObserver = new SubscriptionObserverImpl(this);
|
|
3606
|
+
try {
|
|
3607
|
+
const start = getMethod(observer, "start");
|
|
3608
|
+
if (start) {
|
|
3609
|
+
start.call(observer, this);
|
|
3610
|
+
}
|
|
3611
|
+
} catch (e) {
|
|
3612
|
+
hostReportError(e);
|
|
3613
|
+
}
|
|
3614
|
+
if (this._closed)
|
|
3615
|
+
return;
|
|
3616
|
+
try {
|
|
3617
|
+
const cleanup = subscriber(subscriptionObserver);
|
|
3618
|
+
if (cleanup != null) {
|
|
3619
|
+
if (typeof cleanup !== "function" && typeof cleanup.unsubscribe !== "function") {
|
|
3620
|
+
throw new TypeError(cleanup + " is not a function or a subscription");
|
|
3621
|
+
}
|
|
3622
|
+
this._cleanupFn = cleanup;
|
|
3623
|
+
if (this._closed) {
|
|
3624
|
+
this._cleanup();
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
} catch (e) {
|
|
3628
|
+
subscriptionObserver.error(e);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
Subscription.prototype = Object.create(Object.prototype);
|
|
3632
|
+
Object.defineProperties(Subscription.prototype, {
|
|
3633
|
+
constructor: { value: Object, configurable: true, writable: true },
|
|
3634
|
+
closed: {
|
|
3635
|
+
get() {
|
|
3636
|
+
return this._closed;
|
|
3637
|
+
},
|
|
3638
|
+
configurable: true
|
|
3639
|
+
},
|
|
3640
|
+
unsubscribe: {
|
|
3641
|
+
value: function unsubscribe() {
|
|
3642
|
+
if (this._closed)
|
|
3643
|
+
return;
|
|
3644
|
+
this._closed = true;
|
|
3645
|
+
this._cleanup();
|
|
3646
|
+
},
|
|
3647
|
+
configurable: true,
|
|
3648
|
+
writable: true
|
|
3649
|
+
},
|
|
3650
|
+
_cleanup: {
|
|
3651
|
+
value: function _cleanup() {
|
|
3652
|
+
const cleanup = this._cleanupFn;
|
|
3653
|
+
if (!cleanup)
|
|
3654
|
+
return;
|
|
3655
|
+
this._cleanupFn = undefined;
|
|
3656
|
+
try {
|
|
3657
|
+
if (typeof cleanup === "function") {
|
|
3658
|
+
cleanup();
|
|
3659
|
+
} else if (cleanup && typeof cleanup.unsubscribe === "function") {
|
|
3660
|
+
cleanup.unsubscribe();
|
|
3661
|
+
}
|
|
3662
|
+
} catch (e) {
|
|
3663
|
+
hostReportError(e);
|
|
3664
|
+
}
|
|
3665
|
+
},
|
|
3666
|
+
configurable: true,
|
|
3667
|
+
writable: true
|
|
3668
|
+
}
|
|
3669
|
+
});
|
|
3670
|
+
|
|
3671
|
+
class Observable {
|
|
3672
|
+
_subscriber;
|
|
3673
|
+
constructor(subscriber) {
|
|
3674
|
+
if (typeof subscriber !== "function") {
|
|
3675
|
+
throw new TypeError("Observable initializer must be a function");
|
|
3676
|
+
}
|
|
3677
|
+
this._subscriber = subscriber;
|
|
3678
|
+
}
|
|
3679
|
+
subscribe(observerOrNext, error2, complete2) {
|
|
3680
|
+
let observer;
|
|
3681
|
+
if (typeof observerOrNext === "function") {
|
|
3682
|
+
observer = {
|
|
3683
|
+
next: observerOrNext,
|
|
3684
|
+
error: error2,
|
|
3685
|
+
complete: complete2
|
|
3686
|
+
};
|
|
3687
|
+
} else if (typeof observerOrNext !== "object" || observerOrNext === null) {
|
|
3688
|
+
throw new TypeError(observerOrNext + " is not an object");
|
|
3689
|
+
} else {
|
|
3690
|
+
observer = observerOrNext;
|
|
3691
|
+
}
|
|
3692
|
+
return new Subscription(observer, this._subscriber);
|
|
3693
|
+
}
|
|
3694
|
+
[SymbolObservable]() {
|
|
3695
|
+
return this;
|
|
3696
|
+
}
|
|
3697
|
+
static of(...items) {
|
|
3698
|
+
const C = typeof this === "function" ? this : Observable;
|
|
3699
|
+
return new C((observer) => {
|
|
3700
|
+
for (let i = 0;i < items.length; ++i) {
|
|
3701
|
+
observer.next(items[i]);
|
|
3702
|
+
if (observer.closed)
|
|
3703
|
+
return;
|
|
3704
|
+
}
|
|
3705
|
+
observer.complete();
|
|
3706
|
+
});
|
|
3707
|
+
}
|
|
3708
|
+
static from(x) {
|
|
3709
|
+
const C = typeof this === "function" ? this : Observable;
|
|
3710
|
+
if (x == null)
|
|
3711
|
+
throw new TypeError(x + " is not an object");
|
|
3712
|
+
const method = x[SymbolObservable];
|
|
3713
|
+
if (method != null) {
|
|
3714
|
+
if (typeof method !== "function") {
|
|
3715
|
+
throw new TypeError(method + " is not a function");
|
|
3716
|
+
}
|
|
3717
|
+
const observable = method.call(x);
|
|
3718
|
+
if (Object(observable) !== observable) {
|
|
3719
|
+
throw new TypeError(observable + " is not an object");
|
|
3720
|
+
}
|
|
3721
|
+
if (observable.constructor === C) {
|
|
3722
|
+
return observable;
|
|
3723
|
+
}
|
|
3724
|
+
return new C((observer) => observable.subscribe(observer));
|
|
3725
|
+
}
|
|
3726
|
+
if (Symbol.iterator in x) {
|
|
3727
|
+
return new C((observer) => {
|
|
3728
|
+
for (const item of x) {
|
|
3729
|
+
observer.next(item);
|
|
3730
|
+
if (observer.closed)
|
|
3731
|
+
return;
|
|
3732
|
+
}
|
|
3733
|
+
observer.complete();
|
|
3734
|
+
});
|
|
3735
|
+
}
|
|
3736
|
+
throw new TypeError(x + " is not observable");
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
var PROXY_MARKER = Symbol.for("@lasercat/event-emission/proxy");
|
|
3740
|
+
var ORIGINAL_TARGET = Symbol.for("@lasercat/event-emission/original");
|
|
3741
|
+
var ARRAY_MUTATORS = new Set([
|
|
3742
|
+
"push",
|
|
3743
|
+
"pop",
|
|
3744
|
+
"shift",
|
|
3745
|
+
"unshift",
|
|
3746
|
+
"splice",
|
|
3747
|
+
"sort",
|
|
3748
|
+
"reverse",
|
|
3749
|
+
"fill",
|
|
3750
|
+
"copyWithin"
|
|
3751
|
+
]);
|
|
3752
|
+
function isProxyable(value) {
|
|
3753
|
+
return value !== null && typeof value === "object" && !isProxied(value) && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof Map) && !(value instanceof Set) && !(value instanceof WeakMap) && !(value instanceof WeakSet) && !(value instanceof Promise) && !(value instanceof Error) && !(value instanceof ArrayBuffer) && !ArrayBuffer.isView(value);
|
|
3754
|
+
}
|
|
3755
|
+
function isProxied(value) {
|
|
3756
|
+
return typeof value === "object" && value !== null && value[PROXY_MARKER] === true;
|
|
3757
|
+
}
|
|
3758
|
+
function isArrayMutator(prop) {
|
|
3759
|
+
return typeof prop === "string" && ARRAY_MUTATORS.has(prop);
|
|
3760
|
+
}
|
|
3761
|
+
function cloneAlongPath(obj, path) {
|
|
3762
|
+
const isArray = Array.isArray(obj);
|
|
3763
|
+
const rootClone = isArray ? [...obj] : { ...obj };
|
|
3764
|
+
if (!path || isArray) {
|
|
3765
|
+
return rootClone;
|
|
3766
|
+
}
|
|
3767
|
+
const parts = path.split(".");
|
|
3768
|
+
const result = rootClone;
|
|
3769
|
+
let current = result;
|
|
3770
|
+
for (let i = 0;i < parts.length; i++) {
|
|
3771
|
+
const key = parts[i];
|
|
3772
|
+
const value = current[key];
|
|
3773
|
+
if (value !== null && typeof value === "object") {
|
|
3774
|
+
current[key] = Array.isArray(value) ? [...value] : { ...value };
|
|
3775
|
+
if (i < parts.length - 1) {
|
|
3776
|
+
current = current[key];
|
|
3777
|
+
}
|
|
3778
|
+
} else {
|
|
3779
|
+
break;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
return result;
|
|
3783
|
+
}
|
|
3784
|
+
function cloneForComparison(obj, strategy, changedPath, deepClone) {
|
|
3785
|
+
if (obj === null || typeof obj !== "object")
|
|
3786
|
+
return obj;
|
|
3787
|
+
switch (strategy) {
|
|
3788
|
+
case "shallow":
|
|
3789
|
+
return Array.isArray(obj) ? [...obj] : { ...obj };
|
|
3790
|
+
case "deep":
|
|
3791
|
+
if (deepClone) {
|
|
3792
|
+
return deepClone(obj);
|
|
3793
|
+
}
|
|
3794
|
+
if (typeof structuredClone !== "function") {
|
|
3795
|
+
throw new Error("structuredClone is not available in this runtime; provide observe.deepClone, or use cloneStrategy 'path' or 'shallow'.");
|
|
3796
|
+
}
|
|
3797
|
+
return structuredClone(obj);
|
|
3798
|
+
case "path":
|
|
3799
|
+
return cloneAlongPath(obj, changedPath);
|
|
3800
|
+
default:
|
|
3801
|
+
return obj;
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
function computeArrayDiff(method, before, _after, args) {
|
|
3805
|
+
switch (method) {
|
|
3806
|
+
case "push":
|
|
3807
|
+
return { added: args };
|
|
3808
|
+
case "pop":
|
|
3809
|
+
return { removed: before.length > 0 ? [before[before.length - 1]] : [] };
|
|
3810
|
+
case "shift":
|
|
3811
|
+
return { removed: before.length > 0 ? [before[0]] : [] };
|
|
3812
|
+
case "unshift":
|
|
3813
|
+
return { added: args };
|
|
3814
|
+
case "splice": {
|
|
3815
|
+
const [start, deleteCount, ...items] = args;
|
|
3816
|
+
const actualStart = start < 0 ? Math.max(before.length + start, 0) : Math.min(start, before.length);
|
|
3817
|
+
const actualDeleteCount = Math.min(deleteCount ?? before.length - actualStart, before.length - actualStart);
|
|
3818
|
+
return {
|
|
3819
|
+
removed: before.slice(actualStart, actualStart + actualDeleteCount),
|
|
3820
|
+
added: items
|
|
3821
|
+
};
|
|
3822
|
+
}
|
|
3823
|
+
case "sort":
|
|
3824
|
+
case "reverse":
|
|
3825
|
+
case "fill":
|
|
3826
|
+
case "copyWithin":
|
|
3827
|
+
return {};
|
|
3828
|
+
default:
|
|
3829
|
+
return {};
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
var proxyRegistry = new WeakMap;
|
|
3833
|
+
function getContextRegistry(target) {
|
|
3834
|
+
let contextMap = proxyRegistry.get(target);
|
|
3835
|
+
if (!contextMap) {
|
|
3836
|
+
contextMap = new WeakMap;
|
|
3837
|
+
proxyRegistry.set(target, contextMap);
|
|
3838
|
+
}
|
|
3839
|
+
return contextMap;
|
|
3840
|
+
}
|
|
3841
|
+
function createArrayMethodInterceptor(array, method, path, context) {
|
|
3842
|
+
const original = array[method];
|
|
3843
|
+
return function(...args) {
|
|
3844
|
+
const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, path, context.options.deepClone);
|
|
3845
|
+
const previousItems = [...array];
|
|
3846
|
+
const result = original.apply(this, args);
|
|
3847
|
+
const { added, removed } = computeArrayDiff(method, previousItems, array, args);
|
|
3848
|
+
const methodEventPath = path ? `update:${path}.${method}` : `update:${method}`;
|
|
3849
|
+
const arrayEventPath = path ? `update:${path}` : "update:";
|
|
3850
|
+
context.eventTarget.dispatchEvent({
|
|
3851
|
+
type: methodEventPath,
|
|
3852
|
+
detail: {
|
|
3853
|
+
method,
|
|
3854
|
+
args,
|
|
3855
|
+
result,
|
|
3856
|
+
added,
|
|
3857
|
+
removed,
|
|
3858
|
+
current: context.originalRoot,
|
|
3859
|
+
previous: previousState
|
|
3860
|
+
}
|
|
3861
|
+
});
|
|
3862
|
+
if (path) {
|
|
3863
|
+
context.eventTarget.dispatchEvent({
|
|
3864
|
+
type: arrayEventPath,
|
|
3865
|
+
detail: {
|
|
3866
|
+
value: array,
|
|
3867
|
+
current: context.originalRoot,
|
|
3868
|
+
previous: previousState
|
|
3869
|
+
}
|
|
3870
|
+
});
|
|
3871
|
+
}
|
|
3872
|
+
context.eventTarget.dispatchEvent({
|
|
3873
|
+
type: "update",
|
|
3874
|
+
detail: {
|
|
3875
|
+
current: context.originalRoot,
|
|
3876
|
+
previous: previousState
|
|
3877
|
+
}
|
|
3878
|
+
});
|
|
3879
|
+
return result;
|
|
3880
|
+
};
|
|
3881
|
+
}
|
|
3882
|
+
function createObservableProxyInternal(target, path, context) {
|
|
3883
|
+
const contextRegistry = getContextRegistry(target);
|
|
3884
|
+
const existing = contextRegistry.get(context);
|
|
3885
|
+
if (existing) {
|
|
3886
|
+
return existing.proxy;
|
|
3887
|
+
}
|
|
3888
|
+
const proxy = new Proxy(target, {
|
|
3889
|
+
get(obj, prop, receiver) {
|
|
3890
|
+
if (prop === PROXY_MARKER)
|
|
3891
|
+
return true;
|
|
3892
|
+
if (prop === ORIGINAL_TARGET)
|
|
3893
|
+
return obj;
|
|
3894
|
+
if (typeof prop === "symbol") {
|
|
3895
|
+
return Reflect.get(obj, prop, receiver);
|
|
3896
|
+
}
|
|
3897
|
+
const value = Reflect.get(obj, prop, receiver);
|
|
3898
|
+
if (Array.isArray(obj) && isArrayMutator(prop)) {
|
|
3899
|
+
return createArrayMethodInterceptor(obj, prop, path, context);
|
|
3900
|
+
}
|
|
3901
|
+
if (context.options.deep && isProxyable(value)) {
|
|
3902
|
+
const nestedPath = path ? `${path}.${prop}` : prop;
|
|
3903
|
+
return createObservableProxyInternal(value, nestedPath, context);
|
|
3904
|
+
}
|
|
3905
|
+
return value;
|
|
3906
|
+
},
|
|
3907
|
+
set(obj, prop, value, receiver) {
|
|
3908
|
+
if (typeof prop === "symbol") {
|
|
3909
|
+
return Reflect.set(obj, prop, value, receiver);
|
|
3910
|
+
}
|
|
3911
|
+
const oldValue = Reflect.get(obj, prop, receiver);
|
|
3912
|
+
if (Object.is(oldValue, value)) {
|
|
3913
|
+
return true;
|
|
3914
|
+
}
|
|
3915
|
+
const propPath = path ? `${path}.${prop}` : prop;
|
|
3916
|
+
const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath, context.options.deepClone);
|
|
3917
|
+
const success = Reflect.set(obj, prop, value, receiver);
|
|
3918
|
+
if (success) {
|
|
3919
|
+
context.eventTarget.dispatchEvent({
|
|
3920
|
+
type: `update:${propPath}`,
|
|
3921
|
+
detail: {
|
|
3922
|
+
value,
|
|
3923
|
+
current: context.originalRoot,
|
|
3924
|
+
previous: previousState
|
|
3925
|
+
}
|
|
3926
|
+
});
|
|
3927
|
+
context.eventTarget.dispatchEvent({
|
|
3928
|
+
type: "update",
|
|
3929
|
+
detail: {
|
|
3930
|
+
current: context.originalRoot,
|
|
3931
|
+
previous: previousState
|
|
3932
|
+
}
|
|
3933
|
+
});
|
|
3934
|
+
}
|
|
3935
|
+
return success;
|
|
3936
|
+
},
|
|
3937
|
+
deleteProperty(obj, prop) {
|
|
3938
|
+
if (typeof prop === "symbol") {
|
|
3939
|
+
return Reflect.deleteProperty(obj, prop);
|
|
3940
|
+
}
|
|
3941
|
+
const propPath = path ? `${path}.${String(prop)}` : String(prop);
|
|
3942
|
+
const previousState = cloneForComparison(context.originalRoot, context.options.cloneStrategy, propPath, context.options.deepClone);
|
|
3943
|
+
const success = Reflect.deleteProperty(obj, prop);
|
|
3944
|
+
if (success) {
|
|
3945
|
+
context.eventTarget.dispatchEvent({
|
|
3946
|
+
type: `update:${propPath}`,
|
|
3947
|
+
detail: {
|
|
3948
|
+
value: undefined,
|
|
3949
|
+
current: context.originalRoot,
|
|
3950
|
+
previous: previousState
|
|
3951
|
+
}
|
|
3952
|
+
});
|
|
3953
|
+
context.eventTarget.dispatchEvent({
|
|
3954
|
+
type: "update",
|
|
3955
|
+
detail: {
|
|
3956
|
+
current: context.originalRoot,
|
|
3957
|
+
previous: previousState
|
|
3958
|
+
}
|
|
3959
|
+
});
|
|
3960
|
+
}
|
|
3961
|
+
return success;
|
|
3962
|
+
}
|
|
3963
|
+
});
|
|
3964
|
+
contextRegistry.set(context, {
|
|
3965
|
+
proxy,
|
|
3966
|
+
path
|
|
3967
|
+
});
|
|
3968
|
+
return proxy;
|
|
3969
|
+
}
|
|
3970
|
+
function isEventTarget(obj) {
|
|
3971
|
+
return typeof obj === "object" && obj !== null && typeof obj.addEventListener === "function" && typeof obj.removeEventListener === "function" && typeof obj.dispatchEvent === "function";
|
|
3972
|
+
}
|
|
3973
|
+
function setupEventForwarding(source, target) {
|
|
3974
|
+
const handlers = new Map;
|
|
3975
|
+
const sourceAddEventListener = source.addEventListener.bind(source);
|
|
3976
|
+
const sourceRemoveEventListener = source.removeEventListener.bind(source);
|
|
3977
|
+
const forwardHandler = (type) => (event) => {
|
|
3978
|
+
const detail = event.detail ?? event;
|
|
3979
|
+
target.dispatchEvent({
|
|
3980
|
+
type,
|
|
3981
|
+
detail
|
|
3982
|
+
});
|
|
3983
|
+
};
|
|
3984
|
+
const originalAddEventListener = target.addEventListener.bind(target);
|
|
3985
|
+
const wrappedAddEventListener = (type, listener, options2) => {
|
|
3986
|
+
if (!handlers.has(type) && type !== "update" && !type.startsWith("update:")) {
|
|
3987
|
+
const handler = forwardHandler(type);
|
|
3988
|
+
handlers.set(type, handler);
|
|
3989
|
+
sourceAddEventListener(type, handler);
|
|
3990
|
+
}
|
|
3991
|
+
return originalAddEventListener(type, listener, options2);
|
|
3992
|
+
};
|
|
3993
|
+
target.addEventListener = wrappedAddEventListener;
|
|
3994
|
+
return () => {
|
|
3995
|
+
target.addEventListener = originalAddEventListener;
|
|
3996
|
+
for (const [type, handler] of handlers) {
|
|
3997
|
+
sourceRemoveEventListener(type, handler);
|
|
3998
|
+
}
|
|
3999
|
+
handlers.clear();
|
|
4000
|
+
};
|
|
4001
|
+
}
|
|
4002
|
+
function createObservableProxy(target, eventTarget, options2) {
|
|
4003
|
+
const resolvedOptions = {
|
|
4004
|
+
deep: options2?.deep ?? true,
|
|
4005
|
+
cloneStrategy: options2?.cloneStrategy ?? "path",
|
|
4006
|
+
deepClone: options2?.deepClone
|
|
4007
|
+
};
|
|
4008
|
+
const context = {
|
|
4009
|
+
eventTarget,
|
|
4010
|
+
originalRoot: target,
|
|
4011
|
+
options: resolvedOptions
|
|
4012
|
+
};
|
|
4013
|
+
const proxy = createObservableProxyInternal(target, "", context);
|
|
4014
|
+
if (isEventTarget(target)) {
|
|
4015
|
+
const cleanupForwarding = setupEventForwarding(target, eventTarget);
|
|
4016
|
+
const maybeComplete = eventTarget.complete;
|
|
4017
|
+
if (typeof maybeComplete === "function") {
|
|
4018
|
+
const originalComplete = maybeComplete.bind(eventTarget);
|
|
4019
|
+
let cleaned = false;
|
|
4020
|
+
eventTarget.complete = () => {
|
|
4021
|
+
if (!cleaned) {
|
|
4022
|
+
cleaned = true;
|
|
4023
|
+
cleanupForwarding();
|
|
4024
|
+
}
|
|
4025
|
+
return originalComplete();
|
|
4026
|
+
};
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
return proxy;
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4032
|
+
class BufferOverflowError extends Error {
|
|
4033
|
+
constructor(eventType, bufferSize) {
|
|
4034
|
+
super(`Buffer overflow for event type "${eventType}" (max: ${bufferSize})`);
|
|
4035
|
+
this.name = "BufferOverflowError";
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
function matchesWildcard(eventType, pattern) {
|
|
4039
|
+
if (pattern === "*")
|
|
4040
|
+
return true;
|
|
4041
|
+
return pattern.endsWith(":*") && eventType.startsWith(pattern.slice(0, -2) + ":");
|
|
4042
|
+
}
|
|
4043
|
+
var EVENT_STATE = Symbol("event-emission:event-state");
|
|
4044
|
+
function createEventTarget(targetOrOpts, opts) {
|
|
4045
|
+
if (opts?.observe === true && targetOrOpts && typeof targetOrOpts === "object") {
|
|
4046
|
+
const target = targetOrOpts;
|
|
4047
|
+
const eventTarget = createEventTargetInternal({
|
|
4048
|
+
onListenerError: opts.onListenerError
|
|
4049
|
+
});
|
|
4050
|
+
const proxy = createObservableProxy(target, eventTarget, {
|
|
4051
|
+
deep: opts.deep,
|
|
4052
|
+
cloneStrategy: opts.cloneStrategy,
|
|
4053
|
+
deepClone: opts.deepClone
|
|
4054
|
+
});
|
|
4055
|
+
const methodNames = [
|
|
4056
|
+
"addEventListener",
|
|
4057
|
+
"removeEventListener",
|
|
4058
|
+
"dispatchEvent",
|
|
4059
|
+
"clear",
|
|
4060
|
+
"on",
|
|
4061
|
+
"once",
|
|
4062
|
+
"removeAllListeners",
|
|
4063
|
+
"pipe",
|
|
4064
|
+
"addWildcardListener",
|
|
4065
|
+
"removeWildcardListener",
|
|
4066
|
+
"complete",
|
|
4067
|
+
"subscribe",
|
|
4068
|
+
"toObservable",
|
|
4069
|
+
"events"
|
|
4070
|
+
];
|
|
4071
|
+
for (const name of methodNames) {
|
|
4072
|
+
Object.defineProperty(proxy, name, {
|
|
4073
|
+
value: eventTarget[name],
|
|
4074
|
+
writable: false,
|
|
4075
|
+
enumerable: false,
|
|
4076
|
+
configurable: true
|
|
4077
|
+
});
|
|
4078
|
+
}
|
|
4079
|
+
Object.defineProperty(proxy, "completed", {
|
|
4080
|
+
get: () => eventTarget.completed,
|
|
4081
|
+
enumerable: false,
|
|
4082
|
+
configurable: true
|
|
4083
|
+
});
|
|
4084
|
+
return proxy;
|
|
4085
|
+
}
|
|
4086
|
+
return createEventTargetInternal(targetOrOpts);
|
|
4087
|
+
}
|
|
4088
|
+
function createEventTargetInternal(opts) {
|
|
4089
|
+
const listeners = new Map;
|
|
4090
|
+
const wildcardListeners = new Set;
|
|
4091
|
+
let isCompleted = false;
|
|
4092
|
+
const completionCallbacks = new Set;
|
|
4093
|
+
const now = () => typeof globalThis.performance?.now === "function" ? globalThis.performance.now() : Date.now();
|
|
4094
|
+
const initializeEventState = (state, type, bubbles, cancelable) => {
|
|
4095
|
+
state.initializedFlag = true;
|
|
4096
|
+
state.stopPropagationFlag = false;
|
|
4097
|
+
state.stopImmediatePropagationFlag = false;
|
|
4098
|
+
state.canceledFlag = false;
|
|
4099
|
+
state.isTrusted = false;
|
|
4100
|
+
state.target = null;
|
|
4101
|
+
state.currentTarget = null;
|
|
4102
|
+
state.eventPhase = 0;
|
|
4103
|
+
state.type = type;
|
|
4104
|
+
state.bubbles = bubbles;
|
|
4105
|
+
state.cancelable = cancelable;
|
|
4106
|
+
};
|
|
4107
|
+
const setCanceledFlag = (state) => {
|
|
4108
|
+
if (state.cancelable && !state.inPassiveListenerFlag) {
|
|
4109
|
+
state.canceledFlag = true;
|
|
4110
|
+
}
|
|
4111
|
+
};
|
|
4112
|
+
const createEvent = (type, detail, init) => {
|
|
4113
|
+
const state = {
|
|
4114
|
+
dispatchFlag: false,
|
|
4115
|
+
initializedFlag: true,
|
|
4116
|
+
stopPropagationFlag: false,
|
|
4117
|
+
stopImmediatePropagationFlag: false,
|
|
4118
|
+
canceledFlag: false,
|
|
4119
|
+
inPassiveListenerFlag: false,
|
|
4120
|
+
composedFlag: Boolean(init?.composed),
|
|
4121
|
+
eventPhase: init?.eventPhase ?? 0,
|
|
4122
|
+
currentTarget: init?.currentTarget ?? init?.target ?? null,
|
|
4123
|
+
target: init?.target ?? null,
|
|
4124
|
+
timeStamp: init?.timeStamp ?? now(),
|
|
4125
|
+
path: [],
|
|
4126
|
+
type,
|
|
4127
|
+
bubbles: Boolean(init?.bubbles),
|
|
4128
|
+
cancelable: Boolean(init?.cancelable),
|
|
4129
|
+
isTrusted: false
|
|
4130
|
+
};
|
|
4131
|
+
const event = { detail };
|
|
4132
|
+
Object.defineProperties(event, {
|
|
4133
|
+
type: {
|
|
4134
|
+
get: () => state.type,
|
|
4135
|
+
enumerable: true,
|
|
4136
|
+
configurable: true
|
|
4137
|
+
},
|
|
4138
|
+
bubbles: {
|
|
4139
|
+
get: () => state.bubbles,
|
|
4140
|
+
enumerable: true,
|
|
4141
|
+
configurable: true
|
|
4142
|
+
},
|
|
4143
|
+
cancelable: {
|
|
4144
|
+
get: () => state.cancelable,
|
|
4145
|
+
enumerable: true,
|
|
4146
|
+
configurable: true
|
|
4147
|
+
},
|
|
4148
|
+
cancelBubble: {
|
|
4149
|
+
get: () => state.stopPropagationFlag,
|
|
4150
|
+
set: (value) => {
|
|
4151
|
+
if (value)
|
|
4152
|
+
state.stopPropagationFlag = true;
|
|
4153
|
+
},
|
|
4154
|
+
enumerable: true,
|
|
4155
|
+
configurable: true
|
|
4156
|
+
},
|
|
4157
|
+
composed: {
|
|
4158
|
+
get: () => state.composedFlag,
|
|
4159
|
+
enumerable: true,
|
|
4160
|
+
configurable: true
|
|
4161
|
+
},
|
|
4162
|
+
currentTarget: {
|
|
4163
|
+
get: () => state.currentTarget,
|
|
4164
|
+
enumerable: true,
|
|
4165
|
+
configurable: true
|
|
4166
|
+
},
|
|
4167
|
+
defaultPrevented: {
|
|
4168
|
+
get: () => state.canceledFlag,
|
|
4169
|
+
enumerable: true,
|
|
4170
|
+
configurable: true
|
|
4171
|
+
},
|
|
4172
|
+
eventPhase: {
|
|
4173
|
+
get: () => state.eventPhase,
|
|
4174
|
+
enumerable: true,
|
|
4175
|
+
configurable: true
|
|
4176
|
+
},
|
|
4177
|
+
isTrusted: {
|
|
4178
|
+
get: () => state.isTrusted,
|
|
4179
|
+
enumerable: true,
|
|
4180
|
+
configurable: true
|
|
4181
|
+
},
|
|
4182
|
+
returnValue: {
|
|
4183
|
+
get: () => !state.canceledFlag,
|
|
4184
|
+
set: (value) => {
|
|
4185
|
+
if (value === false)
|
|
4186
|
+
setCanceledFlag(state);
|
|
4187
|
+
},
|
|
4188
|
+
enumerable: true,
|
|
4189
|
+
configurable: true
|
|
4190
|
+
},
|
|
4191
|
+
srcElement: {
|
|
4192
|
+
get: () => state.target,
|
|
4193
|
+
enumerable: true,
|
|
4194
|
+
configurable: true
|
|
4195
|
+
},
|
|
4196
|
+
target: {
|
|
4197
|
+
get: () => state.target,
|
|
4198
|
+
enumerable: true,
|
|
4199
|
+
configurable: true
|
|
4200
|
+
},
|
|
4201
|
+
timeStamp: {
|
|
4202
|
+
get: () => state.timeStamp,
|
|
4203
|
+
enumerable: true,
|
|
4204
|
+
configurable: true
|
|
4205
|
+
},
|
|
4206
|
+
composedPath: {
|
|
4207
|
+
value: () => state.path.map((entry) => entry.invocationTarget),
|
|
4208
|
+
enumerable: true,
|
|
4209
|
+
configurable: true
|
|
4210
|
+
},
|
|
4211
|
+
initEvent: {
|
|
4212
|
+
value: (newType, bubbles = false, cancelable = false) => {
|
|
4213
|
+
if (state.dispatchFlag)
|
|
4214
|
+
return;
|
|
4215
|
+
initializeEventState(state, newType, Boolean(bubbles), Boolean(cancelable));
|
|
4216
|
+
},
|
|
4217
|
+
enumerable: true,
|
|
4218
|
+
configurable: true
|
|
4219
|
+
},
|
|
4220
|
+
preventDefault: {
|
|
4221
|
+
value: () => setCanceledFlag(state),
|
|
4222
|
+
enumerable: true,
|
|
4223
|
+
configurable: true
|
|
4224
|
+
},
|
|
4225
|
+
stopImmediatePropagation: {
|
|
4226
|
+
value: () => {
|
|
4227
|
+
state.stopPropagationFlag = true;
|
|
4228
|
+
state.stopImmediatePropagationFlag = true;
|
|
4229
|
+
},
|
|
4230
|
+
enumerable: true,
|
|
4231
|
+
configurable: true
|
|
4232
|
+
},
|
|
4233
|
+
stopPropagation: {
|
|
4234
|
+
value: () => {
|
|
4235
|
+
state.stopPropagationFlag = true;
|
|
4236
|
+
},
|
|
4237
|
+
enumerable: true,
|
|
4238
|
+
configurable: true
|
|
4239
|
+
},
|
|
4240
|
+
NONE: { value: 0, enumerable: true, configurable: true },
|
|
4241
|
+
CAPTURING_PHASE: { value: 1, enumerable: true, configurable: true },
|
|
4242
|
+
AT_TARGET: { value: 2, enumerable: true, configurable: true },
|
|
4243
|
+
BUBBLING_PHASE: { value: 3, enumerable: true, configurable: true },
|
|
4244
|
+
[EVENT_STATE]: {
|
|
4245
|
+
value: state,
|
|
4246
|
+
enumerable: false,
|
|
4247
|
+
configurable: false
|
|
4248
|
+
}
|
|
4249
|
+
});
|
|
4250
|
+
return event;
|
|
4251
|
+
};
|
|
4252
|
+
const getEventState = (event) => event[EVENT_STATE];
|
|
4253
|
+
const normalizeAddListenerOptions = (options2) => {
|
|
4254
|
+
if (typeof options2 === "boolean") {
|
|
4255
|
+
return {
|
|
4256
|
+
capture: options2,
|
|
4257
|
+
passive: false,
|
|
4258
|
+
once: false,
|
|
4259
|
+
signal: null
|
|
4260
|
+
};
|
|
4261
|
+
}
|
|
4262
|
+
return {
|
|
4263
|
+
capture: Boolean(options2?.capture),
|
|
4264
|
+
passive: Boolean(options2?.passive),
|
|
4265
|
+
once: Boolean(options2?.once),
|
|
4266
|
+
signal: options2?.signal ?? null
|
|
4267
|
+
};
|
|
4268
|
+
};
|
|
4269
|
+
const normalizeCaptureOption = (options2) => {
|
|
4270
|
+
if (typeof options2 === "boolean")
|
|
4271
|
+
return options2;
|
|
4272
|
+
return Boolean(options2?.capture);
|
|
4273
|
+
};
|
|
4274
|
+
const removeListenerRecord = (type, record) => {
|
|
4275
|
+
if (record.removed)
|
|
4276
|
+
return;
|
|
4277
|
+
record.removed = true;
|
|
4278
|
+
const list = listeners.get(type);
|
|
4279
|
+
if (list) {
|
|
4280
|
+
const idx = list.indexOf(record);
|
|
4281
|
+
if (idx >= 0)
|
|
4282
|
+
list.splice(idx, 1);
|
|
4283
|
+
if (list.length === 0)
|
|
4284
|
+
listeners.delete(type);
|
|
4285
|
+
}
|
|
4286
|
+
if (record.signal && record.abortHandler) {
|
|
4287
|
+
record.signal.removeEventListener("abort", record.abortHandler);
|
|
4288
|
+
}
|
|
4289
|
+
};
|
|
4290
|
+
const handleListenerError = (eventType, error2) => {
|
|
4291
|
+
if (eventType === "error")
|
|
4292
|
+
return;
|
|
4293
|
+
if (opts?.onListenerError) {
|
|
4294
|
+
opts.onListenerError(eventType, error2);
|
|
4295
|
+
return;
|
|
4296
|
+
}
|
|
4297
|
+
const errorListeners = listeners.get("error");
|
|
4298
|
+
if (errorListeners && errorListeners.length > 0) {
|
|
4299
|
+
dispatchEvent({ type: "error", detail: error2 });
|
|
4300
|
+
} else {
|
|
4301
|
+
throw error2;
|
|
4302
|
+
}
|
|
4303
|
+
};
|
|
4304
|
+
const notifyWildcardListeners = (eventType, event) => {
|
|
4305
|
+
if (wildcardListeners.size === 0)
|
|
4306
|
+
return;
|
|
4307
|
+
for (const rec of Array.from(wildcardListeners)) {
|
|
4308
|
+
if (!matchesWildcard(eventType, rec.pattern))
|
|
4309
|
+
continue;
|
|
4310
|
+
const baseEvent = createEvent(rec.pattern, event.detail, {
|
|
4311
|
+
target,
|
|
4312
|
+
currentTarget: target,
|
|
4313
|
+
eventPhase: 2,
|
|
4314
|
+
bubbles: event.bubbles,
|
|
4315
|
+
cancelable: event.cancelable,
|
|
4316
|
+
composed: event.composed
|
|
4317
|
+
});
|
|
4318
|
+
const wildcardEvent = Object.defineProperties(baseEvent, {
|
|
4319
|
+
originalType: { value: eventType, enumerable: true, configurable: true }
|
|
4320
|
+
});
|
|
4321
|
+
try {
|
|
4322
|
+
const fn = rec.fn;
|
|
4323
|
+
const res = fn(wildcardEvent);
|
|
4324
|
+
if (res && typeof res.then === "function") {
|
|
4325
|
+
res.catch((error2) => {
|
|
4326
|
+
try {
|
|
4327
|
+
handleListenerError(eventType, error2);
|
|
4328
|
+
} catch (rethrown) {
|
|
4329
|
+
queueMicrotask(() => {
|
|
4330
|
+
throw rethrown;
|
|
4331
|
+
});
|
|
4332
|
+
}
|
|
4333
|
+
});
|
|
4334
|
+
}
|
|
4335
|
+
} catch (error2) {
|
|
4336
|
+
handleListenerError(eventType, error2);
|
|
4337
|
+
} finally {
|
|
4338
|
+
if (rec.once)
|
|
4339
|
+
wildcardListeners.delete(rec);
|
|
4340
|
+
}
|
|
4341
|
+
const state = getEventState(wildcardEvent);
|
|
4342
|
+
if (state?.stopImmediatePropagationFlag || state?.stopPropagationFlag) {
|
|
4343
|
+
break;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
};
|
|
4347
|
+
const addEventListener = (type, listener, options2) => {
|
|
4348
|
+
if (isCompleted || !listener) {
|
|
4349
|
+
return () => {};
|
|
4350
|
+
}
|
|
4351
|
+
const { capture, passive, once, signal } = normalizeAddListenerOptions(options2);
|
|
4352
|
+
let list = listeners.get(type);
|
|
4353
|
+
if (!list) {
|
|
4354
|
+
list = [];
|
|
4355
|
+
listeners.set(type, list);
|
|
4356
|
+
}
|
|
4357
|
+
for (const existing of list) {
|
|
4358
|
+
if (existing.original === listener && existing.capture === capture) {
|
|
4359
|
+
return () => removeEventListener(type, listener, options2);
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
const original = listener;
|
|
4363
|
+
const callback = typeof listener === "function" ? listener : (event) => listener.handleEvent(event);
|
|
4364
|
+
const record = {
|
|
4365
|
+
type,
|
|
4366
|
+
original,
|
|
4367
|
+
callback,
|
|
4368
|
+
capture,
|
|
4369
|
+
passive,
|
|
4370
|
+
once,
|
|
4371
|
+
signal,
|
|
4372
|
+
removed: false
|
|
4373
|
+
};
|
|
4374
|
+
list.push(record);
|
|
4375
|
+
const unsubscribe2 = () => removeListenerRecord(type, record);
|
|
4376
|
+
if (signal) {
|
|
4377
|
+
const onAbort = () => removeListenerRecord(type, record);
|
|
4378
|
+
record.abortHandler = onAbort;
|
|
4379
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4380
|
+
if (signal.aborted)
|
|
4381
|
+
onAbort();
|
|
4382
|
+
}
|
|
4383
|
+
return unsubscribe2;
|
|
4384
|
+
};
|
|
4385
|
+
const addWildcardListener = (pattern, listener, options2) => {
|
|
4386
|
+
if (isCompleted)
|
|
4387
|
+
return () => {};
|
|
4388
|
+
const opts2 = options2 ?? {};
|
|
4389
|
+
for (const existing of wildcardListeners) {
|
|
4390
|
+
if (existing.pattern === pattern && existing.fn === listener) {
|
|
4391
|
+
return () => removeWildcardListener(pattern, listener);
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
const record = {
|
|
4395
|
+
fn: listener,
|
|
4396
|
+
pattern,
|
|
4397
|
+
once: opts2.once,
|
|
4398
|
+
signal: opts2.signal
|
|
4399
|
+
};
|
|
4400
|
+
wildcardListeners.add(record);
|
|
4401
|
+
const unsubscribe2 = () => {
|
|
4402
|
+
wildcardListeners.delete(record);
|
|
4403
|
+
if (record.signal && record.abortHandler) {
|
|
4404
|
+
record.signal.removeEventListener("abort", record.abortHandler);
|
|
4405
|
+
}
|
|
4406
|
+
};
|
|
4407
|
+
if (opts2.signal) {
|
|
4408
|
+
const onAbort = () => unsubscribe2();
|
|
4409
|
+
record.abortHandler = onAbort;
|
|
4410
|
+
opts2.signal.addEventListener("abort", onAbort, { once: true });
|
|
4411
|
+
if (opts2.signal.aborted)
|
|
4412
|
+
onAbort();
|
|
4413
|
+
}
|
|
4414
|
+
return unsubscribe2;
|
|
4415
|
+
};
|
|
4416
|
+
const removeWildcardListener = (pattern, listener) => {
|
|
4417
|
+
for (const record of Array.from(wildcardListeners)) {
|
|
4418
|
+
if (record.pattern === pattern && record.fn === listener) {
|
|
4419
|
+
wildcardListeners.delete(record);
|
|
4420
|
+
if (record.signal && record.abortHandler) {
|
|
4421
|
+
record.signal.removeEventListener("abort", record.abortHandler);
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
4424
|
+
}
|
|
4425
|
+
};
|
|
4426
|
+
const invokeListeners = (eventType, event, phase, listenersSnapshot) => {
|
|
4427
|
+
const state = getEventState(event);
|
|
4428
|
+
if (!state || state.stopPropagationFlag)
|
|
4429
|
+
return;
|
|
4430
|
+
state.currentTarget = target;
|
|
4431
|
+
state.target = target;
|
|
4432
|
+
state.eventPhase = event.AT_TARGET;
|
|
4433
|
+
for (const rec of listenersSnapshot) {
|
|
4434
|
+
if (rec.removed)
|
|
4435
|
+
continue;
|
|
4436
|
+
if (phase === "capturing" && !rec.capture)
|
|
4437
|
+
continue;
|
|
4438
|
+
if (phase === "bubbling" && rec.capture)
|
|
4439
|
+
continue;
|
|
4440
|
+
if (rec.once)
|
|
4441
|
+
removeListenerRecord(rec.type, rec);
|
|
4442
|
+
if (rec.passive)
|
|
4443
|
+
state.inPassiveListenerFlag = true;
|
|
4444
|
+
try {
|
|
4445
|
+
const res = rec.callback.call(state.currentTarget, event);
|
|
4446
|
+
if (res && typeof res.then === "function") {
|
|
4447
|
+
res.catch((error2) => {
|
|
4448
|
+
try {
|
|
4449
|
+
handleListenerError(eventType, error2);
|
|
4450
|
+
} catch (rethrown) {
|
|
4451
|
+
queueMicrotask(() => {
|
|
4452
|
+
throw rethrown;
|
|
4453
|
+
});
|
|
4454
|
+
}
|
|
4455
|
+
});
|
|
4456
|
+
}
|
|
4457
|
+
} catch (error2) {
|
|
4458
|
+
handleListenerError(eventType, error2);
|
|
4459
|
+
} finally {
|
|
4460
|
+
if (rec.passive)
|
|
4461
|
+
state.inPassiveListenerFlag = false;
|
|
4462
|
+
}
|
|
4463
|
+
if (state.stopImmediatePropagationFlag)
|
|
4464
|
+
break;
|
|
4465
|
+
}
|
|
4466
|
+
};
|
|
4467
|
+
const dispatchEvent = (eventInput) => {
|
|
4468
|
+
if (isCompleted)
|
|
4469
|
+
return false;
|
|
4470
|
+
let event;
|
|
4471
|
+
let state;
|
|
4472
|
+
if (eventInput && typeof eventInput === "object") {
|
|
4473
|
+
state = getEventState(eventInput);
|
|
4474
|
+
if (state) {
|
|
4475
|
+
event = eventInput;
|
|
4476
|
+
} else {
|
|
4477
|
+
const input = eventInput;
|
|
4478
|
+
if (typeof input.type !== "string") {
|
|
4479
|
+
throw new TypeError("Event type must be a string");
|
|
4480
|
+
}
|
|
4481
|
+
event = createEvent(input.type, input.detail, {
|
|
4482
|
+
bubbles: input.bubbles,
|
|
4483
|
+
cancelable: input.cancelable,
|
|
4484
|
+
composed: input.composed,
|
|
4485
|
+
timeStamp: input.timeStamp
|
|
4486
|
+
});
|
|
4487
|
+
state = getEventState(event);
|
|
4488
|
+
}
|
|
4489
|
+
} else {
|
|
4490
|
+
throw new TypeError("dispatchEvent expects an event object");
|
|
4491
|
+
}
|
|
4492
|
+
const dispatchState = state ?? getEventState(event);
|
|
4493
|
+
if (dispatchState.dispatchFlag || !dispatchState.initializedFlag) {
|
|
4494
|
+
const message = "Failed to execute dispatchEvent: event is already being dispatched";
|
|
4495
|
+
if (typeof globalThis.DOMException === "function") {
|
|
4496
|
+
throw new globalThis.DOMException(message, "InvalidStateError");
|
|
4497
|
+
}
|
|
4498
|
+
const err = new Error(message);
|
|
4499
|
+
err.name = "InvalidStateError";
|
|
4500
|
+
throw err;
|
|
4501
|
+
}
|
|
4502
|
+
dispatchState.isTrusted = false;
|
|
4503
|
+
dispatchState.dispatchFlag = true;
|
|
4504
|
+
dispatchState.path = [
|
|
4505
|
+
{
|
|
4506
|
+
invocationTarget: target,
|
|
4507
|
+
invocationTargetInShadowTree: false,
|
|
4508
|
+
shadowAdjustedTarget: target,
|
|
4509
|
+
relatedTarget: null,
|
|
4510
|
+
touchTargets: [],
|
|
4511
|
+
rootOfClosedTree: false,
|
|
4512
|
+
slotInClosedTree: false
|
|
4513
|
+
}
|
|
4514
|
+
];
|
|
4515
|
+
notifyWildcardListeners(dispatchState.type, event);
|
|
4516
|
+
const list = listeners.get(dispatchState.type);
|
|
4517
|
+
const snapshot = list ? list.slice() : [];
|
|
4518
|
+
invokeListeners(dispatchState.type, event, "capturing", snapshot);
|
|
4519
|
+
invokeListeners(dispatchState.type, event, "bubbling", snapshot);
|
|
4520
|
+
dispatchState.eventPhase = event.NONE;
|
|
4521
|
+
dispatchState.currentTarget = null;
|
|
4522
|
+
dispatchState.path = [];
|
|
4523
|
+
dispatchState.dispatchFlag = false;
|
|
4524
|
+
dispatchState.stopPropagationFlag = false;
|
|
4525
|
+
dispatchState.stopImmediatePropagationFlag = false;
|
|
4526
|
+
return !dispatchState.canceledFlag;
|
|
4527
|
+
};
|
|
4528
|
+
const removeEventListener = (type, listener, options2) => {
|
|
4529
|
+
if (!listener)
|
|
4530
|
+
return;
|
|
4531
|
+
const capture = normalizeCaptureOption(options2);
|
|
4532
|
+
const list = listeners.get(type);
|
|
4533
|
+
if (!list)
|
|
4534
|
+
return;
|
|
4535
|
+
for (const record of [...list]) {
|
|
4536
|
+
if (record.original === listener && record.capture === capture) {
|
|
4537
|
+
removeListenerRecord(type, record);
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4540
|
+
};
|
|
4541
|
+
const clear = () => {
|
|
4542
|
+
for (const [type, list] of Array.from(listeners.entries())) {
|
|
4543
|
+
for (const record of [...list]) {
|
|
4544
|
+
removeListenerRecord(type, record);
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4547
|
+
listeners.clear();
|
|
4548
|
+
for (const record of wildcardListeners) {
|
|
4549
|
+
if (record.signal && record.abortHandler) {
|
|
4550
|
+
record.signal.removeEventListener("abort", record.abortHandler);
|
|
4551
|
+
}
|
|
4552
|
+
}
|
|
4553
|
+
wildcardListeners.clear();
|
|
4554
|
+
};
|
|
4555
|
+
const on = (type, options2) => {
|
|
4556
|
+
return new Observable((observer) => {
|
|
4557
|
+
let opts2;
|
|
4558
|
+
if (typeof options2 === "boolean") {
|
|
4559
|
+
opts2 = { capture: options2 };
|
|
4560
|
+
} else {
|
|
4561
|
+
opts2 = options2 ?? {};
|
|
4562
|
+
}
|
|
4563
|
+
const handler = opts2.handler;
|
|
4564
|
+
const once = opts2.once;
|
|
4565
|
+
const eventHandler = (e) => {
|
|
4566
|
+
let success = false;
|
|
4567
|
+
try {
|
|
4568
|
+
if (handler) {
|
|
4569
|
+
handler(e);
|
|
4570
|
+
}
|
|
4571
|
+
observer.next(e);
|
|
4572
|
+
success = true;
|
|
4573
|
+
} finally {
|
|
4574
|
+
if (once && success) {
|
|
4575
|
+
observer.complete();
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4578
|
+
};
|
|
4579
|
+
const errorHandler = (e) => {
|
|
4580
|
+
observer.error(e.detail);
|
|
4581
|
+
};
|
|
4582
|
+
const unsubscribeEvent = addEventListener(type, eventHandler, opts2);
|
|
4583
|
+
let unsubscribeError;
|
|
4584
|
+
if (opts2.receiveError) {
|
|
4585
|
+
unsubscribeError = addEventListener("error", errorHandler, opts2);
|
|
4586
|
+
}
|
|
4587
|
+
return () => {
|
|
4588
|
+
unsubscribeEvent();
|
|
4589
|
+
if (unsubscribeError) {
|
|
4590
|
+
unsubscribeError();
|
|
4591
|
+
}
|
|
4592
|
+
};
|
|
4593
|
+
});
|
|
4594
|
+
};
|
|
4595
|
+
const onceMethod = (type, listener, options2) => {
|
|
4596
|
+
if (typeof options2 === "boolean") {
|
|
4597
|
+
return addEventListener(type, listener, { capture: options2, once: true });
|
|
4598
|
+
}
|
|
4599
|
+
return addEventListener(type, listener, { ...options2 ?? {}, once: true });
|
|
4600
|
+
};
|
|
4601
|
+
const removeAllListeners = (type) => {
|
|
4602
|
+
if (type !== undefined) {
|
|
4603
|
+
const list = listeners.get(type);
|
|
4604
|
+
if (list) {
|
|
4605
|
+
for (const record of [...list]) {
|
|
4606
|
+
removeListenerRecord(type, record);
|
|
4607
|
+
}
|
|
4608
|
+
listeners.delete(type);
|
|
4609
|
+
}
|
|
4610
|
+
} else {
|
|
4611
|
+
for (const [eventType, list] of Array.from(listeners.entries())) {
|
|
4612
|
+
for (const record of [...list]) {
|
|
4613
|
+
removeListenerRecord(eventType, record);
|
|
4614
|
+
}
|
|
4615
|
+
}
|
|
4616
|
+
listeners.clear();
|
|
4617
|
+
for (const record of wildcardListeners) {
|
|
4618
|
+
if (record.signal && record.abortHandler) {
|
|
4619
|
+
record.signal.removeEventListener("abort", record.abortHandler);
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
wildcardListeners.clear();
|
|
4623
|
+
}
|
|
4624
|
+
};
|
|
4625
|
+
const pipe = (target2, mapFn) => {
|
|
4626
|
+
if (isCompleted) {
|
|
4627
|
+
return () => {};
|
|
4628
|
+
}
|
|
4629
|
+
const unsubscribe2 = addWildcardListener("*", (event) => {
|
|
4630
|
+
if (mapFn) {
|
|
4631
|
+
const mapped = mapFn(createEvent(event.originalType, event.detail, {
|
|
4632
|
+
target: target2,
|
|
4633
|
+
currentTarget: target2,
|
|
4634
|
+
eventPhase: 2,
|
|
4635
|
+
bubbles: event.bubbles,
|
|
4636
|
+
cancelable: event.cancelable,
|
|
4637
|
+
composed: event.composed
|
|
4638
|
+
}));
|
|
4639
|
+
if (mapped !== null) {
|
|
4640
|
+
target2.dispatchEvent(mapped);
|
|
4641
|
+
}
|
|
4642
|
+
} else {
|
|
4643
|
+
target2.dispatchEvent({
|
|
4644
|
+
type: event.originalType,
|
|
4645
|
+
detail: event.detail
|
|
4646
|
+
});
|
|
4647
|
+
}
|
|
4648
|
+
});
|
|
4649
|
+
const completionUnsub = () => {
|
|
4650
|
+
unsubscribe2();
|
|
4651
|
+
};
|
|
4652
|
+
completionCallbacks.add(completionUnsub);
|
|
4653
|
+
return () => {
|
|
4654
|
+
completionCallbacks.delete(completionUnsub);
|
|
4655
|
+
unsubscribe2();
|
|
4656
|
+
};
|
|
4657
|
+
};
|
|
4658
|
+
const complete2 = () => {
|
|
4659
|
+
if (isCompleted)
|
|
4660
|
+
return;
|
|
4661
|
+
isCompleted = true;
|
|
4662
|
+
for (const cb of completionCallbacks) {
|
|
4663
|
+
try {
|
|
4664
|
+
cb();
|
|
4665
|
+
} catch (err) {
|
|
4666
|
+
try {
|
|
4667
|
+
handleListenerError("complete", err);
|
|
4668
|
+
} catch {}
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
completionCallbacks.clear();
|
|
4672
|
+
for (const [eventType, list] of Array.from(listeners.entries())) {
|
|
4673
|
+
for (const record of [...list]) {
|
|
4674
|
+
removeListenerRecord(eventType, record);
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
listeners.clear();
|
|
4678
|
+
for (const record of wildcardListeners) {
|
|
4679
|
+
if (record.signal && record.abortHandler) {
|
|
4680
|
+
record.signal.removeEventListener("abort", record.abortHandler);
|
|
4681
|
+
}
|
|
4682
|
+
}
|
|
4683
|
+
wildcardListeners.clear();
|
|
4684
|
+
};
|
|
4685
|
+
const subscribe = (type, observerOrNext, error2, completeHandler) => {
|
|
4686
|
+
let observer;
|
|
4687
|
+
if (typeof observerOrNext === "function") {
|
|
4688
|
+
observer = {
|
|
4689
|
+
next: observerOrNext,
|
|
4690
|
+
error: error2,
|
|
4691
|
+
complete: completeHandler
|
|
4692
|
+
};
|
|
4693
|
+
} else {
|
|
4694
|
+
observer = observerOrNext ?? {};
|
|
4695
|
+
}
|
|
4696
|
+
let closed = false;
|
|
4697
|
+
if (isCompleted) {
|
|
4698
|
+
if (observer.complete) {
|
|
4699
|
+
try {
|
|
4700
|
+
observer.complete();
|
|
4701
|
+
} catch {}
|
|
4702
|
+
}
|
|
4703
|
+
return {
|
|
4704
|
+
unsubscribe: () => {
|
|
4705
|
+
closed = true;
|
|
4706
|
+
},
|
|
4707
|
+
get closed() {
|
|
4708
|
+
return closed || isCompleted;
|
|
4709
|
+
}
|
|
4710
|
+
};
|
|
4711
|
+
}
|
|
4712
|
+
const unsub = addEventListener(type, (event) => {
|
|
4713
|
+
if (closed)
|
|
4714
|
+
return;
|
|
4715
|
+
if (observer.next) {
|
|
4716
|
+
try {
|
|
4717
|
+
observer.next(event);
|
|
4718
|
+
} catch (err) {
|
|
4719
|
+
if (observer.error) {
|
|
4720
|
+
try {
|
|
4721
|
+
observer.error(err);
|
|
4722
|
+
} catch {}
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4726
|
+
});
|
|
4727
|
+
const onComplete = () => {
|
|
4728
|
+
if (closed)
|
|
4729
|
+
return;
|
|
4730
|
+
closed = true;
|
|
4731
|
+
if (observer.complete) {
|
|
4732
|
+
try {
|
|
4733
|
+
observer.complete();
|
|
4734
|
+
} catch {}
|
|
4735
|
+
}
|
|
4736
|
+
};
|
|
4737
|
+
completionCallbacks.add(onComplete);
|
|
4738
|
+
return {
|
|
4739
|
+
unsubscribe: () => {
|
|
4740
|
+
if (closed)
|
|
4741
|
+
return;
|
|
4742
|
+
closed = true;
|
|
4743
|
+
completionCallbacks.delete(onComplete);
|
|
4744
|
+
unsub();
|
|
4745
|
+
},
|
|
4746
|
+
get closed() {
|
|
4747
|
+
return closed || isCompleted;
|
|
4748
|
+
}
|
|
4749
|
+
};
|
|
4750
|
+
};
|
|
4751
|
+
const toObservable = () => {
|
|
4752
|
+
return new Observable((observer) => {
|
|
4753
|
+
if (isCompleted) {
|
|
4754
|
+
observer.complete();
|
|
4755
|
+
return;
|
|
4756
|
+
}
|
|
4757
|
+
const wildcardListener = (event) => {
|
|
4758
|
+
observer.next(createEvent(event.originalType, event.detail, {
|
|
4759
|
+
target,
|
|
4760
|
+
currentTarget: target,
|
|
4761
|
+
eventPhase: 2,
|
|
4762
|
+
bubbles: event.bubbles,
|
|
4763
|
+
cancelable: event.cancelable,
|
|
4764
|
+
composed: event.composed
|
|
4765
|
+
}));
|
|
4766
|
+
};
|
|
4767
|
+
const unsubscribe2 = addWildcardListener("*", wildcardListener);
|
|
4768
|
+
const onComplete = () => {
|
|
4769
|
+
observer.complete();
|
|
4770
|
+
};
|
|
4771
|
+
completionCallbacks.add(onComplete);
|
|
4772
|
+
return () => {
|
|
4773
|
+
unsubscribe2();
|
|
4774
|
+
completionCallbacks.delete(onComplete);
|
|
4775
|
+
};
|
|
4776
|
+
});
|
|
4777
|
+
};
|
|
4778
|
+
function events(type, options2) {
|
|
4779
|
+
if (isCompleted) {
|
|
4780
|
+
return {
|
|
4781
|
+
[Symbol.asyncIterator]() {
|
|
4782
|
+
return this;
|
|
4783
|
+
},
|
|
4784
|
+
next() {
|
|
4785
|
+
return Promise.resolve({
|
|
4786
|
+
value: undefined,
|
|
4787
|
+
done: true
|
|
4788
|
+
});
|
|
4789
|
+
},
|
|
4790
|
+
return() {
|
|
4791
|
+
return Promise.resolve({
|
|
4792
|
+
value: undefined,
|
|
4793
|
+
done: true
|
|
4794
|
+
});
|
|
4795
|
+
}
|
|
4796
|
+
};
|
|
4797
|
+
}
|
|
4798
|
+
const signal = options2?.signal;
|
|
4799
|
+
const bufferSize = options2?.bufferSize ?? Infinity;
|
|
4800
|
+
const overflowStrategy = options2?.overflowStrategy ?? "drop-oldest";
|
|
4801
|
+
const buffer = [];
|
|
4802
|
+
let resolve = null;
|
|
4803
|
+
let done = false;
|
|
4804
|
+
let hasOverflow = false;
|
|
4805
|
+
let onAbort = null;
|
|
4806
|
+
const cleanupAbortListener = () => {
|
|
4807
|
+
if (signal && onAbort) {
|
|
4808
|
+
signal.removeEventListener("abort", onAbort);
|
|
4809
|
+
}
|
|
4810
|
+
};
|
|
4811
|
+
const unsub = addEventListener(type, (event) => {
|
|
4812
|
+
if (done)
|
|
4813
|
+
return;
|
|
4814
|
+
const typedEvent = event;
|
|
4815
|
+
if (resolve) {
|
|
4816
|
+
const r = resolve;
|
|
4817
|
+
resolve = null;
|
|
4818
|
+
r({ value: typedEvent, done: false });
|
|
4819
|
+
} else {
|
|
4820
|
+
if (buffer.length >= bufferSize && bufferSize !== Infinity) {
|
|
4821
|
+
switch (overflowStrategy) {
|
|
4822
|
+
case "drop-oldest":
|
|
4823
|
+
buffer.shift();
|
|
4824
|
+
buffer.push(typedEvent);
|
|
4825
|
+
break;
|
|
4826
|
+
case "drop-latest":
|
|
4827
|
+
break;
|
|
4828
|
+
case "throw":
|
|
4829
|
+
unsub();
|
|
4830
|
+
completionCallbacks.delete(onComplete);
|
|
4831
|
+
done = true;
|
|
4832
|
+
hasOverflow = true;
|
|
4833
|
+
cleanupAbortListener();
|
|
4834
|
+
return;
|
|
4835
|
+
}
|
|
4836
|
+
} else {
|
|
4837
|
+
buffer.push(typedEvent);
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4840
|
+
});
|
|
4841
|
+
const onComplete = () => {
|
|
4842
|
+
done = true;
|
|
4843
|
+
cleanupAbortListener();
|
|
4844
|
+
if (resolve) {
|
|
4845
|
+
const r = resolve;
|
|
4846
|
+
resolve = null;
|
|
4847
|
+
r({ value: undefined, done: true });
|
|
4848
|
+
}
|
|
4849
|
+
};
|
|
4850
|
+
completionCallbacks.add(onComplete);
|
|
4851
|
+
if (signal) {
|
|
4852
|
+
onAbort = () => {
|
|
4853
|
+
done = true;
|
|
4854
|
+
completionCallbacks.delete(onComplete);
|
|
4855
|
+
unsub();
|
|
4856
|
+
if (resolve) {
|
|
4857
|
+
const r = resolve;
|
|
4858
|
+
resolve = null;
|
|
4859
|
+
r({ value: undefined, done: true });
|
|
4860
|
+
}
|
|
4861
|
+
};
|
|
4862
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4863
|
+
if (signal.aborted)
|
|
4864
|
+
onAbort();
|
|
4865
|
+
}
|
|
4866
|
+
const iterator = {
|
|
4867
|
+
[Symbol.asyncIterator]() {
|
|
4868
|
+
return this;
|
|
4869
|
+
},
|
|
4870
|
+
async next() {
|
|
4871
|
+
if (buffer.length > 0) {
|
|
4872
|
+
return { value: buffer.shift(), done: false };
|
|
4873
|
+
}
|
|
4874
|
+
if (resolve !== null) {
|
|
4875
|
+
return Promise.reject(new Error("Concurrent calls to next() are not supported on this async iterator"));
|
|
4876
|
+
}
|
|
4877
|
+
return new Promise((_resolve, _reject) => {
|
|
4878
|
+
if (hasOverflow) {
|
|
4879
|
+
hasOverflow = false;
|
|
4880
|
+
_reject(new BufferOverflowError(type, bufferSize));
|
|
4881
|
+
return;
|
|
4882
|
+
}
|
|
4883
|
+
if (done) {
|
|
4884
|
+
_resolve({
|
|
4885
|
+
value: undefined,
|
|
4886
|
+
done: true
|
|
4887
|
+
});
|
|
4888
|
+
return;
|
|
4889
|
+
}
|
|
4890
|
+
resolve = _resolve;
|
|
4891
|
+
});
|
|
4892
|
+
},
|
|
4893
|
+
return() {
|
|
4894
|
+
if (resolve) {
|
|
4895
|
+
const r = resolve;
|
|
4896
|
+
resolve = null;
|
|
4897
|
+
r({ value: undefined, done: true });
|
|
4898
|
+
}
|
|
4899
|
+
done = true;
|
|
4900
|
+
completionCallbacks.delete(onComplete);
|
|
4901
|
+
unsub();
|
|
4902
|
+
cleanupAbortListener();
|
|
4903
|
+
return Promise.resolve({
|
|
4904
|
+
value: undefined,
|
|
4905
|
+
done: true
|
|
4906
|
+
});
|
|
4907
|
+
}
|
|
4908
|
+
};
|
|
4909
|
+
return iterator;
|
|
4910
|
+
}
|
|
4911
|
+
const target = {
|
|
4912
|
+
addEventListener,
|
|
4913
|
+
removeEventListener,
|
|
4914
|
+
dispatchEvent,
|
|
4915
|
+
clear,
|
|
4916
|
+
on,
|
|
4917
|
+
once: onceMethod,
|
|
4918
|
+
removeAllListeners,
|
|
4919
|
+
pipe,
|
|
4920
|
+
addWildcardListener,
|
|
4921
|
+
removeWildcardListener,
|
|
4922
|
+
complete: complete2,
|
|
4923
|
+
get completed() {
|
|
4924
|
+
return isCompleted;
|
|
4925
|
+
},
|
|
4926
|
+
subscribe,
|
|
4927
|
+
toObservable,
|
|
4928
|
+
events
|
|
4929
|
+
};
|
|
4930
|
+
target[SymbolObservable] = () => {
|
|
4931
|
+
return toObservable();
|
|
4932
|
+
};
|
|
4933
|
+
return target;
|
|
4934
|
+
}
|
|
4935
|
+
|
|
4936
|
+
class EventEmission {
|
|
4937
|
+
#target;
|
|
4938
|
+
constructor() {
|
|
4939
|
+
this.#target = createEventTarget();
|
|
4940
|
+
}
|
|
4941
|
+
addEventListener(type, listener, options2) {
|
|
4942
|
+
return this.#target.addEventListener(type, listener, options2);
|
|
4943
|
+
}
|
|
4944
|
+
removeEventListener(type, listener, options2) {
|
|
4945
|
+
this.#target.removeEventListener(type, listener, options2);
|
|
4946
|
+
}
|
|
4947
|
+
dispatchEvent(event) {
|
|
4948
|
+
return this.#target.dispatchEvent(event);
|
|
4949
|
+
}
|
|
4950
|
+
on(type, options2) {
|
|
4951
|
+
return this.#target.on(type, options2);
|
|
4952
|
+
}
|
|
4953
|
+
once(type, listener, options2) {
|
|
4954
|
+
return this.#target.once(type, listener, options2);
|
|
4955
|
+
}
|
|
4956
|
+
removeAllListeners(type) {
|
|
4957
|
+
this.#target.removeAllListeners(type);
|
|
4958
|
+
}
|
|
4959
|
+
clear() {
|
|
4960
|
+
this.#target.clear();
|
|
4961
|
+
}
|
|
4962
|
+
pipe(target, mapFn) {
|
|
4963
|
+
return this.#target.pipe(target, mapFn);
|
|
4964
|
+
}
|
|
4965
|
+
addWildcardListener(pattern, listener, options2) {
|
|
4966
|
+
return this.#target.addWildcardListener(pattern, listener, options2);
|
|
4967
|
+
}
|
|
4968
|
+
removeWildcardListener(pattern, listener) {
|
|
4969
|
+
this.#target.removeWildcardListener(pattern, listener);
|
|
4970
|
+
}
|
|
4971
|
+
subscribe(typeOrObserver, observerOrNext, error2, completeHandler) {
|
|
4972
|
+
if (typeof typeOrObserver === "string") {
|
|
4973
|
+
return this.#target.subscribe(typeOrObserver, observerOrNext, error2, completeHandler);
|
|
4974
|
+
}
|
|
4975
|
+
if (typeof typeOrObserver === "function") {
|
|
4976
|
+
return this.#target.toObservable().subscribe(typeOrObserver);
|
|
4977
|
+
}
|
|
4978
|
+
if (typeof typeOrObserver === "object" && typeOrObserver !== null) {
|
|
4979
|
+
const maybeObserver = typeOrObserver;
|
|
4980
|
+
if (typeof maybeObserver.next === "function" || typeof maybeObserver.error === "function" || typeof maybeObserver.complete === "function") {
|
|
4981
|
+
return this.#target.toObservable().subscribe(typeOrObserver);
|
|
4982
|
+
}
|
|
4983
|
+
return this.#target.toObservable().subscribe({});
|
|
4984
|
+
}
|
|
4985
|
+
throw new Error("subscribe() requires a string event type, callback function, or observer object");
|
|
4986
|
+
}
|
|
4987
|
+
toObservable() {
|
|
4988
|
+
return this.#target.toObservable();
|
|
4989
|
+
}
|
|
4990
|
+
[SymbolObservable]() {
|
|
4991
|
+
return this.toObservable();
|
|
4992
|
+
}
|
|
4993
|
+
complete() {
|
|
4994
|
+
this.#target.complete();
|
|
4995
|
+
}
|
|
4996
|
+
get completed() {
|
|
4997
|
+
return this.#target.completed;
|
|
4998
|
+
}
|
|
4999
|
+
events(type, options2) {
|
|
5000
|
+
return this.#target.events(type, options2);
|
|
5001
|
+
}
|
|
5002
|
+
}
|
|
5003
|
+
|
|
5004
|
+
// src/errors.ts
|
|
5005
|
+
class ConversationalistError extends Error {
|
|
5006
|
+
code;
|
|
5007
|
+
context;
|
|
5008
|
+
cause;
|
|
5009
|
+
constructor(code, message, options2) {
|
|
5010
|
+
super(message);
|
|
5011
|
+
this.name = "ConversationalistError";
|
|
5012
|
+
this.code = code;
|
|
5013
|
+
this.context = options2?.context;
|
|
5014
|
+
this.cause = options2?.cause;
|
|
5015
|
+
if (Error.captureStackTrace) {
|
|
5016
|
+
Error.captureStackTrace(this, ConversationalistError);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
toDetailedString() {
|
|
5020
|
+
const parts = [`[${this.code}] ${this.message}`];
|
|
5021
|
+
if (this.context && Object.keys(this.context).length > 0) {
|
|
5022
|
+
parts.push(`Context: ${JSON.stringify(this.context, null, 2)}`);
|
|
5023
|
+
}
|
|
5024
|
+
if (this.cause) {
|
|
5025
|
+
parts.push(`Caused by: ${this.cause.message}`);
|
|
5026
|
+
}
|
|
5027
|
+
return parts.join(`
|
|
5028
|
+
`);
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
function createInvalidPositionError(expected, actual) {
|
|
5032
|
+
return new ConversationalistError("error:invalid-position", `invalid position: expected ${expected}, got ${actual}`, { context: { expected, actual } });
|
|
5033
|
+
}
|
|
5034
|
+
function createInvalidToolReferenceError(callId) {
|
|
5035
|
+
return new ConversationalistError("error:invalid-tool-reference", `tool result references non-existent tool-use: ${callId}`, { context: { callId } });
|
|
5036
|
+
}
|
|
5037
|
+
function createSerializationError(message, cause) {
|
|
5038
|
+
return new ConversationalistError("error:serialization", message, { cause });
|
|
5039
|
+
}
|
|
5040
|
+
function createValidationError(message, context, cause) {
|
|
5041
|
+
return new ConversationalistError("error:validation", message, { context, cause });
|
|
5042
|
+
}
|
|
5043
|
+
function createIntegrityError(message, context) {
|
|
5044
|
+
return new ConversationalistError("error:integrity", message, { context });
|
|
5045
|
+
}
|
|
5046
|
+
|
|
5047
|
+
// src/schemas.ts
|
|
5048
|
+
import { z } from "zod";
|
|
5049
|
+
var isPlainObject = (value) => {
|
|
5050
|
+
if (!value || typeof value !== "object")
|
|
5051
|
+
return false;
|
|
5052
|
+
const prototype = Reflect.getPrototypeOf(value);
|
|
5053
|
+
return prototype === Object.prototype || prototype === null;
|
|
5054
|
+
};
|
|
5055
|
+
function toMultiModalContent(value) {
|
|
5056
|
+
const result = { type: value.type };
|
|
5057
|
+
if (value.text !== undefined)
|
|
5058
|
+
result.text = value.text;
|
|
5059
|
+
if (value.url !== undefined)
|
|
5060
|
+
result.url = value.url;
|
|
5061
|
+
if (value.mimeType !== undefined)
|
|
5062
|
+
result.mimeType = value.mimeType;
|
|
5063
|
+
return result;
|
|
5064
|
+
}
|
|
5065
|
+
var jsonValueSchema = z.lazy(() => {
|
|
5066
|
+
const jsonObjectSchema = z.preprocess((value, ctx) => {
|
|
5067
|
+
if (!isPlainObject(value)) {
|
|
5068
|
+
ctx.addIssue({
|
|
5069
|
+
code: z.ZodIssueCode.custom,
|
|
5070
|
+
message: "expected a plain object"
|
|
5071
|
+
});
|
|
5072
|
+
return z.NEVER;
|
|
5073
|
+
}
|
|
5074
|
+
return value;
|
|
5075
|
+
}, z.record(z.string(), jsonValueSchema));
|
|
5076
|
+
return z.union([
|
|
5077
|
+
z.string(),
|
|
5078
|
+
z.number().refine((value) => Number.isFinite(value), {
|
|
5079
|
+
message: "expected a finite number"
|
|
5080
|
+
}),
|
|
5081
|
+
z.boolean(),
|
|
5082
|
+
z.null(),
|
|
5083
|
+
z.array(jsonValueSchema),
|
|
5084
|
+
jsonObjectSchema
|
|
5085
|
+
]);
|
|
5086
|
+
});
|
|
5087
|
+
var multiModalContentSchema = z.discriminatedUnion("type", [
|
|
5088
|
+
z.object({
|
|
5089
|
+
type: z.literal("text"),
|
|
5090
|
+
text: z.string()
|
|
5091
|
+
}),
|
|
5092
|
+
z.object({
|
|
5093
|
+
type: z.literal("image"),
|
|
5094
|
+
url: z.string().url(),
|
|
5095
|
+
mimeType: z.string().optional(),
|
|
5096
|
+
text: z.string().optional()
|
|
5097
|
+
})
|
|
5098
|
+
]).transform(toMultiModalContent);
|
|
5099
|
+
var messageRoleSchema = z.enum([
|
|
5100
|
+
"user",
|
|
5101
|
+
"assistant",
|
|
5102
|
+
"system",
|
|
5103
|
+
"developer",
|
|
5104
|
+
"tool-use",
|
|
5105
|
+
"tool-result",
|
|
5106
|
+
"snapshot"
|
|
5107
|
+
]);
|
|
5108
|
+
var toolCallSchema = z.object({
|
|
5109
|
+
id: z.string(),
|
|
5110
|
+
name: z.string(),
|
|
5111
|
+
arguments: jsonValueSchema
|
|
5112
|
+
}).strict();
|
|
5113
|
+
var toolResultSchema = z.object({
|
|
5114
|
+
callId: z.string(),
|
|
5115
|
+
outcome: z.enum(["success", "error"]),
|
|
5116
|
+
content: jsonValueSchema
|
|
5117
|
+
}).strict();
|
|
5118
|
+
var tokenUsageSchema = z.object({
|
|
5119
|
+
prompt: z.number().int().min(0),
|
|
5120
|
+
completion: z.number().int().min(0),
|
|
5121
|
+
total: z.number().int().min(0)
|
|
5122
|
+
});
|
|
5123
|
+
var messageInputSchema = z.object({
|
|
5124
|
+
role: messageRoleSchema,
|
|
5125
|
+
content: z.union([z.string(), z.array(multiModalContentSchema)]),
|
|
5126
|
+
metadata: z.record(z.string(), jsonValueSchema).optional(),
|
|
5127
|
+
hidden: z.boolean().optional(),
|
|
5128
|
+
toolCall: toolCallSchema.optional(),
|
|
5129
|
+
toolResult: toolResultSchema.optional(),
|
|
5130
|
+
tokenUsage: tokenUsageSchema.optional(),
|
|
5131
|
+
goalCompleted: z.boolean().optional()
|
|
5132
|
+
}).strict();
|
|
5133
|
+
var messageSchema = z.object({
|
|
5134
|
+
id: z.string(),
|
|
5135
|
+
role: messageRoleSchema,
|
|
5136
|
+
content: z.union([z.string(), z.array(multiModalContentSchema)]),
|
|
5137
|
+
position: z.number().int().min(0),
|
|
5138
|
+
createdAt: z.string(),
|
|
5139
|
+
metadata: z.record(z.string(), jsonValueSchema),
|
|
5140
|
+
hidden: z.boolean(),
|
|
5141
|
+
toolCall: toolCallSchema.optional(),
|
|
5142
|
+
toolResult: toolResultSchema.optional(),
|
|
5143
|
+
tokenUsage: tokenUsageSchema.optional(),
|
|
5144
|
+
goalCompleted: z.boolean().optional()
|
|
5145
|
+
}).strict();
|
|
5146
|
+
var conversationStatusSchema = z.enum([
|
|
5147
|
+
"active",
|
|
5148
|
+
"archived",
|
|
5149
|
+
"deleted"
|
|
5150
|
+
]);
|
|
5151
|
+
var conversationShape = {
|
|
5152
|
+
schemaVersion: z.number().int().min(1),
|
|
5153
|
+
id: z.string(),
|
|
5154
|
+
title: z.string().optional(),
|
|
5155
|
+
status: conversationStatusSchema,
|
|
5156
|
+
metadata: z.record(z.string(), jsonValueSchema),
|
|
5157
|
+
ids: z.array(z.string()),
|
|
5158
|
+
messages: z.record(z.string(), messageSchema),
|
|
5159
|
+
createdAt: z.string(),
|
|
5160
|
+
updatedAt: z.string()
|
|
5161
|
+
};
|
|
5162
|
+
var conversationSchema = z.object(conversationShape).strict();
|
|
5163
|
+
|
|
5164
|
+
// src/conversation/integrity.ts
|
|
5165
|
+
function validateConversationIntegrity(conversation) {
|
|
5166
|
+
const issues = [];
|
|
5167
|
+
const seenIds = new Set;
|
|
5168
|
+
conversation.ids.forEach((id, index) => {
|
|
5169
|
+
if (seenIds.has(id)) {
|
|
5170
|
+
issues.push({
|
|
5171
|
+
code: "integrity:duplicate-message-id",
|
|
5172
|
+
message: `duplicate message id in ids: ${id}`,
|
|
5173
|
+
data: { id, position: index }
|
|
5174
|
+
});
|
|
5175
|
+
} else {
|
|
5176
|
+
seenIds.add(id);
|
|
5177
|
+
}
|
|
5178
|
+
if (!conversation.messages[id]) {
|
|
5179
|
+
issues.push({
|
|
5180
|
+
code: "integrity:missing-message",
|
|
5181
|
+
message: `missing message for id ${id}`,
|
|
5182
|
+
data: { id, position: index }
|
|
5183
|
+
});
|
|
5184
|
+
}
|
|
5185
|
+
});
|
|
5186
|
+
for (const id of Object.keys(conversation.messages)) {
|
|
5187
|
+
if (!seenIds.has(id)) {
|
|
5188
|
+
issues.push({
|
|
5189
|
+
code: "integrity:unlisted-message",
|
|
5190
|
+
message: `message ${id} is not listed in ids`,
|
|
5191
|
+
data: { id }
|
|
5192
|
+
});
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
const toolUses = new Map;
|
|
5196
|
+
conversation.ids.forEach((id, index) => {
|
|
5197
|
+
const message = conversation.messages[id];
|
|
5198
|
+
if (!message)
|
|
5199
|
+
return;
|
|
5200
|
+
if (message.role === "tool-use" && message.toolCall) {
|
|
5201
|
+
if (toolUses.has(message.toolCall.id)) {
|
|
5202
|
+
issues.push({
|
|
5203
|
+
code: "integrity:duplicate-tool-call",
|
|
5204
|
+
message: `duplicate toolCall.id ${message.toolCall.id}`,
|
|
5205
|
+
data: { toolCallId: message.toolCall.id, messageId: message.id }
|
|
5206
|
+
});
|
|
5207
|
+
} else {
|
|
5208
|
+
toolUses.set(message.toolCall.id, { position: index, messageId: message.id });
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
});
|
|
5212
|
+
conversation.ids.forEach((id, index) => {
|
|
5213
|
+
const message = conversation.messages[id];
|
|
5214
|
+
if (!message)
|
|
5215
|
+
return;
|
|
5216
|
+
if (message.role === "tool-result" && message.toolResult) {
|
|
5217
|
+
const toolUse = toolUses.get(message.toolResult.callId);
|
|
5218
|
+
if (!toolUse) {
|
|
5219
|
+
issues.push({
|
|
5220
|
+
code: "integrity:orphan-tool-result",
|
|
5221
|
+
message: `tool-result references missing tool-use ${message.toolResult.callId}`,
|
|
5222
|
+
data: { callId: message.toolResult.callId, messageId: message.id }
|
|
5223
|
+
});
|
|
5224
|
+
} else if (toolUse.position >= index) {
|
|
5225
|
+
issues.push({
|
|
5226
|
+
code: "integrity:tool-result-before-call",
|
|
5227
|
+
message: `tool-result ${message.toolResult.callId} occurs before tool-use`,
|
|
5228
|
+
data: {
|
|
5229
|
+
callId: message.toolResult.callId,
|
|
5230
|
+
messageId: message.id,
|
|
5231
|
+
toolUseMessageId: toolUse.messageId
|
|
5232
|
+
}
|
|
5233
|
+
});
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
5236
|
+
});
|
|
5237
|
+
return issues;
|
|
5238
|
+
}
|
|
5239
|
+
function assertConversationIntegrity(conversation) {
|
|
5240
|
+
const issues = validateConversationIntegrity(conversation);
|
|
5241
|
+
if (issues.length === 0)
|
|
5242
|
+
return;
|
|
5243
|
+
throw createIntegrityError("conversation integrity check failed", { issues });
|
|
5244
|
+
}
|
|
5245
|
+
|
|
5246
|
+
// src/conversation/validation.ts
|
|
5247
|
+
function assertConversationSafe(conversation) {
|
|
5248
|
+
const parsed = conversationSchema.safeParse(conversation);
|
|
5249
|
+
if (!parsed.success) {
|
|
5250
|
+
throw createValidationError("conversation failed schema validation", {
|
|
5251
|
+
issues: parsed.error.issues
|
|
5252
|
+
});
|
|
5253
|
+
}
|
|
5254
|
+
assertConversationIntegrity(conversation);
|
|
5255
|
+
}
|
|
5256
|
+
function ensureConversationSafe(conversation) {
|
|
5257
|
+
assertConversationSafe(conversation);
|
|
5258
|
+
return conversation;
|
|
5259
|
+
}
|
|
5260
|
+
|
|
3494
5261
|
// src/utilities/content.ts
|
|
3495
5262
|
function normalizeContent(content) {
|
|
3496
5263
|
if (content === undefined)
|
|
@@ -3655,6 +5422,92 @@ var cloneMessageWithPosition = (message, position, content) => {
|
|
|
3655
5422
|
}
|
|
3656
5423
|
return createMessage(baseMessage);
|
|
3657
5424
|
};
|
|
5425
|
+
var createMessageBlock = (message, estimator) => ({
|
|
5426
|
+
messages: [message],
|
|
5427
|
+
minPosition: message.position,
|
|
5428
|
+
maxPosition: message.position,
|
|
5429
|
+
tokenCount: estimator(message)
|
|
5430
|
+
});
|
|
5431
|
+
var buildMessageBlocks = (messages, estimator, preserveToolPairs) => {
|
|
5432
|
+
if (!preserveToolPairs) {
|
|
5433
|
+
const blocks2 = messages.map((message) => createMessageBlock(message, estimator));
|
|
5434
|
+
const messageToBlock2 = new Map;
|
|
5435
|
+
for (const block of blocks2) {
|
|
5436
|
+
const message = block.messages[0];
|
|
5437
|
+
if (message) {
|
|
5438
|
+
messageToBlock2.set(message.id, block);
|
|
5439
|
+
}
|
|
5440
|
+
}
|
|
5441
|
+
return { blocks: blocks2, messageToBlock: messageToBlock2 };
|
|
5442
|
+
}
|
|
5443
|
+
const blocks = [];
|
|
5444
|
+
const toolUses = new Map;
|
|
5445
|
+
for (const message of messages) {
|
|
5446
|
+
if (message.role === "tool-use" && message.toolCall) {
|
|
5447
|
+
const block = createMessageBlock(message, estimator);
|
|
5448
|
+
toolUses.set(message.toolCall.id, block);
|
|
5449
|
+
blocks.push(block);
|
|
5450
|
+
continue;
|
|
5451
|
+
}
|
|
5452
|
+
if (message.role === "tool-result" && message.toolResult) {
|
|
5453
|
+
const existing = toolUses.get(message.toolResult.callId);
|
|
5454
|
+
if (existing) {
|
|
5455
|
+
existing.messages.push(message);
|
|
5456
|
+
existing.maxPosition = Math.max(existing.maxPosition, message.position);
|
|
5457
|
+
existing.tokenCount += estimator(message);
|
|
5458
|
+
continue;
|
|
5459
|
+
}
|
|
5460
|
+
const orphanBlock = createMessageBlock(message, estimator);
|
|
5461
|
+
orphanBlock.orphanToolResult = true;
|
|
5462
|
+
blocks.push(orphanBlock);
|
|
5463
|
+
continue;
|
|
5464
|
+
}
|
|
5465
|
+
blocks.push(createMessageBlock(message, estimator));
|
|
5466
|
+
}
|
|
5467
|
+
const filteredBlocks = blocks.filter((block) => !block.orphanToolResult);
|
|
5468
|
+
const messageToBlock = new Map;
|
|
5469
|
+
for (const block of filteredBlocks) {
|
|
5470
|
+
for (const message of block.messages) {
|
|
5471
|
+
messageToBlock.set(message.id, block);
|
|
5472
|
+
}
|
|
5473
|
+
}
|
|
5474
|
+
return { blocks: filteredBlocks, messageToBlock };
|
|
5475
|
+
};
|
|
5476
|
+
var collectBlocksForMessages = (messages, messageToBlock) => {
|
|
5477
|
+
const blocks = [];
|
|
5478
|
+
const seen = new Set;
|
|
5479
|
+
for (const message of messages) {
|
|
5480
|
+
const block = messageToBlock.get(message.id);
|
|
5481
|
+
if (block && !seen.has(block)) {
|
|
5482
|
+
seen.add(block);
|
|
5483
|
+
blocks.push(block);
|
|
5484
|
+
}
|
|
5485
|
+
}
|
|
5486
|
+
return blocks;
|
|
5487
|
+
};
|
|
5488
|
+
var collectMessagesFromBlocks = (blocks) => {
|
|
5489
|
+
const messages = [];
|
|
5490
|
+
const seen = new Set;
|
|
5491
|
+
for (const block of blocks) {
|
|
5492
|
+
for (const message of block.messages) {
|
|
5493
|
+
if (!seen.has(message.id)) {
|
|
5494
|
+
seen.add(message.id);
|
|
5495
|
+
messages.push(message);
|
|
5496
|
+
}
|
|
5497
|
+
}
|
|
5498
|
+
}
|
|
5499
|
+
messages.sort((a, b) => a.position - b.position);
|
|
5500
|
+
return messages;
|
|
5501
|
+
};
|
|
5502
|
+
var ensureTruncationSafe = (conversation, preserveToolPairs, operation) => {
|
|
5503
|
+
try {
|
|
5504
|
+
return ensureConversationSafe(conversation);
|
|
5505
|
+
} catch (error2) {
|
|
5506
|
+
if (!preserveToolPairs && error2 instanceof ConversationalistError && error2.code === "error:integrity")
|
|
5507
|
+
throw createIntegrityError(`${operation} produced invalid tool linkage; use preserveToolPairs: true to keep tool interactions intact`, { preserveToolPairs, issues: error2.context?.["issues"] });
|
|
5508
|
+
throw error2;
|
|
5509
|
+
}
|
|
5510
|
+
};
|
|
3658
5511
|
function estimateConversationTokens(conversation, estimateTokens, environment) {
|
|
3659
5512
|
let estimator = estimateTokens;
|
|
3660
5513
|
let env = environment;
|
|
@@ -3667,6 +5520,7 @@ function estimateConversationTokens(conversation, estimateTokens, environment) {
|
|
|
3667
5520
|
return getOrderedMessages(conversation).reduce((total, message) => total + finalEstimator(message), 0);
|
|
3668
5521
|
}
|
|
3669
5522
|
function truncateToTokenLimit(conversation, maxTokens, optionsOrEstimator, environment) {
|
|
5523
|
+
assertConversationSafe(conversation);
|
|
3670
5524
|
let options2 = {};
|
|
3671
5525
|
let env = environment;
|
|
3672
5526
|
if (typeof optionsOrEstimator === "function") {
|
|
@@ -3688,54 +5542,56 @@ function truncateToTokenLimit(conversation, maxTokens, optionsOrEstimator, envir
|
|
|
3688
5542
|
const estimator = options2.estimateTokens ?? resolvedEnvironment.estimateTokens;
|
|
3689
5543
|
const preserveSystem = options2.preserveSystemMessages ?? true;
|
|
3690
5544
|
const preserveLastN = options2.preserveLastN ?? 0;
|
|
5545
|
+
const preserveToolPairs = options2.preserveToolPairs ?? true;
|
|
3691
5546
|
const currentTokens = estimateConversationTokens(conversation, estimator, resolvedEnvironment);
|
|
3692
5547
|
if (currentTokens <= maxTokens) {
|
|
3693
5548
|
return conversation;
|
|
3694
5549
|
}
|
|
3695
5550
|
const now = resolvedEnvironment.now();
|
|
3696
5551
|
const orderedMessages = getOrderedMessages(conversation);
|
|
5552
|
+
const { blocks, messageToBlock } = buildMessageBlocks(orderedMessages, estimator, preserveToolPairs);
|
|
3697
5553
|
const systemMessages = preserveSystem ? orderedMessages.filter((m) => m.role === "system") : [];
|
|
3698
5554
|
const nonSystemMessages = orderedMessages.filter((m) => m.role !== "system");
|
|
3699
5555
|
const protectedMessages = preserveLastN > 0 ? nonSystemMessages.slice(-preserveLastN) : [];
|
|
3700
|
-
const
|
|
3701
|
-
const
|
|
3702
|
-
const
|
|
5556
|
+
const systemBlocks = collectBlocksForMessages(systemMessages, messageToBlock);
|
|
5557
|
+
const protectedBlocks = collectBlocksForMessages(protectedMessages, messageToBlock);
|
|
5558
|
+
const lockedBlocks = new Set([...systemBlocks, ...protectedBlocks]);
|
|
5559
|
+
const removableBlocks = blocks.filter((block) => !lockedBlocks.has(block));
|
|
5560
|
+
const systemTokens = systemBlocks.reduce((sum, block) => sum + block.tokenCount, 0);
|
|
5561
|
+
const protectedTokens = protectedBlocks.reduce((sum, block) => sum + block.tokenCount, 0);
|
|
3703
5562
|
const availableTokens = maxTokens - systemTokens - protectedTokens;
|
|
5563
|
+
let selectedBlocks = [];
|
|
3704
5564
|
if (availableTokens <= 0) {
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
const messageTokens = estimator(message);
|
|
3719
|
-
if (usedTokens + messageTokens <= availableTokens) {
|
|
3720
|
-
keptRemovable.unshift(message);
|
|
3721
|
-
usedTokens += messageTokens;
|
|
3722
|
-
} else {
|
|
3723
|
-
break;
|
|
5565
|
+
selectedBlocks = [...systemBlocks, ...protectedBlocks];
|
|
5566
|
+
} else {
|
|
5567
|
+
const sortedRemovable = [...removableBlocks].sort((a, b) => a.maxPosition - b.maxPosition);
|
|
5568
|
+
const keptRemovable = [];
|
|
5569
|
+
let usedTokens = 0;
|
|
5570
|
+
for (let i = sortedRemovable.length - 1;i >= 0; i--) {
|
|
5571
|
+
const block = sortedRemovable[i];
|
|
5572
|
+
if (usedTokens + block.tokenCount <= availableTokens) {
|
|
5573
|
+
keptRemovable.unshift(block);
|
|
5574
|
+
usedTokens += block.tokenCount;
|
|
5575
|
+
} else {
|
|
5576
|
+
break;
|
|
5577
|
+
}
|
|
3724
5578
|
}
|
|
5579
|
+
selectedBlocks = [...systemBlocks, ...keptRemovable, ...protectedBlocks];
|
|
3725
5580
|
}
|
|
3726
|
-
const allMessages =
|
|
3727
|
-
allMessages.sort((a, b) => a.position - b.position);
|
|
5581
|
+
const allMessages = collectMessagesFromBlocks(selectedBlocks);
|
|
3728
5582
|
const renumbered = allMessages.map((message, index) => cloneMessageWithPosition(message, index, copyContent(message.content)));
|
|
3729
|
-
|
|
5583
|
+
const next2 = toReadonly({
|
|
3730
5584
|
...conversation,
|
|
3731
5585
|
ids: renumbered.map((message) => message.id),
|
|
3732
5586
|
messages: toIdRecord(renumbered),
|
|
3733
5587
|
updatedAt: now
|
|
3734
5588
|
});
|
|
5589
|
+
return ensureTruncationSafe(next2, preserveToolPairs, "truncateToTokenLimit");
|
|
3735
5590
|
}
|
|
3736
5591
|
function getRecentMessages(conversation, count, options2) {
|
|
3737
5592
|
const includeHidden = options2?.includeHidden ?? false;
|
|
3738
5593
|
const includeSystem = options2?.includeSystem ?? false;
|
|
5594
|
+
const preserveToolPairs = options2?.preserveToolPairs ?? true;
|
|
3739
5595
|
const filtered = getOrderedMessages(conversation).filter((m) => {
|
|
3740
5596
|
if (!includeHidden && m.hidden)
|
|
3741
5597
|
return false;
|
|
@@ -3743,66 +5599,58 @@ function getRecentMessages(conversation, count, options2) {
|
|
|
3743
5599
|
return false;
|
|
3744
5600
|
return true;
|
|
3745
5601
|
});
|
|
3746
|
-
|
|
5602
|
+
if (!preserveToolPairs) {
|
|
5603
|
+
return filtered.slice(-count);
|
|
5604
|
+
}
|
|
5605
|
+
const { messageToBlock } = buildMessageBlocks(filtered, () => 0, preserveToolPairs);
|
|
5606
|
+
const tail = filtered.slice(-count);
|
|
5607
|
+
const blocks = collectBlocksForMessages(tail, messageToBlock);
|
|
5608
|
+
return collectMessagesFromBlocks(blocks);
|
|
3747
5609
|
}
|
|
3748
5610
|
function truncateFromPosition(conversation, position, options2, environment) {
|
|
5611
|
+
assertConversationSafe(conversation);
|
|
3749
5612
|
const preserveSystem = options2?.preserveSystemMessages ?? true;
|
|
5613
|
+
const preserveToolPairs = options2?.preserveToolPairs ?? true;
|
|
3750
5614
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
3751
5615
|
const now = resolvedEnvironment.now();
|
|
3752
5616
|
const ordered = getOrderedMessages(conversation);
|
|
5617
|
+
const { messageToBlock } = buildMessageBlocks(ordered, () => 0, preserveToolPairs);
|
|
3753
5618
|
const systemMessages = preserveSystem ? ordered.filter((m) => m.role === "system" && m.position < position) : [];
|
|
3754
5619
|
const keptMessages = ordered.filter((m) => m.position >= position);
|
|
3755
|
-
const
|
|
5620
|
+
const systemBlocks = collectBlocksForMessages(systemMessages, messageToBlock);
|
|
5621
|
+
const keptBlocks = collectBlocksForMessages(keptMessages, messageToBlock);
|
|
5622
|
+
const allMessages = collectMessagesFromBlocks([...systemBlocks, ...keptBlocks]);
|
|
3756
5623
|
const renumbered = allMessages.map((message, index) => cloneMessageWithPosition(message, index, copyContent(message.content)));
|
|
3757
|
-
|
|
5624
|
+
const next2 = toReadonly({
|
|
3758
5625
|
...conversation,
|
|
3759
5626
|
ids: renumbered.map((message) => message.id),
|
|
3760
5627
|
messages: toIdRecord(renumbered),
|
|
3761
5628
|
updatedAt: now
|
|
3762
5629
|
});
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
// src/errors.ts
|
|
3766
|
-
class ConversationalistError extends Error {
|
|
3767
|
-
code;
|
|
3768
|
-
context;
|
|
3769
|
-
cause;
|
|
3770
|
-
constructor(code, message, options2) {
|
|
3771
|
-
super(message);
|
|
3772
|
-
this.name = "ConversationalistError";
|
|
3773
|
-
this.code = code;
|
|
3774
|
-
this.context = options2?.context;
|
|
3775
|
-
this.cause = options2?.cause;
|
|
3776
|
-
if (Error.captureStackTrace) {
|
|
3777
|
-
Error.captureStackTrace(this, ConversationalistError);
|
|
3778
|
-
}
|
|
3779
|
-
}
|
|
3780
|
-
toDetailedString() {
|
|
3781
|
-
const parts = [`[${this.code}] ${this.message}`];
|
|
3782
|
-
if (this.context && Object.keys(this.context).length > 0) {
|
|
3783
|
-
parts.push(`Context: ${JSON.stringify(this.context, null, 2)}`);
|
|
3784
|
-
}
|
|
3785
|
-
if (this.cause) {
|
|
3786
|
-
parts.push(`Caused by: ${this.cause.message}`);
|
|
3787
|
-
}
|
|
3788
|
-
return parts.join(`
|
|
3789
|
-
`);
|
|
3790
|
-
}
|
|
3791
|
-
}
|
|
3792
|
-
function createInvalidPositionError(expected, actual) {
|
|
3793
|
-
return new ConversationalistError("error:invalid-position", `invalid position: expected ${expected}, got ${actual}`, { context: { expected, actual } });
|
|
3794
|
-
}
|
|
3795
|
-
function createInvalidToolReferenceError(callId) {
|
|
3796
|
-
return new ConversationalistError("error:invalid-tool-reference", `tool result references non-existent tool-use: ${callId}`, { context: { callId } });
|
|
3797
|
-
}
|
|
3798
|
-
function createSerializationError(message, cause) {
|
|
3799
|
-
return new ConversationalistError("error:serialization", message, { cause });
|
|
5630
|
+
return ensureTruncationSafe(next2, preserveToolPairs, "truncateFromPosition");
|
|
3800
5631
|
}
|
|
3801
5632
|
|
|
3802
5633
|
// src/types.ts
|
|
3803
5634
|
var CURRENT_SCHEMA_VERSION = 3;
|
|
3804
5635
|
|
|
3805
|
-
// src/conversation.ts
|
|
5636
|
+
// src/conversation/create.ts
|
|
5637
|
+
function createConversation(options2, environment) {
|
|
5638
|
+
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5639
|
+
const now = resolvedEnvironment.now();
|
|
5640
|
+
const conv = {
|
|
5641
|
+
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
5642
|
+
id: options2?.id ?? resolvedEnvironment.randomId(),
|
|
5643
|
+
title: options2?.title,
|
|
5644
|
+
status: options2?.status ?? "active",
|
|
5645
|
+
metadata: { ...options2?.metadata ?? {} },
|
|
5646
|
+
ids: [],
|
|
5647
|
+
messages: {},
|
|
5648
|
+
createdAt: now,
|
|
5649
|
+
updatedAt: now
|
|
5650
|
+
};
|
|
5651
|
+
return ensureConversationSafe(toReadonly(conv));
|
|
5652
|
+
}
|
|
5653
|
+
// src/conversation/tool-tracking.ts
|
|
3806
5654
|
var buildToolUseIndex = (messages) => messages.reduce((index, message) => {
|
|
3807
5655
|
if (message.role === "tool-use" && message.toolCall) {
|
|
3808
5656
|
index.set(message.toolCall.id, { name: message.toolCall.name });
|
|
@@ -3810,53 +5658,43 @@ var buildToolUseIndex = (messages) => messages.reduce((index, message) => {
|
|
|
3810
5658
|
return index;
|
|
3811
5659
|
}, new Map);
|
|
3812
5660
|
var registerToolUse = (index, toolCall) => {
|
|
3813
|
-
const
|
|
3814
|
-
|
|
3815
|
-
return
|
|
5661
|
+
const next2 = new Map(index);
|
|
5662
|
+
next2.set(toolCall.id, { name: toolCall.name });
|
|
5663
|
+
return next2;
|
|
3816
5664
|
};
|
|
3817
5665
|
var assertToolReference = (index, callId) => {
|
|
3818
5666
|
if (!index.has(callId)) {
|
|
3819
5667
|
throw createInvalidToolReferenceError(callId);
|
|
3820
5668
|
}
|
|
3821
5669
|
};
|
|
5670
|
+
|
|
5671
|
+
// src/conversation/append.ts
|
|
3822
5672
|
function partitionAppendArgs(args) {
|
|
3823
|
-
|
|
5673
|
+
const filtered = args.filter((arg) => arg !== undefined);
|
|
5674
|
+
if (filtered.length === 0) {
|
|
3824
5675
|
return { inputs: [] };
|
|
3825
5676
|
}
|
|
3826
|
-
const last =
|
|
5677
|
+
const last = filtered[filtered.length - 1];
|
|
3827
5678
|
if (isConversationEnvironmentParameter(last)) {
|
|
3828
5679
|
return {
|
|
3829
|
-
inputs:
|
|
5680
|
+
inputs: filtered.slice(0, -1),
|
|
3830
5681
|
environment: last
|
|
3831
5682
|
};
|
|
3832
5683
|
}
|
|
3833
|
-
return { inputs:
|
|
3834
|
-
}
|
|
3835
|
-
function createConversation(options2, environment) {
|
|
3836
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
3837
|
-
const now = resolvedEnvironment.now();
|
|
3838
|
-
const conv = {
|
|
3839
|
-
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
3840
|
-
id: options2?.id ?? resolvedEnvironment.randomId(),
|
|
3841
|
-
title: options2?.title,
|
|
3842
|
-
status: options2?.status ?? "active",
|
|
3843
|
-
metadata: { ...options2?.metadata ?? {} },
|
|
3844
|
-
ids: [],
|
|
3845
|
-
messages: {},
|
|
3846
|
-
createdAt: now,
|
|
3847
|
-
updatedAt: now
|
|
3848
|
-
};
|
|
3849
|
-
return toReadonly(conv);
|
|
5684
|
+
return { inputs: filtered };
|
|
3850
5685
|
}
|
|
3851
5686
|
function appendMessages(conversation, ...args) {
|
|
5687
|
+
return appendMessagesInternal(conversation, args, true);
|
|
5688
|
+
}
|
|
5689
|
+
var appendMessagesInternal = (conversation, args, validate) => {
|
|
3852
5690
|
const { inputs, environment } = partitionAppendArgs(args);
|
|
3853
5691
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
3854
5692
|
const now = resolvedEnvironment.now();
|
|
3855
5693
|
const startPosition = conversation.ids.length;
|
|
3856
|
-
const initialToolUses = buildToolUseIndex(getOrderedMessages(conversation));
|
|
5694
|
+
const initialToolUses = validate ? buildToolUseIndex(getOrderedMessages(conversation)) : new Map;
|
|
3857
5695
|
const { messages } = inputs.reduce((state, input, index) => {
|
|
3858
5696
|
const processedInput = resolvedEnvironment.plugins.reduce((acc, plugin) => plugin(acc), input);
|
|
3859
|
-
if (processedInput.role === "tool-result" && processedInput.toolResult) {
|
|
5697
|
+
if (validate && processedInput.role === "tool-result" && processedInput.toolResult) {
|
|
3860
5698
|
assertToolReference(state.toolUses, processedInput.toolResult.callId);
|
|
3861
5699
|
}
|
|
3862
5700
|
const normalizedContent = normalizeContent(processedInput.content);
|
|
@@ -3883,30 +5721,47 @@ function appendMessages(conversation, ...args) {
|
|
|
3883
5721
|
} else {
|
|
3884
5722
|
message = createMessage(baseMessage);
|
|
3885
5723
|
}
|
|
3886
|
-
|
|
5724
|
+
let toolUses = state.toolUses;
|
|
5725
|
+
if (processedInput.role === "tool-use" && processedInput.toolCall) {
|
|
5726
|
+
if (validate && state.toolUses.has(processedInput.toolCall.id)) {
|
|
5727
|
+
throw createIntegrityError("duplicate toolCall.id in conversation", {
|
|
5728
|
+
toolCallId: processedInput.toolCall.id,
|
|
5729
|
+
messageId: baseMessage.id
|
|
5730
|
+
});
|
|
5731
|
+
}
|
|
5732
|
+
toolUses = validate ? registerToolUse(state.toolUses, processedInput.toolCall) : state.toolUses;
|
|
5733
|
+
}
|
|
3887
5734
|
return {
|
|
3888
5735
|
toolUses,
|
|
3889
5736
|
messages: [...state.messages, message]
|
|
3890
5737
|
};
|
|
3891
5738
|
}, { toolUses: initialToolUses, messages: [] });
|
|
3892
5739
|
const messageIds = messages.map((message) => message.id);
|
|
3893
|
-
const
|
|
5740
|
+
const next2 = {
|
|
3894
5741
|
...conversation,
|
|
3895
5742
|
ids: [...conversation.ids, ...messageIds],
|
|
3896
5743
|
messages: { ...conversation.messages, ...toIdRecord(messages) },
|
|
3897
5744
|
updatedAt: now
|
|
3898
5745
|
};
|
|
3899
|
-
|
|
3900
|
-
|
|
5746
|
+
const readonly = toReadonly(next2);
|
|
5747
|
+
return validate ? ensureConversationSafe(readonly) : readonly;
|
|
5748
|
+
};
|
|
3901
5749
|
function appendUserMessage(conversation, content, metadata, environment) {
|
|
3902
|
-
|
|
5750
|
+
const resolvedEnvironment = isConversationEnvironmentParameter(metadata) ? metadata : environment;
|
|
5751
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5752
|
+
return appendMessages(conversation, { role: "user", content, metadata: resolvedMetadata }, resolvedEnvironment);
|
|
3903
5753
|
}
|
|
3904
5754
|
function appendAssistantMessage(conversation, content, metadata, environment) {
|
|
3905
|
-
|
|
5755
|
+
const resolvedEnvironment = isConversationEnvironmentParameter(metadata) ? metadata : environment;
|
|
5756
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5757
|
+
return appendMessages(conversation, { role: "assistant", content, metadata: resolvedMetadata }, resolvedEnvironment);
|
|
3906
5758
|
}
|
|
3907
5759
|
function appendSystemMessage(conversation, content, metadata, environment) {
|
|
3908
|
-
|
|
5760
|
+
const resolvedEnvironment = isConversationEnvironmentParameter(metadata) ? metadata : environment;
|
|
5761
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5762
|
+
return appendMessages(conversation, { role: "system", content, metadata: resolvedMetadata }, resolvedEnvironment);
|
|
3909
5763
|
}
|
|
5764
|
+
// src/conversation/query.ts
|
|
3910
5765
|
function getMessages(conversation, options2) {
|
|
3911
5766
|
const includeHidden = options2?.includeHidden ?? false;
|
|
3912
5767
|
const ordered = getOrderedMessages(conversation);
|
|
@@ -3940,6 +5795,7 @@ function getStatistics(conversation) {
|
|
|
3940
5795
|
}, { byRole: {}, hidden: 0, withImages: 0 });
|
|
3941
5796
|
return { total: ordered.length, ...stats };
|
|
3942
5797
|
}
|
|
5798
|
+
// src/conversation/system-messages.ts
|
|
3943
5799
|
function hasSystemMessage(conversation) {
|
|
3944
5800
|
return getOrderedMessages(conversation).some((m) => m.role === "system");
|
|
3945
5801
|
}
|
|
@@ -3950,7 +5806,8 @@ function getSystemMessages(conversation) {
|
|
|
3950
5806
|
return getOrderedMessages(conversation).filter((m) => m.role === "system");
|
|
3951
5807
|
}
|
|
3952
5808
|
function prependSystemMessage(conversation, content, metadata, environment) {
|
|
3953
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5809
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(metadata) ? metadata : environment);
|
|
5810
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
3954
5811
|
const now = resolvedEnvironment.now();
|
|
3955
5812
|
const newMessage = createMessage({
|
|
3956
5813
|
id: resolvedEnvironment.randomId(),
|
|
@@ -3958,7 +5815,7 @@ function prependSystemMessage(conversation, content, metadata, environment) {
|
|
|
3958
5815
|
content,
|
|
3959
5816
|
position: 0,
|
|
3960
5817
|
createdAt: now,
|
|
3961
|
-
metadata: { ...
|
|
5818
|
+
metadata: { ...resolvedMetadata ?? {} },
|
|
3962
5819
|
hidden: false,
|
|
3963
5820
|
toolCall: undefined,
|
|
3964
5821
|
toolResult: undefined,
|
|
@@ -3977,20 +5834,21 @@ function prependSystemMessage(conversation, content, metadata, environment) {
|
|
|
3977
5834
|
toolResult: message.toolResult,
|
|
3978
5835
|
tokenUsage: message.tokenUsage
|
|
3979
5836
|
}));
|
|
3980
|
-
return toReadonly({
|
|
5837
|
+
return ensureConversationSafe(toReadonly({
|
|
3981
5838
|
...conversation,
|
|
3982
5839
|
ids: [newMessage.id, ...ordered.map((message) => message.id)],
|
|
3983
5840
|
messages: toIdRecord([newMessage, ...renumberedMessages]),
|
|
3984
5841
|
updatedAt: now
|
|
3985
|
-
});
|
|
5842
|
+
}));
|
|
3986
5843
|
}
|
|
3987
5844
|
function replaceSystemMessage(conversation, content, metadata, environment) {
|
|
3988
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5845
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(metadata) ? metadata : environment);
|
|
5846
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
3989
5847
|
const now = resolvedEnvironment.now();
|
|
3990
5848
|
const ordered = getOrderedMessages(conversation);
|
|
3991
5849
|
const firstSystemIndex = ordered.findIndex((m) => m.role === "system");
|
|
3992
5850
|
if (firstSystemIndex === -1) {
|
|
3993
|
-
return prependSystemMessage(conversation, content,
|
|
5851
|
+
return prependSystemMessage(conversation, content, resolvedMetadata, resolvedEnvironment);
|
|
3994
5852
|
}
|
|
3995
5853
|
const original = ordered[firstSystemIndex];
|
|
3996
5854
|
const replaced = createMessage({
|
|
@@ -3999,25 +5857,25 @@ function replaceSystemMessage(conversation, content, metadata, environment) {
|
|
|
3999
5857
|
content,
|
|
4000
5858
|
position: original.position,
|
|
4001
5859
|
createdAt: original.createdAt,
|
|
4002
|
-
metadata: { ...
|
|
5860
|
+
metadata: { ...resolvedMetadata ?? original.metadata },
|
|
4003
5861
|
hidden: original.hidden,
|
|
4004
5862
|
toolCall: undefined,
|
|
4005
5863
|
toolResult: undefined,
|
|
4006
5864
|
tokenUsage: undefined
|
|
4007
5865
|
});
|
|
4008
|
-
const
|
|
5866
|
+
const next2 = {
|
|
4009
5867
|
...conversation,
|
|
4010
5868
|
ids: [...conversation.ids],
|
|
4011
5869
|
messages: { ...conversation.messages, [replaced.id]: replaced },
|
|
4012
5870
|
updatedAt: now
|
|
4013
5871
|
};
|
|
4014
|
-
return toReadonly(
|
|
5872
|
+
return ensureConversationSafe(toReadonly(next2));
|
|
4015
5873
|
}
|
|
4016
5874
|
function collapseSystemMessages(conversation, environment) {
|
|
4017
5875
|
const ordered = getOrderedMessages(conversation);
|
|
4018
5876
|
const systemMessages = ordered.filter((m) => m.role === "system");
|
|
4019
5877
|
if (systemMessages.length <= 1) {
|
|
4020
|
-
return conversation;
|
|
5878
|
+
return ensureConversationSafe(conversation);
|
|
4021
5879
|
}
|
|
4022
5880
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
4023
5881
|
const now = resolvedEnvironment.now();
|
|
@@ -4067,15 +5925,48 @@ function collapseSystemMessages(conversation, environment) {
|
|
|
4067
5925
|
tokenUsage: message.tokenUsage
|
|
4068
5926
|
});
|
|
4069
5927
|
});
|
|
4070
|
-
const
|
|
5928
|
+
const next2 = {
|
|
4071
5929
|
...conversation,
|
|
4072
5930
|
ids: renumbered.map((message) => message.id),
|
|
4073
5931
|
messages: toIdRecord(renumbered),
|
|
4074
5932
|
updatedAt: now
|
|
4075
5933
|
};
|
|
4076
|
-
return toReadonly(
|
|
5934
|
+
return ensureConversationSafe(toReadonly(next2));
|
|
5935
|
+
}
|
|
5936
|
+
// src/utilities/tool-results.ts
|
|
5937
|
+
function copyToolResult(toolResult) {
|
|
5938
|
+
return { ...toolResult };
|
|
5939
|
+
}
|
|
5940
|
+
function redactToolResult(toolResult, placeholder) {
|
|
5941
|
+
return { ...toolResult, content: placeholder };
|
|
4077
5942
|
}
|
|
4078
|
-
|
|
5943
|
+
|
|
5944
|
+
// src/conversation/modify.ts
|
|
5945
|
+
var isRedactMessageOptions = (value) => {
|
|
5946
|
+
if (!value || typeof value !== "object")
|
|
5947
|
+
return false;
|
|
5948
|
+
const candidate = value;
|
|
5949
|
+
return "placeholder" in candidate || "redactToolArguments" in candidate || "redactToolResults" in candidate || "clearToolMetadata" in candidate;
|
|
5950
|
+
};
|
|
5951
|
+
function redactMessageAtPosition(conversation, position, placeholderOrOptions, environment) {
|
|
5952
|
+
let placeholder = "[REDACTED]";
|
|
5953
|
+
let options2 = {};
|
|
5954
|
+
let env = environment;
|
|
5955
|
+
if (typeof placeholderOrOptions === "string") {
|
|
5956
|
+
placeholder = placeholderOrOptions;
|
|
5957
|
+
} else if (placeholderOrOptions) {
|
|
5958
|
+
if (!environment && isConversationEnvironmentParameter(placeholderOrOptions)) {
|
|
5959
|
+
env = placeholderOrOptions;
|
|
5960
|
+
} else if (isRedactMessageOptions(placeholderOrOptions)) {
|
|
5961
|
+
options2 = placeholderOrOptions;
|
|
5962
|
+
if (options2.placeholder) {
|
|
5963
|
+
placeholder = options2.placeholder;
|
|
5964
|
+
}
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
const redactToolArguments = options2.redactToolArguments ?? true;
|
|
5968
|
+
const redactToolResults = options2.redactToolResults ?? true;
|
|
5969
|
+
const clearToolMetadata = options2.clearToolMetadata ?? false;
|
|
4079
5970
|
if (position < 0 || position >= conversation.ids.length) {
|
|
4080
5971
|
throw createInvalidPositionError(conversation.ids.length - 1, position);
|
|
4081
5972
|
}
|
|
@@ -4084,6 +5975,22 @@ function redactMessageAtPosition(conversation, position, placeholder = "[REDACTE
|
|
|
4084
5975
|
if (!original) {
|
|
4085
5976
|
throw createInvalidPositionError(conversation.ids.length - 1, position);
|
|
4086
5977
|
}
|
|
5978
|
+
let toolCall = original.toolCall ? { ...original.toolCall } : undefined;
|
|
5979
|
+
let toolResult = original.toolResult ? { ...original.toolResult } : undefined;
|
|
5980
|
+
if (clearToolMetadata) {
|
|
5981
|
+
toolCall = undefined;
|
|
5982
|
+
toolResult = undefined;
|
|
5983
|
+
} else {
|
|
5984
|
+
if (original.role === "tool-use" && toolCall) {
|
|
5985
|
+
toolCall = {
|
|
5986
|
+
...toolCall,
|
|
5987
|
+
arguments: redactToolArguments ? placeholder : toolCall.arguments
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
if (original.role === "tool-result" && toolResult) {
|
|
5991
|
+
toolResult = redactToolResults ? redactToolResult(toolResult, placeholder) : { ...toolResult };
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
4087
5994
|
const redacted = createMessage({
|
|
4088
5995
|
id: original.id,
|
|
4089
5996
|
role: original.role,
|
|
@@ -4092,82 +5999,74 @@ function redactMessageAtPosition(conversation, position, placeholder = "[REDACTE
|
|
|
4092
5999
|
createdAt: original.createdAt,
|
|
4093
6000
|
metadata: { ...original.metadata },
|
|
4094
6001
|
hidden: original.hidden,
|
|
4095
|
-
toolCall
|
|
4096
|
-
toolResult
|
|
4097
|
-
tokenUsage: undefined
|
|
6002
|
+
toolCall,
|
|
6003
|
+
toolResult,
|
|
6004
|
+
tokenUsage: original.tokenUsage ? { ...original.tokenUsage } : undefined
|
|
4098
6005
|
});
|
|
4099
|
-
const resolvedEnvironment = resolveConversationEnvironment(
|
|
6006
|
+
const resolvedEnvironment = resolveConversationEnvironment(env);
|
|
4100
6007
|
const now = resolvedEnvironment.now();
|
|
4101
|
-
const
|
|
6008
|
+
const next2 = {
|
|
4102
6009
|
...conversation,
|
|
4103
6010
|
ids: [...conversation.ids],
|
|
4104
6011
|
messages: { ...conversation.messages, [redacted.id]: redacted },
|
|
4105
6012
|
updatedAt: now
|
|
4106
6013
|
};
|
|
4107
|
-
return toReadonly(
|
|
6014
|
+
return ensureConversationSafe(toReadonly(next2));
|
|
4108
6015
|
}
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
messages = { ...rawMessages };
|
|
4134
|
-
if (isStringArray(rawIds) && rawIds.length > 0) {
|
|
4135
|
-
ids = [...rawIds];
|
|
4136
|
-
} else {
|
|
4137
|
-
ids = Object.values(messages).sort((a, b) => a.position - b.position).map((message) => message.id);
|
|
4138
|
-
}
|
|
4139
|
-
}
|
|
4140
|
-
if (ids.length > 0) {
|
|
4141
|
-
ids = ids.filter((id) => (id in messages));
|
|
4142
|
-
const missing = Object.keys(messages).filter((id) => !ids.includes(id));
|
|
4143
|
-
if (missing.length > 0) {
|
|
4144
|
-
const sortedMissing = missing.sort((a, b) => (messages[a]?.position ?? 0) - (messages[b]?.position ?? 0));
|
|
4145
|
-
ids = [...ids, ...sortedMissing];
|
|
4146
|
-
}
|
|
4147
|
-
}
|
|
4148
|
-
if (!("schemaVersion" in json)) {
|
|
6016
|
+
// src/conversation/serialization.ts
|
|
6017
|
+
function normalizeToolResult(toolResult) {
|
|
6018
|
+
if (!toolResult)
|
|
6019
|
+
return;
|
|
6020
|
+
return {
|
|
6021
|
+
callId: toolResult.callId,
|
|
6022
|
+
outcome: toolResult.outcome,
|
|
6023
|
+
content: toolResult.content
|
|
6024
|
+
};
|
|
6025
|
+
}
|
|
6026
|
+
function normalizeMessage(message) {
|
|
6027
|
+
const base = {
|
|
6028
|
+
id: message.id,
|
|
6029
|
+
role: message.role,
|
|
6030
|
+
content: message.content,
|
|
6031
|
+
position: message.position,
|
|
6032
|
+
createdAt: message.createdAt,
|
|
6033
|
+
metadata: message.metadata,
|
|
6034
|
+
hidden: message.hidden,
|
|
6035
|
+
toolCall: message.toolCall ? { ...message.toolCall } : undefined,
|
|
6036
|
+
toolResult: normalizeToolResult(message.toolResult),
|
|
6037
|
+
tokenUsage: message.tokenUsage ? { ...message.tokenUsage } : undefined
|
|
6038
|
+
};
|
|
6039
|
+
if (isAssistantMessage(message)) {
|
|
4149
6040
|
return {
|
|
4150
|
-
...
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
messages
|
|
6041
|
+
...base,
|
|
6042
|
+
role: "assistant",
|
|
6043
|
+
goalCompleted: message.goalCompleted
|
|
4154
6044
|
};
|
|
4155
6045
|
}
|
|
4156
|
-
return
|
|
6046
|
+
return base;
|
|
4157
6047
|
}
|
|
4158
6048
|
function deserializeConversation(json) {
|
|
4159
|
-
const
|
|
6049
|
+
const parsed = conversationSchema.safeParse(json);
|
|
6050
|
+
if (!parsed.success) {
|
|
6051
|
+
throw createSerializationError("failed to deserialize conversation: invalid data");
|
|
6052
|
+
}
|
|
6053
|
+
const data = parsed.data;
|
|
4160
6054
|
try {
|
|
4161
|
-
const
|
|
4162
|
-
|
|
6055
|
+
const messageIds = new Set(Object.keys(data.messages));
|
|
6056
|
+
const orderedMessages = data.ids.map((id, index) => {
|
|
6057
|
+
const message = data.messages[id];
|
|
4163
6058
|
if (!message) {
|
|
4164
6059
|
throw createSerializationError(`missing message for id ${id}`);
|
|
4165
6060
|
}
|
|
4166
6061
|
if (message.position !== index) {
|
|
4167
6062
|
throw createInvalidPositionError(index, message.position);
|
|
4168
6063
|
}
|
|
4169
|
-
|
|
6064
|
+
messageIds.delete(id);
|
|
6065
|
+
return normalizeMessage(message);
|
|
4170
6066
|
});
|
|
6067
|
+
if (messageIds.size > 0) {
|
|
6068
|
+
throw createSerializationError(`messages not listed in ids: ${[...messageIds].join(", ")}`);
|
|
6069
|
+
}
|
|
4171
6070
|
orderedMessages.reduce((state, message) => {
|
|
4172
6071
|
if (message.role === "tool-use" && message.toolCall) {
|
|
4173
6072
|
return {
|
|
@@ -4179,24 +6078,28 @@ function deserializeConversation(json) {
|
|
|
4179
6078
|
}
|
|
4180
6079
|
return state;
|
|
4181
6080
|
}, { toolUses: new Map });
|
|
4182
|
-
const messageInstances = orderedMessages.map((
|
|
6081
|
+
const messageInstances = orderedMessages.map((message) => createMessage(message));
|
|
4183
6082
|
const conv = {
|
|
4184
|
-
schemaVersion:
|
|
4185
|
-
id:
|
|
4186
|
-
title:
|
|
4187
|
-
status:
|
|
4188
|
-
metadata: { ...
|
|
6083
|
+
schemaVersion: data.schemaVersion,
|
|
6084
|
+
id: data.id,
|
|
6085
|
+
title: data.title,
|
|
6086
|
+
status: data.status,
|
|
6087
|
+
metadata: { ...data.metadata },
|
|
4189
6088
|
ids: orderedMessages.map((message) => message.id),
|
|
4190
6089
|
messages: toIdRecord(messageInstances),
|
|
4191
|
-
createdAt:
|
|
4192
|
-
updatedAt:
|
|
6090
|
+
createdAt: data.createdAt,
|
|
6091
|
+
updatedAt: data.updatedAt
|
|
4193
6092
|
};
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
6093
|
+
const readonly = toReadonly(conv);
|
|
6094
|
+
assertConversationIntegrity(readonly);
|
|
6095
|
+
return readonly;
|
|
6096
|
+
} catch (error2) {
|
|
6097
|
+
throw createSerializationError(`failed to deserialize conversation: ${error2 instanceof Error ? error2.message : String(error2)}`, error2);
|
|
4197
6098
|
}
|
|
4198
6099
|
}
|
|
6100
|
+
// src/conversation/transform.ts
|
|
4199
6101
|
function toChatMessages(conversation) {
|
|
6102
|
+
assertConversationSafe(conversation);
|
|
4200
6103
|
const roleMap = {
|
|
4201
6104
|
user: "user",
|
|
4202
6105
|
assistant: "assistant",
|
|
@@ -4218,7 +6121,6 @@ function toChatMessages(conversation) {
|
|
|
4218
6121
|
}
|
|
4219
6122
|
return result;
|
|
4220
6123
|
}
|
|
4221
|
-
|
|
4222
6124
|
// src/streaming.ts
|
|
4223
6125
|
var STREAMING_KEY = "__streaming";
|
|
4224
6126
|
var cloneMessage = (original, overrides = {}) => {
|
|
@@ -4251,7 +6153,8 @@ function getStreamingMessage(conversation) {
|
|
|
4251
6153
|
return getOrderedMessages(conversation).find(isStreamingMessage);
|
|
4252
6154
|
}
|
|
4253
6155
|
function appendStreamingMessage(conversation, role, metadata, environment) {
|
|
4254
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
6156
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(metadata) ? metadata : environment);
|
|
6157
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
4255
6158
|
const now = resolvedEnvironment.now();
|
|
4256
6159
|
const messageId = resolvedEnvironment.randomId();
|
|
4257
6160
|
const newMessage = createMessage({
|
|
@@ -4260,7 +6163,7 @@ function appendStreamingMessage(conversation, role, metadata, environment) {
|
|
|
4260
6163
|
content: "",
|
|
4261
6164
|
position: conversation.ids.length,
|
|
4262
6165
|
createdAt: now,
|
|
4263
|
-
metadata: { ...
|
|
6166
|
+
metadata: { ...resolvedMetadata ?? {}, [STREAMING_KEY]: true },
|
|
4264
6167
|
hidden: false,
|
|
4265
6168
|
toolCall: undefined,
|
|
4266
6169
|
toolResult: undefined,
|
|
@@ -4272,14 +6175,14 @@ function appendStreamingMessage(conversation, role, metadata, environment) {
|
|
|
4272
6175
|
messages: { ...conversation.messages, [messageId]: newMessage },
|
|
4273
6176
|
updatedAt: now
|
|
4274
6177
|
});
|
|
4275
|
-
return { conversation: updatedConversation, messageId };
|
|
6178
|
+
return { conversation: ensureConversationSafe(updatedConversation), messageId };
|
|
4276
6179
|
}
|
|
4277
6180
|
function updateStreamingMessage(conversation, messageId, content, environment) {
|
|
4278
6181
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
4279
6182
|
const now = resolvedEnvironment.now();
|
|
4280
6183
|
const original = conversation.messages[messageId];
|
|
4281
6184
|
if (!original) {
|
|
4282
|
-
return conversation;
|
|
6185
|
+
return ensureConversationSafe(conversation);
|
|
4283
6186
|
}
|
|
4284
6187
|
const overrides = {
|
|
4285
6188
|
content: typeof content === "string" ? content : [...content]
|
|
@@ -4288,44 +6191,45 @@ function updateStreamingMessage(conversation, messageId, content, environment) {
|
|
|
4288
6191
|
overrides.tokenUsage = { ...original.tokenUsage };
|
|
4289
6192
|
}
|
|
4290
6193
|
const updated = cloneMessage(original, overrides);
|
|
4291
|
-
return toReadonly({
|
|
6194
|
+
return ensureConversationSafe(toReadonly({
|
|
4292
6195
|
...conversation,
|
|
4293
6196
|
ids: [...conversation.ids],
|
|
4294
6197
|
messages: { ...conversation.messages, [updated.id]: updated },
|
|
4295
6198
|
updatedAt: now
|
|
4296
|
-
});
|
|
6199
|
+
}));
|
|
4297
6200
|
}
|
|
4298
6201
|
function finalizeStreamingMessage(conversation, messageId, options2, environment) {
|
|
4299
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
6202
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(options2) ? options2 : environment);
|
|
6203
|
+
const resolvedOptions = isConversationEnvironmentParameter(options2) ? undefined : options2;
|
|
4300
6204
|
const now = resolvedEnvironment.now();
|
|
4301
6205
|
const original = conversation.messages[messageId];
|
|
4302
6206
|
if (!original) {
|
|
4303
|
-
return conversation;
|
|
6207
|
+
return ensureConversationSafe(conversation);
|
|
4304
6208
|
}
|
|
4305
6209
|
const { [STREAMING_KEY]: _, ...restMetadata } = original.metadata;
|
|
4306
6210
|
const finalMetadata = {
|
|
4307
6211
|
...restMetadata,
|
|
4308
|
-
...
|
|
6212
|
+
...resolvedOptions?.metadata ?? {}
|
|
4309
6213
|
};
|
|
4310
6214
|
const finalizeOverrides = {
|
|
4311
6215
|
metadata: finalMetadata
|
|
4312
6216
|
};
|
|
4313
|
-
if (
|
|
4314
|
-
finalizeOverrides.tokenUsage = { ...
|
|
6217
|
+
if (resolvedOptions?.tokenUsage) {
|
|
6218
|
+
finalizeOverrides.tokenUsage = { ...resolvedOptions.tokenUsage };
|
|
4315
6219
|
}
|
|
4316
6220
|
const updated = cloneMessage(original, finalizeOverrides);
|
|
4317
|
-
return toReadonly({
|
|
6221
|
+
return ensureConversationSafe(toReadonly({
|
|
4318
6222
|
...conversation,
|
|
4319
6223
|
ids: [...conversation.ids],
|
|
4320
6224
|
messages: { ...conversation.messages, [updated.id]: updated },
|
|
4321
6225
|
updatedAt: now
|
|
4322
|
-
});
|
|
6226
|
+
}));
|
|
4323
6227
|
}
|
|
4324
6228
|
function cancelStreamingMessage(conversation, messageId, environment) {
|
|
4325
6229
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
4326
6230
|
const now = resolvedEnvironment.now();
|
|
4327
6231
|
if (!conversation.messages[messageId]) {
|
|
4328
|
-
return conversation;
|
|
6232
|
+
return ensureConversationSafe(conversation);
|
|
4329
6233
|
}
|
|
4330
6234
|
const messages = getOrderedMessages(conversation).filter((m) => m.id !== messageId).map((message, index) => message.position === index ? message : (() => {
|
|
4331
6235
|
const overrides = {
|
|
@@ -4336,29 +6240,26 @@ function cancelStreamingMessage(conversation, messageId, environment) {
|
|
|
4336
6240
|
}
|
|
4337
6241
|
return cloneMessage(message, overrides);
|
|
4338
6242
|
})());
|
|
4339
|
-
return toReadonly({
|
|
6243
|
+
return ensureConversationSafe(toReadonly({
|
|
4340
6244
|
...conversation,
|
|
4341
6245
|
ids: messages.map((message) => message.id),
|
|
4342
6246
|
messages: toIdRecord(messages),
|
|
4343
6247
|
updatedAt: now
|
|
4344
|
-
});
|
|
6248
|
+
}));
|
|
4345
6249
|
}
|
|
4346
6250
|
|
|
4347
6251
|
// src/history.ts
|
|
4348
|
-
class ConversationHistoryEvent extends CustomEvent {
|
|
4349
|
-
constructor(type, detail) {
|
|
4350
|
-
super(type, { detail });
|
|
4351
|
-
}
|
|
4352
|
-
}
|
|
4353
|
-
|
|
4354
6252
|
class ConversationHistory extends EventTarget {
|
|
4355
6253
|
currentNode;
|
|
4356
6254
|
environment;
|
|
6255
|
+
events;
|
|
4357
6256
|
constructor(initial = createConversation(), environment) {
|
|
4358
6257
|
super();
|
|
4359
6258
|
this.environment = resolveConversationEnvironment(environment);
|
|
6259
|
+
this.events = createEventTarget();
|
|
6260
|
+
const safeInitial = ensureConversationSafe(initial);
|
|
4360
6261
|
this.currentNode = {
|
|
4361
|
-
conversation:
|
|
6262
|
+
conversation: safeInitial,
|
|
4362
6263
|
parent: null,
|
|
4363
6264
|
children: []
|
|
4364
6265
|
};
|
|
@@ -4368,25 +6269,54 @@ class ConversationHistory extends EventTarget {
|
|
|
4368
6269
|
type,
|
|
4369
6270
|
conversation: this.current
|
|
4370
6271
|
};
|
|
4371
|
-
this.dispatchEvent(
|
|
4372
|
-
this.dispatchEvent(
|
|
6272
|
+
this.events.dispatchEvent({ type: "change", detail });
|
|
6273
|
+
this.events.dispatchEvent({ type, detail });
|
|
6274
|
+
}
|
|
6275
|
+
toAddListenerOptions(options2) {
|
|
6276
|
+
if (typeof options2 === "boolean" || options2 === undefined)
|
|
6277
|
+
return options2;
|
|
6278
|
+
const mapped = {};
|
|
6279
|
+
if (options2.capture !== undefined)
|
|
6280
|
+
mapped.capture = options2.capture;
|
|
6281
|
+
if (options2.once !== undefined)
|
|
6282
|
+
mapped.once = options2.once;
|
|
6283
|
+
if (options2.passive !== undefined)
|
|
6284
|
+
mapped.passive = options2.passive;
|
|
6285
|
+
if (options2.signal !== undefined) {
|
|
6286
|
+
mapped.signal = options2.signal;
|
|
6287
|
+
}
|
|
6288
|
+
return mapped;
|
|
6289
|
+
}
|
|
6290
|
+
toRemoveListenerOptions(options2) {
|
|
6291
|
+
if (typeof options2 === "boolean" || options2 === undefined)
|
|
6292
|
+
return options2;
|
|
6293
|
+
const mapped = {};
|
|
6294
|
+
if (options2.capture !== undefined)
|
|
6295
|
+
mapped.capture = options2.capture;
|
|
6296
|
+
return mapped;
|
|
4373
6297
|
}
|
|
4374
6298
|
addEventListener(type, callback, options2) {
|
|
4375
6299
|
if (!callback)
|
|
4376
6300
|
return;
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
6301
|
+
return this.events.addEventListener(type, callback, this.toAddListenerOptions(options2));
|
|
6302
|
+
}
|
|
6303
|
+
removeEventListener(type, callback, options2) {
|
|
6304
|
+
if (!callback)
|
|
6305
|
+
return;
|
|
6306
|
+
this.events.removeEventListener(type, callback, this.toRemoveListenerOptions(options2));
|
|
6307
|
+
}
|
|
6308
|
+
dispatchEvent(event) {
|
|
6309
|
+
return this.events.dispatchEvent(event);
|
|
4380
6310
|
}
|
|
4381
6311
|
subscribe(run) {
|
|
4382
6312
|
run(this.current);
|
|
4383
6313
|
const handler = (event) => {
|
|
4384
|
-
if (event
|
|
6314
|
+
if (event?.detail?.conversation) {
|
|
4385
6315
|
run(event.detail.conversation);
|
|
4386
6316
|
}
|
|
4387
6317
|
};
|
|
4388
|
-
const
|
|
4389
|
-
return
|
|
6318
|
+
const unsubscribe2 = this.addEventListener("change", handler);
|
|
6319
|
+
return unsubscribe2 || (() => {});
|
|
4390
6320
|
}
|
|
4391
6321
|
getSnapshot() {
|
|
4392
6322
|
return this.current;
|
|
@@ -4417,9 +6347,9 @@ class ConversationHistory extends EventTarget {
|
|
|
4417
6347
|
get redoCount() {
|
|
4418
6348
|
return this.currentNode.children.length;
|
|
4419
6349
|
}
|
|
4420
|
-
push(
|
|
6350
|
+
push(next2) {
|
|
4421
6351
|
const newNode = {
|
|
4422
|
-
conversation:
|
|
6352
|
+
conversation: next2,
|
|
4423
6353
|
parent: this.currentNode,
|
|
4424
6354
|
children: []
|
|
4425
6355
|
};
|
|
@@ -4436,9 +6366,9 @@ class ConversationHistory extends EventTarget {
|
|
|
4436
6366
|
return;
|
|
4437
6367
|
}
|
|
4438
6368
|
redo(childIndex = 0) {
|
|
4439
|
-
const
|
|
4440
|
-
if (
|
|
4441
|
-
this.currentNode =
|
|
6369
|
+
const next2 = this.currentNode.children[childIndex];
|
|
6370
|
+
if (next2) {
|
|
6371
|
+
this.currentNode = next2;
|
|
4442
6372
|
this.notifyChange("redo");
|
|
4443
6373
|
return this.current;
|
|
4444
6374
|
}
|
|
@@ -4527,8 +6457,8 @@ class ConversationHistory extends EventTarget {
|
|
|
4527
6457
|
collapseSystemMessages() {
|
|
4528
6458
|
this.push(collapseSystemMessages(this.current, this.env));
|
|
4529
6459
|
}
|
|
4530
|
-
redactMessageAtPosition(position,
|
|
4531
|
-
this.push(redactMessageAtPosition(this.current, position,
|
|
6460
|
+
redactMessageAtPosition(position, placeholderOrOptions) {
|
|
6461
|
+
this.push(redactMessageAtPosition(this.current, position, placeholderOrOptions, this.env));
|
|
4532
6462
|
}
|
|
4533
6463
|
truncateFromPosition(position, options2) {
|
|
4534
6464
|
this.push(truncateFromPosition(this.current, position, options2, this.env));
|
|
@@ -4625,6 +6555,7 @@ class ConversationHistory extends EventTarget {
|
|
|
4625
6555
|
};
|
|
4626
6556
|
if (root)
|
|
4627
6557
|
clearNode(root);
|
|
6558
|
+
this.events.clear();
|
|
4628
6559
|
}
|
|
4629
6560
|
}
|
|
4630
6561
|
function isConversation(value) {
|
|
@@ -4633,23 +6564,6 @@ function isConversation(value) {
|
|
|
4633
6564
|
|
|
4634
6565
|
// src/utilities/markdown.ts
|
|
4635
6566
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
4636
|
-
|
|
4637
|
-
// src/utilities/tool-results.ts
|
|
4638
|
-
function copyToolResult(toolResult) {
|
|
4639
|
-
return { ...toolResult };
|
|
4640
|
-
}
|
|
4641
|
-
function redactToolResult(toolResult, placeholder) {
|
|
4642
|
-
const result = { ...toolResult, content: placeholder };
|
|
4643
|
-
if (result.result !== undefined) {
|
|
4644
|
-
result.result = placeholder;
|
|
4645
|
-
}
|
|
4646
|
-
if (result.error !== undefined) {
|
|
4647
|
-
result.error = placeholder;
|
|
4648
|
-
}
|
|
4649
|
-
return result;
|
|
4650
|
-
}
|
|
4651
|
-
|
|
4652
|
-
// src/utilities/markdown.ts
|
|
4653
6567
|
var ROLE_LABELS = {
|
|
4654
6568
|
user: "User",
|
|
4655
6569
|
assistant: "Assistant",
|
|
@@ -4659,7 +6573,6 @@ var ROLE_LABELS = {
|
|
|
4659
6573
|
"tool-result": "Tool Result",
|
|
4660
6574
|
snapshot: "Snapshot"
|
|
4661
6575
|
};
|
|
4662
|
-
var ROLE_DISPLAY_NAMES = ROLE_LABELS;
|
|
4663
6576
|
var LABEL_TO_ROLE = {
|
|
4664
6577
|
User: "user",
|
|
4665
6578
|
Assistant: "assistant",
|
|
@@ -4669,7 +6582,6 @@ var LABEL_TO_ROLE = {
|
|
|
4669
6582
|
"Tool Result": "tool-result",
|
|
4670
6583
|
Snapshot: "snapshot"
|
|
4671
6584
|
};
|
|
4672
|
-
var DISPLAY_NAME_TO_ROLE = LABEL_TO_ROLE;
|
|
4673
6585
|
function getRoleLabel(role) {
|
|
4674
6586
|
return ROLE_LABELS[role];
|
|
4675
6587
|
}
|
|
@@ -4752,6 +6664,7 @@ function formatMessageContent(message) {
|
|
|
4752
6664
|
`);
|
|
4753
6665
|
}
|
|
4754
6666
|
function toMarkdown(conversation, options2 = {}) {
|
|
6667
|
+
assertConversationSafe(conversation);
|
|
4755
6668
|
const resolved = resolveMarkdownOptions(options2);
|
|
4756
6669
|
const prepared = prepareConversationForMarkdown(conversation, resolved);
|
|
4757
6670
|
if (resolved.includeMetadata) {
|
|
@@ -4762,7 +6675,7 @@ function toMarkdown(conversation, options2 = {}) {
|
|
|
4762
6675
|
function toMarkdownSimple(conversation) {
|
|
4763
6676
|
const sections = [];
|
|
4764
6677
|
for (const message of getOrderedMessages(conversation)) {
|
|
4765
|
-
const roleName =
|
|
6678
|
+
const roleName = ROLE_LABELS[message.role];
|
|
4766
6679
|
const header = `### ${roleName}`;
|
|
4767
6680
|
const content = formatMessageContent(message);
|
|
4768
6681
|
sections.push(`${header}
|
|
@@ -4813,7 +6726,7 @@ function toMarkdownWithMetadata(conversation, _options) {
|
|
|
4813
6726
|
}
|
|
4814
6727
|
const messageSections = [];
|
|
4815
6728
|
for (const message of getOrderedMessages(conversation)) {
|
|
4816
|
-
const roleName =
|
|
6729
|
+
const roleName = ROLE_LABELS[message.role];
|
|
4817
6730
|
const header = `### ${roleName} (${message.id})`;
|
|
4818
6731
|
const content = formatMessageContent(message);
|
|
4819
6732
|
messageSections.push(`${header}
|
|
@@ -4838,10 +6751,13 @@ function generateId() {
|
|
|
4838
6751
|
function fromMarkdown(markdown) {
|
|
4839
6752
|
const trimmed = markdown.trim();
|
|
4840
6753
|
const hasFrontmatter = trimmed.startsWith("---");
|
|
4841
|
-
|
|
4842
|
-
|
|
6754
|
+
const conversation = hasFrontmatter ? parseMarkdownWithMetadata(trimmed) : parseMarkdownSimple(trimmed);
|
|
6755
|
+
try {
|
|
6756
|
+
assertConversationSafe(conversation);
|
|
6757
|
+
} catch (error2) {
|
|
6758
|
+
throw new MarkdownParseError(`Invalid markdown conversation: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
4843
6759
|
}
|
|
4844
|
-
return
|
|
6760
|
+
return conversation;
|
|
4845
6761
|
}
|
|
4846
6762
|
function parseMarkdownWithMetadata(trimmed) {
|
|
4847
6763
|
let parsed;
|
|
@@ -4860,7 +6776,7 @@ function parseMarkdownWithMetadata(trimmed) {
|
|
|
4860
6776
|
let match;
|
|
4861
6777
|
while ((match = messagePattern.exec(body)) !== null) {
|
|
4862
6778
|
const [, roleDisplay, messageId, contentBody] = match;
|
|
4863
|
-
const role =
|
|
6779
|
+
const role = LABEL_TO_ROLE[roleDisplay];
|
|
4864
6780
|
if (!role) {
|
|
4865
6781
|
throw new MarkdownParseError(`Unknown role: ${roleDisplay}`);
|
|
4866
6782
|
}
|
|
@@ -4917,7 +6833,7 @@ function parseMarkdownSimple(body) {
|
|
|
4917
6833
|
let position = 0;
|
|
4918
6834
|
while ((match = messagePattern.exec(body)) !== null) {
|
|
4919
6835
|
const [, roleDisplay, contentBody] = match;
|
|
4920
|
-
const role =
|
|
6836
|
+
const role = LABEL_TO_ROLE[roleDisplay];
|
|
4921
6837
|
if (!role) {
|
|
4922
6838
|
throw new MarkdownParseError(`Unknown role: ${roleDisplay}`);
|
|
4923
6839
|
}
|
|
@@ -4966,4 +6882,4 @@ export {
|
|
|
4966
6882
|
LABEL_TO_ROLE
|
|
4967
6883
|
};
|
|
4968
6884
|
|
|
4969
|
-
//# debugId=
|
|
6885
|
+
//# debugId=C9F3624DCBE2A76564756E2164756E21
|