@mastra/libsql 1.20.0 → 1.21.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.
Files changed (31) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/docs/SKILL.md +6 -9
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/{docs-agents-agent-approval.md → docs-agents-human-in-the-loop.md} +11 -9
  5. package/dist/docs/references/docs-agents-networks.md +3 -3
  6. package/dist/docs/references/docs-deployment-workers.md +253 -7
  7. package/dist/docs/references/docs-memory-memory-processors.md +1 -1
  8. package/dist/docs/references/docs-memory-message-history.md +3 -3
  9. package/dist/docs/references/docs-memory-overview.md +4 -4
  10. package/dist/docs/references/docs-memory-semantic-recall.md +1 -1
  11. package/dist/docs/references/docs-memory-working-memory.md +3 -3
  12. package/dist/docs/references/{docs-storage-overview.md → docs-storage.md} +9 -7
  13. package/dist/docs/references/{docs-editor-overview.md → docs-studio-editor.md} +3 -1
  14. package/dist/docs/references/docs-workflows-snapshots.md +1 -1
  15. package/dist/docs/references/integrations-channels-github.md +1 -1
  16. package/dist/docs/references/{guides-agent-frameworks-ai-sdk.md → reference-ai-sdk-overview.md} +1 -1
  17. package/dist/docs/references/reference-core-mastra-class.md +1 -1
  18. package/dist/docs/references/reference-file-based-agents-memory.md +2 -2
  19. package/dist/docs/references/reference-file-based-agents-storage.md +3 -3
  20. package/dist/docs/references/reference-memory-memory-class.md +1 -0
  21. package/dist/docs/references/reference-storage-retention.md +1 -1
  22. package/dist/index.cjs +854 -13
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.js +855 -15
  25. package/dist/index.js.map +1 -1
  26. package/dist/storage/domains/agents/index.d.ts.map +1 -1
  27. package/dist/storage/domains/knowledge/index.d.ts +81 -0
  28. package/dist/storage/domains/knowledge/index.d.ts.map +1 -0
  29. package/dist/storage/index.d.ts +2 -1
  30. package/dist/storage/index.d.ts.map +1 -1
  31. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createClient } from "@libsql/client";
2
2
  import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
