@mastra/pg 1.31.0-alpha.2 → 1.31.0-alpha.3

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.cjs CHANGED
@@ -35,8 +35,8 @@ let pg_connection_string = require("pg-connection-string");
35
35
  let _mastra_core_vector_filter = require("@mastra/core/vector/filter");
36
36
  let _mastra_core_base = require("@mastra/core/base");
37
37
  let crypto$1 = require("crypto");
38
- let _mastra_core_agent = require("@mastra/core/agent");
39
38
  let _mastra_core_features = require("@mastra/core/features");
39
+ let _mastra_core_agent = require("@mastra/core/agent");
40
40
  let _mastra_core_evals = require("@mastra/core/evals");
41
41
  let _mastra_core_storage_domains_skills = require("@mastra/core/storage/domains/skills");
42
42
  let util = require("util");
@@ -8301,18 +8301,650 @@ var FavoritesPG = class FavoritesPG extends _mastra_core_storage.FavoritesStorag
8301
8301
  }
8302
8302
  };
8303
8303
  //#endregion
8304
+ //#region ../../packages/_internal-core/dist/knowledge-compat/index.js
8305
+ const KNOWLEDGE_V2_CORE_FEATURE = "knowledge-v2";
8306
+ /** Hard cap on scope nodes returned by one `listScopeNodes` read. */
8307
+ const MAX_KNOWLEDGE_SCOPE_NODES = 1e3;
8308
+ function knowledgeScopeNodeFilterKey(input) {
8309
+ return JSON.stringify([
8310
+ input.withinAddress ?? null,
8311
+ input.addresses ? [...input.addresses].sort() : null,
8312
+ input.ids ? [...input.ids].sort() : null
8313
+ ]);
8314
+ }
8315
+ function createKnowledgeScopeNodeCursor(scope, input) {
8316
+ return encodeURIComponent(JSON.stringify({
8317
+ version: 1,
8318
+ type: "scope",
8319
+ name: scope.name,
8320
+ id: scope.id,
8321
+ filter: knowledgeScopeNodeFilterKey(input)
8322
+ }));
8323
+ }
8324
+ /** Validates the page size and cursor of a `listScopeNodes` query; throws on a cursor from a different query. */
8325
+ function parseListKnowledgeScopeNodesInput(input = {}) {
8326
+ const requested = Number.isFinite(input.limit) ? Math.trunc(input.limit) : MAX_KNOWLEDGE_SCOPE_NODES;
8327
+ const limit = Math.min(Math.max(requested, 1), MAX_KNOWLEDGE_SCOPE_NODES);
8328
+ if (!input.cursor) return {
8329
+ limit,
8330
+ after: null
8331
+ };
8332
+ let value;
8333
+ try {
8334
+ value = JSON.parse(decodeURIComponent(input.cursor));
8335
+ } catch {
8336
+ throw new Error("Invalid Knowledge scope node cursor.");
8337
+ }
8338
+ const parsed = value && typeof value === "object" ? value : {};
8339
+ if (parsed.version !== 1 || parsed.type !== "scope" || typeof parsed.name !== "string" || typeof parsed.id !== "string" || parsed.filter !== knowledgeScopeNodeFilterKey(input)) throw new Error("Knowledge scope node cursor does not match this query.");
8340
+ return {
8341
+ limit,
8342
+ after: {
8343
+ name: parsed.name,
8344
+ id: parsed.id
8345
+ }
8346
+ };
8347
+ }
8348
+ /** Builds a page from up to `limit + 1` name/id-ordered scope nodes. */
8349
+ function pageKnowledgeScopeNodes(rows, limit, input) {
8350
+ const scopes = rows.slice(0, limit);
8351
+ const last = scopes.at(-1);
8352
+ return {
8353
+ scopes,
8354
+ nextCursor: rows.length > limit && last ? createKnowledgeScopeNodeCursor(last, input) : null
8355
+ };
8356
+ }
8357
+ /** Clamps a requested member limit to 1–{@link MAX_KNOWLEDGE_SCOPE_MEMBERS_LIMIT}. */
8358
+ function knowledgeScopeMembersLimit(limit) {
8359
+ if (limit === void 0 || !Number.isFinite(limit)) return 500;
8360
+ return Math.min(Math.max(Math.trunc(limit), 1), 500);
8361
+ }
8362
+ /** Validates the page size and cursor of a `listScopeMembers` query; throws on a cursor from another scope. */
8363
+ function parseListKnowledgeScopeMembersInput(input) {
8364
+ const limit = knowledgeScopeMembersLimit(input.limit);
8365
+ if (!input.cursor) return {
8366
+ limit,
8367
+ after: null
8368
+ };
8369
+ let value;
8370
+ try {
8371
+ value = JSON.parse(decodeURIComponent(input.cursor));
8372
+ } catch {
8373
+ throw new Error("Invalid Knowledge scope member cursor.");
8374
+ }
8375
+ const parsed = value && typeof value === "object" ? value : {};
8376
+ const updatedAt = typeof parsed.updatedAt === "string" ? new Date(parsed.updatedAt) : /* @__PURE__ */ new Date(NaN);
8377
+ if (parsed.version !== 1 || parsed.type !== "scope-member" || parsed.scopeNodeId !== input.scopeNodeId || typeof parsed.name !== "string" || typeof parsed.id !== "string" || Number.isNaN(updatedAt.getTime())) throw new Error("Knowledge scope member cursor does not match this query.");
8378
+ return {
8379
+ limit,
8380
+ after: {
8381
+ updatedAt,
8382
+ name: parsed.name,
8383
+ id: parsed.id
8384
+ }
8385
+ };
8386
+ }
8387
+ /** Builds a page from up to `limit + 1` members in `listScopeMembers` order. */
8388
+ function pageKnowledgeScopeMembers(rows, limit, input) {
8389
+ const members = rows.slice(0, limit);
8390
+ const last = members.at(-1);
8391
+ const hasMore = rows.length > limit;
8392
+ return {
8393
+ members,
8394
+ hasMore,
8395
+ nextCursor: hasMore && last ? encodeURIComponent(JSON.stringify({
8396
+ version: 1,
8397
+ type: "scope-member",
8398
+ scopeNodeId: input.scopeNodeId,
8399
+ updatedAt: last.updatedAt.toISOString(),
8400
+ name: last.name,
8401
+ id: last.id
8402
+ })) : null
8403
+ };
8404
+ }
8405
+ const TABLE_KNOWLEDGE_NODES$1 = "mastra_knowledge_nodes";
8406
+ const TABLE_KNOWLEDGE_RECORDS$1 = "mastra_knowledge_records";
8407
+ const TABLE_KNOWLEDGE_MENTIONS$1 = "mastra_knowledge_mentions";
8408
+ const TABLE_KNOWLEDGE_ACTIVITY$1 = "mastra_knowledge_activity";
8409
+ const TABLE_KNOWLEDGE_SEMANTIC_OUTBOX$1 = "mastra_knowledge_semantic_outbox";
8410
+ const TABLE_KNOWLEDGE_NODE_SCOPES = "mastra_knowledge_node_scopes";
8411
+ const TABLE_KNOWLEDGE_RECORD_SCOPES = "mastra_knowledge_record_scopes";
8412
+ const TABLE_KNOWLEDGE_SCOPE_GRANTS = "mastra_knowledge_scope_grants";
8413
+ const TABLE_KNOWLEDGE_ACCESS_STATE = "mastra_knowledge_access_state";
8414
+ const TABLE_KNOWLEDGE_SCOPE_ADDRESSES = "mastra_knowledge_scope_addresses";
8415
+ const TABLE_KNOWLEDGE_NODE_ADDRESSES = "mastra_knowledge_node_addresses";
8416
+ const TABLE_KNOWLEDGE_IMPORT_STATE = "mastra_knowledge_import_state";
8417
+ const TABLE_KNOWLEDGE_IMPORT_RUNS = "mastra_knowledge_import_runs";
8418
+ const TABLE_KNOWLEDGE_PROPOSALS = "mastra_knowledge_proposals";
8419
+ const KNOWLEDGE_TABLE_NAMES = [
8420
+ TABLE_KNOWLEDGE_NODES$1,
8421
+ TABLE_KNOWLEDGE_RECORDS$1,
8422
+ TABLE_KNOWLEDGE_MENTIONS$1,
8423
+ TABLE_KNOWLEDGE_ACTIVITY$1,
8424
+ TABLE_KNOWLEDGE_SEMANTIC_OUTBOX$1,
8425
+ TABLE_KNOWLEDGE_NODE_SCOPES,
8426
+ TABLE_KNOWLEDGE_RECORD_SCOPES,
8427
+ TABLE_KNOWLEDGE_SCOPE_GRANTS,
8428
+ TABLE_KNOWLEDGE_ACCESS_STATE,
8429
+ TABLE_KNOWLEDGE_SCOPE_ADDRESSES,
8430
+ TABLE_KNOWLEDGE_NODE_ADDRESSES,
8431
+ TABLE_KNOWLEDGE_IMPORT_STATE,
8432
+ TABLE_KNOWLEDGE_IMPORT_RUNS,
8433
+ TABLE_KNOWLEDGE_PROPOSALS
8434
+ ];
8435
+ /** Knowledge v1 tables with no v2 equivalent; an explicit schema reset drops them. */
8436
+ const RETIRED_KNOWLEDGE_TABLE_NAMES = ["mastra_knowledge_cursors"];
8437
+ /** Tables and indexes published v1 adapters created for every app, whether or not it used Knowledge. */
8438
+ const PUBLISHED_KNOWLEDGE_V1_TABLE_NAMES = /* @__PURE__ */ new Set([
8439
+ TABLE_KNOWLEDGE_NODES$1,
8440
+ TABLE_KNOWLEDGE_RECORDS$1,
8441
+ TABLE_KNOWLEDGE_MENTIONS$1,
8442
+ TABLE_KNOWLEDGE_ACTIVITY$1,
8443
+ TABLE_KNOWLEDGE_SEMANTIC_OUTBOX$1,
8444
+ ...RETIRED_KNOWLEDGE_TABLE_NAMES
8445
+ ]);
8446
+ const PUBLISHED_KNOWLEDGE_V1_INDEX_NAMES = /* @__PURE__ */ new Set([
8447
+ "idx_knowledge_nodes_identity",
8448
+ "idx_knowledge_nodes_scope",
8449
+ "idx_knowledge_records_node_latest",
8450
+ "idx_knowledge_records_thread_latest",
8451
+ "idx_knowledge_mentions_record",
8452
+ "idx_knowledge_activity_latest",
8453
+ "idx_knowledge_outbox_idempotency",
8454
+ "idx_knowledge_outbox_claim"
8455
+ ]);
8456
+ const KNOWLEDGE_V2_NODES_SCHEMA = {
8457
+ id: {
8458
+ type: "text",
8459
+ nullable: false,
8460
+ primaryKey: true
8461
+ },
8462
+ name: {
8463
+ type: "text",
8464
+ nullable: false
8465
+ },
8466
+ kind: {
8467
+ type: "text",
8468
+ nullable: true
8469
+ },
8470
+ isScope: {
8471
+ type: "boolean",
8472
+ nullable: false
8473
+ },
8474
+ metadata: {
8475
+ type: "jsonb",
8476
+ nullable: true
8477
+ },
8478
+ version: {
8479
+ type: "integer",
8480
+ nullable: false
8481
+ },
8482
+ createdAt: {
8483
+ type: "timestamp",
8484
+ nullable: false
8485
+ },
8486
+ updatedAt: {
8487
+ type: "timestamp",
8488
+ nullable: false
8489
+ },
8490
+ deletedAt: {
8491
+ type: "timestamp",
8492
+ nullable: true
8493
+ },
8494
+ deletedBy: {
8495
+ type: "text",
8496
+ nullable: true
8497
+ },
8498
+ type: {
8499
+ type: "text",
8500
+ nullable: true
8501
+ },
8502
+ canonicalName: {
8503
+ type: "text",
8504
+ nullable: true
8505
+ },
8506
+ content: {
8507
+ type: "text",
8508
+ nullable: true
8509
+ },
8510
+ description: {
8511
+ type: "text",
8512
+ nullable: true
8513
+ },
8514
+ scope: {
8515
+ type: "jsonb",
8516
+ nullable: true
8517
+ },
8518
+ scopeKey: {
8519
+ type: "text",
8520
+ nullable: true
8521
+ },
8522
+ mergedInto: {
8523
+ type: "text",
8524
+ nullable: true
8525
+ }
8526
+ };
8527
+ const KNOWLEDGE_V2_RECORDS_SCHEMA = {
8528
+ id: {
8529
+ type: "text",
8530
+ nullable: false,
8531
+ primaryKey: true
8532
+ },
8533
+ node: {
8534
+ type: "text",
8535
+ nullable: false,
8536
+ references: {
8537
+ table: TABLE_KNOWLEDGE_NODES$1,
8538
+ column: "id"
8539
+ }
8540
+ },
8541
+ text: {
8542
+ type: "text",
8543
+ nullable: false
8544
+ },
8545
+ metadata: {
8546
+ type: "jsonb",
8547
+ nullable: true
8548
+ },
8549
+ version: {
8550
+ type: "integer",
8551
+ nullable: false
8552
+ },
8553
+ capturedAt: {
8554
+ type: "timestamp",
8555
+ nullable: false
8556
+ },
8557
+ updatedAt: {
8558
+ type: "timestamp",
8559
+ nullable: false
8560
+ },
8561
+ deletedAt: {
8562
+ type: "timestamp",
8563
+ nullable: true
8564
+ },
8565
+ deletedBy: {
8566
+ type: "text",
8567
+ nullable: true
8568
+ },
8569
+ scope: {
8570
+ type: "jsonb",
8571
+ nullable: true
8572
+ },
8573
+ scopeKey: {
8574
+ type: "text",
8575
+ nullable: true
8576
+ },
8577
+ sourceThreadId: {
8578
+ type: "text",
8579
+ nullable: true
8580
+ },
8581
+ when: {
8582
+ type: "timestamp",
8583
+ nullable: true
8584
+ }
8585
+ };
8586
+ const KNOWLEDGE_V2_MENTIONS_SCHEMA = {
8587
+ recordId: {
8588
+ type: "text",
8589
+ nullable: false,
8590
+ references: {
8591
+ table: TABLE_KNOWLEDGE_RECORDS$1,
8592
+ column: "id"
8593
+ }
8594
+ },
8595
+ targetNodeId: {
8596
+ type: "text",
8597
+ nullable: true,
8598
+ references: {
8599
+ table: TABLE_KNOWLEDGE_NODES$1,
8600
+ column: "id"
8601
+ }
8602
+ },
8603
+ sourceType: {
8604
+ type: "text",
8605
+ nullable: true
8606
+ },
8607
+ sourceId: {
8608
+ type: "text",
8609
+ nullable: true
8610
+ }
8611
+ };
8612
+ const KNOWLEDGE_NODE_SCOPES_SCHEMA = {
8613
+ nodeId: {
8614
+ type: "text",
8615
+ nullable: false,
8616
+ references: {
8617
+ table: TABLE_KNOWLEDGE_NODES$1,
8618
+ column: "id"
8619
+ }
8620
+ },
8621
+ scopeNodeId: {
8622
+ type: "text",
8623
+ nullable: false,
8624
+ references: {
8625
+ table: TABLE_KNOWLEDGE_NODES$1,
8626
+ column: "id"
8627
+ }
8628
+ },
8629
+ addedAt: {
8630
+ type: "timestamp",
8631
+ nullable: false
8632
+ }
8633
+ };
8634
+ const KNOWLEDGE_RECORD_SCOPES_SCHEMA = {
8635
+ recordId: {
8636
+ type: "text",
8637
+ nullable: false,
8638
+ references: {
8639
+ table: TABLE_KNOWLEDGE_RECORDS$1,
8640
+ column: "id"
8641
+ }
8642
+ },
8643
+ scopeNodeId: {
8644
+ type: "text",
8645
+ nullable: false,
8646
+ references: {
8647
+ table: TABLE_KNOWLEDGE_NODES$1,
8648
+ column: "id"
8649
+ }
8650
+ },
8651
+ addedAt: {
8652
+ type: "timestamp",
8653
+ nullable: false
8654
+ }
8655
+ };
8656
+ const KNOWLEDGE_SCOPE_GRANTS_SCHEMA = {
8657
+ scopeNodeId: {
8658
+ type: "text",
8659
+ nullable: false,
8660
+ references: {
8661
+ table: TABLE_KNOWLEDGE_NODES$1,
8662
+ column: "id"
8663
+ }
8664
+ },
8665
+ scopeRefId: {
8666
+ type: "text",
8667
+ nullable: false,
8668
+ references: {
8669
+ table: TABLE_KNOWLEDGE_NODES$1,
8670
+ column: "id"
8671
+ }
8672
+ },
8673
+ role: {
8674
+ type: "text",
8675
+ nullable: false
8676
+ },
8677
+ canSuggest: {
8678
+ type: "boolean",
8679
+ nullable: true
8680
+ }
8681
+ };
8682
+ const KNOWLEDGE_ACCESS_STATE_SCHEMA = {
8683
+ id: {
8684
+ type: "text",
8685
+ nullable: false,
8686
+ primaryKey: true
8687
+ },
8688
+ epoch: {
8689
+ type: "integer",
8690
+ nullable: false
8691
+ },
8692
+ schemaVersion: {
8693
+ type: "integer",
8694
+ nullable: false
8695
+ }
8696
+ };
8697
+ const KNOWLEDGE_SCOPE_ADDRESSES_SCHEMA = {
8698
+ address: {
8699
+ type: "text",
8700
+ nullable: false,
8701
+ primaryKey: true
8702
+ },
8703
+ scopeNodeId: {
8704
+ type: "text",
8705
+ nullable: false,
8706
+ references: {
8707
+ table: TABLE_KNOWLEDGE_NODES$1,
8708
+ column: "id"
8709
+ }
8710
+ }
8711
+ };
8712
+ const KNOWLEDGE_NODE_ADDRESSES_SCHEMA = {
8713
+ source: {
8714
+ type: "text",
8715
+ nullable: false
8716
+ },
8717
+ address: {
8718
+ type: "text",
8719
+ nullable: false
8720
+ },
8721
+ nodeId: {
8722
+ type: "text",
8723
+ nullable: false,
8724
+ references: {
8725
+ table: TABLE_KNOWLEDGE_NODES$1,
8726
+ column: "id"
8727
+ }
8728
+ }
8729
+ };
8730
+ const KNOWLEDGE_IMPORT_STATE_SCHEMA = {
8731
+ importerId: {
8732
+ type: "text",
8733
+ nullable: false
8734
+ },
8735
+ binding: {
8736
+ type: "text",
8737
+ nullable: false
8738
+ },
8739
+ key: {
8740
+ type: "text",
8741
+ nullable: false
8742
+ },
8743
+ value: {
8744
+ type: "text",
8745
+ nullable: false
8746
+ }
8747
+ };
8748
+ const KNOWLEDGE_IMPORT_RUNS_SCHEMA = {
8749
+ id: {
8750
+ type: "text",
8751
+ nullable: false,
8752
+ primaryKey: true
8753
+ },
8754
+ importerId: {
8755
+ type: "text",
8756
+ nullable: false
8757
+ },
8758
+ binding: {
8759
+ type: "text",
8760
+ nullable: false
8761
+ },
8762
+ importKind: {
8763
+ type: "text",
8764
+ nullable: false
8765
+ },
8766
+ triggerKind: {
8767
+ type: "text",
8768
+ nullable: false
8769
+ },
8770
+ status: {
8771
+ type: "text",
8772
+ nullable: false
8773
+ },
8774
+ error: {
8775
+ type: "text",
8776
+ nullable: true
8777
+ },
8778
+ transcriptThreadId: {
8779
+ type: "text",
8780
+ nullable: true
8781
+ },
8782
+ traceId: {
8783
+ type: "text",
8784
+ nullable: true
8785
+ },
8786
+ queuedAt: {
8787
+ type: "timestamp",
8788
+ nullable: false
8789
+ },
8790
+ startedAt: {
8791
+ type: "timestamp",
8792
+ nullable: true
8793
+ },
8794
+ completedAt: {
8795
+ type: "timestamp",
8796
+ nullable: true
8797
+ }
8798
+ };
8799
+ const KNOWLEDGE_V2_ACTIVITY_SCHEMA = {
8800
+ id: {
8801
+ type: "text",
8802
+ nullable: false,
8803
+ primaryKey: true
8804
+ },
8805
+ action: {
8806
+ type: "text",
8807
+ nullable: false
8808
+ },
8809
+ targetType: {
8810
+ type: "text",
8811
+ nullable: true
8812
+ },
8813
+ targetId: {
8814
+ type: "text",
8815
+ nullable: true
8816
+ },
8817
+ contextScopeId: {
8818
+ type: "text",
8819
+ nullable: true,
8820
+ references: {
8821
+ table: TABLE_KNOWLEDGE_NODES$1,
8822
+ column: "id"
8823
+ }
8824
+ },
8825
+ importRunId: {
8826
+ type: "text",
8827
+ nullable: true,
8828
+ references: {
8829
+ table: TABLE_KNOWLEDGE_IMPORT_RUNS,
8830
+ column: "id"
8831
+ }
8832
+ },
8833
+ details: {
8834
+ type: "jsonb",
8835
+ nullable: true
8836
+ },
8837
+ createdAt: {
8838
+ type: "timestamp",
8839
+ nullable: false
8840
+ },
8841
+ recordType: {
8842
+ type: "text",
8843
+ nullable: true
8844
+ },
8845
+ recordId: {
8846
+ type: "text",
8847
+ nullable: true
8848
+ },
8849
+ scope: {
8850
+ type: "jsonb",
8851
+ nullable: true
8852
+ },
8853
+ scopeKey: {
8854
+ type: "text",
8855
+ nullable: true
8856
+ },
8857
+ sourceThreadId: {
8858
+ type: "text",
8859
+ nullable: true
8860
+ }
8861
+ };
8862
+ const KNOWLEDGE_PROPOSALS_SCHEMA = {
8863
+ id: {
8864
+ type: "text",
8865
+ nullable: false,
8866
+ primaryKey: true
8867
+ },
8868
+ targetType: {
8869
+ type: "text",
8870
+ nullable: false
8871
+ },
8872
+ targetId: {
8873
+ type: "text",
8874
+ nullable: false
8875
+ },
8876
+ action: {
8877
+ type: "text",
8878
+ nullable: false
8879
+ },
8880
+ changes: {
8881
+ type: "jsonb",
8882
+ nullable: false
8883
+ },
8884
+ reason: {
8885
+ type: "text",
8886
+ nullable: true
8887
+ },
8888
+ proposerContextScopeId: {
8889
+ type: "text",
8890
+ nullable: false
8891
+ },
8892
+ expectedVersion: {
8893
+ type: "integer",
8894
+ nullable: false
8895
+ },
8896
+ status: {
8897
+ type: "text",
8898
+ nullable: false
8899
+ },
8900
+ reviewerContextScopeId: {
8901
+ type: "text",
8902
+ nullable: true
8903
+ },
8904
+ reviewedAt: {
8905
+ type: "timestamp",
8906
+ nullable: true
8907
+ },
8908
+ createdAt: {
8909
+ type: "timestamp",
8910
+ nullable: false
8911
+ }
8912
+ };
8913
+ function assertKnowledgeV2CoreSupport(features) {
8914
+ if (!features.has("knowledge-v2")) throw new Error(`Knowledge v2 requires a @mastra/core release with the "${KNOWLEDGE_V2_CORE_FEATURE}" feature. Upgrade @mastra/core to use Knowledge; other storage domains keep working on this version.`);
8915
+ }
8916
+ function resolveKnowledgeV2Core(storageModule) {
8917
+ if (typeof storageModule !== "object" || storageModule === null) throw new Error("@mastra/core advertises Knowledge v2 without the required storage API");
8918
+ const { assertKnowledgeDescriptionWithinBound: assertDescription, assertKnowledgeRecordTextWithinBound: assertRecordText, assertKnowledgeSchemaCompatible: assertCompatible, inspectKnowledgeSchema: inspectSchema } = storageModule;
8919
+ if (typeof assertDescription !== "function" || typeof assertRecordText !== "function" || typeof assertCompatible !== "function" || typeof inspectSchema !== "function") throw new Error("@mastra/core advertises Knowledge v2 without the required storage API");
8920
+ return {
8921
+ assertKnowledgeDescriptionWithinBound: (description) => assertDescription(description),
8922
+ assertKnowledgeRecordTextWithinBound: (text) => assertRecordText(text),
8923
+ assertKnowledgeSchemaCompatible: (inspection) => assertCompatible(inspection),
8924
+ inspectKnowledgeSchema: (snapshot) => inspectSchema(snapshot)
8925
+ };
8926
+ }
8927
+ function createKnowledgeV2CoreLoader(features, loadStorageModule) {
8928
+ let knowledgeV2Core;
8929
+ return async () => {
8930
+ assertKnowledgeV2CoreSupport(features);
8931
+ knowledgeV2Core ??= loadStorageModule().then(resolveKnowledgeV2Core).catch((error) => {
8932
+ knowledgeV2Core = void 0;
8933
+ throw error;
8934
+ });
8935
+ return knowledgeV2Core;
8936
+ };
8937
+ }
8938
+ //#endregion
8304
8939
  //#region src/storage/domains/knowledge/index.ts
