@mastra/mongodb 1.17.0 → 1.18.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -10,7 +10,7 @@ let _mastra_core_agent = require("@mastra/core/agent");
10
10
  let _mastra_core_evals = require("@mastra/core/evals");
11
11
  let _mastra_core_storage_domains_skills = require("@mastra/core/storage/domains/skills");
12
12
  //#region package.json
13
- var version = "1.17.0";
13
+ var version = "1.18.0-alpha.1";
14
14
  //#endregion
15
15
  //#region src/vector/filter.ts
16
16
  /**
@@ -1514,6 +1514,7 @@ const SNAPSHOT_FIELDS$6 = [
1514
1514
  "workspace",
1515
1515
  "skills",
1516
1516
  "skillsFormat",
1517
+ "durable",
1517
1518
  "browser"
1518
1519
  ];
1519
1520
  var MongoDBAgentsStorage = class MongoDBAgentsStorage extends _mastra_core_storage.AgentsStorage {
@@ -4292,6 +4293,809 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
4292
4293
  }
4293
4294
  };
4294
4295
  //#endregion
4296
+ //#region src/storage/domains/knowledge/index.ts
4297
+ const cloneScope = (scope) => [...scope];
4298
+ const canonicalName = (name) => name.trim().toLocaleLowerCase();
4299
+ const nodeReferenceId = (node) => typeof node === "string" ? node : node.id;
4300
+ const sessionOptions = (session) => session ? { session } : {};
4301
+ function visibleScopeKeys(scope) {
4302
+ const canonical = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(scope);
4303
+ return canonical.map((_, index) => (0, _mastra_core_storage.knowledgeScopeKey)(canonical.slice(0, index + 1)));
4304
+ }
4305
+ function recordCursorFilter(cursor, expected) {
4306
+ const parsed = (0, _mastra_core_storage.parseKnowledgeNodeCursor)(cursor, expected);
4307
+ return { $or: [{ updatedAt: { $lt: parsed.updatedAt } }, {
4308
+ updatedAt: parsed.updatedAt,
4309
+ $or: [{ name: { $gt: parsed.name } }, {
4310
+ name: parsed.name,
4311
+ id: { $gt: parsed.id }
4312
+ }]
4313
+ }] };
4314
+ }
4315
+ function nodeFromDocument(row) {
4316
+ return {
4317
+ id: String(row.id),
4318
+ type: "node",
4319
+ name: String(row.name),
4320
+ kind: String(row.kind),
4321
+ content: row.content == null ? void 0 : String(row.content),
4322
+ scope: cloneScope(row.scope),
4323
+ version: Number(row.version),
4324
+ mergedInto: row.mergedInto ?? void 0,
4325
+ createdAt: new Date(row.createdAt),
4326
+ updatedAt: new Date(row.updatedAt)
4327
+ };
4328
+ }
4329
+ function recordFromDocument(row) {
4330
+ return {
4331
+ id: String(row.id),
4332
+ node: String(row.node),
4333
+ text: String(row.text),
4334
+ scope: cloneScope(row.scope),
4335
+ sourceThreadId: String(row.sourceThreadId),
4336
+ capturedAt: new Date(row.capturedAt),
4337
+ when: row.when ? new Date(row.when) : void 0,
4338
+ maxScope: row.maxScope ?? void 0,
4339
+ metadata: row.metadata ?? void 0,
4340
+ deletedAt: row.deletedAt ? new Date(row.deletedAt) : void 0,
4341
+ deletedBy: row.deletedBy ?? void 0
4342
+ };
4343
+ }
4344
+ function outboxFromDocument(row) {
4345
+ return {
4346
+ id: String(row.id),
4347
+ idempotencyKey: String(row.idempotencyKey),
4348
+ documentId: String(row.documentId),
4349
+ documentType: row.documentType,
4350
+ operation: row.operation,
4351
+ scope: cloneScope(row.scope),
4352
+ status: row.status,
4353
+ attempts: Number(row.attempts),
4354
+ availableAt: new Date(row.availableAt),
4355
+ claimedAt: row.claimedAt ? new Date(row.claimedAt) : void 0,
4356
+ claimedBy: row.claimedBy ?? void 0,
4357
+ createdAt: new Date(row.createdAt),
4358
+ completedAt: row.completedAt ? new Date(row.completedAt) : void 0
4359
+ };
4360
+ }
4361
+ var KnowledgeMongoDB = class KnowledgeMongoDB extends _mastra_core_storage.KnowledgeStorage {
4362
+ static MANAGED_COLLECTIONS = [
4363
+ _mastra_core_storage.TABLE_KNOWLEDGE_NODES,
4364
+ _mastra_core_storage.TABLE_KNOWLEDGE_RECORDS,
4365
+ _mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS,
4366
+ _mastra_core_storage.TABLE_KNOWLEDGE_CURSORS,
4367
+ _mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY,
4368
+ _mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX
4369
+ ];
4370
+ #connector;
4371
+ constructor(config) {
4372
+ super();
4373
+ this.#connector = resolveMongoDBConfig(config);
4374
+ }
4375
+ async init() {
4376
+ const nodes = await this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_NODES);
4377
+ const knowledge = await this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS);
4378
+ const mentions = await this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS);
4379
+ const cursors = await this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_CURSORS);
4380
+ const activity = await this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY);
4381
+ const outbox = await this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX);
4382
+ await Promise.all([
4383
+ nodes.createIndex({
4384
+ type: 1,
4385
+ scopeKey: 1,
4386
+ canonicalName: 1
4387
+ }, { unique: true }),
4388
+ nodes.createIndex({
4389
+ scopeKey: 1,
4390
+ type: 1
4391
+ }),
4392
+ knowledge.createIndex({
4393
+ node: 1,
4394
+ id: -1
4395
+ }),
4396
+ knowledge.createIndex({
4397
+ sourceThreadId: 1,
4398
+ id: -1
4399
+ }),
4400
+ mentions.createIndex({
4401
+ sourceType: 1,
4402
+ sourceId: 1,
4403
+ recordId: 1
4404
+ }, { unique: true }),
4405
+ mentions.createIndex({
4406
+ recordId: 1,
4407
+ sourceType: 1,
4408
+ sourceId: 1
4409
+ }),
4410
+ cursors.createIndex({
4411
+ sourceThreadId: 1,
4412
+ agent: 1
4413
+ }, { unique: true }),
4414
+ activity.createIndex({ id: -1 }),
4415
+ outbox.createIndex({ idempotencyKey: 1 }, { unique: true }),
4416
+ outbox.createIndex({
4417
+ status: 1,
4418
+ availableAt: 1,
4419
+ createdAt: 1
4420
+ })
4421
+ ]);
4422
+ }
4423
+ async dangerouslyClearAll() {
4424
+ await this.#connector.withTransaction(async (session) => {
4425
+ for (const name of KnowledgeMongoDB.MANAGED_COLLECTIONS) await (await this.#collection(name)).deleteMany({}, sessionOptions(session));
4426
+ });
4427
+ }
4428
+ async createNode(input) {
4429
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4430
+ return this.#connector.withTransaction(async (session) => {
4431
+ const existing = await this.#getNodeByName(input.name, scope, session);
4432
+ if (existing) {
4433
+ const terminal = await this.#resolveTerminalNode(existing.id, session);
4434
+ if (!(0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) throw new Error(`Merged knowledge node is not visible from scope: ${input.name}`);
4435
+ return terminal;
4436
+ }
4437
+ const now = /* @__PURE__ */ new Date();
4438
+ const node = {
4439
+ id: input.id ?? crypto.randomUUID(),
4440
+ type: "node",
4441
+ name: input.name.trim(),
4442
+ kind: input.kind,
4443
+ content: input.content,
4444
+ scope,
4445
+ version: 1,
4446
+ createdAt: now,
4447
+ updatedAt: now
4448
+ };
4449
+ try {
4450
+ await (await this.#nodes()).insertOne({
4451
+ ...node,
4452
+ canonicalName: canonicalName(node.name),
4453
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
4454
+ mergedInto: null
4455
+ }, sessionOptions(session));
4456
+ } catch (error) {
4457
+ if (error.code !== 11e3) throw error;
4458
+ const concurrent = await this.#getNodeByName(input.name, scope, session);
4459
+ if (!concurrent) throw error;
4460
+ return await this.#resolveTerminalNode(concurrent.id, session);
4461
+ }
4462
+ await this.#replaceMentions("node", node.id, node.content ?? "", input.resolutionScope ?? scope, scope, session);
4463
+ await this.#activity("node-created", "node", node.id, scope, void 0, session);
4464
+ await this.#outbox("node", node.id, "upsert", 1, scope, session);
4465
+ return node;
4466
+ });
4467
+ }
4468
+ async getNode(id) {
4469
+ return this.#getNode(id);
4470
+ }
4471
+ async getNodeByName(input) {
4472
+ return this.#getNodeByName(input.name, (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
4473
+ }
4474
+ async resolveNode(input) {
4475
+ return this.#resolveNode(input.name, (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope));
4476
+ }
4477
+ async listNodes(input) {
4478
+ const filter = {
4479
+ type: "node",
4480
+ mergedInto: null,
4481
+ scopeKey: { $in: visibleScopeKeys((0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope)) },
4482
+ ...input.namePrefix ? { canonicalName: { $regex: `^${this.#escapeRegex(canonicalName(input.namePrefix))}` } } : {},
4483
+ ...input.kind ? { kind: input.kind } : {},
4484
+ ...input.hasContent === void 0 ? {} : input.hasContent ? { content: {
4485
+ $exists: true,
4486
+ $nin: [null, ""]
4487
+ } } : { $or: [
4488
+ { content: { $exists: false } },
4489
+ { content: null },
4490
+ { content: "" }
4491
+ ] },
4492
+ ...input.cursor ? recordCursorFilter(input.cursor, {
4493
+ namePrefix: input.namePrefix,
4494
+ kind: input.kind,
4495
+ hasContent: input.hasContent
4496
+ }) : {}
4497
+ };
4498
+ return (await (await this.#nodes()).find(filter).sort({
4499
+ updatedAt: -1,
4500
+ name: 1,
4501
+ id: 1
4502
+ }).limit(input.limit ?? 100).toArray()).map(nodeFromDocument);
4503
+ }
4504
+ async updateNode(input) {
4505
+ return this.#connector.withTransaction(async (session) => {
4506
+ const existing = await this.#getNode(input.id, session);
4507
+ if (!existing) throw new _mastra_core_storage.KnowledgeNotFoundError("node", input.id);
4508
+ if (existing.mergedInto) throw new Error(`Cannot update merged knowledge node: ${input.id}`);
4509
+ const scope = input.scope ? (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope) : existing.scope;
4510
+ const name = input.name?.trim() ?? existing.name;
4511
+ const content = input.content ?? existing.content;
4512
+ const now = /* @__PURE__ */ new Date();
4513
+ const result = await (await this.#nodes()).findOneAndUpdate({
4514
+ id: input.id,
4515
+ type: "node",
4516
+ version: input.version
4517
+ }, {
4518
+ $set: {
4519
+ name,
4520
+ canonicalName: canonicalName(name),
4521
+ kind: input.kind ?? existing.kind,
4522
+ content: content ?? null,
4523
+ scope,
4524
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
4525
+ updatedAt: now
4526
+ },
4527
+ $inc: { version: 1 }
4528
+ }, {
4529
+ ...sessionOptions(session),
4530
+ returnDocument: "after"
4531
+ });
4532
+ if (!result) throw new _mastra_core_storage.KnowledgeConflictError(input.id);
4533
+ if (input.content !== void 0 || input.name !== void 0 || input.scope !== void 0) await this.#replaceMentions("node", input.id, content ?? "", input.resolutionScope ?? scope, scope, session);
4534
+ if ((0, _mastra_core_storage.knowledgeScopeKey)(scope) !== (0, _mastra_core_storage.knowledgeScopeKey)(existing.scope)) {
4535
+ await this.#outbox("node", input.id, "delete", (0, _mastra_core_storage.createKnowledgeUlid)(), existing.scope, session);
4536
+ const records = await (await this.#knowledge()).find({ node: input.id }, sessionOptions(session)).toArray();
4537
+ for (const record of records) {
4538
+ await this.#outbox("record", record.id, "delete", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope, session);
4539
+ if (!record.deletedAt) await this.#outbox("record", record.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope, session);
4540
+ }
4541
+ }
4542
+ await this.#activity("node-updated", "node", input.id, scope, void 0, session);
4543
+ await this.#outbox("node", input.id, "upsert", Number(result.version), scope, session);
4544
+ return nodeFromDocument(result);
4545
+ });
4546
+ }
4547
+ async mergeNodes(input) {
4548
+ if (input.sourceId === input.targetId) throw new Error("Cannot merge a knowledge node into itself");
4549
+ return this.#connector.withTransaction(async (session) => {
4550
+ const source = await this.#getNode(input.sourceId, session);
4551
+ if (!source) throw new _mastra_core_storage.KnowledgeNotFoundError("node", input.sourceId);
4552
+ const target = await this.#resolveTerminalNode(input.targetId, session);
4553
+ if (!target) throw new _mastra_core_storage.KnowledgeNotFoundError("node", input.targetId);
4554
+ if (target.id === source.id) throw new Error("Cannot create a knowledge merge cycle");
4555
+ if (!(0, _mastra_core_storage.isKnowledgeScopeVisible)(target.scope, source.scope)) throw new Error("Cannot merge a knowledge node into a target that is narrower than its source scope");
4556
+ const mentions = await this.#mentions();
4557
+ const affected = await mentions.find({ recordId: source.id }, sessionOptions(session)).toArray();
4558
+ const movedFacts = await (await this.#knowledge()).find({ node: source.id }, sessionOptions(session)).toArray();
4559
+ if ((await (await this.#nodes()).updateOne({
4560
+ id: source.id,
4561
+ type: "node",
4562
+ version: input.sourceVersion,
4563
+ mergedInto: null
4564
+ }, {
4565
+ $set: {
4566
+ mergedInto: target.id,
4567
+ updatedAt: /* @__PURE__ */ new Date()
4568
+ },
4569
+ $inc: { version: 1 }
4570
+ }, sessionOptions(session))).modifiedCount === 0) throw new _mastra_core_storage.KnowledgeConflictError(source.id);
4571
+ await (await this.#knowledge()).updateMany({ node: source.id }, { $set: { node: target.id } }, sessionOptions(session));
4572
+ for (const mention of affected) if (await mentions.findOne({
4573
+ sourceType: mention.sourceType,
4574
+ sourceId: mention.sourceId,
4575
+ recordId: target.id
4576
+ }, sessionOptions(session))) await mentions.deleteOne({ _id: mention._id }, sessionOptions(session));
4577
+ else await mentions.updateOne({ _id: mention._id }, { $set: { recordId: target.id } }, sessionOptions(session));
4578
+ for (const record of movedFacts) if (!record.deletedAt) await this.#outbox("record", record.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope, session);
4579
+ for (const mention of affected) {
4580
+ const scope = mention.sourceType === "record" ? (await (await this.#knowledge()).findOne({ id: mention.sourceId }, sessionOptions(session)))?.scope : (await (await this.#nodes()).findOne({
4581
+ id: mention.sourceId,
4582
+ type: "node"
4583
+ }, sessionOptions(session)))?.scope;
4584
+ if (scope) await this.#outbox(mention.sourceType, mention.sourceId, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), scope, session);
4585
+ }
4586
+ await this.#activity("node-merged", "node", source.id, source.scope, void 0, session);
4587
+ await this.#outbox("node", source.id, "delete", input.sourceVersion + 1, source.scope, session);
4588
+ await this.#outbox("node", target.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), target.scope, session);
4589
+ return target;
4590
+ });
4591
+ }
4592
+ async appendKnowledge(input) {
4593
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4594
+ const defaultScope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.defaultScope);
4595
+ (0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, input.maxScope);
4596
+ return this.#connector.withTransaction(async (session) => {
4597
+ const parent = await this.#resolveTerminalNode(nodeReferenceId(input.node), session);
4598
+ if (!parent) throw new _mastra_core_storage.KnowledgeNotFoundError("node", nodeReferenceId(input.node));
4599
+ const id = input.id ?? (0, _mastra_core_storage.createKnowledgeUlid)();
4600
+ const existing = await (await this.#knowledge()).findOne({ id }, sessionOptions(session));
4601
+ if (existing) return recordFromDocument(existing);
4602
+ const record = {
4603
+ id,
4604
+ node: parent.id,
4605
+ text: input.text,
4606
+ scope,
4607
+ sourceThreadId: input.sourceThreadId,
4608
+ capturedAt: /* @__PURE__ */ new Date(),
4609
+ when: input.when,
4610
+ maxScope: input.maxScope,
4611
+ metadata: input.metadata
4612
+ };
4613
+ await (await this.#knowledge()).insertOne({
4614
+ ...record,
4615
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
4616
+ when: record.when ?? null,
4617
+ maxScope: record.maxScope ?? null,
4618
+ deletedAt: null,
4619
+ deletedBy: null
4620
+ }, sessionOptions(session));
4621
+ await this.#replaceMentions("record", id, record.text, input.resolutionScope, defaultScope, session);
4622
+ await this.#activity("record-created", "record", id, scope, input.sourceThreadId, session);
4623
+ await this.#outbox("record", id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), scope, session);
4624
+ return record;
4625
+ });
4626
+ }
4627
+ async getKnowledge(input) {
4628
+ const row = await (await this.#knowledge()).findOne({
4629
+ id: input.id,
4630
+ ...input.includeDeleted ? {} : { deletedAt: null }
4631
+ });
4632
+ return row ? recordFromDocument(row) : null;
4633
+ }
4634
+ async listKnowledgeAbout(input) {
4635
+ return this.#queryKnowledge(input, "about");
4636
+ }
4637
+ async listKnowledgeMentioning(input) {
4638
+ return this.#queryKnowledge(input, "mentioning");
4639
+ }
4640
+ async listKnowledgeRelatedTo(input) {
4641
+ return this.#queryKnowledge(input, "related");
4642
+ }
4643
+ async knowledgeBySource(input) {
4644
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4645
+ const limit = input.limit ?? 100;
4646
+ const rows = await (await this.#knowledge()).find({
4647
+ sourceThreadId: input.sourceThreadId,
4648
+ scopeKey: { $in: visibleScopeKeys(scope) },
4649
+ ...input.includeDeleted ? {} : { deletedAt: null },
4650
+ ...input.after ? { id: { $gt: input.after } } : {}
4651
+ }).sort({ id: 1 }).limit(limit + 1).toArray();
4652
+ return {
4653
+ records: rows.slice(0, limit).map(recordFromDocument),
4654
+ nextCursor: rows.length > limit ? rows[limit - 1]?.id : void 0
4655
+ };
4656
+ }
4657
+ async removeKnowledge(input) {
4658
+ return this.#connector.withTransaction(async (session) => {
4659
+ const record = await this.#getKnowledge(input.id, true, session);
4660
+ if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
4661
+ if (record.deletedAt) return record;
4662
+ const deletedAt = /* @__PURE__ */ new Date();
4663
+ await (await this.#knowledge()).updateOne({
4664
+ id: input.id,
4665
+ deletedAt: null
4666
+ }, { $set: {
4667
+ deletedAt,
4668
+ deletedBy: input.deletedBy
4669
+ } }, sessionOptions(session));
4670
+ await this.#activity("record-deleted", "record", input.id, record.scope, record.sourceThreadId, session);
4671
+ await this.#outbox("record", input.id, "delete", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope, session);
4672
+ return {
4673
+ ...record,
4674
+ deletedAt,
4675
+ deletedBy: input.deletedBy
4676
+ };
4677
+ });
4678
+ }
4679
+ async restoreKnowledge(input) {
4680
+ return this.#connector.withTransaction(async (session) => {
4681
+ const record = await this.#getKnowledge(input.id, true, session);
4682
+ if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
4683
+ if (!record.deletedAt) return record;
4684
+ await (await this.#knowledge()).updateOne({ id: input.id }, { $set: {
4685
+ deletedAt: null,
4686
+ deletedBy: null
4687
+ } }, sessionOptions(session));
4688
+ await this.#activity("record-restored", "record", input.id, record.scope, record.sourceThreadId, session);
4689
+ await this.#outbox("record", input.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope, session);
4690
+ return {
4691
+ ...record,
4692
+ deletedAt: void 0,
4693
+ deletedBy: void 0
4694
+ };
4695
+ });
4696
+ }
4697
+ async rescopeKnowledge(input) {
4698
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4699
+ return this.#connector.withTransaction(async (session) => {
4700
+ const record = await this.#getKnowledge(input.id, true, session);
4701
+ if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
4702
+ (0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(scope, record.maxScope);
4703
+ await (await this.#knowledge()).updateOne({ id: input.id }, { $set: {
4704
+ scope,
4705
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope)
4706
+ } }, sessionOptions(session));
4707
+ await this.#activity("record-rescoped", "record", input.id, scope, record.sourceThreadId, session);
4708
+ await this.#outbox("record", input.id, "delete", (0, _mastra_core_storage.createKnowledgeUlid)(), record.scope, session);
4709
+ if (!record.deletedAt) await this.#outbox("record", input.id, "upsert", (0, _mastra_core_storage.createKnowledgeUlid)(), scope, session);
4710
+ return {
4711
+ ...record,
4712
+ scope
4713
+ };
4714
+ });
4715
+ }
4716
+ async raiseKnowledgeCeiling(input) {
4717
+ const record = await this.#getKnowledge(input.id, true);
4718
+ if (!record) throw new _mastra_core_storage.KnowledgeNotFoundError("record", input.id);
4719
+ (0, _mastra_core_storage.assertKnowledgeScopeWithinCeiling)(record.scope, input.maxScope);
4720
+ (0, _mastra_core_storage.assertKnowledgeCeilingRaised)(record.maxScope, input.maxScope);
4721
+ await (await this.#knowledge()).updateOne({ id: input.id }, { $set: { maxScope: input.maxScope ?? null } });
4722
+ return {
4723
+ ...record,
4724
+ maxScope: input.maxScope
4725
+ };
4726
+ }
4727
+ async search(input) {
4728
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4729
+ const query = input.query.trim();
4730
+ if (!query) return [];
4731
+ const regex = new RegExp(this.#escapeRegex(query), "i");
4732
+ const limit = input.limit ?? 20;
4733
+ const results = (await (await this.#nodes()).find({
4734
+ mergedInto: null,
4735
+ scopeKey: { $in: visibleScopeKeys(scope) },
4736
+ $or: [
4737
+ { name: regex },
4738
+ { kind: regex },
4739
+ { content: regex }
4740
+ ]
4741
+ }).sort({ updatedAt: -1 }).limit(limit).toArray()).map((row) => ({
4742
+ type: "node",
4743
+ id: row.id,
4744
+ recordId: row.id,
4745
+ name: row.name,
4746
+ text: row.content ? `${row.name}\n${row.content}` : row.name,
4747
+ scope: cloneScope(row.scope)
4748
+ }));
4749
+ if (results.length < limit) {
4750
+ const records = await (await this.#knowledge()).find({
4751
+ deletedAt: null,
4752
+ scopeKey: { $in: visibleScopeKeys(scope) },
4753
+ text: regex
4754
+ }).sort({ id: -1 }).limit(limit - results.length).toArray();
4755
+ for (const record of records) {
4756
+ const parent = await this.#resolveTerminalNode(record.node);
4757
+ const parentVisible = parent && (0, _mastra_core_storage.isKnowledgeScopeVisible)(parent.scope, scope);
4758
+ results.push({
4759
+ type: "record",
4760
+ id: record.id,
4761
+ recordId: record.node,
4762
+ name: parentVisible ? parent.name : "(private node)",
4763
+ text: record.text,
4764
+ scope: cloneScope(record.scope)
4765
+ });
4766
+ }
4767
+ }
4768
+ return results.slice(0, limit);
4769
+ }
4770
+ async getCurationCursor(input) {
4771
+ const row = await (await this.#cursors()).findOne(input);
4772
+ return row ? {
4773
+ sourceThreadId: row.sourceThreadId,
4774
+ agent: row.agent,
4775
+ lastKnowledgeId: row.lastKnowledgeId,
4776
+ updatedAt: new Date(row.updatedAt)
4777
+ } : null;
4778
+ }
4779
+ async advanceCurationCursor(input) {
4780
+ const row = await (await this.#cursors()).findOneAndUpdate({
4781
+ sourceThreadId: input.sourceThreadId,
4782
+ agent: input.agent
4783
+ }, {
4784
+ $max: { lastKnowledgeId: input.lastKnowledgeId },
4785
+ $set: { updatedAt: /* @__PURE__ */ new Date() },
4786
+ $setOnInsert: {
4787
+ sourceThreadId: input.sourceThreadId,
4788
+ agent: input.agent
4789
+ }
4790
+ }, {
4791
+ upsert: true,
4792
+ returnDocument: "after"
4793
+ });
4794
+ return {
4795
+ sourceThreadId: row.sourceThreadId,
4796
+ agent: row.agent,
4797
+ lastKnowledgeId: row.lastKnowledgeId,
4798
+ updatedAt: new Date(row.updatedAt)
4799
+ };
4800
+ }
4801
+ async listActivity(input) {
4802
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4803
+ return (await (await this.#activityCollection()).find({
4804
+ scopeKey: { $in: visibleScopeKeys(scope) },
4805
+ ...input.after ? { id: { $lt: input.after } } : {}
4806
+ }).sort({ id: -1 }).limit(input.limit ?? 100).toArray()).map((row) => ({
4807
+ id: row.id,
4808
+ action: row.action,
4809
+ recordType: row.recordType,
4810
+ recordId: row.recordId,
4811
+ scope: cloneScope(row.scope),
4812
+ sourceThreadId: row.sourceThreadId ?? void 0,
4813
+ createdAt: new Date(row.createdAt)
4814
+ }));
4815
+ }
4816
+ async listSemanticOutbox(input = {}) {
4817
+ const filter = {
4818
+ ...input.status ? { status: input.status } : {},
4819
+ ...input.scope ? { scopeKey: { $in: visibleScopeKeys(input.scope) } } : {}
4820
+ };
4821
+ return (await (await this.#outboxCollection()).find(filter).sort({
4822
+ createdAt: 1,
4823
+ id: 1
4824
+ }).limit(input.limit ?? 100).toArray()).map(outboxFromDocument);
4825
+ }
4826
+ async claimSemanticOutbox(input) {
4827
+ return this.#connector.withTransaction(async (session) => {
4828
+ const collection = await this.#outboxCollection();
4829
+ const now = input.now ?? /* @__PURE__ */ new Date();
4830
+ const staleBefore = new Date(now.getTime() - (input.claimTimeoutMs ?? 6e4));
4831
+ const filter = {
4832
+ $or: [{
4833
+ status: "pending",
4834
+ availableAt: { $lte: now }
4835
+ }, {
4836
+ status: "processing",
4837
+ claimedAt: { $lte: staleBefore }
4838
+ }],
4839
+ ...input.scope ? { scopeKey: { $in: visibleScopeKeys(input.scope) } } : {}
4840
+ };
4841
+ const limit = input.limit ?? 100;
4842
+ const candidates = await collection.find(filter, sessionOptions(session)).sort({
4843
+ createdAt: 1,
4844
+ id: 1
4845
+ }).limit(Math.max(limit * 10, 100)).toArray();
4846
+ const claimed = [];
4847
+ for (const candidate of candidates) {
4848
+ if (claimed.length >= limit) break;
4849
+ if (await collection.findOne({
4850
+ documentId: candidate.documentId,
4851
+ status: { $ne: "completed" },
4852
+ $or: [{ createdAt: { $lt: candidate.createdAt } }, {
4853
+ createdAt: candidate.createdAt,
4854
+ id: { $lt: candidate.id }
4855
+ }]
4856
+ }, sessionOptions(session))) continue;
4857
+ const result = await collection.findOneAndUpdate({
4858
+ id: candidate.id,
4859
+ $or: [{
4860
+ status: "pending",
4861
+ availableAt: { $lte: now }
4862
+ }, {
4863
+ status: "processing",
4864
+ claimedAt: { $lte: staleBefore }
4865
+ }]
4866
+ }, {
4867
+ $set: {
4868
+ status: "processing",
4869
+ claimedAt: now,
4870
+ claimedBy: input.workerId
4871
+ },
4872
+ $inc: { attempts: 1 }
4873
+ }, {
4874
+ ...sessionOptions(session),
4875
+ returnDocument: "after"
4876
+ });
4877
+ if (result) claimed.push(result);
4878
+ }
4879
+ return claimed.map(outboxFromDocument);
4880
+ });
4881
+ }
4882
+ async completeSemanticOutbox(input) {
4883
+ if (!input.ids.length) return;
4884
+ await (await this.#outboxCollection()).updateMany({
4885
+ id: { $in: input.ids },
4886
+ status: "processing",
4887
+ claimedBy: input.workerId
4888
+ }, { $set: {
4889
+ status: "completed",
4890
+ completedAt: /* @__PURE__ */ new Date(),
4891
+ claimedAt: null,
4892
+ claimedBy: null
4893
+ } });
4894
+ }
4895
+ async releaseSemanticOutbox(input) {
4896
+ if (!input.ids.length) return;
4897
+ await (await this.#outboxCollection()).updateMany({
4898
+ id: { $in: input.ids },
4899
+ status: "processing",
4900
+ claimedBy: input.workerId
4901
+ }, { $set: {
4902
+ status: "pending",
4903
+ availableAt: input.retryAt ?? /* @__PURE__ */ new Date(),
4904
+ claimedAt: null,
4905
+ claimedBy: null
4906
+ } });
4907
+ }
4908
+ async #collection(name) {
4909
+ return this.#connector.getCollection(name);
4910
+ }
4911
+ #nodes() {
4912
+ return this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_NODES);
4913
+ }
4914
+ #knowledge() {
4915
+ return this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_RECORDS);
4916
+ }
4917
+ #mentions() {
4918
+ return this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_MENTIONS);
4919
+ }
4920
+ #cursors() {
4921
+ return this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_CURSORS);
4922
+ }
4923
+ #activityCollection() {
4924
+ return this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_ACTIVITY);
4925
+ }
4926
+ #outboxCollection() {
4927
+ return this.#collection(_mastra_core_storage.TABLE_KNOWLEDGE_SEMANTIC_OUTBOX);
4928
+ }
4929
+ async #getNode(id, session) {
4930
+ const row = await (await this.#nodes()).findOne({
4931
+ id,
4932
+ type: "node"
4933
+ }, sessionOptions(session));
4934
+ return row ? nodeFromDocument(row) : null;
4935
+ }
4936
+ async #getNodeByName(name, scope, session) {
4937
+ const row = await (await this.#nodes()).findOne({
4938
+ type: "node",
4939
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
4940
+ canonicalName: canonicalName(name)
4941
+ }, sessionOptions(session));
4942
+ return row ? nodeFromDocument(row) : null;
4943
+ }
4944
+ async #resolveNode(name, scope, session) {
4945
+ for (let length = scope.length; length > 0; length--) {
4946
+ const node = await this.#getNodeByName(name, scope.slice(0, length), session);
4947
+ if (node) {
4948
+ const terminal = await this.#resolveTerminalNode(node.id, session);
4949
+ if (terminal && (0, _mastra_core_storage.isKnowledgeScopeVisible)(terminal.scope, scope)) return terminal;
4950
+ }
4951
+ }
4952
+ return null;
4953
+ }
4954
+ async #resolveTerminalNode(id, session) {
4955
+ let node = await this.#getNode(id, session);
4956
+ const seen = /* @__PURE__ */ new Set();
4957
+ while (node?.mergedInto) {
4958
+ if (seen.has(node.id)) throw new Error(`Knowledge merge cycle detected at ${node.id}`);
4959
+ seen.add(node.id);
4960
+ node = await this.#getNode(node.mergedInto, session);
4961
+ }
4962
+ return node;
4963
+ }
4964
+ async #getPageByExactName(name, scope, session) {
4965
+ const row = await (await this.#nodes()).findOne({
4966
+ type: "page",
4967
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
4968
+ canonicalName: canonicalName(name)
4969
+ }, sessionOptions(session));
4970
+ return row ? nodeFromDocument(row) : null;
4971
+ }
4972
+ async #getKnowledge(id, includeDeleted, session) {
4973
+ const row = await (await this.#knowledge()).findOne({
4974
+ id,
4975
+ ...includeDeleted ? {} : { deletedAt: null }
4976
+ }, sessionOptions(session));
4977
+ return row ? recordFromDocument(row) : null;
4978
+ }
4979
+ async #queryKnowledge(input, relationship) {
4980
+ const scope = (0, _mastra_core_storage.canonicalizeKnowledgeScope)(input.scope);
4981
+ const node = await this.#resolveTerminalNode(nodeReferenceId(input.node));
4982
+ if (!node) return { records: [] };
4983
+ const nodeIds = [node.id];
4984
+ if (relationship !== "about") {
4985
+ const mentions = await (await this.#mentions()).find({
4986
+ recordId: node.id,
4987
+ sourceType: "record"
4988
+ }).toArray();
4989
+ nodeIds.push(...mentions.map((row) => row.sourceId));
4990
+ }
4991
+ const limit = input.limit ?? 100;
4992
+ const filter = relationship === "about" ? { node: node.id } : relationship === "mentioning" ? { id: { $in: nodeIds.slice(1) } } : { $or: [{ node: node.id }, { id: { $in: nodeIds.slice(1) } }] };
4993
+ Object.assign(filter, {
4994
+ scopeKey: { $in: visibleScopeKeys(scope) },
4995
+ ...input.includeDeleted ? {} : { deletedAt: null },
4996
+ ...input.after ? { id: { $lt: input.after } } : {}
4997
+ });
4998
+ const rows = await (await this.#knowledge()).find(filter).sort({ id: -1 }).limit(limit + 1).toArray();
4999
+ return {
5000
+ records: rows.slice(0, limit).map(recordFromDocument),
5001
+ nextCursor: rows.length > limit ? rows[limit - 1]?.id : void 0
5002
+ };
5003
+ }
5004
+ async #replaceMentions(sourceType, sourceId, text, resolutionScope, defaultScope, session) {
5005
+ const mentions = await this.#mentions();
5006
+ await mentions.deleteMany({
5007
+ sourceType,
5008
+ sourceId
5009
+ }, sessionOptions(session));
5010
+ for (const name of (0, _mastra_core_storage.parseKnowledgeWikilinks)(text)) {
5011
+ let node = await this.#resolveNode(name, resolutionScope, session);
5012
+ if (!node) {
5013
+ const existing = await this.#getNodeByName(name, defaultScope, session);
5014
+ node = existing ? await this.#resolveTerminalNode(existing.id, session) : null;
5015
+ }
5016
+ if (!node) {
5017
+ const now = /* @__PURE__ */ new Date();
5018
+ node = {
5019
+ id: crypto.randomUUID(),
5020
+ type: "node",
5021
+ name,
5022
+ kind: "node",
5023
+ scope: defaultScope,
5024
+ version: 1,
5025
+ createdAt: now,
5026
+ updatedAt: now
5027
+ };
5028
+ try {
5029
+ await (await this.#nodes()).insertOne({
5030
+ ...node,
5031
+ canonicalName: canonicalName(name),
5032
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(defaultScope),
5033
+ mergedInto: null
5034
+ }, sessionOptions(session));
5035
+ await this.#activity("node-created", "node", node.id, defaultScope, void 0, session);
5036
+ await this.#outbox("node", node.id, "upsert", 1, defaultScope, session);
5037
+ } catch (error) {
5038
+ if (error.code !== 11e3) throw error;
5039
+ node = await this.#getNodeByName(name, defaultScope, session);
5040
+ if (!node) throw error;
5041
+ }
5042
+ }
5043
+ await mentions.updateOne({
5044
+ sourceType,
5045
+ sourceId,
5046
+ recordId: node.id
5047
+ }, { $setOnInsert: {
5048
+ sourceType,
5049
+ sourceId,
5050
+ recordId: node.id
5051
+ } }, {
5052
+ ...sessionOptions(session),
5053
+ upsert: true
5054
+ });
5055
+ }
5056
+ }
5057
+ async #activity(action, recordType, recordId, scope, sourceThreadId, session) {
5058
+ await (await this.#activityCollection()).insertOne({
5059
+ id: (0, _mastra_core_storage.createKnowledgeUlid)(),
5060
+ action,
5061
+ recordType,
5062
+ recordId,
5063
+ scope,
5064
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
5065
+ sourceThreadId: sourceThreadId ?? null,
5066
+ createdAt: /* @__PURE__ */ new Date()
5067
+ }, sessionOptions(session));
5068
+ }
5069
+ async #outbox(documentType, id, operation, version, scope, session) {
5070
+ const documentId = (0, _mastra_core_storage.knowledgeSemanticDocumentId)(documentType, id);
5071
+ const idempotencyKey = (0, _mastra_core_storage.knowledgeSemanticIdempotencyKey)(documentId, operation, version);
5072
+ const now = /* @__PURE__ */ new Date();
5073
+ try {
5074
+ await (await this.#outboxCollection()).insertOne({
5075
+ id: (0, _mastra_core_storage.createKnowledgeUlid)(),
5076
+ idempotencyKey,
5077
+ documentId,
5078
+ documentType,
5079
+ operation,
5080
+ scope,
5081
+ scopeKey: (0, _mastra_core_storage.knowledgeScopeKey)(scope),
5082
+ status: "pending",
5083
+ attempts: 0,
5084
+ availableAt: now,
5085
+ claimedAt: null,
5086
+ claimedBy: null,
5087
+ createdAt: now,
5088
+ completedAt: null
5089
+ }, sessionOptions(session));
5090
+ } catch (error) {
5091
+ if (error.code !== 11e3) throw error;
5092
+ }
5093
+ }
5094
+ #escapeRegex(value) {
5095
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5096
+ }
5097
+ };
5098
+ //#endregion
4295
5099
  //#region src/storage/domains/mcp-clients/index.ts
