jazz-tools 0.18.24 → 0.18.26
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/.svelte-kit/__package__/Provider.svelte +2 -0
- package/.svelte-kit/__package__/Provider.svelte.d.ts.map +1 -1
- package/.turbo/turbo-build.log +49 -49
- package/CHANGELOG.md +24 -0
- package/dist/browser/index.js +9 -9
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-BOMSRY5H.js → chunk-M2HGBOXS.js} +2 -2
- package/dist/chunk-M2HGBOXS.js.map +1 -0
- package/dist/{chunk-W7JT3QUN.js → chunk-ZIAN4UY5.js} +406 -40
- package/dist/chunk-ZIAN4UY5.js.map +1 -0
- package/dist/index.js +2 -2
- package/dist/inspector/{custom-element-XDJT5T57.js → custom-element-A7UAELEG.js} +3 -1
- package/dist/inspector/{custom-element-XDJT5T57.js.map → custom-element-A7UAELEG.js.map} +1 -1
- package/dist/inspector/index.js +2 -0
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/viewer/use-open-inspector.d.ts.map +1 -1
- package/dist/inspector/viewer/use-page-path.d.ts.map +1 -1
- package/dist/react/index.js +4 -2
- package/dist/react/index.js.map +1 -1
- package/dist/react/provider.d.ts +2 -1
- package/dist/react/provider.d.ts.map +1 -1
- package/dist/react/ssr.js +1 -1
- package/dist/react/ssr.js.map +1 -1
- package/dist/react-native-core/index.js +12 -11
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/react-native-core/provider.d.ts +2 -1
- package/dist/react-native-core/provider.d.ts.map +1 -1
- package/dist/svelte/Provider.svelte +2 -0
- package/dist/svelte/Provider.svelte.d.ts.map +1 -1
- package/dist/testing.js +4 -4
- package/dist/testing.js.map +1 -1
- package/dist/tools/auth/AuthSecretStorage.d.ts +3 -1
- package/dist/tools/auth/AuthSecretStorage.d.ts.map +1 -1
- package/dist/tools/coValues/account.d.ts +3 -3
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/coVector.d.ts +127 -0
- package/dist/tools/coValues/coVector.d.ts.map +1 -0
- package/dist/tools/coValues/group.d.ts +20 -1
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/implementation/ContextManager.d.ts +1 -0
- package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
- package/dist/tools/implementation/createContext.d.ts +7 -7
- package/dist/tools/implementation/createContext.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/coExport.d.ts +2 -1
- package/dist/tools/implementation/zodSchema/coExport.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.d.ts +47 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts +5 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +2 -2
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +2 -2
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts +2 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodSchema.d.ts +3 -2
- package/dist/tools/implementation/zodSchema/zodSchema.d.ts.map +1 -1
- package/dist/tools/internal.d.ts +2 -0
- package/dist/tools/internal.d.ts.map +1 -1
- package/dist/tools/ssr.js +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/coVector.test-d.d.ts +2 -0
- package/dist/tools/tests/coVector.test-d.d.ts.map +1 -0
- package/dist/tools/tests/coVector.test.d.ts +2 -0
- package/dist/tools/tests/coVector.test.d.ts.map +1 -0
- package/dist/worker/index.js +3 -3
- package/dist/worker/index.js.map +1 -1
- package/package.json +4 -4
- package/src/better-auth/database-adapter/tests/sync-utils.ts +1 -1
- package/src/browser/createBrowserContext.ts +9 -9
- package/src/browser/tests/utils.ts +2 -2
- package/src/inspector/viewer/use-open-inspector.ts +1 -0
- package/src/inspector/viewer/use-page-path.ts +1 -0
- package/src/react/provider.tsx +3 -0
- package/src/react-native-core/platform.ts +9 -9
- package/src/react-native-core/provider.tsx +3 -1
- package/src/svelte/Provider.svelte +2 -0
- package/src/tools/auth/AuthSecretStorage.ts +16 -9
- package/src/tools/coValues/account.ts +5 -5
- package/src/tools/coValues/coVector.ts +432 -0
- package/src/tools/coValues/group.ts +33 -0
- package/src/tools/coValues/interfaces.ts +4 -1
- package/src/tools/implementation/ContextManager.ts +7 -3
- package/src/tools/implementation/createContext.ts +12 -12
- package/src/tools/implementation/zodSchema/coExport.ts +2 -0
- package/src/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.ts +13 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoVectorSchema.ts +105 -0
- package/src/tools/implementation/zodSchema/schemaTypes/GroupSchema.ts +7 -1
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +9 -5
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +15 -9
- package/src/tools/implementation/zodSchema/zodCo.ts +15 -0
- package/src/tools/implementation/zodSchema/zodSchema.ts +15 -6
- package/src/tools/internal.ts +2 -0
- package/src/tools/ssr/ssr.ts +1 -1
- package/src/tools/testing.ts +3 -3
- package/src/tools/tests/AuthSecretStorage.test.ts +59 -1
- package/src/tools/tests/ContextManager.test.ts +11 -1
- package/src/tools/tests/account.test.ts +16 -0
- package/src/tools/tests/coPlainText.test.ts +2 -2
- package/src/tools/tests/coVector.test-d.ts +40 -0
- package/src/tools/tests/coVector.test.ts +891 -0
- package/src/tools/tests/createContext.test.ts +19 -19
- package/src/tools/tests/deepLoading.test.ts +2 -2
- package/src/tools/tests/group.test.ts +59 -0
- package/src/tools/tests/inbox.test.ts +2 -2
- package/src/tools/tests/utils.ts +3 -3
- package/src/worker/index.ts +3 -3
- package/dist/chunk-BOMSRY5H.js.map +0 -1
- package/dist/chunk-W7JT3QUN.js.map +0 -1
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import type { RawBinaryCoStream } from "cojson";
|
|
2
|
+
import { cojsonInternals } from "cojson";
|
|
3
|
+
import {
|
|
4
|
+
AnonymousJazzAgent,
|
|
5
|
+
CoValue,
|
|
6
|
+
CoValueClass,
|
|
7
|
+
getCoValueOwner,
|
|
8
|
+
Group,
|
|
9
|
+
ID,
|
|
10
|
+
Resolved,
|
|
11
|
+
SubscribeListenerOptions,
|
|
12
|
+
SubscribeRestArgs,
|
|
13
|
+
TypeSym,
|
|
14
|
+
} from "../internal.js";
|
|
15
|
+
import {
|
|
16
|
+
Account,
|
|
17
|
+
CoValueJazzApi,
|
|
18
|
+
inspect,
|
|
19
|
+
loadCoValueWithoutMe,
|
|
20
|
+
parseCoValueCreateOptions,
|
|
21
|
+
parseSubscribeRestArgs,
|
|
22
|
+
subscribeToCoValueWithoutMe,
|
|
23
|
+
subscribeToExistingCoValue,
|
|
24
|
+
} from "../internal.js";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* CoVectors are collaborative storages of vectors (floating point arrays).
|
|
28
|
+
*
|
|
29
|
+
* @category CoValues
|
|
30
|
+
*/
|
|
31
|
+
export class CoVector
|
|
32
|
+
extends Float32Array
|
|
33
|
+
implements Readonly<Float32Array>, CoValue
|
|
34
|
+
{
|
|
35
|
+
declare $jazz: CoVectorJazzApi<this>;
|
|
36
|
+
|
|
37
|
+
/** @category Type Helpers */
|
|
38
|
+
declare [TypeSym]: "BinaryCoStream";
|
|
39
|
+
|
|
40
|
+
static get [Symbol.species]() {
|
|
41
|
+
return Float32Array;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected static requiredDimensionsCount: number | undefined = undefined;
|
|
45
|
+
private declare _isVectorLoaded: boolean;
|
|
46
|
+
private declare _requiredDimensionsCount: number;
|
|
47
|
+
|
|
48
|
+
constructor(
|
|
49
|
+
options:
|
|
50
|
+
| {
|
|
51
|
+
owner: Account | Group;
|
|
52
|
+
}
|
|
53
|
+
| {
|
|
54
|
+
fromRaw: RawBinaryCoStream;
|
|
55
|
+
},
|
|
56
|
+
) {
|
|
57
|
+
const dimensionsCount = (new.target as typeof CoVector)
|
|
58
|
+
.requiredDimensionsCount;
|
|
59
|
+
|
|
60
|
+
if (dimensionsCount === undefined) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Instantiating CoVector without a dimensions count is not allowed. Use co.vector(...).create() instead.",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Initialize empty Float32Array buffer with the expected vector length
|
|
67
|
+
// to be filled with the vector data later
|
|
68
|
+
super(dimensionsCount);
|
|
69
|
+
|
|
70
|
+
const isFromRaw = "fromRaw" in options;
|
|
71
|
+
|
|
72
|
+
const raw: RawBinaryCoStream = isFromRaw
|
|
73
|
+
? options.fromRaw
|
|
74
|
+
: options.owner.$jazz.raw.createBinaryStream();
|
|
75
|
+
|
|
76
|
+
Object.defineProperties(this, {
|
|
77
|
+
[TypeSym]: { value: "BinaryCoStream", enumerable: false },
|
|
78
|
+
$jazz: {
|
|
79
|
+
value: new CoVectorJazzApi(this, raw),
|
|
80
|
+
enumerable: false,
|
|
81
|
+
},
|
|
82
|
+
_isVectorLoaded: { value: false, enumerable: false, writable: true },
|
|
83
|
+
_requiredDimensionsCount: {
|
|
84
|
+
value: dimensionsCount,
|
|
85
|
+
enumerable: false,
|
|
86
|
+
writable: false,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (isFromRaw) {
|
|
91
|
+
this.loadVectorData();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** @category Internals */
|
|
96
|
+
static fromRaw<V extends CoVector>(
|
|
97
|
+
this: CoValueClass<V> & typeof CoVector,
|
|
98
|
+
raw: RawBinaryCoStream,
|
|
99
|
+
) {
|
|
100
|
+
return new this({ fromRaw: raw });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create a new `CoVector` instance with the given vector.
|
|
105
|
+
*
|
|
106
|
+
* @category Creation
|
|
107
|
+
* @deprecated Use `co.vector(...).create` instead.
|
|
108
|
+
*/
|
|
109
|
+
static create<S extends CoVector>(
|
|
110
|
+
this: CoValueClass<S> & typeof CoVector,
|
|
111
|
+
vector: number[] | Float32Array,
|
|
112
|
+
options?: { owner?: Account | Group } | Account | Group,
|
|
113
|
+
) {
|
|
114
|
+
const vectorAsFloat32Array =
|
|
115
|
+
vector instanceof Float32Array ? vector : new Float32Array(vector);
|
|
116
|
+
|
|
117
|
+
const givenVectorDimensions =
|
|
118
|
+
vectorAsFloat32Array.byteLength / vectorAsFloat32Array.BYTES_PER_ELEMENT;
|
|
119
|
+
|
|
120
|
+
if (
|
|
121
|
+
this.requiredDimensionsCount !== undefined &&
|
|
122
|
+
givenVectorDimensions !== this.requiredDimensionsCount
|
|
123
|
+
) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`Vector dimension mismatch! Expected ${this.requiredDimensionsCount} dimensions, got ${
|
|
126
|
+
givenVectorDimensions
|
|
127
|
+
}`,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const coVector = new this(parseCoValueCreateOptions(options));
|
|
132
|
+
coVector.setVectorData(vectorAsFloat32Array);
|
|
133
|
+
|
|
134
|
+
const byteArray = CoVector.toByteArray(vectorAsFloat32Array);
|
|
135
|
+
|
|
136
|
+
coVector.$jazz.raw.startBinaryStream({
|
|
137
|
+
mimeType: "application/vector+octet-stream",
|
|
138
|
+
totalSizeBytes: byteArray.byteLength,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const chunkSize =
|
|
142
|
+
cojsonInternals.TRANSACTION_CONFIG.MAX_RECOMMENDED_TX_SIZE;
|
|
143
|
+
|
|
144
|
+
// Although most embedding vectors are small
|
|
145
|
+
// (3072-dimensional vector is only 12,288 bytes),
|
|
146
|
+
// we should still chunk the data to avoid transaction size limits
|
|
147
|
+
for (let idx = 0; idx < byteArray.length; idx += chunkSize) {
|
|
148
|
+
coVector.$jazz.raw.pushBinaryStreamChunk(
|
|
149
|
+
byteArray.slice(idx, idx + chunkSize),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
coVector.$jazz.raw.endBinaryStream();
|
|
153
|
+
|
|
154
|
+
return coVector;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private static toByteArray(vector: Float32Array): Uint8Array {
|
|
158
|
+
// zero copy view of the vector bytes
|
|
159
|
+
return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private static fromByteArray(bytesChunks: Uint8Array[]): Float32Array {
|
|
163
|
+
const total = bytesChunks.reduce((acc, c) => acc + c.byteLength, 0);
|
|
164
|
+
|
|
165
|
+
if (total % 4 !== 0)
|
|
166
|
+
throw new Error("[INTERNAL] Total byte length must be multiple of 4");
|
|
167
|
+
|
|
168
|
+
const u8 = new Uint8Array(total);
|
|
169
|
+
let off = 0;
|
|
170
|
+
|
|
171
|
+
for (const c of bytesChunks) {
|
|
172
|
+
u8.set(c, off);
|
|
173
|
+
off += c.byteLength;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return new Float32Array(u8.buffer, u8.byteOffset, total / 4);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private loadVectorData(): void {
|
|
180
|
+
if (this._isVectorLoaded === true) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const chunks = this.$jazz.raw.getBinaryChunks();
|
|
185
|
+
|
|
186
|
+
if (!chunks) {
|
|
187
|
+
// This should never happen
|
|
188
|
+
throw new Error(`CoVector '${this.$jazz.raw.id}' is not loaded`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const vector = CoVector.fromByteArray(chunks.chunks);
|
|
192
|
+
|
|
193
|
+
if (vector.length !== this._requiredDimensionsCount) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Vector dimension mismatch! CoVector '${this.$jazz.raw.id}' loaded with ${vector.length} dimensions, but the schema requires ${this._requiredDimensionsCount} dimensions`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
this.setVectorData(vector);
|
|
200
|
+
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private setVectorData(vector: Float32Array): void {
|
|
205
|
+
super.set(vector, 0);
|
|
206
|
+
this._isVectorLoaded = true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get a JSON representation of the `CoVector`
|
|
211
|
+
* @category Content
|
|
212
|
+
*/
|
|
213
|
+
toJSON(): Array<number> {
|
|
214
|
+
return Array.from(this);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** @internal */
|
|
218
|
+
[inspect]() {
|
|
219
|
+
return this.toJSON();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Load a `CoVector`
|
|
224
|
+
*
|
|
225
|
+
* @category Subscription & Loading
|
|
226
|
+
* @deprecated Use `co.vector(...).load` instead.
|
|
227
|
+
*/
|
|
228
|
+
static async load<C extends CoVector>(
|
|
229
|
+
this: CoValueClass<C>,
|
|
230
|
+
id: ID<C>,
|
|
231
|
+
options?: {
|
|
232
|
+
loadAs?: Account | AnonymousJazzAgent;
|
|
233
|
+
},
|
|
234
|
+
): Promise<C | null> {
|
|
235
|
+
const coVector = await loadCoValueWithoutMe(this, id, options);
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* We are only interested in the entire vector. Since most vectors are small (<15kB),
|
|
239
|
+
* we can wait for the stream to be complete before returning the vector
|
|
240
|
+
*/
|
|
241
|
+
if (!coVector?.$jazz.raw.isBinaryStreamEnded()) {
|
|
242
|
+
return new Promise<C | null>((resolve) => {
|
|
243
|
+
subscribeToCoValueWithoutMe(
|
|
244
|
+
this,
|
|
245
|
+
id,
|
|
246
|
+
options || {},
|
|
247
|
+
(value, unsubscribe) => {
|
|
248
|
+
if (value.$jazz.raw.isBinaryStreamEnded()) {
|
|
249
|
+
unsubscribe();
|
|
250
|
+
resolve(value);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
coVector.loadVectorData();
|
|
258
|
+
return coVector;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Subscribe to a `CoVector`, when you have an ID but don't have a `CoVector` instance yet
|
|
263
|
+
* @category Subscription & Loading
|
|
264
|
+
* @deprecated Use `co.vector(...).subscribe` instead.
|
|
265
|
+
*/
|
|
266
|
+
static subscribe<V extends CoVector>(
|
|
267
|
+
this: CoValueClass<V>,
|
|
268
|
+
id: ID<V>,
|
|
269
|
+
listener: (value: Resolved<V, true>, unsubscribe: () => void) => void,
|
|
270
|
+
): () => void;
|
|
271
|
+
static subscribe<V extends CoVector>(
|
|
272
|
+
this: CoValueClass<V>,
|
|
273
|
+
id: ID<V>,
|
|
274
|
+
options: SubscribeListenerOptions<V, true>,
|
|
275
|
+
listener: (value: Resolved<V, true>, unsubscribe: () => void) => void,
|
|
276
|
+
): () => void;
|
|
277
|
+
static subscribe<V extends CoVector>(
|
|
278
|
+
this: CoValueClass<V>,
|
|
279
|
+
id: ID<V>,
|
|
280
|
+
...args: SubscribeRestArgs<V, true>
|
|
281
|
+
): () => void {
|
|
282
|
+
const { options, listener } = parseSubscribeRestArgs(args);
|
|
283
|
+
return subscribeToCoValueWithoutMe<V, true>(this, id, options, listener);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// CoVector mutation method overrides, as CoVectors aren't meant to be mutated
|
|
287
|
+
/**
|
|
288
|
+
* Calling `copyWithin` on a CoVector is forbidden. CoVectors are immutable.
|
|
289
|
+
* @deprecated If you want to change the vector, replace the former instance of CoVector with a new one.
|
|
290
|
+
*/
|
|
291
|
+
override copyWithin(target: number, start: number, end?: number): never {
|
|
292
|
+
throw new Error("Cannot mutate a CoVector using `copyWithin`");
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Calling `fill` on a CoVector is forbidden. CoVectors are immutable.
|
|
296
|
+
* @deprecated If you want to change the vector, replace the former instance of CoVector with a new one.
|
|
297
|
+
*/
|
|
298
|
+
override fill(value: number, start?: number, end?: number): never {
|
|
299
|
+
throw new Error("Cannot mutate a CoVector using `fill`");
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Calling `reverse` on a CoVector is forbidden. CoVectors are immutable.
|
|
303
|
+
* @deprecated If you want to change the vector, replace the former instance of CoVector with a new one.
|
|
304
|
+
*/
|
|
305
|
+
override reverse(): never {
|
|
306
|
+
throw new Error("Cannot mutate a CoVector using `reverse`");
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Calling `set` on a CoVector is forbidden. CoVectors are immutable.
|
|
310
|
+
* @deprecated If you want to change the vector, replace the former instance of CoVector with a new one.
|
|
311
|
+
// */
|
|
312
|
+
override set(array: ArrayLike<number>, offset?: number): never {
|
|
313
|
+
throw new Error("Cannot mutate a CoVector using `set`");
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Calling `sort` on a CoVector is forbidden. CoVectors are immutable.
|
|
317
|
+
* @deprecated If you want to change the vector, replace the former instance of CoVector with a new one.
|
|
318
|
+
*/
|
|
319
|
+
override sort(compareFn?: (a: number, b: number) => number): never {
|
|
320
|
+
throw new Error("Cannot mutate a CoVector using `sort`");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export class CoVectorJazzApi<V extends CoVector> extends CoValueJazzApi<V> {
|
|
325
|
+
constructor(
|
|
326
|
+
private coVector: V,
|
|
327
|
+
public raw: RawBinaryCoStream,
|
|
328
|
+
) {
|
|
329
|
+
super(coVector);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
get owner(): Group {
|
|
333
|
+
return getCoValueOwner(this.coVector);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* An instance method to subscribe to an existing `CoVector`
|
|
338
|
+
* @category Subscription & Loading
|
|
339
|
+
*/
|
|
340
|
+
subscribe<B extends CoVector>(
|
|
341
|
+
this: CoVectorJazzApi<B>,
|
|
342
|
+
listener: (value: Resolved<B, true>) => void,
|
|
343
|
+
): () => void {
|
|
344
|
+
return subscribeToExistingCoValue(this.coVector, {}, listener);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Wait for the `CoVector` to be uploaded to the other peers.
|
|
349
|
+
*
|
|
350
|
+
* @category Subscription & Loading
|
|
351
|
+
*/
|
|
352
|
+
waitForSync(options?: { timeout?: number }) {
|
|
353
|
+
return this.raw.core.waitForSync(options);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Vector operations
|
|
357
|
+
/**
|
|
358
|
+
* Calculate the magnitude of this vector.
|
|
359
|
+
*/
|
|
360
|
+
magnitude(): number {
|
|
361
|
+
return VectorCalculation.magnitude(this.coVector);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Normalize this vector.
|
|
366
|
+
* @returns A new instance of a normalized vector.
|
|
367
|
+
*/
|
|
368
|
+
normalize(): Float32Array {
|
|
369
|
+
return VectorCalculation.normalize(this.coVector);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Calculate the dot product of this vector and another vector.
|
|
374
|
+
*/
|
|
375
|
+
dotProduct(otherVector: CoVector | Float32Array | number[]): number {
|
|
376
|
+
return VectorCalculation.dotProduct(this.coVector, otherVector);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Calculate the cosine similarity between this vector and another vector.
|
|
381
|
+
*
|
|
382
|
+
* @returns A value between `-1` and `1`:
|
|
383
|
+
* - `1` means the vectors are identical
|
|
384
|
+
* - `0` means the vectors are orthogonal (i.e. no similarity)
|
|
385
|
+
* - `-1` means the vectors are opposite direction (perfectly dissimilar)
|
|
386
|
+
*/
|
|
387
|
+
cosineSimilarity(otherVector: CoVector | Float32Array | number[]): number {
|
|
388
|
+
return VectorCalculation.cosineSimilarity(this.coVector, otherVector);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const VectorCalculation = {
|
|
393
|
+
magnitude: (vector: Float32Array | number[]) => {
|
|
394
|
+
let sum = 0;
|
|
395
|
+
for (const v of vector) {
|
|
396
|
+
sum += v * v;
|
|
397
|
+
}
|
|
398
|
+
return Math.sqrt(sum);
|
|
399
|
+
},
|
|
400
|
+
normalize: (vector: Float32Array) => {
|
|
401
|
+
const mag = VectorCalculation.magnitude(vector);
|
|
402
|
+
|
|
403
|
+
if (mag === 0) {
|
|
404
|
+
return new Float32Array(vector.length).fill(0);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return vector.map((v) => v / mag);
|
|
408
|
+
},
|
|
409
|
+
dotProduct: (vectorA: Float32Array, vectorB: Float32Array | number[]) => {
|
|
410
|
+
if (vectorA.length !== vectorB.length) {
|
|
411
|
+
throw new Error(
|
|
412
|
+
`Vector dimensions don't match: ${vectorA.length} vs ${vectorB.length}`,
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return vectorA.reduce((sum, a, i) => sum + a * vectorB[i]!, 0);
|
|
417
|
+
},
|
|
418
|
+
cosineSimilarity: (
|
|
419
|
+
vectorA: Float32Array,
|
|
420
|
+
vectorB: Float32Array | number[],
|
|
421
|
+
) => {
|
|
422
|
+
const magnitudeA = VectorCalculation.magnitude(vectorA);
|
|
423
|
+
const magnitudeB = VectorCalculation.magnitude(vectorB);
|
|
424
|
+
|
|
425
|
+
if (magnitudeA === 0 || magnitudeB === 0) {
|
|
426
|
+
return 0;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const dotProductAB = VectorCalculation.dotProduct(vectorA, vectorB);
|
|
430
|
+
return dotProductAB / (magnitudeA * magnitudeB);
|
|
431
|
+
},
|
|
432
|
+
};
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type AccountRole,
|
|
4
4
|
type AgentID,
|
|
5
5
|
type Everyone,
|
|
6
|
+
type InviteSecret,
|
|
6
7
|
type RawAccountID,
|
|
7
8
|
type RawGroup,
|
|
8
9
|
type Role,
|
|
@@ -299,6 +300,29 @@ export class Group extends CoValueBase implements CoValue {
|
|
|
299
300
|
const { options, listener } = parseSubscribeRestArgs(args);
|
|
300
301
|
return subscribeToCoValueWithoutMe<G, R>(this, id, options, listener);
|
|
301
302
|
}
|
|
303
|
+
|
|
304
|
+
/** @category Invites
|
|
305
|
+
* Creates a group invite
|
|
306
|
+
* @param id The ID of the group to create an invite for
|
|
307
|
+
* @param options Optional configuration
|
|
308
|
+
* @param options.role The role to grant to the accepter of the invite. Defaults to 'reader'
|
|
309
|
+
* @param options.loadAs The account to use when loading the group. Defaults to the current account
|
|
310
|
+
* @returns An invite secret, (a string starting with "inviteSecret_"). Can be
|
|
311
|
+
* accepted using `Account.acceptInvite()`
|
|
312
|
+
*/
|
|
313
|
+
static async createInvite<G extends Group>(
|
|
314
|
+
this: CoValueClass<G>,
|
|
315
|
+
id: ID<G>,
|
|
316
|
+
options?: { role?: AccountRole; loadAs?: Account },
|
|
317
|
+
): Promise<InviteSecret> {
|
|
318
|
+
const group = await loadCoValueWithoutMe(this, id, {
|
|
319
|
+
loadAs: options?.loadAs,
|
|
320
|
+
});
|
|
321
|
+
if (!group) {
|
|
322
|
+
throw new Error(`Group with id ${id} not found`);
|
|
323
|
+
}
|
|
324
|
+
return group.$jazz.createInvite(options?.role ?? "reader");
|
|
325
|
+
}
|
|
302
326
|
}
|
|
303
327
|
|
|
304
328
|
export class GroupJazzApi<G extends Group> extends CoValueJazzApi<G> {
|
|
@@ -350,6 +374,15 @@ export class GroupJazzApi<G extends Group> extends CoValueJazzApi<G> {
|
|
|
350
374
|
return subscribeToExistingCoValue(this.group, options, listener);
|
|
351
375
|
}
|
|
352
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Create an invite to this group
|
|
379
|
+
*
|
|
380
|
+
* @category Invites
|
|
381
|
+
*/
|
|
382
|
+
createInvite(role: AccountRole = "reader"): InviteSecret {
|
|
383
|
+
return this.raw.createInvite(role);
|
|
384
|
+
}
|
|
385
|
+
|
|
353
386
|
/**
|
|
354
387
|
* Wait for the `Group` to be uploaded to the other peers.
|
|
355
388
|
*
|
|
@@ -301,7 +301,10 @@ export function subscribeToCoValue<
|
|
|
301
301
|
if (value.type === "unavailable") {
|
|
302
302
|
options.onUnavailable?.();
|
|
303
303
|
|
|
304
|
-
|
|
304
|
+
// Don't log unavailable errors when `loadUnique` or `upsertUnique` are used
|
|
305
|
+
if (!options.skipRetry) {
|
|
306
|
+
console.error(value.toString());
|
|
307
|
+
}
|
|
305
308
|
} else if (value.type === "unauthorized") {
|
|
306
309
|
options.onUnauthorized?.();
|
|
307
310
|
|
|
@@ -45,7 +45,7 @@ type PlatformSpecificContext<Acc extends Account> =
|
|
|
45
45
|
|
|
46
46
|
function getAnonymousFallback() {
|
|
47
47
|
const context = createAnonymousJazzContext({
|
|
48
|
-
|
|
48
|
+
peers: [],
|
|
49
49
|
crypto: new PureJSCrypto(),
|
|
50
50
|
});
|
|
51
51
|
|
|
@@ -71,13 +71,17 @@ export class JazzContextManager<
|
|
|
71
71
|
protected value: JazzContextType<Acc> | undefined;
|
|
72
72
|
protected context: PlatformSpecificContext<Acc> | undefined;
|
|
73
73
|
protected props: P | undefined;
|
|
74
|
-
protected authSecretStorage
|
|
74
|
+
protected authSecretStorage;
|
|
75
75
|
protected keepContextOpen = false;
|
|
76
76
|
contextPromise: Promise<void> | undefined;
|
|
77
77
|
protected authenticatingAccountID: string | null = null;
|
|
78
78
|
|
|
79
|
-
constructor(opts?: {
|
|
79
|
+
constructor(opts?: {
|
|
80
|
+
useAnonymousFallback?: boolean;
|
|
81
|
+
authSecretStorageKey?: string;
|
|
82
|
+
}) {
|
|
80
83
|
KvStoreContext.getInstance().initialize(this.getKvStore());
|
|
84
|
+
this.authSecretStorage = new AuthSecretStorage(opts?.authSecretStorageKey);
|
|
81
85
|
|
|
82
86
|
if (opts?.useAnonymousFallback) {
|
|
83
87
|
this.value = getAnonymousFallback();
|
|
@@ -90,7 +90,7 @@ export async function createJazzContextFromExistingCredentials<
|
|
|
90
90
|
| CoreAccountSchema,
|
|
91
91
|
>({
|
|
92
92
|
credentials,
|
|
93
|
-
|
|
93
|
+
peers,
|
|
94
94
|
crypto,
|
|
95
95
|
storage,
|
|
96
96
|
AccountSchema: PropsAccountSchema,
|
|
@@ -99,7 +99,7 @@ export async function createJazzContextFromExistingCredentials<
|
|
|
99
99
|
asActiveAccount,
|
|
100
100
|
}: {
|
|
101
101
|
credentials: Credentials;
|
|
102
|
-
|
|
102
|
+
peers: Peer[];
|
|
103
103
|
crypto: CryptoProvider;
|
|
104
104
|
AccountSchema?: S;
|
|
105
105
|
sessionProvider: SessionProvider;
|
|
@@ -122,7 +122,7 @@ export async function createJazzContextFromExistingCredentials<
|
|
|
122
122
|
accountID: credentials.accountID as unknown as CoID<RawAccount>,
|
|
123
123
|
accountSecret: credentials.secret,
|
|
124
124
|
sessionID: sessionID,
|
|
125
|
-
|
|
125
|
+
peers: peers,
|
|
126
126
|
crypto: crypto,
|
|
127
127
|
storage,
|
|
128
128
|
migration: async (rawAccount, _node, creationProps) => {
|
|
@@ -162,7 +162,7 @@ export async function createJazzContextForNewAccount<
|
|
|
162
162
|
>({
|
|
163
163
|
creationProps,
|
|
164
164
|
initialAgentSecret,
|
|
165
|
-
|
|
165
|
+
peers,
|
|
166
166
|
crypto,
|
|
167
167
|
AccountSchema: PropsAccountSchema,
|
|
168
168
|
onLogOut,
|
|
@@ -170,7 +170,7 @@ export async function createJazzContextForNewAccount<
|
|
|
170
170
|
}: {
|
|
171
171
|
creationProps: { name: string };
|
|
172
172
|
initialAgentSecret?: AgentSecret;
|
|
173
|
-
|
|
173
|
+
peers: Peer[];
|
|
174
174
|
crypto: CryptoProvider;
|
|
175
175
|
AccountSchema?: S;
|
|
176
176
|
onLogOut?: () => Promise<void>;
|
|
@@ -184,7 +184,7 @@ export async function createJazzContextForNewAccount<
|
|
|
184
184
|
|
|
185
185
|
const { node } = await LocalNode.withNewlyCreatedAccount({
|
|
186
186
|
creationProps,
|
|
187
|
-
|
|
187
|
+
peers,
|
|
188
188
|
crypto,
|
|
189
189
|
initialAgentSecret,
|
|
190
190
|
storage,
|
|
@@ -219,7 +219,7 @@ export async function createJazzContext<
|
|
|
219
219
|
>(options: {
|
|
220
220
|
credentials?: AuthCredentials;
|
|
221
221
|
newAccountProps?: NewAccountProps;
|
|
222
|
-
|
|
222
|
+
peers: Peer[];
|
|
223
223
|
crypto: CryptoProvider;
|
|
224
224
|
defaultProfileName?: string;
|
|
225
225
|
AccountSchema?: S;
|
|
@@ -243,7 +243,7 @@ export async function createJazzContext<
|
|
|
243
243
|
accountID: credentials.accountID,
|
|
244
244
|
secret: credentials.accountSecret,
|
|
245
245
|
},
|
|
246
|
-
|
|
246
|
+
peers: options.peers,
|
|
247
247
|
crypto,
|
|
248
248
|
AccountSchema: options.AccountSchema,
|
|
249
249
|
sessionProvider: options.sessionProvider,
|
|
@@ -267,7 +267,7 @@ export async function createJazzContext<
|
|
|
267
267
|
context = await createJazzContextForNewAccount({
|
|
268
268
|
creationProps,
|
|
269
269
|
initialAgentSecret,
|
|
270
|
-
|
|
270
|
+
peers: options.peers,
|
|
271
271
|
crypto,
|
|
272
272
|
AccountSchema: options.AccountSchema,
|
|
273
273
|
onLogOut: async () => {
|
|
@@ -293,11 +293,11 @@ export async function createJazzContext<
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
export function createAnonymousJazzContext({
|
|
296
|
-
|
|
296
|
+
peers,
|
|
297
297
|
crypto,
|
|
298
298
|
storage,
|
|
299
299
|
}: {
|
|
300
|
-
|
|
300
|
+
peers: Peer[];
|
|
301
301
|
crypto: CryptoProvider;
|
|
302
302
|
storage?: StorageAPI;
|
|
303
303
|
}): JazzContextWithAgent {
|
|
@@ -309,7 +309,7 @@ export function createAnonymousJazzContext({
|
|
|
309
309
|
crypto,
|
|
310
310
|
);
|
|
311
311
|
|
|
312
|
-
for (const peer of
|
|
312
|
+
for (const peer of peers) {
|
|
313
313
|
node.syncManager.addPeer(peer);
|
|
314
314
|
}
|
|
315
315
|
|
|
@@ -7,6 +7,7 @@ export { CoFeedSchema as Feed } from "./schemaTypes/CoFeedSchema.js";
|
|
|
7
7
|
export { PlainTextSchema as PlainText } from "./schemaTypes/PlainTextSchema.js";
|
|
8
8
|
export { RichTextSchema as RichText } from "./schemaTypes/RichTextSchema.js";
|
|
9
9
|
export { FileStreamSchema as FileStream } from "./schemaTypes/FileStreamSchema.js";
|
|
10
|
+
export { CoVectorSchema as Vector } from "./schemaTypes/CoVectorSchema.js";
|
|
10
11
|
export { CoInput as input } from "./typeConverters/CoFieldSchemaInit.js";
|
|
11
12
|
export {
|
|
12
13
|
AccountSchema as Account,
|
|
@@ -23,6 +24,7 @@ export {
|
|
|
23
24
|
coPlainTextDefiner as plainText,
|
|
24
25
|
coRichTextDefiner as richText,
|
|
25
26
|
coFileStreamDefiner as fileStream,
|
|
27
|
+
coVectorDefiner as vector,
|
|
26
28
|
coImageDefiner as image,
|
|
27
29
|
coAccountDefiner as account,
|
|
28
30
|
coGroupDefiner as group,
|
|
@@ -12,12 +12,14 @@ import {
|
|
|
12
12
|
CoValueClass,
|
|
13
13
|
FileStream,
|
|
14
14
|
FileStreamSchema,
|
|
15
|
+
CoVectorSchema,
|
|
15
16
|
PlainTextSchema,
|
|
16
17
|
SchemaUnion,
|
|
17
18
|
enrichAccountSchema,
|
|
18
19
|
enrichCoMapSchema,
|
|
19
20
|
isCoValueClass,
|
|
20
21
|
Group,
|
|
22
|
+
CoVector,
|
|
21
23
|
} from "../../../internal.js";
|
|
22
24
|
import { coField } from "../../schema.js";
|
|
23
25
|
|
|
@@ -123,6 +125,17 @@ export function hydrateCoreCoValueSchema<S extends AnyCoreCoValueSchema>(
|
|
|
123
125
|
} else if (schema.builtin === "FileStream") {
|
|
124
126
|
const coValueClass = FileStream;
|
|
125
127
|
return new FileStreamSchema(coValueClass) as CoValueSchemaFromCoreSchema<S>;
|
|
128
|
+
} else if (schema.builtin === "CoVector") {
|
|
129
|
+
const dimensions = schema.dimensions;
|
|
130
|
+
|
|
131
|
+
const coValueClass = class CoVectorWithDimensions extends CoVector {
|
|
132
|
+
protected static requiredDimensionsCount = dimensions;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return new CoVectorSchema(
|
|
136
|
+
dimensions,
|
|
137
|
+
coValueClass,
|
|
138
|
+
) as CoValueSchemaFromCoreSchema<S>;
|
|
126
139
|
} else if (schema.builtin === "CoPlainText") {
|
|
127
140
|
const coValueClass = CoPlainText;
|
|
128
141
|
return new PlainTextSchema(coValueClass) as CoValueSchemaFromCoreSchema<S>;
|