3
- import { AGENTS_SCHEMA, AGENT_VERSIONS_SCHEMA, AgentsStorage, BackgroundTasksStorage, BlobStore, ChannelsStorage, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, DatasetsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, ExperimentsStorage, FAVORITES_SCHEMA, FactoryStorage, FavoritesStorage, HarnessStorage, MCPClientsStorage, MCPServersStorage, MCP_CLIENTS_SCHEMA, MCP_CLIENT_VERSIONS_SCHEMA, MCP_SERVERS_SCHEMA, MCP_SERVER_VERSIONS_SCHEMA, MastraCompositeStore, MemoryStorage, NotificationsStorage, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, ObservabilityStorage, PROMPT_BLOCKS_SCHEMA, PROMPT_BLOCK_VERSIONS_SCHEMA, PromptBlocksStorage, SCORERS_SCHEMA, SCORER_DEFINITIONS_SCHEMA, SCORER_DEFINITION_VERSIONS_SCHEMA, SKILLS_SCHEMA, SKILL_BLOBS_SCHEMA, SKILL_VERSIONS_SCHEMA, SPAN_SCHEMA, SchedulesStorage, ScorerDefinitionsStorage, ScoresStorage, SkillsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_BACKGROUND_TASKS, TABLE_CHANNEL_CONFIG, TABLE_CHANNEL_INSTALLATIONS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_HARNESS_SESSIONS, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_THREAD_STATE, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_WORKFLOW_DEFINITIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, THREAD_STATE_SCHEMA, TOOL_PROVIDER_CONNECTIONS_SCHEMA, ThreadStateStorage, ToolProviderConnectionsStorage, TraceStatus, UniqueViolationError, WORKSPACES_SCHEMA, WORKSPACE_VERSIONS_SCHEMA, WorkflowDefinitionsStorage, WorkflowsStorage, WorkspacesStorage, calculatePagination, createStorageErrorId, createVectorErrorId, ensureDate, getSqlType, hasErrorCode, listTracesArgsSchema, mergeWorkflowStepResult, normalizePerPage, normalizeScheduleTarget, parseDuration, safelyParseJSON, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
3
+ import { AGENTS_SCHEMA, AGENT_VERSIONS_SCHEMA, AgentsStorage, BackgroundTasksStorage, BlobStore, ChannelsStorage, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, DatasetsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, ExperimentsStorage, FAVORITES_SCHEMA, FactoryStorage, FavoritesStorage, HarnessStorage, KNOWLEDGE_ACTIVITY_SCHEMA, KNOWLEDGE_CURSORS_SCHEMA, KNOWLEDGE_MENTIONS_SCHEMA, KNOWLEDGE_NODES_SCHEMA, KNOWLEDGE_RECORDS_SCHEMA, KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA, KnowledgeConflictError, KnowledgeNotFoundError, KnowledgeStorage, MCPClientsStorage, MCPServersStorage, MCP_CLIENTS_SCHEMA, MCP_CLIENT_VERSIONS_SCHEMA, MCP_SERVERS_SCHEMA, MCP_SERVER_VERSIONS_SCHEMA, MastraCompositeStore, MemoryStorage, NotificationsStorage, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, ObservabilityStorage, PROMPT_BLOCKS_SCHEMA, PROMPT_BLOCK_VERSIONS_SCHEMA, PromptBlocksStorage, SCORERS_SCHEMA, SCORER_DEFINITIONS_SCHEMA, SCORER_DEFINITION_VERSIONS_SCHEMA, SKILLS_SCHEMA, SKILL_BLOBS_SCHEMA, SKILL_VERSIONS_SCHEMA, SPAN_SCHEMA, SchedulesStorage, ScorerDefinitionsStorage, ScoresStorage, SkillsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, TABLE_BACKGROUND_TASKS, TABLE_CHANNEL_CONFIG, TABLE_CHANNEL_INSTALLATIONS, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, TABLE_FAVORITES, TABLE_HARNESS_SESSIONS, TABLE_KNOWLEDGE_ACTIVITY, TABLE_KNOWLEDGE_CURSORS, TABLE_KNOWLEDGE_MENTIONS, TABLE_KNOWLEDGE_NODES, TABLE_KNOWLEDGE_RECORDS, TABLE_KNOWLEDGE_SEMANTIC_OUTBOX, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, TABLE_MESSAGES, TABLE_NOTIFICATIONS, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, TABLE_RESOURCES, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEMAS, TABLE_SCORERS, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, TABLE_SKILLS, TABLE_SKILL_BLOBS, TABLE_SKILL_VERSIONS, TABLE_SPANS, TABLE_THREADS, TABLE_THREAD_STATE, TABLE_TOOL_PROVIDER_CONNECTIONS, TABLE_WORKFLOW_DEFINITIONS, TABLE_WORKFLOW_SNAPSHOT, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, THREAD_STATE_SCHEMA, TOOL_PROVIDER_CONNECTIONS_SCHEMA, ThreadStateStorage, ToolProviderConnectionsStorage, TraceStatus, UniqueViolationError, WORKSPACES_SCHEMA, WORKSPACE_VERSIONS_SCHEMA, WorkflowDefinitionsStorage, WorkflowsStorage, WorkspacesStorage, assertKnowledgeCeilingRaised, assertKnowledgeScopeWithinCeiling, calculatePagination, canonicalizeKnowledgeScope, createKnowledgeUlid, createStorageErrorId, createVectorErrorId, ensureDate, getSqlType, hasErrorCode, isKnowledgeScopeVisible, knowledgeScopeKey, knowledgeSemanticDocumentId, knowledgeSemanticIdempotencyKey, listTracesArgsSchema, mergeWorkflowStepResult, normalizePerPage, normalizeScheduleTarget, parseDuration, parseKnowledgeNodeCursor, parseKnowledgeWikilinks, safelyParseJSON, toTraceSpans, transformScoreRow, validateStorageMetadataFilter } from "@mastra/core/storage";
4
4
  import { parseFieldKey, parseSqlIdentifier } from "@mastra/core/utils";
5
5
  import { MastraVector, validateTopK, validateUpsertInput } from "@mastra/core/vector";
6
6
  import { BaseFilterTranslator } from "@mastra/core/vector/filter";
@@ -268,7 +268,7 @@ const FILTER_OPERATORS = {
268
268
  transformValue: () => {
269
269
  if (Array.isArray(value)) return [JSON.stringify(value)];
270
270
  if (typeof value === "object" && value !== null) return [JSON.stringify(value)];
271
- if (typeof value === "string") return [escapeLikePattern(value)];
271
+ if (typeof value === "string") return [escapeLikePattern$1(value)];
272
272
  return [value];
273
273
  }
274
274
  };
@@ -285,7 +285,7 @@ const parseJsonPathKey = (key) => {
285
285
  const getJsonPath = (key) => {
286
286
  return `'$.${parseJsonPathKey(key)}'`;
287
287
  };
288
- function escapeLikePattern(str) {
288
+ function escapeLikePattern$1(str) {
289
289
  return str.replace(/([%_\\])/g, "\\$1");
290
290
  }
291
291
  function buildFilterQuery(filter) {
@@ -2020,6 +2020,7 @@ var AgentsLibSQL = class extends AgentsStorage {
2020
2020
  "workspace",
2021
2021
  "skills",
2022
2022
  "skillsFormat",
2023
+ "durable",
2023
2024
  "browser",
2024
2025
  "toolProviders"
2025
2026
  ]
@@ -2455,6 +2456,7 @@ var AgentsLibSQL = class extends AgentsStorage {
2455
2456
  workspace: input.workspace ?? null,
2456
2457
  skills: input.skills ?? null,
2457
2458
  skillsFormat: input.skillsFormat ?? null,
2459
+ durable: input.durable ?? null,
2458
2460
  browser: input.browser ?? null,
2459
2461
  changedFields: input.changedFields ?? null,
2460
2462
  changeMessage: input.changeMessage ?? null,
@@ -2690,6 +2692,7 @@ var AgentsLibSQL = class extends AgentsStorage {
2690
2692
  workspace: this.parseJson(row.workspace, "workspace"),
2691
2693
  skills: this.parseJson(row.skills, "skills"),
2692
2694
  skillsFormat: row.skillsFormat,
2695
+ durable: this.parseJson(row.durable, "durable"),
2693
2696
  browser: this.parseJson(row.browser, "browser"),
2694
2697
  changedFields: this.parseJson(row.changedFields, "changedFields"),
2695
2698
  changeMessage: row.changeMessage,
@@ -2853,7 +2856,7 @@ function serializeJson(v) {
2853
2856
  if (typeof v === "object" && v != null) return JSON.stringify(v);
2854
2857
  return v ?? null;
2855
2858
  }
2856
- function parseJson$3(val) {
2859
+ function parseJson$4(val) {
2857
2860
  if (val == null) return void 0;
2858
2861
  if (typeof val === "string") try {
2859
2862
  return JSON.parse(val);
@@ -2868,14 +2871,14 @@ function rowToTask(row) {
2868
2871
  status: String(row.status),
2869
2872
  toolName: String(row.tool_name),
2870
2873
  toolCallId: String(row.tool_call_id),
2871
- args: parseJson$3(row.args) ?? {},
2874
+ args: parseJson$4(row.args) ?? {},
2872
2875
  agentId: String(row.agent_id),
2873
2876
  threadId: row.thread_id != null ? String(row.thread_id) : void 0,
2874
2877
  resourceId: row.resource_id != null ? String(row.resource_id) : void 0,
2875
2878
  runId: String(row.run_id),
2876
- result: parseJson$3(row.result),
2877
- error: parseJson$3(row.error),
2878
- suspendPayload: parseJson$3(row.suspend_payload),
2879
+ result: parseJson$4(row.result),
2880
+ error: parseJson$4(row.error),
2881
+ suspendPayload: parseJson$4(row.suspend_payload),
2879
2882
  retryCount: Number(row.retry_count),
2880
2883
  maxRetries: Number(row.max_retries),
2881
2884
  timeoutMs: Number(row.timeout_ms),
@@ -5536,10 +5539,10 @@ var FavoritesLibSQL = class extends FavoritesStorage {
5536
5539
  };
5537
5540
  //#endregion
5538
5541
  //#region src/storage/domains/harness/index.ts
5539
- const toDate = (value) => new Date(value);
5542
+ const toDate$1 = (value) => new Date(value);
5540
5543
  const toOptionalDate = (value) => {
5541
5544
  if (value == null) return void 0;
5542
- return toDate(value);
5545
+ return toDate$1(value);
5543
5546
  };
5544
5547
  function cloneJson(value) {
5545
5548
  return value === void 0 ? void 0 : structuredClone(value);
@@ -5550,8 +5553,8 @@ function hydratePendingItem(item) {
5550
5553
  kind: item.kind,
5551
5554
  status: item.status,
5552
5555
  sessionId: item.sessionId,
5553
- createdAt: toDate(item.createdAt),
5554
- updatedAt: toDate(item.updatedAt)
5556
+ createdAt: toDate$1(item.createdAt),
5557
+ updatedAt: toDate$1(item.updatedAt)
5555
5558
  };
5556
5559
  if (item.runId !== void 0) record.runId = item.runId;
5557
5560
  if (item.traceId !== void 0) record.traceId = item.traceId;
@@ -5569,8 +5572,8 @@ function rowToSession(row) {
5569
5572
  origin: row.origin,
5570
5573
  modeId: row.modeId,
5571
5574
  modelId: row.modelId,
5572
- createdAt: toDate(row.createdAt),
5573
- lastActivityAt: toDate(row.lastActivityAt)
5575
+ createdAt: toDate$1(row.createdAt),
5576
+ lastActivityAt: toDate$1(row.lastActivityAt)
5574
5577
  };
5575
5578
  if (row.parentSessionId != null) record.parentSessionId = row.parentSessionId;
5576
5579
  if (row.subagentDepth != null) record.subagentDepth = row.subagentDepth;
@@ -5680,6 +5683,841 @@ var HarnessLibSQL = class HarnessLibSQL extends HarnessStorage {
5680
5683
  }
5681
5684
  };
5682
5685
  //#endregion
5686
+ //#region src/storage/domains/knowledge/index.ts
5687
+ const visibleSql = `(scopeKey = ? OR substr(?, 1, length(scopeKey) + 1) = scopeKey || char(31))`;
5688
+ function parseJson$3(value) {
5689
+ if (typeof value === "string") return JSON.parse(value);
5690
+ if (value instanceof Uint8Array) return JSON.parse(new TextDecoder().decode(value));
5691
+ if (value instanceof ArrayBuffer) return JSON.parse(new TextDecoder().decode(value));
5692
+ return value;
5693
+ }
5694
+ function toDate(value) {
5695
+ return new Date(String(value));
5696
+ }
5697
+ function optionalDate(value) {
5698
+ return value == null ? void 0 : toDate(value);
5699
+ }
5700
+ function canonicalName(name) {
5701
+ return name.trim().toLocaleLowerCase();
5702
+ }
5703
+ function escapeLikePattern(value) {
5704
+ return value.replaceAll("=", "==").replaceAll("%", "=%").replaceAll("_", "=_");
5705
+ }
5706
+ function nodeReferenceId(node) {
5707
+ return typeof node === "string" ? node : node.id;
5708
+ }
5709
+ function parseNode(row) {
5710
+ return {
5711
+ id: String(row.id),
5712
+ type: "node",
5713
+ name: String(row.name),
5714
+ kind: row.kind == null ? "" : String(row.kind),
5715
+ content: row.content == null ? void 0 : String(row.content),
5716
+ scope: parseJson$3(row.scopeJson ?? row.scope),
5717
+ version: Number(row.version),
5718
+ mergedInto: row.mergedInto == null ? void 0 : String(row.mergedInto),
5719
+ createdAt: toDate(row.createdAt),
5720
+ updatedAt: toDate(row.updatedAt)
5721
+ };
5722
+ }
5723
+ function parseKnowledge(row) {
5724
+ return {
5725
+ id: String(row.id),
5726
+ node: String(row.node),
5727
+ text: String(row.text),
5728
+ scope: parseJson$3(row.scopeJson ?? row.scope),
5729
+ sourceThreadId: String(row.sourceThreadId),
5730
+ capturedAt: toDate(row.capturedAt),
5731
+ when: optionalDate(row.when),
5732
+ maxScope: row.maxScope == null ? void 0 : String(row.maxScope),
5733
+ metadata: (row.metadataJson ?? row.metadata) == null ? void 0 : parseJson$3(row.metadataJson ?? row.metadata),
5734
+ deletedAt: optionalDate(row.deletedAt),
5735
+ deletedBy: row.deletedBy == null ? void 0 : String(row.deletedBy)
5736
+ };
5737
+ }
5738
+ function parseOutbox(row) {
5739
+ return {
5740
+ id: String(row.id),
5741
+ idempotencyKey: String(row.idempotencyKey),
5742
+ documentId: String(row.documentId),
5743
+ documentType: String(row.documentType),
5744
+ operation: String(row.operation),
5745
+ scope: parseJson$3(row.scopeJson ?? row.scope),
5746
+ status: String(row.status),
5747
+ attempts: Number(row.attempts),
5748
+ availableAt: toDate(row.availableAt),
5749
+ claimedAt: optionalDate(row.claimedAt),
5750
+ claimedBy: row.claimedBy == null ? void 0 : String(row.claimedBy),
5751
+ createdAt: toDate(row.createdAt),
5752
+ completedAt: optionalDate(row.completedAt)
5753
+ };
5754
+ }
5755
+ var KnowledgeLibSQL = class extends KnowledgeStorage {
5756
+ #client;
5757
+ #db;
5758
+ constructor(config) {
5759
+ super();
5760
+ this.#client = resolveClient(config);
5761
+ this.#db = new LibSQLDB({
5762
+ client: this.#client,
5763
+ maxRetries: config.maxRetries,
5764
+ initialBackoffMs: config.initialBackoffMs
5765
+ });
5766
+ }
5767
+ async init() {
5768
+ await this.#db.createTable({
5769
+ tableName: TABLE_KNOWLEDGE_NODES,
5770
+ schema: KNOWLEDGE_NODES_SCHEMA
5771
+ });
5772
+ await this.#db.createTable({
5773
+ tableName: TABLE_KNOWLEDGE_RECORDS,
5774
+ schema: KNOWLEDGE_RECORDS_SCHEMA
5775
+ });
5776
+ await this.#db.createTable({
5777
+ tableName: TABLE_KNOWLEDGE_MENTIONS,
5778
+ schema: KNOWLEDGE_MENTIONS_SCHEMA,
5779
+ compositePrimaryKey: [
5780
+ "sourceType",
5781
+ "sourceId",
5782
+ "recordId"
5783
+ ]
5784
+ });
5785
+ await this.#db.createTable({
5786
+ tableName: TABLE_KNOWLEDGE_CURSORS,
5787
+ schema: KNOWLEDGE_CURSORS_SCHEMA,
5788
+ compositePrimaryKey: ["sourceThreadId", "agent"]
5789
+ });
5790
+ await this.#db.createTable({
5791
+ tableName: TABLE_KNOWLEDGE_ACTIVITY,
5792
+ schema: KNOWLEDGE_ACTIVITY_SCHEMA
5793
+ });
5794
+ await this.#db.createTable({
5795
+ tableName: TABLE_KNOWLEDGE_SEMANTIC_OUTBOX,
5796
+ schema: KNOWLEDGE_SEMANTIC_OUTBOX_SCHEMA
5797
+ });
5798
+ await this.#client.batch([
5799
+ {
5800
+ sql: `CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_nodes_identity ON "${TABLE_KNOWLEDGE_NODES}" (type, scopeKey, canonicalName)`,
5801
+ args: []
5802
+ },
5803
+ {
5804
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_nodes_scope ON "${TABLE_KNOWLEDGE_NODES}" (scopeKey, type)`,
5805
+ args: []
5806
+ },
5807
+ {
5808
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_records_node_latest ON "${TABLE_KNOWLEDGE_RECORDS}" (node, id DESC)`,
5809
+ args: []
5810
+ },
5811
+ {
5812
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_records_thread_latest ON "${TABLE_KNOWLEDGE_RECORDS}" (sourceThreadId, id DESC)`,
5813
+ args: []
5814
+ },
5815
+ {
5816
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_mentions_record ON "${TABLE_KNOWLEDGE_MENTIONS}" (recordId, sourceType, sourceId)`,
5817
+ args: []
5818
+ },
5819
+ {
5820
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_activity_latest ON "${TABLE_KNOWLEDGE_ACTIVITY}" (id DESC)`,
5821
+ args: []
5822
+ },
5823
+ {
5824
+ sql: `CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_outbox_idempotency ON "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" (idempotencyKey)`,
5825
+ args: []
5826
+ },
5827
+ {
5828
+ sql: `CREATE INDEX IF NOT EXISTS idx_knowledge_outbox_claim ON "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" (status, availableAt, createdAt)`,
5829
+ args: []
5830
+ }
5831
+ ], "write");
5832
+ }
5833
+ async dangerouslyClearAll() {
5834
+ await this.#transaction(async (tx) => {
5835
+ for (const table of [
5836
+ TABLE_KNOWLEDGE_MENTIONS,
5837
+ TABLE_KNOWLEDGE_RECORDS,
5838
+ TABLE_KNOWLEDGE_NODES,
5839
+ TABLE_KNOWLEDGE_CURSORS,
5840
+ TABLE_KNOWLEDGE_ACTIVITY,
5841
+ TABLE_KNOWLEDGE_SEMANTIC_OUTBOX
5842
+ ]) await tx.execute(`DELETE FROM "${table}"`);
5843
+ });
5844
+ }
5845
+ async createNode(input) {
5846
+ const scope = canonicalizeKnowledgeScope(input.scope);
5847
+ return this.#transaction(async (tx) => {
5848
+ const existing = await this.#getNodeByName(tx, input.name, scope);
5849
+ if (existing) {
5850
+ const terminal = await this.#resolveTerminalNode(tx, existing.id);
5851
+ if (!isKnowledgeScopeVisible(terminal.scope, scope)) throw new Error(`Merged knowledge node is not visible from scope: ${input.name}`);
5852
+ return terminal;
5853
+ }
5854
+ const now = /* @__PURE__ */ new Date();
5855
+ const node = {
5856
+ id: input.id ?? crypto.randomUUID(),
5857
+ type: "node",
5858
+ name: input.name.trim(),
5859
+ kind: input.kind,
5860
+ content: input.content,
5861
+ scope,
5862
+ version: 1,
5863
+ createdAt: now,
5864
+ updatedAt: now
5865
+ };
5866
+ await tx.execute({
5867
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODES}" (id,type,name,canonicalName,kind,content,scope,scopeKey,version,mergedInto,createdAt,updatedAt) VALUES (?,?,?,?,?,?,jsonb(?),?,?,NULL,?,?)`,
5868
+ args: [
5869
+ node.id,
5870
+ "node",
5871
+ node.name,
5872
+ canonicalName(node.name),
5873
+ node.kind,
5874
+ node.content ?? null,
5875
+ JSON.stringify(scope),
5876
+ knowledgeScopeKey(scope),
5877
+ node.version,
5878
+ now.toISOString(),
5879
+ now.toISOString()
5880
+ ]
5881
+ });
5882
+ await this.#replaceMentions(tx, "node", node.id, node.content ?? "", input.resolutionScope ?? scope, scope);
5883
+ await this.#activity(tx, "node-created", "node", node.id, scope);
5884
+ await this.#outbox(tx, "node", node.id, "upsert", node.version, scope);
5885
+ return node;
5886
+ });
5887
+ }
5888
+ async getNode(id) {
5889
+ return this.#getNode(this.#client, id);
5890
+ }
5891
+ async getNodeByName(input) {
5892
+ return this.#getNodeByName(this.#client, input.name, canonicalizeKnowledgeScope(input.scope));
5893
+ }
5894
+ async resolveNode(input) {
5895
+ return this.#resolveNode(this.#client, input.name, canonicalizeKnowledgeScope(input.scope));
5896
+ }
5897
+ async listNodes(input) {
5898
+ const key = knowledgeScopeKey(canonicalizeKnowledgeScope(input.scope));
5899
+ const clauses = [
5900
+ `type = 'node'`,
5901
+ "mergedInto IS NULL",
5902
+ visibleSql
5903
+ ];
5904
+ const args = [key, key];
5905
+ if (input.namePrefix) {
5906
+ clauses.push("canonicalName LIKE ? ESCAPE '='");
5907
+ args.push(`${escapeLikePattern(canonicalName(input.namePrefix))}%`);
5908
+ }
5909
+ if (input.kind) {
5910
+ clauses.push("kind = ?");
5911
+ args.push(input.kind);
5912
+ }
5913
+ if (input.hasContent !== void 0) clauses.push(input.hasContent ? "content IS NOT NULL AND content <> ''" : "(content IS NULL OR content = '')");
5914
+ if (input.cursor) {
5915
+ const cursor = parseKnowledgeNodeCursor(input.cursor, {
5916
+ namePrefix: input.namePrefix,
5917
+ kind: input.kind,
5918
+ hasContent: input.hasContent
5919
+ });
5920
+ clauses.push("(updatedAt < ? OR (updatedAt = ? AND (name > ? OR (name = ? AND id > ?))))");
5921
+ const updatedAt = cursor.updatedAt.toISOString();
5922
+ args.push(updatedAt, updatedAt, cursor.name, cursor.name, cursor.id);
5923
+ }
5924
+ args.push(input.limit ?? 100);
5925
+ return (await this.#client.execute({
5926
+ sql: `SELECT *, json(scope) AS scopeJson FROM "${TABLE_KNOWLEDGE_NODES}" WHERE ${clauses.join(" AND ")} ORDER BY updatedAt DESC, name ASC, id ASC LIMIT ?`,
5927
+ args
5928
+ })).rows.map(parseNode);
5929
+ }
5930
+ async updateNode(input) {
5931
+ return this.#transaction(async (tx) => {
5932
+ const existing = await this.#getNode(tx, input.id);
5933
+ if (!existing) throw new KnowledgeNotFoundError("node", input.id);
5934
+ if (existing.mergedInto) throw new Error(`Cannot update merged knowledge node: ${input.id}`);
5935
+ const scope = canonicalizeKnowledgeScope(input.scope ?? existing.scope);
5936
+ const name = (input.name ?? existing.name).trim();
5937
+ const content = input.content ?? existing.content;
5938
+ const now = /* @__PURE__ */ new Date();
5939
+ if ((await tx.execute({
5940
+ sql: `UPDATE "${TABLE_KNOWLEDGE_NODES}" SET name=?,canonicalName=?,kind=?,content=?,scope=jsonb(?),scopeKey=?,version=version+1,updatedAt=? WHERE id=? AND type='node' AND version=?`,
5941
+ args: [
5942
+ name,
5943
+ canonicalName(name),
5944
+ input.kind ?? existing.kind,
5945
+ content ?? null,
5946
+ JSON.stringify(scope),
5947
+ knowledgeScopeKey(scope),
5948
+ now.toISOString(),
5949
+ input.id,
5950
+ input.version
5951
+ ]
5952
+ })).rowsAffected === 0) throw new KnowledgeConflictError(input.id);
5953
+ 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);
5954
+ await this.#activity(tx, "node-updated", "node", input.id, scope);
5955
+ if (knowledgeScopeKey(existing.scope) !== knowledgeScopeKey(scope)) {
5956
+ await this.#outbox(tx, "node", input.id, "delete", createKnowledgeUlid(), existing.scope);
5957
+ const knowledge = await tx.execute({
5958
+ sql: `SELECT id,json(scope) AS scopeJson,deletedAt FROM "${TABLE_KNOWLEDGE_RECORDS}" WHERE node=?`,
5959
+ args: [input.id]
5960
+ });
5961
+ for (const row of knowledge.rows) {
5962
+ const recordScope = parseJson$3(row.scopeJson);
5963
+ await this.#outbox(tx, "record", String(row.id), "delete", createKnowledgeUlid(), recordScope);
5964
+ if (row.deletedAt == null) await this.#outbox(tx, "record", String(row.id), "upsert", createKnowledgeUlid(), recordScope);
5965
+ }
5966
+ }
5967
+ await this.#outbox(tx, "node", input.id, "upsert", input.version + 1, scope);
5968
+ return {
5969
+ ...existing,
5970
+ name,
5971
+ kind: input.kind ?? existing.kind,
5972
+ content,
5973
+ scope,
5974
+ version: input.version + 1,
5975
+ updatedAt: now
5976
+ };
5977
+ });
5978
+ }
5979
+ async mergeNodes(input) {
5980
+ if (input.sourceId === input.targetId) throw new Error("Cannot merge a knowledge node into itself");
5981
+ return this.#transaction(async (tx) => {
5982
+ const source = await this.#getNode(tx, input.sourceId);
5983
+ if (!source) throw new KnowledgeNotFoundError("node", input.sourceId);
5984
+ const target = await this.#resolveTerminalNode(tx, input.targetId);
5985
+ if (!target) throw new KnowledgeNotFoundError("node", input.targetId);
5986
+ if (target.id === source.id) throw new Error("Cannot create a knowledge merge cycle");
5987
+ if (!isKnowledgeScopeVisible(target.scope, source.scope)) throw new Error("Cannot merge a knowledge node into a target that is narrower than its source scope");
5988
+ const affected = await tx.execute({
5989
+ sql: `SELECT DISTINCT m.sourceType,m.sourceId,json(COALESCE(f.scope,r.scope)) AS scopeJson,CASE WHEN f.deletedAt IS NULL THEN 0 ELSE 1 END AS deleted FROM "${TABLE_KNOWLEDGE_MENTIONS}" m LEFT JOIN "${TABLE_KNOWLEDGE_RECORDS}" f ON m.sourceType='record' AND f.id=m.sourceId LEFT JOIN "${TABLE_KNOWLEDGE_NODES}" r ON m.sourceType='node' AND r.id=m.sourceId WHERE m.recordId=?`,
5990
+ args: [source.id]
5991
+ });
5992
+ const movedKnowledge = await tx.execute({
5993
+ sql: `SELECT id,json(scope) AS scopeJson,deletedAt FROM "${TABLE_KNOWLEDGE_RECORDS}" WHERE node=?`,
5994
+ args: [source.id]
5995
+ });
5996
+ if ((await tx.execute({
5997
+ sql: `UPDATE "${TABLE_KNOWLEDGE_NODES}" SET mergedInto=?,version=version+1,updatedAt=? WHERE id=? AND type='node' AND version=? AND mergedInto IS NULL`,
5998
+ args: [
5999
+ target.id,
6000
+ (/* @__PURE__ */ new Date()).toISOString(),
6001
+ source.id,
6002
+ input.sourceVersion
6003
+ ]
6004
+ })).rowsAffected === 0) throw new KnowledgeConflictError(source.id);
6005
+ await tx.execute({
6006
+ sql: `UPDATE "${TABLE_KNOWLEDGE_RECORDS}" SET node=? WHERE node=?`,
6007
+ args: [target.id, source.id]
6008
+ });
6009
+ await tx.execute({
6010
+ sql: `DELETE FROM "${TABLE_KNOWLEDGE_MENTIONS}" WHERE recordId=? AND EXISTS (SELECT 1 FROM "${TABLE_KNOWLEDGE_MENTIONS}" target WHERE target.sourceType="${TABLE_KNOWLEDGE_MENTIONS}".sourceType AND target.sourceId="${TABLE_KNOWLEDGE_MENTIONS}".sourceId AND target.recordId=?)`,
6011
+ args: [source.id, target.id]
6012
+ });
6013
+ await tx.execute({
6014
+ sql: `UPDATE "${TABLE_KNOWLEDGE_MENTIONS}" SET recordId=? WHERE recordId=?`,
6015
+ args: [target.id, source.id]
6016
+ });
6017
+ for (const row of movedKnowledge.rows) await this.#outbox(tx, "record", String(row.id), row.deletedAt == null ? "upsert" : "delete", createKnowledgeUlid(), parseJson$3(row.scopeJson));
6018
+ for (const row of affected.rows) await this.#outbox(tx, String(row.sourceType), String(row.sourceId), Number(row.deleted) ? "delete" : "upsert", createKnowledgeUlid(), parseJson$3(row.scopeJson));
6019
+ await this.#activity(tx, "node-merged", "node", source.id, source.scope);
6020
+ await this.#outbox(tx, "node", source.id, "delete", input.sourceVersion + 1, source.scope);
6021
+ await this.#outbox(tx, "node", target.id, "upsert", createKnowledgeUlid(), target.scope);
6022
+ return target;
6023
+ });
6024
+ }
6025
+ async appendKnowledge(input) {
6026
+ const scope = canonicalizeKnowledgeScope(input.scope);
6027
+ const resolutionScope = canonicalizeKnowledgeScope(input.resolutionScope);
6028
+ const defaultScope = canonicalizeKnowledgeScope(input.defaultScope);
6029
+ assertKnowledgeScopeWithinCeiling(scope, input.maxScope);
6030
+ return this.#transaction(async (tx) => {
6031
+ const node = nodeReferenceId(input.node);
6032
+ const parent = await this.#resolveTerminalNode(tx, node);
6033
+ if (!parent) throw new KnowledgeNotFoundError("node", node);
6034
+ const record = {
6035
+ id: input.id ?? createKnowledgeUlid(),
6036
+ node: parent.id,
6037
+ text: input.text,
6038
+ scope,
6039
+ sourceThreadId: input.sourceThreadId,
6040
+ capturedAt: /* @__PURE__ */ new Date(),
6041
+ when: input.when ? new Date(input.when) : void 0,
6042
+ maxScope: input.maxScope,
6043
+ metadata: input.metadata
6044
+ };
6045
+ await tx.execute({
6046
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_RECORDS}" (id,node,text,scope,scopeKey,sourceThreadId,capturedAt,"when",maxScope,metadata,deletedAt,deletedBy) VALUES (?,?,?,jsonb(?),?,?,?,?,?,jsonb(?),NULL,NULL)`,
6047
+ args: [
6048
+ record.id,
6049
+ record.node,
6050
+ record.text,
6051
+ JSON.stringify(scope),
6052
+ knowledgeScopeKey(scope),
6053
+ record.sourceThreadId,
6054
+ record.capturedAt.toISOString(),
6055
+ record.when?.toISOString() ?? null,
6056
+ record.maxScope ?? null,
6057
+ record.metadata ? JSON.stringify(record.metadata) : null
6058
+ ]
6059
+ });
6060
+ await this.#replaceMentions(tx, "record", record.id, record.text, resolutionScope, defaultScope);
6061
+ await this.#activity(tx, "record-created", "record", record.id, scope, record.sourceThreadId);
6062
+ await this.#outbox(tx, "record", record.id, "upsert", record.id, scope);
6063
+ return record;
6064
+ });
6065
+ }
6066
+ async getKnowledge(input) {
6067
+ const result = await this.#client.execute({
6068
+ sql: `SELECT *,json(scope) AS scopeJson,json(metadata) AS metadataJson FROM "${TABLE_KNOWLEDGE_RECORDS}" WHERE id=?${input.includeDeleted ? "" : " AND deletedAt IS NULL"}`,
6069
+ args: [input.id]
6070
+ });
6071
+ return result.rows[0] ? parseKnowledge(result.rows[0]) : null;
6072
+ }
6073
+ async listKnowledgeAbout(input) {
6074
+ return this.#queryKnowledge(input, "about");
6075
+ }
6076
+ async listKnowledgeMentioning(input) {
6077
+ return this.#queryKnowledge(input, "mentioning");
6078
+ }
6079
+ async listKnowledgeRelatedTo(input) {
6080
+ return this.#queryKnowledge(input, "related");
6081
+ }
6082
+ async knowledgeBySource(input) {
6083
+ const key = knowledgeScopeKey(canonicalizeKnowledgeScope(input.scope));
6084
+ const args = [
6085
+ input.sourceThreadId,
6086
+ key,
6087
+ key
6088
+ ];
6089
+ if (input.after) args.push(input.after);
6090
+ const limit = input.limit ?? 100;
6091
+ args.push(limit + 1);
6092
+ const records = (await this.#client.execute({
6093
+ sql: `SELECT *,json(scope) AS scopeJson,json(metadata) AS metadataJson FROM "${TABLE_KNOWLEDGE_RECORDS}" WHERE sourceThreadId=? AND ${visibleSql}${input.includeDeleted ? "" : " AND deletedAt IS NULL"}${input.after ? " AND id > ?" : ""} ORDER BY id ASC LIMIT ?`,
6094
+ args
6095
+ })).rows.map(parseKnowledge);
6096
+ return {
6097
+ records: records.slice(0, limit),
6098
+ nextCursor: records.length > limit ? records[limit - 1]?.id : void 0
6099
+ };
6100
+ }
6101
+ async removeKnowledge(input) {
6102
+ return this.#transaction(async (tx) => {
6103
+ const record = await this.#getKnowledge(tx, input.id, true);
6104
+ if (!record) throw new KnowledgeNotFoundError("record", input.id);
6105
+ if (record.deletedAt) return record;
6106
+ const deletedAt = /* @__PURE__ */ new Date();
6107
+ await tx.execute({
6108
+ sql: `UPDATE "${TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=?,deletedBy=? WHERE id=? AND deletedAt IS NULL`,
6109
+ args: [
6110
+ deletedAt.toISOString(),
6111
+ input.deletedBy,
6112
+ input.id
6113
+ ]
6114
+ });
6115
+ await this.#activity(tx, "record-deleted", "record", input.id, record.scope, record.sourceThreadId);
6116
+ await this.#outbox(tx, "record", input.id, "delete", deletedAt.toISOString(), record.scope);
6117
+ return {
6118
+ ...record,
6119
+ deletedAt,
6120
+ deletedBy: input.deletedBy
6121
+ };
6122
+ });
6123
+ }
6124
+ async restoreKnowledge(input) {
6125
+ return this.#transaction(async (tx) => {
6126
+ const record = await this.#getKnowledge(tx, input.id, true);
6127
+ if (!record) throw new KnowledgeNotFoundError("record", input.id);
6128
+ if (!record.deletedAt) return record;
6129
+ await tx.execute({
6130
+ sql: `UPDATE "${TABLE_KNOWLEDGE_RECORDS}" SET deletedAt=NULL,deletedBy=NULL WHERE id=?`,
6131
+ args: [input.id]
6132
+ });
6133
+ await this.#activity(tx, "record-restored", "record", input.id, record.scope, record.sourceThreadId);
6134
+ await this.#outbox(tx, "record", input.id, "upsert", createKnowledgeUlid(), record.scope);
6135
+ return {
6136
+ ...record,
6137
+ deletedAt: void 0,
6138
+ deletedBy: void 0
6139
+ };
6140
+ });
6141
+ }
6142
+ async rescopeKnowledge(input) {
6143
+ const scope = canonicalizeKnowledgeScope(input.scope);
6144
+ return this.#transaction(async (tx) => {
6145
+ const record = await this.#getKnowledge(tx, input.id, true);
6146
+ if (!record) throw new KnowledgeNotFoundError("record", input.id);
6147
+ assertKnowledgeScopeWithinCeiling(scope, record.maxScope);
6148
+ await tx.execute({
6149
+ sql: `UPDATE "${TABLE_KNOWLEDGE_RECORDS}" SET scope=jsonb(?),scopeKey=? WHERE id=?`,
6150
+ args: [
6151
+ JSON.stringify(scope),
6152
+ knowledgeScopeKey(scope),
6153
+ input.id
6154
+ ]
6155
+ });
6156
+ await this.#activity(tx, "record-rescoped", "record", input.id, scope, record.sourceThreadId);
6157
+ if (knowledgeScopeKey(record.scope) !== knowledgeScopeKey(scope)) await this.#outbox(tx, "record", input.id, "delete", createKnowledgeUlid(), record.scope);
6158
+ if (!record.deletedAt) await this.#outbox(tx, "record", input.id, "upsert", createKnowledgeUlid(), scope);
6159
+ return {
6160
+ ...record,
6161
+ scope
6162
+ };
6163
+ });
6164
+ }
6165
+ async raiseKnowledgeCeiling(input) {
6166
+ return this.#transaction(async (tx) => {
6167
+ const record = await this.#getKnowledge(tx, input.id, true);
6168
+ if (!record) throw new KnowledgeNotFoundError("record", input.id);
6169
+ assertKnowledgeScopeWithinCeiling(record.scope, input.maxScope);
6170
+ assertKnowledgeCeilingRaised(record.maxScope, input.maxScope);
6171
+ await tx.execute({
6172
+ sql: `UPDATE "${TABLE_KNOWLEDGE_RECORDS}" SET maxScope=? WHERE id=?`,
6173
+ args: [input.maxScope ?? null, input.id]
6174
+ });
6175
+ return {
6176
+ ...record,
6177
+ maxScope: input.maxScope
6178
+ };
6179
+ });
6180
+ }
6181
+ async search(input) {
6182
+ const key = knowledgeScopeKey(canonicalizeKnowledgeScope(input.scope));
6183
+ const normalizedQuery = input.query.trim().toLocaleLowerCase();
6184
+ if (!normalizedQuery) return [];
6185
+ const query = `%${escapeLikePattern(normalizedQuery)}%`;
6186
+ const results = (await this.#client.execute({
6187
+ sql: `SELECT *,json(scope) AS scopeJson FROM "${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 '=') ORDER BY updatedAt DESC LIMIT ?`,
6188
+ args: [
6189
+ key,
6190
+ key,
6191
+ query,
6192
+ query,
6193
+ query,
6194
+ input.limit ?? 20
6195
+ ]
6196
+ })).rows.map((row) => ({
6197
+ type: String(row.type),
6198
+ id: String(row.id),
6199
+ recordId: String(row.id),
6200
+ name: String(row.name),
6201
+ text: row.content ? `${String(row.name)}\n${String(row.content)}` : String(row.name),
6202
+ scope: parseJson$3(row.scopeJson)
6203
+ }));
6204
+ if (results.length < (input.limit ?? 20)) {
6205
+ const knowledge = await this.#client.execute({
6206
+ sql: `SELECT k.*,json(k.scope) AS scopeJson,json(k.metadata) AS metadataJson,n.name FROM "${TABLE_KNOWLEDGE_RECORDS}" k JOIN "${TABLE_KNOWLEDGE_NODES}" n ON n.id=k.node AND n.type='node' AND n.mergedInto IS NULL WHERE k.deletedAt IS NULL AND ${visibleSql.replaceAll("scopeKey", "k.scopeKey")} AND lower(k.text) LIKE ? ESCAPE '=' ORDER BY k.id DESC LIMIT ?`,
6207
+ args: [
6208
+ key,
6209
+ key,
6210
+ query,
6211
+ (input.limit ?? 20) - results.length
6212
+ ]
6213
+ });
6214
+ results.push(...knowledge.rows.map((row) => ({
6215
+ type: "record",
6216
+ id: String(row.id),
6217
+ recordId: String(row.node),
6218
+ name: String(row.name),
6219
+ text: String(row.text),
6220
+ scope: parseJson$3(row.scopeJson)
6221
+ })));
6222
+ }
6223
+ return results;
6224
+ }
6225
+ async getCurationCursor(input) {
6226
+ const row = (await this.#client.execute({
6227
+ sql: `SELECT * FROM "${TABLE_KNOWLEDGE_CURSORS}" WHERE sourceThreadId=? AND agent=?`,
6228
+ args: [input.sourceThreadId, input.agent]
6229
+ })).rows[0];
6230
+ return row ? {
6231
+ sourceThreadId: String(row.sourceThreadId),
6232
+ agent: String(row.agent),
6233
+ lastKnowledgeId: String(row.lastKnowledgeId),
6234
+ updatedAt: toDate(row.updatedAt)
6235
+ } : null;
6236
+ }
6237
+ async advanceCurationCursor(input) {
6238
+ const updatedAt = /* @__PURE__ */ new Date();
6239
+ if ((await this.#db.executeWriteOperationWithRetry(() => withClientWriteLock(this.#client, () => this.#client.execute({
6240
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_CURSORS}" (sourceThreadId,agent,lastKnowledgeId,updatedAt) VALUES (?,?,?,?) ON CONFLICT(sourceThreadId,agent) DO UPDATE SET lastKnowledgeId=excluded.lastKnowledgeId,updatedAt=excluded.updatedAt WHERE excluded.lastKnowledgeId >= "${TABLE_KNOWLEDGE_CURSORS}".lastKnowledgeId`,
6241
+ args: [
6242
+ input.sourceThreadId,
6243
+ input.agent,
6244
+ input.lastKnowledgeId,
6245
+ updatedAt.toISOString()
6246
+ ]
6247
+ })), "advance knowledge curation cursor")).rowsAffected === 0) throw new Error("Knowledge curation cursor cannot move backwards");
6248
+ return {
6249
+ ...input,
6250
+ updatedAt
6251
+ };
6252
+ }
6253
+ async listActivity(input) {
6254
+ const key = knowledgeScopeKey(canonicalizeKnowledgeScope(input.scope));
6255
+ return (await this.#client.execute({
6256
+ sql: `SELECT *,json(scope) AS scopeJson FROM "${TABLE_KNOWLEDGE_ACTIVITY}" WHERE ${visibleSql}${input.after ? " AND id < ?" : ""} ORDER BY id DESC LIMIT ?`,
6257
+ args: [
6258
+ key,
6259
+ key,
6260
+ ...input.after ? [input.after] : [],
6261
+ input.limit ?? 100
6262
+ ]
6263
+ })).rows.map((row) => ({
6264
+ id: String(row.id),
6265
+ action: String(row.action),
6266
+ recordType: String(row.recordType),
6267
+ recordId: String(row.recordId),
6268
+ scope: parseJson$3(row.scopeJson),
6269
+ sourceThreadId: row.sourceThreadId == null ? void 0 : String(row.sourceThreadId),
6270
+ createdAt: toDate(row.createdAt)
6271
+ }));
6272
+ }
6273
+ async listSemanticOutbox(input = {}) {
6274
+ const clauses = [];
6275
+ const args = [];
6276
+ if (input.status) {
6277
+ clauses.push("status=?");
6278
+ args.push(input.status);
6279
+ }
6280
+ if (input.scope) {
6281
+ const key = knowledgeScopeKey(canonicalizeKnowledgeScope(input.scope));
6282
+ clauses.push(visibleSql);
6283
+ args.push(key, key);
6284
+ }
6285
+ args.push(input.limit ?? 100);
6286
+ return (await this.#client.execute({
6287
+ sql: `SELECT *,json(scope) AS scopeJson FROM "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}"${clauses.length ? ` WHERE ${clauses.join(" AND ")}` : ""} ORDER BY createdAt ASC,id ASC LIMIT ?`,
6288
+ args
6289
+ })).rows.map(parseOutbox);
6290
+ }
6291
+ async claimSemanticOutbox(input) {
6292
+ const now = input.now ?? /* @__PURE__ */ new Date();
6293
+ const stale = new Date(now.getTime() - (input.claimTimeoutMs ?? 6e4));
6294
+ return this.#transaction(async (tx) => {
6295
+ const clauses = [
6296
+ `availableAt <= ?`,
6297
+ `(status='pending' OR (status='processing' AND claimedAt <= ?))`,
6298
+ `NOT EXISTS (SELECT 1 FROM "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" AS earlier WHERE earlier.documentId = "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}".documentId AND earlier.status != 'completed' AND (earlier.createdAt < "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}".createdAt OR (earlier.createdAt = "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}".createdAt AND earlier.id < "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}".id)))`
6299
+ ];
6300
+ const args = [now.toISOString(), stale.toISOString()];
6301
+ if (input.scope) {
6302
+ const key = knowledgeScopeKey(canonicalizeKnowledgeScope(input.scope));
6303
+ clauses.push(visibleSql);
6304
+ args.push(key, key);
6305
+ }
6306
+ args.push(input.limit ?? 100);
6307
+ const ids = (await tx.execute({
6308
+ sql: `SELECT id FROM "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" WHERE ${clauses.join(" AND ")} ORDER BY createdAt ASC,id ASC LIMIT ?`,
6309
+ args
6310
+ })).rows.map((row) => String(row.id));
6311
+ for (const id of ids) await tx.execute({
6312
+ sql: `UPDATE "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" SET status='processing',attempts=attempts+1,claimedAt=?,claimedBy=? WHERE id=?`,
6313
+ args: [
6314
+ now.toISOString(),
6315
+ input.workerId,
6316
+ id
6317
+ ]
6318
+ });
6319
+ if (!ids.length) return [];
6320
+ return (await tx.execute({
6321
+ sql: `SELECT *,json(scope) AS scopeJson FROM "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" WHERE id IN (${ids.map(() => "?").join(",")}) ORDER BY createdAt ASC,id ASC`,
6322
+ args: ids
6323
+ })).rows.map(parseOutbox);
6324
+ });
6325
+ }
6326
+ async completeSemanticOutbox(input) {
6327
+ if (!input.ids.length) return;
6328
+ const now = (/* @__PURE__ */ new Date()).toISOString();
6329
+ await this.#transaction(async (tx) => {
6330
+ for (const id of input.ids) await tx.execute({
6331
+ sql: `UPDATE "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" SET status='completed',completedAt=? WHERE id=? AND status='processing' AND claimedBy=?`,
6332
+ args: [
6333
+ now,
6334
+ id,
6335
+ input.workerId
6336
+ ]
6337
+ });
6338
+ });
6339
+ }
6340
+ async releaseSemanticOutbox(input) {
6341
+ if (!input.ids.length) return;
6342
+ await this.#transaction(async (tx) => {
6343
+ for (const id of input.ids) await tx.execute({
6344
+ sql: `UPDATE "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" SET status='pending',availableAt=?,claimedAt=NULL,claimedBy=NULL WHERE id=? AND status='processing' AND claimedBy=?`,
6345
+ args: [
6346
+ (input.retryAt ?? /* @__PURE__ */ new Date()).toISOString(),
6347
+ id,
6348
+ input.workerId
6349
+ ]
6350
+ });
6351
+ });
6352
+ }
6353
+ async #transaction(operation) {
6354
+ return this.#db.executeWriteOperationWithRetry(() => withClientWriteLock(this.#client, async () => {
6355
+ const tx = await this.#client.transaction("write");
6356
+ try {
6357
+ const result = await operation(tx);
6358
+ await tx.commit();
6359
+ return result;
6360
+ } catch (error) {
6361
+ if (!tx.closed) await tx.rollback();
6362
+ throw error;
6363
+ }
6364
+ }), "write knowledge state");
6365
+ }
6366
+ async #getNode(executor, id) {
6367
+ const result = await executor.execute({
6368
+ sql: `SELECT *,json(scope) AS scopeJson FROM "${TABLE_KNOWLEDGE_NODES}" WHERE id=? AND type='node'`,
6369
+ args: [id]
6370
+ });
6371
+ return result.rows[0] ? parseNode(result.rows[0]) : null;
6372
+ }
6373
+ async #getNodeByName(executor, name, scope) {
6374
+ const result = await executor.execute({
6375
+ sql: `SELECT *,json(scope) AS scopeJson FROM "${TABLE_KNOWLEDGE_NODES}" WHERE type='node' AND scopeKey=? AND canonicalName=?`,
6376
+ args: [knowledgeScopeKey(scope), canonicalName(name)]
6377
+ });
6378
+ return result.rows[0] ? parseNode(result.rows[0]) : null;
6379
+ }
6380
+ async #resolveNode(executor, name, scope) {
6381
+ for (let length = scope.length; length > 0; length--) {
6382
+ const node = await this.#getNodeByName(executor, name, scope.slice(0, length));
6383
+ if (node) {
6384
+ const terminal = await this.#resolveTerminalNode(executor, node.id);
6385
+ if (terminal && isKnowledgeScopeVisible(terminal.scope, scope)) return terminal;
6386
+ }
6387
+ }
6388
+ return null;
6389
+ }
6390
+ async #resolveTerminalNode(executor, id) {
6391
+ let node = await this.#getNode(executor, id);
6392
+ const seen = /* @__PURE__ */ new Set();
6393
+ while (node?.mergedInto) {
6394
+ if (seen.has(node.id)) throw new Error(`Knowledge merge cycle detected at ${node.id}`);
6395
+ seen.add(node.id);
6396
+ node = await this.#getNode(executor, node.mergedInto);
6397
+ }
6398
+ return node;
6399
+ }
6400
+ async #getKnowledge(executor, id, includeDeleted) {
6401
+ const result = await executor.execute({
6402
+ sql: `SELECT *,json(scope) AS scopeJson,json(metadata) AS metadataJson FROM "${TABLE_KNOWLEDGE_RECORDS}" WHERE id=?${includeDeleted ? "" : " AND deletedAt IS NULL"}`,
6403
+ args: [id]
6404
+ });
6405
+ return result.rows[0] ? parseKnowledge(result.rows[0]) : null;
6406
+ }
6407
+ async #queryKnowledge(input, relationship) {
6408
+ const scope = canonicalizeKnowledgeScope(input.scope);
6409
+ const node = await this.#resolveTerminalNode(this.#client, nodeReferenceId(input.node));
6410
+ if (!node) return { records: [] };
6411
+ const key = knowledgeScopeKey(scope);
6412
+ const includesMentions = relationship !== "about";
6413
+ const relationSql = relationship === "about" ? "k.node=?" : relationship === "mentioning" ? "m.recordId=?" : "(k.node=? OR m.recordId=?)";
6414
+ const args = [
6415
+ node.id,
6416
+ ...relationship === "related" ? [node.id] : [],
6417
+ key,
6418
+ key
6419
+ ];
6420
+ if (input.after) args.push(input.after);
6421
+ args.push((input.limit ?? 100) + 1);
6422
+ const result = await this.#client.execute({
6423
+ sql: `SELECT DISTINCT k.*,json(k.scope) AS scopeJson,json(k.metadata) AS metadataJson FROM "${TABLE_KNOWLEDGE_RECORDS}" k${includesMentions ? ` LEFT JOIN "${TABLE_KNOWLEDGE_MENTIONS}" m ON m.sourceType='record' AND m.sourceId=k.id` : ""} WHERE ${relationSql} AND ${visibleSql.replaceAll("scopeKey", "k.scopeKey")}${input.includeDeleted ? "" : " AND k.deletedAt IS NULL"}${input.after ? " AND k.id < ?" : ""} ORDER BY k.id DESC LIMIT ?`,
6424
+ args
6425
+ });
6426
+ const limit = input.limit ?? 100;
6427
+ const rows = result.rows.slice(0, limit);
6428
+ return {
6429
+ records: rows.map(parseKnowledge),
6430
+ nextCursor: result.rows.length > limit ? String(rows.at(-1)?.id) : void 0
6431
+ };
6432
+ }
6433
+ async #replaceMentions(tx, sourceType, sourceId, text, resolutionScope, defaultScope) {
6434
+ await tx.execute({
6435
+ sql: `DELETE FROM "${TABLE_KNOWLEDGE_MENTIONS}" WHERE sourceType=? AND sourceId=?`,
6436
+ args: [sourceType, sourceId]
6437
+ });
6438
+ for (const name of parseKnowledgeWikilinks(text)) {
6439
+ let node = await this.#resolveNode(tx, name, resolutionScope);
6440
+ if (!node) {
6441
+ node = await this.#getNodeByName(tx, name, defaultScope);
6442
+ if (node) node = await this.#resolveTerminalNode(tx, node.id);
6443
+ if (!node) {
6444
+ const now = /* @__PURE__ */ new Date();
6445
+ node = {
6446
+ id: crypto.randomUUID(),
6447
+ type: "node",
6448
+ name,
6449
+ kind: "node",
6450
+ scope: defaultScope,
6451
+ version: 1,
6452
+ createdAt: now,
6453
+ updatedAt: now
6454
+ };
6455
+ await tx.execute({
6456
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_NODES}" (id,type,name,canonicalName,kind,content,scope,scopeKey,version,mergedInto,createdAt,updatedAt) VALUES (?,?,?,?,?,NULL,jsonb(?),?,?,NULL,?,?)`,
6457
+ args: [
6458
+ node.id,
6459
+ "node",
6460
+ node.name,
6461
+ canonicalName(node.name),
6462
+ node.kind,
6463
+ JSON.stringify(defaultScope),
6464
+ knowledgeScopeKey(defaultScope),
6465
+ 1,
6466
+ now.toISOString(),
6467
+ now.toISOString()
6468
+ ]
6469
+ });
6470
+ await this.#activity(tx, "node-created", "node", node.id, defaultScope);
6471
+ await this.#outbox(tx, "node", node.id, "upsert", 1, defaultScope);
6472
+ }
6473
+ }
6474
+ await tx.execute({
6475
+ sql: `INSERT OR IGNORE INTO "${TABLE_KNOWLEDGE_MENTIONS}" (sourceType,sourceId,recordId) VALUES (?,?,?)`,
6476
+ args: [
6477
+ sourceType,
6478
+ sourceId,
6479
+ node.id
6480
+ ]
6481
+ });
6482
+ }
6483
+ }
6484
+ async #activity(executor, action, recordType, recordId, scope, sourceThreadId) {
6485
+ const now = /* @__PURE__ */ new Date();
6486
+ await executor.execute({
6487
+ sql: `INSERT INTO "${TABLE_KNOWLEDGE_ACTIVITY}" (id,action,recordType,recordId,scope,scopeKey,sourceThreadId,createdAt) VALUES (?,?,?,?,jsonb(?),?,?,?)`,
6488
+ args: [
6489
+ createKnowledgeUlid(),
6490
+ action,
6491
+ recordType,
6492
+ recordId,
6493
+ JSON.stringify(scope),
6494
+ knowledgeScopeKey(scope),
6495
+ sourceThreadId ?? null,
6496
+ now.toISOString()
6497
+ ]
6498
+ });
6499
+ }
6500
+ async #outbox(executor, documentType, id, operation, version, scope) {
6501
+ const documentId = knowledgeSemanticDocumentId(documentType, id);
6502
+ const idempotencyKey = knowledgeSemanticIdempotencyKey(documentId, operation, version);
6503
+ const now = /* @__PURE__ */ new Date();
6504
+ await executor.execute({
6505
+ sql: `INSERT OR IGNORE INTO "${TABLE_KNOWLEDGE_SEMANTIC_OUTBOX}" (id,idempotencyKey,documentId,documentType,operation,scope,scopeKey,status,attempts,availableAt,claimedAt,claimedBy,createdAt,completedAt) VALUES (?,?,?,?,?,jsonb(?),?,'pending',0,?,NULL,NULL,?,NULL)`,
6506
+ args: [
6507
+ createKnowledgeUlid(),
6508
+ idempotencyKey,
6509
+ documentId,
6510
+ documentType,
6511
+ operation,
6512
+ JSON.stringify(scope),
6513
+ knowledgeScopeKey(scope),
6514
+ now.toISOString(),
6515
+ now.toISOString()
6516
+ ]
6517
+ });
6518
+ }
6519
+ };
6520
+ //#endregion
5683
6521
  //#region src/storage/domains/mcp-clients/index.ts