4296
5100
  /**
4297
5101
  * Snapshot config fields that live on MCP client version documents.
@@ -10976,6 +11780,7 @@ var MongoDBStore = class extends _mastra_core_storage.MastraCompositeStore {
10976
11780
  indexes: config.indexes
10977
11781
  };
10978
11782
  const memory = new MemoryStorageMongoDB(domainConfig);
11783
+ const knowledge = new KnowledgeMongoDB(domainConfig);
10979
11784
  const notifications = new NotificationsMongoDB(domainConfig);
10980
11785
  const scores = new ScoresStorageMongoDB(domainConfig);
10981
11786
  const workflows = new WorkflowsStorageMongoDB(domainConfig);
@@ -10995,6 +11800,7 @@ var MongoDBStore = class extends _mastra_core_storage.MastraCompositeStore {
10995
11800
  const workflowDefinitions = new MongoDBWorkflowDefinitionsStore(domainConfig);
10996
11801
  this.stores = {
10997
11802
  memory,
11803
+ knowledge,
10998
11804
  notifications,
10999
11805
  scores,
11000
11806
  workflows,
@@ -11132,6 +11938,7 @@ Example Complex Query:
11132
11938
  }`;
11133
11939
  //#endregion
11134
11940
  exports.BackgroundTasksStorageMongoDB = BackgroundTasksStorageMongoDB;
11941
+ exports.KnowledgeMongoDB = KnowledgeMongoDB;
11135
11942
  exports.MONGODB_PROMPT = MONGODB_PROMPT;
11136
11943
  exports.MemoryStorageMongoDB = MemoryStorageMongoDB;
11137
11944
  exports.MongoDBAgentsStorage = MongoDBAgentsStorage;