@mastra/mysql 0.16.0-alpha.0 → 0.16.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -851,6 +851,7 @@ var AgentsMySQL = class AgentsMySQL extends AgentsStorage {
851
851
  tableName: TABLE_AGENT_VERSIONS,
852
852
  schema: AGENT_VERSIONS_SCHEMA,
853
853
  ifNotExists: [
854
+ "modelList",
854
855
  "mcpClients",
855
856
  "requestContextSchema",
856
857
  "workspace",
@@ -1132,8 +1133,9 @@ var AgentsMySQL = class AgentsMySQL extends AgentsStorage {
1132
1133
  versionNumber: input.versionNumber,
1133
1134
  name: input.name ?? null,
1134
1135
  description: input.description ?? null,
1135
- instructions: this.serializeInstructions(input.instructions),
1136
- model: input.model,
1136
+ instructions: this.serializeInstructions(input.instructions ?? ""),
1137
+ model: input.model ?? {},
1138
+ modelList: input.modelList ?? null,
1137
1139
  tools: input.tools ?? null,
1138
1140
  defaultOptions: input.defaultOptions ?? null,
1139
1141
  workflows: input.workflows ?? null,
@@ -1350,6 +1352,7 @@ var AgentsMySQL = class AgentsMySQL extends AgentsStorage {
1350
1352
  description: row.description ?? void 0,
1351
1353
  instructions: this.deserializeInstructions(row.instructions),
1352
1354
  model: this.safeParseJSON(row.model),
1355
+ modelList: this.safeParseJSON(row.modelList),
1353
1356
  tools: this.safeParseJSON(row.tools),
1354
1357
  defaultOptions: this.safeParseJSON(row.defaultOptions),
1355
1358
  workflows: this.safeParseJSON(row.workflows),
@@ -3154,7 +3157,7 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
3154
3157
  let purgeMetadata = null;
3155
3158
  if (datasetId) {
3156
3159
  await connection.execute(`SELECT ${quoteIdentifier("id", "column name")} FROM ${formatTableName(TABLE_DATASETS)} WHERE ${quoteIdentifier("id", "column name")} = ? FOR UPDATE`, [datasetId]);
3157
- const [itemRows] = await connection.execute(`SELECT ${quoteIdentifier("metadata", "column name")} FROM ${formatTableName(TABLE_DATASET_ITEMS)} WHERE ${quoteIdentifier("id", "column name")} = ? AND ${quoteIdentifier("datasetId", "column name")} = ?`, [itemId, datasetId]);
3160
+ const [itemRows] = await connection.execute(`SELECT ${quoteIdentifier("metadata", "column name")} FROM ${formatTableName(TABLE_DATASET_ITEMS)} WHERE ${quoteIdentifier("id", "column name")} = ? AND ${quoteIdentifier("datasetId", "column name")} = ? FOR UPDATE`, [itemId, datasetId]);
3158
3161
  if (Array.isArray(itemRows)) {
3159
3162
  const purgedRow = itemRows.find((row) => parseJSON$2(row.metadata)?.__purged === true);
3160
3163
  purgeMetadata = purgedRow ? parseJSON$2(purgedRow.metadata) ?? null : null;
@@ -4318,13 +4321,23 @@ function createKnowledgePagesCoreLoader(features, loadStorageModule) {
4318
4321
  };
4319
4322
  }
4320
4323
  /**
4321
- * Keyword-search words: the query split on whitespace, lowercased, deduplicated. Every word must
4322
- * appear (as a case-insensitive substring) in a hit; an empty list means the search returns nothing.
4324
+ * Keyword-search words: the query split on whitespace, lowercased, deduplicated. A hit needs at
4325
+ * least one of them (as a case-insensitive substring); an empty list means the search returns nothing.
4323
4326
  */
4324
4327
  function knowledgeSearchWords(query) {
4325
4328
  return [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))];
4326
4329
  }
4327
4330
  /**
4331
+ * Points one matched search word earns on a page, by the best field it appears in: name, then
4332
+ * description, then body. Pages rank by how many query words they match first; these points only
4333
+ * break ties between pages that match the same number of words.
4334
+ */
4335
+ const KNOWLEDGE_SEARCH_WEIGHTS = {
4336
+ name: 3,
4337
+ description: 2,
4338
+ body: 1
4339
+ };
4340
+ /**
4328
4341
  * Why `key` can't be a Knowledge page key, or undefined when it can. Keys are one path segment:
4329
4342
  * non-empty, with no `/` (path separator), `#` (scope/path separator) or `%` (escape character).
4330
4343
  */
@@ -4555,6 +4568,13 @@ function isRetryableRace(error) {
4555
4568
  }
4556
4569
  return false;
4557
4570
  }
4571
+ function isLiveKeyClash(error) {
4572
+ for (let current = error; current && typeof current === "object"; current = current.cause) {
4573
+ const { code, errno, message } = current;
4574
+ if ((code === "ER_DUP_ENTRY" || errno === 1062) && String(message).includes("idx_kpages_live_key")) return true;
4575
+ }
4576
+ return false;
4577
+ }
4558
4578
  function escapeLike(value) {
4559
4579
  return value.replace(/[=%_]/g, (match) => `=${match}`);
4560
4580
  }
@@ -5008,7 +5028,12 @@ var MySQLKnowledgePages = class {
5008
5028
  }
5009
5029
  async createPage(input) {
5010
5030
  await assertKnowledgePageDescriptionWithinBound(input.description);
5011
- return this.#transaction((tx) => this.#insertPage(tx, input));
5031
+ try {
5032
+ return await this.#transaction((tx) => this.#insertPage(tx, input));
5033
+ } catch (error) {
5034
+ if (input.key !== void 0 && isLiveKeyClash(error)) throw new (await (loadPagesCore())).KnowledgePageKeyConflictError(input.key, input.parentId);
5035
+ throw error;
5036
+ }
5012
5037
  }
5013
5038
  async updatePage(input) {
5014
5039
  const core = await loadPagesCore();
@@ -5261,6 +5286,15 @@ var MySQLKnowledgePages = class {
5261
5286
  const rows = await this.#query(this.#read, `SELECT n.* FROM ${T.notes} n WHERE n.pageId = ?${input.includeDeleted ? "" : " AND n.deletedAt IS NULL"} AND ${readable.sql}${after} ORDER BY n.createdAt, n.id LIMIT ?`, args);
5262
5287
  return this.#noteOutput(rows, limit);
5263
5288
  }
5289
+ async countChildPages(input) {
5290
+ const ids = [...new Set(input.parentIds)];
5291
+ const counts = Object.fromEntries(ids.map((id) => [id, 0]));
5292
+ if (ids.length === 0) return counts;
5293
+ const readable = pageReadable("p", input.read);
5294
+ const rows = await this.#query(this.#read, `SELECT p.parentId AS parentId, COUNT(*) AS total FROM ${T.pages} p WHERE p.parentId IN ${JV} AND p.isScope = 0 AND p.deletedAt IS NULL AND ${readable.sql} GROUP BY p.parentId`, [jsonList(ids), ...readable.args]);
5295
+ for (const row of rows) counts[String(row.parentId)] = Number(row.total);
5296
+ return counts;
5297
+ }
5264
5298
  async countNotes(input) {
5265
5299
  const ids = [...new Set(input.pageIds)];
5266
5300
  const counts = Object.fromEntries(ids.map((id) => [id, 0]));
@@ -5432,18 +5466,22 @@ var MySQLKnowledgePages = class {
5432
5466
  const readable = pagesInReadableScopes("p", input.read);
5433
5467
  const scopeFilter = input.scopeIds ? ` AND p.scopeId IN ${JV}` : "";
5434
5468
  const scopeArgs = input.scopeIds ? [jsonList(input.scopeIds)] : [];
5435
- const pageMatch = words.map(() => `(LOWER(p.name) LIKE ? ESCAPE '=' OR LOWER(COALESCE(p.description, '')) LIKE ? ESCAPE '=' OR LOWER(COALESCE(p.body, '')) LIKE ? ESCAPE '=')`).join(" AND ");
5436
- const nameMatch = words.map(() => `LOWER(p.name) LIKE ? ESCAPE '='`).join(" AND ");
5437
- const hits = (await this.#query(this.#read, `SELECT p.* ${readable.sql} WHERE p.deletedAt IS NULL AND p.isScope = 0${scopeFilter} AND ${pageMatch} ORDER BY CASE WHEN LOCATE(?, p.canonicalName) > 0 THEN 0 WHEN ${nameMatch} THEN 1 ELSE 2 END, p.updatedAt DESC, p.id ASC LIMIT ?`, [
5469
+ const field = (column) => `LOWER(COALESCE(${column}, '')) LIKE ? ESCAPE '='`;
5470
+ const pageMatch = words.map(() => `(${field("p.name")} OR ${field("p.description")} OR ${field("p.body")})`).join(" OR ");
5471
+ const pageScore = words.map(() => `(CASE WHEN ${field("p.name")} THEN ${KNOWLEDGE_SEARCH_WEIGHTS.name} WHEN ${field("p.description")} THEN ${KNOWLEDGE_SEARCH_WEIGHTS.description} WHEN ${field("p.body")} THEN ${KNOWLEDGE_SEARCH_WEIGHTS.body} ELSE 0 END)`).join(" + ");
5472
+ const pageCount = words.map(() => `(CASE WHEN ${field("p.name")} OR ${field("p.description")} OR ${field("p.body")} THEN 1 ELSE 0 END)`).join(" + ");
5473
+ const triple = likes.flatMap((like) => [
5474
+ like,
5475
+ like,
5476
+ like
5477
+ ]);
5478
+ const hits = (await this.#query(this.#read, `SELECT p.* ${readable.sql} WHERE p.deletedAt IS NULL AND p.isScope = 0${scopeFilter} AND (${pageMatch}) ORDER BY CASE WHEN LOCATE(?, p.canonicalName) > 0 THEN 0 ELSE 1 END, (${pageCount}) DESC, (${pageScore}) DESC, p.updatedAt DESC, p.id ASC LIMIT ?`, [
5438
5479
  ...readable.args,
5439
5480
  ...scopeArgs,
5440
- ...likes.flatMap((like) => [
5441
- like,
5442
- like,
5443
- like
5444
- ]),
5481
+ ...triple,
5445
5482
  phrase,
5446
- ...likes,
5483
+ ...triple,
5484
+ ...triple,
5447
5485
  limit
5448
5486
  ])).map((row) => ({
5449
5487
  type: "page",
@@ -5451,11 +5489,12 @@ var MySQLKnowledgePages = class {
5451
5489
  }));
5452
5490
  if (hits.length >= limit) return hits;
5453
5491
  const noteVisible = noteReadable("n", input.read);
5454
- const noteMatch = words.map(() => `LOWER(n.text) LIKE ? ESCAPE '='`).join(" AND ");
5455
- const noteRows = await this.#query(this.#read, `SELECT n.* FROM ${T.notes} n JOIN ${T.pages} p ON p.id = n.pageId WHERE n.deletedAt IS NULL AND p.deletedAt IS NULL${scopeFilter} AND ${noteMatch} AND ${noteVisible.sql} ORDER BY n.updatedAt DESC, n.id DESC LIMIT ?`, [
5492
+ const noteHas = words.map(() => `LOWER(n.text) LIKE ? ESCAPE '='`);
5493
+ const noteRows = await this.#query(this.#read, `SELECT n.* FROM ${T.notes} n JOIN ${T.pages} p ON p.id = n.pageId WHERE n.deletedAt IS NULL AND p.deletedAt IS NULL${scopeFilter} AND (${noteHas.join(" OR ")}) AND ${noteVisible.sql} ORDER BY (${noteHas.map((has) => `(CASE WHEN ${has} THEN 1 ELSE 0 END)`).join(" + ")}) DESC, n.updatedAt DESC, n.id DESC LIMIT ?`, [
5456
5494
  ...scopeArgs,
5457
5495
  ...likes,
5458
5496
  ...noteVisible.args,
5497
+ ...likes,
5459
5498
  limit - hits.length
5460
5499
  ]);
5461
5500
  const notes = await this.#hydrateNotes(this.#read, noteRows);
@@ -5788,6 +5827,9 @@ var KnowledgeMySQL = class extends KnowledgeStorage {
5788
5827
  listNotes(input) {
5789
5828
  return this.#pages.listNotes(input);
5790
5829
  }
5830
+ countChildPages(input) {
5831
+ return this.#pages.countChildPages(input);
5832
+ }
5791
5833
  countNotes(input) {
5792
5834
  return this.#pages.countNotes(input);
5793
5835
  }