@mastra/core 0.5.0-alpha.9 → 0.5.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.
Files changed (91) hide show
  1. package/dist/agent/index.cjs +3 -2140
  2. package/dist/agent/index.d.cts +1 -1
  3. package/dist/agent/index.d.ts +1 -1
  4. package/dist/agent/index.js +1 -1
  5. package/dist/{base-CMEKtEnE.d.cts → base-CIPKleAU.d.cts} +97 -60
  6. package/dist/{base-B78F6w8S.d.ts → base-C_Oq53qk.d.ts} +97 -60
  7. package/dist/base.cjs +5 -140
  8. package/dist/bundler/index.cjs +5 -160
  9. package/dist/chunk-2W2GYEYQ.cjs +25 -0
  10. package/dist/chunk-3ASEZT7U.cjs +1586 -0
  11. package/dist/chunk-43Y7WG5W.cjs +335 -0
  12. package/dist/{chunk-IM7CM3DU.js → chunk-4Y74D74B.js} +1 -1
  13. package/dist/chunk-ENT7U27Y.cjs +37 -0
  14. package/dist/chunk-F5UYWPV4.cjs +14 -0
  15. package/dist/chunk-FL3GQXQ2.cjs +218 -0
  16. package/dist/chunk-FRQFWZDN.cjs +2 -0
  17. package/dist/chunk-GXQRMKSN.cjs +367 -0
  18. package/dist/chunk-HJPMYDWO.cjs +37 -0
  19. package/dist/chunk-IIWRJFLQ.cjs +51 -0
  20. package/dist/chunk-KFQ7Z3PO.cjs +347 -0
  21. package/dist/{chunk-TWAIC2XA.js → chunk-KP5UAFLN.js} +1 -1
  22. package/dist/chunk-KPKFLQFR.cjs +12 -0
  23. package/dist/{chunk-NR5T72G7.js → chunk-MLFXOST6.js} +1 -1
  24. package/dist/{chunk-6V737PR2.js → chunk-OD7ZMKHY.js} +166 -58
  25. package/dist/chunk-OTFLHXHZ.cjs +65 -0
  26. package/dist/chunk-RWTSGWWL.cjs +81 -0
  27. package/dist/chunk-ST5RMVLG.cjs +87 -0
  28. package/dist/chunk-SYQ7NK2E.cjs +24 -0
  29. package/dist/chunk-UZNQG7QO.cjs +1868 -0
  30. package/dist/chunk-V5ORZPFW.cjs +38 -0
  31. package/dist/chunk-VA4P7QJT.cjs +443 -0
  32. package/dist/chunk-WB2HREXE.cjs +166 -0
  33. package/dist/chunk-WOMOGDGR.cjs +691 -0
  34. package/dist/chunk-XB2TJ7LX.cjs +408 -0
  35. package/dist/{chunk-4AQBRUR2.js → chunk-XF2FMJYK.js} +1 -1
  36. package/dist/chunk-XLSROQ26.cjs +91 -0
  37. package/dist/chunk-YK3XJ52U.cjs +192 -0
  38. package/dist/{chunk-EWB556GS.js → chunk-YPD6BQIM.js} +29 -1
  39. package/dist/deployer/index.cjs +5 -167
  40. package/dist/eval/index.cjs +9 -105
  41. package/dist/eval/index.d.cts +1 -1
  42. package/dist/eval/index.d.ts +1 -1
  43. package/dist/hooks/index.cjs +14 -83
  44. package/dist/index.cjs +253 -7516
  45. package/dist/index.d.cts +3 -3
  46. package/dist/index.d.ts +3 -3
  47. package/dist/index.js +7 -7
  48. package/dist/integration/index.cjs +9 -108
  49. package/dist/integration/index.d.cts +1 -1
  50. package/dist/integration/index.d.ts +1 -1
  51. package/dist/llm/index.d.cts +1 -1
  52. package/dist/llm/index.d.ts +1 -1
  53. package/dist/logger/index.cjs +33 -161
  54. package/dist/mastra/index.cjs +3 -1755
  55. package/dist/mastra/index.d.cts +1 -1
  56. package/dist/mastra/index.d.ts +1 -1
  57. package/dist/mastra/index.js +1 -1
  58. package/dist/memory/index.cjs +4 -2050
  59. package/dist/memory/index.d.cts +1 -1
  60. package/dist/memory/index.d.ts +1 -1
  61. package/dist/memory/index.js +1 -1
  62. package/dist/relevance/index.cjs +10 -2201
  63. package/dist/relevance/index.d.cts +19 -2
  64. package/dist/relevance/index.d.ts +19 -2
  65. package/dist/relevance/index.js +1 -1
  66. package/dist/storage/index.cjs +29 -367
  67. package/dist/storage/index.d.cts +1 -1
  68. package/dist/storage/index.d.ts +1 -1
  69. package/dist/storage/libsql/index.cjs +9 -798
  70. package/dist/storage/libsql/index.d.cts +1 -1
  71. package/dist/storage/libsql/index.d.ts +1 -1
  72. package/dist/telemetry/index.cjs +21 -408
  73. package/dist/telemetry/index.d.cts +1 -1
  74. package/dist/telemetry/index.d.ts +1 -1
  75. package/dist/tools/index.cjs +11 -22
  76. package/dist/tools/index.d.cts +3 -3
  77. package/dist/tools/index.d.ts +3 -3
  78. package/dist/tts/index.cjs +3 -328
  79. package/dist/utils.cjs +41 -350
  80. package/dist/utils.d.cts +3 -3
  81. package/dist/utils.d.ts +3 -3
  82. package/dist/utils.js +1 -1
  83. package/dist/vector/filter/index.cjs +7 -189
  84. package/dist/vector/index.cjs +5 -172
  85. package/dist/vector/libsql/index.cjs +9 -1047
  86. package/dist/voice/index.cjs +8 -306
  87. package/dist/workflows/index.cjs +65 -1936
  88. package/dist/workflows/index.d.cts +4 -3
  89. package/dist/workflows/index.d.ts +4 -3
  90. package/dist/workflows/index.js +1 -1
  91. package/package.json +27 -27