8305
- let assertDescriptionWithinBound;
8940
+ const loadKnowledgeV2Core = createKnowledgeV2CoreLoader(_mastra_core_features.coreFeatures, () => import("@mastra/core/storage"));
8306
8941
  async function assertKnowledgeDescriptionWithinBoundCompat(description) {
8307
- let assertWithinBound = assertDescriptionWithinBound;
8308
- if (!assertWithinBound) {
8309
- const resolvedAssert = (await import("@mastra/core/storage")).assertKnowledgeDescriptionWithinBound ?? ((value) => {
8310
- if (value !== void 0 && value.length > 400) throw new Error("Knowledge node description exceeds the 400 UTF-16 code unit limit");
8311
- });
8312
- assertDescriptionWithinBound = resolvedAssert;
8313
- assertWithinBound = resolvedAssert;
8314
- }
8315
- assertWithinBound(description);
8942
+ const { assertKnowledgeDescriptionWithinBound } = await loadKnowledgeV2Core();
8943
+ assertKnowledgeDescriptionWithinBound(description);
8944
+ }
8945
+ async function assertKnowledgeRecordTextWithinBoundCompat(text) {
8946
+ const { assertKnowledgeRecordTextWithinBound } = await loadKnowledgeV2Core();
8947
+ assertKnowledgeRecordTextWithinBound(text);
8316
8948
  }
