@mastra/libsql 1.29.0-alpha.1 → 1.29.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.
Files changed (39) hide show
  1. package/dist/_types/@internal_core@0.1.4/dist/knowledge-compat/index.d.ts +9 -4
  2. package/dist/index.cjs +216 -30
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +216 -30
  5. package/dist/index.js.map +1 -1
  6. package/dist/storage/domains/knowledge/index.d.ts +6 -0
  7. package/dist/storage/domains/knowledge/index.d.ts.map +1 -1
  8. package/dist/storage/domains/knowledge/pages.d.ts +24 -12
  9. package/dist/storage/domains/knowledge/pages.d.ts.map +1 -1
  10. package/package.json +8 -8
  11. package/dist/docs/SKILL.md +0 -54
  12. package/dist/docs/assets/SOURCE_MAP.json +0 -6
  13. package/dist/docs/references/docs-agents-human-in-the-loop.md +0 -773
  14. package/dist/docs/references/docs-agents-networks.md +0 -186
  15. package/dist/docs/references/docs-deployment-workers.md +0 -404
  16. package/dist/docs/references/docs-memory-memory-processors.md +0 -442
  17. package/dist/docs/references/docs-memory-message-history.md +0 -424
  18. package/dist/docs/references/docs-memory-multi-user-threads.md +0 -210
  19. package/dist/docs/references/docs-memory-overview.md +0 -305
  20. package/dist/docs/references/docs-memory-semantic-recall.md +0 -485
  21. package/dist/docs/references/docs-memory-working-memory.md +0 -450
  22. package/dist/docs/references/docs-signals-overview.md +0 -94
  23. package/dist/docs/references/docs-storage.md +0 -224
  24. package/dist/docs/references/docs-studio-editor.md +0 -372
  25. package/dist/docs/references/docs-workflows-snapshots.md +0 -244
  26. package/dist/docs/references/integrations-channels-github.md +0 -156
  27. package/dist/docs/references/integrations-databases-dynamodb.md +0 -286
  28. package/dist/docs/references/integrations-databases-libsql.md +0 -161
  29. package/dist/docs/references/integrations-vectors-libsql.md +0 -325
  30. package/dist/docs/references/reference-ai-sdk-overview.md +0 -144
  31. package/dist/docs/references/reference-core-getMemory.md +0 -53
  32. package/dist/docs/references/reference-core-listMemory.md +0 -59
  33. package/dist/docs/references/reference-core-mastra-class.md +0 -177
  34. package/dist/docs/references/reference-file-based-agents-memory.md +0 -60
  35. package/dist/docs/references/reference-file-based-agents-storage.md +0 -32
  36. package/dist/docs/references/reference-memory-memory-class.md +0 -237
  37. package/dist/docs/references/reference-rag-retrieval.md +0 -672
  38. package/dist/docs/references/reference-storage-composite.md +0 -433
  39. package/dist/docs/references/reference-storage-retention.md +0 -310
