@midsummer-ai/sdk 0.0.0-stage → 0.1.0-next.419

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.
Files changed (79) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +4 -2
  3. package/agents/contract.d.mts +9 -0
  4. package/agents/contract.mjs +221 -0
  5. package/agents/index.d.mts +128 -0
  6. package/agents/index.mjs +203 -0
  7. package/agents/stand-in.d.mts +35 -0
  8. package/agents/stand-in.mjs +149 -0
  9. package/ai/contract.d.mts +10 -0
  10. package/ai/contract.mjs +77 -0
  11. package/ai/index.d.mts +94 -0
  12. package/ai/index.mjs +193 -0
  13. package/ai/stand-in.d.mts +7 -0
  14. package/ai/stand-in.mjs +41 -0
  15. package/build-SQ44jwSa.d.mts +41 -0
  16. package/client.d.mts +45 -0
  17. package/client.mjs +106 -0
  18. package/connection-CDk7H1FL.mjs +1871 -0
  19. package/contract.d.mts +10 -0
  20. package/contract.mjs +469 -0
  21. package/database/build.d.mts +2 -0
  22. package/database/build.mjs +579 -0
  23. package/database/client.d.mts +60 -0
  24. package/database/client.mjs +126 -0
  25. package/database/contract.d.mts +11 -0
  26. package/database/contract.mjs +164 -0
  27. package/database/errors.d.mts +23 -0
  28. package/database/errors.mjs +13 -0
  29. package/database/server.d.mts +3 -0
  30. package/database/server.mjs +320 -0
  31. package/database/stand-in.d.mts +96 -0
  32. package/database/stand-in.mjs +422 -0
  33. package/email/client.d.mts +34 -0
  34. package/email/client.mjs +131 -0
  35. package/email/contract.d.mts +11 -0
  36. package/email/contract.mjs +99 -0
  37. package/email/index.d.mts +74 -0
  38. package/email/index.mjs +59 -0
  39. package/email/smtp.d.mts +22 -0
  40. package/email/smtp.mjs +296 -0
  41. package/email/stand-in.d.mts +13 -0
  42. package/email/stand-in.mjs +51 -0
  43. package/index-DdoK0y7D.d.mts +192 -0
  44. package/index-sgdyoA2P.d.mts +212 -0
  45. package/index.d.mts +2 -0
  46. package/index.mjs +137 -0
  47. package/names-DfCBKupJ.mjs +115 -0
  48. package/package.json +152 -4
  49. package/predict-Drfm_8pO.mjs +179 -0
  50. package/queues/contract.d.mts +13 -0
  51. package/queues/contract.mjs +278 -0
  52. package/queues/index.d.mts +184 -0
  53. package/queues/index.mjs +126 -0
  54. package/queues/stand-in.d.mts +7 -0
  55. package/queues/stand-in.mjs +110 -0
  56. package/queues/wire.d.mts +9 -0
  57. package/queues/wire.mjs +199 -0
  58. package/s3.d.mts +43 -0
  59. package/s3.mjs +1003 -0
  60. package/schema-BF-Y1EVu.mjs +142 -0
  61. package/schema-DS8x1Dn8.mjs +115 -0
  62. package/schema-f7E9uzUn.d.mts +74 -0
  63. package/server-C7O7CICU.d.mts +182 -0
  64. package/socket.d.mts +67 -0
  65. package/socket.mjs +263 -0
  66. package/stand-in.d.mts +7 -0
  67. package/stand-in.mjs +185 -0
  68. package/store-BzI9at5x.mjs +237 -0
  69. package/tabs-D-P8_ci_.mjs +457 -0
  70. package/vector/contract.d.mts +10 -0
  71. package/vector/contract.mjs +635 -0
  72. package/vector/index.d.mts +2 -0
  73. package/vector/index.mjs +108 -0
  74. package/vector/stand-in.d.mts +11 -0
  75. package/vector/stand-in.mjs +169 -0
  76. package/vector/wire.d.mts +25 -0
  77. package/vector/wire.mjs +175 -0
  78. package/wire.d.mts +54 -0
  79. package/wire.mjs +731 -0