8317
8949
  const camelCaseColumns = [
8318
8950
  "canonicalName",
@@ -8323,7 +8955,6 @@ const camelCaseColumns = [
8323
8955
  "node",
8324
8956
  "sourceThreadId",
8325
8957
  "capturedAt",
8326
- "maxScope",
8327
8958
  "deletedAt",
8328
8959
  "deletedBy",
8329
8960
  "sourceType",
@@ -8337,7 +8968,30 @@ const camelCaseColumns = [
8337
8968
  "availableAt",
8338
8969
  "claimedAt",
8339
8970
  "claimedBy",
8340
- "completedAt"
8971
+ "completedAt",
8972
+ "isScope",
8973
+ "nodeId",
8974
+ "targetNodeId",
8975
+ "scopeNodeId",
8976
+ "scopeRefId",
8977
+ "canSuggest",
8978
+ "schemaVersion",
8979
+ "importerId",
8980
+ "importKind",
8981
+ "triggerKind",
8982
+ "transcriptThreadId",
8983
+ "traceId",
8984
+ "queuedAt",
8985
+ "startedAt",
8986
+ "targetType",
8987
+ "targetId",
8988
+ "contextScopeId",
8989
+ "importRunId",
8990
+ "proposerContextScopeId",
8991
+ "expectedVersion",
8992
+ "reviewerContextScopeId",
8993
+ "reviewedAt",
8994
+ "addedAt"
8341
8995
  ];
8342
8996
  function transformSqlCode(sql, transform) {
8343
8997
  return sql.split(/('(?:''|[^'])*')/g).map((part, index) => index % 2 === 0 ? transform(part) : part).join("");
@@ -8352,14 +9006,7 @@ function postgresSql(sql, schemaName) {
8352
9006
  const quotedSchema = `"${parseSchemaName(schemaName)}"`;
8353
9007
  normalized = transformSqlCode(normalized, (code) => {
8354
9008
  let transformed = code;
8355
- for (const table of [
8356
- _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
8357
- _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
8358
- _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
8359
- _mastra_core_storage.TABLE_KNOWLEDGE_CURSORS,
8360
- _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
8361
- _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX
8362
- ]) transformed = transformed.replaceAll(`"${table}"`, `${quotedSchema}."${table}"`);
9009
+ for (const table of [...KNOWLEDGE_TABLE_NAMES, ...RETIRED_KNOWLEDGE_TABLE_NAMES]) transformed = transformed.replaceAll(`"${table}"`, `${quotedSchema}."${table}"`);
8363
9010
  return transformed;
8364
9011
  });
8365
9012
  }
@@ -8367,17 +9014,35 @@ function postgresSql(sql, schemaName) {
8367
9014
  return transformSqlCode(normalized, (code) => code.replace(/\?/g, () => `$${++index}`));
8368
9015
  }
8369
9016
  function createExecutor(client, schemaName) {
8370
- return { async execute(statement) {
9017
+ const execute = async (statement, qualifyWithSchema) => {
8371
9018
  const sql = typeof statement === "string" ? statement : statement.sql;
8372
9019
  const args = typeof statement === "string" ? [] : statement.args ?? [];
8373
- const result = await client.query(postgresSql(sql, schemaName), args);
9020
+ const result = await client.query(postgresSql(sql, qualifyWithSchema ? schemaName : void 0), args);
8374
9021
  return {
8375
9022
  rows: result.rows,
8376
9023
  rowsAffected: result.rowCount ?? 0
8377
9024
  };
8378
- } };
9025
+ };
9026
+ return {
9027
+ execute: (statement) => execute(statement, true),
9028
+ executeRaw: (statement) => execute(statement, false)
9029
+ };
9030
+ }
9031
+ /**
9032
+ * Scope keys visible to a caller holding `scope`: a row is visible when its scope is a subset of the
9033
+ * caller's (companion entries such as `resource:x:uncurated` make this more than a prefix match).
9034
+ * Matching rows by `scopeKey` keeps visibility filters on an index; a caller scope has only a few
9035
+ * entries, so the list stays small.
9036
+ */
9037
+ function visibleScopeKeys(scope) {
9038
+ const canonical = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(scope);
9039
+ const keys = /* @__PURE__ */ new Set();
9040
+ for (let mask = 1; mask < 1 << canonical.length; mask++) try {
9041
+ keys.add((0, _mastra_core_storage.knowledgeScopeKey)(canonical.filter((_, index) => mask & 1 << index)));
9042
+ } catch {}
9043
+ return [...keys];
8379
9044
  }
8380
- const visibleSql = `(scopeKey = ? OR LEFT(?, LENGTH(scopeKey) + 1) = scopeKey || chr(31))`;
9045
+ const visibleSql = (keys, scopeKeyColumn = "scopeKey") => `${scopeKeyColumn} IN (${keys.map(() => "?").join(",")})`;
8381
9046
  function parseJson$1(value) {
8382
9047
  if (typeof value === "string") return JSON.parse(value);
8383
9048
  if (value instanceof Uint8Array) return JSON.parse(new TextDecoder().decode(value));
@@ -8417,9 +9082,10 @@ function parseNode(row) {
8417
9082
  id: String(row.id),
8418
9083
  type: "node",
8419
9084
  name: String(row.name),
8420
- kind: String(row.kind),
9085
+ kind: row.kind == null ? "" : String(row.kind),
8421
9086
  content: row.content == null ? void 0 : String(row.content),
8422
9087
  description: row.description == null ? void 0 : String(row.description),
9088
+ isScope: row.isScope === true || row.isScope === 1 ? true : void 0,
8423
9089
  scope: parseJson$1(row.scopeJson ?? row.scope),
8424
9090
  version: Number(row.version),
8425
9091
  mergedInto: row.mergedInto == null ? void 0 : String(row.mergedInto),
@@ -8436,7 +9102,6 @@ function parseKnowledge(row) {
8436
9102
  sourceThreadId: String(row.sourceThreadId),
8437
9103
  capturedAt: toDate$1(row.capturedAt),
8438
9104
  when: optionalDate(row.when),
8439
- maxScope: row.maxScope == null ? void 0 : String(row.maxScope),
8440
9105
  metadata: row.metadata == null ? void 0 : parseJson$1(row.metadata),
8441
9106
  deletedAt: optionalDate(row.deletedAt),
8442
9107
  deletedBy: row.deletedBy == null ? void 0 : String(row.deletedBy)
@@ -8473,6 +9138,10 @@ function knowledgeIndexes(schemaName) {
8473
9138
  name: "idx_knowledge_nodes_scope",
8474
9139
  sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_nodes_scope ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_NODES)} ("scopeKey", "type");`
8475
9140
  },
9141
+ {
9142
+ name: "idx_knowledge_nodes_name",
9143
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_nodes_name ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_NODES)} ("type", "canonicalName");`
9144
+ },
8476
9145
  {
8477
9146
  name: "idx_knowledge_records_node_latest",
8478
9147
  sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_records_node_latest ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS)} ("node", "id" DESC);`
@@ -8489,6 +9158,14 @@ function knowledgeIndexes(schemaName) {
8489
9158
  name: "idx_knowledge_activity_latest",
8490
9159
  sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_latest ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY)} ("id" DESC);`
8491
9160
  },
9161
+ {
9162
+ name: "idx_knowledge_records_scope",
9163
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_records_scope ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS)} ("scopeKey", "id");`
9164
+ },
9165
+ {
9166
+ name: "idx_knowledge_activity_scope",
9167
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_scope ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY)} ("scopeKey", "id" DESC);`
9168
+ },
8492
9169
  {
8493
9170
  name: "idx_knowledge_outbox_idempotency",
8494
9171
  sql: `CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_outbox_idempotency ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX)} ("idempotencyKey");`
@@ -8496,67 +9173,152 @@ function knowledgeIndexes(schemaName) {
8496
9173
  {
8497
9174
  name: "idx_knowledge_outbox_claim",
8498
9175
  sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_outbox_claim ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX)} ("status", "availableAt", "createdAt");`
9176
+ },
9177
+ {
9178
+ name: "idx_knowledge_node_scopes_scope",
9179
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_node_scopes_scope ON ${table(TABLE_KNOWLEDGE_NODE_SCOPES)} ("scopeNodeId", "nodeId");`
9180
+ },
9181
+ {
9182
+ name: "idx_knowledge_record_scopes_scope",
9183
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_record_scopes_scope ON ${table(TABLE_KNOWLEDGE_RECORD_SCOPES)} ("scopeNodeId", "recordId");`
9184
+ },
9185
+ {
9186
+ name: "idx_knowledge_scope_grants_ref",
9187
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_scope_grants_ref ON ${table(TABLE_KNOWLEDGE_SCOPE_GRANTS)} ("scopeRefId", "scopeNodeId");`
9188
+ },
9189
+ {
9190
+ name: "idx_knowledge_node_addresses_node",
9191
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_node_addresses_node ON ${table(TABLE_KNOWLEDGE_NODE_ADDRESSES)} ("nodeId");`
9192
+ },
9193
+ {
9194
+ name: "idx_knowledge_import_runs_lookup",
9195
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_import_runs_lookup ON ${table(TABLE_KNOWLEDGE_IMPORT_RUNS)} ("importerId", "binding", "queuedAt" DESC);`
9196
+ },
9197
+ {
9198
+ name: "idx_knowledge_activity_import_run",
9199
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_import_run ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY)} ("importRunId", "id" DESC);`
8499
9200
  }
8500
9201
  ];
8501
9202
  }
8502
9203
  function knowledgeIndexDDL(schemaName) {
8503
9204
  return knowledgeIndexes(schemaName).map((index) => index.sql);
8504
9205
  }
9206
+ const KNOWLEDGE_CURATION_CURSOR_REMOVED_MESSAGE = "Knowledge curation cursors were removed: observation-time curate is the only Knowledge writer and needs no cursor.";
9207
+ const knowledgeTableDefinitions = [
9208
+ {
9209
+ tableName: _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
9210
+ schema: KNOWLEDGE_V2_NODES_SCHEMA
9211
+ },
9212
+ {
9213
+ tableName: _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
9214
+ schema: KNOWLEDGE_V2_RECORDS_SCHEMA
9215
+ },
9216
+ {
9217
+ tableName: _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
9218
+ schema: KNOWLEDGE_V2_MENTIONS_SCHEMA,
9219
+ compositePrimaryKey: ["recordId", "sourceId"]
9220
+ },
9221
+ {
9222
+ tableName: TABLE_KNOWLEDGE_NODE_SCOPES,
9223
+ schema: KNOWLEDGE_NODE_SCOPES_SCHEMA,
9224
+ compositePrimaryKey: ["nodeId", "scopeNodeId"]
9225
+ },
9226
+ {
9227
+ tableName: TABLE_KNOWLEDGE_RECORD_SCOPES,
9228
+ schema: KNOWLEDGE_RECORD_SCOPES_SCHEMA,
9229
+ compositePrimaryKey: ["recordId", "scopeNodeId"]
9230
+ },
9231
+ {
9232
+ tableName: TABLE_KNOWLEDGE_SCOPE_GRANTS,
9233
+ schema: KNOWLEDGE_SCOPE_GRANTS_SCHEMA,
9234
+ compositePrimaryKey: ["scopeNodeId", "scopeRefId"]
9235
+ },
9236
+ {
9237
+ tableName: TABLE_KNOWLEDGE_ACCESS_STATE,
9238
+ schema: KNOWLEDGE_ACCESS_STATE_SCHEMA
9239
+ },
9240
+ {
9241
+ tableName: TABLE_KNOWLEDGE_SCOPE_ADDRESSES,
9242
+ schema: KNOWLEDGE_SCOPE_ADDRESSES_SCHEMA
9243
+ },
9244
+ {
9245
+ tableName: TABLE_KNOWLEDGE_NODE_ADDRESSES,
9246
+ schema: KNOWLEDGE_NODE_ADDRESSES_SCHEMA,
9247
+ compositePrimaryKey: ["source", "address"]
9248
+ },
9249
+ {
9250
+ tableName: TABLE_KNOWLEDGE_IMPORT_STATE,
9251
+ schema: KNOWLEDGE_IMPORT_STATE_SCHEMA,
9252
+ compositePrimaryKey: [
9253
+ "importerId",
9254
+ "binding",
9255
+ "key"
9256
+ ]
9257
+ },
9258
+ {
9259
+ tableName: TABLE_KNOWLEDGE_IMPORT_RUNS,
9260
+ schema: KNOWLEDGE_IMPORT_RUNS_SCHEMA
9261
+ },
9262
+ {
9263
+ tableName: TABLE_KNOWLEDGE_PROPOSALS,
9264
+ schema: KNOWLEDGE_PROPOSALS_SCHEMA
9265
+ },
9266
+ {
9267
+ tableName: _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
9268
+ schema: KNOWLEDGE_V2_ACTIVITY_SCHEMA
9269
+ },
9270
+ {
9271
+ tableName: _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
9272
+ schema: _mastra_core_storage.KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA
9273
+ }
9274
+ ];
9275
+ function pgSetting(config, key) {
9276
+ const value = config[key] || process.env[`PG${key.toUpperCase()}`] || pg.defaults[key];
9277
+ return value === void 0 || value === null || value === "" ? void 0 : String(value);
9278
+ }
9279
+ function effectivePgTarget(config) {
9280
+ const host = pgSetting(config, "host");
9281
+ const database = pgSetting(config, "database") ?? pgSetting(config, "user");
9282
+ if (!host || !database) return void 0;
9283
+ return `${host.startsWith("/") ? host : host.toLocaleLowerCase()}:${pgSetting(config, "port") ?? "5432"}/${database}`;
9284
+ }
9285
+ function canonicalPgTarget(config) {
9286
+ if (config.connectionString) try {
9287
+ const parsed = new URL(config.connectionString);
9288
+ return effectivePgTarget({
9289
+ host: decodeURIComponent(parsed.hostname) || config.host,
9290
+ port: parsed.port || config.port,
9291
+ database: decodeURIComponent(parsed.pathname.slice(1)) || config.database,
9292
+ user: decodeURIComponent(parsed.username) || config.user
9293
+ });
9294
+ } catch {
9295
+ return config.connectionString;
9296
+ }
9297
+ return effectivePgTarget(config);
9298
+ }
9299
+ function pgSourceConfig(source) {
9300
+ if (!source || !("options" in source)) return void 0;
9301
+ return source.options;
9302
+ }
9303
+ function pgClientPool(client) {
9304
+ if (!client || !("$pool" in client)) return void 0;
9305
+ return client.$pool;
9306
+ }
9307
+ function getPgKnowledgeIsolationKey(config) {
9308
+ const schema = config.schemaName ?? "public";
9309
+ const poolConfig = pgSourceConfig(config.pool ?? pgClientPool(config.client));
9310
+ const target = Boolean(config.connectionString || config.host || config.database) ? canonicalPgTarget(config) : poolConfig ? canonicalPgTarget(poolConfig) : void 0;
9311
+ if (target) return `pg:${target}:schema:${schema}`;
9312
+ return `pg:unidentified:schema:${schema}`;
9313
+ }
8505
9314
  var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8506
- static MANAGED_TABLES = [
8507
- _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
8508
- _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
8509
- _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
8510
- _mastra_core_storage.TABLE_KNOWLEDGE_CURSORS,
8511
- _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
8512
- _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX
8513
- ];
9315
+ static MANAGED_TABLES = KNOWLEDGE_TABLE_NAMES;
8514
9316
  static getExportDDL(schemaName) {
8515
- return [
8516
- generateTableSQL({
8517
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
8518
- schema: _mastra_core_storage.KNOWLEDGE_NODES_SCHEMA,
8519
- schemaName,
8520
- includeAllConstraints: true
8521
- }),
8522
- generateTableSQL({
8523
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
8524
- schema: _mastra_core_storage.KNOWLEDGE_RECORDS_SCHEMA,
8525
- schemaName,
8526
- includeAllConstraints: true
8527
- }),
8528
- generateTableSQL({
8529
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
8530
- schema: _mastra_core_storage.KNOWLEDGE_MENTIONS_SCHEMA,
8531
- schemaName,
8532
- compositePrimaryKey: [
8533
- "sourceType",
8534
- "sourceId",
8535
- "recordId"
8536
- ],
8537
- includeAllConstraints: true
8538
- }),
8539
- generateTableSQL({
8540
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_CURSORS,
8541
- schema: _mastra_core_storage.KNOWLEDGE_CURSORS_SCHEMA,
8542
- schemaName,
8543
- compositePrimaryKey: ["sourceThreadId", "agent"],
8544
- includeAllConstraints: true
8545
- }),
8546
- generateTableSQL({
8547
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
8548
- schema: _mastra_core_storage.KNOWLEDGE_ACTIVITY_SCHEMA,
8549
- schemaName,
8550
- includeAllConstraints: true
8551
- }),
8552
- generateTableSQL({
8553
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
8554
- schema: _mastra_core_storage.KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA,
8555
- schemaName,
8556
- includeAllConstraints: true
8557
- }),
8558
- ...knowledgeIndexDDL(schemaName)
8559
- ];
9317
+ return [...knowledgeTableDefinitions.map((definition) => generateTableSQL({
9318
+ ...definition,
9319
+ schemaName,
9320
+ includeAllConstraints: true
9321
+ })), ...knowledgeIndexDDL(schemaName)];
8560
9322
  }
8561
9323
  #client;
8562
9324
  #executor;
@@ -8565,7 +9327,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8565
9327
  #db;
8566
9328
  #schemaName;
8567
9329
  constructor(config) {
8568
- super();
9330
+ super({ storageIsolationKey: config.storageIsolationKey ?? getPgKnowledgeIsolationKey(config) });
8569
9331
  const { client, readClient, schemaName, skipDefaultIndexes } = resolvePgConfig(config);
8570
9332
  this.#client = client;
8571
9333
  this.#schemaName = schemaName;
@@ -8578,56 +9340,359 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8578
9340
  skipDefaultIndexes
8579
9341
  });
8580
9342
  }
8581
- async init() {
8582
- await this.#db.createTable({
8583
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
8584
- schema: _mastra_core_storage.KNOWLEDGE_NODES_SCHEMA
8585
- });
8586
- await this.#db.alterTable({
8587
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
8588
- schema: _mastra_core_storage.KNOWLEDGE_NODES_SCHEMA,
8589
- ifNotExists: ["description"]
9343
+ getCapabilities() {
9344
+ return {
9345
+ contractVersion: 2,
9346
+ schemaVersion: 2,
9347
+ supportsV2: true,
9348
+ supportsSchemaInspection: true,
9349
+ supportsExplicitReset: true
9350
+ };
9351
+ }
9352
+ async inspectSchema() {
9353
+ const { inspectKnowledgeSchema } = await loadKnowledgeV2Core();
9354
+ try {
9355
+ const snapshot = getSchemaSnapshot(this.#client, this.#schemaName);
9356
+ if (snapshot) {
9357
+ const tableNames = KNOWLEDGE_TABLE_NAMES.filter((table) => snapshot.tables.has(table));
9358
+ return this.#classifySchema(this.#executor, tableNames, snapshot.columns);
9359
+ }
9360
+ return this.#inspectSchemaWithExecutor(this.#executor);
9361
+ } catch (error) {
9362
+ return inspectKnowledgeSchema({
9363
+ available: false,
9364
+ tableNames: [],
9365
+ reason: error instanceof Error ? error.message : String(error)
9366
+ });
9367
+ }
9368
+ }
9369
+ async #inspectSchemaWithExecutor(executor) {
9370
+ const tableNames = (await executor.execute({
9371
+ sql: `SELECT table_name FROM information_schema.tables WHERE table_schema = COALESCE(?, current_schema()) AND table_name = ANY(?::text[])`,
9372
+ args: [this.#schemaName ?? null, [...KNOWLEDGE_TABLE_NAMES]]
9373
+ })).rows.map((row) => String(row.table_name));
9374
+ const columnResult = await executor.execute({
9375
+ sql: `SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = COALESCE(?, current_schema()) AND table_name = ANY(?::text[])`,
9376
+ args: [this.#schemaName ?? null, [...KNOWLEDGE_TABLE_NAMES]]
9377
+ });
9378
+ const columns = /* @__PURE__ */ new Map();
9379
+ for (const row of columnResult.rows) {
9380
+ const table = String(row.table_name);
9381
+ const names = columns.get(table) ?? /* @__PURE__ */ new Set();
9382
+ names.add(String(row.column_name));
9383
+ columns.set(table, names);
9384
+ }
9385
+ return this.#classifySchema(executor, tableNames, columns);
9386
+ }
9387
+ async #classifySchema(executor, tableNames, columns) {
9388
+ const { inspectKnowledgeSchema } = await loadKnowledgeV2Core();
9389
+ if (tableNames.length === 0) return inspectKnowledgeSchema({
9390
+ available: true,
9391
+ tableNames
9392
+ });
9393
+ const missingTables = KNOWLEDGE_TABLE_NAMES.filter((table) => !tableNames.includes(table));
9394
+ if (missingTables.length > 0) return inspectKnowledgeSchema({
9395
+ available: true,
9396
+ tableNames,
9397
+ reason: `Missing Knowledge v2 tables: ${missingTables.join(", ")}`
9398
+ });
9399
+ for (const { tableName: table, schema } of knowledgeTableDefinitions) {
9400
+ const actual = columns.get(table) ?? /* @__PURE__ */ new Set();
9401
+ const missing = Object.keys(schema).filter((column) => !actual.has(column));
9402
+ if (missing.length > 0) return inspectKnowledgeSchema({
9403
+ available: true,
9404
+ tableNames,
9405
+ reason: `Knowledge table ${table} is missing v2 columns: ${missing.join(", ")}`
9406
+ });
9407
+ }
9408
+ const accessState = await executor.execute(`SELECT schemaVersion FROM "${TABLE_KNOWLEDGE_ACCESS_STATE}" WHERE id='global'`);
9409
+ if (Number(accessState.rows[0]?.schemaVersion) !== 2) return inspectKnowledgeSchema({
9410
+ available: true,
9411
+ tableNames,
9412
+ reason: "Knowledge schema version marker is missing or incompatible"
9413
+ });
9414
+ return inspectKnowledgeSchema({
9415
+ available: true,
9416
+ tableNames,
9417
+ schemaVersion: 2
8590
9418
  });
8591
- await this.#db.createTable({
8592
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
8593
- schema: _mastra_core_storage.KNOWLEDGE_RECORDS_SCHEMA
9419
+ }
9420
+ async init() {
9421
+ await this.#transaction(async (tx) => {
9422
+ await tx.execute({
9423
+ sql: "SELECT pg_advisory_xact_lock(hashtext(?))",
9424
+ args: [`mastra-knowledge-v2:${this.#schemaName ?? "current_schema"}`]
9425
+ });
9426
+ const { assertKnowledgeSchemaCompatible } = await loadKnowledgeV2Core();
9427
+ let inspection = await this.#inspectSchemaWithExecutor(tx);
9428
+ if (inspection.status === "incompatible-reset-required" && await this.#isPublishedV1Layout(tx)) {
9429
+ const tables = [...RETIRED_KNOWLEDGE_TABLE_NAMES, ...[...KNOWLEDGE_TABLE_NAMES].reverse()].map((table) => `"${table}"`).join(", ");
9430
+ await tx.execute(`DROP TABLE IF EXISTS ${tables}`);
9431
+ inspection = await this.#inspectSchemaWithExecutor(tx);
9432
+ }
9433
+ assertKnowledgeSchemaCompatible(inspection);
9434
+ for (const definition of knowledgeTableDefinitions) await tx.executeRaw(generateTableSQL({
9435
+ ...definition,
9436
+ schemaName: this.#schemaName,
9437
+ includeAllConstraints: true
9438
+ }));
9439
+ for (const index of knowledgeIndexes(this.#schemaName)) await tx.executeRaw(index.sql);
9440
+ await tx.execute({
9441
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_ACCESS_STATE}" (id, epoch, schemaVersion) VALUES ('global', 0, ?) ON CONFLICT (id) DO NOTHING`,
9442
+ args: [2]
9443
+ });
8594
9444
  });
