@mastra/pg 1.31.0-alpha.2 → 1.31.0-alpha.4
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/_types/@internal_core/dist/knowledge-compat/index.d.ts +594 -0
- package/dist/_types/@internal_core/package.json +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-retention.md +21 -18
- package/dist/index.cjs +1749 -310
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1752 -313
- package/dist/index.js.map +1 -1
- package/dist/shared/config.d.ts +6 -0
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/storage/db/index.d.ts +15 -9
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/db/run-fencing.d.ts +23 -0
- package/dist/storage/db/run-fencing.d.ts.map +1 -0
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/domains/knowledge/index.d.ts +38 -9
- package/dist/storage/domains/knowledge/index.d.ts.map +1 -1
- package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -1
- package/dist/storage/domains/mcp-servers/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +21 -7
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/prompt-blocks/index.d.ts.map +1 -1
- package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -1
- package/dist/storage/domains/skills/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +21 -6
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/domains/workspaces/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/retention.d.ts +3 -3
- package/dist/storage/retention.d.ts.map +1 -1
- package/package.json +5 -4
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");
|
|
@@ -3213,9 +3213,10 @@ var PgDB = class extends _mastra_core_base.MastraBase {
|
|
|
3213
3213
|
}
|
|
3214
3214
|
await flush();
|
|
3215
3215
|
}
|
|
3216
|
-
|
|
3216
|
+
/** `client` lets a caller run the insert inside its own transaction. */
|
|
3217
|
+
async insert({ tableName, record }, client = this.client) {
|
|
3217
3218
|
try {
|
|
3218
|
-
await this.executeInsert(
|
|
3219
|
+
await this.executeInsert(client, {
|
|
3219
3220
|
tableName,
|
|
3220
3221
|
record
|
|
3221
3222
|
});
|
|
@@ -4049,13 +4050,15 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
|
|
|
4049
4050
|
indexName: tableName,
|
|
4050
4051
|
schemaName: getSchemaName$6(this.schemaName)
|
|
4051
4052
|
});
|
|
4053
|
+
const parsedColumn = `"${(0, _mastra_core_utils.parseSqlIdentifier)(column, "column name")}"`;
|
|
4052
4054
|
const sql = `
|
|
4053
4055
|
DELETE FROM ${fullTableName}
|
|
4054
4056
|
WHERE ctid IN (
|
|
4055
4057
|
SELECT ctid FROM ${fullTableName}
|
|
4056
|
-
WHERE ${
|
|
4058
|
+
WHERE ${parsedColumn} < $1
|
|
4057
4059
|
LIMIT $2
|
|
4058
4060
|
)
|
|
4061
|
+
AND ${parsedColumn} < $1
|
|
4059
4062
|
`;
|
|
4060
4063
|
return (await this.client.query(sql, [cutoff, limit])).rowCount ?? 0;
|
|
4061
4064
|
}
|
|
@@ -4518,6 +4521,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4518
4521
|
}
|
|
4519
4522
|
async create(input) {
|
|
4520
4523
|
const { agent } = input;
|
|
4524
|
+
let draftInserted = false;
|
|
4521
4525
|
try {
|
|
4522
4526
|
const agentsTable = getTableName$5({
|
|
4523
4527
|
indexName: _mastra_core_storage.TABLE_AGENTS,
|
|
@@ -4544,6 +4548,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4544
4548
|
nowIso,
|
|
4545
4549
|
nowIso
|
|
4546
4550
|
]);
|
|
4551
|
+
draftInserted = true;
|
|
4547
4552
|
const { id: _id, authorId: _authorId, visibility: _visibility, metadata: _metadata, ...snapshotConfig } = agent;
|
|
4548
4553
|
const versionId = crypto.randomUUID();
|
|
4549
4554
|
await this.createVersion({
|
|
@@ -4566,14 +4571,14 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
|
|
|
4566
4571
|
updatedAt: now
|
|
4567
4572
|
};
|
|
4568
4573
|
} catch (error) {
|
|
4569
|
-
if (
|
|
4570
|
-
try {
|
|
4574
|
+
if (draftInserted) try {
|
|
4571
4575
|
const agentsTable = getTableName$5({
|
|
4572
4576
|
indexName: _mastra_core_storage.TABLE_AGENTS,
|
|
4573
4577
|
schemaName: getSchemaName$5(this.#schema)
|
|
4574
4578
|
});
|
|
4575
4579
|
await this.#db.client.none(`DELETE FROM ${agentsTable} WHERE id = $1 AND status = 'draft' AND "activeVersionId" IS NULL`, [agent.id]);
|
|
4576
4580
|
} catch {}
|
|
4581
|
+
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
4577
4582
|
throw new _mastra_core_error.MastraError({
|
|
4578
4583
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "CREATE_AGENT", "FAILED"),
|
|
4579
4584
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -8301,18 +8306,650 @@ var FavoritesPG = class FavoritesPG extends _mastra_core_storage.FavoritesStorag
|
|
|
8301
8306
|
}
|
|
8302
8307
|
};
|
|
8303
8308
|
//#endregion
|
|
8309
|
+
//#region ../../packages/_internal-core/dist/knowledge-compat/index.js
|
|
8310
|
+
const KNOWLEDGE_V2_CORE_FEATURE = "knowledge-v2";
|
|
8311
|
+
/** Hard cap on scope nodes returned by one `listScopeNodes` read. */
|
|
8312
|
+
const MAX_KNOWLEDGE_SCOPE_NODES = 1e3;
|
|
8313
|
+
function knowledgeScopeNodeFilterKey(input) {
|
|
8314
|
+
return JSON.stringify([
|
|
8315
|
+
input.withinAddress ?? null,
|
|
8316
|
+
input.addresses ? [...input.addresses].sort() : null,
|
|
8317
|
+
input.ids ? [...input.ids].sort() : null
|
|
8318
|
+
]);
|
|
8319
|
+
}
|
|
8320
|
+
function createKnowledgeScopeNodeCursor(scope, input) {
|
|
8321
|
+
return encodeURIComponent(JSON.stringify({
|
|
8322
|
+
version: 1,
|
|
8323
|
+
type: "scope",
|
|
8324
|
+
name: scope.name,
|
|
8325
|
+
id: scope.id,
|
|
8326
|
+
filter: knowledgeScopeNodeFilterKey(input)
|
|
8327
|
+
}));
|
|
8328
|
+
}
|
|
8329
|
+
/** Validates the page size and cursor of a `listScopeNodes` query; throws on a cursor from a different query. */
|
|
8330
|
+
function parseListKnowledgeScopeNodesInput(input = {}) {
|
|
8331
|
+
const requested = Number.isFinite(input.limit) ? Math.trunc(input.limit) : MAX_KNOWLEDGE_SCOPE_NODES;
|
|
8332
|
+
const limit = Math.min(Math.max(requested, 1), MAX_KNOWLEDGE_SCOPE_NODES);
|
|
8333
|
+
if (!input.cursor) return {
|
|
8334
|
+
limit,
|
|
8335
|
+
after: null
|
|
8336
|
+
};
|
|
8337
|
+
let value;
|
|
8338
|
+
try {
|
|
8339
|
+
value = JSON.parse(decodeURIComponent(input.cursor));
|
|
8340
|
+
} catch {
|
|
8341
|
+
throw new Error("Invalid Knowledge scope node cursor.");
|
|
8342
|
+
}
|
|
8343
|
+
const parsed = value && typeof value === "object" ? value : {};
|
|
8344
|
+
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.");
|
|
8345
|
+
return {
|
|
8346
|
+
limit,
|
|
8347
|
+
after: {
|
|
8348
|
+
name: parsed.name,
|
|
8349
|
+
id: parsed.id
|
|
8350
|
+
}
|
|
8351
|
+
};
|
|
8352
|
+
}
|
|
8353
|
+
/** Builds a page from up to `limit + 1` name/id-ordered scope nodes. */
|
|
8354
|
+
function pageKnowledgeScopeNodes(rows, limit, input) {
|
|
8355
|
+
const scopes = rows.slice(0, limit);
|
|
8356
|
+
const last = scopes.at(-1);
|
|
8357
|
+
return {
|
|
8358
|
+
scopes,
|
|
8359
|
+
nextCursor: rows.length > limit && last ? createKnowledgeScopeNodeCursor(last, input) : null
|
|
8360
|
+
};
|
|
8361
|
+
}
|
|
8362
|
+
/** Clamps a requested member limit to 1–{@link MAX_KNOWLEDGE_SCOPE_MEMBERS_LIMIT}. */
|
|
8363
|
+
function knowledgeScopeMembersLimit(limit) {
|
|
8364
|
+
if (limit === void 0 || !Number.isFinite(limit)) return 500;
|
|
8365
|
+
return Math.min(Math.max(Math.trunc(limit), 1), 500);
|
|
8366
|
+
}
|
|
8367
|
+
/** Validates the page size and cursor of a `listScopeMembers` query; throws on a cursor from another scope. */
|
|
8368
|
+
function parseListKnowledgeScopeMembersInput(input) {
|
|
8369
|
+
const limit = knowledgeScopeMembersLimit(input.limit);
|
|
8370
|
+
if (!input.cursor) return {
|
|
8371
|
+
limit,
|
|
8372
|
+
after: null
|
|
8373
|
+
};
|
|
8374
|
+
let value;
|
|
8375
|
+
try {
|
|
8376
|
+
value = JSON.parse(decodeURIComponent(input.cursor));
|
|
8377
|
+
} catch {
|
|
8378
|
+
throw new Error("Invalid Knowledge scope member cursor.");
|
|
8379
|
+
}
|
|
8380
|
+
const parsed = value && typeof value === "object" ? value : {};
|
|
8381
|
+
const updatedAt = typeof parsed.updatedAt === "string" ? new Date(parsed.updatedAt) : /* @__PURE__ */ new Date(NaN);
|
|
8382
|
+
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.");
|
|
8383
|
+
return {
|
|
8384
|
+
limit,
|
|
8385
|
+
after: {
|
|
8386
|
+
updatedAt,
|
|
8387
|
+
name: parsed.name,
|
|
8388
|
+
id: parsed.id
|
|
8389
|
+
}
|
|
8390
|
+
};
|
|
8391
|
+
}
|
|
8392
|
+
/** Builds a page from up to `limit + 1` members in `listScopeMembers` order. */
|
|
8393
|
+
function pageKnowledgeScopeMembers(rows, limit, input) {
|
|
8394
|
+
const members = rows.slice(0, limit);
|
|
8395
|
+
const last = members.at(-1);
|
|
8396
|
+
const hasMore = rows.length > limit;
|
|
8397
|
+
return {
|
|
8398
|
+
members,
|
|
8399
|
+
hasMore,
|
|
8400
|
+
nextCursor: hasMore && last ? encodeURIComponent(JSON.stringify({
|
|
8401
|
+
version: 1,
|
|
8402
|
+
type: "scope-member",
|
|
8403
|
+
scopeNodeId: input.scopeNodeId,
|
|
8404
|
+
updatedAt: last.updatedAt.toISOString(),
|
|
8405
|
+
name: last.name,
|
|
8406
|
+
id: last.id
|
|
8407
|
+
})) : null
|
|
8408
|
+
};
|
|
8409
|
+
}
|
|
8410
|
+
const TABLE_KNOWLEDGE_NODES$1 = "mastra_knowledge_nodes";
|
|
8411
|
+
const TABLE_KNOWLEDGE_RECORDS$1 = "mastra_knowledge_records";
|
|
8412
|
+
const TABLE_KNOWLEDGE_MENTIONS$1 = "mastra_knowledge_mentions";
|
|
8413
|
+
const TABLE_KNOWLEDGE_ACTIVITY$1 = "mastra_knowledge_activity";
|
|
8414
|
+
const TABLE_KNOWLEDGE_SEMANTIC_OUTBOX$1 = "mastra_knowledge_semantic_outbox";
|
|
8415
|
+
const TABLE_KNOWLEDGE_NODE_SCOPES = "mastra_knowledge_node_scopes";
|
|
8416
|
+
const TABLE_KNOWLEDGE_RECORD_SCOPES = "mastra_knowledge_record_scopes";
|
|
8417
|
+
const TABLE_KNOWLEDGE_SCOPE_GRANTS = "mastra_knowledge_scope_grants";
|
|
8418
|
+
const TABLE_KNOWLEDGE_ACCESS_STATE = "mastra_knowledge_access_state";
|
|
8419
|
+
const TABLE_KNOWLEDGE_SCOPE_ADDRESSES = "mastra_knowledge_scope_addresses";
|
|
8420
|
+
const TABLE_KNOWLEDGE_NODE_ADDRESSES = "mastra_knowledge_node_addresses";
|
|
8421
|
+
const TABLE_KNOWLEDGE_IMPORT_STATE = "mastra_knowledge_import_state";
|
|
8422
|
+
const TABLE_KNOWLEDGE_IMPORT_RUNS = "mastra_knowledge_import_runs";
|
|
8423
|
+
const TABLE_KNOWLEDGE_PROPOSALS = "mastra_knowledge_proposals";
|
|
8424
|
+
const KNOWLEDGE_TABLE_NAMES = [
|
|
8425
|
+
TABLE_KNOWLEDGE_NODES$1,
|
|
8426
|
+
TABLE_KNOWLEDGE_RECORDS$1,
|
|
8427
|
+
TABLE_KNOWLEDGE_MENTIONS$1,
|
|
8428
|
+
TABLE_KNOWLEDGE_ACTIVITY$1,
|
|
8429
|
+
TABLE_KNOWLEDGE_SEMANTIC_OUTBOX$1,
|
|
8430
|
+
TABLE_KNOWLEDGE_NODE_SCOPES,
|
|
8431
|
+
TABLE_KNOWLEDGE_RECORD_SCOPES,
|
|
8432
|
+
TABLE_KNOWLEDGE_SCOPE_GRANTS,
|
|
8433
|
+
TABLE_KNOWLEDGE_ACCESS_STATE,
|
|
8434
|
+
TABLE_KNOWLEDGE_SCOPE_ADDRESSES,
|
|
8435
|
+
TABLE_KNOWLEDGE_NODE_ADDRESSES,
|
|
8436
|
+
TABLE_KNOWLEDGE_IMPORT_STATE,
|
|
8437
|
+
TABLE_KNOWLEDGE_IMPORT_RUNS,
|
|
8438
|
+
TABLE_KNOWLEDGE_PROPOSALS
|
|
8439
|
+
];
|
|
8440
|
+
/** Knowledge v1 tables with no v2 equivalent; an explicit schema reset drops them. */
|
|
8441
|
+
const RETIRED_KNOWLEDGE_TABLE_NAMES = ["mastra_knowledge_cursors"];
|
|
8442
|
+
/** Tables and indexes published v1 adapters created for every app, whether or not it used Knowledge. */
|
|
8443
|
+
const PUBLISHED_KNOWLEDGE_V1_TABLE_NAMES = /* @__PURE__ */ new Set([
|
|
8444
|
+
TABLE_KNOWLEDGE_NODES$1,
|
|
8445
|
+
TABLE_KNOWLEDGE_RECORDS$1,
|
|
8446
|
+
TABLE_KNOWLEDGE_MENTIONS$1,
|
|
8447
|
+
TABLE_KNOWLEDGE_ACTIVITY$1,
|
|
8448
|
+
TABLE_KNOWLEDGE_SEMANTIC_OUTBOX$1,
|
|
8449
|
+
...RETIRED_KNOWLEDGE_TABLE_NAMES
|
|
8450
|
+
]);
|
|
8451
|
+
const PUBLISHED_KNOWLEDGE_V1_INDEX_NAMES = /* @__PURE__ */ new Set([
|
|
8452
|
+
"idx_knowledge_nodes_identity",
|
|
8453
|
+
"idx_knowledge_nodes_scope",
|
|
8454
|
+
"idx_knowledge_records_node_latest",
|
|
8455
|
+
"idx_knowledge_records_thread_latest",
|
|
8456
|
+
"idx_knowledge_mentions_record",
|
|
8457
|
+
"idx_knowledge_activity_latest",
|
|
8458
|
+
"idx_knowledge_outbox_idempotency",
|
|
8459
|
+
"idx_knowledge_outbox_claim"
|
|
8460
|
+
]);
|
|
8461
|
+
const KNOWLEDGE_V2_NODES_SCHEMA = {
|
|
8462
|
+
id: {
|
|
8463
|
+
type: "text",
|
|
8464
|
+
nullable: false,
|
|
8465
|
+
primaryKey: true
|
|
8466
|
+
},
|
|
8467
|
+
name: {
|
|
8468
|
+
type: "text",
|
|
8469
|
+
nullable: false
|
|
8470
|
+
},
|
|
8471
|
+
kind: {
|
|
8472
|
+
type: "text",
|
|
8473
|
+
nullable: true
|
|
8474
|
+
},
|
|
8475
|
+
isScope: {
|
|
8476
|
+
type: "boolean",
|
|
8477
|
+
nullable: false
|
|
8478
|
+
},
|
|
8479
|
+
metadata: {
|
|
8480
|
+
type: "jsonb",
|
|
8481
|
+
nullable: true
|
|
8482
|
+
},
|
|
8483
|
+
version: {
|
|
8484
|
+
type: "integer",
|
|
8485
|
+
nullable: false
|
|
8486
|
+
},
|
|
8487
|
+
createdAt: {
|
|
8488
|
+
type: "timestamp",
|
|
8489
|
+
nullable: false
|
|
8490
|
+
},
|
|
8491
|
+
updatedAt: {
|
|
8492
|
+
type: "timestamp",
|
|
8493
|
+
nullable: false
|
|
8494
|
+
},
|
|
8495
|
+
deletedAt: {
|
|
8496
|
+
type: "timestamp",
|
|
8497
|
+
nullable: true
|
|
8498
|
+
},
|
|
8499
|
+
deletedBy: {
|
|
8500
|
+
type: "text",
|
|
8501
|
+
nullable: true
|
|
8502
|
+
},
|
|
8503
|
+
type: {
|
|
8504
|
+
type: "text",
|
|
8505
|
+
nullable: true
|
|
8506
|
+
},
|
|
8507
|
+
canonicalName: {
|
|
8508
|
+
type: "text",
|
|
8509
|
+
nullable: true
|
|
8510
|
+
},
|
|
8511
|
+
content: {
|
|
8512
|
+
type: "text",
|
|
8513
|
+
nullable: true
|
|
8514
|
+
},
|
|
8515
|
+
description: {
|
|
8516
|
+
type: "text",
|
|
8517
|
+
nullable: true
|
|
8518
|
+
},
|
|
8519
|
+
scope: {
|
|
8520
|
+
type: "jsonb",
|
|
8521
|
+
nullable: true
|
|
8522
|
+
},
|
|
8523
|
+
scopeKey: {
|
|
8524
|
+
type: "text",
|
|
8525
|
+
nullable: true
|
|
8526
|
+
},
|
|
8527
|
+
mergedInto: {
|
|
8528
|
+
type: "text",
|
|
8529
|
+
nullable: true
|
|
8530
|
+
}
|
|
8531
|
+
};
|
|
8532
|
+
const KNOWLEDGE_V2_RECORDS_SCHEMA = {
|
|
8533
|
+
id: {
|
|
8534
|
+
type: "text",
|
|
8535
|
+
nullable: false,
|
|
8536
|
+
primaryKey: true
|
|
8537
|
+
},
|
|
8538
|
+
node: {
|
|
8539
|
+
type: "text",
|
|
8540
|
+
nullable: false,
|
|
8541
|
+
references: {
|
|
8542
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8543
|
+
column: "id"
|
|
8544
|
+
}
|
|
8545
|
+
},
|
|
8546
|
+
text: {
|
|
8547
|
+
type: "text",
|
|
8548
|
+
nullable: false
|
|
8549
|
+
},
|
|
8550
|
+
metadata: {
|
|
8551
|
+
type: "jsonb",
|
|
8552
|
+
nullable: true
|
|
8553
|
+
},
|
|
8554
|
+
version: {
|
|
8555
|
+
type: "integer",
|
|
8556
|
+
nullable: false
|
|
8557
|
+
},
|
|
8558
|
+
capturedAt: {
|
|
8559
|
+
type: "timestamp",
|
|
8560
|
+
nullable: false
|
|
8561
|
+
},
|
|
8562
|
+
updatedAt: {
|
|
8563
|
+
type: "timestamp",
|
|
8564
|
+
nullable: false
|
|
8565
|
+
},
|
|
8566
|
+
deletedAt: {
|
|
8567
|
+
type: "timestamp",
|
|
8568
|
+
nullable: true
|
|
8569
|
+
},
|
|
8570
|
+
deletedBy: {
|
|
8571
|
+
type: "text",
|
|
8572
|
+
nullable: true
|
|
8573
|
+
},
|
|
8574
|
+
scope: {
|
|
8575
|
+
type: "jsonb",
|
|
8576
|
+
nullable: true
|
|
8577
|
+
},
|
|
8578
|
+
scopeKey: {
|
|
8579
|
+
type: "text",
|
|
8580
|
+
nullable: true
|
|
8581
|
+
},
|
|
8582
|
+
sourceThreadId: {
|
|
8583
|
+
type: "text",
|
|
8584
|
+
nullable: true
|
|
8585
|
+
},
|
|
8586
|
+
when: {
|
|
8587
|
+
type: "timestamp",
|
|
8588
|
+
nullable: true
|
|
8589
|
+
}
|
|
8590
|
+
};
|
|
8591
|
+
const KNOWLEDGE_V2_MENTIONS_SCHEMA = {
|
|
8592
|
+
recordId: {
|
|
8593
|
+
type: "text",
|
|
8594
|
+
nullable: false,
|
|
8595
|
+
references: {
|
|
8596
|
+
table: TABLE_KNOWLEDGE_RECORDS$1,
|
|
8597
|
+
column: "id"
|
|
8598
|
+
}
|
|
8599
|
+
},
|
|
8600
|
+
targetNodeId: {
|
|
8601
|
+
type: "text",
|
|
8602
|
+
nullable: true,
|
|
8603
|
+
references: {
|
|
8604
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8605
|
+
column: "id"
|
|
8606
|
+
}
|
|
8607
|
+
},
|
|
8608
|
+
sourceType: {
|
|
8609
|
+
type: "text",
|
|
8610
|
+
nullable: true
|
|
8611
|
+
},
|
|
8612
|
+
sourceId: {
|
|
8613
|
+
type: "text",
|
|
8614
|
+
nullable: true
|
|
8615
|
+
}
|
|
8616
|
+
};
|
|
8617
|
+
const KNOWLEDGE_NODE_SCOPES_SCHEMA = {
|
|
8618
|
+
nodeId: {
|
|
8619
|
+
type: "text",
|
|
8620
|
+
nullable: false,
|
|
8621
|
+
references: {
|
|
8622
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8623
|
+
column: "id"
|
|
8624
|
+
}
|
|
8625
|
+
},
|
|
8626
|
+
scopeNodeId: {
|
|
8627
|
+
type: "text",
|
|
8628
|
+
nullable: false,
|
|
8629
|
+
references: {
|
|
8630
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8631
|
+
column: "id"
|
|
8632
|
+
}
|
|
8633
|
+
},
|
|
8634
|
+
addedAt: {
|
|
8635
|
+
type: "timestamp",
|
|
8636
|
+
nullable: false
|
|
8637
|
+
}
|
|
8638
|
+
};
|
|
8639
|
+
const KNOWLEDGE_RECORD_SCOPES_SCHEMA = {
|
|
8640
|
+
recordId: {
|
|
8641
|
+
type: "text",
|
|
8642
|
+
nullable: false,
|
|
8643
|
+
references: {
|
|
8644
|
+
table: TABLE_KNOWLEDGE_RECORDS$1,
|
|
8645
|
+
column: "id"
|
|
8646
|
+
}
|
|
8647
|
+
},
|
|
8648
|
+
scopeNodeId: {
|
|
8649
|
+
type: "text",
|
|
8650
|
+
nullable: false,
|
|
8651
|
+
references: {
|
|
8652
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8653
|
+
column: "id"
|
|
8654
|
+
}
|
|
8655
|
+
},
|
|
8656
|
+
addedAt: {
|
|
8657
|
+
type: "timestamp",
|
|
8658
|
+
nullable: false
|
|
8659
|
+
}
|
|
8660
|
+
};
|
|
8661
|
+
const KNOWLEDGE_SCOPE_GRANTS_SCHEMA = {
|
|
8662
|
+
scopeNodeId: {
|
|
8663
|
+
type: "text",
|
|
8664
|
+
nullable: false,
|
|
8665
|
+
references: {
|
|
8666
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8667
|
+
column: "id"
|
|
8668
|
+
}
|
|
8669
|
+
},
|
|
8670
|
+
scopeRefId: {
|
|
8671
|
+
type: "text",
|
|
8672
|
+
nullable: false,
|
|
8673
|
+
references: {
|
|
8674
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8675
|
+
column: "id"
|
|
8676
|
+
}
|
|
8677
|
+
},
|
|
8678
|
+
role: {
|
|
8679
|
+
type: "text",
|
|
8680
|
+
nullable: false
|
|
8681
|
+
},
|
|
8682
|
+
canSuggest: {
|
|
8683
|
+
type: "boolean",
|
|
8684
|
+
nullable: true
|
|
8685
|
+
}
|
|
8686
|
+
};
|
|
8687
|
+
const KNOWLEDGE_ACCESS_STATE_SCHEMA = {
|
|
8688
|
+
id: {
|
|
8689
|
+
type: "text",
|
|
8690
|
+
nullable: false,
|
|
8691
|
+
primaryKey: true
|
|
8692
|
+
},
|
|
8693
|
+
epoch: {
|
|
8694
|
+
type: "integer",
|
|
8695
|
+
nullable: false
|
|
8696
|
+
},
|
|
8697
|
+
schemaVersion: {
|
|
8698
|
+
type: "integer",
|
|
8699
|
+
nullable: false
|
|
8700
|
+
}
|
|
8701
|
+
};
|
|
8702
|
+
const KNOWLEDGE_SCOPE_ADDRESSES_SCHEMA = {
|
|
8703
|
+
address: {
|
|
8704
|
+
type: "text",
|
|
8705
|
+
nullable: false,
|
|
8706
|
+
primaryKey: true
|
|
8707
|
+
},
|
|
8708
|
+
scopeNodeId: {
|
|
8709
|
+
type: "text",
|
|
8710
|
+
nullable: false,
|
|
8711
|
+
references: {
|
|
8712
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8713
|
+
column: "id"
|
|
8714
|
+
}
|
|
8715
|
+
}
|
|
8716
|
+
};
|
|
8717
|
+
const KNOWLEDGE_NODE_ADDRESSES_SCHEMA = {
|
|
8718
|
+
source: {
|
|
8719
|
+
type: "text",
|
|
8720
|
+
nullable: false
|
|
8721
|
+
},
|
|
8722
|
+
address: {
|
|
8723
|
+
type: "text",
|
|
8724
|
+
nullable: false
|
|
8725
|
+
},
|
|
8726
|
+
nodeId: {
|
|
8727
|
+
type: "text",
|
|
8728
|
+
nullable: false,
|
|
8729
|
+
references: {
|
|
8730
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8731
|
+
column: "id"
|
|
8732
|
+
}
|
|
8733
|
+
}
|
|
8734
|
+
};
|
|
8735
|
+
const KNOWLEDGE_IMPORT_STATE_SCHEMA = {
|
|
8736
|
+
importerId: {
|
|
8737
|
+
type: "text",
|
|
8738
|
+
nullable: false
|
|
8739
|
+
},
|
|
8740
|
+
binding: {
|
|
8741
|
+
type: "text",
|
|
8742
|
+
nullable: false
|
|
8743
|
+
},
|
|
8744
|
+
key: {
|
|
8745
|
+
type: "text",
|
|
8746
|
+
nullable: false
|
|
8747
|
+
},
|
|
8748
|
+
value: {
|
|
8749
|
+
type: "text",
|
|
8750
|
+
nullable: false
|
|
8751
|
+
}
|
|
8752
|
+
};
|
|
8753
|
+
const KNOWLEDGE_IMPORT_RUNS_SCHEMA = {
|
|
8754
|
+
id: {
|
|
8755
|
+
type: "text",
|
|
8756
|
+
nullable: false,
|
|
8757
|
+
primaryKey: true
|
|
8758
|
+
},
|
|
8759
|
+
importerId: {
|
|
8760
|
+
type: "text",
|
|
8761
|
+
nullable: false
|
|
8762
|
+
},
|
|
8763
|
+
binding: {
|
|
8764
|
+
type: "text",
|
|
8765
|
+
nullable: false
|
|
8766
|
+
},
|
|
8767
|
+
importKind: {
|
|
8768
|
+
type: "text",
|
|
8769
|
+
nullable: false
|
|
8770
|
+
},
|
|
8771
|
+
triggerKind: {
|
|
8772
|
+
type: "text",
|
|
8773
|
+
nullable: false
|
|
8774
|
+
},
|
|
8775
|
+
status: {
|
|
8776
|
+
type: "text",
|
|
8777
|
+
nullable: false
|
|
8778
|
+
},
|
|
8779
|
+
error: {
|
|
8780
|
+
type: "text",
|
|
8781
|
+
nullable: true
|
|
8782
|
+
},
|
|
8783
|
+
transcriptThreadId: {
|
|
8784
|
+
type: "text",
|
|
8785
|
+
nullable: true
|
|
8786
|
+
},
|
|
8787
|
+
traceId: {
|
|
8788
|
+
type: "text",
|
|
8789
|
+
nullable: true
|
|
8790
|
+
},
|
|
8791
|
+
queuedAt: {
|
|
8792
|
+
type: "timestamp",
|
|
8793
|
+
nullable: false
|
|
8794
|
+
},
|
|
8795
|
+
startedAt: {
|
|
8796
|
+
type: "timestamp",
|
|
8797
|
+
nullable: true
|
|
8798
|
+
},
|
|
8799
|
+
completedAt: {
|
|
8800
|
+
type: "timestamp",
|
|
8801
|
+
nullable: true
|
|
8802
|
+
}
|
|
8803
|
+
};
|
|
8804
|
+
const KNOWLEDGE_V2_ACTIVITY_SCHEMA = {
|
|
8805
|
+
id: {
|
|
8806
|
+
type: "text",
|
|
8807
|
+
nullable: false,
|
|
8808
|
+
primaryKey: true
|
|
8809
|
+
},
|
|
8810
|
+
action: {
|
|
8811
|
+
type: "text",
|
|
8812
|
+
nullable: false
|
|
8813
|
+
},
|
|
8814
|
+
targetType: {
|
|
8815
|
+
type: "text",
|
|
8816
|
+
nullable: true
|
|
8817
|
+
},
|
|
8818
|
+
targetId: {
|
|
8819
|
+
type: "text",
|
|
8820
|
+
nullable: true
|
|
8821
|
+
},
|
|
8822
|
+
contextScopeId: {
|
|
8823
|
+
type: "text",
|
|
8824
|
+
nullable: true,
|
|
8825
|
+
references: {
|
|
8826
|
+
table: TABLE_KNOWLEDGE_NODES$1,
|
|
8827
|
+
column: "id"
|
|
8828
|
+
}
|
|
8829
|
+
},
|
|
8830
|
+
importRunId: {
|
|
8831
|
+
type: "text",
|
|
8832
|
+
nullable: true,
|
|
8833
|
+
references: {
|
|
8834
|
+
table: TABLE_KNOWLEDGE_IMPORT_RUNS,
|
|
8835
|
+
column: "id"
|
|
8836
|
+
}
|
|
8837
|
+
},
|
|
8838
|
+
details: {
|
|
8839
|
+
type: "jsonb",
|
|
8840
|
+
nullable: true
|
|
8841
|
+
},
|
|
8842
|
+
createdAt: {
|
|
8843
|
+
type: "timestamp",
|
|
8844
|
+
nullable: false
|
|
8845
|
+
},
|
|
8846
|
+
recordType: {
|
|
8847
|
+
type: "text",
|
|
8848
|
+
nullable: true
|
|
8849
|
+
},
|
|
8850
|
+
recordId: {
|
|
8851
|
+
type: "text",
|
|
8852
|
+
nullable: true
|
|
8853
|
+
},
|
|
8854
|
+
scope: {
|
|
8855
|
+
type: "jsonb",
|
|
8856
|
+
nullable: true
|
|
8857
|
+
},
|
|
8858
|
+
scopeKey: {
|
|
8859
|
+
type: "text",
|
|
8860
|
+
nullable: true
|
|
8861
|
+
},
|
|
8862
|
+
sourceThreadId: {
|
|
8863
|
+
type: "text",
|
|
8864
|
+
nullable: true
|
|
8865
|
+
}
|
|
8866
|
+
};
|
|
8867
|
+
const KNOWLEDGE_PROPOSALS_SCHEMA = {
|
|
8868
|
+
id: {
|
|
8869
|
+
type: "text",
|
|
8870
|
+
nullable: false,
|
|
8871
|
+
primaryKey: true
|
|
8872
|
+
},
|
|
8873
|
+
targetType: {
|
|
8874
|
+
type: "text",
|
|
8875
|
+
nullable: false
|
|
8876
|
+
},
|
|
8877
|
+
targetId: {
|
|
8878
|
+
type: "text",
|
|
8879
|
+
nullable: false
|
|
8880
|
+
},
|
|
8881
|
+
action: {
|
|
8882
|
+
type: "text",
|
|
8883
|
+
nullable: false
|
|
8884
|
+
},
|
|
8885
|
+
changes: {
|
|
8886
|
+
type: "jsonb",
|
|
8887
|
+
nullable: false
|
|
8888
|
+
},
|
|
8889
|
+
reason: {
|
|
8890
|
+
type: "text",
|
|
8891
|
+
nullable: true
|
|
8892
|
+
},
|
|
8893
|
+
proposerContextScopeId: {
|
|
8894
|
+
type: "text",
|
|
8895
|
+
nullable: false
|
|
8896
|
+
},
|
|
8897
|
+
expectedVersion: {
|
|
8898
|
+
type: "integer",
|
|
8899
|
+
nullable: false
|
|
8900
|
+
},
|
|
8901
|
+
status: {
|
|
8902
|
+
type: "text",
|
|
8903
|
+
nullable: false
|
|
8904
|
+
},
|
|
8905
|
+
reviewerContextScopeId: {
|
|
8906
|
+
type: "text",
|
|
8907
|
+
nullable: true
|
|
8908
|
+
},
|
|
8909
|
+
reviewedAt: {
|
|
8910
|
+
type: "timestamp",
|
|
8911
|
+
nullable: true
|
|
8912
|
+
},
|
|
8913
|
+
createdAt: {
|
|
8914
|
+
type: "timestamp",
|
|
8915
|
+
nullable: false
|
|
8916
|
+
}
|
|
8917
|
+
};
|
|
8918
|
+
function assertKnowledgeV2CoreSupport(features) {
|
|
8919
|
+
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.`);
|
|
8920
|
+
}
|
|
8921
|
+
function resolveKnowledgeV2Core(storageModule) {
|
|
8922
|
+
if (typeof storageModule !== "object" || storageModule === null) throw new Error("@mastra/core advertises Knowledge v2 without the required storage API");
|
|
8923
|
+
const { assertKnowledgeDescriptionWithinBound: assertDescription, assertKnowledgeRecordTextWithinBound: assertRecordText, assertKnowledgeSchemaCompatible: assertCompatible, inspectKnowledgeSchema: inspectSchema } = storageModule;
|
|
8924
|
+
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");
|
|
8925
|
+
return {
|
|
8926
|
+
assertKnowledgeDescriptionWithinBound: (description) => assertDescription(description),
|
|
8927
|
+
assertKnowledgeRecordTextWithinBound: (text) => assertRecordText(text),
|
|
8928
|
+
assertKnowledgeSchemaCompatible: (inspection) => assertCompatible(inspection),
|
|
8929
|
+
inspectKnowledgeSchema: (snapshot) => inspectSchema(snapshot)
|
|
8930
|
+
};
|
|
8931
|
+
}
|
|
8932
|
+
function createKnowledgeV2CoreLoader(features, loadStorageModule) {
|
|
8933
|
+
let knowledgeV2Core;
|
|
8934
|
+
return async () => {
|
|
8935
|
+
assertKnowledgeV2CoreSupport(features);
|
|
8936
|
+
knowledgeV2Core ??= loadStorageModule().then(resolveKnowledgeV2Core).catch((error) => {
|
|
8937
|
+
knowledgeV2Core = void 0;
|
|
8938
|
+
throw error;
|
|
8939
|
+
});
|
|
8940
|
+
return knowledgeV2Core;
|
|
8941
|
+
};
|
|
8942
|
+
}
|
|
8943
|
+
//#endregion
|
|
8304
8944
|
//#region src/storage/domains/knowledge/index.ts
|
|
8305
|
-
|
|
8945
|
+
const loadKnowledgeV2Core = createKnowledgeV2CoreLoader(_mastra_core_features.coreFeatures, () => import("@mastra/core/storage"));
|
|
8306
8946
|
async function assertKnowledgeDescriptionWithinBoundCompat(description) {
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
assertWithinBound = resolvedAssert;
|
|
8314
|
-
}
|
|
8315
|
-
assertWithinBound(description);
|
|
8947
|
+
const { assertKnowledgeDescriptionWithinBound } = await loadKnowledgeV2Core();
|
|
8948
|
+
assertKnowledgeDescriptionWithinBound(description);
|
|
8949
|
+
}
|
|
8950
|
+
async function assertKnowledgeRecordTextWithinBoundCompat(text) {
|
|
8951
|
+
const { assertKnowledgeRecordTextWithinBound } = await loadKnowledgeV2Core();
|
|
8952
|
+
assertKnowledgeRecordTextWithinBound(text);
|
|
8316
8953
|
}
|
|
8317
8954
|
const camelCaseColumns = [
|
|
8318
8955
|
"canonicalName",
|
|
@@ -8323,7 +8960,6 @@ const camelCaseColumns = [
|
|
|
8323
8960
|
"node",
|
|
8324
8961
|
"sourceThreadId",
|
|
8325
8962
|
"capturedAt",
|
|
8326
|
-
"maxScope",
|
|
8327
8963
|
"deletedAt",
|
|
8328
8964
|
"deletedBy",
|
|
8329
8965
|
"sourceType",
|
|
@@ -8337,7 +8973,30 @@ const camelCaseColumns = [
|
|
|
8337
8973
|
"availableAt",
|
|
8338
8974
|
"claimedAt",
|
|
8339
8975
|
"claimedBy",
|
|
8340
|
-
"completedAt"
|
|
8976
|
+
"completedAt",
|
|
8977
|
+
"isScope",
|
|
8978
|
+
"nodeId",
|
|
8979
|
+
"targetNodeId",
|
|
8980
|
+
"scopeNodeId",
|
|
8981
|
+
"scopeRefId",
|
|
8982
|
+
"canSuggest",
|
|
8983
|
+
"schemaVersion",
|
|
8984
|
+
"importerId",
|
|
8985
|
+
"importKind",
|
|
8986
|
+
"triggerKind",
|
|
8987
|
+
"transcriptThreadId",
|
|
8988
|
+
"traceId",
|
|
8989
|
+
"queuedAt",
|
|
8990
|
+
"startedAt",
|
|
8991
|
+
"targetType",
|
|
8992
|
+
"targetId",
|
|
8993
|
+
"contextScopeId",
|
|
8994
|
+
"importRunId",
|
|
8995
|
+
"proposerContextScopeId",
|
|
8996
|
+
"expectedVersion",
|
|
8997
|
+
"reviewerContextScopeId",
|
|
8998
|
+
"reviewedAt",
|
|
8999
|
+
"addedAt"
|
|
8341
9000
|
];
|
|
8342
9001
|
function transformSqlCode(sql, transform) {
|
|
8343
9002
|
return sql.split(/('(?:''|[^'])*')/g).map((part, index) => index % 2 === 0 ? transform(part) : part).join("");
|
|
@@ -8352,14 +9011,7 @@ function postgresSql(sql, schemaName) {
|
|
|
8352
9011
|
const quotedSchema = `"${parseSchemaName(schemaName)}"`;
|
|
8353
9012
|
normalized = transformSqlCode(normalized, (code) => {
|
|
8354
9013
|
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}"`);
|
|
9014
|
+
for (const table of [...KNOWLEDGE_TABLE_NAMES, ...RETIRED_KNOWLEDGE_TABLE_NAMES]) transformed = transformed.replaceAll(`"${table}"`, `${quotedSchema}."${table}"`);
|
|
8363
9015
|
return transformed;
|
|
8364
9016
|
});
|
|
8365
9017
|
}
|
|
@@ -8367,17 +9019,35 @@ function postgresSql(sql, schemaName) {
|
|
|
8367
9019
|
return transformSqlCode(normalized, (code) => code.replace(/\?/g, () => `$${++index}`));
|
|
8368
9020
|
}
|
|
8369
9021
|
function createExecutor(client, schemaName) {
|
|
8370
|
-
|
|
9022
|
+
const execute = async (statement, qualifyWithSchema) => {
|
|
8371
9023
|
const sql = typeof statement === "string" ? statement : statement.sql;
|
|
8372
9024
|
const args = typeof statement === "string" ? [] : statement.args ?? [];
|
|
8373
|
-
const result = await client.query(postgresSql(sql, schemaName), args);
|
|
9025
|
+
const result = await client.query(postgresSql(sql, qualifyWithSchema ? schemaName : void 0), args);
|
|
8374
9026
|
return {
|
|
8375
9027
|
rows: result.rows,
|
|
8376
9028
|
rowsAffected: result.rowCount ?? 0
|
|
8377
9029
|
};
|
|
8378
|
-
}
|
|
9030
|
+
};
|
|
9031
|
+
return {
|
|
9032
|
+
execute: (statement) => execute(statement, true),
|
|
9033
|
+
executeRaw: (statement) => execute(statement, false)
|
|
9034
|
+
};
|
|
8379
9035
|
}
|
|
8380
|
-
|
|
9036
|
+
/**
|
|
9037
|
+
* Scope keys visible to a caller holding `scope`: a row is visible when its scope is a subset of the
|
|
9038
|
+
* caller's (companion entries such as `resource:x:uncurated` make this more than a prefix match).
|
|
9039
|
+
* Matching rows by `scopeKey` keeps visibility filters on an index; a caller scope has only a few
|
|
9040
|
+
* entries, so the list stays small.
|
|
9041
|
+
*/
|
|
9042
|
+
function visibleScopeKeys(scope) {
|
|
9043
|
+
const canonical = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(scope);
|
|
9044
|
+
const keys = /* @__PURE__ */ new Set();
|
|
9045
|
+
for (let mask = 1; mask < 1 << canonical.length; mask++) try {
|
|
9046
|
+
keys.add((0, _mastra_core_storage.knowledgeScopeKey)(canonical.filter((_, index) => mask & 1 << index)));
|
|
9047
|
+
} catch {}
|
|
9048
|
+
return [...keys];
|
|
9049
|
+
}
|
|
9050
|
+
const visibleSql = (keys, scopeKeyColumn = "scopeKey") => `${scopeKeyColumn} IN (${keys.map(() => "?").join(",")})`;
|
|
8381
9051
|
function parseJson$1(value) {
|
|
8382
9052
|
if (typeof value === "string") return JSON.parse(value);
|
|
8383
9053
|
if (value instanceof Uint8Array) return JSON.parse(new TextDecoder().decode(value));
|
|
@@ -8417,9 +9087,10 @@ function parseNode(row) {
|
|
|
8417
9087
|
id: String(row.id),
|
|
8418
9088
|
type: "node",
|
|
8419
9089
|
name: String(row.name),
|
|
8420
|
-
kind: String(row.kind),
|
|
9090
|
+
kind: row.kind == null ? "" : String(row.kind),
|
|
8421
9091
|
content: row.content == null ? void 0 : String(row.content),
|
|
8422
9092
|
description: row.description == null ? void 0 : String(row.description),
|
|
9093
|
+
isScope: row.isScope === true || row.isScope === 1 ? true : void 0,
|
|
8423
9094
|
scope: parseJson$1(row.scopeJson ?? row.scope),
|
|
8424
9095
|
version: Number(row.version),
|
|
8425
9096
|
mergedInto: row.mergedInto == null ? void 0 : String(row.mergedInto),
|
|
@@ -8436,7 +9107,6 @@ function parseKnowledge(row) {
|
|
|
8436
9107
|
sourceThreadId: String(row.sourceThreadId),
|
|
8437
9108
|
capturedAt: toDate$1(row.capturedAt),
|
|
8438
9109
|
when: optionalDate(row.when),
|
|
8439
|
-
maxScope: row.maxScope == null ? void 0 : String(row.maxScope),
|
|
8440
9110
|
metadata: row.metadata == null ? void 0 : parseJson$1(row.metadata),
|
|
8441
9111
|
deletedAt: optionalDate(row.deletedAt),
|
|
8442
9112
|
deletedBy: row.deletedBy == null ? void 0 : String(row.deletedBy)
|
|
@@ -8473,6 +9143,10 @@ function knowledgeIndexes(schemaName) {
|
|
|
8473
9143
|
name: "idx_knowledge_nodes_scope",
|
|
8474
9144
|
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_nodes_scope ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_NODES)} ("scopeKey", "type");`
|
|
8475
9145
|
},
|
|
9146
|
+
{
|
|
9147
|
+
name: "idx_knowledge_nodes_name",
|
|
9148
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_nodes_name ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_NODES)} ("type", "canonicalName");`
|
|
9149
|
+
},
|
|
8476
9150
|
{
|
|
8477
9151
|
name: "idx_knowledge_records_node_latest",
|
|
8478
9152
|
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_records_node_latest ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS)} ("node", "id" DESC);`
|
|
@@ -8489,6 +9163,14 @@ function knowledgeIndexes(schemaName) {
|
|
|
8489
9163
|
name: "idx_knowledge_activity_latest",
|
|
8490
9164
|
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_latest ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY)} ("id" DESC);`
|
|
8491
9165
|
},
|
|
9166
|
+
{
|
|
9167
|
+
name: "idx_knowledge_records_scope",
|
|
9168
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_records_scope ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS)} ("scopeKey", "id");`
|
|
9169
|
+
},
|
|
9170
|
+
{
|
|
9171
|
+
name: "idx_knowledge_activity_scope",
|
|
9172
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_scope ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY)} ("scopeKey", "id" DESC);`
|
|
9173
|
+
},
|
|
8492
9174
|
{
|
|
8493
9175
|
name: "idx_knowledge_outbox_idempotency",
|
|
8494
9176
|
sql: `CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_outbox_idempotency ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX)} ("idempotencyKey");`
|
|
@@ -8496,67 +9178,152 @@ function knowledgeIndexes(schemaName) {
|
|
|
8496
9178
|
{
|
|
8497
9179
|
name: "idx_knowledge_outbox_claim",
|
|
8498
9180
|
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_outbox_claim ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX)} ("status", "availableAt", "createdAt");`
|
|
9181
|
+
},
|
|
9182
|
+
{
|
|
9183
|
+
name: "idx_knowledge_node_scopes_scope",
|
|
9184
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_node_scopes_scope ON ${table(TABLE_KNOWLEDGE_NODE_SCOPES)} ("scopeNodeId", "nodeId");`
|
|
9185
|
+
},
|
|
9186
|
+
{
|
|
9187
|
+
name: "idx_knowledge_record_scopes_scope",
|
|
9188
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_record_scopes_scope ON ${table(TABLE_KNOWLEDGE_RECORD_SCOPES)} ("scopeNodeId", "recordId");`
|
|
9189
|
+
},
|
|
9190
|
+
{
|
|
9191
|
+
name: "idx_knowledge_scope_grants_ref",
|
|
9192
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_scope_grants_ref ON ${table(TABLE_KNOWLEDGE_SCOPE_GRANTS)} ("scopeRefId", "scopeNodeId");`
|
|
9193
|
+
},
|
|
9194
|
+
{
|
|
9195
|
+
name: "idx_knowledge_node_addresses_node",
|
|
9196
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_node_addresses_node ON ${table(TABLE_KNOWLEDGE_NODE_ADDRESSES)} ("nodeId");`
|
|
9197
|
+
},
|
|
9198
|
+
{
|
|
9199
|
+
name: "idx_knowledge_import_runs_lookup",
|
|
9200
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_import_runs_lookup ON ${table(TABLE_KNOWLEDGE_IMPORT_RUNS)} ("importerId", "binding", "queuedAt" DESC);`
|
|
9201
|
+
},
|
|
9202
|
+
{
|
|
9203
|
+
name: "idx_knowledge_activity_import_run",
|
|
9204
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_import_run ON ${table(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY)} ("importRunId", "id" DESC);`
|
|
8499
9205
|
}
|
|
8500
9206
|
];
|
|
8501
9207
|
}
|
|
8502
9208
|
function knowledgeIndexDDL(schemaName) {
|
|
8503
9209
|
return knowledgeIndexes(schemaName).map((index) => index.sql);
|
|
8504
9210
|
}
|
|
9211
|
+
const KNOWLEDGE_CURATION_CURSOR_REMOVED_MESSAGE = "Knowledge curation cursors were removed: observation-time curate is the only Knowledge writer and needs no cursor.";
|
|
9212
|
+
const knowledgeTableDefinitions = [
|
|
9213
|
+
{
|
|
9214
|
+
tableName: _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
|
|
9215
|
+
schema: KNOWLEDGE_V2_NODES_SCHEMA
|
|
9216
|
+
},
|
|
9217
|
+
{
|
|
9218
|
+
tableName: _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
|
|
9219
|
+
schema: KNOWLEDGE_V2_RECORDS_SCHEMA
|
|
9220
|
+
},
|
|
9221
|
+
{
|
|
9222
|
+
tableName: _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
|
|
9223
|
+
schema: KNOWLEDGE_V2_MENTIONS_SCHEMA,
|
|
9224
|
+
compositePrimaryKey: ["recordId", "sourceId"]
|
|
9225
|
+
},
|
|
9226
|
+
{
|
|
9227
|
+
tableName: TABLE_KNOWLEDGE_NODE_SCOPES,
|
|
9228
|
+
schema: KNOWLEDGE_NODE_SCOPES_SCHEMA,
|
|
9229
|
+
compositePrimaryKey: ["nodeId", "scopeNodeId"]
|
|
9230
|
+
},
|
|
9231
|
+
{
|
|
9232
|
+
tableName: TABLE_KNOWLEDGE_RECORD_SCOPES,
|
|
9233
|
+
schema: KNOWLEDGE_RECORD_SCOPES_SCHEMA,
|
|
9234
|
+
compositePrimaryKey: ["recordId", "scopeNodeId"]
|
|
9235
|
+
},
|
|
9236
|
+
{
|
|
9237
|
+
tableName: TABLE_KNOWLEDGE_SCOPE_GRANTS,
|
|
9238
|
+
schema: KNOWLEDGE_SCOPE_GRANTS_SCHEMA,
|
|
9239
|
+
compositePrimaryKey: ["scopeNodeId", "scopeRefId"]
|
|
9240
|
+
},
|
|
9241
|
+
{
|
|
9242
|
+
tableName: TABLE_KNOWLEDGE_ACCESS_STATE,
|
|
9243
|
+
schema: KNOWLEDGE_ACCESS_STATE_SCHEMA
|
|
9244
|
+
},
|
|
9245
|
+
{
|
|
9246
|
+
tableName: TABLE_KNOWLEDGE_SCOPE_ADDRESSES,
|
|
9247
|
+
schema: KNOWLEDGE_SCOPE_ADDRESSES_SCHEMA
|
|
9248
|
+
},
|
|
9249
|
+
{
|
|
9250
|
+
tableName: TABLE_KNOWLEDGE_NODE_ADDRESSES,
|
|
9251
|
+
schema: KNOWLEDGE_NODE_ADDRESSES_SCHEMA,
|
|
9252
|
+
compositePrimaryKey: ["source", "address"]
|
|
9253
|
+
},
|
|
9254
|
+
{
|
|
9255
|
+
tableName: TABLE_KNOWLEDGE_IMPORT_STATE,
|
|
9256
|
+
schema: KNOWLEDGE_IMPORT_STATE_SCHEMA,
|
|
9257
|
+
compositePrimaryKey: [
|
|
9258
|
+
"importerId",
|
|
9259
|
+
"binding",
|
|
9260
|
+
"key"
|
|
9261
|
+
]
|
|
9262
|
+
},
|
|
9263
|
+
{
|
|
9264
|
+
tableName: TABLE_KNOWLEDGE_IMPORT_RUNS,
|
|
9265
|
+
schema: KNOWLEDGE_IMPORT_RUNS_SCHEMA
|
|
9266
|
+
},
|
|
9267
|
+
{
|
|
9268
|
+
tableName: TABLE_KNOWLEDGE_PROPOSALS,
|
|
9269
|
+
schema: KNOWLEDGE_PROPOSALS_SCHEMA
|
|
9270
|
+
},
|
|
9271
|
+
{
|
|
9272
|
+
tableName: _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
|
|
9273
|
+
schema: KNOWLEDGE_V2_ACTIVITY_SCHEMA
|
|
9274
|
+
},
|
|
9275
|
+
{
|
|
9276
|
+
tableName: _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
|
|
9277
|
+
schema: _mastra_core_storage.KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA
|
|
9278
|
+
}
|
|
9279
|
+
];
|
|
9280
|
+
function pgSetting(config, key) {
|
|
9281
|
+
const value = config[key] || process.env[`PG${key.toUpperCase()}`] || pg.defaults[key];
|
|
9282
|
+
return value === void 0 || value === null || value === "" ? void 0 : String(value);
|
|
9283
|
+
}
|
|
9284
|
+
function effectivePgTarget(config) {
|
|
9285
|
+
const host = pgSetting(config, "host");
|
|
9286
|
+
const database = pgSetting(config, "database") ?? pgSetting(config, "user");
|
|
9287
|
+
if (!host || !database) return void 0;
|
|
9288
|
+
return `${host.startsWith("/") ? host : host.toLocaleLowerCase()}:${pgSetting(config, "port") ?? "5432"}/${database}`;
|
|
9289
|
+
}
|
|
9290
|
+
function canonicalPgTarget(config) {
|
|
9291
|
+
if (config.connectionString) try {
|
|
9292
|
+
const parsed = new URL(config.connectionString);
|
|
9293
|
+
return effectivePgTarget({
|
|
9294
|
+
host: decodeURIComponent(parsed.hostname) || config.host,
|
|
9295
|
+
port: parsed.port || config.port,
|
|
9296
|
+
database: decodeURIComponent(parsed.pathname.slice(1)) || config.database,
|
|
9297
|
+
user: decodeURIComponent(parsed.username) || config.user
|
|
9298
|
+
});
|
|
9299
|
+
} catch {
|
|
9300
|
+
return config.connectionString;
|
|
9301
|
+
}
|
|
9302
|
+
return effectivePgTarget(config);
|
|
9303
|
+
}
|
|
9304
|
+
function pgSourceConfig(source) {
|
|
9305
|
+
if (!source || !("options" in source)) return void 0;
|
|
9306
|
+
return source.options;
|
|
9307
|
+
}
|
|
9308
|
+
function pgClientPool(client) {
|
|
9309
|
+
if (!client || !("$pool" in client)) return void 0;
|
|
9310
|
+
return client.$pool;
|
|
9311
|
+
}
|
|
9312
|
+
function getPgKnowledgeIsolationKey(config) {
|
|
9313
|
+
const schema = config.schemaName ?? "public";
|
|
9314
|
+
const poolConfig = pgSourceConfig(config.pool ?? pgClientPool(config.client));
|
|
9315
|
+
const target = Boolean(config.connectionString || config.host || config.database) ? canonicalPgTarget(config) : poolConfig ? canonicalPgTarget(poolConfig) : void 0;
|
|
9316
|
+
if (target) return `pg:${target}:schema:${schema}`;
|
|
9317
|
+
return `pg:unidentified:schema:${schema}`;
|
|
9318
|
+
}
|
|
8505
9319
|
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
|
-
];
|
|
9320
|
+
static MANAGED_TABLES = KNOWLEDGE_TABLE_NAMES;
|
|
8514
9321
|
static getExportDDL(schemaName) {
|
|
8515
|
-
return [
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
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
|
-
];
|
|
9322
|
+
return [...knowledgeTableDefinitions.map((definition) => generateTableSQL({
|
|
9323
|
+
...definition,
|
|
9324
|
+
schemaName,
|
|
9325
|
+
includeAllConstraints: true
|
|
9326
|
+
})), ...knowledgeIndexDDL(schemaName)];
|
|
8560
9327
|
}
|
|
8561
9328
|
#client;
|
|
8562
9329
|
#executor;
|
|
@@ -8565,7 +9332,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8565
9332
|
#db;
|
|
8566
9333
|
#schemaName;
|
|
8567
9334
|
constructor(config) {
|
|
8568
|
-
super();
|
|
9335
|
+
super({ storageIsolationKey: config.storageIsolationKey ?? getPgKnowledgeIsolationKey(config) });
|
|
8569
9336
|
const { client, readClient, schemaName, skipDefaultIndexes } = resolvePgConfig(config);
|
|
8570
9337
|
this.#client = client;
|
|
8571
9338
|
this.#schemaName = schemaName;
|
|
@@ -8578,55 +9345,358 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8578
9345
|
skipDefaultIndexes
|
|
8579
9346
|
});
|
|
8580
9347
|
}
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
9348
|
+
getCapabilities() {
|
|
9349
|
+
return {
|
|
9350
|
+
contractVersion: 2,
|
|
9351
|
+
schemaVersion: 2,
|
|
9352
|
+
supportsV2: true,
|
|
9353
|
+
supportsSchemaInspection: true,
|
|
9354
|
+
supportsExplicitReset: true
|
|
9355
|
+
};
|
|
9356
|
+
}
|
|
9357
|
+
async inspectSchema() {
|
|
9358
|
+
const { inspectKnowledgeSchema } = await loadKnowledgeV2Core();
|
|
9359
|
+
try {
|
|
9360
|
+
const snapshot = getSchemaSnapshot(this.#client, this.#schemaName);
|
|
9361
|
+
if (snapshot) {
|
|
9362
|
+
const tableNames = KNOWLEDGE_TABLE_NAMES.filter((table) => snapshot.tables.has(table));
|
|
9363
|
+
return this.#classifySchema(this.#executor, tableNames, snapshot.columns);
|
|
9364
|
+
}
|
|
9365
|
+
return this.#inspectSchemaWithExecutor(this.#executor);
|
|
9366
|
+
} catch (error) {
|
|
9367
|
+
return inspectKnowledgeSchema({
|
|
9368
|
+
available: false,
|
|
9369
|
+
tableNames: [],
|
|
9370
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
9371
|
+
});
|
|
9372
|
+
}
|
|
9373
|
+
}
|
|
9374
|
+
async #inspectSchemaWithExecutor(executor) {
|
|
9375
|
+
const tableNames = (await executor.execute({
|
|
9376
|
+
sql: `SELECT table_name FROM information_schema.tables WHERE table_schema = COALESCE(?, current_schema()) AND table_name = ANY(?::text[])`,
|
|
9377
|
+
args: [this.#schemaName ?? null, [...KNOWLEDGE_TABLE_NAMES]]
|
|
9378
|
+
})).rows.map((row) => String(row.table_name));
|
|
9379
|
+
const columnResult = await executor.execute({
|
|
9380
|
+
sql: `SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = COALESCE(?, current_schema()) AND table_name = ANY(?::text[])`,
|
|
9381
|
+
args: [this.#schemaName ?? null, [...KNOWLEDGE_TABLE_NAMES]]
|
|
9382
|
+
});
|
|
9383
|
+
const columns = /* @__PURE__ */ new Map();
|
|
9384
|
+
for (const row of columnResult.rows) {
|
|
9385
|
+
const table = String(row.table_name);
|
|
9386
|
+
const names = columns.get(table) ?? /* @__PURE__ */ new Set();
|
|
9387
|
+
names.add(String(row.column_name));
|
|
9388
|
+
columns.set(table, names);
|
|
9389
|
+
}
|
|
9390
|
+
return this.#classifySchema(executor, tableNames, columns);
|
|
9391
|
+
}
|
|
9392
|
+
async #classifySchema(executor, tableNames, columns) {
|
|
9393
|
+
const { inspectKnowledgeSchema } = await loadKnowledgeV2Core();
|
|
9394
|
+
if (tableNames.length === 0) return inspectKnowledgeSchema({
|
|
9395
|
+
available: true,
|
|
9396
|
+
tableNames
|
|
9397
|
+
});
|
|
9398
|
+
const missingTables = KNOWLEDGE_TABLE_NAMES.filter((table) => !tableNames.includes(table));
|
|
9399
|
+
if (missingTables.length > 0) return inspectKnowledgeSchema({
|
|
9400
|
+
available: true,
|
|
9401
|
+
tableNames,
|
|
9402
|
+
reason: `Missing Knowledge v2 tables: ${missingTables.join(", ")}`
|
|
9403
|
+
});
|
|
9404
|
+
for (const { tableName: table, schema } of knowledgeTableDefinitions) {
|
|
9405
|
+
const actual = columns.get(table) ?? /* @__PURE__ */ new Set();
|
|
9406
|
+
const missing = Object.keys(schema).filter((column) => !actual.has(column));
|
|
9407
|
+
if (missing.length > 0) return inspectKnowledgeSchema({
|
|
9408
|
+
available: true,
|
|
9409
|
+
tableNames,
|
|
9410
|
+
reason: `Knowledge table ${table} is missing v2 columns: ${missing.join(", ")}`
|
|
9411
|
+
});
|
|
9412
|
+
}
|
|
9413
|
+
const accessState = await executor.execute(`SELECT schemaVersion FROM "${TABLE_KNOWLEDGE_ACCESS_STATE}" WHERE id='global'`);
|
|
9414
|
+
if (Number(accessState.rows[0]?.schemaVersion) !== 2) return inspectKnowledgeSchema({
|
|
9415
|
+
available: true,
|
|
9416
|
+
tableNames,
|
|
9417
|
+
reason: "Knowledge schema version marker is missing or incompatible"
|
|
9418
|
+
});
|
|
9419
|
+
return inspectKnowledgeSchema({
|
|
9420
|
+
available: true,
|
|
9421
|
+
tableNames,
|
|
9422
|
+
schemaVersion: 2
|
|
8590
9423
|
});
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
9424
|
+
}
|
|
9425
|
+
async init() {
|
|
9426
|
+
await this.#transaction(async (tx) => {
|
|
9427
|
+
await tx.execute({
|
|
9428
|
+
sql: "SELECT pg_advisory_xact_lock(hashtext(?))",
|
|
9429
|
+
args: [`mastra-knowledge-v2:${this.#schemaName ?? "current_schema"}`]
|
|
9430
|
+
});
|
|
9431
|
+
const { assertKnowledgeSchemaCompatible } = await loadKnowledgeV2Core();
|
|
9432
|
+
let inspection = await this.#inspectSchemaWithExecutor(tx);
|
|
9433
|
+
if (inspection.status === "incompatible-reset-required" && await this.#isPublishedV1Layout(tx)) {
|
|
9434
|
+
const tables = [...RETIRED_KNOWLEDGE_TABLE_NAMES, ...[...KNOWLEDGE_TABLE_NAMES].reverse()].map((table) => `"${table}"`).join(", ");
|
|
9435
|
+
await tx.execute(`DROP TABLE IF EXISTS ${tables}`);
|
|
9436
|
+
inspection = await this.#inspectSchemaWithExecutor(tx);
|
|
9437
|
+
}
|
|
9438
|
+
assertKnowledgeSchemaCompatible(inspection);
|
|
9439
|
+
for (const definition of knowledgeTableDefinitions) await tx.executeRaw(generateTableSQL({
|
|
9440
|
+
...definition,
|
|
9441
|
+
schemaName: this.#schemaName,
|
|
9442
|
+
includeAllConstraints: true
|
|
9443
|
+
}));
|
|
9444
|
+
for (const index of knowledgeIndexes(this.#schemaName)) await tx.executeRaw(index.sql);
|
|
9445
|
+
await tx.execute({
|
|
9446
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_ACCESS_STATE}" (id, epoch, schemaVersion) VALUES ('global', 0, ?) ON CONFLICT (id) DO NOTHING`,
|
|
9447
|
+
args: [2]
|
|
9448
|
+
});
|
|
8594
9449
|
});
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
9450
|
+
}
|
|
9451
|
+
/**
|
|
9452
|
+
* True when the only Knowledge objects are the tables and indexes published v1 adapters created,
|
|
9453
|
+
* with or without rows. Anything else (v2 tables, unknown tables, views, triggers, extra indexes)
|
|
9454
|
+
* needs an explicit reset.
|
|
9455
|
+
*/
|
|
9456
|
+
async #isPublishedV1Layout(executor) {
|
|
9457
|
+
const schema = this.#schemaName ?? null;
|
|
9458
|
+
const relations = await executor.execute({
|
|
9459
|
+
sql: `SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = COALESCE(?, current_schema()) AND table_name LIKE 'mastra\\_knowledge\\_%'`,
|
|
9460
|
+
args: [schema]
|
|
9461
|
+
});
|
|
9462
|
+
const tables = [];
|
|
9463
|
+
for (const row of relations.rows) {
|
|
9464
|
+
const name = String(row.table_name);
|
|
9465
|
+
if (row.table_type !== "BASE TABLE" || !PUBLISHED_KNOWLEDGE_V1_TABLE_NAMES.has(name)) return false;
|
|
9466
|
+
tables.push(name);
|
|
9467
|
+
}
|
|
9468
|
+
const indexes = await executor.execute({
|
|
9469
|
+
sql: `SELECT indexname FROM pg_indexes WHERE schemaname = COALESCE(?, current_schema()) AND tablename = ANY(?::text[])`,
|
|
9470
|
+
args: [schema, tables]
|
|
9471
|
+
});
|
|
9472
|
+
for (const row of indexes.rows) {
|
|
9473
|
+
const name = String(row.indexname);
|
|
9474
|
+
if (!PUBLISHED_KNOWLEDGE_V1_INDEX_NAMES.has(name) && !name.endsWith("_pkey")) return false;
|
|
9475
|
+
}
|
|
9476
|
+
if ((await executor.execute({
|
|
9477
|
+
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`,
|
|
9478
|
+
args: [
|
|
9479
|
+
schema,
|
|
9480
|
+
tables,
|
|
9481
|
+
schema,
|
|
9482
|
+
tables
|
|
8602
9483
|
]
|
|
9484
|
+
})).rows.length > 0) return false;
|
|
9485
|
+
return true;
|
|
9486
|
+
}
|
|
9487
|
+
async dangerouslyClearAll() {
|
|
9488
|
+
await this.#transaction(async (tx) => {
|
|
9489
|
+
for (const table of [
|
|
9490
|
+
TABLE_KNOWLEDGE_RECORD_SCOPES,
|
|
9491
|
+
TABLE_KNOWLEDGE_NODE_SCOPES,
|
|
9492
|
+
TABLE_KNOWLEDGE_SCOPE_GRANTS,
|
|
9493
|
+
TABLE_KNOWLEDGE_SCOPE_ADDRESSES,
|
|
9494
|
+
TABLE_KNOWLEDGE_NODE_ADDRESSES,
|
|
9495
|
+
_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
|
|
9496
|
+
TABLE_KNOWLEDGE_PROPOSALS,
|
|
9497
|
+
_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
|
|
9498
|
+
TABLE_KNOWLEDGE_IMPORT_STATE,
|
|
9499
|
+
TABLE_KNOWLEDGE_IMPORT_RUNS,
|
|
9500
|
+
_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
|
|
9501
|
+
_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
|
|
9502
|
+
_mastra_core_storage.TABLE_KNOWLEDGE_NODES
|
|
9503
|
+
]) await tx.execute(`DELETE FROM "${table}"`);
|
|
9504
|
+
await tx.execute(`UPDATE "${TABLE_KNOWLEDGE_ACCESS_STATE}" SET epoch = 0 WHERE id = 'global'`);
|
|
8603
9505
|
});
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
9506
|
+
}
|
|
9507
|
+
async dangerouslyReset() {
|
|
9508
|
+
const tables = [...RETIRED_KNOWLEDGE_TABLE_NAMES, ...[...KNOWLEDGE_TABLE_NAMES].reverse()].map((table) => `"${table}"`).join(", ");
|
|
9509
|
+
await this.#executor.execute(`DROP TABLE IF EXISTS ${tables}`);
|
|
9510
|
+
await this.init();
|
|
9511
|
+
}
|
|
9512
|
+
async reconcileStructure(plan) {
|
|
9513
|
+
return this.#transaction(async (tx) => {
|
|
9514
|
+
await tx.execute({
|
|
9515
|
+
sql: `SELECT pg_advisory_xact_lock(hashtext(?))`,
|
|
9516
|
+
args: [`mastra-knowledge-reconcile:${this.#schemaName}`]
|
|
9517
|
+
});
|
|
9518
|
+
const scopes = {};
|
|
9519
|
+
const createdScopeIds = [];
|
|
9520
|
+
const createdAddresses = /* @__PURE__ */ new Set();
|
|
9521
|
+
const retrofit = plan.retrofit ?? true;
|
|
9522
|
+
let structureChanged = false;
|
|
9523
|
+
const deletedScopeAddresses = /* @__PURE__ */ new Set();
|
|
9524
|
+
const resolveAddress = async (address) => {
|
|
9525
|
+
if (scopes[address]) return scopes[address];
|
|
9526
|
+
const row = (await tx.execute({
|
|
9527
|
+
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=?`,
|
|
9528
|
+
args: [address]
|
|
9529
|
+
})).rows[0];
|
|
9530
|
+
if (!row) return void 0;
|
|
9531
|
+
if (!row.isScope) throw new Error(`Knowledge address ${address} does not reference a scope`);
|
|
9532
|
+
if (row.deletedAt) deletedScopeAddresses.add(address);
|
|
9533
|
+
scopes[address] = String(row.scopeNodeId);
|
|
9534
|
+
return scopes[address];
|
|
9535
|
+
};
|
|
9536
|
+
for (const scope of plan.scopes) {
|
|
9537
|
+
if (await resolveAddress(scope.address)) continue;
|
|
9538
|
+
const id = (0, crypto$1.randomUUID)();
|
|
9539
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
9540
|
+
await tx.execute({
|
|
9541
|
+
sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_NODES}" (id,type,name,"canonicalName",kind,description,"isScope",metadata,version,"createdAt","updatedAt") VALUES (?,'node',?,?,?,?,TRUE,?,1,?,?)`,
|
|
9542
|
+
args: [
|
|
9543
|
+
id,
|
|
9544
|
+
scope.name,
|
|
9545
|
+
canonicalName(scope.name),
|
|
9546
|
+
scope.kind ?? null,
|
|
9547
|
+
scope.description ?? null,
|
|
9548
|
+
scope.metadata ?? null,
|
|
9549
|
+
now,
|
|
9550
|
+
now
|
|
9551
|
+
]
|
|
9552
|
+
});
|
|
9553
|
+
await tx.execute({
|
|
9554
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" (address,"scopeNodeId") VALUES (?,?)`,
|
|
9555
|
+
args: [scope.address, id]
|
|
9556
|
+
});
|
|
9557
|
+
scopes[scope.address] = id;
|
|
9558
|
+
createdAddresses.add(scope.address);
|
|
9559
|
+
createdScopeIds.push(id);
|
|
9560
|
+
structureChanged = true;
|
|
9561
|
+
}
|
|
9562
|
+
for (const scope of plan.scopes) {
|
|
9563
|
+
if (!createdAddresses.has(scope.address) && (!retrofit || deletedScopeAddresses.has(scope.address))) continue;
|
|
9564
|
+
const scopeNodeId = scopes[scope.address];
|
|
9565
|
+
for (const parentAddress of scope.parentAddresses ?? []) {
|
|
9566
|
+
const parentId = await resolveAddress(parentAddress);
|
|
9567
|
+
if (!parentId || deletedScopeAddresses.has(parentAddress)) {
|
|
9568
|
+
const deletedParentId = scopes[parentAddress];
|
|
9569
|
+
if ((deletedParentId ? await tx.execute({
|
|
9570
|
+
sql: `SELECT 1 FROM "mastra_knowledge_node_scopes" WHERE "nodeId"=? AND "scopeNodeId"=?`,
|
|
9571
|
+
args: [scopeNodeId, deletedParentId]
|
|
9572
|
+
}) : void 0)?.rows.length) continue;
|
|
9573
|
+
throw new Error(`Knowledge parent scope does not exist: ${parentAddress}`);
|
|
9574
|
+
}
|
|
9575
|
+
if ((await tx.execute({
|
|
9576
|
+
sql: `SELECT 1 FROM "mastra_knowledge_node_scopes" WHERE "nodeId"=? AND "scopeNodeId"=?`,
|
|
9577
|
+
args: [scopeNodeId, parentId]
|
|
9578
|
+
})).rows.length) continue;
|
|
9579
|
+
if ((await tx.execute({
|
|
9580
|
+
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`,
|
|
9581
|
+
args: [
|
|
9582
|
+
parentId,
|
|
9583
|
+
canonicalName(scope.name),
|
|
9584
|
+
scopeNodeId
|
|
9585
|
+
]
|
|
9586
|
+
})).rows.length) throw new Error(`Knowledge scope name ${scope.name} already exists under ${parentAddress}`);
|
|
9587
|
+
const inserted = await tx.execute({
|
|
9588
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" ("nodeId","scopeNodeId","addedAt") VALUES (?,?,?) ON CONFLICT DO NOTHING`,
|
|
9589
|
+
args: [
|
|
9590
|
+
scopeNodeId,
|
|
9591
|
+
parentId,
|
|
9592
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
9593
|
+
]
|
|
9594
|
+
});
|
|
9595
|
+
structureChanged ||= inserted.rowsAffected > 0;
|
|
9596
|
+
}
|
|
9597
|
+
for (const grant of scope.grants ?? []) {
|
|
9598
|
+
const scopeRefId = await resolveAddress(grant.scopeRefAddress);
|
|
9599
|
+
if (!scopeRefId || deletedScopeAddresses.has(grant.scopeRefAddress)) {
|
|
9600
|
+
const deletedScopeRefId = scopes[grant.scopeRefAddress];
|
|
9601
|
+
if ((deletedScopeRefId ? await tx.execute({
|
|
9602
|
+
sql: `SELECT 1 FROM "mastra_knowledge_scope_grants" WHERE "scopeNodeId"=? AND "scopeRefId"=?`,
|
|
9603
|
+
args: [scopeNodeId, deletedScopeRefId]
|
|
9604
|
+
}) : void 0)?.rows.length) continue;
|
|
9605
|
+
throw new Error(`Knowledge grant scope does not exist: ${grant.scopeRefAddress}`);
|
|
9606
|
+
}
|
|
9607
|
+
const inserted = await tx.execute({
|
|
9608
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_SCOPE_GRANTS}" ("scopeNodeId","scopeRefId",role,"canSuggest") VALUES (?,?,?,?) ON CONFLICT DO NOTHING`,
|
|
9609
|
+
args: [
|
|
9610
|
+
scopeNodeId,
|
|
9611
|
+
scopeRefId,
|
|
9612
|
+
grant.role,
|
|
9613
|
+
grant.canSuggest ?? null
|
|
9614
|
+
]
|
|
9615
|
+
});
|
|
9616
|
+
structureChanged ||= inserted.rowsAffected > 0;
|
|
9617
|
+
}
|
|
9618
|
+
}
|
|
9619
|
+
if (structureChanged) await tx.execute(`UPDATE "${TABLE_KNOWLEDGE_ACCESS_STATE}" SET epoch=epoch+1 WHERE id='global'`);
|
|
9620
|
+
const state = await tx.execute(`SELECT epoch FROM "${TABLE_KNOWLEDGE_ACCESS_STATE}" WHERE id='global'`);
|
|
9621
|
+
return {
|
|
9622
|
+
scopes,
|
|
9623
|
+
createdScopeIds,
|
|
9624
|
+
deletedScopeAddresses: [...deletedScopeAddresses],
|
|
9625
|
+
changed: structureChanged,
|
|
9626
|
+
accessEpoch: Number(state.rows[0]?.epoch ?? 0)
|
|
9627
|
+
};
|
|
8616
9628
|
});
|
|
8617
|
-
await Promise.all(knowledgeIndexes(this.#schemaName).map((index) => this.#db.createIndexFromStatement(index.name, index.sql)));
|
|
8618
9629
|
}
|
|
8619
|
-
async
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
9630
|
+
async listScopeNodes(input = {}) {
|
|
9631
|
+
const { limit, after } = parseListKnowledgeScopeNodesInput(input);
|
|
9632
|
+
if (input.addresses?.length === 0 || input.ids?.length === 0) return {
|
|
9633
|
+
scopes: [],
|
|
9634
|
+
nextCursor: null
|
|
9635
|
+
};
|
|
9636
|
+
const args = [];
|
|
9637
|
+
const where = [`n."isScope"`, `n."deletedAt" IS NULL`];
|
|
9638
|
+
let within = "";
|
|
9639
|
+
if (input.withinAddress !== void 0) {
|
|
9640
|
+
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) `;
|
|
9641
|
+
args.push(input.withinAddress);
|
|
9642
|
+
where.push("n.id IN (SELECT id FROM within_scope)");
|
|
9643
|
+
}
|
|
9644
|
+
if (input.addresses) {
|
|
9645
|
+
where.push(`a.address IN (${input.addresses.map(() => "?").join(",")})`);
|
|
9646
|
+
args.push(...input.addresses);
|
|
9647
|
+
}
|
|
9648
|
+
if (input.ids) {
|
|
9649
|
+
where.push(`n.id IN (${input.ids.map(() => "?").join(",")})`);
|
|
9650
|
+
args.push(...input.ids);
|
|
9651
|
+
}
|
|
9652
|
+
if (after) {
|
|
9653
|
+
where.push("(n.name COLLATE \"C\" > ? OR (n.name = ? AND n.id > ?))");
|
|
9654
|
+
args.push(after.name, after.name, after.id);
|
|
9655
|
+
}
|
|
9656
|
+
args.push(limit + 1);
|
|
9657
|
+
const rows = (await this.#readExecutor.execute({
|
|
9658
|
+
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 ?`,
|
|
9659
|
+
args
|
|
9660
|
+
})).rows;
|
|
9661
|
+
if (rows.length === 0) return {
|
|
9662
|
+
scopes: [],
|
|
9663
|
+
nextCursor: null
|
|
9664
|
+
};
|
|
9665
|
+
const parents = await this.#readExecutor.execute({
|
|
9666
|
+
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"`,
|
|
9667
|
+
args: rows.map((row) => String(row.id))
|
|
9668
|
+
});
|
|
9669
|
+
const parentsByScopeId = /* @__PURE__ */ new Map();
|
|
9670
|
+
for (const row of parents.rows) {
|
|
9671
|
+
const scopeId = String(row.nodeId);
|
|
9672
|
+
const parentId = String(row.scopeNodeId);
|
|
9673
|
+
const existing = parentsByScopeId.get(scopeId);
|
|
9674
|
+
if (existing) existing.push(parentId);
|
|
9675
|
+
else parentsByScopeId.set(scopeId, [parentId]);
|
|
9676
|
+
}
|
|
9677
|
+
return pageKnowledgeScopeNodes(rows.map((row) => ({
|
|
9678
|
+
id: String(row.id),
|
|
9679
|
+
address: String(row.address),
|
|
9680
|
+
name: String(row.name),
|
|
9681
|
+
...row.kind == null ? {} : { kind: String(row.kind) },
|
|
9682
|
+
...row.description == null ? {} : { description: String(row.description) },
|
|
9683
|
+
parentIds: parentsByScopeId.get(String(row.id)) ?? []
|
|
9684
|
+
})), limit, input);
|
|
9685
|
+
}
|
|
9686
|
+
async listScopeMembers(input) {
|
|
9687
|
+
const { limit, after } = parseListKnowledgeScopeMembersInput(input);
|
|
9688
|
+
const args = [input.scopeNodeId];
|
|
9689
|
+
let keyset = "";
|
|
9690
|
+
if (after) {
|
|
9691
|
+
const updatedAt = postgresTimestamp(after.updatedAt);
|
|
9692
|
+
keyset = ` AND (n."updatedAt" < ? OR (n."updatedAt" = ? AND (n.name > ? OR (n.name = ? AND n.id > ?))))`;
|
|
9693
|
+
args.push(updatedAt, updatedAt, after.name, after.name, after.id);
|
|
9694
|
+
}
|
|
9695
|
+
args.push(limit + 1);
|
|
9696
|
+
return pageKnowledgeScopeMembers((await this.#readExecutor.execute({
|
|
9697
|
+
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 ?`,
|
|
9698
|
+
args
|
|
9699
|
+
})).rows.map(parseNode), limit, input);
|
|
8630
9700
|
}
|
|
8631
9701
|
async createNode(input) {
|
|
8632
9702
|
await assertKnowledgeDescriptionWithinBoundCompat(input.description);
|
|
@@ -8636,6 +9706,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8636
9706
|
if (existing) {
|
|
8637
9707
|
const terminal = await this.#resolveTerminalNode(tx, existing.id);
|
|
8638
9708
|
if (!(0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) throw new Error(`Merged knowledge node is not visible from scope: ${input.name}`);
|
|
9709
|
+
await this.#placeNodeInScopes(tx, terminal.id, input.scopeAddresses, /* @__PURE__ */ new Date());
|
|
8639
9710
|
return terminal;
|
|
8640
9711
|
}
|
|
8641
9712
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -8652,7 +9723,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8652
9723
|
updatedAt: now
|
|
8653
9724
|
};
|
|
8654
9725
|
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,?,?)`,
|
|
9726
|
+
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
9727
|
args: [
|
|
8657
9728
|
node.id,
|
|
8658
9729
|
"node",
|
|
@@ -8668,6 +9739,8 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8668
9739
|
now.toISOString()
|
|
8669
9740
|
]
|
|
8670
9741
|
});
|
|
9742
|
+
await this.#replaceNodeScopes(tx, node.id, scope, now);
|
|
9743
|
+
await this.#placeNodeInScopes(tx, node.id, input.scopeAddresses, now);
|
|
8671
9744
|
await this.#replaceMentions(tx, "node", node.id, node.content ?? "", input.resolutionScope ?? scope, scope);
|
|
8672
9745
|
await this.#activity(tx, "node-created", "node", node.id, scope);
|
|
8673
9746
|
await this.#outbox(tx, "node", node.id, "upsert", node.version, scope);
|
|
@@ -8684,13 +9757,13 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8684
9757
|
return this.#resolveNode(this.#readExecutor, input.name, (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
|
|
8685
9758
|
}
|
|
8686
9759
|
async listNodes(input) {
|
|
8687
|
-
const
|
|
9760
|
+
const keys = visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
|
|
8688
9761
|
const clauses = [
|
|
8689
9762
|
`type = 'node'`,
|
|
8690
9763
|
"mergedInto IS NULL",
|
|
8691
|
-
visibleSql
|
|
9764
|
+
visibleSql(keys)
|
|
8692
9765
|
];
|
|
8693
|
-
const args = [
|
|
9766
|
+
const args = [...keys];
|
|
8694
9767
|
if (input.namePrefix) {
|
|
8695
9768
|
clauses.push("canonicalName LIKE ? ESCAPE '='");
|
|
8696
9769
|
args.push(`${escapeLikePattern(canonicalName(input.namePrefix))}%`);
|
|
@@ -8742,6 +9815,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8742
9815
|
input.version
|
|
8743
9816
|
]
|
|
8744
9817
|
})).rowsAffected === 0) throw new _mastra_core_storage.KnowledgeConflictError(input.id);
|
|
9818
|
+
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
9819
|
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
9820
|
await this.#activity(tx, "node-updated", "node", input.id, scope);
|
|
8747
9821
|
if ((0, _mastra_core_storage.knowledgeScopeKey)(existing.scope) !== (0, _mastra_core_storage.knowledgeScopeKey)(scope)) {
|
|
@@ -8796,8 +9870,12 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8796
9870
|
]
|
|
8797
9871
|
})).rowsAffected === 0) throw new _mastra_core_storage.KnowledgeConflictError(source.id);
|
|
8798
9872
|
await tx.execute({
|
|
8799
|
-
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET node=? WHERE node=?`,
|
|
8800
|
-
args: [
|
|
9873
|
+
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET node=?,version=version+1,updatedAt=? WHERE node=?`,
|
|
9874
|
+
args: [
|
|
9875
|
+
target.id,
|
|
9876
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
9877
|
+
source.id
|
|
9878
|
+
]
|
|
8801
9879
|
});
|
|
8802
9880
|
await tx.execute({
|
|
8803
9881
|
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 +9915,10 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8837
9915
|
});
|
|
8838
9916
|
}
|
|
8839
9917
|
async appendKnowledge(input) {
|
|
9918
|
+
await assertKnowledgeRecordTextWithinBoundCompat(input.text);
|
|
8840
9919
|
const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
|
|
8841
9920
|
const resolutionScope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.resolutionScope);
|
|
8842
9921
|
const defaultScope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.defaultScope);
|
|
8843
|
-
(0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, input.maxScope);
|
|
8844
9922
|
return this.#transaction(async (tx) => {
|
|
8845
9923
|
const parent = await this.#resolveTerminalNode(tx, nodeReferenceId(input.node));
|
|
8846
9924
|
if (!parent) throw new _mastra_core_storage.KnowledgeNotFoundError("node", nodeReferenceId(input.node));
|
|
@@ -8853,11 +9931,10 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8853
9931
|
sourceThreadId: input.sourceThreadId,
|
|
8854
9932
|
capturedAt: /* @__PURE__ */ new Date(),
|
|
8855
9933
|
when: input.when ? new Date(input.when) : void 0,
|
|
8856
|
-
maxScope: input.maxScope,
|
|
8857
9934
|
metadata: input.metadata
|
|
8858
9935
|
};
|
|
8859
9936
|
await tx.execute({
|
|
8860
|
-
sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" (id,node,text,scope,scopeKey,sourceThreadId,capturedAt,"when",
|
|
9937
|
+
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
9938
|
args: [
|
|
8862
9939
|
record.id,
|
|
8863
9940
|
record.node,
|
|
@@ -8867,10 +9944,12 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8867
9944
|
record.sourceThreadId,
|
|
8868
9945
|
record.capturedAt.toISOString(),
|
|
8869
9946
|
record.when?.toISOString() ?? null,
|
|
8870
|
-
|
|
8871
|
-
|
|
9947
|
+
metadataJson,
|
|
9948
|
+
1,
|
|
9949
|
+
record.capturedAt.toISOString()
|
|
8872
9950
|
]
|
|
8873
9951
|
});
|
|
9952
|
+
await this.#replaceRecordScopes(tx, record.id, scope, record.capturedAt);
|
|
8874
9953
|
await this.#replaceMentions(tx, "record", record.id, record.text, resolutionScope, defaultScope);
|
|
8875
9954
|
await this.#activity(tx, "record-created", "record", record.id, scope, record.sourceThreadId);
|
|
8876
9955
|
await this.#outbox(tx, "record", record.id, "upsert", record.id, scope);
|
|
@@ -8897,17 +9976,13 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8897
9976
|
return this.#queryKnowledge(input, "related");
|
|
8898
9977
|
}
|
|
8899
9978
|
async knowledgeBySource(input) {
|
|
8900
|
-
const
|
|
8901
|
-
const args = [
|
|
8902
|
-
input.sourceThreadId,
|
|
8903
|
-
key,
|
|
8904
|
-
key
|
|
8905
|
-
];
|
|
9979
|
+
const keys = visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
|
|
9980
|
+
const args = [input.sourceThreadId, ...keys];
|
|
8906
9981
|
if (input.after) args.push(input.after);
|
|
8907
9982
|
const limit = input.limit ?? 100;
|
|
8908
9983
|
args.push(limit + 1);
|
|
8909
9984
|
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 ?`,
|
|
9985
|
+
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
9986
|
args
|
|
8912
9987
|
})).rows.map(parseKnowledge);
|
|
8913
9988
|
return {
|
|
@@ -8922,10 +9997,11 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8922
9997
|
if (record.deletedAt) return record;
|
|
8923
9998
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
8924
9999
|
await tx.execute({
|
|
8925
|
-
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=?,deletedBy=? WHERE id=? AND deletedAt IS NULL`,
|
|
10000
|
+
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=?,deletedBy=?,version=version+1,updatedAt=? WHERE id=? AND deletedAt IS NULL`,
|
|
8926
10001
|
args: [
|
|
8927
10002
|
deletedAt.toISOString(),
|
|
8928
10003
|
input.deletedBy,
|
|
10004
|
+
deletedAt.toISOString(),
|
|
8929
10005
|
input.id
|
|
8930
10006
|
]
|
|
8931
10007
|
});
|
|
@@ -8944,8 +10020,8 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8944
10020
|
if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
|
|
8945
10021
|
if (!record.deletedAt) return record;
|
|
8946
10022
|
await tx.execute({
|
|
8947
|
-
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=NULL,deletedBy=NULL WHERE id=?`,
|
|
8948
|
-
args: [input.id]
|
|
10023
|
+
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=NULL,deletedBy=NULL,version=version+1,updatedAt=? WHERE id=?`,
|
|
10024
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), input.id]
|
|
8949
10025
|
});
|
|
8950
10026
|
await this.#activity(tx, "record-restored", "record", input.id, record.scope, record.sourceThreadId);
|
|
8951
10027
|
await this.#outbox(tx, "record", input.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope);
|
|
@@ -8961,15 +10037,17 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8961
10037
|
return this.#transaction(async (tx) => {
|
|
8962
10038
|
const record = await this.#getKnowledge(tx, input.id, true);
|
|
8963
10039
|
if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
|
|
8964
|
-
|
|
10040
|
+
const updatedAt = /* @__PURE__ */ new Date();
|
|
8965
10041
|
await tx.execute({
|
|
8966
|
-
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET scope=jsonb(?),scopeKey=? WHERE id=?`,
|
|
10042
|
+
sql: `UPDATE "${_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS}" SET scope=jsonb(?),scopeKey=?,version=version+1,updatedAt=? WHERE id=?`,
|
|
8967
10043
|
args: [
|
|
8968
10044
|
JSON.stringify(scope),
|
|
8969
10045
|
(0, _mastra_core_storage.knowledgeScopeKey)(scope),
|
|
10046
|
+
updatedAt.toISOString(),
|
|
8970
10047
|
input.id
|
|
8971
10048
|
]
|
|
8972
10049
|
});
|
|
10050
|
+
await this.#replaceRecordScopes(tx, input.id, scope, updatedAt);
|
|
8973
10051
|
await this.#activity(tx, "record-rescoped", "record", input.id, scope, record.sourceThreadId);
|
|
8974
10052
|
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
10053
|
if (!record.deletedAt) await this.#outbox(tx, "record", input.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), scope);
|
|
@@ -8979,33 +10057,16 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
8979
10057
|
};
|
|
8980
10058
|
});
|
|
8981
10059
|
}
|
|
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
10060
|
async search(input) {
|
|
8999
10061
|
const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
|
|
9000
|
-
const
|
|
10062
|
+
const keys = visibleScopeKeys(scope);
|
|
9001
10063
|
const normalizedQuery = input.query.trim().toLocaleLowerCase();
|
|
9002
10064
|
if (!normalizedQuery) return [];
|
|
9003
10065
|
const query = `%${escapeLikePattern(normalizedQuery)}%`;
|
|
9004
10066
|
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 ?`,
|
|
10067
|
+
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
10068
|
args: [
|
|
9007
|
-
|
|
9008
|
-
key,
|
|
10069
|
+
...keys,
|
|
9009
10070
|
query,
|
|
9010
10071
|
query,
|
|
9011
10072
|
query,
|
|
@@ -9026,10 +10087,9 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9026
10087
|
}));
|
|
9027
10088
|
if (results.length < (input.limit ?? 20)) {
|
|
9028
10089
|
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
|
|
10090
|
+
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
10091
|
args: [
|
|
9031
|
-
|
|
9032
|
-
key,
|
|
10092
|
+
...keys,
|
|
9033
10093
|
query,
|
|
9034
10094
|
(input.limit ?? 20) - results.length
|
|
9035
10095
|
]
|
|
@@ -9039,7 +10099,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9039
10099
|
return {
|
|
9040
10100
|
type: "record",
|
|
9041
10101
|
id: String(row.id),
|
|
9042
|
-
recordId: String(row.node),
|
|
10102
|
+
recordId: parentVisible ? String(row.node) : String(row.id),
|
|
9043
10103
|
name: parentVisible ? String(row.name) : "(private node)",
|
|
9044
10104
|
text: String(row.text),
|
|
9045
10105
|
scope: parseJson$1(row.scopeJson)
|
|
@@ -9048,41 +10108,26 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9048
10108
|
}
|
|
9049
10109
|
return results;
|
|
9050
10110
|
}
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
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
|
-
};
|
|
10111
|
+
/**
|
|
10112
|
+
* @deprecated Curation cursors were removed. Observation-time curate is the only Knowledge writer and needs no
|
|
10113
|
+
* cursor. Always throws.
|
|
10114
|
+
*/
|
|
10115
|
+
async getCurationCursor(_input) {
|
|
10116
|
+
throw new Error(KNOWLEDGE_CURATION_CURSOR_REMOVED_MESSAGE);
|
|
10117
|
+
}
|
|
10118
|
+
/**
|
|
10119
|
+
* @deprecated Curation cursors were removed. Observation-time curate is the only Knowledge writer and needs no
|
|
10120
|
+
* cursor. Always throws.
|
|
10121
|
+
*/
|
|
10122
|
+
async advanceCurationCursor(_input) {
|
|
10123
|
+
throw new Error(KNOWLEDGE_CURATION_CURSOR_REMOVED_MESSAGE);
|
|
9078
10124
|
}
|
|
9079
10125
|
async listActivity(input) {
|
|
9080
|
-
const
|
|
10126
|
+
const keys = visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
|
|
9081
10127
|
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 ?`,
|
|
10128
|
+
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
10129
|
args: [
|
|
9084
|
-
|
|
9085
|
-
key,
|
|
10130
|
+
...keys,
|
|
9086
10131
|
...input.after ? [input.after] : [],
|
|
9087
10132
|
input.limit ?? 100
|
|
9088
10133
|
]
|
|
@@ -9104,9 +10149,9 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9104
10149
|
args.push(input.status);
|
|
9105
10150
|
}
|
|
9106
10151
|
if (input.scope) {
|
|
9107
|
-
const
|
|
9108
|
-
clauses.push(visibleSql);
|
|
9109
|
-
args.push(
|
|
10152
|
+
const keys = visibleScopeKeys(input.scope);
|
|
10153
|
+
clauses.push(visibleSql(keys));
|
|
10154
|
+
args.push(...keys);
|
|
9110
10155
|
}
|
|
9111
10156
|
args.push(input.limit ?? 100);
|
|
9112
10157
|
return (await this.#executor.execute({
|
|
@@ -9125,9 +10170,9 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9125
10170
|
];
|
|
9126
10171
|
const args = [now.toISOString(), stale.toISOString()];
|
|
9127
10172
|
if (input.scope) {
|
|
9128
|
-
const
|
|
9129
|
-
clauses.push(visibleSql);
|
|
9130
|
-
args.push(
|
|
10173
|
+
const keys = visibleScopeKeys(input.scope);
|
|
10174
|
+
clauses.push(visibleSql(keys));
|
|
10175
|
+
args.push(...keys);
|
|
9131
10176
|
}
|
|
9132
10177
|
args.push(input.limit ?? 100);
|
|
9133
10178
|
const ids = (await tx.execute({
|
|
@@ -9194,12 +10239,14 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9194
10239
|
return result.rows[0] ? parseNode(result.rows[0]) : null;
|
|
9195
10240
|
}
|
|
9196
10241
|
async #resolveNode(executor, name, scope) {
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
10242
|
+
const keys = visibleScopeKeys(scope);
|
|
10243
|
+
const candidates = (await executor.execute({
|
|
10244
|
+
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)`,
|
|
10245
|
+
args: [canonicalName(name), ...keys]
|
|
10246
|
+
})).rows.map(parseNode).sort((left, right) => right.scope.length - left.scope.length);
|
|
10247
|
+
for (const candidate of candidates) {
|
|
10248
|
+
const terminal = await this.#resolveTerminalNode(executor, candidate.id);
|
|
10249
|
+
if (terminal && (0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) return terminal;
|
|
9203
10250
|
}
|
|
9204
10251
|
return null;
|
|
9205
10252
|
}
|
|
@@ -9224,17 +10271,16 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9224
10271
|
const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
|
|
9225
10272
|
const node = await this.#resolveTerminalNode(this.#readExecutor, nodeReferenceId(input.node));
|
|
9226
10273
|
if (!node) return { records: [] };
|
|
9227
|
-
const
|
|
10274
|
+
const keys = visibleScopeKeys(scope);
|
|
9228
10275
|
const args = [
|
|
9229
10276
|
node.id,
|
|
9230
10277
|
...relationship === "related" ? [node.id] : [],
|
|
9231
|
-
|
|
9232
|
-
key
|
|
10278
|
+
...keys
|
|
9233
10279
|
];
|
|
9234
10280
|
if (input.after) args.push(input.after);
|
|
9235
10281
|
args.push((input.limit ?? 100) + 1);
|
|
9236
10282
|
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
|
|
10283
|
+
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
10284
|
args
|
|
9239
10285
|
})).rows.map(parseKnowledge);
|
|
9240
10286
|
const limit = input.limit ?? 100;
|
|
@@ -9243,6 +10289,90 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9243
10289
|
nextCursor: records.length > limit ? records[limit - 1]?.id : void 0
|
|
9244
10290
|
};
|
|
9245
10291
|
}
|
|
10292
|
+
async #resolveScopeNodeIds(executor, addresses) {
|
|
10293
|
+
const scopeNodeIds = /* @__PURE__ */ new Set();
|
|
10294
|
+
for (const address of addresses) {
|
|
10295
|
+
const result = await executor.execute({
|
|
10296
|
+
sql: `SELECT scopeNodeId FROM "${TABLE_KNOWLEDGE_SCOPE_ADDRESSES}" WHERE address=?`,
|
|
10297
|
+
args: [address]
|
|
10298
|
+
});
|
|
10299
|
+
if (result.rows[0]?.scopeNodeId != null) scopeNodeIds.add(String(result.rows[0].scopeNodeId));
|
|
10300
|
+
}
|
|
10301
|
+
return [...scopeNodeIds];
|
|
10302
|
+
}
|
|
10303
|
+
async #replaceNodeScopes(executor, nodeId, addresses, addedAt) {
|
|
10304
|
+
await executor.execute({
|
|
10305
|
+
sql: `DELETE FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" WHERE nodeId=?`,
|
|
10306
|
+
args: [nodeId]
|
|
10307
|
+
});
|
|
10308
|
+
for (const scopeNodeId of await this.#resolveScopeNodeIds(executor, addresses)) await executor.execute({
|
|
10309
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" (nodeId,scopeNodeId,addedAt) VALUES (?,?,?) ON CONFLICT DO NOTHING`,
|
|
10310
|
+
args: [
|
|
10311
|
+
nodeId,
|
|
10312
|
+
scopeNodeId,
|
|
10313
|
+
addedAt.toISOString()
|
|
10314
|
+
]
|
|
10315
|
+
});
|
|
10316
|
+
}
|
|
10317
|
+
/**
|
|
10318
|
+
* Move a node's identity memberships from `from` to `to` without touching structural
|
|
10319
|
+
* placements added by `#placeNodeInScopes`, which a scope change must not erase.
|
|
10320
|
+
*/
|
|
10321
|
+
async #swapIdentityScopes(executor, nodeId, from, to, addedAt) {
|
|
10322
|
+
const next = await this.#resolveScopeNodeIds(executor, to);
|
|
10323
|
+
for (const scopeNodeId of await this.#resolveScopeNodeIds(executor, from)) {
|
|
10324
|
+
if (next.includes(scopeNodeId)) continue;
|
|
10325
|
+
await executor.execute({
|
|
10326
|
+
sql: `DELETE FROM "${TABLE_KNOWLEDGE_NODE_SCOPES}" WHERE nodeId=? AND scopeNodeId=?`,
|
|
10327
|
+
args: [nodeId, scopeNodeId]
|
|
10328
|
+
});
|
|
10329
|
+
}
|
|
10330
|
+
for (const scopeNodeId of next) await executor.execute({
|
|
10331
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" (nodeId,scopeNodeId,addedAt) VALUES (?,?,?) ON CONFLICT DO NOTHING`,
|
|
10332
|
+
args: [
|
|
10333
|
+
nodeId,
|
|
10334
|
+
scopeNodeId,
|
|
10335
|
+
addedAt.toISOString()
|
|
10336
|
+
]
|
|
10337
|
+
});
|
|
10338
|
+
}
|
|
10339
|
+
/**
|
|
10340
|
+
* Additive structural placement: every address must resolve to a live scope node
|
|
10341
|
+
* (unlike identity membership, an unknown address is a caller error, not a lazy
|
|
10342
|
+
* materialization miss). Runs inside the caller's transaction, so a throw aborts
|
|
10343
|
+
* the whole mutation.
|
|
10344
|
+
*/
|
|
10345
|
+
async #placeNodeInScopes(executor, nodeId, addresses, addedAt) {
|
|
10346
|
+
for (const address of addresses ?? []) {
|
|
10347
|
+
const scopeNodeId = (await executor.execute({
|
|
10348
|
+
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`,
|
|
10349
|
+
args: [address]
|
|
10350
|
+
})).rows[0]?.scopeNodeId;
|
|
10351
|
+
if (scopeNodeId == null) throw new _mastra_core_storage.KnowledgeNotFoundError("scope", address);
|
|
10352
|
+
await executor.execute({
|
|
10353
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODE_SCOPES}" ("nodeId","scopeNodeId","addedAt") VALUES (?,?,?) ON CONFLICT DO NOTHING`,
|
|
10354
|
+
args: [
|
|
10355
|
+
nodeId,
|
|
10356
|
+
String(scopeNodeId),
|
|
10357
|
+
addedAt.toISOString()
|
|
10358
|
+
]
|
|
10359
|
+
});
|
|
10360
|
+
}
|
|
10361
|
+
}
|
|
10362
|
+
async #replaceRecordScopes(executor, recordId, addresses, addedAt) {
|
|
10363
|
+
await executor.execute({
|
|
10364
|
+
sql: `DELETE FROM "${TABLE_KNOWLEDGE_RECORD_SCOPES}" WHERE recordId=?`,
|
|
10365
|
+
args: [recordId]
|
|
10366
|
+
});
|
|
10367
|
+
for (const scopeNodeId of await this.#resolveScopeNodeIds(executor, addresses)) await executor.execute({
|
|
10368
|
+
sql: `INSERT INTO "${TABLE_KNOWLEDGE_RECORD_SCOPES}" (recordId,scopeNodeId,addedAt) VALUES (?,?,?) ON CONFLICT DO NOTHING`,
|
|
10369
|
+
args: [
|
|
10370
|
+
recordId,
|
|
10371
|
+
scopeNodeId,
|
|
10372
|
+
addedAt.toISOString()
|
|
10373
|
+
]
|
|
10374
|
+
});
|
|
10375
|
+
}
|
|
9246
10376
|
async #replaceMentions(tx, sourceType, sourceId, text, resolutionScope, defaultScope) {
|
|
9247
10377
|
await tx.execute({
|
|
9248
10378
|
sql: `DELETE FROM "${_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS}" WHERE sourceType=? AND sourceId=?`,
|
|
@@ -9266,7 +10396,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9266
10396
|
updatedAt: now
|
|
9267
10397
|
};
|
|
9268
10398
|
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,?,?)`,
|
|
10399
|
+
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
10400
|
args: [
|
|
9271
10401
|
node.id,
|
|
9272
10402
|
"node",
|
|
@@ -9280,6 +10410,7 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9280
10410
|
now.toISOString()
|
|
9281
10411
|
]
|
|
9282
10412
|
});
|
|
10413
|
+
await this.#replaceNodeScopes(tx, node.id, defaultScope, now);
|
|
9283
10414
|
await this.#activity(tx, "node-created", "node", node.id, defaultScope);
|
|
9284
10415
|
await this.#outbox(tx, "node", node.id, "upsert", 1, defaultScope);
|
|
9285
10416
|
}
|
|
@@ -9296,13 +10427,17 @@ var KnowledgePG = class extends _mastra_core_storage.KnowledgeStorage {
|
|
|
9296
10427
|
}
|
|
9297
10428
|
async #activity(executor, action, recordType, recordId, scope, sourceThreadId) {
|
|
9298
10429
|
const now = /* @__PURE__ */ new Date();
|
|
10430
|
+
const [contextScopeId] = await this.#resolveScopeNodeIds(executor, scope);
|
|
9299
10431
|
await executor.execute({
|
|
9300
|
-
sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY}" (id,action,recordType,recordId,scope,scopeKey,sourceThreadId,createdAt) VALUES (
|
|
10432
|
+
sql: `INSERT INTO "${_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY}" (id,action,targetType,targetId,contextScopeId,recordType,recordId,scope,scopeKey,sourceThreadId,createdAt) VALUES (?,?,?,?,?,?,?,jsonb(?),?,?,?)`,
|
|
9301
10433
|
args: [
|
|
9302
10434
|
(0, _mastra_core_storage.createKnowledgeUlid)(),
|
|
9303
10435
|
action,
|
|
9304
10436
|
recordType,
|
|
9305
10437
|
recordId,
|
|
10438
|
+
contextScopeId ?? null,
|
|
10439
|
+
recordType,
|
|
10440
|
+
recordId,
|
|
9306
10441
|
JSON.stringify(scope),
|
|
9307
10442
|
(0, _mastra_core_storage.knowledgeScopeKey)(scope),
|
|
9308
10443
|
sourceThreadId ?? null,
|
|
@@ -9439,6 +10574,7 @@ var MCPClientsPG = class MCPClientsPG extends _mastra_core_storage.MCPClientsSto
|
|
|
9439
10574
|
}
|
|
9440
10575
|
async create(input) {
|
|
9441
10576
|
const { mcpClient } = input;
|
|
10577
|
+
let draftInserted = false;
|
|
9442
10578
|
try {
|
|
9443
10579
|
const tableName = getTableName$5({
|
|
9444
10580
|
indexName: _mastra_core_storage.TABLE_MCP_CLIENTS,
|
|
@@ -9461,6 +10597,7 @@ var MCPClientsPG = class MCPClientsPG extends _mastra_core_storage.MCPClientsSto
|
|
|
9461
10597
|
nowIso,
|
|
9462
10598
|
nowIso
|
|
9463
10599
|
]);
|
|
10600
|
+
draftInserted = true;
|
|
9464
10601
|
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = mcpClient;
|
|
9465
10602
|
const versionId = crypto.randomUUID();
|
|
9466
10603
|
await this.createVersion({
|
|
@@ -9481,7 +10618,7 @@ var MCPClientsPG = class MCPClientsPG extends _mastra_core_storage.MCPClientsSto
|
|
|
9481
10618
|
updatedAt: now
|
|
9482
10619
|
};
|
|
9483
10620
|
} catch (error) {
|
|
9484
|
-
try {
|
|
10621
|
+
if (draftInserted) try {
|
|
9485
10622
|
const tableName = getTableName$5({
|
|
9486
10623
|
indexName: _mastra_core_storage.TABLE_MCP_CLIENTS,
|
|
9487
10624
|
schemaName: getSchemaName$5(this.#schema)
|
|
@@ -10007,6 +11144,7 @@ var MCPServersPG = class MCPServersPG extends _mastra_core_storage.MCPServersSto
|
|
|
10007
11144
|
}
|
|
10008
11145
|
async create(input) {
|
|
10009
11146
|
const { mcpServer } = input;
|
|
11147
|
+
let draftInserted = false;
|
|
10010
11148
|
try {
|
|
10011
11149
|
const tableName = getTableName$5({
|
|
10012
11150
|
indexName: _mastra_core_storage.TABLE_MCP_SERVERS,
|
|
@@ -10028,6 +11166,7 @@ var MCPServersPG = class MCPServersPG extends _mastra_core_storage.MCPServersSto
|
|
|
10028
11166
|
nowIso,
|
|
10029
11167
|
nowIso
|
|
10030
11168
|
]);
|
|
11169
|
+
draftInserted = true;
|
|
10031
11170
|
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = mcpServer;
|
|
10032
11171
|
const versionId = crypto.randomUUID();
|
|
10033
11172
|
await this.createVersion({
|
|
@@ -10048,7 +11187,7 @@ var MCPServersPG = class MCPServersPG extends _mastra_core_storage.MCPServersSto
|
|
|
10048
11187
|
updatedAt: now
|
|
10049
11188
|
};
|
|
10050
11189
|
} catch (error) {
|
|
10051
|
-
try {
|
|
11190
|
+
if (draftInserted) try {
|
|
10052
11191
|
const tableName = getTableName$5({
|
|
10053
11192
|
indexName: _mastra_core_storage.TABLE_MCP_SERVERS,
|
|
10054
11193
|
schemaName: getSchemaName$5(this.#schema)
|
|
@@ -10472,6 +11611,38 @@ var MCPServersPG = class MCPServersPG extends _mastra_core_storage.MCPServersSto
|
|
|
10472
11611
|
}
|
|
10473
11612
|
};
|
|
10474
11613
|
//#endregion
|
|
11614
|
+
//#region src/storage/db/run-fencing.ts
|
|
11615
|
+
/**
|
|
11616
|
+
* Epoch milliseconds on the database clock. `clock_timestamp()` rather than
|
|
11617
|
+
* `now()`: a statement can wait on a row lock, and lease math must use the
|
|
11618
|
+
* time it actually runs, not when its transaction started.
|
|
11619
|
+
*/
|
|
11620
|
+
const DB_NOW_MS = `(EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::bigint`;
|
|
11621
|
+
/**
|
|
11622
|
+
* The check half of a fenced write; call it first inside the write's
|
|
11623
|
+
* transaction. `FOR SHARE` holds the claim row until commit, so a claim that
|
|
11624
|
+
* updates the row waits for the write to finish, and every later write sees
|
|
11625
|
+
* the new claim.
|
|
11626
|
+
*/
|
|
11627
|
+
async function assertRunFence(t, claimsTable, fence, operation) {
|
|
11628
|
+
const row = await t.oneOrNone(`SELECT generation, "ownerId" FROM ${claimsTable} WHERE "runId" = $1 FOR SHARE`, [fence.runId]);
|
|
11629
|
+
if (!(0, _mastra_core_storage.matchesRunFence)(row && {
|
|
11630
|
+
generation: Number(row.generation),
|
|
11631
|
+
ownerId: row.ownerId
|
|
11632
|
+
}, fence)) throw new _mastra_core_storage.RunFenceConflictError(fence, operation);
|
|
11633
|
+
}
|
|
11634
|
+
/**
|
|
11635
|
+
* Runs `write` directly when it carries no fence, or in a transaction behind
|
|
11636
|
+
* the fence check when it does.
|
|
11637
|
+
*/
|
|
11638
|
+
function withRunFence(client, claimsTable, fence, operation, write) {
|
|
11639
|
+
if (!fence) return write(client);
|
|
11640
|
+
return client.tx(async (t) => {
|
|
11641
|
+
await assertRunFence(t, claimsTable, fence, operation);
|
|
11642
|
+
return write(t);
|
|
11643
|
+
});
|
|
11644
|
+
}
|
|
11645
|
+
//#endregion
|
|
10475
11646
|
//#region src/storage/domains/memory/index.ts
|
|
10476
11647
|
/**
|
|
10477
11648
|
* Local constant for the observational memory table name.
|
|
@@ -10572,6 +11743,10 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
10572
11743
|
* and are indexed for fast batched deletes. Cascade order is enforced in
|
|
10573
11744
|
* `prune()` (children before threads), not here. Observational memory has no
|
|
10574
11745
|
* timestamp anchor and is deliberately excluded.
|
|
11746
|
+
*
|
|
11747
|
+
* Run fences anchor on `retiredAt` (epoch ms), which stays NULL until the
|
|
11748
|
+
* execution holding the fence settles, so a running execution's fence is
|
|
11749
|
+
* never pruned.
|
|
10575
11750
|
*/
|
|
10576
11751
|
static retentionTables = {
|
|
10577
11752
|
messages: {
|
|
@@ -10588,6 +11763,12 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
10588
11763
|
table: _mastra_core_storage.TABLE_THREADS,
|
|
10589
11764
|
column: "createdAtZ",
|
|
10590
11765
|
indexed: true
|
|
11766
|
+
},
|
|
11767
|
+
runFences: {
|
|
11768
|
+
table: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
11769
|
+
column: "retiredAt",
|
|
11770
|
+
indexed: true,
|
|
11771
|
+
anchorType: "epoch-ms"
|
|
10591
11772
|
}
|
|
10592
11773
|
};
|
|
10593
11774
|
#db;
|
|
@@ -10651,6 +11832,10 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
10651
11832
|
});
|
|
10652
11833
|
await this.#db.createIndexFromStatement("idx_om_lookup_key", `CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON ${omTableName} ("lookupKey")`);
|
|
10653
11834
|
}
|
|
11835
|
+
await this.#db.createTable({
|
|
11836
|
+
tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
11837
|
+
schema: _mastra_core_storage.RUN_FENCING_TABLE_SCHEMAS[_mastra_core_storage.TABLE_MEMORY_RUN_FENCES]
|
|
11838
|
+
});
|
|
10654
11839
|
await this.createDefaultIndexes();
|
|
10655
11840
|
await this.createCustomIndexes();
|
|
10656
11841
|
}
|
|
@@ -10728,6 +11913,12 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
10728
11913
|
statements.push(`CREATE INDEX IF NOT EXISTS "${idxPrefix}idx_om_lookup_key" ON ${fullOmTableName} ("lookupKey");`);
|
|
10729
11914
|
}
|
|
10730
11915
|
for (const idx of MemoryPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
|
|
11916
|
+
statements.push(generateTableSQL({
|
|
11917
|
+
tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
11918
|
+
schema: _mastra_core_storage.RUN_FENCING_TABLE_SCHEMAS[_mastra_core_storage.TABLE_MEMORY_RUN_FENCES],
|
|
11919
|
+
schemaName,
|
|
11920
|
+
includeAllConstraints: true
|
|
11921
|
+
}));
|
|
10731
11922
|
return statements;
|
|
10732
11923
|
}
|
|
10733
11924
|
/**
|
|
@@ -10763,6 +11954,61 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
10763
11954
|
await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_MESSAGES });
|
|
10764
11955
|
await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_THREADS });
|
|
10765
11956
|
await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_RESOURCES });
|
|
11957
|
+
await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES });
|
|
11958
|
+
}
|
|
11959
|
+
supportsRunFencing() {
|
|
11960
|
+
return true;
|
|
11961
|
+
}
|
|
11962
|
+
#runFencesTable() {
|
|
11963
|
+
return getTableName$3({
|
|
11964
|
+
indexName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
11965
|
+
schemaName: getSchemaName$3(this.#schema)
|
|
11966
|
+
});
|
|
11967
|
+
}
|
|
11968
|
+
/** Runs `write` behind the run's fence check when it carries a fence. */
|
|
11969
|
+
#fenced(fence, operation, write) {
|
|
11970
|
+
return withRunFence(this.#db.client, this.#runFencesTable(), (0, _mastra_core_storage.resolveRunFence)(this, fence), operation, write);
|
|
11971
|
+
}
|
|
11972
|
+
async raiseRunFence(fence) {
|
|
11973
|
+
try {
|
|
11974
|
+
return await this.#db.client.oneOrNone(`INSERT INTO ${this.#runFencesTable()} AS f ("runId", generation, "ownerId")
|
|
11975
|
+
VALUES ($1, $2, $3)
|
|
11976
|
+
ON CONFLICT ("runId") DO UPDATE
|
|
11977
|
+
SET generation = EXCLUDED.generation, "ownerId" = EXCLUDED."ownerId", "retiredAt" = NULL
|
|
11978
|
+
WHERE f.generation < EXCLUDED.generation
|
|
11979
|
+
OR (f.generation = EXCLUDED.generation AND f."ownerId" = EXCLUDED."ownerId")
|
|
11980
|
+
RETURNING "runId"`, [
|
|
11981
|
+
fence.runId,
|
|
11982
|
+
fence.generation,
|
|
11983
|
+
fence.ownerId
|
|
11984
|
+
]) !== null;
|
|
11985
|
+
} catch (error) {
|
|
11986
|
+
throw new _mastra_core_error.MastraError({
|
|
11987
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "RAISE_RUN_FENCE", "FAILED"),
|
|
11988
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11989
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11990
|
+
details: { runId: fence.runId }
|
|
11991
|
+
}, error);
|
|
11992
|
+
}
|
|
11993
|
+
}
|
|
11994
|
+
async retireRunFence(fence) {
|
|
11995
|
+
try {
|
|
11996
|
+
return await this.#db.client.oneOrNone(`UPDATE ${this.#runFencesTable()}
|
|
11997
|
+
SET "retiredAt" = ${DB_NOW_MS}
|
|
11998
|
+
WHERE "runId" = $1 AND generation = $2 AND "ownerId" = $3
|
|
11999
|
+
RETURNING "runId"`, [
|
|
12000
|
+
fence.runId,
|
|
12001
|
+
fence.generation,
|
|
12002
|
+
fence.ownerId
|
|
12003
|
+
]) !== null;
|
|
12004
|
+
} catch (error) {
|
|
12005
|
+
throw new _mastra_core_error.MastraError({
|
|
12006
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "RETIRE_RUN_FENCE", "FAILED"),
|
|
12007
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
12008
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
12009
|
+
details: { runId: fence.runId }
|
|
12010
|
+
}, error);
|
|
12011
|
+
}
|
|
10766
12012
|
}
|
|
10767
12013
|
/**
|
|
10768
12014
|
* Deletes rows older than the configured `maxAge` per table, in bounded,
|
|
@@ -10783,7 +12029,8 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
10783
12029
|
order: [
|
|
10784
12030
|
"messages",
|
|
10785
12031
|
"resources",
|
|
10786
|
-
"threads"
|
|
12032
|
+
"threads",
|
|
12033
|
+
"runFences"
|
|
10787
12034
|
]
|
|
10788
12035
|
});
|
|
10789
12036
|
const results = await runPrune({
|
|
@@ -11041,7 +12288,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11041
12288
|
throw mastraError;
|
|
11042
12289
|
}
|
|
11043
12290
|
}
|
|
11044
|
-
async saveThread({ thread }) {
|
|
12291
|
+
async saveThread({ thread, fence }) {
|
|
11045
12292
|
try {
|
|
11046
12293
|
const tableName = getTableName$3({
|
|
11047
12294
|
indexName: _mastra_core_storage.TABLE_THREADS,
|
|
@@ -11050,7 +12297,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11050
12297
|
const createdAt = toUtcISOString(thread.createdAt);
|
|
11051
12298
|
const updatedAt = toUtcISOString(thread.updatedAt);
|
|
11052
12299
|
const metadataJson = thread.metadata ? toPgJson(thread.metadata) : null;
|
|
11053
|
-
await this.#
|
|
12300
|
+
await this.#fenced(fence, "saveThread", (q) => q.none(`INSERT INTO ${tableName} (
|
|
11054
12301
|
id,
|
|
11055
12302
|
"resourceId",
|
|
11056
12303
|
title,
|
|
@@ -11076,12 +12323,13 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11076
12323
|
createdAt,
|
|
11077
12324
|
updatedAt,
|
|
11078
12325
|
updatedAt
|
|
11079
|
-
]);
|
|
12326
|
+
]));
|
|
11080
12327
|
return {
|
|
11081
12328
|
...thread,
|
|
11082
12329
|
metadata: metadataJson ? JSON.parse(metadataJson) : thread.metadata
|
|
11083
12330
|
};
|
|
11084
12331
|
} catch (error) {
|
|
12332
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
11085
12333
|
throw new _mastra_core_error.MastraError({
|
|
11086
12334
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SAVE_THREAD", "FAILED"),
|
|
11087
12335
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -11090,29 +12338,30 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11090
12338
|
}, error);
|
|
11091
12339
|
}
|
|
11092
12340
|
}
|
|
11093
|
-
async updateThread({ id, title, metadata }) {
|
|
12341
|
+
async updateThread({ id, title, metadata, fence }) {
|
|
11094
12342
|
const threadTableName = getTableName$3({
|
|
11095
12343
|
indexName: _mastra_core_storage.TABLE_THREADS,
|
|
11096
12344
|
schemaName: getSchemaName$3(this.#schema)
|
|
11097
12345
|
});
|
|
11098
|
-
const existingThread = await this.#getThreadById(this.#db.client, { threadId: id });
|
|
11099
|
-
if (!existingThread) throw new _mastra_core_error.MastraError({
|
|
11100
|
-
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_THREAD", "FAILED"),
|
|
11101
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11102
|
-
category: _mastra_core_error.ErrorCategory.USER,
|
|
11103
|
-
text: `Thread ${id} not found`,
|
|
11104
|
-
details: {
|
|
11105
|
-
threadId: id,
|
|
11106
|
-
title: title ?? null
|
|
11107
|
-
}
|
|
11108
|
-
});
|
|
11109
|
-
const mergedMetadata = {
|
|
11110
|
-
...existingThread.metadata,
|
|
11111
|
-
...metadata
|
|
11112
|
-
};
|
|
11113
12346
|
try {
|
|
11114
|
-
|
|
11115
|
-
|
|
12347
|
+
return await this.#fenced(fence, "updateThread", async (q) => {
|
|
12348
|
+
const existingThread = await this.#getThreadById(q, { threadId: id });
|
|
12349
|
+
if (!existingThread) throw new _mastra_core_error.MastraError({
|
|
12350
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_THREAD", "FAILED"),
|
|
12351
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
12352
|
+
category: _mastra_core_error.ErrorCategory.USER,
|
|
12353
|
+
text: `Thread ${id} not found`,
|
|
12354
|
+
details: {
|
|
12355
|
+
threadId: id,
|
|
12356
|
+
title: title ?? null
|
|
12357
|
+
}
|
|
12358
|
+
});
|
|
12359
|
+
const mergedMetadata = {
|
|
12360
|
+
...existingThread.metadata,
|
|
12361
|
+
...metadata
|
|
12362
|
+
};
|
|
12363
|
+
const nowStr = toUtcISOString(/* @__PURE__ */ new Date());
|
|
12364
|
+
const thread = await q.one(`UPDATE ${threadTableName}
|
|
11116
12365
|
SET
|
|
11117
12366
|
title = COALESCE($1, title),
|
|
11118
12367
|
metadata = $2,
|
|
@@ -11121,21 +12370,23 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11121
12370
|
WHERE id = $5
|
|
11122
12371
|
RETURNING *
|
|
11123
12372
|
`, [
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
|
|
12373
|
+
title ?? null,
|
|
12374
|
+
mergedMetadata,
|
|
12375
|
+
nowStr,
|
|
12376
|
+
nowStr,
|
|
12377
|
+
id
|
|
12378
|
+
]);
|
|
12379
|
+
return {
|
|
12380
|
+
id: thread.id,
|
|
12381
|
+
resourceId: thread.resourceId,
|
|
12382
|
+
title: thread.title,
|
|
12383
|
+
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
12384
|
+
createdAt: thread.createdAtZ || thread.createdAt,
|
|
12385
|
+
updatedAt: thread.updatedAtZ || thread.updatedAt
|
|
12386
|
+
};
|
|
12387
|
+
});
|
|
11138
12388
|
} catch (error) {
|
|
12389
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
11139
12390
|
throw new _mastra_core_error.MastraError({
|
|
11140
12391
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_THREAD", "FAILED"),
|
|
11141
12392
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -11688,8 +12939,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11688
12939
|
throw mastraError;
|
|
11689
12940
|
}
|
|
11690
12941
|
}
|
|
11691
|
-
async saveMessages({ messages }) {
|
|
12942
|
+
async saveMessages({ messages, fence: explicitFence }) {
|
|
11692
12943
|
if (messages.length === 0) return { messages: [] };
|
|
12944
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, explicitFence);
|
|
11693
12945
|
const threadId = messages[0]?.threadId;
|
|
11694
12946
|
if (!threadId) throw new _mastra_core_error.MastraError({
|
|
11695
12947
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SAVE_MESSAGES", "FAILED"),
|
|
@@ -11717,6 +12969,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11717
12969
|
});
|
|
11718
12970
|
const messagesToSave = dedupeMessagesForSave(messages);
|
|
11719
12971
|
await this.#db.client.tx(async (t) => {
|
|
12972
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "saveMessages");
|
|
11720
12973
|
for (let offset = 0; offset < messagesToSave.length; offset += MAX_MESSAGES_PER_INSERT) {
|
|
11721
12974
|
const batch = messagesToSave.slice(offset, offset + MAX_MESSAGES_PER_INSERT);
|
|
11722
12975
|
const values = [];
|
|
@@ -11763,7 +13016,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11763
13016
|
});
|
|
11764
13017
|
return { messages: new _mastra_core_agent.MessageList().add(messagesWithParsedContent, "memory").get.all.db() };
|
|
11765
13018
|
} catch (error) {
|
|
11766
|
-
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
13019
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
11767
13020
|
throw new _mastra_core_error.MastraError({
|
|
11768
13021
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SAVE_MESSAGES", "FAILED"),
|
|
11769
13022
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -11772,8 +13025,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11772
13025
|
}, error);
|
|
11773
13026
|
}
|
|
11774
13027
|
}
|
|
11775
|
-
async updateMessages({ messages }) {
|
|
13028
|
+
async updateMessages({ messages, fence: explicitFence }) {
|
|
11776
13029
|
if (messages.length === 0) return [];
|
|
13030
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, explicitFence);
|
|
11777
13031
|
const messageIds = messages.map((m) => m.id);
|
|
11778
13032
|
const selectQuery = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId" FROM ${getTableName$3({
|
|
11779
13033
|
indexName: _mastra_core_storage.TABLE_MESSAGES,
|
|
@@ -11789,6 +13043,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11789
13043
|
});
|
|
11790
13044
|
const threadIdsToUpdate = /* @__PURE__ */ new Set();
|
|
11791
13045
|
await this.#db.client.tx(async (t) => {
|
|
13046
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "updateMessages");
|
|
11792
13047
|
const queries = [];
|
|
11793
13048
|
const columnMapping = { threadId: "thread_id" };
|
|
11794
13049
|
for (const existingMessage of existingMessages) {
|
|
@@ -11849,8 +13104,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11849
13104
|
return message;
|
|
11850
13105
|
});
|
|
11851
13106
|
}
|
|
11852
|
-
async deleteMessages(messageIds) {
|
|
13107
|
+
async deleteMessages(messageIds, options) {
|
|
11853
13108
|
if (!messageIds || messageIds.length === 0) return;
|
|
13109
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, options?.fence);
|
|
11854
13110
|
try {
|
|
11855
13111
|
const messageTableName = getTableName$3({
|
|
11856
13112
|
indexName: _mastra_core_storage.TABLE_MESSAGES,
|
|
@@ -11861,12 +13117,14 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11861
13117
|
schemaName: getSchemaName$3(this.#schema)
|
|
11862
13118
|
});
|
|
11863
13119
|
await this.#db.client.tx(async (t) => {
|
|
13120
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "deleteMessages");
|
|
11864
13121
|
const placeholders = messageIds.map((_, idx) => `$${idx + 1}`).join(",");
|
|
11865
13122
|
const threadIds = (await t.manyOrNone(`SELECT DISTINCT thread_id FROM ${messageTableName} WHERE id IN (${placeholders})`, messageIds))?.map((msg) => msg.thread_id).filter(Boolean) || [];
|
|
11866
13123
|
await t.none(`DELETE FROM ${messageTableName} WHERE id IN (${placeholders})`, messageIds);
|
|
11867
13124
|
if (threadIds.length > 0) await t.none(`UPDATE ${threadTableName} SET "updatedAt" = NOW(), "updatedAtZ" = NOW() WHERE id IN (${inPlaceholders(threadIds.length)})`, threadIds);
|
|
11868
13125
|
});
|
|
11869
13126
|
} catch (error) {
|
|
13127
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
11870
13128
|
throw new _mastra_core_error.MastraError({
|
|
11871
13129
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "DELETE_MESSAGES", "FAILED"),
|
|
11872
13130
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -11894,6 +13152,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11894
13152
|
};
|
|
11895
13153
|
}
|
|
11896
13154
|
async saveResource({ resource }) {
|
|
13155
|
+
return this.#insertResource(this.#db.client, resource);
|
|
13156
|
+
}
|
|
13157
|
+
async #insertResource(q, resource) {
|
|
11897
13158
|
const createdAt = toUtcISOString(resource.createdAt);
|
|
11898
13159
|
const updatedAt = toUtcISOString(resource.updatedAt);
|
|
11899
13160
|
const metadataJson = toPgJson(resource.metadata);
|
|
@@ -11905,7 +13166,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11905
13166
|
createdAt,
|
|
11906
13167
|
updatedAt
|
|
11907
13168
|
}
|
|
11908
|
-
});
|
|
13169
|
+
}, q);
|
|
11909
13170
|
return {
|
|
11910
13171
|
...resource,
|
|
11911
13172
|
metadata: metadataJson ? JSON.parse(metadataJson) : resource.metadata
|
|
@@ -11916,9 +13177,11 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11916
13177
|
indexName: _mastra_core_storage.TABLE_RESOURCES,
|
|
11917
13178
|
schemaName: getSchemaName$3(this.#schema)
|
|
11918
13179
|
});
|
|
13180
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, void 0);
|
|
11919
13181
|
const callbackError = {};
|
|
11920
13182
|
try {
|
|
11921
13183
|
return await this.#db.client.tx(async (t) => {
|
|
13184
|
+
if (fence) await assertRunFence(t, this.#runFencesTable(), fence, "mergeResourceWorkingMemory");
|
|
11922
13185
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11923
13186
|
await t.none(`INSERT INTO ${tableName} (id, metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ")
|
|
11924
13187
|
VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (id) DO NOTHING`, [
|
|
@@ -11962,8 +13225,15 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11962
13225
|
}, error);
|
|
11963
13226
|
}
|
|
11964
13227
|
}
|
|
11965
|
-
async updateResource({ resourceId, workingMemory, metadata }) {
|
|
11966
|
-
|
|
13228
|
+
async updateResource({ resourceId, workingMemory, metadata, fence }) {
|
|
13229
|
+
return this.#fenced(fence, "updateResource", (q) => this.#updateResource(q, {
|
|
13230
|
+
resourceId,
|
|
13231
|
+
workingMemory,
|
|
13232
|
+
metadata
|
|
13233
|
+
}));
|
|
13234
|
+
}
|
|
13235
|
+
async #updateResource(q, { resourceId, workingMemory, metadata }) {
|
|
13236
|
+
const existingResource = await this.#getResourceById(q, resourceId);
|
|
11967
13237
|
if (!existingResource) {
|
|
11968
13238
|
const newResource = {
|
|
11969
13239
|
id: resourceId,
|
|
@@ -11972,7 +13242,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
11972
13242
|
createdAt: /* @__PURE__ */ new Date(),
|
|
11973
13243
|
updatedAt: /* @__PURE__ */ new Date()
|
|
11974
13244
|
};
|
|
11975
|
-
return this
|
|
13245
|
+
return this.#insertResource(q, newResource);
|
|
11976
13246
|
}
|
|
11977
13247
|
const updatedResource = {
|
|
11978
13248
|
...existingResource,
|
|
@@ -12008,7 +13278,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12008
13278
|
updates.push(`"updatedAtZ" = $${paramIndex++}`);
|
|
12009
13279
|
values.push(updatedAtStr);
|
|
12010
13280
|
values.push(resourceId);
|
|
12011
|
-
await
|
|
13281
|
+
await q.none(`UPDATE ${tableName} SET ${updates.join(", ")} WHERE id = $${paramIndex}`, values);
|
|
12012
13282
|
return metadataJson ? {
|
|
12013
13283
|
...updatedResource,
|
|
12014
13284
|
metadata: JSON.parse(metadataJson)
|
|
@@ -12147,9 +13417,11 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12147
13417
|
* serializes generation creation across processes instead. It is
|
|
12148
13418
|
* transaction-scoped so it also works behind transaction-pooling proxies.
|
|
12149
13419
|
*/
|
|
12150
|
-
async #withOMLookupKeyLock(tableName, lookupKey, fn) {
|
|
13420
|
+
async #withOMLookupKeyLock(tableName, lookupKey, fn, fencedOperation) {
|
|
13421
|
+
const fence = fencedOperation ? (0, _mastra_core_storage.resolveRunFence)(this, void 0) : void 0;
|
|
12151
13422
|
return this.#db.client.tx(async (t) => {
|
|
12152
13423
|
await t.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [`${tableName}:${lookupKey}`]);
|
|
13424
|
+
if (fence && fencedOperation) await assertRunFence(t, this.#runFencesTable(), fence, fencedOperation);
|
|
12153
13425
|
return fn(t);
|
|
12154
13426
|
});
|
|
12155
13427
|
}
|
|
@@ -12446,7 +13718,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12446
13718
|
const lastObservedAtStr = input.lastObservedAt.toISOString();
|
|
12447
13719
|
const nowStr = now.toISOString();
|
|
12448
13720
|
const observedMessageIdsJson = input.observedMessageIds ? toPgJson(input.observedMessageIds) : null;
|
|
12449
|
-
if ((await this.#
|
|
13721
|
+
if ((await this.#fenced(void 0, "updateActiveObservations", (q) => q.query(`UPDATE ${tableName} SET
|
|
12450
13722
|
"activeObservations" = $1,
|
|
12451
13723
|
"lastObservedAt" = $2,
|
|
12452
13724
|
"lastObservedAtZ" = $3,
|
|
@@ -12466,7 +13738,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12466
13738
|
nowStr,
|
|
12467
13739
|
nowStr,
|
|
12468
13740
|
input.id
|
|
12469
|
-
])).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
13741
|
+
]))).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
12470
13742
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_ACTIVE_OBSERVATIONS", "NOT_FOUND"),
|
|
12471
13743
|
text: `Observational memory record not found: ${input.id}`,
|
|
12472
13744
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -12474,7 +13746,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12474
13746
|
details: { id: input.id }
|
|
12475
13747
|
});
|
|
12476
13748
|
} catch (error) {
|
|
12477
|
-
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
13749
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
12478
13750
|
throw new _mastra_core_error.MastraError({
|
|
12479
13751
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_ACTIVE_OBSERVATIONS", "FAILED"),
|
|
12480
13752
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -12494,8 +13766,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12494
13766
|
const newer = await this.#getNewerOMGeneration(t, tableName, lookupKey, input.currentRecord.generationCount);
|
|
12495
13767
|
if (newer) return newer;
|
|
12496
13768
|
return this.#insertReflectionGeneration(t, tableName, lookupKey, input);
|
|
12497
|
-
});
|
|
13769
|
+
}, "createReflectionGeneration");
|
|
12498
13770
|
} catch (error) {
|
|
13771
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
12499
13772
|
throw new _mastra_core_error.MastraError({
|
|
12500
13773
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "CREATE_REFLECTION_GENERATION", "FAILED"),
|
|
12501
13774
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -12855,7 +14128,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12855
14128
|
extractionFailures: input.chunk.extractionFailures
|
|
12856
14129
|
};
|
|
12857
14130
|
const lastBufferedAtTime = input.lastBufferedAtTime ? input.lastBufferedAtTime.toISOString() : null;
|
|
12858
|
-
if ((await this.#
|
|
14131
|
+
if ((await this.#fenced(void 0, "updateBufferedObservations", (q) => q.query(`UPDATE ${tableName} SET
|
|
12859
14132
|
"bufferedObservationChunks" = CASE
|
|
12860
14133
|
WHEN EXISTS (
|
|
12861
14134
|
SELECT 1
|
|
@@ -12874,7 +14147,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12874
14147
|
nowStr,
|
|
12875
14148
|
nowStr,
|
|
12876
14149
|
input.id
|
|
12877
|
-
])).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
14150
|
+
]))).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
12878
14151
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
|
|
12879
14152
|
text: `Observational memory record not found: ${input.id}`,
|
|
12880
14153
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -12882,7 +14155,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12882
14155
|
details: { id: input.id }
|
|
12883
14156
|
});
|
|
12884
14157
|
} catch (error) {
|
|
12885
|
-
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
14158
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
12886
14159
|
throw new _mastra_core_error.MastraError({
|
|
12887
14160
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_BUFFERED_OBSERVATIONS", "FAILED"),
|
|
12888
14161
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -12964,7 +14237,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12964
14237
|
const lastObservedAt = input.lastObservedAt ?? (latestChunk?.lastObservedAt ? new Date(latestChunk.lastObservedAt) : /* @__PURE__ */ new Date());
|
|
12965
14238
|
const lastObservedAtStr = lastObservedAt.toISOString();
|
|
12966
14239
|
const boundary = `\n\n--- message boundary (${lastObservedAt.toISOString()}) ---\n\n`;
|
|
12967
|
-
if ((await this.#
|
|
14240
|
+
if ((await this.#fenced(void 0, "swapBufferedToActive", (q) => q.query(`UPDATE ${tableName} SET
|
|
12968
14241
|
"activeObservations" = CASE
|
|
12969
14242
|
WHEN "activeObservations" IS NOT NULL AND "activeObservations" != ''
|
|
12970
14243
|
THEN "activeObservations" || $10 || $1
|
|
@@ -12990,7 +14263,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
12990
14263
|
nowStr,
|
|
12991
14264
|
input.id,
|
|
12992
14265
|
boundary
|
|
12993
|
-
])).rowCount === 0) return {
|
|
14266
|
+
]))).rowCount === 0) return {
|
|
12994
14267
|
chunksActivated: 0,
|
|
12995
14268
|
messageTokensActivated: 0,
|
|
12996
14269
|
observationTokensActivated: 0,
|
|
@@ -13018,7 +14291,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13018
14291
|
currentTask: latestChunkHints?.currentTask ?? void 0
|
|
13019
14292
|
};
|
|
13020
14293
|
} catch (error) {
|
|
13021
|
-
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
14294
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
13022
14295
|
throw new _mastra_core_error.MastraError({
|
|
13023
14296
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SWAP_BUFFERED_TO_ACTIVE", "FAILED"),
|
|
13024
14297
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -13034,7 +14307,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13034
14307
|
schemaName: getSchemaName$3(this.#schema)
|
|
13035
14308
|
});
|
|
13036
14309
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
13037
|
-
if ((await this.#
|
|
14310
|
+
if ((await this.#fenced(void 0, "updateBufferedReflection", (q) => q.query(`UPDATE ${tableName} SET
|
|
13038
14311
|
"bufferedReflection" = CASE
|
|
13039
14312
|
WHEN "bufferedReflection" IS NOT NULL AND "bufferedReflection" != ''
|
|
13040
14313
|
THEN "bufferedReflection" || E'\\n\\n' || $1
|
|
@@ -13053,7 +14326,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13053
14326
|
nowStr,
|
|
13054
14327
|
nowStr,
|
|
13055
14328
|
input.id
|
|
13056
|
-
])).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
14329
|
+
]))).rowCount === 0) throw new _mastra_core_error.MastraError({
|
|
13057
14330
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_BUFFERED_REFLECTION", "NOT_FOUND"),
|
|
13058
14331
|
text: `Observational memory record not found: ${input.id}`,
|
|
13059
14332
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -13061,7 +14334,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13061
14334
|
details: { id: input.id }
|
|
13062
14335
|
});
|
|
13063
14336
|
} catch (error) {
|
|
13064
|
-
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
14337
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
13065
14338
|
throw new _mastra_core_error.MastraError({
|
|
13066
14339
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_BUFFERED_REFLECTION", "FAILED"),
|
|
13067
14340
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -13118,9 +14391,9 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
|
|
|
13118
14391
|
input.currentRecord.id
|
|
13119
14392
|
]);
|
|
13120
14393
|
return newRecord;
|
|
13121
|
-
});
|
|
14394
|
+
}, "swapBufferedReflectionToActive");
|
|
13122
14395
|
} catch (error) {
|
|
13123
|
-
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
14396
|
+
if (error instanceof _mastra_core_error.MastraError || (0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
13124
14397
|
throw new _mastra_core_error.MastraError({
|
|
13125
14398
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "FAILED"),
|
|
13126
14399
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -20116,6 +21389,7 @@ var PromptBlocksPG = class PromptBlocksPG extends _mastra_core_storage.PromptBlo
|
|
|
20116
21389
|
}
|
|
20117
21390
|
async create(input) {
|
|
20118
21391
|
const { promptBlock } = input;
|
|
21392
|
+
let draftInserted = false;
|
|
20119
21393
|
try {
|
|
20120
21394
|
const tableName = getTableName$5({
|
|
20121
21395
|
indexName: _mastra_core_storage.TABLE_PROMPT_BLOCKS,
|
|
@@ -20137,6 +21411,7 @@ var PromptBlocksPG = class PromptBlocksPG extends _mastra_core_storage.PromptBlo
|
|
|
20137
21411
|
nowIso,
|
|
20138
21412
|
nowIso
|
|
20139
21413
|
]);
|
|
21414
|
+
draftInserted = true;
|
|
20140
21415
|
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = promptBlock;
|
|
20141
21416
|
const versionId = crypto.randomUUID();
|
|
20142
21417
|
await this.createVersion({
|
|
@@ -20157,14 +21432,14 @@ var PromptBlocksPG = class PromptBlocksPG extends _mastra_core_storage.PromptBlo
|
|
|
20157
21432
|
updatedAt: now
|
|
20158
21433
|
};
|
|
20159
21434
|
} catch (error) {
|
|
20160
|
-
if (
|
|
20161
|
-
try {
|
|
21435
|
+
if (draftInserted) try {
|
|
20162
21436
|
const tableName = getTableName$5({
|
|
20163
21437
|
indexName: _mastra_core_storage.TABLE_PROMPT_BLOCKS,
|
|
20164
21438
|
schemaName: getSchemaName$5(this.#schema)
|
|
20165
21439
|
});
|
|
20166
21440
|
await this.#db.client.none(`DELETE FROM ${tableName} WHERE id = $1 AND status = 'draft' AND "activeVersionId" IS NULL`, [promptBlock.id]);
|
|
20167
21441
|
} catch {}
|
|
21442
|
+
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
20168
21443
|
throw new _mastra_core_error.MastraError({
|
|
20169
21444
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "CREATE_PROMPT_BLOCK", "FAILED"),
|
|
20170
21445
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -21060,6 +22335,7 @@ var ScorerDefinitionsPG = class ScorerDefinitionsPG extends _mastra_core_storage
|
|
|
21060
22335
|
}
|
|
21061
22336
|
async create(input) {
|
|
21062
22337
|
const { scorerDefinition } = input;
|
|
22338
|
+
let draftInserted = false;
|
|
21063
22339
|
try {
|
|
21064
22340
|
const tableName = getTableName$5({
|
|
21065
22341
|
indexName: _mastra_core_storage.TABLE_SCORER_DEFINITIONS,
|
|
@@ -21083,6 +22359,7 @@ var ScorerDefinitionsPG = class ScorerDefinitionsPG extends _mastra_core_storage
|
|
|
21083
22359
|
nowIso,
|
|
21084
22360
|
nowIso
|
|
21085
22361
|
]);
|
|
22362
|
+
draftInserted = true;
|
|
21086
22363
|
const { id: _id, authorId: _authorId, organizationId: _organizationId, projectId: _projectId, metadata: _metadata, ...snapshotConfig } = scorerDefinition;
|
|
21087
22364
|
const versionId = crypto.randomUUID();
|
|
21088
22365
|
await this.createVersion({
|
|
@@ -21105,7 +22382,7 @@ var ScorerDefinitionsPG = class ScorerDefinitionsPG extends _mastra_core_storage
|
|
|
21105
22382
|
updatedAt: now
|
|
21106
22383
|
};
|
|
21107
22384
|
} catch (error) {
|
|
21108
|
-
try {
|
|
22385
|
+
if (draftInserted) try {
|
|
21109
22386
|
const tableName = getTableName$5({
|
|
21110
22387
|
indexName: _mastra_core_storage.TABLE_SCORER_DEFINITIONS,
|
|
21111
22388
|
schemaName: getSchemaName$5(this.#schema)
|
|
@@ -22123,6 +23400,7 @@ var SkillsPG = class SkillsPG extends _mastra_core_storage.SkillsStorage {
|
|
|
22123
23400
|
}
|
|
22124
23401
|
async create(input) {
|
|
22125
23402
|
const { skill } = input;
|
|
23403
|
+
let draftInserted = false;
|
|
22126
23404
|
try {
|
|
22127
23405
|
const tableName = getTableName$5({
|
|
22128
23406
|
indexName: _mastra_core_storage.TABLE_SKILLS,
|
|
@@ -22146,6 +23424,7 @@ var SkillsPG = class SkillsPG extends _mastra_core_storage.SkillsStorage {
|
|
|
22146
23424
|
nowIso,
|
|
22147
23425
|
nowIso
|
|
22148
23426
|
]);
|
|
23427
|
+
draftInserted = true;
|
|
22149
23428
|
const { id: _id, authorId: _authorId, visibility: _visibility, ...snapshotConfig } = skill;
|
|
22150
23429
|
const versionId = crypto.randomUUID();
|
|
22151
23430
|
await this.createVersion({
|
|
@@ -22167,7 +23446,7 @@ var SkillsPG = class SkillsPG extends _mastra_core_storage.SkillsStorage {
|
|
|
22167
23446
|
updatedAt: now
|
|
22168
23447
|
};
|
|
22169
23448
|
} catch (error) {
|
|
22170
|
-
try {
|
|
23449
|
+
if (draftInserted) try {
|
|
22171
23450
|
const tableName = getTableName$5({
|
|
22172
23451
|
indexName: _mastra_core_storage.TABLE_SKILLS,
|
|
22173
23452
|
schemaName: getSchemaName$5(this.#schema)
|
|
@@ -23312,6 +24591,17 @@ function getTableName({ indexName, schemaName }) {
|
|
|
23312
24591
|
const quotedIndexName = `"${indexName}"`;
|
|
23313
24592
|
return schemaName ? `${schemaName}.${quotedIndexName}` : quotedIndexName;
|
|
23314
24593
|
}
|
|
24594
|
+
const RUN_OWNER_COLUMNS = `generation, "ownerId", "leaseExpiresAt", ${DB_NOW_MS} AS "nowMs"`;
|
|
24595
|
+
function toRunOwnershipRecord(runId, row) {
|
|
24596
|
+
const leaseExpiresAt = row.leaseExpiresAt === null ? null : Number(row.leaseExpiresAt);
|
|
24597
|
+
return {
|
|
24598
|
+
runId,
|
|
24599
|
+
generation: Number(row.generation),
|
|
24600
|
+
ownerId: row.ownerId,
|
|
24601
|
+
leaseExpiresAt: leaseExpiresAt === null ? null : new Date(leaseExpiresAt),
|
|
24602
|
+
live: leaseExpiresAt !== null && leaseExpiresAt > Number(row.nowMs)
|
|
24603
|
+
};
|
|
24604
|
+
}
|
|
23315
24605
|
/** Base name (before any schema prefix) of the expression index backing the status filter. */
|
|
23316
24606
|
const WORKFLOW_SNAPSHOT_STATUS_INDEX = "mastra_workflow_snapshot_name_status_createdat_idx";
|
|
23317
24607
|
/**
|
|
@@ -23396,12 +24686,24 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23396
24686
|
* Workflow run snapshots accumulate as runs execute. Anchored on the
|
|
23397
24687
|
* timezone-aware `updatedAtZ` mirror column (last activity) so suspended or
|
|
23398
24688
|
* long-running runs are not pruned by start age.
|
|
24689
|
+
*
|
|
24690
|
+
* Run ownership rows are anchored on `updatedAt` (epoch ms), which every
|
|
24691
|
+
* claim, renewal and release refreshes, so a live execution's row is never
|
|
24692
|
+
* older than its renew interval.
|
|
23399
24693
|
*/
|
|
23400
|
-
static retentionTables = {
|
|
23401
|
-
|
|
23402
|
-
|
|
23403
|
-
|
|
23404
|
-
|
|
24694
|
+
static retentionTables = {
|
|
24695
|
+
workflowSnapshot: {
|
|
24696
|
+
table: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
24697
|
+
column: "updatedAtZ",
|
|
24698
|
+
indexed: true
|
|
24699
|
+
},
|
|
24700
|
+
runOwnership: {
|
|
24701
|
+
table: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
|
|
24702
|
+
column: "updatedAt",
|
|
24703
|
+
indexed: true,
|
|
24704
|
+
anchorType: "epoch-ms"
|
|
24705
|
+
}
|
|
24706
|
+
};
|
|
23405
24707
|
constructor(config) {
|
|
23406
24708
|
super();
|
|
23407
24709
|
const { client, readClient, schemaName, skipDefaultIndexes, indexes } = resolvePgConfig(config);
|
|
@@ -23458,6 +24760,12 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23458
24760
|
for (const idx of WorkflowsPG.getDefaultIndexDefs(schemaPrefix)) statements.push(generateIndexSQL(idx, schemaName));
|
|
23459
24761
|
statements.push(`${workflowSnapshotStatusIndexSQL(workflowSnapshotStatusIndexName(parsedSchema), schemaName)};`);
|
|
23460
24762
|
statements.push(`${workflowSnapshotThreadIdIndexSQL(workflowSnapshotThreadIdIndexName(parsedSchema), schemaName)};`);
|
|
24763
|
+
statements.push(generateTableSQL({
|
|
24764
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
|
|
24765
|
+
schema: _mastra_core_storage.RUN_FENCING_TABLE_SCHEMAS[_mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS],
|
|
24766
|
+
schemaName,
|
|
24767
|
+
includeAllConstraints: true
|
|
24768
|
+
}));
|
|
23461
24769
|
return statements;
|
|
23462
24770
|
}
|
|
23463
24771
|
/**
|
|
@@ -23501,6 +24809,10 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23501
24809
|
schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT],
|
|
23502
24810
|
ifNotExists: ["resourceId"]
|
|
23503
24811
|
});
|
|
24812
|
+
await this.#db.createTable({
|
|
24813
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
|
|
24814
|
+
schema: _mastra_core_storage.RUN_FENCING_TABLE_SCHEMAS[_mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS]
|
|
24815
|
+
});
|
|
23504
24816
|
await this.createDefaultIndexes();
|
|
23505
24817
|
await this.createCustomIndexes();
|
|
23506
24818
|
}
|
|
@@ -23528,13 +24840,13 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23528
24840
|
}
|
|
23529
24841
|
}
|
|
23530
24842
|
}
|
|
23531
|
-
/** Delete workflow run snapshots older than
|
|
24843
|
+
/** Delete workflow run snapshots and run ownership rows older than their policy's `maxAge`, batched. */
|
|
23532
24844
|
async prune(policies, options) {
|
|
23533
24845
|
await this.ensureRetentionIndexes(policies);
|
|
23534
24846
|
const targets = resolveTargets({
|
|
23535
24847
|
policies,
|
|
23536
24848
|
descriptor: WorkflowsPG.retentionTables,
|
|
23537
|
-
order: ["workflowSnapshot"]
|
|
24849
|
+
order: ["workflowSnapshot", "runOwnership"]
|
|
23538
24850
|
});
|
|
23539
24851
|
return runPrune({
|
|
23540
24852
|
db: this.#db,
|
|
@@ -23556,10 +24868,126 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23556
24868
|
}
|
|
23557
24869
|
async dangerouslyClearAll() {
|
|
23558
24870
|
await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT });
|
|
24871
|
+
await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS });
|
|
24872
|
+
}
|
|
24873
|
+
supportsRunFencing() {
|
|
24874
|
+
return true;
|
|
24875
|
+
}
|
|
24876
|
+
#runOwnersTable() {
|
|
24877
|
+
return getTableName({
|
|
24878
|
+
indexName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
|
|
24879
|
+
schemaName: getSchemaName(this.#schema)
|
|
24880
|
+
});
|
|
24881
|
+
}
|
|
24882
|
+
async #readRunOwner(q, runId) {
|
|
24883
|
+
const row = await q.oneOrNone(`SELECT ${RUN_OWNER_COLUMNS} FROM ${this.#runOwnersTable()} WHERE "runId" = $1`, [runId]);
|
|
24884
|
+
return row ? toRunOwnershipRecord(runId, row) : null;
|
|
24885
|
+
}
|
|
24886
|
+
#ownershipError(operation, runId, error) {
|
|
24887
|
+
return new _mastra_core_error.MastraError({
|
|
24888
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", operation, "FAILED"),
|
|
24889
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
24890
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
24891
|
+
details: { runId }
|
|
24892
|
+
}, error);
|
|
24893
|
+
}
|
|
24894
|
+
async claimRunOwnership({ runId, ownerId, leaseMs, force, expectedGeneration }) {
|
|
24895
|
+
const table = this.#runOwnersTable();
|
|
24896
|
+
try {
|
|
24897
|
+
return await this.#db.client.tx(async (t) => {
|
|
24898
|
+
if (!await t.oneOrNone(`SELECT 1 FROM ${table} WHERE "runId" = $1 FOR UPDATE`, [runId])) {
|
|
24899
|
+
if (expectedGeneration !== void 0 && expectedGeneration !== 0) return {
|
|
24900
|
+
acquired: false,
|
|
24901
|
+
record: null
|
|
24902
|
+
};
|
|
24903
|
+
const inserted = await t.oneOrNone(`INSERT INTO ${table} ("runId", generation, "ownerId", "leaseExpiresAt", "updatedAt")
|
|
24904
|
+
VALUES ($1, GREATEST(1, ${DB_NOW_MS}), $2, ${DB_NOW_MS} + $3, ${DB_NOW_MS})
|
|
24905
|
+
ON CONFLICT ("runId") DO NOTHING
|
|
24906
|
+
RETURNING ${RUN_OWNER_COLUMNS}`, [
|
|
24907
|
+
runId,
|
|
24908
|
+
ownerId,
|
|
24909
|
+
leaseMs
|
|
24910
|
+
]);
|
|
24911
|
+
if (inserted) return {
|
|
24912
|
+
acquired: true,
|
|
24913
|
+
record: toRunOwnershipRecord(runId, inserted)
|
|
24914
|
+
};
|
|
24915
|
+
}
|
|
24916
|
+
const claimed = await t.oneOrNone(`UPDATE ${table}
|
|
24917
|
+
SET generation = generation + 1, "ownerId" = $2, "leaseExpiresAt" = ${DB_NOW_MS} + $3,
|
|
24918
|
+
"updatedAt" = ${DB_NOW_MS}
|
|
24919
|
+
WHERE "runId" = $1
|
|
24920
|
+
AND ($4::bigint IS NULL OR generation = $4)
|
|
24921
|
+
AND ($5::boolean OR "leaseExpiresAt" IS NULL OR "leaseExpiresAt" <= ${DB_NOW_MS})
|
|
24922
|
+
RETURNING ${RUN_OWNER_COLUMNS}`, [
|
|
24923
|
+
runId,
|
|
24924
|
+
ownerId,
|
|
24925
|
+
leaseMs,
|
|
24926
|
+
expectedGeneration ?? null,
|
|
24927
|
+
force === true
|
|
24928
|
+
]);
|
|
24929
|
+
if (claimed) return {
|
|
24930
|
+
acquired: true,
|
|
24931
|
+
record: toRunOwnershipRecord(runId, claimed)
|
|
24932
|
+
};
|
|
24933
|
+
return {
|
|
24934
|
+
acquired: false,
|
|
24935
|
+
record: await this.#readRunOwner(t, runId)
|
|
24936
|
+
};
|
|
24937
|
+
});
|
|
24938
|
+
} catch (error) {
|
|
24939
|
+
throw this.#ownershipError("CLAIM_RUN_OWNERSHIP", runId, error);
|
|
24940
|
+
}
|
|
24941
|
+
}
|
|
24942
|
+
async renewRunOwnership({ leaseMs, ...fence }) {
|
|
24943
|
+
try {
|
|
24944
|
+
const renewed = await this.#db.client.oneOrNone(`UPDATE ${this.#runOwnersTable()}
|
|
24945
|
+
SET "leaseExpiresAt" = ${DB_NOW_MS} + $4, "updatedAt" = ${DB_NOW_MS}
|
|
24946
|
+
WHERE "runId" = $1 AND generation = $2 AND "ownerId" = $3 AND "leaseExpiresAt" IS NOT NULL
|
|
24947
|
+
RETURNING ${RUN_OWNER_COLUMNS}`, [
|
|
24948
|
+
fence.runId,
|
|
24949
|
+
fence.generation,
|
|
24950
|
+
fence.ownerId,
|
|
24951
|
+
leaseMs
|
|
24952
|
+
]);
|
|
24953
|
+
if (renewed) return {
|
|
24954
|
+
renewed: true,
|
|
24955
|
+
record: toRunOwnershipRecord(fence.runId, renewed)
|
|
24956
|
+
};
|
|
24957
|
+
return {
|
|
24958
|
+
renewed: false,
|
|
24959
|
+
record: await this.#readRunOwner(this.#db.client, fence.runId)
|
|
24960
|
+
};
|
|
24961
|
+
} catch (error) {
|
|
24962
|
+
throw this.#ownershipError("RENEW_RUN_OWNERSHIP", fence.runId, error);
|
|
24963
|
+
}
|
|
24964
|
+
}
|
|
24965
|
+
async releaseRunOwnership(fence) {
|
|
24966
|
+
try {
|
|
24967
|
+
return await this.#db.client.oneOrNone(`UPDATE ${this.#runOwnersTable()}
|
|
24968
|
+
SET "leaseExpiresAt" = NULL, "updatedAt" = ${DB_NOW_MS}
|
|
24969
|
+
WHERE "runId" = $1 AND generation = $2 AND "ownerId" = $3
|
|
24970
|
+
RETURNING "runId"`, [
|
|
24971
|
+
fence.runId,
|
|
24972
|
+
fence.generation,
|
|
24973
|
+
fence.ownerId
|
|
24974
|
+
]) !== null;
|
|
24975
|
+
} catch (error) {
|
|
24976
|
+
throw this.#ownershipError("RELEASE_RUN_OWNERSHIP", fence.runId, error);
|
|
24977
|
+
}
|
|
24978
|
+
}
|
|
24979
|
+
async getRunOwnership({ runId }) {
|
|
24980
|
+
try {
|
|
24981
|
+
return await this.#readRunOwner(this.#db.client, runId);
|
|
24982
|
+
} catch (error) {
|
|
24983
|
+
throw this.#ownershipError("GET_RUN_OWNERSHIP", runId, error);
|
|
24984
|
+
}
|
|
23559
24985
|
}
|
|
23560
|
-
async updateWorkflowResults({ workflowName, runId, stepId, result, requestContext, state }) {
|
|
24986
|
+
async updateWorkflowResults({ workflowName, runId, stepId, result, requestContext, state, fence: explicitFence }) {
|
|
24987
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, explicitFence, runId);
|
|
23561
24988
|
try {
|
|
23562
24989
|
return await this.#db.client.tx(async (t) => {
|
|
24990
|
+
if (fence) await assertRunFence(t, this.#runOwnersTable(), fence, "updateWorkflowResults");
|
|
23563
24991
|
const tableName = getTableName({
|
|
23564
24992
|
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
23565
24993
|
schemaName: getSchemaName(this.#schema)
|
|
@@ -23609,6 +25037,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23609
25037
|
return snapshot.context;
|
|
23610
25038
|
});
|
|
23611
25039
|
} catch (error) {
|
|
25040
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
23612
25041
|
throw new _mastra_core_error.MastraError({
|
|
23613
25042
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
|
|
23614
25043
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -23621,9 +25050,11 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23621
25050
|
}, error);
|
|
23622
25051
|
}
|
|
23623
25052
|
}
|
|
23624
|
-
async updateWorkflowState({ workflowName, runId, opts }) {
|
|
25053
|
+
async updateWorkflowState({ workflowName, runId, opts, fence: explicitFence }) {
|
|
25054
|
+
const fence = (0, _mastra_core_storage.resolveRunFence)(this, explicitFence, runId);
|
|
23625
25055
|
try {
|
|
23626
25056
|
return await this.#db.client.tx(async (t) => {
|
|
25057
|
+
if (fence) await assertRunFence(t, this.#runOwnersTable(), fence, "updateWorkflowState");
|
|
23627
25058
|
const tableName = getTableName({
|
|
23628
25059
|
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
23629
25060
|
schemaName: getSchemaName(this.#schema)
|
|
@@ -23653,6 +25084,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23653
25084
|
return updatedSnapshot;
|
|
23654
25085
|
});
|
|
23655
25086
|
} catch (error) {
|
|
25087
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
23656
25088
|
throw new _mastra_core_error.MastraError({
|
|
23657
25089
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_WORKFLOW_STATE", "FAILED"),
|
|
23658
25090
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -23664,13 +25096,13 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23664
25096
|
}, error);
|
|
23665
25097
|
}
|
|
23666
25098
|
}
|
|
23667
|
-
async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt }) {
|
|
25099
|
+
async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence }) {
|
|
23668
25100
|
try {
|
|
23669
25101
|
const now = /* @__PURE__ */ new Date();
|
|
23670
25102
|
const createdAtValue = createdAt ? createdAt : now;
|
|
23671
25103
|
const updatedAtValue = updatedAt ? updatedAt : now;
|
|
23672
25104
|
const sanitizedSnapshot = toPgJson(snapshot);
|
|
23673
|
-
await this.#db.client.none(`INSERT INTO ${getTableName({
|
|
25105
|
+
await withRunFence(this.#db.client, this.#runOwnersTable(), (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "persistWorkflowSnapshot", (q) => q.none(`INSERT INTO ${getTableName({
|
|
23674
25106
|
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
23675
25107
|
schemaName: getSchemaName(this.#schema)
|
|
23676
25108
|
})} AS t
|
|
@@ -23686,8 +25118,9 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23686
25118
|
updatedAtValue,
|
|
23687
25119
|
createdAtValue,
|
|
23688
25120
|
updatedAtValue
|
|
23689
|
-
]);
|
|
25121
|
+
]));
|
|
23690
25122
|
} catch (error) {
|
|
25123
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
23691
25124
|
throw new _mastra_core_error.MastraError({
|
|
23692
25125
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
|
|
23693
25126
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -23753,13 +25186,14 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
|
|
|
23753
25186
|
}, error);
|
|
23754
25187
|
}
|
|
23755
25188
|
}
|
|
23756
|
-
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
25189
|
+
async deleteWorkflowRunById({ runId, workflowName, fence }) {
|
|
23757
25190
|
try {
|
|
23758
|
-
await this.#db.client.none(`DELETE FROM ${getTableName({
|
|
25191
|
+
await withRunFence(this.#db.client, this.#runOwnersTable(), (0, _mastra_core_storage.resolveRunFence)(this, fence, runId), "deleteWorkflowRunById", (q) => q.none(`DELETE FROM ${getTableName({
|
|
23759
25192
|
indexName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
23760
25193
|
schemaName: getSchemaName(this.#schema)
|
|
23761
|
-
})} WHERE run_id = $1 AND workflow_name = $2`, [runId, workflowName]);
|
|
25194
|
+
})} WHERE run_id = $1 AND workflow_name = $2`, [runId, workflowName]));
|
|
23762
25195
|
} catch (error) {
|
|
25196
|
+
if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
|
|
23763
25197
|
throw new _mastra_core_error.MastraError({
|
|
23764
25198
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
23765
25199
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -23971,6 +25405,7 @@ var WorkspacesPG = class WorkspacesPG extends _mastra_core_storage.WorkspacesSto
|
|
|
23971
25405
|
}
|
|
23972
25406
|
async create(input) {
|
|
23973
25407
|
const { workspace } = input;
|
|
25408
|
+
let draftInserted = false;
|
|
23974
25409
|
try {
|
|
23975
25410
|
const tableName = getTableName$5({
|
|
23976
25411
|
indexName: _mastra_core_storage.TABLE_WORKSPACES,
|
|
@@ -23992,6 +25427,7 @@ var WorkspacesPG = class WorkspacesPG extends _mastra_core_storage.WorkspacesSto
|
|
|
23992
25427
|
nowIso,
|
|
23993
25428
|
nowIso
|
|
23994
25429
|
]);
|
|
25430
|
+
draftInserted = true;
|
|
23995
25431
|
const { id: _id, authorId: _authorId, metadata: _metadata, ...snapshotConfig } = workspace;
|
|
23996
25432
|
const versionId = crypto.randomUUID();
|
|
23997
25433
|
await this.createVersion({
|
|
@@ -24012,7 +25448,7 @@ var WorkspacesPG = class WorkspacesPG extends _mastra_core_storage.WorkspacesSto
|
|
|
24012
25448
|
updatedAt: now
|
|
24013
25449
|
};
|
|
24014
25450
|
} catch (error) {
|
|
24015
|
-
try {
|
|
25451
|
+
if (draftInserted) try {
|
|
24016
25452
|
const tableName = getTableName$5({
|
|
24017
25453
|
indexName: _mastra_core_storage.TABLE_WORKSPACES,
|
|
24018
25454
|
schemaName: getSchemaName$5(this.#schema)
|
|
@@ -25062,7 +26498,10 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
|
|
|
25062
26498
|
workflows: new WorkflowsPG(domainConfig),
|
|
25063
26499
|
workflowDefinitions: new WorkflowDefinitionsPG(domainConfig),
|
|
25064
26500
|
memory: new MemoryPG(domainConfig),
|
|
25065
|
-
knowledge: new KnowledgePG(
|
|
26501
|
+
knowledge: new KnowledgePG({
|
|
26502
|
+
...domainConfig,
|
|
26503
|
+
storageIsolationKey: config.storageIsolationKey ?? getPgKnowledgeIsolationKey(config)
|
|
26504
|
+
}),
|
|
25066
26505
|
notifications: new NotificationsPG(domainConfig),
|
|
25067
26506
|
observability: new ObservabilityPG(domainConfig),
|
|
25068
26507
|
agents: new AgentsPG(domainConfig),
|
|
@@ -25116,7 +26555,7 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
|
|
|
25116
26555
|
const pinned = new PinnedClientAdapter(this.#writePool, pinnedClient);
|
|
25117
26556
|
this.#db.pin(pinned);
|
|
25118
26557
|
this.#db.setSchemaSnapshot(await loadSchemaSnapshot(pinned, this.schema));
|
|
25119
|
-
await
|
|
26558
|
+
await Promise.all(Object.entries(this.stores).filter(([name, store]) => name !== "knowledge" && store).map(([, store]) => store.init()));
|
|
25120
26559
|
this.isInitialized = true;
|
|
25121
26560
|
} catch (error) {
|
|
25122
26561
|
this.#initPromise = null;
|