@@ -318,6 +318,7 @@ export interface KnowledgePagesCore {
318
318
  MAX_KNOWLEDGE_MOVE_PAGES: number;
319
319
  MAX_KNOWLEDGE_PAGE_DEPTH: number;
320
320
  MAX_KNOWLEDGE_PAGE_LIST_LIMIT: number;
321
+ MAX_KNOWLEDGE_PAGE_LINKS: number;
321
322
  KnowledgeMoveTooLargeError: new (pageId: string, pages: number) => Error;
322
323
  KnowledgePageDepthError: new (pageId: string) => Error;
323
324
  KnowledgePageHasChildrenError: new (pageId: string) => Error;
@@ -325,15 +326,19 @@ export interface KnowledgePagesCore {
325
326
  }
326
327
  /** Loads core's page-store runtime once, after checking core advertises `knowledge-pages`. */
327
328
  export declare function createKnowledgePagesCoreLoader(features: ReadonlySet<string>, loadStorageModule: () => Promise<unknown>): () => Promise<KnowledgePagesCore>;
329
+ /** Most words one keyword search uses; every word adds a substring check per page in each store. */
330
+ export declare const KNOWLEDGE_SEARCH_MAX_WORDS = 16;
328
331
  /**
329
- * Keyword-search words: the query split on whitespace, lowercased, deduplicated. A hit needs at
330
- * least one of them (as a case-insensitive substring); an empty list means the search returns nothing.
332
+ * Keyword-search words: the query split on whitespace, lowercased, deduplicated, keeping the first
333
+ * {@link KNOWLEDGE_SEARCH_MAX_WORDS}. A hit needs at least one of them (as a case-insensitive
334
+ * substring); an empty list means the search returns nothing.
331
335
  */
332
336
  export declare function knowledgeSearchWords(query: string): string[];
333
337
  /**
334
338
  * Points one matched search word earns on a page, by the best field it appears in: name, then
335
- * description, then body. Pages rank by how many query words they match first; these points only
336
- * break ties between pages that match the same number of words.
339
+ * description, then body. A page whose name contains the whole query ranks first; below that, pages
340
+ * rank by how many query words they match, and these points only break ties between pages that
341
+ * match the same number of words.
337
342
  */
338
343
  export declare const KNOWLEDGE_SEARCH_WEIGHTS: {
339
344
  readonly name: 3;
package/dist/index.cjs CHANGED
@@ -6650,7 +6650,8 @@ const KNOWLEDGE_PAGES_CORE_FUNCTIONS = [
6650
6650
  const KNOWLEDGE_PAGES_CORE_NUMBERS = [
6651
6651
  "MAX_KNOWLEDGE_MOVE_PAGES",
6652
6652
  "MAX_KNOWLEDGE_PAGE_DEPTH",
6653
- "MAX_KNOWLEDGE_PAGE_LIST_LIMIT"
6653
+ "MAX_KNOWLEDGE_PAGE_LIST_LIMIT",
6654
+ "MAX_KNOWLEDGE_PAGE_LINKS"
6654
6655
  ];
6655
6656
  function resolveKnowledgePagesCore(storageModule) {
6656
6657
  const module = typeof storageModule === "object" && storageModule !== null ? storageModule : {};
@@ -6671,16 +6672,18 @@ function createKnowledgePagesCoreLoader(features, loadStorageModule) {
6671
6672
  };
6672
6673
  }
6673
6674
  /**
6674
- * Keyword-search words: the query split on whitespace, lowercased, deduplicated. A hit needs at
6675
- * least one of them (as a case-insensitive substring); an empty list means the search returns nothing.
6675
+ * Keyword-search words: the query split on whitespace, lowercased, deduplicated, keeping the first
6676
+ * {@link KNOWLEDGE_SEARCH_MAX_WORDS}. A hit needs at least one of them (as a case-insensitive
6677
+ * substring); an empty list means the search returns nothing.
6676
6678
  */
6677
6679
  function knowledgeSearchWords(query) {
6678
- return [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))];
6680
+ return [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))].slice(0, 16);
6679
6681
  }
6680
6682
  /**
6681
6683
  * Points one matched search word earns on a page, by the best field it appears in: name, then
6682
- * description, then body. Pages rank by how many query words they match first; these points only
6683
- * break ties between pages that match the same number of words.
6684
+ * description, then body. A page whose name contains the whole query ranks first; below that, pages
6685
+ * rank by how many query words they match, and these points only break ties between pages that
6686
+ * match the same number of words.
6684
6687
  */