8595
- await this.#db.createTable({
8596
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
8597
- schema: _mastra_core_storage.KNOWLEDGE_MENTIONS_SCHEMA,
8598
- compositePrimaryKey: [
8599
- "sourceType",
8600
- "sourceId",
8601
- "recordId"
9445
+ }
9446
+ /**
9447
+ * True when the only Knowledge objects are the tables and indexes published v1 adapters created,
9448
+ * with or without rows. Anything else (v2 tables, unknown tables, views, triggers, extra indexes)
9449
+ * needs an explicit reset.
9450
+ */
9451
+ async #isPublishedV1Layout(executor) {
9452
+ const schema = this.#schemaName ?? null;
9453
+ const relations = await executor.execute({
9454
+ sql: `SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = COALESCE(?, current_schema()) AND table_name LIKE 'mastra\\_knowledge\\_%'`,
9455
+ args: [schema]
9456
+ });
9457
+ const tables = [];
9458
+ for (const row of relations.rows) {
9459
+ const name = String(row.table_name);
9460
+ if (row.table_type !== "BASE TABLE" || !PUBLISHED_KNOWLEDGE_V1_TABLE_NAMES.has(name)) return false;
9461
+ tables.push(name);
9462
+ }
9463
+ const indexes = await executor.execute({
9464
+ sql: `SELECT indexname FROM pg_indexes WHERE schemaname = COALESCE(?, current_schema()) AND tablename = ANY(?::text[])`,
9465
+ args: [schema, tables]
9466
+ });
9467
+ for (const row of indexes.rows) {
9468
+ const name = String(row.indexname);
9469
+ if (!PUBLISHED_KNOWLEDGE_V1_INDEX_NAMES.has(name) && !name.endsWith("_pkey")) return false;
9470
+ }
9471
+ if ((await executor.execute({
9472
+ sql: `SELECT 1 FROM information_schema.view_table_usage WHERE table_schema = COALESCE(?, current_schema()) AND table_name = ANY(?::text[]) UNION ALL SELECT 1 FROM information_schema.triggers WHERE event_object_schema = COALESCE(?, current_schema()) AND event_object_table = ANY(?::text[]) LIMIT 1`,
9473
+ args: [
9474
+ schema,
9475
+ tables,
9476
+ schema,
9477
+ tables
8602
9478
  ]
8603
- });
8604
- await this.#db.createTable({
8605
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_CURSORS,
8606
- schema: _mastra_core_storage.KNOWLEDGE_CURSORS_SCHEMA,
8607
- compositePrimaryKey: ["sourceThreadId", "agent"]
8608
- });
8609
- await this.#db.createTable({
8610
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
8611
- schema: _mastra_core_storage.KNOWLEDGE_ACTIVITY_SCHEMA
8612
- });
8613
- await this.#db.createTable({
8614
- tableName: _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
8615
- schema: _mastra_core_storage.KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA
8616
- });
8617
- await Promise.all(knowledgeIndexes(this.#schemaName).map((index) => this.#db.createIndexFromStatement(index.name, index.sql)));
9479
+ })).rows.length > 0) return false;
9480
+ return true;
8618
9481
  }