@@ -1,1052 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
4
- var client = require('@libsql/client');
5
- var stream = require('stream');
6
- var pino = require('pino');
7
- var pretty = require('pino-pretty');
3
+ var chunkWOMOGDGR_cjs = require('../../chunk-WOMOGDGR.cjs');
8
4
 
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
5
 
11
- var pino__default = /*#__PURE__*/_interopDefault(pino);
12
- var pretty__default = /*#__PURE__*/_interopDefault(pretty);
13
6
 
14
- // src/vector/libsql/index.ts
15
- var RegisteredLogger = {
16
- LLM: "LLM"};
17
- var LogLevel = {
18
- INFO: "info"};
19
- var Logger = class {
20
- logger;
21
- transports;
22
- constructor(options = {}) {
23
- this.transports = options.transports || {};
24
- const transportsAry = Object.entries(this.transports);
25
- this.logger = pino__default.default(
26
- {
27
- name: options.name || "app",
28
- level: options.level || LogLevel.INFO,
29
- formatters: {
30
- level: (label) => {
31
- return {
32
- level: label
33
- };
34
- }
35
- }
36
- },
37
- options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? pretty__default.default({
38
- colorize: true,
39
- levelFirst: true,
40
- ignore: "pid,hostname",
41
- colorizeObjects: true,
42
- translateTime: "SYS:standard",
43
- singleLine: false
44
- }) : pino__default.default.multistream([
45
- ...transportsAry.map(([_, transport]) => ({
46
- stream: transport,
47
- level: options.level || LogLevel.INFO
48
- })),
49
- {
50
- stream: pretty__default.default({
51
- colorize: true,
52
- levelFirst: true,
53
- ignore: "pid,hostname",
54
- colorizeObjects: true,
55
- translateTime: "SYS:standard",
56
- singleLine: false
57
- }),
58
- level: options.level || LogLevel.INFO
59
- }
60
- ])
61
- );
62
- }
63
- debug(message, args = {}) {
64
- this.logger.debug(args, message);
65
- }
66
- info(message, args = {}) {
67
- this.logger.info(args, message);
68
- }
69
- warn(message, args = {}) {
70
- this.logger.warn(args, message);
71
- }
72
- error(message, args = {}) {
73
- this.logger.error(args, message);
74
- }
75
- // Stream creation for process output handling
76
- createStream() {
77
- return new stream.Transform({
78
- transform: (chunk, _encoding, callback) => {
79
- const line = chunk.toString().trim();
80
- if (line) {
81
- this.info(line);
82
- }
83
- callback(null, chunk);
84
- }
85
- });
86
- }
87
- async getLogs(transportId) {
88
- if (!transportId || !this.transports[transportId]) {
89
- return [];
90
- }
91
- return this.transports[transportId].getLogs();
92
- }
93
- async getLogsByRunId({ runId, transportId }) {
94
- return this.transports[transportId]?.getLogsByRunId({ runId });
95
- }
96
- };
97
- function createLogger(options) {
98
- return new Logger(options);
99
- }
100
-
101
- // src/base.ts
102
- var MastraBase = class {
103
- component = RegisteredLogger.LLM;
104
- logger;
105
- name;
106
- telemetry;
107
- constructor({ component, name }) {
108
- this.component = component || RegisteredLogger.LLM;
109
- this.name = name;
110
- this.logger = createLogger({ name: `${this.component} - ${this.name}` });
111
- }
112
- /**
113
- * Set the logger for the agent
114
- * @param logger
115
- */
116
- __setLogger(logger) {
117
- this.logger = logger;
118
- this.logger.debug(`Logger updated [component=${this.component}] [name=${this.name}]`);
119
- }
120
- /**
121
- * Set the telemetry for the
122
- * @param telemetry
123
- */
124
- __setTelemetry(telemetry) {
125
- this.telemetry = telemetry;
126
- this.logger.debug(`Telemetry updated [component=${this.component}] [tracer=${this.telemetry.tracer}]`);
127
- }
128
- /**
129
- * Get the telemetry on the vector
130
- * @returns telemetry
131
- */
132
- __getTelemetry() {
133
- return this.telemetry;
134
- }
135
- /*
136
- get experimental_telemetry config
137
- */
138
- get experimental_telemetry() {
139
- return this.telemetry ? {
140
- // tracer: this.telemetry.tracer,
141
- tracer: this.telemetry.getBaggageTracer(),
142
- isEnabled: !!this.telemetry.tracer
143
- } : void 0;
144
- }
145
- };
146
-
147
- // src/vector/vector.ts
148
- var MastraVector = class extends MastraBase {
149
- constructor() {
150
- super({ name: "MastraVector", component: "VECTOR" });
151
- }
152
- baseKeys = {
153
- query: ["queryVector", "topK", "filter", "includeVector"],
154
- upsert: ["vectors", "metadata", "ids"],
155
- createIndex: ["dimension", "metric"]
156
- };
157
- normalizeArgs(method, [first, ...rest], extendedKeys = []) {
158
- if (typeof first === "object") {
159
- return first;
160
- }
161
- this.logger.warn(
162
- `Deprecation Warning: Passing individual arguments to ${method}() is deprecated. Please use an object parameter instead.`
163
- );
164
- const baseKeys = this.baseKeys[method] || [];
165
- const paramKeys = [...baseKeys, ...extendedKeys].slice(0, rest.length);
166
- return {
167
- indexName: first,
168
- ...Object.fromEntries(paramKeys.map((key, i) => [key, rest[i]]))
169
- };
170
- }
171
- async updateIndexById(_indexName, _id, _update) {
172
- throw new Error("updateIndexById is not implemented yet");
173
- }
174
- async deleteIndexById(_indexName, _id) {
175
- throw new Error("deleteById is not implemented yet");
176
- }
177
- };
178
-
179
- // src/vector/filter/base.ts
180
- var BaseFilterTranslator = class _BaseFilterTranslator {
181
- /**
182
- * Operator type checks
183
- */
184
- isOperator(key) {
185
- return key.startsWith("$");
186
- }
187
- static BASIC_OPERATORS = ["$eq", "$ne"];
188
- static NUMERIC_OPERATORS = ["$gt", "$gte", "$lt", "$lte"];
189
- static ARRAY_OPERATORS = ["$in", "$nin", "$all", "$elemMatch"];
190
- static LOGICAL_OPERATORS = ["$and", "$or", "$not", "$nor"];
191
- static ELEMENT_OPERATORS = ["$exists"];
192
- static REGEX_OPERATORS = ["$regex", "$options"];
193
- static DEFAULT_OPERATORS = {
194
- logical: _BaseFilterTranslator.LOGICAL_OPERATORS,
195
- basic: _BaseFilterTranslator.BASIC_OPERATORS,
196
- numeric: _BaseFilterTranslator.NUMERIC_OPERATORS,
197
- array: _BaseFilterTranslator.ARRAY_OPERATORS,
198
- element: _BaseFilterTranslator.ELEMENT_OPERATORS,
199
- regex: _BaseFilterTranslator.REGEX_OPERATORS
200
- };
201
- isLogicalOperator(key) {
202
- return _BaseFilterTranslator.DEFAULT_OPERATORS.logical.includes(key);
203
- }
204
- isBasicOperator(key) {
205
- return _BaseFilterTranslator.DEFAULT_OPERATORS.basic.includes(key);
206
- }
207
- isNumericOperator(key) {
208
- return _BaseFilterTranslator.DEFAULT_OPERATORS.numeric.includes(key);
209
- }
210
- isArrayOperator(key) {
211
- return _BaseFilterTranslator.DEFAULT_OPERATORS.array.includes(key);
212
- }
213
- isElementOperator(key) {
214
- return _BaseFilterTranslator.DEFAULT_OPERATORS.element.includes(key);
215
- }
216
- isRegexOperator(key) {
217
- return _BaseFilterTranslator.DEFAULT_OPERATORS.regex.includes(key);
218
- }
219
- isFieldOperator(key) {
220
- return this.isOperator(key) && !this.isLogicalOperator(key);
221
- }
222
- isCustomOperator(key) {
223
- const support = this.getSupportedOperators();
224
- return support.custom?.includes(key) ?? false;
225
- }
226
- getSupportedOperators() {
227
- return _BaseFilterTranslator.DEFAULT_OPERATORS;
228
- }
229
- isValidOperator(key) {
230
- const support = this.getSupportedOperators();
231
- const allSupported = Object.values(support).flat();
232
- return allSupported.includes(key);
233
- }
234
- /**
235
- * Value normalization for comparison operators
236
- */
237
- normalizeComparisonValue(value) {
238
- if (value instanceof Date) {
239
- return value.toISOString();
240
- }
241
- if (typeof value === "number" && Object.is(value, -0)) {
242
- return 0;
243
- }
244
- return value;
245
- }
246
- /**
247
- * Helper method to simulate $all operator using $and + $eq when needed.
248
- * Some vector stores don't support $all natively.
249
- */
250
- simulateAllOperator(field, values) {
251
- return {
252
- $and: values.map((value) => ({
253
- [field]: { $in: [this.normalizeComparisonValue(value)] }
254
- }))
255
- };
256
- }
257
- /**
258
- * Utility functions for type checking
259
- */
260
- isPrimitive(value) {
261
- return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
262
- }
263
- isRegex(value) {
264
- return value instanceof RegExp;
265
- }
266
- isEmpty(obj) {
267
- return obj === null || obj === void 0 || typeof obj === "object" && Object.keys(obj).length === 0;
268
- }
269
- static ErrorMessages = {
270
- UNSUPPORTED_OPERATOR: (op) => `Unsupported operator: ${op}`,
271
- INVALID_LOGICAL_OPERATOR_LOCATION: (op, path) => `Logical operator ${op} cannot be used at field level: ${path}`,
272
- NOT_REQUIRES_OBJECT: `$not operator requires an object`,
273
- NOT_CANNOT_BE_EMPTY: `$not operator cannot be empty`,
274
- INVALID_LOGICAL_OPERATOR_CONTENT: (path) => `Logical operators must contain field conditions, not direct operators: ${path}`,
275
- INVALID_TOP_LEVEL_OPERATOR: (op) => `Invalid top-level operator: ${op}`,
276
- ELEM_MATCH_REQUIRES_OBJECT: `$elemMatch requires an object with conditions`
277
- };
278
- /**
279
- * Helper to handle array value normalization consistently
280
- */
281
- normalizeArrayValues(values) {
282
- return values.map((value) => this.normalizeComparisonValue(value));
283
- }
284
- validateFilter(filter) {
285
- const validation = this.validateFilterSupport(filter);
286
- if (!validation.supported) {
287
- throw new Error(validation.messages.join(", "));
288
- }
289
- }
290
- /**
291
- * Validates if a filter structure is supported by the specific vector DB
292
- * and returns detailed validation information.
293
- */
294
- validateFilterSupport(node, path = "") {
295
- const messages = [];
296
- if (this.isPrimitive(node) || this.isEmpty(node)) {
297
- return { supported: true, messages: [] };
298
- }
299
- if (Array.isArray(node)) {
300
- const arrayResults = node.map((item) => this.validateFilterSupport(item, path));
301
- const arrayMessages = arrayResults.flatMap((r) => r.messages);
302
- return {
303
- supported: arrayResults.every((r) => r.supported),
304
- messages: arrayMessages
305
- };
306
- }
307
- const nodeObj = node;
308
- let isSupported = true;
309
- for (const [key, value] of Object.entries(nodeObj)) {
310
- const newPath = path ? `${path}.${key}` : key;
311
- if (this.isOperator(key)) {
312
- if (!this.isValidOperator(key)) {
313
- isSupported = false;
314
- messages.push(_BaseFilterTranslator.ErrorMessages.UNSUPPORTED_OPERATOR(key));
315
- continue;
316
- }
317
- if (!path && !this.isLogicalOperator(key)) {
318
- isSupported = false;
319
- messages.push(_BaseFilterTranslator.ErrorMessages.INVALID_TOP_LEVEL_OPERATOR(key));
320
- continue;
321
- }
322
- if (key === "$elemMatch" && (typeof value !== "object" || Array.isArray(value))) {
323
- isSupported = false;
324
- messages.push(_BaseFilterTranslator.ErrorMessages.ELEM_MATCH_REQUIRES_OBJECT);
325
- continue;
326
- }
327
- if (this.isLogicalOperator(key)) {
328
- if (key === "$not") {
329
- if (Array.isArray(value) || typeof value !== "object") {
330
- isSupported = false;
331
- messages.push(_BaseFilterTranslator.ErrorMessages.NOT_REQUIRES_OBJECT);
332
- continue;
333
- }
334
- if (this.isEmpty(value)) {
335
- isSupported = false;
336
- messages.push(_BaseFilterTranslator.ErrorMessages.NOT_CANNOT_BE_EMPTY);
337
- continue;
338
- }
339
- continue;
340
- }
341
- if (path && !this.isLogicalOperator(path.split(".").pop())) {
342
- isSupported = false;
343
- messages.push(_BaseFilterTranslator.ErrorMessages.INVALID_LOGICAL_OPERATOR_LOCATION(key, newPath));
344
- continue;
345
- }
346
- if (Array.isArray(value)) {
347
- const hasDirectOperators = value.some(
348
- (item) => typeof item === "object" && Object.keys(item).length === 1 && this.isFieldOperator(Object.keys(item)[0])
349
- );
350
- if (hasDirectOperators) {
351
- isSupported = false;
352
- messages.push(_BaseFilterTranslator.ErrorMessages.INVALID_LOGICAL_OPERATOR_CONTENT(newPath));
353
- continue;
354
- }
355
- }
356
- }
357
- }
358
- const nestedValidation = this.validateFilterSupport(value, newPath);
359
- if (!nestedValidation.supported) {
360
- isSupported = false;
361
- messages.push(...nestedValidation.messages);
362
- }
363
- }
364
- return { supported: isSupported, messages };
365
- }
366
- };
367
-
368
- // src/vector/libsql/filter.ts
369
- var LibSQLFilterTranslator = class extends BaseFilterTranslator {
370
- getSupportedOperators() {
371
- return {
372
- ...BaseFilterTranslator.DEFAULT_OPERATORS,
373
- regex: [],
374
- custom: ["$contains", "$size"]
375
- };
376
- }
377
- translate(filter) {
378
- if (this.isEmpty(filter)) {
379
- return filter;
380
- }
381
- this.validateFilter(filter);
382
- return this.translateNode(filter);
383
- }
384
- translateNode(node, currentPath = "") {
385
- if (this.isRegex(node)) {
386
- throw new Error("Direct regex pattern format is not supported in LibSQL");
387
- }
388
- const withPath = (result2) => currentPath ? { [currentPath]: result2 } : result2;
389
- if (this.isPrimitive(node)) {
390
- return withPath({ $eq: this.normalizeComparisonValue(node) });
391
- }
392
- if (Array.isArray(node)) {
393
- return withPath({ $in: this.normalizeArrayValues(node) });
394
- }
395
- const entries = Object.entries(node);
396
- const result = {};
397
- for (const [key, value] of entries) {
398
- const newPath = currentPath ? `${currentPath}.${key}` : key;
399
- if (this.isLogicalOperator(key)) {
400
- result[key] = Array.isArray(value) ? value.map((filter) => this.translateNode(filter)) : this.translateNode(value);
401
- } else if (this.isOperator(key)) {
402
- if (this.isArrayOperator(key) && !Array.isArray(value) && key !== "$elemMatch") {
403
- result[key] = [value];
404
- } else if (this.isBasicOperator(key) && Array.isArray(value)) {
405
- result[key] = JSON.stringify(value);
406
- } else {
407
- result[key] = value;
408
- }
409
- } else if (typeof value === "object" && value !== null) {
410
- const hasOperators = Object.keys(value).some((k) => this.isOperator(k));
411
- if (hasOperators) {
412
- result[newPath] = this.translateNode(value);
413
- } else {
414
- Object.assign(result, this.translateNode(value, newPath));
415
- }
416
- } else {
417
- result[newPath] = this.translateNode(value);
418
- }
419
- }
420
- return result;
421
- }
422
- // TODO: Look more into regex support for LibSQL
423
- // private translateRegexPattern(pattern: string, options: string = ''): any {
424
- // if (!options) return { $regex: pattern };
425
- // const flags = options
426
- // .split('')
427
- // .filter(f => 'imsux'.includes(f))
428
- // .join('');
429
- // return {
430
- // $regex: pattern,
431
- // $options: flags,
432
- // };
433
- // }
434
- };
435
-
436
- // src/vector/libsql/sql-builder.ts
437
- var createBasicOperator = (symbol) => {
438
- return (key) => ({
439
- sql: `CASE
440
- WHEN ? IS NULL THEN json_extract(metadata, '$."${handleKey(key)}"') IS ${symbol === "=" ? "" : "NOT"} NULL
441
- ELSE json_extract(metadata, '$."${handleKey(key)}"') ${symbol} ?
442
- END`,
443
- needsValue: true,
444
- transformValue: (value) => {
445
- return [value, value];
446
- }
447
- });
448
- };
449
- var createNumericOperator = (symbol) => {
450
- return (key) => ({
451
- sql: `CAST(json_extract(metadata, '$."${handleKey(key)}"') AS NUMERIC) ${symbol} ?`,
452
- needsValue: true
453
- });
454
- };
455
- var validateJsonArray = (key) => `json_valid(json_extract(metadata, '$."${handleKey(key)}"'))
456
- AND json_type(json_extract(metadata, '$."${handleKey(key)}"')) = 'array'`;
457
- var FILTER_OPERATORS = {
458
- $eq: createBasicOperator("="),
459
- $ne: createBasicOperator("!="),
460
- $gt: createNumericOperator(">"),
461
- $gte: createNumericOperator(">="),
462
- $lt: createNumericOperator("<"),
463
- $lte: createNumericOperator("<="),
464
- // Array Operators
465
- $in: (key, value) => ({
466
- sql: `json_extract(metadata, '$."${handleKey(key)}"') IN (${value.map(() => "?").join(",")})`,
467
- needsValue: true
468
- }),
469
- $nin: (key, value) => ({
470
- sql: `json_extract(metadata, '$."${handleKey(key)}"') NOT IN (${value.map(() => "?").join(",")})`,
471
- needsValue: true
472
- }),
473
- $all: (key) => ({
474
- sql: `json_extract(metadata, '$."${handleKey(key)}"') = ?`,
475
- needsValue: true,
476
- transformValue: (value) => {
477
- const arrayValue = Array.isArray(value) ? value : [value];
478
- if (arrayValue.length === 0) {
479
- return {
480
- sql: "1 = 0",
481
- values: []
482
- };
483
- }
484
- return {
485
- sql: `(
486
- CASE
487
- WHEN ${validateJsonArray(key)} THEN
488
- NOT EXISTS (
489
- SELECT value
490
- FROM json_each(?)
491
- WHERE value NOT IN (
492
- SELECT value
493
- FROM json_each(json_extract(metadata, '$."${handleKey(key)}"'))
494
- )
495
- )
496
- ELSE FALSE
497
- END
498
- )`,
499
- values: [JSON.stringify(arrayValue)]
500
- };
501
- }
502
- }),
503
- $elemMatch: (key) => ({
504
- sql: `json_extract(metadata, '$."${handleKey(key)}"') = ?`,
505
- needsValue: true,
506
- transformValue: (value) => {
507
- if (typeof value !== "object" || Array.isArray(value)) {
508
- throw new Error("$elemMatch requires an object with conditions");
509
- }
510
- const conditions = Object.entries(value).map(([field, fieldValue]) => {
511
- if (field.startsWith("$")) {
512
- const { sql, values } = buildCondition("elem.value", { [field]: fieldValue });
513
- const pattern = /json_extract\(metadata, '\$\."[^"]*"(\."[^"]*")*'\)/g;
514
- const elemSql = sql.replace(pattern, "elem.value");
515
- return { sql: elemSql, values };
516
- } else if (typeof fieldValue === "object" && !Array.isArray(fieldValue)) {
517
- const { sql, values } = buildCondition(field, fieldValue);
518
- const pattern = /json_extract\(metadata, '\$\."[^"]*"(\."[^"]*")*'\)/g;
519
- const elemSql = sql.replace(pattern, `json_extract(elem.value, '$."${field}"')`);
520
- return { sql: elemSql, values };
521
- } else {
522
- return {
523
- sql: `json_extract(elem.value, '$."${field}"') = ?`,
524
- values: [fieldValue]
525
- };
526
- }
527
- });
528
- return {
529
- sql: `(
530
- CASE
531
- WHEN ${validateJsonArray(key)} THEN
532
- EXISTS (
533
- SELECT 1
534
- FROM json_each(json_extract(metadata, '$."${handleKey(key)}"')) as elem
535
- WHERE ${conditions.map((c) => c.sql).join(" AND ")}
536
- )
537
- ELSE FALSE
538
- END
539
- )`,
540
- values: conditions.flatMap((c) => c.values)
541
- };
542
- }
543
- }),
544
- // Element Operators
545
- $exists: (key) => ({
546
- sql: `json_extract(metadata, '$."${handleKey(key)}"') IS NOT NULL`,
547
- needsValue: false
548
- }),
549
- // Logical Operators
550
- $and: (key) => ({
551
- sql: `(${key})`,
552
- needsValue: false
553
- }),
554
- $or: (key) => ({
555
- sql: `(${key})`,
556
- needsValue: false
557
- }),
558
- $not: (key) => ({ sql: `NOT (${key})`, needsValue: false }),
559
- $nor: (key) => ({
560
- sql: `NOT (${key})`,
561
- needsValue: false
562
- }),
563
- $size: (key, paramIndex) => ({
564
- sql: `(
565
- CASE
566
- WHEN json_type(json_extract(metadata, '$."${handleKey(key)}"')) = 'array' THEN
567
- json_array_length(json_extract(metadata, '$."${handleKey(key)}"')) = $${paramIndex}
568
- ELSE FALSE
569
- END
570
- )`,
571
- needsValue: true
572
- }),
573
- // /**
574
- // * Regex Operators
575
- // * Supports case insensitive and multiline
576
- // */
577
- // $regex: (key: string): FilterOperator => ({
578
- // sql: `json_extract(metadata, '$."${handleKey(key)}"') = ?`,
579
- // needsValue: true,
580
- // transformValue: (value: any) => {
581
- // const pattern = typeof value === 'object' ? value.$regex : value;
582
- // const options = typeof value === 'object' ? value.$options || '' : '';
583
- // let sql = `json_extract(metadata, '$."${handleKey(key)}"')`;
584
- // // Handle multiline
585
- // // if (options.includes('m')) {
586
- // // sql = `REPLACE(${sql}, CHAR(10), '\n')`;
587
- // // }
588
- // // let finalPattern = pattern;
589
- // // if (options) {
590
- // // finalPattern = `(\\?${options})${pattern}`;
591
- // // }
592
- // // // Handle case insensitivity
593
- // // if (options.includes('i')) {
594
- // // sql = `LOWER(${sql}) REGEXP LOWER(?)`;
595
- // // } else {
596
- // // sql = `${sql} REGEXP ?`;
597
- // // }
598
- // if (options.includes('m')) {
599
- // sql = `EXISTS (
600
- // SELECT 1
601
- // FROM json_each(
602
- // json_array(
603
- // ${sql},
604
- // REPLACE(${sql}, CHAR(10), CHAR(13))
605
- // )
606
- // ) as lines
607
- // WHERE lines.value REGEXP ?
608
- // )`;
609
- // } else {
610
- // sql = `${sql} REGEXP ?`;
611
- // }
612
- // // Handle case insensitivity
613
- // if (options.includes('i')) {
614
- // sql = sql.replace('REGEXP ?', 'REGEXP LOWER(?)');
615
- // sql = sql.replace('value REGEXP', 'LOWER(value) REGEXP');
616
- // }
617
- // // Handle extended - allows whitespace and comments in pattern
618
- // if (options.includes('x')) {
619
- // // Remove whitespace and comments from pattern
620
- // const cleanPattern = pattern.replace(/\s+|#.*$/gm, '');
621
- // return {
622
- // sql,
623
- // values: [cleanPattern],
624
- // };
625
- // }
626
- // return {
627
- // sql,
628
- // values: [pattern],
629
- // };
630
- // },
631
- // }),
632
- $contains: (key) => ({
633
- sql: `json_extract(metadata, '$."${handleKey(key)}"') = ?`,
634
- needsValue: true,
635
- transformValue: (value) => {
636
- if (Array.isArray(value)) {
637
- return {
638
- sql: `(
639
- SELECT ${validateJsonArray(key)}
640
- AND EXISTS (
641
- SELECT 1
642
- FROM json_each(json_extract(metadata, '$."${handleKey(key)}"')) as m
643
- WHERE m.value IN (SELECT value FROM json_each(?))
644
- )
645
- )`,
646
- values: [JSON.stringify(value)]
647
- };
648
- }
649
- if (value && typeof value === "object") {
650
- let traverse2 = function(obj, path = []) {
651
- for (const [k, v] of Object.entries(obj)) {
652
- const currentPath = [...path, k];
653
- if (v && typeof v === "object" && !Array.isArray(v)) {
654
- traverse2(v, currentPath);
655
- } else {
656
- paths.push(currentPath.join("."));
657
- values.push(v);
658
- }
659
- }
660
- };
661
- const paths = [];
662
- const values = [];
663
- traverse2(value);
664
- return {
665
- sql: `(${paths.map((path) => `json_extract(metadata, '$."${handleKey(key)}"."${path}"') = ?`).join(" AND ")})`,
666
- values
667
- };
668
- }
669
- return value;
670
- }
671
- })
672
- };
673
- var handleKey = (key) => {
674
- return key.replace(/\./g, '"."');
675
- };
676
- function buildFilterQuery(filter) {
677
- if (!filter) {
678
- return { sql: "", values: [] };
679
- }
680
- const values = [];
681
- const conditions = Object.entries(filter).map(([key, value]) => {
682
- const condition = buildCondition(key, value);
683
- values.push(...condition.values);
684
- return condition.sql;
685
- }).join(" AND ");
686
- return {
687
- sql: conditions ? `WHERE ${conditions}` : "",
688
- values
689
- };
690
- }
691
- function buildCondition(key, value, parentPath) {
692
- if (["$and", "$or", "$not", "$nor"].includes(key)) {
693
- return handleLogicalOperator(key, value);
694
- }
695
- if (!value || typeof value !== "object") {
696
- return {
697
- sql: `json_extract(metadata, '$."${key.replace(/\./g, '"."')}"') = ?`,
698
- values: [value]
699
- };
700
- }
701
- return handleOperator(key, value);
702
- }
703
- function handleLogicalOperator(key, value, parentPath) {
704
- if (!value || value.length === 0) {
705
- switch (key) {
706
- case "$and":
707
- case "$nor":
708
- return { sql: "true", values: [] };
709
- case "$or":
710
- return { sql: "false", values: [] };
711
- case "$not":
712
- throw new Error("$not operator cannot be empty");
713
- default:
714
- return { sql: "true", values: [] };
715
- }
716
- }
717
- if (key === "$not") {
718
- const entries = Object.entries(value);
719
- const conditions2 = entries.map(([fieldKey, fieldValue]) => buildCondition(fieldKey, fieldValue));
720
- return {
721
- sql: `NOT (${conditions2.map((c) => c.sql).join(" AND ")})`,
722
- values: conditions2.flatMap((c) => c.values)
723
- };
724
- }
725
- const values = [];
726
- const joinOperator = key === "$or" || key === "$nor" ? "OR" : "AND";
727
- const conditions = Array.isArray(value) ? value.map((f) => {
728
- const entries = Object.entries(f);
729
- return entries.map(([k, v]) => buildCondition(k, v));
730
- }) : [buildCondition(key, value)];
731
- const joined = conditions.flat().map((c) => {
732
- values.push(...c.values);
733
- return c.sql;
734
- }).join(` ${joinOperator} `);
735
- return {
736
- sql: key === "$nor" ? `NOT (${joined})` : `(${joined})`,
737
- values
738
- };
739
- }
740
- function handleOperator(key, value) {
741
- if (typeof value === "object" && !Array.isArray(value)) {
742
- const entries = Object.entries(value);
743
- const results = entries.map(
744
- ([operator2, operatorValue2]) => operator2 === "$not" ? {
745
- sql: `NOT (${Object.entries(operatorValue2).map(([op, val]) => processOperator(key, op, val).sql).join(" AND ")})`,
746
- values: Object.entries(operatorValue2).flatMap(
747
- ([op, val]) => processOperator(key, op, val).values
748
- )
749
- } : processOperator(key, operator2, operatorValue2)
750
- );
751
- return {
752
- sql: `(${results.map((r) => r.sql).join(" AND ")})`,
753
- values: results.flatMap((r) => r.values)
754
- };
755
- }
756
- const [[operator, operatorValue] = []] = Object.entries(value);
757
- return processOperator(key, operator, operatorValue);
758
- }
759
- var processOperator = (key, operator, operatorValue) => {
760
- if (!operator.startsWith("$") || !FILTER_OPERATORS[operator]) {
761
- throw new Error(`Invalid operator: ${operator}`);
762
- }
763
- const operatorFn = FILTER_OPERATORS[operator];
764
- const operatorResult = operatorFn(key, operatorValue);
765
- if (!operatorResult.needsValue) {
766
- return { sql: operatorResult.sql, values: [] };
767
- }
768
- const transformed = operatorResult.transformValue ? operatorResult.transformValue(operatorValue) : operatorValue;
769
- if (transformed && typeof transformed === "object" && "sql" in transformed) {
770
- return transformed;
771
- }
772
- return {
773
- sql: operatorResult.sql,
774
- values: Array.isArray(transformed) ? transformed : [transformed]
775
- };
776
- };
777
-
778
- // src/vector/libsql/index.ts
779
- var LibSQLVector = class extends MastraVector {
780
- turso;
781
- constructor({
782
- connectionUrl,
783
- authToken,
784
- syncUrl,
785
- syncInterval
786
- }) {
787
- super();
788
- this.turso = client.createClient({
789
- url: this.rewriteDbUrl(connectionUrl),
790
- syncUrl,
791
- authToken,
792
- syncInterval
793
- });
794
- }
795
- // If we're in the .mastra/output directory, use the dir outside .mastra dir
796
- // reason we need to do this is libsql relative file paths are based on cwd, not current file path
797
- // since mastra dev sets cwd to .mastra/output this means running an agent directly vs running with mastra dev
798
- // will put db files in different locations, leading to an inconsistent experience between the two.
799
- // Ex: with `file:ex.db`
800
- // 1. `mastra dev`: ${cwd}/.mastra/output/ex.db
801
- // 2. `tsx src/index.ts`: ${cwd}/ex.db
802
- // so if we're in .mastra/output we need to rewrite the file url to be relative to the project root dir
803
- // or the experience will be inconsistent
804
- // this means `file:` urls are always relative to project root
805
- // TODO: can we make this easier via bundling? https://github.com/mastra-ai/mastra/pull/2783#pullrequestreview-2662444241
806
- rewriteDbUrl(url) {
807
- if (url.startsWith("file:")) {
808
- const pathPart = url.slice("file:".length);
809
- if (path.isAbsolute(pathPart)) {
810
- return url;
811
- }
812
- const cwd = process.cwd();
813
- if (cwd.includes(".mastra") && (cwd.endsWith(`output`) || cwd.endsWith(`output/`) || cwd.endsWith(`output\\`))) {
814
- const baseDir = path.join(cwd, `..`, `..`);
815
- const fullPath = path.resolve(baseDir, pathPart);
816
- this.logger.debug(
817
- `Initializing LibSQL db with url ${url} with relative file path from inside .mastra/output directory. Rewriting relative file url to "file:${fullPath}". This ensures it's outside the .mastra/output directory.`
818
- );
819
- return `file:${fullPath}`;
820
- }
821
- }
822
- return url;
823
- }
824
- transformFilter(filter) {
825
- const translator = new LibSQLFilterTranslator();
826
- return translator.translate(filter);
827
- }
828
- async query(...args) {
829
- const params = this.normalizeArgs("query", args, ["minScore"]);
830
- try {
831
- const { indexName, queryVector, topK = 10, filter, includeVector = false, minScore = 0 } = params;
832
- const vectorStr = `[${queryVector.join(",")}]`;
833
- const translatedFilter = this.transformFilter(filter);
834
- const { sql: filterQuery, values: filterValues } = buildFilterQuery(translatedFilter);
835
- filterValues.push(minScore);
836
- const query = `
837
- WITH vector_scores AS (
838
- SELECT
839
- vector_id as id,
840
- (1-vector_distance_cos(embedding, '${vectorStr}')) as score,
841
- metadata
842
- ${includeVector ? ", vector_extract(embedding) as embedding" : ""}
843
- FROM ${indexName}
844
- ${filterQuery}
845
- )
846
- SELECT *
847
- FROM vector_scores
848
- WHERE score > ?
849
- ORDER BY score DESC
850
- LIMIT ${topK}`;
851
- const result = await this.turso.execute({
852
- sql: query,
853
- args: filterValues
854
- });
855
- return result.rows.map(({ id, score, metadata, embedding }) => ({
856
- id,
857
- score,
858
- metadata: JSON.parse(metadata ?? "{}"),
859
- ...includeVector && embedding && { vector: JSON.parse(embedding) }
860
- }));
861
- } finally {
862
- }
863
- }
864
- async upsert(...args) {
865
- const params = this.normalizeArgs("upsert", args);
866
- const { indexName, vectors, metadata, ids } = params;
867
- const tx = await this.turso.transaction("write");
868
- try {
869
- const vectorIds = ids || vectors.map(() => crypto.randomUUID());
870
- for (let i = 0; i < vectors.length; i++) {
871
- const query = `
872
- INSERT INTO ${indexName} (vector_id, embedding, metadata)
873
- VALUES (?, vector32(?), ?)
874
- ON CONFLICT(vector_id) DO UPDATE SET
875
- embedding = vector32(?),
876
- metadata = ?
877
- `;
878
- await tx.execute({
879
- sql: query,
880
- // @ts-ignore
881
- args: [
882
- vectorIds[i],
883
- JSON.stringify(vectors[i]),
884
- JSON.stringify(metadata?.[i] || {}),
885
- JSON.stringify(vectors[i]),
886
- JSON.stringify(metadata?.[i] || {})
887
- ]
888
- });
889
- }
890
- await tx.commit();
891
- return vectorIds;
892
- } catch (error) {
893
- await tx.rollback();
894
- throw error;
895
- }
896
- }
897
- async createIndex(...args) {
898
- const params = this.normalizeArgs("createIndex", args);
899
- const { indexName, dimension } = params;
900
- try {
901
- if (!indexName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) {
902
- throw new Error("Invalid index name format");
903
- }
904
- if (!Number.isInteger(dimension) || dimension <= 0) {
905
- throw new Error("Dimension must be a positive integer");
906
- }
907
- await this.turso.execute({
908
- sql: `
909
- CREATE TABLE IF NOT EXISTS ${indexName} (
910
- id SERIAL PRIMARY KEY,
911
- vector_id TEXT UNIQUE NOT NULL,
912
- embedding F32_BLOB(${dimension}),
913
- metadata TEXT DEFAULT '{}'
914
- );
915
- `,
916
- args: []
917
- });
918
- await this.turso.execute({
919
- sql: `
920
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
921
- ON ${indexName} (libsql_vector_idx(embedding))
922
- `,
923
- args: []
924
- });
925
- } catch (error) {
926
- console.error("Failed to create vector table:", error);
927
- throw error;
928
- } finally {
929
- }
930
- }
931
- async deleteIndex(indexName) {
932
- try {
933
- await this.turso.execute({
934
- sql: `DROP TABLE IF EXISTS ${indexName}`,
935
- args: []
936
- });
937
- } catch (error) {
938
- console.error("Failed to delete vector table:", error);
939
- throw new Error(`Failed to delete vector table: ${error.message}`);
940
- } finally {
941
- }
942
- }
943
- async listIndexes() {
944
- try {
945
- const vectorTablesQuery = `
946
- SELECT name FROM sqlite_master
947
- WHERE type='table'
948
- AND sql LIKE '%F32_BLOB%';
949
- `;
950
- const result = await this.turso.execute({
951
- sql: vectorTablesQuery,
952
- args: []
953
- });
954
- return result.rows.map((row) => row.name);
955
- } catch (error) {
956
- throw new Error(`Failed to list vector tables: ${error.message}`);
957
- }
958
- }
959
- async describeIndex(indexName) {
960
- try {
961
- const tableInfoQuery = `
962
- SELECT sql
963
- FROM sqlite_master
964
- WHERE type='table'
965
- AND name = ?;
966
- `;
967
- const tableInfo = await this.turso.execute({
968
- sql: tableInfoQuery,
969
- args: [indexName]
970
- });
971
- if (!tableInfo.rows[0]?.sql) {
972
- throw new Error(`Table ${indexName} not found`);
973
- }
974
- const dimension = parseInt(tableInfo.rows[0].sql.match(/F32_BLOB\((\d+)\)/)?.[1] || "0");
975
- const countQuery = `
976
- SELECT COUNT(*) as count
977
- FROM ${indexName};
978
- `;
979
- const countResult = await this.turso.execute({
980
- sql: countQuery,
981
- args: []
982
- });
983
- const metric = "cosine";
984
- return {
985
- dimension,
986
- count: countResult?.rows?.[0]?.count ?? 0,
987
- metric
988
- };
989
- } catch (e) {
990
- throw new Error(`Failed to describe vector table: ${e.message}`);
991
- }
992
- }
993
- /**
994
- * Updates an index entry by its ID with the provided vector and/or metadata.
995
- *
996
- * @param indexName - The name of the index to update.
997
- * @param id - The ID of the index entry to update.
998
- * @param update - An object containing the vector and/or metadata to update.
999
- * @param update.vector - An optional array of numbers representing the new vector.
1000
- * @param update.metadata - An optional record containing the new metadata.
1001
- * @returns A promise that resolves when the update is complete.
1002
- * @throws Will throw an error if no updates are provided or if the update operation fails.
1003
- */
1004
- async updateIndexById(indexName, id, update) {
1005
- try {
1006
- const updates = [];
1007
- const args = [];
1008
- if (update.vector) {
1009
- updates.push("embedding = vector32(?)");
1010
- args.push(JSON.stringify(update.vector));
1011
- }
1012
- if (update.metadata) {
1013
- updates.push("metadata = ?");
1014
- args.push(JSON.stringify(update.metadata));
1015
- }
1016
- if (updates.length === 0) {
1017
- throw new Error("No updates provided");
1018
- }
1019
- args.push(id);
1020
- const query = `
1021
- UPDATE ${indexName}
1022
- SET ${updates.join(", ")}
1023
- WHERE vector_id = ?;
1024
- `;
1025
- await this.turso.execute({
1026
- sql: query,
1027
- args
1028
- });
1029
- } catch (error) {
1030
- throw new Error(`Failed to update index by id: ${id} for index: ${indexName}: ${error.message}`);
1031
- }
1032
- }
1033
- async deleteIndexById(indexName, id) {
1034
- try {
1035
- await this.turso.execute({
1036
- sql: `DELETE FROM ${indexName} WHERE vector_id = ?`,
1037
- args: [id]
1038
- });
1039
- } catch (error) {
1040
- throw new Error(`Failed to delete index by id: ${id} for index: ${indexName}: ${error.message}`);
1041
- }
1042
- }
1043
- async truncateIndex(indexName) {
1044
- await this.turso.execute({
1045
- sql: `DELETE FROM ${indexName}`,
1046
- args: []
1047
- });
1048
- }
1049
- };
1050
-
1051
- exports.DefaultVectorDB = LibSQLVector;
1052
- exports.LibSQLVector = LibSQLVector;
7
+ Object.defineProperty(exports, "DefaultVectorDB", {
8
+ enumerable: true,
9
+ get: function () { return chunkWOMOGDGR_cjs.LibSQLVector; }
10
+ });
11
+ Object.defineProperty(exports, "LibSQLVector", {
12
+ enumerable: true,
13
+ get: function () { return chunkWOMOGDGR_cjs.LibSQLVector; }
14
+ });