5684
6522
  var MCPClientsLibSQL = class extends MCPClientsStorage {
5685
6523
  #db;
@@ -13205,6 +14043,7 @@ var LibSQLStore = class extends MastraCompositeStore {
13205
14043
  const workflows = new WorkflowsLibSQL(domainConfig);
13206
14044
  const workflowDefinitions = new WorkflowDefinitionsLibSQL(domainConfig);
13207
14045
  const memory = new MemoryLibSQL(domainConfig);
14046
+ const knowledge = new KnowledgeLibSQL(domainConfig);
13208
14047
  const observability = new ObservabilityLibSQL(domainConfig);
13209
14048
  const agents = new AgentsLibSQL(domainConfig);
13210
14049
  const channels = new ChannelsLibSQL(domainConfig);
@@ -13229,6 +14068,7 @@ var LibSQLStore = class extends MastraCompositeStore {
13229
14068
  workflows,
13230
14069
  workflowDefinitions,
13231
14070
  memory,
14071
+ knowledge,
13232
14072
  observability,
13233
14073
  agents,
13234
14074
  channels,
@@ -13416,6 +14256,6 @@ Example Complex Query:
13416
14256
  ]
13417
14257
  }`;
13418
14258
  //#endregion
13419
- export { AgentsLibSQL, BackgroundTasksLibSQL, BlobsLibSQL, ChannelsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, LibSQLStore, ExperimentsLibSQL, FavoritesLibSQL, HarnessLibSQL, LIBSQL_PROMPT, LibSQLFactoryStorage, LibSQLVector, MCPClientsLibSQL, MCPServersLibSQL, MemoryLibSQL, NotificationsLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, SchedulesLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, SkillsLibSQL, ThreadStateLibSQL, ToolProviderConnectionsLibSQL, WorkflowDefinitionsLibSQL, WorkflowsLibSQL, WorkspacesLibSQL };
14259
+ export { AgentsLibSQL, BackgroundTasksLibSQL, BlobsLibSQL, ChannelsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, LibSQLStore, ExperimentsLibSQL, FavoritesLibSQL, HarnessLibSQL, KnowledgeLibSQL, LIBSQL_PROMPT, LibSQLFactoryStorage, LibSQLVector, MCPClientsLibSQL, MCPServersLibSQL, MemoryLibSQL, NotificationsLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, SchedulesLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, SkillsLibSQL, ThreadStateLibSQL, ToolProviderConnectionsLibSQL, WorkflowDefinitionsLibSQL, WorkflowsLibSQL, WorkspacesLibSQL };
13420
14260
 
13421
14261
  //# sourceMappingURL=index.js.map