8619
9482
  async dangerouslyClearAll() {
8620
9483
  await this.#transaction(async (tx) => {
8621
9484
  for (const table of [
9485
+ TABLE_KNOWLEDGE_RECORD_SCOPES,
9486
+ TABLE_KNOWLEDGE_NODE_SCOPES,
9487
+ TABLE_KNOWLEDGE_SCOPE_GRANTS,
9488
+ TABLE_KNOWLEDGE_SCOPE_ADDRESSES,
9489
+ TABLE_KNOWLEDGE_NODE_ADDRESSES,
8622
9490
  _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
8623
- _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
8624
- _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
8625
- _mastra_core_storage.TABLE_KNOWLEDGE_CURSORS,
9491
+ TABLE_KNOWLEDGE_PROPOSALS,
8626
9492
  _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
8627
- _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX
9493
+ TABLE_KNOWLEDGE_IMPORT_STATE,
9494
+ TABLE_KNOWLEDGE_IMPORT_RUNS,
9495
+ _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
9496
+ _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
9497
+ _mastra_core_storage.TABLE_KNOWLEDGE_NODES
8628
9498
  ]) await tx.execute(`DELETE FROM "${table}"`);
9499
+ await tx.execute(`UPDATE "${TABLE_KNOWLEDGE_ACCESS_STATE}" SET epoch = 0 WHERE id = 'global'`);
9500
+ });
9501
+ }
9502
+ async dangerouslyReset() {
9503
+ const tables = [...RETIRED_KNOWLEDGE_TABLE_NAMES, ...[...KNOWLEDGE_TABLE_NAMES].reverse()].map((table) => `"${table}"`).join(", ");
9504
+ await this.#executor.execute(`DROP TABLE IF EXISTS ${tables}`);
9505
+ await this.init();
9506
+ }
9507
+ async reconcileStructure(plan) {
9508
+ return this.#transaction(async (tx) => {
9509
+ await tx.execute({
9510
+ sql: `SELECT pg_advisory_xact_lock(hashtext(?))`,
9511
+ args: [`mastra-knowledge-reconcile:${this.#schemaName}`]
9512
+ });
9513
+ const scopes = {};
9514
+ const createdScopeIds = [];
9515
+ const createdAddresses = /* @__PURE__ */ new Set();
9516
+ const retrofit = plan.retrofit ?? true;
9517
+ let structureChanged = false;
9518
+ const deletedScopeAddresses = /* @__PURE__ */ new Set();
9519
+ const resolveAddress = async (address) => {
9520
+ if (scopes[address]) return scopes[address];
9521
+ const row = (await tx.execute({
9522
+ sql: `SELECT a."scopeNodeId",n."isScope",n."deletedAt" FROM "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" a JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" n ON n.id=a."scopeNodeId" WHERE a.address=?`,
9523
+ args: [address]
9524
+ })).rows[0];
9525
+ if (!row) return void 0;
9526
+ if (!row.isScope) throw new Error(`Knowledge address ${address} does not reference a scope`);
9527
+ if (row.deletedAt) deletedScopeAddresses.add(address);
9528
+ scopes[address] = String(row.scopeNodeId);
9529
+ return scopes[address];
9530
+ };
9531
+ for (const scope of plan.scopes) {
9532
+ if (await resolveAddress(scope.address)) continue;
9533
+ const id = (0, crypto$1.randomUUID)();
9534
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9535
+ await tx.execute({
9536
+ sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" (id,type,name,"canonicalName",kind,description,"isScope",metadata,version,"createdAt","updatedAt") VALUES (?,'node',?,?,?,?,TRUE,?,1,?,?)`,
9537
+ args: [
9538
+ id,
9539
+ scope.name,
9540
+ canonicalName(scope.name),
9541
+ scope.kind ?? null,
9542
+ scope.description ?? null,
9543
+ scope.metadata ?? null,
9544
+ now,
9545
+ now
9546
+ ]
9547
+ });
9548
+ await tx.execute({
9549
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" (address,"scopeNodeId") VALUES (?,?)`,
9550
+ args: [scope.address, id]
9551
+ });
9552
+ scopes[scope.address] = id;
9553
+ createdAddresses.add(scope.address);
9554
+ createdScopeIds.push(id);
9555
+ structureChanged = true;
9556
+ }
9557
+ for (const scope of plan.scopes) {
9558
+ if (!createdAddresses.has(scope.address) && (!retrofit || deletedScopeAddresses.has(scope.address))) continue;
9559
+ const scopeNodeId = scopes[scope.address];
9560
+ for (const parentAddress of scope.parentAddresses ?? []) {
9561
+ const parentId = await resolveAddress(parentAddress);
9562
+ if (!parentId || deletedScopeAddresses.has(parentAddress)) {
9563
+ const deletedParentId = scopes[parentAddress];
9564
+ if ((deletedParentId ? await tx.execute({
9565
+ sql: `SELECT 1 FROM "mastra_knowledge_node_scopes" WHERE "nodeId"=? AND "scopeNodeId"=?`,
9566
+ args: [scopeNodeId, deletedParentId]
9567
+ }) : void 0)?.rows.length) continue;
9568
+ throw new Error(`Knowledge parent scope does not exist: ${parentAddress}`);
9569
+ }
9570
+ if ((await tx.execute({
9571
+ sql: `SELECT 1 FROM "mastra_knowledge_node_scopes" WHERE "nodeId"=? AND "scopeNodeId"=?`,
9572
+ args: [scopeNodeId, parentId]
9573
+ })).rows.length) continue;
9574
+ if ((await tx.execute({
9575
+ sql: `SELECT n.id FROM "mastra_knowledge_node_scopes" ns JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" n ON n.id=ns."nodeId" WHERE ns."scopeNodeId"=? AND n."isScope" AND n."canonicalName"=? AND n."deletedAt" IS NULL AND n.id<>? LIMIT 1`,
9576
+ args: [
9577
+ parentId,
9578
+ canonicalName(scope.name),
9579
+ scopeNodeId
9580
+ ]
9581
+ })).rows.length) throw new Error(`Knowledge scope name ${scope.name} already exists under ${parentAddress}`);
9582
+ const inserted = await tx.execute({
9583
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" ("nodeId","scopeNodeId","addedAt") VALUES (?,?,?) ON CONFLICT DO NOTHING`,
9584
+ args: [
9585
+ scopeNodeId,
9586
+ parentId,
9587
+ (/* @__PURE__ */ new Date()).toISOString()
9588
+ ]
9589
+ });
9590
+ structureChanged ||= inserted.rowsAffected > 0;
9591
+ }
9592
+ for (const grant of scope.grants ?? []) {
9593
+ const scopeRefId = await resolveAddress(grant.scopeRefAddress);
9594
+ if (!scopeRefId || deletedScopeAddresses.has(grant.scopeRefAddress)) {
9595
+ const deletedScopeRefId = scopes[grant.scopeRefAddress];
9596
+ if ((deletedScopeRefId ? await tx.execute({
9597
+ sql: `SELECT 1 FROM "mastra_knowledge_scope_grants" WHERE "scopeNodeId"=? AND "scopeRefId"=?`,
9598
+ args: [scopeNodeId, deletedScopeRefId]
9599
+ }) : void 0)?.rows.length) continue;
9600
+ throw new Error(`Knowledge grant scope does not exist: ${grant.scopeRefAddress}`);
9601
+ }
9602
+ const inserted = await tx.execute({
9603
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_SCOPE_GRANTS}" ("scopeNodeId","scopeRefId",role,"canSuggest") VALUES (?,?,?,?) ON CONFLICT DO NOTHING`,
9604
+ args: [
9605
+ scopeNodeId,
9606
+ scopeRefId,
9607
+ grant.role,
9608
+ grant.canSuggest ?? null
9609
+ ]
9610
+ });
9611
+ structureChanged ||= inserted.rowsAffected > 0;
9612
+ }
9613
+ }
9614
+ if (structureChanged) await tx.execute(`UPDATE "${TABLE_KNOWLEDGE_ACCESS_STATE}" SET epoch=epoch+1 WHERE id='global'`);
9615
+ const state = await tx.execute(`SELECT epoch FROM "${TABLE_KNOWLEDGE_ACCESS_STATE}" WHERE id='global'`);
9616
+ return {
9617
+ scopes,
9618
+ createdScopeIds,
9619
+ deletedScopeAddresses: [...deletedScopeAddresses],
9620
+ changed: structureChanged,
9621
+ accessEpoch: Number(state.rows[0]?.epoch ?? 0)
9622
+ };
8629
9623
  });