6685
6688
  const KNOWLEDGE_SEARCH_WEIGHTS = {
6686
6689
  name: 3,
@@ -6706,9 +6709,37 @@ const KNOWLEDGE_PAGE_TABLES = {
6706
6709
  mentions: "mastra_knowledge_mentions",
6707
6710
  pins: "mastra_knowledge_pins",
6708
6711
  pinAudiences: "mastra_knowledge_pin_audiences",
6709
- activity: "mastra_knowledge_activity"
6712
+ activity: "mastra_knowledge_activity",
6713
+ links: "mastra_knowledge_page_links"
6710
6714
  };
6711
6715
  const T = KNOWLEDGE_PAGE_TABLES;
6716
+ function pinsTableDDL(name) {
6717
+ return `CREATE TABLE IF NOT EXISTS "${name}" (
6718
+ id TEXT PRIMARY KEY,
6719
+ pageId TEXT NOT NULL,
6720
+ kind TEXT NOT NULL DEFAULT 'page',
6721
+ depth INTEGER,
6722
+ audience TEXT NOT NULL,
6723
+ createdBy TEXT NOT NULL,
6724
+ createdAt TEXT NOT NULL,
6725
+ updatedAt TEXT NOT NULL,
6726
+ UNIQUE (pageId, kind)
6727
+ )`;
6728
+ }
6729
+ /**
6730
+ * Pins tables from before pin kinds kept one pin per page (`pageId UNIQUE`). SQLite can't drop that
6731
+ * constraint in place, so the table is rebuilt with every existing pin as a `page` pin. Run after
6732
+ * {@link KNOWLEDGE_PAGE_DDL}, in the same transaction; a no-op once `kind` exists.
6733
+ */
6734
+ async function upgradeKnowledgePinKinds(tx) {
6735
+ if ((await tx.execute(`SELECT name FROM pragma_table_info('${T.pins}')`)).rows.some((row) => String(row.name) === "kind")) return;
6736
+ const next = `${T.pins}_kinds`;
6737
+ await tx.execute(`DROP TABLE IF EXISTS "${next}"`);
6738
+ await tx.execute(pinsTableDDL(next));
6739
+ await tx.execute(`INSERT INTO "${next}" (id, pageId, kind, audience, createdBy, createdAt, updatedAt) SELECT id, pageId, 'page', audience, createdBy, createdAt, updatedAt FROM "${T.pins}"`);
6740
+ await tx.execute(`DROP TABLE "${T.pins}"`);
6741
+ await tx.execute(`ALTER TABLE "${next}" RENAME TO "${T.pins}"`);
6742
+ }
6712
6743
  /** DDL for the schema-4 page tables, in creation order. Every statement is idempotent. */
6713
6744
  const KNOWLEDGE_PAGE_DDL = [
6714
6745
  `CREATE TABLE IF NOT EXISTS "mastra_knowledge_access_state" (
@@ -6772,14 +6803,7 @@ const KNOWLEDGE_PAGE_DDL = [
6772
6803
  PRIMARY KEY (noteId, pageId)
6773
6804
  )`,
6774
6805
  `CREATE INDEX IF NOT EXISTS idx_kmentions_page ON "${T.mentions}" (pageId)`,
6775
- `CREATE TABLE IF NOT EXISTS "${T.pins}" (
6776
- id TEXT PRIMARY KEY,
6777
- pageId TEXT NOT NULL UNIQUE,
6778
- audience TEXT NOT NULL,
6779
- createdBy TEXT NOT NULL,
6780
- createdAt TEXT NOT NULL,
6781
- updatedAt TEXT NOT NULL
6782
- )`,
6806
+ pinsTableDDL(T.pins),
6783
6807
  `CREATE TABLE IF NOT EXISTS "${T.pinAudiences}" (
6784
6808
  pinId TEXT NOT NULL,
6785
6809
  audience TEXT NOT NULL,
@@ -6796,7 +6820,16 @@ const KNOWLEDGE_PAGE_DDL = [
6796
6820
  provenance TEXT NOT NULL,
6797
6821
  createdAt TEXT NOT NULL
6798
6822
  )`,
6799
- `CREATE INDEX IF NOT EXISTS idx_kactivity_page ON "${T.activity}" (pageId, id DESC)`
6823
+ `CREATE INDEX IF NOT EXISTS idx_kactivity_page ON "${T.activity}" (pageId, id DESC)`,
6824
+ `CREATE TABLE IF NOT EXISTS "${T.links}" (
6825
+ fromPageId TEXT NOT NULL,
6826
+ ref TEXT NOT NULL,
6827
+ toPageId TEXT,
6828
+ count INTEGER NOT NULL,
6829
+ PRIMARY KEY (fromPageId, ref)
6830
+ ) WITHOUT ROWID`,
6831
+ `CREATE INDEX IF NOT EXISTS idx_klinks_to ON "${T.links}" (toPageId) WHERE toPageId IS NOT NULL`,
6832
+ `CREATE INDEX IF NOT EXISTS idx_klinks_ref ON "${T.links}" (ref) WHERE toPageId IS NULL`
6800
6833
  ];
6801
6834
  function str(value) {
6802
6835
  return value === null || value === void 0 ? void 0 : String(value);
@@ -6851,6 +6884,8 @@ function toPin(row) {
6851
6884
  return {
6852
6885
  id: String(row.id),
6853
6886
  pageId: String(row.pageId),
6887
+ kind: String(row.kind),
6888
+ ...row.depth !== null && row.depth !== void 0 ? { depth: Number(row.depth) } : {},
6854
6889
  audience: JSON.parse(String(row.audience)),
6855
6890
  createdBy: String(row.createdBy),
6856
6891
  createdAt: new Date(String(row.createdAt)),
@@ -6979,10 +7014,11 @@ var LibSQLKnowledgePages = class {
6979
7014
  this.#read = config.read;
6980
7015
  this.#transaction = config.transaction;
6981
7016
  }
6982
- /** Deletes every row from the page tables (scopes, pages, notes, pins, activity). */
7017
+ /** Deletes every row from the page tables (scopes, pages, notes, pins, activity, links). */
6983
7018
  async clearAll() {
6984
7019
  await this.#transaction(async (tx) => {
6985
7020
  for (const table of [
7021
+ T.links,
6986
7022
  T.activity,
6987
7023
  T.pinAudiences,
6988
7024
  T.pins,
@@ -7164,13 +7200,19 @@ var LibSQLKnowledgePages = class {
7164
7200
  const limit = limitOf(input.limit, core.MAX_KNOWLEDGE_PAGE_LIST_LIMIT);
7165
7201
  const cursor = decodeCursor(input.cursor, 2);
7166
7202
  const args = [input.parentId];
7203
+ let filter = "";
7204
+ if (input.read) {
7205
+ const readable = readableScopes(input.read);
7206
+ filter = ` AND id IN (${readable.sql})`;
7207
+ args.push(...readable.args);
7208
+ }
7167
7209
  let after = "";
7168
7210
  if (cursor) {
7169
7211
  after = ` AND (position > ? OR (position = ? AND id > ?))`;
7170
7212
  args.push(cursor[0], cursor[0], cursor[1]);
7171
7213
  }
7172
7214
  args.push(limit + 1);
7173
- const rows = await this.#query(this.#read, `SELECT * FROM "${T.pages}" WHERE isScope = 1 AND parentId IS ?${after} ORDER BY position, id LIMIT ?`, args);
7215
+ const rows = await this.#query(this.#read, `SELECT * FROM "${T.pages}" WHERE isScope = 1 AND parentId IS ?${filter}${after} ORDER BY position, id LIMIT ?`, args);
7174
7216
  return this.#pageOutput(rows, limit, (row) => [String(row.position), String(row.id)]);
7175
7217
  }
7176
7218
  #pageOutput(rows, limit, cursorOf) {
@@ -7455,9 +7497,8 @@ var LibSQLKnowledgePages = class {
7455
7497
  args: [input.sourceId]
7456
7498
  });
7457
7499
  const pins = await this.#query(tx, `SELECT * FROM "${T.pins}" WHERE pageId IN (?, ?)`, [input.sourceId, input.targetId]);
7458
- const sourcePin = pins.find((pin) => String(pin.pageId) === input.sourceId);
7459
- if (sourcePin) {
7460
- const targetPin = pins.find((pin) => String(pin.pageId) === input.targetId);
7500
+ for (const sourcePin of pins.filter((pin) => String(pin.pageId) === input.sourceId)) {
7501
+ const targetPin = pins.find((pin) => String(pin.pageId) === input.targetId && pin.kind === sourcePin.kind);
7461
7502
  const audience = JSON.parse(String(sourcePin.audience));
7462
7503
  if (targetPin) {
7463
7504
  const merged = [.../* @__PURE__ */ new Set([...JSON.parse(String(targetPin.audience)), ...audience])];
@@ -7557,6 +7598,15 @@ var LibSQLKnowledgePages = class {
7557
7598
  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);
7558
7599
  return this.#noteOutput(rows, limit);
7559
7600
  }
7601
+ async countChildScopes(input) {
7602
+ const ids = [...new Set(input.parentIds)];
7603
+ const counts = Object.fromEntries(ids.map((id) => [id, 0]));
7604
+ if (ids.length === 0) return counts;
7605
+ const readable = readableScopes(input.read);
7606
+ const rows = await this.#query(this.#read, `SELECT parentId, COUNT(*) AS total FROM "${T.pages}" WHERE parentId IN (SELECT value FROM json_each(?)) AND isScope = 1 AND id IN (${readable.sql}) GROUP BY parentId`, [jsonList(ids), ...readable.args]);
7607
+ for (const row of rows) counts[String(row.parentId)] = Number(row.total);
7608
+ return counts;
7609
+ }
7560
7610
  async countChildPages(input) {
7561
7611
  const ids = [...new Set(input.parentIds)];
7562
7612
  const counts = Object.fromEntries(ids.map((id) => [id, 0]));
@@ -7566,6 +7616,111 @@ var LibSQLKnowledgePages = class {
7566
7616
  for (const row of rows) counts[String(row.parentId)] = Number(row.total);
7567
7617
  return counts;
7568
7618
  }
7619
+ async replacePageBodyLinks(input) {
7620
+ await this.#transaction(async (tx) => {
7621
+ await tx.execute({
7622
+ sql: `DELETE FROM "${T.links}" WHERE fromPageId = ?`,
7623
+ args: [input.pageId]
7624
+ });
7625
+ if (input.links.length === 0) return;
7626
+ await tx.execute({
7627
+ sql: `INSERT INTO "${T.links}" (fromPageId, ref, toPageId, count) SELECT ?, json_extract(value, '$.ref'), json_extract(value, '$.toPageId'), json_extract(value, '$.count') FROM json_each(?)`,
7628
+ args: [input.pageId, JSON.stringify(input.links.map(({ ref, toPageId, count }) => ({
7629
+ ref,
7630
+ toPageId,
7631
+ count
7632
+ })))]
7633
+ });
7634
+ });
7635
+ }
7636
+ async listPageBodyLinkSources(input) {
7637
+ const refs = input.refs ?? [];
7638
+ const targets = input.toPageIds ?? [];
7639
+ if (refs.length === 0 && targets.length === 0) return [];
7640
+ return (await this.#query(this.#read, `SELECT DISTINCT fromPageId FROM "${T.links}" WHERE (toPageId IS NULL AND ref IN (SELECT value FROM json_each(?))) OR toPageId IN (SELECT value FROM json_each(?)) ORDER BY fromPageId`, [jsonList(refs), jsonList(targets)])).map((row) => String(row.fromPageId));
7641
+ }
7642
+ /**
7643
+ * Visible links touching `ids` (from them for `out`, to them for `in`): resolved, both ends live
7644
+ * and readable, not self-links; a note link also needs a visible live note. One row per
7645
+ * (from, to, kind), counts summed.
7646
+ */
7647
+ async #links(read, kinds, ids, direction) {
7648
+ const wanted = new Set(kinds ?? ["body", "note"]);
7649
+ const touches = (from, to) => {
7650
+ const parts = [];
7651
+ const args = [];
7652
+ if (direction !== "in") {
7653
+ parts.push(`${from} IN (SELECT value FROM json_each(?))`);
7654
+ args.push(jsonList(ids));
7655
+ }
7656
+ if (direction !== "out") {
7657
+ parts.push(`${to} IN (SELECT value FROM json_each(?))`);
7658
+ args.push(jsonList(ids));
7659
+ }
7660
+ return {
7661
+ sql: `(${parts.join(" OR ")})`,
7662
+ args
7663
+ };
7664
+ };
7665
+ const sources = [];
7666
+ const args = [];
7667
+ if (wanted.has("body")) {
7668
+ const near = touches("l.fromPageId", "l.toPageId");
7669
+ sources.push(`SELECT l.fromPageId AS fromPageId, l.toPageId AS toPageId, 'body' AS kind, l.count AS count FROM "${T.links}" l WHERE l.toPageId IS NOT NULL AND ${near.sql}`);
7670
+ args.push(...near.args);
7671
+ }
7672
+ if (wanted.has("note")) {
7673
+ const near = touches("n.pageId", "m.pageId");
7674
+ const visible = noteReadable("n", read);
7675
+ sources.push(`SELECT n.pageId AS fromPageId, m.pageId AS toPageId, 'note' AS kind, 1 AS count FROM "${T.mentions}" m JOIN "${T.notes}" n ON n.id = m.noteId WHERE n.deletedAt IS NULL AND ${near.sql} AND ${visible.sql}`);
7676
+ args.push(...near.args, ...visible.args);
7677
+ }
7678
+ if (sources.length === 0) return [];
7679
+ const fromReadable = pageReadable("fp", read);
7680
+ const toReadable = pageReadable("tp", read);
7681
+ return this.#query(this.#read, `SELECT e.fromPageId AS fromPageId, e.toPageId AS toPageId, e.kind AS kind, SUM(e.count) AS count
7682
+ FROM (${sources.join(" UNION ALL ")}) e
7683
+ JOIN "${T.pages}" fp ON fp.id = e.fromPageId AND fp.deletedAt IS NULL AND ${fromReadable.sql}
7684
+ JOIN "${T.pages}" tp ON tp.id = e.toPageId AND tp.deletedAt IS NULL AND ${toReadable.sql}
7685
+ WHERE e.fromPageId <> e.toPageId
7686
+ GROUP BY e.fromPageId, e.toPageId, e.kind
7687
+ ORDER BY e.fromPageId, e.toPageId, CASE e.kind WHEN 'body' THEN 0 ELSE 1 END`, [
7688
+ ...args,
7689
+ ...fromReadable.args,
7690
+ ...toReadable.args
7691
+ ]);
7692
+ }
7693
+ async countPageLinks(input) {
7694
+ const ids = [...new Set(input.pageIds)];
7695
+ const linked = new Map(ids.map((id) => [id, {
7696
+ in: /* @__PURE__ */ new Set(),
7697
+ out: /* @__PURE__ */ new Set()
7698
+ }]));
7699
+ if (ids.length === 0) return {};
7700
+ for (const row of await this.#links(input.read, input.kinds, ids, "both")) {
7701
+ const from = String(row.fromPageId);
7702
+ const to = String(row.toPageId);
7703
+ linked.get(from)?.out.add(to);
7704
+ linked.get(to)?.in.add(from);
7705
+ }
7706
+ return Object.fromEntries([...linked].map(([id, sets]) => [id, {
7707
+ in: sets.in.size,
7708
+ out: sets.out.size
7709
+ }]));
7710
+ }
7711
+ async listPageLinks(input) {
7712
+ const limit = input.limit ?? 1e3;
7713
+ if (!Number.isInteger(limit) || limit < 1) throw new RangeError("Knowledge link limit must be a positive integer");
7714
+ const ids = [...new Set(input.pageIds)];
7715
+ if (ids.length === 0) return [];
7716
+ const core = await loadPagesCore();
7717
+ return (await this.#links(input.read, input.kinds, ids, input.direction ?? "both")).slice(0, Math.min(limit, core.MAX_KNOWLEDGE_PAGE_LINKS)).map((row) => ({
7718
+ fromPageId: String(row.fromPageId),
7719
+ toPageId: String(row.toPageId),
7720
+ kind: row.kind === "note" ? "note" : "body",
7721
+ count: Number(row.count)
7722
+ }));
7723
+ }
7569
7724
  async countNotes(input) {
7570
7725
  const ids = [...new Set(input.pageIds)];
7571
7726
  const counts = Object.fromEntries(ids.map((id) => [id, 0]));
@@ -7827,17 +7982,21 @@ var LibSQLKnowledgePages = class {
7827
7982
  });
7828
7983
  }
7829
7984
  addPinAudience(input) {
7985
+ const kind = input.kind ?? "page";
7986
+ const depth = kind === "list" ? input.depth ?? 1 : null;
7830
7987
  return this.#transaction(async (tx) => {
7831
7988
  const page = await this.#livePage(tx, input.pageId);
7832
7989
  const now = (/* @__PURE__ */ new Date()).toISOString();
7833
- const existing = (await this.#query(tx, `SELECT * FROM "${T.pins}" WHERE pageId = ?`, [input.pageId]))[0];
7990
+ const existing = (await this.#query(tx, `SELECT * FROM "${T.pins}" WHERE pageId = ? AND kind = ?`, [input.pageId, kind]))[0];
7834
7991
  if (!existing) {
7835
7992
  const id = (0, _mastra_core_storage.createKnowledgeUlid)();
7836
7993
  await tx.execute({
7837
- sql: `INSERT INTO "${T.pins}" (id, pageId, audience, createdBy, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?)`,
7994
+ sql: `INSERT INTO "${T.pins}" (id, pageId, kind, depth, audience, createdBy, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
7838
7995
  args: [
7839
7996
  id,
7840
7997
  input.pageId,
7998
+ kind,
7999
+ depth,
7841
8000
  JSON.stringify([...new Set(input.audience)]),
7842
8001
  input.createdBy,
7843
8002
  now,
@@ -7854,11 +8013,13 @@ var LibSQLKnowledgePages = class {
7854
8013
  }
7855
8014
  const current = JSON.parse(String(existing.audience));
7856
8015
  const merged = [.../* @__PURE__ */ new Set([...current, ...input.audience])];
7857
- if (merged.length !== current.length) {
8016
+ const depthChanged = (existing.depth === null ? null : Number(existing.depth)) !== depth;
8017
+ if (merged.length !== current.length || depthChanged) {
7858
8018
  await tx.execute({
7859
- sql: `UPDATE "${T.pins}" SET audience = ?, updatedAt = ? WHERE id = ?`,
8019
+ sql: `UPDATE "${T.pins}" SET audience = ?, depth = ?, updatedAt = ? WHERE id = ?`,
7860
8020
  args: [
7861
8021
  JSON.stringify(merged),
8022
+ depth,
7862
8023
  now,
7863
8024
  String(existing.id)
7864
8025
  ]
@@ -7875,7 +8036,7 @@ var LibSQLKnowledgePages = class {
7875
8036
  }
7876
8037
  removePinAudience(input) {
7877
8038
  return this.#transaction(async (tx) => {
7878
- const existing = (await this.#query(tx, `SELECT * FROM "${T.pins}" WHERE pageId = ?`, [input.pageId]))[0];
8039
+ const existing = (await this.#query(tx, `SELECT * FROM "${T.pins}" WHERE pageId = ? AND kind = ?`, [input.pageId, input.kind ?? "page"]))[0];
7879
8040
  if (!existing) return null;
7880
8041
  const current = JSON.parse(String(existing.audience));
7881
8042
  const remove = new Set(input.audience);
@@ -7919,15 +8080,19 @@ var LibSQLKnowledgePages = class {
7919
8080
  filters += ` AND pin.id IN (SELECT pa.pinId FROM json_each(?) a JOIN "${T.pinAudiences}" pa ON pa.audience = a.value)`;
7920
8081
  args.push(jsonList(input.audience));
7921
8082
  }
8083
+ if (input.kind) {
8084
+ filters += ` AND pin.kind = ?`;
8085
+ args.push(input.kind);
8086
+ }
7922
8087
  if (input.pageIds) {
7923
8088
  filters += ` AND pin.pageId IN (SELECT value FROM json_each(?))`;
7924
8089
  args.push(jsonList(input.pageIds));
7925
8090
  }
7926
8091
  if (input.excludePageIds?.length) {
7927
- filters += ` AND pin.pageId NOT IN (SELECT value FROM json_each(?))`;
8092
+ filters += ` AND (pin.kind <> 'page' OR pin.pageId NOT IN (SELECT value FROM json_each(?)))`;
7928
8093
  args.push(jsonList(input.excludePageIds));
7929
8094
  }
7930
- if (input.withBody) filters += ` AND p.body IS NOT NULL AND trim(p.body, char(32, 9, 10, 11, 12, 13)) <> ''`;
8095
+ if (input.withBody) filters += ` AND (pin.kind <> 'page' OR (p.body IS NOT NULL AND trim(p.body, char(32, 9, 10, 11, 12, 13)) <> ''))`;
7931
8096
  const from = `FROM "${T.pins}" pin JOIN "${T.pages}" p ON p.id = pin.pageId WHERE p.deletedAt IS NULL AND ${readable.sql}${filters}`;
7932
8097
  let total;
7933
8098
  if (input.count) total = Number((await this.#query(this.#read, `SELECT COUNT(*) AS n ${from}`, args))[0].n);
@@ -7999,7 +8164,8 @@ var KnowledgeLibSQL = class extends _mastra_core_storage.KnowledgeStorage {
7999
8164
  contractVersion: 4,
8000
8165
  schemaVersion: 4,
8001
8166
  supportsSchemaInspection: true,
8002
- supportsExplicitReset: true
8167
+ supportsExplicitReset: true,
8168
+ supportsPinKinds: true
8003
8169
  };
8004
8170
  }
8005
8171
  async dangerouslyClearAll() {
@@ -8029,6 +8195,7 @@ var KnowledgeLibSQL = class extends _mastra_core_storage.KnowledgeStorage {
8029
8195
  const inspection = await this.#inspectPages(tx);
8030
8196
  if (inspection.status === "incompatible-reset-required") throw new _mastra_core_storage.KnowledgeSchemaResetRequiredError(inspection);
8031
8197
  for (const statement of KNOWLEDGE_PAGE_DDL) await tx.execute(statement);
8198
+ await upgradeKnowledgePinKinds(tx);
8032
8199
  await tx.execute({
8033
8200
  sql: `INSERT OR IGNORE INTO "${TABLE_KNOWLEDGE_PAGES_STATE}" (id, schemaVersion) VALUES ('knowledge', ?)`,
8034
8201
  args: [4]
@@ -8037,7 +8204,11 @@ var KnowledgeLibSQL = class extends _mastra_core_storage.KnowledgeStorage {
8037
8204
  }
8038
8205
  async dangerouslyReset() {
8039
8206
  await withClientWriteLock(this.#client, async () => {
8040
- await this.#client.batch([...KNOWLEDGE_RESETTABLE_TABLE_NAMES, KNOWLEDGE_PAGE_TABLES.pinAudiences].map((table) => ({
8207
+ await this.#client.batch([
8208
+ ...KNOWLEDGE_RESETTABLE_TABLE_NAMES,
8209
+ KNOWLEDGE_PAGE_TABLES.pinAudiences,
8210
+ KNOWLEDGE_PAGE_TABLES.links
8211
+ ].map((table) => ({
8041
8212
  sql: `DROP TABLE IF EXISTS "${table}"`,
8042
8213
  args: []
8043
8214
  })), "write");
@@ -8059,6 +8230,9 @@ var KnowledgeLibSQL = class extends _mastra_core_storage.KnowledgeStorage {
8059
8230
  listChildScopes(input) {
8060
8231
  return this.#pages.listChildScopes(input);
8061
8232
  }
8233
+ countChildScopes(input) {
8234
+ return this.#pages.countChildScopes(input);
8235
+ }
8062
8236
  getPage(input) {
8063
8237
  return this.#pages.getPage(input);
8064
8238
  }
@@ -8098,6 +8272,18 @@ var KnowledgeLibSQL = class extends _mastra_core_storage.KnowledgeStorage {
8098
8272
  countChildPages(input) {
8099
8273
  return this.#pages.countChildPages(input);
8100
8274
  }
8275
+ replacePageBodyLinks(input) {
8276
+ return this.#pages.replacePageBodyLinks(input);
8277
+ }
8278
+ listPageBodyLinkSources(input) {
8279
+ return this.#pages.listPageBodyLinkSources(input);
8280
+ }
8281
+ countPageLinks(input) {
8282
+ return this.#pages.countPageLinks(input);
8283
+ }
8284
+ listPageLinks(input) {
8285
+ return this.#pages.listPageLinks(input);
8286
+ }
8101
8287
  countNotes(input) {
8102
8288
  return this.#pages.countNotes(input);
8103
8289
  }