@@ -0,0 +1,635 @@
1
+ import { p as VectorError } from "../schema-DS8x1Dn8.mjs";
2
+ import { vectorDb } from "./index.mjs";
3
+ //#region src/vector/contract.ts
4
+ /**
5
+ * Vector DB's contract: what every engine promises, as cases any test runner can run. The Stand-in
6
+ * runs them in this package; the real Capability runs the same cases against its own engine,
7
+ * through the wire. A behaviour that is not a case here is not promised.
8
+ *
9
+ * for (const c of vectorContract) test(c.name, () => c.run(makeEngine()))
10
+ *
11
+ * Each case gets an engine with no namespaces in it, makes the ones it needs, and throws when the
12
+ * engine breaks the promise. Expected values are worked out by hand, never computed with the SDK's
13
+ * own code.
14
+ */
15
+ const points = [
16
+ {
17
+ id: "east",
18
+ values: [1, 0],
19
+ metadata: {
20
+ kind: "axis",
21
+ rank: 1
22
+ }
23
+ },
24
+ {
25
+ id: "north",
26
+ values: [0, 1],
27
+ metadata: {
28
+ kind: "axis",
29
+ rank: 2
30
+ }
31
+ },
32
+ {
33
+ id: "north-east",
34
+ values: [1, 1],
35
+ metadata: {
36
+ kind: "diagonal",
37
+ rank: 3
38
+ }
39
+ },
40
+ {
41
+ id: "west",
42
+ values: [-1, 0],
43
+ metadata: {
44
+ kind: "axis",
45
+ rank: 4,
46
+ lonely: true
47
+ }
48
+ }
49
+ ];
50
+ const vectorContract = [
51
+ {
52
+ name: "a Vector upserted is fetched back with its values and metadata, in the order asked, leaving out ids it does not hold",
53
+ async run(engine) {
54
+ await engine.create("docs", {
55
+ dimension: 3,
56
+ metric: "cosine"
57
+ });
58
+ const docs = vectorDb(engine).namespace("docs");
59
+ equal(await docs.upsert([{
60
+ id: "a",
61
+ values: [
62
+ .5,
63
+ .25,
64
+ 1
65
+ ],
66
+ metadata: {
67
+ lang: "en",
68
+ year: 2026,
69
+ draft: false
70
+ }
71
+ }, {
72
+ id: "b",
73
+ values: [
74
+ 1,
75
+ 2,
76
+ 3
77
+ ]
78
+ }]), { upserted: 2 }, "the upsert's answer");
79
+ equal(await docs.fetch([
80
+ "b",
81
+ "missing",
82
+ "a"
83
+ ]), [{
84
+ id: "b",
85
+ values: [
86
+ 1,
87
+ 2,
88
+ 3
89
+ ]
90
+ }, {
91
+ id: "a",
92
+ values: [
93
+ .5,
94
+ .25,
95
+ 1
96
+ ],
97
+ metadata: {
98
+ lang: "en",
99
+ year: 2026,
100
+ draft: false
101
+ }
102
+ }], "the fetch");
103
+ equal(await docs.describe(), {
104
+ dimension: 3,
105
+ metric: "cosine",
106
+ count: 2
107
+ }, "the namespace");
108
+ }
109
+ },
110
+ {
111
+ name: "an upsert replaces a Vector with the same id whole, metadata included, and a delete removes it; deleting one not there is not an error",
112
+ async run(engine) {
113
+ await engine.create("docs", {
114
+ dimension: 2,
115
+ metric: "dot"
116
+ });
117
+ const docs = vectorDb(engine).namespace("docs");
118
+ await docs.upsert([{
119
+ id: "a",
120
+ values: [1, 2],
121
+ metadata: { lang: "en" }
122
+ }]);
123
+ await docs.upsert([{
124
+ id: "a",
125
+ values: [3, 4]
126
+ }]);
127
+ equal(await docs.fetch(["a"]), [{
128
+ id: "a",
129
+ values: [3, 4]
130
+ }], "the replaced Vector");
131
+ await docs.delete(["a", "never-there"]);
132
+ equal(await docs.fetch(["a"]), [], "the fetch after its delete");
133
+ equal((await docs.describe()).count, 0, "the count after its delete");
134
+ }
135
+ },
136
+ {
137
+ name: "a cosine query answers the topK closest by cosine similarity, highest first, without values or metadata unless asked",
138
+ async run(engine) {
139
+ await engine.create("compass", {
140
+ dimension: 2,
141
+ metric: "cosine"
142
+ });
143
+ const compass = vectorDb(engine).namespace("compass");
144
+ await compass.upsert(points);
145
+ const matches = await compass.query([2, 0], { topK: 3 });
146
+ equal(matches.map((m) => m.id), [
147
+ "east",
148
+ "north-east",
149
+ "north"
150
+ ], "the ids, closest first");
151
+ near(matches.map((m) => m.score), [
152
+ 1,
153
+ Math.SQRT1_2,
154
+ 0
155
+ ], "the scores");
156
+ equal(matches.map((m) => [m.values, m.metadata]), [
157
+ [void 0, void 0],
158
+ [void 0, void 0],
159
+ [void 0, void 0]
160
+ ], "values and metadata left out");
161
+ equal((await compass.query([2, 0], {
162
+ topK: 1,
163
+ includeValues: true,
164
+ includeMetadata: true
165
+ })).map(({ score: _, ...rest }) => rest), [{
166
+ id: "east",
167
+ values: [1, 0],
168
+ metadata: {
169
+ kind: "axis",
170
+ rank: 1
171
+ }
172
+ }], "a match with values and metadata");
173
+ }
174
+ },
175
+ {
176
+ name: "a euclidean query answers distances, lowest first, and a dot query answers dot products, highest first",
177
+ async run(engine) {
178
+ await engine.create("flat", {
179
+ dimension: 2,
180
+ metric: "euclidean"
181
+ });
182
+ await engine.create("dots", {
183
+ dimension: 2,
184
+ metric: "dot"
185
+ });
186
+ const flat = vectorDb(engine).namespace("flat");
187
+ const dots = vectorDb(engine).namespace("dots");
188
+ await flat.upsert(points);
189
+ await dots.upsert(points);
190
+ const near1 = await flat.query([1, 0], { topK: 4 });
191
+ equal(near1.map((m) => m.id), [
192
+ "east",
193
+ "north-east",
194
+ "north",
195
+ "west"
196
+ ], "euclidean order");
197
+ near(near1.map((m) => m.score), [
198
+ 0,
199
+ 1,
200
+ Math.SQRT2,
201
+ 2
202
+ ], "euclidean distances");
203
+ const dot = await dots.query([3, 1], { topK: 4 });
204
+ equal(dot.map((m) => m.id), [
205
+ "north-east",
206
+ "east",
207
+ "north",
208
+ "west"
209
+ ], "dot order");
210
+ near(dot.map((m) => m.score), [
211
+ 4,
212
+ 3,
213
+ 1,
214
+ -3
215
+ ], "dot products");
216
+ }
217
+ },
218
+ {
219
+ name: "equal scores come in id order, and topK cuts the matches",
220
+ async run(engine) {
221
+ await engine.create("ties", {
222
+ dimension: 2,
223
+ metric: "dot"
224
+ });
225
+ const ties = vectorDb(engine).namespace("ties");
226
+ await ties.upsert([
227
+ {
228
+ id: "c",
229
+ values: [1, 0]
230
+ },
231
+ {
232
+ id: "a",
233
+ values: [1, 0]
234
+ },
235
+ {
236
+ id: "b",
237
+ values: [1, 0]
238
+ },
239
+ {
240
+ id: "d",
241
+ values: [0, 1]
242
+ }
243
+ ]);
244
+ equal((await ties.query([1, 0], { topK: 2 })).map((m) => m.id), ["a", "b"], "the first two of three ties");
245
+ equal((await ties.query([1, 0])).map((m) => m.id), [
246
+ "a",
247
+ "b",
248
+ "c",
249
+ "d"
250
+ ], "every Vector, under the default topK of 10");
251
+ }
252
+ },
253
+ {
254
+ name: "a filter keeps only Vectors whose metadata meets every condition; a missing field meets only $ne and $nin",
255
+ async run(engine) {
256
+ await engine.create("compass", {
257
+ dimension: 2,
258
+ metric: "dot"
259
+ });
260
+ const compass = vectorDb(engine).namespace("compass");
261
+ await compass.upsert(points);
262
+ const ids = async (filter) => (await compass.query([0, 0], {
263
+ topK: 10,
264
+ filter
265
+ })).map((m) => m.id).sort();
266
+ equal(await ids({ kind: "axis" }), [
267
+ "east",
268
+ "north",
269
+ "west"
270
+ ], "a bare value");
271
+ equal(await ids({ kind: { $ne: "axis" } }), ["north-east"], "$ne");
272
+ equal(await ids({ rank: { $in: [1, 3] } }), ["east", "north-east"], "$in");
273
+ equal(await ids({ rank: { $nin: [1, 3] } }), ["north", "west"], "$nin");
274
+ equal(await ids({ rank: {
275
+ $gt: 1,
276
+ $lte: 3
277
+ } }), ["north", "north-east"], "a range");
278
+ equal(await ids({
279
+ kind: "axis",
280
+ rank: { $gte: 2 }
281
+ }), ["north", "west"], "two fields");
282
+ equal(await ids({ lonely: true }), ["west"], "a boolean");
283
+ equal(await ids({ lonely: { $ne: true } }), [
284
+ "east",
285
+ "north",
286
+ "north-east"
287
+ ], "$ne on a field some lack");
288
+ equal(await ids({ lonely: { $nin: [true] } }), [
289
+ "east",
290
+ "north",
291
+ "north-east"
292
+ ], "$nin on a field some lack");
293
+ equal(await ids({ rank: { $gt: "1" } }), [], "a string bound never orders a number");
294
+ }
295
+ },
296
+ {
297
+ name: "a Vector or query of another dimension is invalid, and a refused upsert keeps none of its Vectors",
298
+ async run(engine) {
299
+ await engine.create("docs", {
300
+ dimension: 3,
301
+ metric: "euclidean"
302
+ });
303
+ const docs = vectorDb(engine).namespace("docs");
304
+ await fails(docs.upsert([{
305
+ id: "a",
306
+ values: [
307
+ 1,
308
+ 2,
309
+ 3
310
+ ]
311
+ }, {
312
+ id: "b",
313
+ values: [1, 2]
314
+ }]), "invalid", "an upsert with a short Vector");
315
+ equal(await docs.fetch(["a", "b"]), [], "nothing kept from it");
316
+ await fails(docs.query([
317
+ 1,
318
+ 2,
319
+ 3,
320
+ 4
321
+ ]), "invalid", "a long query");
322
+ }
323
+ },
324
+ {
325
+ name: "with cosine, a Vector or query of all zeros is invalid",
326
+ async run(engine) {
327
+ await engine.create("docs", {
328
+ dimension: 2,
329
+ metric: "cosine"
330
+ });
331
+ const docs = vectorDb(engine).namespace("docs");
332
+ await fails(docs.upsert([{
333
+ id: "zero",
334
+ values: [0, 0]
335
+ }]), "invalid", "a zero Vector");
336
+ await fails(docs.query([0, 0]), "invalid", "a zero query");
337
+ }
338
+ },
339
+ {
340
+ name: "a namespace that does not exist is not_found for every call",
341
+ async run(engine) {
342
+ const nowhere = vectorDb(engine).namespace("nowhere");
343
+ await fails(nowhere.describe(), "not_found", "describe");
344
+ await fails(nowhere.upsert([{
345
+ id: "a",
346
+ values: [1]
347
+ }]), "not_found", "upsert");
348
+ await fails(nowhere.query([1]), "not_found", "query");
349
+ await fails(nowhere.fetch(["a"]), "not_found", "fetch");
350
+ await fails(nowhere.delete(["a"]), "not_found", "delete");
351
+ }
352
+ },
353
+ {
354
+ name: "a namespace's dimension and metric are fixed: making it again the same way changes nothing, another way is a conflict",
355
+ async run(engine) {
356
+ await engine.create("docs", {
357
+ dimension: 2,
358
+ metric: "cosine"
359
+ });
360
+ await vectorDb(engine).namespace("docs").upsert([{
361
+ id: "a",
362
+ values: [1, 0]
363
+ }]);
364
+ await engine.create("docs", {
365
+ dimension: 2,
366
+ metric: "cosine"
367
+ });
368
+ equal(await vectorDb(engine).namespace("docs").describe(), {
369
+ dimension: 2,
370
+ metric: "cosine",
371
+ count: 1
372
+ }, "the namespace made again");
373
+ await fails(engine.create("docs", {
374
+ dimension: 3,
375
+ metric: "cosine"
376
+ }), "conflict", "another dimension");
377
+ await fails(engine.create("docs", {
378
+ dimension: 2,
379
+ metric: "dot"
380
+ }), "conflict", "another metric");
381
+ }
382
+ },
383
+ {
384
+ name: "namespaces are apart: a Vector in one is not in another, and dropping one leaves the other",
385
+ async run(engine) {
386
+ await engine.create("one", {
387
+ dimension: 1,
388
+ metric: "dot"
389
+ });
390
+ await engine.create("two", {
391
+ dimension: 1,
392
+ metric: "dot"
393
+ });
394
+ const db = vectorDb(engine);
395
+ await db.namespace("one").upsert([{
396
+ id: "a",
397
+ values: [1]
398
+ }]);
399
+ equal(await db.namespace("two").fetch(["a"]), [], "the other namespace");
400
+ await engine.drop("one");
401
+ await engine.drop("one");
402
+ await fails(db.namespace("one").describe(), "not_found", "the dropped namespace");
403
+ equal((await db.namespace("two").describe()).count, 0, "the namespace left");
404
+ }
405
+ },
406
+ {
407
+ name: "what a caller does to the arrays it upserted or was answered does not change what is stored",
408
+ async run(engine) {
409
+ await engine.create("docs", {
410
+ dimension: 2,
411
+ metric: "dot"
412
+ });
413
+ const docs = vectorDb(engine).namespace("docs");
414
+ const values = [1, 2];
415
+ const metadata = { lang: "en" };
416
+ await docs.upsert([{
417
+ id: "a",
418
+ values,
419
+ metadata
420
+ }]);
421
+ values[0] = 9;
422
+ metadata.lang = "fr";
423
+ const [fetched] = await docs.fetch(["a"]);
424
+ fetched.values[1] = 9;
425
+ equal(await docs.fetch(["a"]), [{
426
+ id: "a",
427
+ values: [1, 2],
428
+ metadata: { lang: "en" }
429
+ }], "the stored Vector");
430
+ }
431
+ },
432
+ {
433
+ name: "names, ids, values, filters and limits are checked before a call reaches the engine",
434
+ async run(engine) {
435
+ await engine.create("docs", {
436
+ dimension: 1,
437
+ metric: "dot"
438
+ });
439
+ const db = vectorDb(engine);
440
+ const docs = db.namespace("docs");
441
+ await fails(Promise.resolve().then(() => db.namespace("Docs")), "invalid", "an uppercase name");
442
+ await fails(docs.upsert([]), "invalid", "an empty upsert");
443
+ await fails(docs.upsert([{
444
+ id: "",
445
+ values: [1]
446
+ }]), "invalid", "an empty id");
447
+ await fails(docs.upsert([{
448
+ id: "a",
449
+ values: [NaN]
450
+ }]), "invalid", "a NaN value");
451
+ await fails(docs.upsert([{
452
+ id: "a",
453
+ values: [1]
454
+ }, {
455
+ id: "a",
456
+ values: [2]
457
+ }]), "invalid", "one id twice");
458
+ await fails(docs.upsert([{
459
+ id: "a",
460
+ values: [1],
461
+ metadata: { $kind: "x" }
462
+ }]), "invalid", "a field starting with $");
463
+ await fails(docs.upsert([{
464
+ id: "a",
465
+ values: [1],
466
+ metadata: { "a.b": "x" }
467
+ }]), "invalid", "a field holding a dot");
468
+ await fails(docs.query([1], { topK: 0 }), "invalid", "topK 0");
469
+ await fails(docs.query([1], { topK: 101 }), "invalid", "topK 101");
470
+ await fails(docs.query([1], { filter: { kind: { $like: "x" } } }), "invalid", "an unknown operator");
471
+ await fails(docs.query([1], { consistency: "sometimes" }), "invalid", "an unknown consistency");
472
+ await fails(docs.fetch([]), "invalid", "a fetch of no ids");
473
+ }
474
+ },
475
+ {
476
+ name: "every score is a finite number, for values as large or as small as a Vector may hold",
477
+ async run(engine) {
478
+ await engine.create("angles", {
479
+ dimension: 2,
480
+ metric: "cosine"
481
+ });
482
+ await engine.create("far", {
483
+ dimension: 2,
484
+ metric: "euclidean"
485
+ });
486
+ await engine.create("dots", {
487
+ dimension: 2,
488
+ metric: "dot"
489
+ });
490
+ const db = vectorDb(engine);
491
+ const angles = db.namespace("angles");
492
+ await angles.upsert([
493
+ {
494
+ id: "big",
495
+ values: [0x16345785d8a0000, 0]
496
+ },
497
+ {
498
+ id: "tiny",
499
+ values: [1e-17, 0]
500
+ },
501
+ {
502
+ id: "both",
503
+ values: [0x16345785d8a0000, 0x16345785d8a0000]
504
+ }
505
+ ]);
506
+ for (const vector of [[0x16345785d8a0000, 0], [1e-17, 0]]) {
507
+ const matches = await angles.query(vector);
508
+ equal(matches.map((m) => m.id), [
509
+ "big",
510
+ "tiny",
511
+ "both"
512
+ ], `the order for ${vector[0]}`);
513
+ near(matches.map((m) => m.score), [
514
+ 1,
515
+ 1,
516
+ Math.SQRT1_2
517
+ ], `cosine scores for ${vector[0]}`);
518
+ }
519
+ const far = db.namespace("far");
520
+ await far.upsert([{
521
+ id: "corner",
522
+ values: [0x16345785d8a0000, -0x16345785d8a0000]
523
+ }, {
524
+ id: "origin",
525
+ values: [0, 0]
526
+ }]);
527
+ const distances = await far.query([-0x16345785d8a0000, 0x16345785d8a0000]);
528
+ equal(distances.map((m) => m.id), ["origin", "corner"], "the euclidean order");
529
+ near(distances.map((m) => m.score), [0x16345785d8a0000 * Math.SQRT2, 0x2c68af0bb140000 * Math.SQRT2], "euclidean distances");
530
+ const dots = db.namespace("dots");
531
+ await dots.upsert([{
532
+ id: "big",
533
+ values: [0x16345785d8a0000, 0x16345785d8a0000]
534
+ }]);
535
+ near((await dots.query([0x16345785d8a0000, 0x16345785d8a0000])).map((m) => m.score), [2e34], "the dot product of the largest values");
536
+ }
537
+ },
538
+ {
539
+ name: "a namespace made with an embedding model takes text: the Vector of a query's own text is found first, kept as values, not text",
540
+ async run(engine) {
541
+ await engine.create("notes", {
542
+ dimension: 1024,
543
+ metric: "cosine",
544
+ embed: "bge-m3"
545
+ });
546
+ const notes = vectorDb(engine).namespace("notes");
547
+ const texts = {
548
+ cat: "The cat sat on the warm mat by the door",
549
+ revenue: "Quarterly revenue grew by four percent in Europe",
550
+ reset: "How to reset a forgotten account password"
551
+ };
552
+ equal(await notes.upsert(Object.entries(texts).map(([id, text]) => ({
553
+ id,
554
+ text,
555
+ metadata: { text }
556
+ }))), { upserted: 3 }, "the upsert's answer");
557
+ const [best] = await notes.query(texts.reset, {
558
+ topK: 3,
559
+ includeMetadata: true
560
+ });
561
+ equal([best?.id, best?.metadata], ["reset", { text: texts.reset }], "the closest Vector");
562
+ if (!(best.score > .99)) throw new Error(`the score of a query's own text: expected about 1, got ${best.score}`);
563
+ const [kept] = await notes.fetch(["cat"]);
564
+ equal([Object.keys(kept), kept.values.length], [[
565
+ "id",
566
+ "values",
567
+ "metadata"
568
+ ], 1024], "the stored Vector");
569
+ await fails(engine.create("notes", {
570
+ dimension: 1024,
571
+ metric: "cosine"
572
+ }), "conflict", "making it again without its embedding model");
573
+ }
574
+ },
575
+ {
576
+ name: "a namespace made without an embedding model refuses text as invalid",
577
+ async run(engine) {
578
+ await engine.create("docs", {
579
+ dimension: 2,
580
+ metric: "cosine"
581
+ });
582
+ const docs = vectorDb(engine).namespace("docs");
583
+ await fails(docs.upsert([{
584
+ id: "a",
585
+ text: "hello"
586
+ }]), "invalid", "an upsert of text");
587
+ await fails(docs.query("hello"), "invalid", "a query by text");
588
+ await fails(docs.upsert([{
589
+ id: "a",
590
+ text: " "
591
+ }]), "invalid", "an upsert of all spaces");
592
+ equal((await docs.describe()).count, 0, "the count after refused upserts");
593
+ }
594
+ },
595
+ {
596
+ name: "a value beyond 1e17 in size is invalid",
597
+ async run(engine) {
598
+ await engine.create("docs", {
599
+ dimension: 1,
600
+ metric: "dot"
601
+ });
602
+ const docs = vectorDb(engine).namespace("docs");
603
+ await fails(docs.upsert([{
604
+ id: "a",
605
+ values: [0x163457ab195e400]
606
+ }]), "invalid", "an upsert just past 1e17");
607
+ await fails(docs.upsert([{
608
+ id: "a",
609
+ values: [1e39]
610
+ }]), "invalid", "an upsert of 1e39");
611
+ await fails(docs.query([-1e39]), "invalid", "a query of -1e39");
612
+ }
613
+ }
614
+ ];
615
+ function equal(actual, expected, what) {
616
+ const a = JSON.stringify(actual);
617
+ const e = JSON.stringify(expected);
618
+ if (a !== e) throw new Error(`${what}: expected ${e}, got ${a}`);
619
+ }
620
+ /** Each score a finite number within a millionth of what was expected, relative to its size once past 1. */
621
+ function near(actual, expected, what) {
622
+ const off = (value, index) => !Number.isFinite(value) || Math.abs(value - expected[index]) > 1e-6 * Math.max(1, Math.abs(expected[index]));
623
+ if (actual.length !== expected.length || actual.some(off)) throw new Error(`${what}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
624
+ }
625
+ async function fails(call, code, what) {
626
+ try {
627
+ await call;
628
+ } catch (error) {
629
+ if (error instanceof VectorError && error.code === code) return;
630
+ throw new Error(`${what}: expected ${code}, got ${error instanceof VectorError ? error.code : String(error)}`);
631
+ }
632
+ throw new Error(`${what}: expected ${code}, but it succeeded`);
633
+ }
634
+ //#endregion
635
+ export { vectorContract };
@@ -0,0 +1,2 @@
1
+ import { C as MAX_TOP_K, D as vectorErrorCodes, E as VectorErrorCode, S as MAX_TEXT, T as VectorError, _ as embedded, a as Match, b as MAX_DIMENSION, c as Namespace, d as TextVector, f as ValuesEngine, g as VectorEngine, h as VectorDb, i as Filter, l as NamespaceInfo, m as VectorControl, n as Consistency, o as MetadataValue, p as Vector, r as EngineQuery, s as Metric, t as Condition, u as QueryOptions, v as vectorDb, w as MAX_VALUE, x as MAX_METADATA_BYTES, y as MAX_BATCH } from "../index-DdoK0y7D.mjs";
2
+ export { Condition, Consistency, EngineQuery, Filter, MAX_BATCH, MAX_DIMENSION, MAX_METADATA_BYTES, MAX_TEXT, MAX_TOP_K, MAX_VALUE, Match, MetadataValue, Metric, Namespace, NamespaceInfo, QueryOptions, TextVector, ValuesEngine, Vector, VectorControl, VectorDb, VectorEngine, VectorError, type VectorErrorCode, embedded, vectorDb, vectorErrorCodes };