8630
9624
  }
9625
+ async listScopeNodes(input = {}) {
9626
+ const { limit, after } = parseListKnowledgeScopeNodesInput(input);
9627
+ if (input.addresses?.length === 0 || input.ids?.length === 0) return {
9628
+ scopes: [],
9629
+ nextCursor: null
9630
+ };
9631
+ const args = [];
9632
+ const where = [`n."isScope"`, `n."deletedAt" IS NULL`];
9633
+ let within = "";
9634
+ if (input.withinAddress !== void 0) {
9635
+ within = `WITH RECURSIVE within_scope(id) AS (SELECT r.id FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" r JOIN "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" ra ON ra."scopeNodeId"=r.id WHERE ra.address=? AND r."isScope" AND r."deletedAt" IS NULL UNION SELECT ns."nodeId" FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" ns JOIN within_scope w ON ns."scopeNodeId"=w.id JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" c ON c.id=ns."nodeId" WHERE c."isScope" AND c."deletedAt" IS NULL) `;
9636
+ args.push(input.withinAddress);
9637
+ where.push("n.id IN (SELECT id FROM within_scope)");
9638
+ }
9639
+ if (input.addresses) {
9640
+ where.push(`a.address IN (${input.addresses.map(() => "?").join(",")})`);
9641
+ args.push(...input.addresses);
9642
+ }
9643
+ if (input.ids) {
9644
+ where.push(`n.id IN (${input.ids.map(() => "?").join(",")})`);
9645
+ args.push(...input.ids);
9646
+ }
9647
+ if (after) {
9648
+ where.push("(n.name COLLATE \"C\" > ? OR (n.name = ? AND n.id > ?))");
9649
+ args.push(after.name, after.name, after.id);
9650
+ }
9651
+ args.push(limit + 1);
9652
+ const rows = (await this.#readExecutor.execute({
9653
+ sql: `${within}SELECT n.id,n.name,n.kind,n.description,a.address FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" n LEFT JOIN "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" a ON a."scopeNodeId"=n.id WHERE ${where.join(" AND ")} ORDER BY n.name COLLATE "C", n.id LIMIT ?`,
9654
+ args
9655
+ })).rows;
9656
+ if (rows.length === 0) return {
9657
+ scopes: [],
9658
+ nextCursor: null
9659
+ };
9660
+ const parents = await this.#readExecutor.execute({
9661
+ sql: `SELECT ns."nodeId",ns."scopeNodeId" FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" ns WHERE ns."nodeId" IN (${rows.map(() => "?").join(",")}) ORDER BY ns."scopeNodeId" COLLATE "C"`,
9662
+ args: rows.map((row) => String(row.id))
9663
+ });
9664
+ const parentsByScopeId = /* @__PURE__ */ new Map();
9665
+ for (const row of parents.rows) {
9666
+ const scopeId = String(row.nodeId);
9667
+ const parentId = String(row.scopeNodeId);
9668
+ const existing = parentsByScopeId.get(scopeId);
9669
+ if (existing) existing.push(parentId);
9670
+ else parentsByScopeId.set(scopeId, [parentId]);
9671
+ }
9672
+ return pageKnowledgeScopeNodes(rows.map((row) => ({
9673
+ id: String(row.id),
9674
+ address: String(row.address),
9675
+ name: String(row.name),
9676
+ ...row.kind == null ? {} : { kind: String(row.kind) },
9677
+ ...row.description == null ? {} : { description: String(row.description) },
9678
+ parentIds: parentsByScopeId.get(String(row.id)) ?? []
9679
+ })), limit, input);
9680
+ }
9681
+ async listScopeMembers(input) {
9682
+ const { limit, after } = parseListKnowledgeScopeMembersInput(input);
9683
+ const args = [input.scopeNodeId];
9684
+ let keyset = "";
9685
+ if (after) {
9686
+ const updatedAt = postgresTimestamp(after.updatedAt);
9687
+ keyset = ` AND (n."updatedAt" < ? OR (n."updatedAt" = ? AND (n.name > ? OR (n.name = ? AND n.id > ?))))`;
9688
+ args.push(updatedAt, updatedAt, after.name, after.name, after.id);
9689
+ }
9690
+ args.push(limit + 1);
9691
+ return pageKnowledgeScopeMembers((await this.#readExecutor.execute({
9692
+ sql: `SELECT *, scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" n WHERE EXISTS (SELECT 1 FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" ns WHERE ns."nodeId"=n.id AND ns."scopeNodeId"=?) AND n."deletedAt" IS NULL AND n."mergedInto" IS NULL${keyset} ORDER BY n."updatedAt" DESC, n.name ASC, n.id ASC LIMIT ?`,
9693
+ args
9694
+ })).rows.map(parseNode), limit, input);
9695
+ }
8631
9696
  async createNode(input) {
8632
9697
  await assertKnowledgeDescriptionWithinBoundCompat(input.description);
8633
9698
  const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
@@ -8636,6 +9701,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8636
9701
  if (existing) {
8637
9702
  const terminal = await this.#resolveTerminalNode(tx, existing.id);
8638
9703
  if (!(0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) throw new Error(`Merged knowledge node is not visible from scope: ${input.name}`);
9704
+ await this.#placeNodeInScopes(tx, terminal.id, input.scopeAddresses, /* @__PURE__ */ new Date());
8639
9705
  return terminal;
8640
9706
  }
8641
9707
  const now = /* @__PURE__ */ new Date();
@@ -8652,7 +9718,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8652
9718
  updatedAt: now
8653
9719
  };
8654
9720
  await tx.execute({
8655
- sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" (id,type,name,canonicalName,kind,content,description,scope,scopeKey,version,mergedInto,createdAt,updatedAt) VALUES (?,?,?,?,?,?,?,jsonb(?),?,?,NULL,?,?)`,
9721
+ sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" (id,type,name,canonicalName,kind,content,description,isScope,scope,scopeKey,version,mergedInto,createdAt,updatedAt) VALUES (?,?,?,?,?,?,?,FALSE,jsonb(?),?,?,NULL,?,?)`,
8656
9722
  args: [
8657
9723
  node.id,
8658
9724
  "node",
@@ -8668,6 +9734,8 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8668
9734
  now.toISOString()
8669
9735
  ]
8670
9736
  });
9737
+ await this.#replaceNodeScopes(tx, node.id, scope, now);
9738
+ await this.#placeNodeInScopes(tx, node.id, input.scopeAddresses, now);
8671
9739
  await this.#replaceMentions(tx, "node", node.id, node.content ?? "", input.resolutionScope ?? scope, scope);
8672
9740
  await this.#activity(tx, "node-created", "node", node.id, scope);
8673
9741
  await this.#outbox(tx, "node", node.id, "upsert", node.version, scope);
@@ -8684,13 +9752,13 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8684
9752
  return this.#resolveNode(this.#readExecutor, input.name, (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
8685
9753
  }
8686
9754
  async listNodes(input) {
8687
- const key = (0, _mastra_core_storage.knowledgeScopeKey)((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
9755
+ const keys = visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
8688
9756
  const clauses = [
8689
9757
  `type = 'node'`,
8690
9758
  "mergedInto IS NULL",
8691
- visibleSql
9759
+ visibleSql(keys)
8692
9760
  ];
8693
- const args = [key, key];
9761
+ const args = [...keys];
8694
9762
  if (input.namePrefix) {
8695
9763
  clauses.push("canonicalName LIKE ? ESCAPE '='");
8696
9764
  args.push(`${escapeLikePattern(canonicalName(input.namePrefix))}%`);
@@ -8742,6 +9810,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8742
9810
  input.version
8743
9811
  ]
8744
9812
  })).rowsAffected === 0) throw new _mastra_core_storage.KnowledgeConflictError(input.id);
9813
+ if ((0, _mastra_core_storage.knowledgeScopeKey)(existing.scope) !== (0, _mastra_core_storage.knowledgeScopeKey)(scope)) await this.#swapIdentityScopes(tx, input.id, existing.scope, scope, now);
8745
9814
  if (input.content !== void 0 || input.name !== void 0 || input.scope !== void 0) await this.#replaceMentions(tx, "node", input.id, content ?? "", input.resolutionScope ?? scope, scope);
8746
9815
  await this.#activity(tx, "node-updated", "node", input.id, scope);
8747
9816
  if ((0, _mastra_core_storage.knowledgeScopeKey)(existing.scope) !== (0, _mastra_core_storage.knowledgeScopeKey)(scope)) {
@@ -8796,8 +9865,12 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8796
9865
  ]
8797
9866
  })).rowsAffected === 0) throw new _mastra_core_storage.KnowledgeConflictError(source.id);
8798
9867
  await tx.execute({
8799
- sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET node=? WHERE node=?`,
8800
- args: [target.id, source.id]
9868
+ sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET node=?,version=version+1,updatedAt=? WHERE node=?`,
9869
+ args: [
9870
+ target.id,
9871
+ (/* @__PURE__ */ new Date()).toISOString(),
9872
+ source.id
9873
+ ]
8801
9874
  });
8802
9875
  await tx.execute({
8803
9876
  sql: `DELETE FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}" WHERE recordId=? AND EXISTS (SELECT 1 FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}" target WHERE target.sourceType="${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}".sourceType AND target.sourceId="${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}".sourceId AND target.recordId=?)`,
@@ -8837,10 +9910,10 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8837
9910
  });
8838
9911
  }
8839
9912
  async appendKnowledge(input) {
9913
+ await assertKnowledgeRecordTextWithinBoundCompat(input.text);
8840
9914
  const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
8841
9915
  const resolutionScope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.resolutionScope);
8842
9916
  const defaultScope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.defaultScope);
8843
- (0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, input.maxScope);
8844
9917
  return this.#transaction(async (tx) => {
8845
9918
  const parent = await this.#resolveTerminalNode(tx, nodeReferenceId(input.node));
8846
9919
  if (!parent) throw new _mastra_core_storage.KnowledgeNotFoundError("node", nodeReferenceId(input.node));
@@ -8853,11 +9926,10 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8853
9926
  sourceThreadId: input.sourceThreadId,
8854
9927
  capturedAt: /* @__PURE__ */ new Date(),
8855
9928
  when: input.when ? new Date(input.when) : void 0,
8856
- maxScope: input.maxScope,
8857
9929
  metadata: input.metadata
8858
9930
  };
8859
9931
  await tx.execute({
8860
- sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" (id,node,text,scope,scopeKey,sourceThreadId,capturedAt,"when",maxScope,metadata,deletedAt,deletedBy) VALUES (?,?,?,jsonb(?),?,?,?,?,?,jsonb(?),NULL,NULL)`,
9932
+ sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" (id,node,text,scope,scopeKey,sourceThreadId,capturedAt,"when",metadata,version,updatedAt,deletedAt,deletedBy) VALUES (?,?,?,jsonb(?),?,?,?,?,jsonb(?),?,?,NULL,NULL)`,
8861
9933
  args: [
8862
9934
  record.id,
8863
9935
  record.node,
@@ -8867,10 +9939,12 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8867
9939
  record.sourceThreadId,
8868
9940
  record.capturedAt.toISOString(),
8869
9941
  record.when?.toISOString() ?? null,
8870
- record.maxScope ?? null,
8871
- metadataJson
9942
+ metadataJson,
9943
+ 1,
9944
+ record.capturedAt.toISOString()
8872
9945
  ]
8873
9946
  });
