@liveblocks/core 3.8.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
 
7
7
  // src/version.ts
8
8
  var PKG_NAME = "@liveblocks/core";
9
- var PKG_VERSION = "3.8.0";
9
+ var PKG_VERSION = "3.9.0";
10
10
  var PKG_FORMAT = "esm";
11
11
 
12
12
  // src/dupe-detection.ts
@@ -703,6 +703,7 @@ var AiChatDB = class {
703
703
  this.signal = new MutableSignal(this);
704
704
  }
705
705
  getEvenIfDeleted(chatId) {
706
+ this.signal.get();
706
707
  return this.#byId.get(chatId);
707
708
  }
708
709
  markDeleted(chatId) {
@@ -2386,6 +2387,14 @@ function createApiClient({
2386
2387
  function getGroup(groupId) {
2387
2388
  return batchedGetGroups.get(groupId);
2388
2389
  }
2390
+ async function getUrlMetadata(_url) {
2391
+ const { metadata } = await httpClient.get(
2392
+ url`/v2/c/urls/metadata`,
2393
+ await authManager.getAuthValue({ requestedScope: "comments:read" }),
2394
+ { url: _url }
2395
+ );
2396
+ return metadata;
2397
+ }
2389
2398
  return {
2390
2399
  // Room threads
2391
2400
  getThreads,
@@ -2443,7 +2452,9 @@ function createApiClient({
2443
2452
  groupsStore,
2444
2453
  getGroup,
2445
2454
  // AI
2446
- executeContextualPrompt
2455
+ executeContextualPrompt,
2456
+ // URL metadata
2457
+ getUrlMetadata
2447
2458
  };
2448
2459
  }
2449
2460
  function getBearerTokenFromAuthValue(authValue) {
@@ -3058,7 +3069,6 @@ var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
3058
3069
  ServerMsgCode2[ServerMsgCode2["ROOM_STATE"] = 104] = "ROOM_STATE";
3059
3070
  ServerMsgCode2[ServerMsgCode2["INITIAL_STORAGE_STATE"] = 200] = "INITIAL_STORAGE_STATE";
3060
3071
  ServerMsgCode2[ServerMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
3061
- ServerMsgCode2[ServerMsgCode2["REJECT_STORAGE_OP"] = 299] = "REJECT_STORAGE_OP";
3062
3072
  ServerMsgCode2[ServerMsgCode2["UPDATE_YDOC"] = 300] = "UPDATE_YDOC";
3063
3073
  ServerMsgCode2[ServerMsgCode2["THREAD_CREATED"] = 400] = "THREAD_CREATED";
3064
3074
  ServerMsgCode2[ServerMsgCode2["THREAD_DELETED"] = 407] = "THREAD_DELETED";
@@ -3069,6 +3079,7 @@ var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
3069
3079
  ServerMsgCode2[ServerMsgCode2["COMMENT_DELETED"] = 404] = "COMMENT_DELETED";
3070
3080
  ServerMsgCode2[ServerMsgCode2["COMMENT_REACTION_ADDED"] = 405] = "COMMENT_REACTION_ADDED";
3071
3081
  ServerMsgCode2[ServerMsgCode2["COMMENT_REACTION_REMOVED"] = 406] = "COMMENT_REACTION_REMOVED";
3082
+ ServerMsgCode2[ServerMsgCode2["REJECT_STORAGE_OP"] = 299] = "REJECT_STORAGE_OP";
3072
3083
  return ServerMsgCode2;
3073
3084
  })(ServerMsgCode || {});
3074
3085
 
@@ -3696,240 +3707,6 @@ var ManagedSocket = class {
3696
3707
  // src/internal.ts
3697
3708
  var kInternal = Symbol();
3698
3709
 
3699
- // src/lib/shallow.ts
3700
- function shallowArray(xs, ys) {
3701
- if (xs.length !== ys.length) {
3702
- return false;
3703
- }
3704
- for (let i = 0; i < xs.length; i++) {
3705
- if (!Object.is(xs[i], ys[i])) {
3706
- return false;
3707
- }
3708
- }
3709
- return true;
3710
- }
3711
- function shallowObj(objA, objB) {
3712
- if (!isPlainObject(objA) || !isPlainObject(objB)) {
3713
- return false;
3714
- }
3715
- const keysA = Object.keys(objA);
3716
- if (keysA.length !== Object.keys(objB).length) {
3717
- return false;
3718
- }
3719
- return keysA.every(
3720
- (key) => Object.prototype.hasOwnProperty.call(objB, key) && Object.is(objA[key], objB[key])
3721
- );
3722
- }
3723
- function shallow(a, b) {
3724
- if (Object.is(a, b)) {
3725
- return true;
3726
- }
3727
- const isArrayA = Array.isArray(a);
3728
- const isArrayB = Array.isArray(b);
3729
- if (isArrayA || isArrayB) {
3730
- if (!isArrayA || !isArrayB) {
3731
- return false;
3732
- }
3733
- return shallowArray(a, b);
3734
- }
3735
- return shallowObj(a, b);
3736
- }
3737
- function shallow2(a, b) {
3738
- if (!isPlainObject(a) || !isPlainObject(b)) {
3739
- return shallow(a, b);
3740
- }
3741
- const keysA = Object.keys(a);
3742
- if (keysA.length !== Object.keys(b).length) {
3743
- return false;
3744
- }
3745
- return keysA.every(
3746
- (key) => Object.prototype.hasOwnProperty.call(b, key) && shallow(a[key], b[key])
3747
- );
3748
- }
3749
-
3750
- // src/lib/TreePool.ts
3751
- var TreePool = class {
3752
- #_items;
3753
- #_childrenOf;
3754
- #_sorted;
3755
- #_primaryKey;
3756
- #_parentKeyFn;
3757
- #_lt;
3758
- constructor(primaryKey, parentKey, lt) {
3759
- this.#_primaryKey = primaryKey;
3760
- this.#_parentKeyFn = parentKey;
3761
- this.#_lt = lt;
3762
- this.#_items = /* @__PURE__ */ new Map();
3763
- this.#_childrenOf = new DefaultMap(() => /* @__PURE__ */ new Set());
3764
- this.#_sorted = SortedList.with(lt);
3765
- }
3766
- get(id) {
3767
- return this.#_items.get(id);
3768
- }
3769
- getOrThrow(id) {
3770
- return this.get(id) ?? raise(`Item with id ${id} not found`);
3771
- }
3772
- get sorted() {
3773
- return this.#_sorted;
3774
- }
3775
- getParentId(id) {
3776
- const item = this.getOrThrow(id);
3777
- return this.#_parentKeyFn(item);
3778
- }
3779
- getParent(id) {
3780
- const parentId = this.getParentId(id);
3781
- return parentId ? this.getOrThrow(parentId) : null;
3782
- }
3783
- getChildren(id) {
3784
- const childIds = this.#_childrenOf.get(id);
3785
- if (!childIds) return [];
3786
- return Array.from(childIds).map(
3787
- (id2) => this.#_items.get(id2)
3788
- // eslint-disable-line no-restricted-syntax
3789
- );
3790
- }
3791
- *walkUp(id, predicate) {
3792
- const includeSelf = true;
3793
- let nodeId = id;
3794
- do {
3795
- const item = this.getOrThrow(nodeId);
3796
- if (includeSelf || nodeId !== id) {
3797
- if (!predicate || predicate(item)) {
3798
- yield item;
3799
- }
3800
- }
3801
- nodeId = this.#_parentKeyFn(item);
3802
- } while (nodeId !== null);
3803
- }
3804
- // XXXX Generalize
3805
- *walkLeft(id, predicate) {
3806
- const self = this.getOrThrow(id);
3807
- const siblings = SortedList.from(this.getSiblings(id), this.#_lt);
3808
- for (const sibling of siblings.iterReversed()) {
3809
- if (this.#_lt(self, sibling)) continue;
3810
- if (!predicate || predicate(sibling)) {
3811
- yield sibling;
3812
- }
3813
- }
3814
- }
3815
- // XXXX Generalize
3816
- *walkRight(id, predicate) {
3817
- const self = this.getOrThrow(id);
3818
- const siblings = SortedList.from(this.getSiblings(id), this.#_lt);
3819
- for (const sibling of siblings) {
3820
- if (this.#_lt(sibling, self)) continue;
3821
- if (!predicate || predicate(sibling)) {
3822
- yield sibling;
3823
- }
3824
- }
3825
- }
3826
- // XXXX Generalize
3827
- *walkDown(id, predicate) {
3828
- const children = SortedList.from(this.getChildren(id), this.#_lt).rawArray;
3829
- for (let i = children.length - 1; i >= 0; i--) {
3830
- const child = children[i];
3831
- yield* this.walkDown(
3832
- this.#_primaryKey(child),
3833
- predicate
3834
- // "depth-first",
3835
- // true
3836
- );
3837
- if (!predicate || predicate(child)) {
3838
- yield child;
3839
- }
3840
- }
3841
- }
3842
- /** Returns all siblings, not including the item itself. */
3843
- getSiblings(id) {
3844
- const self = this.getOrThrow(id);
3845
- const parentId = this.getParentId(id);
3846
- return this.getChildren(parentId).filter((item) => item !== self);
3847
- }
3848
- [Symbol.iterator]() {
3849
- return this.#_sorted[Symbol.iterator]();
3850
- }
3851
- upsert(item) {
3852
- const pk = this.#_primaryKey(item);
3853
- const existing = this.#_items.get(pk);
3854
- if (existing) {
3855
- if (this.#_parentKeyFn(existing) !== this.#_parentKeyFn(item)) {
3856
- throw new Error(
3857
- "Cannot upsert parent ID changes that change the tree structure. Remove the entry first, and recreate it"
3858
- );
3859
- }
3860
- this.#_sorted.remove(existing);
3861
- }
3862
- this.#_items.set(pk, item);
3863
- this.#_sorted.add(item);
3864
- const parentId = this.#_parentKeyFn(item);
3865
- this.#_childrenOf.getOrCreate(parentId).add(pk);
3866
- }
3867
- remove(pk) {
3868
- const item = this.#_items.get(pk);
3869
- if (!item) return false;
3870
- const childIds = this.#_childrenOf.get(pk);
3871
- if (childIds) {
3872
- throw new Error(
3873
- `Cannot remove item '${pk}' while it still has children. Remove children first.`
3874
- );
3875
- }
3876
- const parentId = this.#_parentKeyFn(item);
3877
- const siblings = this.#_childrenOf.get(parentId);
3878
- if (siblings) {
3879
- siblings.delete(pk);
3880
- if (siblings.size === 0) {
3881
- this.#_childrenOf.delete(parentId);
3882
- }
3883
- }
3884
- this.#_sorted.remove(item);
3885
- this.#_childrenOf.delete(pk);
3886
- this.#_items.delete(pk);
3887
- return true;
3888
- }
3889
- clear() {
3890
- if (this.#_items.size === 0) return false;
3891
- this.#_childrenOf.clear();
3892
- this.#_items.clear();
3893
- this.#_sorted.clear();
3894
- return true;
3895
- }
3896
- };
3897
-
3898
- // src/protocol/AuthToken.ts
3899
- var Permission = /* @__PURE__ */ ((Permission2) => {
3900
- Permission2["Read"] = "room:read";
3901
- Permission2["Write"] = "room:write";
3902
- Permission2["PresenceWrite"] = "room:presence:write";
3903
- Permission2["CommentsWrite"] = "comments:write";
3904
- Permission2["CommentsRead"] = "comments:read";
3905
- return Permission2;
3906
- })(Permission || {});
3907
- function canWriteStorage(scopes) {
3908
- return scopes.includes("room:write" /* Write */);
3909
- }
3910
- function canComment(scopes) {
3911
- return scopes.includes("comments:write" /* CommentsWrite */) || scopes.includes("room:write" /* Write */);
3912
- }
3913
- function isValidAuthTokenPayload(data) {
3914
- return isPlainObject(data) && (data.k === "acc" /* ACCESS_TOKEN */ || data.k === "id" /* ID_TOKEN */ || data.k === "sec-legacy" /* SECRET_LEGACY */);
3915
- }
3916
- function parseAuthToken(rawTokenString) {
3917
- const tokenParts = rawTokenString.split(".");
3918
- if (tokenParts.length !== 3) {
3919
- throw new Error("Authentication error: invalid JWT token");
3920
- }
3921
- const payload = tryParseJson(b64decode(tokenParts[1]));
3922
- if (!(payload && isValidAuthTokenPayload(payload))) {
3923
- throw new Error(
3924
- "Authentication error: expected a valid token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
3925
- );
3926
- }
3927
- return {
3928
- raw: rawTokenString,
3929
- parsed: payload
3930
- };
3931
- }
3932
-
3933
3710
  // src/lib/IncrementalJsonParser.ts
3934
3711
  var EMPTY_OBJECT = Object.freeze({});
3935
3712
  var NULL_KEYWORD_CHARS = Array.from(new Set("null"));
@@ -4099,95 +3876,237 @@ var IncrementalJsonParser = class {
4099
3876
  }
4100
3877
  };
4101
3878
 
4102
- // src/types/ai.ts
4103
- function replaceOrAppend(content, newItem, keyFn, now2) {
4104
- const existingIndex = findLastIndex(
4105
- content,
4106
- (item) => item.type === newItem.type && keyFn(item) === keyFn(newItem)
3879
+ // src/lib/shallow.ts
3880
+ function shallowArray(xs, ys) {
3881
+ if (xs.length !== ys.length) {
3882
+ return false;
3883
+ }
3884
+ for (let i = 0; i < xs.length; i++) {
3885
+ if (!Object.is(xs[i], ys[i])) {
3886
+ return false;
3887
+ }
3888
+ }
3889
+ return true;
3890
+ }
3891
+ function shallowObj(objA, objB) {
3892
+ if (!isPlainObject(objA) || !isPlainObject(objB)) {
3893
+ return false;
3894
+ }
3895
+ const keysA = Object.keys(objA);
3896
+ if (keysA.length !== Object.keys(objB).length) {
3897
+ return false;
3898
+ }
3899
+ return keysA.every(
3900
+ (key) => Object.prototype.hasOwnProperty.call(objB, key) && Object.is(objA[key], objB[key])
4107
3901
  );
4108
- if (existingIndex > -1) {
4109
- content[existingIndex] = newItem;
4110
- } else {
4111
- closePart(content[content.length - 1], now2);
4112
- content.push(newItem);
3902
+ }
3903
+ function shallow(a, b) {
3904
+ if (Object.is(a, b)) {
3905
+ return true;
3906
+ }
3907
+ const isArrayA = Array.isArray(a);
3908
+ const isArrayB = Array.isArray(b);
3909
+ if (isArrayA || isArrayB) {
3910
+ if (!isArrayA || !isArrayB) {
3911
+ return false;
3912
+ }
3913
+ return shallowArray(a, b);
4113
3914
  }
3915
+ return shallowObj(a, b);
4114
3916
  }
4115
- function closePart(prevPart, endedAt) {
4116
- if (prevPart?.type === "reasoning") {
4117
- prevPart.endedAt ??= endedAt;
3917
+ function shallow2(a, b) {
3918
+ if (!isPlainObject(a) || !isPlainObject(b)) {
3919
+ return shallow(a, b);
3920
+ }
3921
+ const keysA = Object.keys(a);
3922
+ if (keysA.length !== Object.keys(b).length) {
3923
+ return false;
4118
3924
  }
3925
+ return keysA.every(
3926
+ (key) => Object.prototype.hasOwnProperty.call(b, key) && shallow(a[key], b[key])
3927
+ );
4119
3928
  }
4120
- function patchContentWithDelta(content, delta) {
4121
- if (delta === null)
4122
- return;
4123
- const now2 = (/* @__PURE__ */ new Date()).toISOString();
4124
- const lastPart = content[content.length - 1];
4125
- switch (delta.type) {
4126
- case "text-delta":
4127
- if (lastPart?.type === "text") {
4128
- lastPart.text += delta.textDelta;
4129
- } else {
4130
- closePart(lastPart, now2);
4131
- content.push({ type: "text", text: delta.textDelta });
3929
+
3930
+ // src/lib/TreePool.ts
3931
+ var TreePool = class {
3932
+ #_items;
3933
+ #_childrenOf;
3934
+ #_sorted;
3935
+ #_primaryKey;
3936
+ #_parentKeyFn;
3937
+ #_lt;
3938
+ constructor(primaryKey, parentKey, lt) {
3939
+ this.#_primaryKey = primaryKey;
3940
+ this.#_parentKeyFn = parentKey;
3941
+ this.#_lt = lt;
3942
+ this.#_items = /* @__PURE__ */ new Map();
3943
+ this.#_childrenOf = new DefaultMap(() => /* @__PURE__ */ new Set());
3944
+ this.#_sorted = SortedList.with(lt);
3945
+ }
3946
+ get(id) {
3947
+ return this.#_items.get(id);
3948
+ }
3949
+ getOrThrow(id) {
3950
+ return this.get(id) ?? raise(`Item with id ${id} not found`);
3951
+ }
3952
+ get sorted() {
3953
+ return this.#_sorted;
3954
+ }
3955
+ getParentId(id) {
3956
+ const item = this.getOrThrow(id);
3957
+ return this.#_parentKeyFn(item);
3958
+ }
3959
+ getParent(id) {
3960
+ const parentId = this.getParentId(id);
3961
+ return parentId ? this.getOrThrow(parentId) : null;
3962
+ }
3963
+ getChildren(id) {
3964
+ const childIds = this.#_childrenOf.get(id);
3965
+ if (!childIds) return [];
3966
+ return Array.from(childIds).map(
3967
+ (id2) => this.#_items.get(id2)
3968
+ // eslint-disable-line no-restricted-syntax
3969
+ );
3970
+ }
3971
+ *walkUp(id, predicate) {
3972
+ const includeSelf = true;
3973
+ let nodeId = id;
3974
+ do {
3975
+ const item = this.getOrThrow(nodeId);
3976
+ if (includeSelf || nodeId !== id) {
3977
+ if (!predicate || predicate(item)) {
3978
+ yield item;
3979
+ }
3980
+ }
3981
+ nodeId = this.#_parentKeyFn(item);
3982
+ } while (nodeId !== null);
3983
+ }
3984
+ // XXXX Generalize
3985
+ *walkLeft(id, predicate) {
3986
+ const self = this.getOrThrow(id);
3987
+ const siblings = SortedList.from(this.getSiblings(id), this.#_lt);
3988
+ for (const sibling of siblings.iterReversed()) {
3989
+ if (this.#_lt(self, sibling)) continue;
3990
+ if (!predicate || predicate(sibling)) {
3991
+ yield sibling;
3992
+ }
3993
+ }
3994
+ }
3995
+ // XXXX Generalize
3996
+ *walkRight(id, predicate) {
3997
+ const self = this.getOrThrow(id);
3998
+ const siblings = SortedList.from(this.getSiblings(id), this.#_lt);
3999
+ for (const sibling of siblings) {
4000
+ if (this.#_lt(sibling, self)) continue;
4001
+ if (!predicate || predicate(sibling)) {
4002
+ yield sibling;
4003
+ }
4004
+ }
4005
+ }
4006
+ // XXXX Generalize
4007
+ *walkDown(id, predicate) {
4008
+ const children = SortedList.from(this.getChildren(id), this.#_lt).rawArray;
4009
+ for (let i = children.length - 1; i >= 0; i--) {
4010
+ const child = children[i];
4011
+ yield* this.walkDown(
4012
+ this.#_primaryKey(child),
4013
+ predicate
4014
+ // "depth-first",
4015
+ // true
4016
+ );
4017
+ if (!predicate || predicate(child)) {
4018
+ yield child;
4132
4019
  }
4133
- break;
4134
- case "reasoning-delta":
4135
- if (lastPart?.type === "reasoning") {
4136
- lastPart.text += delta.textDelta;
4137
- } else {
4138
- closePart(lastPart, now2);
4139
- content.push({
4140
- type: "reasoning",
4141
- text: delta.textDelta,
4142
- startedAt: now2
4143
- });
4020
+ }
4021
+ }
4022
+ /** Returns all siblings, not including the item itself. */
4023
+ getSiblings(id) {
4024
+ const self = this.getOrThrow(id);
4025
+ const parentId = this.getParentId(id);
4026
+ return this.getChildren(parentId).filter((item) => item !== self);
4027
+ }
4028
+ [Symbol.iterator]() {
4029
+ return this.#_sorted[Symbol.iterator]();
4030
+ }
4031
+ upsert(item) {
4032
+ const pk = this.#_primaryKey(item);
4033
+ const existing = this.#_items.get(pk);
4034
+ if (existing) {
4035
+ if (this.#_parentKeyFn(existing) !== this.#_parentKeyFn(item)) {
4036
+ throw new Error(
4037
+ "Cannot upsert parent ID changes that change the tree structure. Remove the entry first, and recreate it"
4038
+ );
4144
4039
  }
4145
- break;
4146
- case "tool-stream": {
4147
- const toolInvocation = createReceivingToolInvocation(
4148
- delta.invocationId,
4149
- delta.name
4040
+ this.#_sorted.remove(existing);
4041
+ }
4042
+ this.#_items.set(pk, item);
4043
+ this.#_sorted.add(item);
4044
+ const parentId = this.#_parentKeyFn(item);
4045
+ this.#_childrenOf.getOrCreate(parentId).add(pk);
4046
+ }
4047
+ remove(pk) {
4048
+ const item = this.#_items.get(pk);
4049
+ if (!item) return false;
4050
+ const childIds = this.#_childrenOf.get(pk);
4051
+ if (childIds) {
4052
+ throw new Error(
4053
+ `Cannot remove item '${pk}' while it still has children. Remove children first.`
4150
4054
  );
4151
- content.push(toolInvocation);
4152
- break;
4153
4055
  }
4154
- case "tool-delta": {
4155
- if (lastPart?.type === "tool-invocation" && lastPart.stage === "receiving") {
4156
- lastPart.__appendDelta?.(delta.delta);
4056
+ const parentId = this.#_parentKeyFn(item);
4057
+ const siblings = this.#_childrenOf.get(parentId);
4058
+ if (siblings) {
4059
+ siblings.delete(pk);
4060
+ if (siblings.size === 0) {
4061
+ this.#_childrenOf.delete(parentId);
4157
4062
  }
4158
- break;
4159
4063
  }
4160
- case "tool-invocation":
4161
- replaceOrAppend(content, delta, (x) => x.invocationId, now2);
4162
- break;
4163
- case "retrieval":
4164
- replaceOrAppend(content, delta, (x) => x.id, now2);
4165
- break;
4166
- default:
4167
- return assertNever(delta, "Unhandled case");
4064
+ this.#_sorted.remove(item);
4065
+ this.#_childrenOf.delete(pk);
4066
+ this.#_items.delete(pk);
4067
+ return true;
4068
+ }
4069
+ clear() {
4070
+ if (this.#_items.size === 0) return false;
4071
+ this.#_childrenOf.clear();
4072
+ this.#_items.clear();
4073
+ this.#_sorted.clear();
4074
+ return true;
4168
4075
  }
4076
+ };
4077
+
4078
+ // src/protocol/AuthToken.ts
4079
+ var Permission = /* @__PURE__ */ ((Permission2) => {
4080
+ Permission2["Read"] = "room:read";
4081
+ Permission2["Write"] = "room:write";
4082
+ Permission2["PresenceWrite"] = "room:presence:write";
4083
+ Permission2["CommentsWrite"] = "comments:write";
4084
+ Permission2["CommentsRead"] = "comments:read";
4085
+ return Permission2;
4086
+ })(Permission || {});
4087
+ function canWriteStorage(scopes) {
4088
+ return scopes.includes("room:write" /* Write */);
4169
4089
  }
4170
- function createReceivingToolInvocation(invocationId, name, partialArgsText = "") {
4171
- const parser = new IncrementalJsonParser(partialArgsText);
4090
+ function canComment(scopes) {
4091
+ return scopes.includes("comments:write" /* CommentsWrite */) || scopes.includes("room:write" /* Write */);
4092
+ }
4093
+ function isValidAuthTokenPayload(data) {
4094
+ return isPlainObject(data) && (data.k === "acc" /* ACCESS_TOKEN */ || data.k === "id" /* ID_TOKEN */ || data.k === "sec-legacy" /* SECRET_LEGACY */);
4095
+ }
4096
+ function parseAuthToken(rawTokenString) {
4097
+ const tokenParts = rawTokenString.split(".");
4098
+ if (tokenParts.length !== 3) {
4099
+ throw new Error("Authentication error: invalid JWT token");
4100
+ }
4101
+ const payload = tryParseJson(b64decode(tokenParts[1]));
4102
+ if (!(payload && isValidAuthTokenPayload(payload))) {
4103
+ throw new Error(
4104
+ "Authentication error: expected a valid token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
4105
+ );
4106
+ }
4172
4107
  return {
4173
- type: "tool-invocation",
4174
- stage: "receiving",
4175
- invocationId,
4176
- name,
4177
- // --- Alternative implementation for FRONTEND only ------------------------
4178
- get partialArgsText() {
4179
- return parser.source;
4180
- },
4181
- // prettier-ignore
4182
- get partialArgs() {
4183
- return parser.json;
4184
- },
4185
- // prettier-ignore
4186
- __appendDelta(delta) {
4187
- parser.append(delta);
4188
- }
4189
- // prettier-ignore
4190
- // ------------------------------------------------------------------------
4108
+ raw: rawTokenString,
4109
+ parsed: payload
4191
4110
  };
4192
4111
  }
4193
4112
 
@@ -4255,6 +4174,23 @@ var KnowledgeStack = class {
4255
4174
  this.invalidate();
4256
4175
  }
4257
4176
  };
4177
+ function createStore_forKnowledge() {
4178
+ const knowledgeByChatId = new DefaultMap(
4179
+ (_chatId) => new KnowledgeStack()
4180
+ );
4181
+ function getKnowledgeStack(chatId) {
4182
+ return knowledgeByChatId.getOrCreate(chatId ?? kWILDCARD);
4183
+ }
4184
+ function getKnowledgeForChat(chatId) {
4185
+ const globalKnowledge = knowledgeByChatId.getOrCreate(kWILDCARD).get();
4186
+ const scopedKnowledge = knowledgeByChatId.get(chatId)?.get() ?? [];
4187
+ return [...globalKnowledge, ...scopedKnowledge];
4188
+ }
4189
+ return {
4190
+ getKnowledgeStack,
4191
+ getKnowledgeForChat
4192
+ };
4193
+ }
4258
4194
  function now() {
4259
4195
  return (/* @__PURE__ */ new Date()).toISOString();
4260
4196
  }
@@ -4658,6 +4594,7 @@ function createAi(config) {
4658
4594
  );
4659
4595
  const chatsStore = createStore_forUserAiChats();
4660
4596
  const toolsStore = createStore_forTools();
4597
+ const knowledgeStore = createStore_forKnowledge();
4661
4598
  const messagesStore = createStore_forChatMessages(toolsStore, setToolResult);
4662
4599
  const context = {
4663
4600
  staticSessionInfoSig: new Signal(null),
@@ -4666,8 +4603,9 @@ function createAi(config) {
4666
4603
  chatsStore,
4667
4604
  messagesStore,
4668
4605
  toolsStore,
4669
- knowledge: new KnowledgeStack()
4606
+ knowledgeStore
4670
4607
  };
4608
+ const status\u03A3 = new Signal("initial");
4671
4609
  const DELTA_THROTTLE = 25;
4672
4610
  let pendingDeltas = [];
4673
4611
  let deltaBatchTimer = null;
@@ -4691,7 +4629,7 @@ function createAi(config) {
4691
4629
  }
4692
4630
  }
4693
4631
  let lastTokenKey;
4694
- function onStatusDidChange(_newStatus) {
4632
+ function onStatusDidChange(newStatus) {
4695
4633
  const authValue = managedSocket.authValue;
4696
4634
  if (authValue !== null) {
4697
4635
  const tokenKey = getBearerTokenFromAuthValue(authValue);
@@ -4711,6 +4649,7 @@ function createAi(config) {
4711
4649
  }
4712
4650
  }
4713
4651
  }
4652
+ status\u03A3.set(newStatus);
4714
4653
  }
4715
4654
  let _connectionLossTimerId;
4716
4655
  let _hasLostConnection = false;
@@ -4895,17 +4834,8 @@ function createAi(config) {
4895
4834
  chatId
4896
4835
  });
4897
4836
  }
4898
- function registerKnowledgeLayer(uniqueLayerId) {
4899
- return context.knowledge.registerLayer(uniqueLayerId);
4900
- }
4901
- function deregisterKnowledgeLayer(layerKey) {
4902
- context.knowledge.deregisterLayer(layerKey);
4903
- }
4904
- function updateKnowledge(layerKey, data, key = nanoid()) {
4905
- context.knowledge.updateKnowledge(layerKey, key, data);
4906
- }
4907
4837
  async function setToolResult(chatId, messageId, invocationId, result, options) {
4908
- const knowledge = context.knowledge.get();
4838
+ const knowledge = context.knowledgeStore.getKnowledgeForChat(chatId);
4909
4839
  const tools = context.toolsStore.getToolDescriptions(chatId);
4910
4840
  const resp = await sendClientMsgWithResponse({
4911
4841
  cmd: "set-tool-result",
@@ -4952,9 +4882,9 @@ function createAi(config) {
4952
4882
  deleteMessage: (chatId, messageId) => sendClientMsgWithResponse({ cmd: "delete-message", chatId, messageId }),
4953
4883
  clearChat: (chatId) => sendClientMsgWithResponse({ cmd: "clear-chat", chatId }),
4954
4884
  askUserMessageInChat: async (chatId, userMessage, targetMessageId, options) => {
4955
- const globalKnowledge = context.knowledge.get();
4885
+ const knowledge = context.knowledgeStore.getKnowledgeForChat(chatId);
4956
4886
  const requestKnowledge = options?.knowledge || [];
4957
- const combinedKnowledge = [...globalKnowledge, ...requestKnowledge];
4887
+ const combinedKnowledge = [...knowledge, ...requestKnowledge];
4958
4888
  const tools = context.toolsStore.getToolDescriptions(chatId);
4959
4889
  messagesStore.markMine(targetMessageId);
4960
4890
  const resp = await sendClientMsgWithResponse({
@@ -4978,14 +4908,24 @@ function createAi(config) {
4978
4908
  getStatus: () => managedSocket.getStatus(),
4979
4909
  signals: {
4980
4910
  getChatMessagesForBranch\u03A3: context.messagesStore.getChatMessagesForBranch\u03A3,
4981
- getTool\u03A3: context.toolsStore.getTool\u03A3
4911
+ getTool\u03A3: context.toolsStore.getTool\u03A3,
4912
+ status\u03A3
4982
4913
  },
4983
4914
  getChatById: context.chatsStore.getChatById,
4984
4915
  queryChats: context.chatsStore.findMany,
4985
4916
  getLastUsedCopilotId: context.messagesStore.getLastUsedCopilotId,
4986
- registerKnowledgeLayer,
4987
- deregisterKnowledgeLayer,
4988
- updateKnowledge,
4917
+ registerKnowledgeLayer: (uniqueLayerId, chatId) => {
4918
+ const stack = context.knowledgeStore.getKnowledgeStack(chatId);
4919
+ const layerKey = stack.registerLayer(uniqueLayerId);
4920
+ const deregister = () => stack.deregisterLayer(layerKey);
4921
+ return {
4922
+ layerKey,
4923
+ deregister
4924
+ };
4925
+ },
4926
+ updateKnowledge: (layerKey, data, key, chatId) => {
4927
+ context.knowledgeStore.getKnowledgeStack(chatId).updateKnowledge(layerKey, key ?? nanoid(), data);
4928
+ },
4989
4929
  registerTool: context.toolsStore.registerTool
4990
4930
  },
4991
4931
  kInternal,
@@ -5002,7 +4942,7 @@ function makeCreateSocketDelegateForAi(baseUrl, WebSocketPolyfill) {
5002
4942
  }
5003
4943
  const url2 = new URL(baseUrl);
5004
4944
  url2.protocol = url2.protocol === "http:" ? "ws" : "wss";
5005
- url2.pathname = "/ai/v6";
4945
+ url2.pathname = "/ai/v7";
5006
4946
  if (authValue.type === "secret") {
5007
4947
  url2.searchParams.set("tok", authValue.token.raw);
5008
4948
  } else if (authValue.type === "public") {
@@ -5014,6 +4954,112 @@ function makeCreateSocketDelegateForAi(baseUrl, WebSocketPolyfill) {
5014
4954
  return new ws(url2.toString());
5015
4955
  };
5016
4956
  }
4957
+ function replaceOrAppend(content, newItem, keyFn, now2) {
4958
+ const existingIndex = findLastIndex(
4959
+ content,
4960
+ (item) => item.type === newItem.type && keyFn(item) === keyFn(newItem)
4961
+ );
4962
+ if (existingIndex > -1) {
4963
+ content[existingIndex] = newItem;
4964
+ } else {
4965
+ closePart(content[content.length - 1], now2);
4966
+ content.push(newItem);
4967
+ }
4968
+ }
4969
+ function closePart(prevPart, endedAt) {
4970
+ if (prevPart?.type === "reasoning") {
4971
+ prevPart.endedAt ??= endedAt;
4972
+ }
4973
+ }
4974
+ function patchContentWithDelta(content, delta) {
4975
+ if (delta === null)
4976
+ return;
4977
+ const parts = content.filter(
4978
+ (part) => part.type !== "sources"
4979
+ );
4980
+ const sources = content.filter((part) => part.type === "sources").flatMap((part) => part.sources);
4981
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
4982
+ const lastPart = parts[parts.length - 1];
4983
+ switch (delta.type) {
4984
+ case "text-delta":
4985
+ if (lastPart?.type === "text") {
4986
+ lastPart.text += delta.textDelta;
4987
+ } else {
4988
+ closePart(lastPart, now2);
4989
+ parts.push({ type: "text", text: delta.textDelta });
4990
+ }
4991
+ break;
4992
+ case "reasoning-delta":
4993
+ if (lastPart?.type === "reasoning") {
4994
+ lastPart.text += delta.textDelta;
4995
+ } else {
4996
+ closePart(lastPart, now2);
4997
+ parts.push({
4998
+ type: "reasoning",
4999
+ text: delta.textDelta,
5000
+ startedAt: now2
5001
+ });
5002
+ }
5003
+ break;
5004
+ case "tool-stream": {
5005
+ const toolInvocation = createReceivingToolInvocation(
5006
+ delta.invocationId,
5007
+ delta.name
5008
+ );
5009
+ parts.push(toolInvocation);
5010
+ break;
5011
+ }
5012
+ case "tool-delta": {
5013
+ if (lastPart?.type === "tool-invocation" && lastPart.stage === "receiving") {
5014
+ lastPart.__appendDelta?.(delta.delta);
5015
+ }
5016
+ break;
5017
+ }
5018
+ case "tool-invocation":
5019
+ replaceOrAppend(parts, delta, (x) => x.invocationId, now2);
5020
+ break;
5021
+ case "retrieval":
5022
+ replaceOrAppend(parts, delta, (x) => x.id, now2);
5023
+ break;
5024
+ case "source": {
5025
+ sources.push(delta);
5026
+ break;
5027
+ }
5028
+ default:
5029
+ return assertNever(delta, "Unhandled case");
5030
+ }
5031
+ if (sources.length > 0) {
5032
+ parts.push({
5033
+ type: "sources",
5034
+ sources
5035
+ });
5036
+ }
5037
+ content.length = 0;
5038
+ content.push(...parts);
5039
+ }
5040
+ function createReceivingToolInvocation(invocationId, name, partialArgsText = "") {
5041
+ const parser = new IncrementalJsonParser(partialArgsText);
5042
+ return {
5043
+ type: "tool-invocation",
5044
+ stage: "receiving",
5045
+ invocationId,
5046
+ name,
5047
+ // --- Alternative implementation for FRONTEND only ------------------------
5048
+ get partialArgsText() {
5049
+ return parser.source;
5050
+ },
5051
+ // prettier-ignore
5052
+ get partialArgs() {
5053
+ return parser.json;
5054
+ },
5055
+ // prettier-ignore
5056
+ __appendDelta(delta) {
5057
+ parser.append(delta);
5058
+ }
5059
+ // prettier-ignore
5060
+ // ------------------------------------------------------------------------
5061
+ };
5062
+ }
5017
5063
 
5018
5064
  // src/auth-manager.ts
5019
5065
  function createAuthManager(authOptions, onAuthenticate) {
@@ -8142,16 +8188,6 @@ function findNonSerializableValue(value, path = "") {
8142
8188
  return false;
8143
8189
  }
8144
8190
 
8145
- // src/lib/debug.ts
8146
- function captureStackTrace(msg, traceRoot) {
8147
- const errorLike = { name: msg };
8148
- if (typeof Error.captureStackTrace !== "function") {
8149
- return void 0;
8150
- }
8151
- Error.captureStackTrace(errorLike, traceRoot);
8152
- return errorLike.stack;
8153
- }
8154
-
8155
8191
  // src/lib/Deque.ts
8156
8192
  var Deque = class {
8157
8193
  #data;
@@ -8562,9 +8598,7 @@ function createRoom(options, config) {
8562
8598
  redoStack: [],
8563
8599
  pausedHistory: null,
8564
8600
  activeBatch: null,
8565
- unacknowledgedOps: /* @__PURE__ */ new Map(),
8566
- // Debug
8567
- opStackTraces: process.env.NODE_ENV !== "production" ? /* @__PURE__ */ new Map() : void 0
8601
+ unacknowledgedOps: /* @__PURE__ */ new Map()
8568
8602
  };
8569
8603
  let lastTokenKey;
8570
8604
  function onStatusDidChange(newStatus) {
@@ -8648,16 +8682,6 @@ function createRoom(options, config) {
8648
8682
  }
8649
8683
  });
8650
8684
  function onDispatch(ops, reverse, storageUpdates) {
8651
- if (process.env.NODE_ENV !== "production") {
8652
- const stackTrace = captureStackTrace("Storage mutation", onDispatch);
8653
- if (stackTrace) {
8654
- for (const op of ops) {
8655
- if (op.opId) {
8656
- nn(context.opStackTraces).set(op.opId, stackTrace);
8657
- }
8658
- }
8659
- }
8660
- }
8661
8685
  if (context.activeBatch) {
8662
8686
  for (const op of ops) {
8663
8687
  context.activeBatch.ops.push(op);
@@ -8974,9 +8998,6 @@ function createRoom(options, config) {
8974
8998
  source = 0 /* UNDOREDO_RECONNECT */;
8975
8999
  } else {
8976
9000
  const opId = nn(op.opId);
8977
- if (process.env.NODE_ENV !== "production") {
8978
- nn(context.opStackTraces).delete(opId);
8979
- }
8980
9001
  const deleted = context.unacknowledgedOps.delete(opId);
8981
9002
  source = deleted ? 2 /* ACK */ : 1 /* REMOTE */;
8982
9003
  }
@@ -9262,38 +9283,6 @@ function createRoom(options, config) {
9262
9283
  }
9263
9284
  break;
9264
9285
  }
9265
- // Receiving a RejectedOps message in the client means that the server is no
9266
- // longer in sync with the client. Trying to synchronize the client again by
9267
- // rolling back particular Ops may be hard/impossible. It's fine to not try and
9268
- // accept the out-of-sync reality and throw an error. We look at this kind of bug
9269
- // as a developer-owned bug. In production, these errors are not expected to happen.
9270
- case 299 /* REJECT_STORAGE_OP */: {
9271
- errorWithTitle(
9272
- "Storage mutation rejection error",
9273
- message.reason
9274
- );
9275
- if (process.env.NODE_ENV !== "production") {
9276
- const traces = /* @__PURE__ */ new Set();
9277
- for (const opId of message.opIds) {
9278
- const trace = context.opStackTraces?.get(opId);
9279
- if (trace) {
9280
- traces.add(trace);
9281
- }
9282
- }
9283
- if (traces.size > 0) {
9284
- warnWithTitle(
9285
- "The following function calls caused the rejected storage mutations:",
9286
- `
9287
-
9288
- ${Array.from(traces).join("\n\n")}`
9289
- );
9290
- }
9291
- throw new Error(
9292
- `Storage mutations rejected by server: ${message.reason}`
9293
- );
9294
- }
9295
- break;
9296
- }
9297
9286
  case 400 /* THREAD_CREATED */:
9298
9287
  case 407 /* THREAD_DELETED */:
9299
9288
  case 401 /* THREAD_METADATA_UPDATED */:
@@ -9306,6 +9295,8 @@ ${Array.from(traces).join("\n\n")}`
9306
9295
  eventHub.comments.notify(message);
9307
9296
  break;
9308
9297
  }
9298
+ default:
9299
+ break;
9309
9300
  }
9310
9301
  }
9311
9302
  notify(updates);