9947
+ await this.#replaceRecordScopes(tx, record.id, scope, record.capturedAt);
8874
9948
  await this.#replaceMentions(tx, "record", record.id, record.text, resolutionScope, defaultScope);
8875
9949
  await this.#activity(tx, "record-created", "record", record.id, scope, record.sourceThreadId);
8876
9950
  await this.#outbox(tx, "record", record.id, "upsert", record.id, scope);
@@ -8897,17 +9971,13 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8897
9971
  return this.#queryKnowledge(input, "related");
8898
9972
  }
8899
9973
  async knowledgeBySource(input) {
8900
- const key = (0, _mastra_core_storage.knowledgeScopeKey)((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
8901
- const args = [
8902
- input.sourceThreadId,
8903
- key,
8904
- key
8905
- ];
9974
+ const keys = visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
9975
+ const args = [input.sourceThreadId, ...keys];
8906
9976
  if (input.after) args.push(input.after);
8907
9977
  const limit = input.limit ?? 100;
8908
9978
  args.push(limit + 1);
8909
9979
  const records = (await this.#readExecutor.execute({
8910
- sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" WHERE sourceThreadId=? AND ${visibleSql}${input.includeDeleted ? "" : " AND deletedAt IS NULL"}${input.after ? " AND id > ?" : ""} ORDER BY id ASC LIMIT ?`,
9980
+ sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" WHERE sourceThreadId=? AND ${visibleSql(keys)}${input.includeDeleted ? "" : " AND deletedAt IS NULL"}${input.after ? " AND id > ?" : ""} ORDER BY id ASC LIMIT ?`,
8911
9981
  args
8912
9982
  })).rows.map(parseKnowledge);
8913
9983
  return {
@@ -8922,10 +9992,11 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8922
9992
  if (record.deletedAt) return record;
8923
9993
  const deletedAt = /* @__PURE__ */ new Date();
8924
9994
  await tx.execute({
8925
- sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=?,deletedBy=? WHERE id=? AND deletedAt IS NULL`,
9995
+ sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=?,deletedBy=?,version=version+1,updatedAt=? WHERE id=? AND deletedAt IS NULL`,
8926
9996
  args: [
8927
9997
  deletedAt.toISOString(),
8928
9998
  input.deletedBy,
9999
+ deletedAt.toISOString(),
8929
10000
  input.id
8930
10001
  ]
8931
10002
  });
@@ -8944,8 +10015,8 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8944
10015
  if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
8945
10016
  if (!record.deletedAt) return record;
8946
10017
  await tx.execute({
8947
- sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=NULL,deletedBy=NULL WHERE id=?`,
8948
- args: [input.id]
10018
+ sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=NULL,deletedBy=NULL,version=version+1,updatedAt=? WHERE id=?`,
10019
+ args: [(/* @__PURE__ */ new Date()).toISOString(), input.id]
8949
10020
  });
8950
10021
  await this.#activity(tx, "record-restored", "record", input.id, record.scope, record.sourceThreadId);
8951
10022
  await this.#outbox(tx, "record", input.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope);
@@ -8961,15 +10032,17 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8961
10032
  return this.#transaction(async (tx) => {
8962
10033
  const record = await this.#getKnowledge(tx, input.id, true);
8963
10034
  if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
8964
- (0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, record.maxScope);
10035
+ const updatedAt = /* @__PURE__ */ new Date();
8965
10036
  await tx.execute({
8966
- sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET scope=jsonb(?),scopeKey=? WHERE id=?`,
10037
+ sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET scope=jsonb(?),scopeKey=?,version=version+1,updatedAt=? WHERE id=?`,
8967
10038
  args: [
8968
10039
  JSON.stringify(scope),
8969
10040
  (0, _mastra_core_storage.knowledgeScopeKey)(scope),
10041
+ updatedAt.toISOString(),
8970
10042
  input.id
8971
10043
  ]
8972
10044
  });
10045
+ await this.#replaceRecordScopes(tx, input.id, scope, updatedAt);
8973
10046
  await this.#activity(tx, "record-rescoped", "record", input.id, scope, record.sourceThreadId);
8974
10047
  if ((0, _mastra_core_storage.knowledgeScopeKey)(record.scope) !== (0, _mastra_core_storage.knowledgeScopeKey)(scope)) await this.#outbox(tx, "record", input.id, "delete", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope);
8975
10048
  if (!record.deletedAt) await this.#outbox(tx, "record", input.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), scope);
@@ -8979,33 +10052,16 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
8979
10052
  };
8980
10053
  });
8981
10054
  }
8982
- async raiseKnowledgeCeiling(input) {
8983
- return this.#transaction(async (tx) => {
8984
- const record = await this.#getKnowledge(tx, input.id, true);
8985
- if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
8986
- (0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(record.scope, input.maxScope);
8987
- (0, _mastra_core_storage.assertKnowledgeCeilingRaised)(record.maxScope, input.maxScope);
8988
- await tx.execute({
8989
- sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET maxScope=? WHERE id=?`,
8990
- args: [input.maxScope ?? null, input.id]
8991
- });
8992
- return {
8993
- ...record,
8994
- maxScope: input.maxScope
8995
- };
8996
- });
8997
- }
8998
10055
  async search(input) {
8999
10056
  const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
9000
- const key = (0, _mastra_core_storage.knowledgeScopeKey)(scope);
10057
+ const keys = visibleScopeKeys(scope);
9001
10058
  const normalizedQuery = input.query.trim().toLocaleLowerCase();
9002
10059
  if (!normalizedQuery) return [];
9003
10060
  const query = `%${escapeLikePattern(normalizedQuery)}%`;
9004
10061
  const results = (await this.#readExecutor.execute({
9005
- sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" WHERE mergedInto IS NULL AND ${visibleSql} AND (canonicalName LIKE ? ESCAPE '=' OR lower(COALESCE(kind,'')) LIKE ? ESCAPE '=' OR lower(COALESCE(content,'')) LIKE ? ESCAPE '=' OR lower(COALESCE(description,'')) LIKE ? ESCAPE '=') ORDER BY updatedAt DESC LIMIT ?`,
10062
+ sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" WHERE mergedInto IS NULL AND ${visibleSql(keys)} AND (canonicalName LIKE ? ESCAPE '=' OR lower(COALESCE(kind,'')) LIKE ? ESCAPE '=' OR lower(COALESCE(content,'')) LIKE ? ESCAPE '=' OR lower(COALESCE(description,'')) LIKE ? ESCAPE '=') ORDER BY updatedAt DESC LIMIT ?`,
9006
10063
  args: [
9007
- key,
9008
- key,
10064
+ ...keys,
9009
10065
  query,
9010
10066
  query,
9011
10067
  query,
@@ -9026,10 +10082,9 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9026
10082
  }));
9027
10083
  if (results.length < (input.limit ?? 20)) {
9028
10084
  const records = await this.#readExecutor.execute({
9029
- sql: `SELECT f.*,f.scope AS "scopeJson",r.name,r.scope AS "parentScopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" f JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" r ON r.id=f.node AND r.type='node' AND r.mergedInto IS NULL WHERE f.deletedAt IS NULL AND ${visibleSql.replaceAll("scopeKey", "f.scopeKey")} AND lower(f.text) LIKE ? ESCAPE '=' ORDER BY f.id DESC LIMIT ?`,
10085
+ sql: `SELECT f.*,f.scope AS "scopeJson",r.name,r.scope AS "parentScopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" f JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" r ON r.id=f.node AND r.type='node' AND r.mergedInto IS NULL WHERE f.deletedAt IS NULL AND ${visibleSql(keys, "f.scopeKey")} AND lower(f.text) LIKE ? ESCAPE '=' ORDER BY f.id DESC LIMIT ?`,
9030
10086
  args: [
9031
- key,
9032
- key,
10087
+ ...keys,
9033
10088
  query,
9034
10089
  (input.limit ?? 20) - results.length
9035
10090
  ]
@@ -9039,7 +10094,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9039
10094
  return {
9040
10095
  type: "record",
9041
10096
  id: String(row.id),
9042
- recordId: String(row.node),
10097
+ recordId: parentVisible ? String(row.node) : String(row.id),
9043
10098
  name: parentVisible ? String(row.name) : "(private node)",
9044
10099
  text: String(row.text),
9045
10100
  scope: parseJson$1(row.scopeJson)
@@ -9048,41 +10103,26 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9048
10103
  }
9049
10104
  return results;
9050
10105
  }
9051
- async getCurationCursor(input) {
9052
- const row = (await this.#executor.execute({
9053
- sql: `SELECT * FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_CURSORS}" WHERE sourceThreadId=? AND agent=?`,
9054
- args: [input.sourceThreadId, input.agent]
9055
- })).rows[0];
9056
- return row ? {
9057
- sourceThreadId: String(row.sourceThreadId),
9058
- agent: String(row.agent),
9059
- lastKnowledgeId: String(row.lastKnowledgeId),
9060
- updatedAt: toDate$1(row.updatedAt)
9061
- } : null;
9062
- }
9063
- async advanceCurationCursor(input) {
9064
- const updatedAt = /* @__PURE__ */ new Date();
9065
- if ((await this.#executor.execute({
9066
- sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_CURSORS}" (sourceThreadId,agent,lastKnowledgeId,updatedAt) VALUES (?,?,?,?) ON CONFLICT(sourceThreadId,agent) DO UPDATE SET lastKnowledgeId=excluded.lastKnowledgeId,updatedAt=excluded.updatedAt WHERE excluded.lastKnowledgeId >= "${_mastra_core_storage.TABLE_KNOWLEDGE_CURSORS}".lastKnowledgeId`,
9067
- args: [
9068
- input.sourceThreadId,
9069
- input.agent,
9070
- input.lastKnowledgeId,
9071
- updatedAt.toISOString()
9072
- ]
9073
- })).rowsAffected === 0) throw new Error("Knowledge curation cursor cannot move backwards");
9074
- return {
9075
- ...input,
9076
- updatedAt
9077
- };
10106
+ /**
10107
+ * @deprecated Curation cursors were removed. Observation-time curate is the only Knowledge writer and needs no
10108
+ * cursor. Always throws.
10109
+ */
10110
+ async getCurationCursor(_input) {
10111
+ throw new Error(KNOWLEDGE_CURATION_CURSOR_REMOVED_MESSAGE);
10112
+ }
10113
+ /**
10114
+ * @deprecated Curation cursors were removed. Observation-time curate is the only Knowledge writer and needs no
10115
+ * cursor. Always throws.
10116
+ */
10117
+ async advanceCurationCursor(_input) {
10118
+ throw new Error(KNOWLEDGE_CURATION_CURSOR_REMOVED_MESSAGE);
9078
10119
  }
9079
10120
  async listActivity(input) {
9080
- const key = (0, _mastra_core_storage.knowledgeScopeKey)((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
10121
+ const keys = visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
9081
10122
  return (await this.#readExecutor.execute({
9082
- sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY}" WHERE ${visibleSql}${input.after ? " AND id < ?" : ""} ORDER BY id DESC LIMIT ?`,
10123
+ sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY}" WHERE ${visibleSql(keys)}${input.after ? " AND id < ?" : ""} ORDER BY id DESC LIMIT ?`,
9083
10124
  args: [
9084
- key,
9085
- key,
10125
+ ...keys,
9086
10126
  ...input.after ? [input.after] : [],
9087
10127
  input.limit ?? 100
9088
10128
  ]
@@ -9104,9 +10144,9 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9104
10144
  args.push(input.status);
9105
10145
  }
9106
10146
  if (input.scope) {
9107
- const key = (0, _mastra_core_storage.knowledgeScopeKey)((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
9108
- clauses.push(visibleSql);
9109
- args.push(key, key);
10147
+ const keys = visibleScopeKeys(input.scope);
10148
+ clauses.push(visibleSql(keys));
10149
+ args.push(...keys);
9110
10150
  }
9111
10151
  args.push(input.limit ?? 100);
9112
10152
  return (await this.#executor.execute({
@@ -9125,9 +10165,9 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9125
10165
  ];
9126
10166
  const args = [now.toISOString(), stale.toISOString()];
9127
10167
  if (input.scope) {
9128
- const key = (0, _mastra_core_storage.knowledgeScopeKey)((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
9129
- clauses.push(visibleSql);
9130
- args.push(key, key);
10168
+ const keys = visibleScopeKeys(input.scope);
10169
+ clauses.push(visibleSql(keys));
10170
+ args.push(...keys);
9131
10171
  }
9132
10172
  args.push(input.limit ?? 100);
9133
10173
  const ids = (await tx.execute({
@@ -9194,12 +10234,14 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9194
10234
  return result.rows[0] ? parseNode(result.rows[0]) : null;
9195
10235
  }
9196
10236
  async #resolveNode(executor, name, scope) {
9197
- for (let length = scope.length; length > 0; length--) {
9198
- const node = await this.#getNodeByName(executor, name, scope.slice(0, length));
9199
- if (node) {
9200
- const terminal = await this.#resolveTerminalNode(executor, node.id);
9201
- if (terminal && (0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) return terminal;
9202
- }
10237
+ const keys = visibleScopeKeys(scope);
10238
+ const candidates = (await executor.execute({
10239
+ sql: `SELECT *,scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" WHERE type='node' AND canonicalName=? AND ("scopeKey" IN (${keys.map(() => "?").join(",")}) OR "mergedInto" IS NOT NULL)`,
10240
+ args: [canonicalName(name), ...keys]
10241
+ })).rows.map(parseNode).sort((left, right) => right.scope.length - left.scope.length);
10242
+ for (const candidate of candidates) {
10243
+ const terminal = await this.#resolveTerminalNode(executor, candidate.id);
10244
+ if (terminal && (0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) return terminal;
9203
10245
  }
9204
10246
  return null;
9205
10247
  }
@@ -9224,17 +10266,16 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9224
10266
  const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
9225
10267
  const node = await this.#resolveTerminalNode(this.#readExecutor, nodeReferenceId(input.node));
9226
10268
  if (!node) return { records: [] };
9227
- const key = (0, _mastra_core_storage.knowledgeScopeKey)(scope);
10269
+ const keys = visibleScopeKeys(scope);
9228
10270
  const args = [
9229
10271
  node.id,
9230
10272
  ...relationship === "related" ? [node.id] : [],
9231
- key,
9232
- key
10273
+ ...keys
9233
10274
  ];
9234
10275
  if (input.after) args.push(input.after);
9235
10276
  args.push((input.limit ?? 100) + 1);
9236
10277
  const records = (await this.#readExecutor.execute({
9237
- sql: `SELECT DISTINCT f.*,f.scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" f${relationship === "about" ? "" : ` LEFT JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}" m ON m.sourceType='record' AND m.sourceId=f.id`} WHERE ${relationship === "about" ? "f.node=?" : relationship === "mentioning" ? "m.recordId=?" : "(f.node=? OR m.recordId=?)"} AND ${visibleSql.replaceAll("scopeKey", "f.scopeKey")}${input.includeDeleted ? "" : " AND f.deletedAt IS NULL"}${input.after ? " AND f.id < ?" : ""} ORDER BY f.id DESC LIMIT ?`,
10278
+ sql: `SELECT DISTINCT f.*,f.scope AS "scopeJson" FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" f${relationship === "about" ? "" : ` LEFT JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}" m ON m.sourceType='record' AND m.sourceId=f.id`} WHERE ${relationship === "about" ? "f.node=?" : relationship === "mentioning" ? "m.recordId=?" : "(f.node=? OR m.recordId=?)"} AND ${visibleSql(keys, "f.scopeKey")}${input.includeDeleted ? "" : " AND f.deletedAt IS NULL"}${input.after ? " AND f.id < ?" : ""} ORDER BY f.id DESC LIMIT ?`,
9238
10279
  args
9239
10280
  })).rows.map(parseKnowledge);
9240
10281
  const limit = input.limit ?? 100;
@@ -9243,6 +10284,90 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9243
10284
  nextCursor: records.length > limit ? records[limit - 1]?.id : void 0
9244
10285
  };
9245
10286
  }
10287
+ async #resolveScopeNodeIds(executor, addresses) {
10288
+ const scopeNodeIds = /* @__PURE__ */ new Set();
10289
+ for (const address of addresses) {
10290
+ const result = await executor.execute({
10291
+ sql: `SELECT scopeNodeId FROM "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" WHERE address=?`,
10292
+ args: [address]
10293
+ });
10294
+ if (result.rows[0]?.scopeNodeId != null) scopeNodeIds.add(String(result.rows[0].scopeNodeId));
10295
+ }
10296
+ return [...scopeNodeIds];
10297
+ }
10298
+ async #replaceNodeScopes(executor, nodeId, addresses, addedAt) {
10299
+ await executor.execute({
10300
+ sql: `DELETE FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" WHERE nodeId=?`,
10301
+ args: [nodeId]
10302
+ });
10303
+ for (const scopeNodeId of await this.#resolveScopeNodeIds(executor, addresses)) await executor.execute({
10304
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" (nodeId,scopeNodeId,addedAt) VALUES (?,?,?) ON CONFLICT DO NOTHING`,
10305
+ args: [
10306
+ nodeId,
10307
+ scopeNodeId,
10308
+ addedAt.toISOString()
10309
+ ]
10310
+ });
10311
+ }
10312
+ /**
10313
+ * Move a node's identity memberships from `from` to `to` without touching structural
10314
+ * placements added by `#placeNodeInScopes`, which a scope change must not erase.
10315
+ */
10316
+ async #swapIdentityScopes(executor, nodeId, from, to, addedAt) {
10317
+ const next = await this.#resolveScopeNodeIds(executor, to);
10318
+ for (const scopeNodeId of await this.#resolveScopeNodeIds(executor, from)) {
10319
+ if (next.includes(scopeNodeId)) continue;
10320
+ await executor.execute({
10321
+ sql: `DELETE FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" WHERE nodeId=? AND scopeNodeId=?`,
10322
+ args: [nodeId, scopeNodeId]
10323
+ });
10324
+ }
10325
+ for (const scopeNodeId of next) await executor.execute({
10326
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" (nodeId,scopeNodeId,addedAt) VALUES (?,?,?) ON CONFLICT DO NOTHING`,
10327
+ args: [
10328
+ nodeId,
10329
+ scopeNodeId,
10330
+ addedAt.toISOString()
10331
+ ]
10332
+ });
10333
+ }
10334
+ /**
10335
+ * Additive structural placement: every address must resolve to a live scope node
10336
+ * (unlike identity membership, an unknown address is a caller error, not a lazy
10337
+ * materialization miss). Runs inside the caller's transaction, so a throw aborts
10338
+ * the whole mutation.
10339
+ */
10340
+ async #placeNodeInScopes(executor, nodeId, addresses, addedAt) {
10341
+ for (const address of addresses ?? []) {
10342
+ const scopeNodeId = (await executor.execute({
10343
+ sql: `SELECT sa.scopeNodeId AS "scopeNodeId" FROM "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" sa JOIN "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" n ON n.id=sa."scopeNodeId" WHERE sa.address=? AND n."isScope" AND n."deletedAt" IS NULL`,
10344
+ args: [address]
10345
+ })).rows[0]?.scopeNodeId;
10346
+ if (scopeNodeId == null) throw new _mastra_core_storage.KnowledgeNotFoundError("scope", address);
10347
+ await executor.execute({
10348
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" ("nodeId","scopeNodeId","addedAt") VALUES (?,?,?) ON CONFLICT DO NOTHING`,
10349
+ args: [
10350
+ nodeId,
10351
+ String(scopeNodeId),
10352
+ addedAt.toISOString()
10353
+ ]
10354
+ });
10355
+ }
10356
+ }
10357
+ async #replaceRecordScopes(executor, recordId, addresses, addedAt) {
10358
+ await executor.execute({
10359
+ sql: `DELETE FROM "${TABLE_KNOWLEDGE_RECORD_SCOPES}" WHERE recordId=?`,
10360
+ args: [recordId]
10361
+ });
10362
+ for (const scopeNodeId of await this.#resolveScopeNodeIds(executor, addresses)) await executor.execute({
10363
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_RECORD_SCOPES}" (recordId,scopeNodeId,addedAt) VALUES (?,?,?) ON CONFLICT DO NOTHING`,
10364
+ args: [
10365
+ recordId,
10366
+ scopeNodeId,
10367
+ addedAt.toISOString()
10368
+ ]
10369
+ });
10370
+ }
9246
10371
  async #replaceMentions(tx, sourceType, sourceId, text, resolutionScope, defaultScope) {
9247
10372
  await tx.execute({
9248
10373
  sql: `DELETE FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}" WHERE sourceType=? AND sourceId=?`,
@@ -9266,7 +10391,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9266
10391
  updatedAt: now
9267
10392
  };
9268
10393
  await tx.execute({
9269
- sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" (id,type,name,canonicalName,kind,content,scope,scopeKey,version,mergedInto,createdAt,updatedAt) VALUES (?,?,?,?,?,NULL,jsonb(?),?,?,NULL,?,?)`,
10394
+ sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" (id,type,name,canonicalName,kind,content,isScope,scope,scopeKey,version,mergedInto,createdAt,updatedAt) VALUES (?,?,?,?,?,NULL,FALSE,jsonb(?),?,?,NULL,?,?)`,
9270
10395
  args: [
9271
10396
  node.id,
9272
10397
  "node",
@@ -9280,6 +10405,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9280
10405
  now.toISOString()
9281
10406
  ]
9282
10407
  });
10408
+ await this.#replaceNodeScopes(tx, node.id, defaultScope, now);
9283
10409
  await this.#activity(tx, "node-created", "node", node.id, defaultScope);
9284
10410
  await this.#outbox(tx, "node", node.id, "upsert", 1, defaultScope);
9285
10411
  }
@@ -9296,13 +10422,17 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
9296
10422
  }
9297
10423
  async #activity(executor, action, recordType, recordId, scope, sourceThreadId) {
9298
10424
  const now = /* @__PURE__ */ new Date();
10425
+ const [contextScopeId] = await this.#resolveScopeNodeIds(executor, scope);
9299
10426
  await executor.execute({
9300
- sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY}" (id,action,recordType,recordId,scope,scopeKey,sourceThreadId,createdAt) VALUES (?,?,?,?,jsonb(?),?,?,?)`,
10427
+ sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY}" (id,action,targetType,targetId,contextScopeId,recordType,recordId,scope,scopeKey,sourceThreadId,createdAt) VALUES (?,?,?,?,?,?,?,jsonb(?),?,?,?)`,
9301
10428
  args: [
9302
10429
  (0, _mastra_core_storage.createKnowledgeUlid)(),
9303
10430
  action,
9304
10431
  recordType,
9305
10432
  recordId,
10433
+ contextScopeId ?? null,
10434
+ recordType,
10435
+ recordId,
9306
10436
  JSON.stringify(scope),
9307
10437
  (0, _mastra_core_storage.knowledgeScopeKey)(scope),
9308
10438
  sourceThreadId ?? null,
@@ -25062,7 +26192,10 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
25062
26192
  workflows: new WorkflowsPG(domainConfig),
25063
26193
  workflowDefinitions: new WorkflowDefinitionsPG(domainConfig),
25064
26194
  memory: new MemoryPG(domainConfig),
25065
- knowledge: new KnowledgePG(domainConfig),
26195
+ knowledge: new KnowledgePG({
26196
+ ...domainConfig,
26197
+ storageIsolationKey: config.storageIsolationKey ?? getPgKnowledgeIsolationKey(config)
26198
+ }),
25066
26199
  notifications: new NotificationsPG(domainConfig),
25067
26200
  observability: new ObservabilityPG(domainConfig),
25068
26201
  agents: new AgentsPG(domainConfig),
@@ -25116,7 +26249,7 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
25116
26249
  const pinned = new PinnedClientAdapter(this.#writePool, pinnedClient);
25117
26250
  this.#db.pin(pinned);
25118
26251
  this.#db.setSchemaSnapshot(await loadSchemaSnapshot(pinned, this.schema));
25119
- await super.init();
26252
+ await Promise.all(Object.entries(this.stores).filter(([name, store]) => name !== "knowledge" && store).map(([, store]) => store.init()));
25120
26253
  this.isInitialized = true;
25121
26254
  } catch (error) {
25122
26255
  this.#initPromise = null;