@mastra/libsql 0.0.0-knowledge-w2-demo-20261009074925 → 0.0.0-knowledge-studio-20261029065150
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 +203 -0
- package/dist/_types/@internal_core/dist/memory/index.d.ts +101 -0
- package/dist/_types/@internal_core/package.json +1 -0
- package/dist/docs/SKILL.md +2 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-agents-human-in-the-loop.md +20 -6
- package/dist/docs/references/docs-agents-networks.md +1 -1
- package/dist/docs/references/docs-deployment-workers.md +1 -1
- package/dist/docs/references/docs-memory-memory-processors.md +21 -15
- package/dist/docs/references/docs-memory-message-history.md +20 -13
- package/dist/docs/references/docs-memory-multi-user-threads.md +2 -2
- package/dist/docs/references/docs-memory-overview.md +31 -0
- package/dist/docs/references/docs-memory-semantic-recall.md +24 -2
- package/dist/docs/references/docs-memory-working-memory.md +3 -3
- package/dist/docs/references/docs-signals-overview.md +94 -0
- package/dist/docs/references/docs-storage.md +1 -1
- package/dist/docs/references/docs-studio-editor.md +39 -23
- package/dist/docs/references/integrations-channels-github.md +2 -2
- package/dist/docs/references/reference-core-mastra-class.md +18 -4
- package/dist/docs/references/reference-memory-memory-class.md +5 -3
- package/dist/docs/references/reference-rag-retrieval.md +13 -13
- package/dist/docs/references/reference-storage-composite.md +34 -0
- package/dist/docs/references/reference-storage-retention.md +37 -31
- package/dist/docs/references/reference-vectors-libsql.md +2 -2
- package/dist/index.cjs +2293 -752
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2294 -753
- package/dist/index.js.map +1 -1
- package/dist/shared/file-transaction-gate.d.ts +28 -0
- package/dist/shared/file-transaction-gate.d.ts.map +1 -0
- package/dist/shared/reset-after-busy-client.d.ts +34 -0
- package/dist/shared/reset-after-busy-client.d.ts.map +1 -0
- package/dist/shared/single-connection-client.d.ts +1 -1
- package/dist/shared/single-connection-client.d.ts.map +1 -1
- package/dist/storage/db/client.d.ts +2 -0
- package/dist/storage/db/client.d.ts.map +1 -1
- package/dist/storage/db/index.d.ts +14 -3
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/db/run-fencing.d.ts +41 -0
- package/dist/storage/db/run-fencing.d.ts.map +1 -0
- package/dist/storage/db/utils.d.ts +5 -0
- package/dist/storage/db/utils.d.ts.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/knowledge/fixtures/generate-snapshot-dbs.d.mts +2 -0
- package/dist/storage/domains/knowledge/fixtures/generate-snapshot-dbs.d.mts.map +1 -0
- package/dist/storage/domains/knowledge/index.d.ts +19 -3
- package/dist/storage/domains/knowledge/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +24 -7
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/notifications/index.d.ts +8 -0
- package/dist/storage/domains/notifications/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/factory-storage.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- 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/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/write-lock.d.ts +0 -25
- package/dist/vector/write-lock.d.ts.map +1 -1
- package/package.json +16 -15
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
//#region src/knowledge-compat/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Knowledge values that storage adapters bundle instead of importing from `@mastra/core`, so adapters keep
|
|
4
|
+
* the same `@mastra/core` peer range as releases without Knowledge. Adapter tests assert these copies equal
|
|
5
|
+
* the current core exports. Runtime behavior that must come from the
|
|
6
|
+
* installed core (errors, sanitizers) is loaded lazily through {@link createKnowledgeCoreLoader} once core
|
|
7
|
+
* advertises a matching Knowledge storage contract.
|
|
8
|
+
*/
|
|
9
|
+
export declare const KNOWLEDGE_CORE_FEATURE = "knowledge-v2";
|
|
10
|
+
export declare const KNOWLEDGE_STORAGE_CONTRACT_VERSION: 3;
|
|
11
|
+
export declare const KNOWLEDGE_STORAGE_SCHEMA_VERSION: 3;
|
|
12
|
+
/**
|
|
13
|
+
* Marker version pre-release snapshots wrote for the same canonical layout before the version moved past
|
|
14
|
+
* the released v2 contract; adapters rewrite it to {@link KNOWLEDGE_STORAGE_SCHEMA_VERSION} and keep the rows.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PRE_RELEASE_KNOWLEDGE_SCHEMA_VERSION: 1;
|
|
17
|
+
export declare const TABLE_KNOWLEDGE_NODE_SCOPES = "mastra_knowledge_node_scopes";
|
|
18
|
+
export declare const TABLE_KNOWLEDGE_RECORD_SCOPES = "mastra_knowledge_record_scopes";
|
|
19
|
+
export declare const TABLE_KNOWLEDGE_SCOPE_GRANTS = "mastra_knowledge_scope_grants";
|
|
20
|
+
export declare const TABLE_KNOWLEDGE_ACCESS_STATE = "mastra_knowledge_access_state";
|
|
21
|
+
export declare const TABLE_KNOWLEDGE_SCOPE_ADDRESSES = "mastra_knowledge_scope_addresses";
|
|
22
|
+
export declare const TABLE_KNOWLEDGE_NODE_ADDRESSES = "mastra_knowledge_node_addresses";
|
|
23
|
+
export declare const TABLE_KNOWLEDGE_IMPORT_STATE = "mastra_knowledge_import_state";
|
|
24
|
+
export declare const TABLE_KNOWLEDGE_IMPORT_RUNS = "mastra_knowledge_import_runs";
|
|
25
|
+
export declare const TABLE_KNOWLEDGE_PROPOSALS = "mastra_knowledge_proposals";
|
|
26
|
+
export declare const TABLE_KNOWLEDGE_SCHEMA = "mastra_knowledge_schema";
|
|
27
|
+
/** Every table managed by canonical Knowledge storage, in creation order. */
|
|
28
|
+
export declare const KNOWLEDGE_TABLE_NAMES: readonly ["mastra_knowledge_nodes", "mastra_knowledge_records", "mastra_knowledge_mentions", "mastra_knowledge_activity", "mastra_knowledge_semantic_outbox", "mastra_knowledge_node_scopes", "mastra_knowledge_record_scopes", "mastra_knowledge_scope_grants", "mastra_knowledge_access_state", "mastra_knowledge_scope_addresses", "mastra_knowledge_node_addresses", "mastra_knowledge_import_state", "mastra_knowledge_import_runs", "mastra_knowledge_proposals", "mastra_knowledge_schema"];
|
|
29
|
+
/** Knowledge v1 tables with no canonical equivalent; an explicit schema reset drops them. */
|
|
30
|
+
export declare const RETIRED_KNOWLEDGE_TABLE_NAMES: readonly ['mastra_knowledge_cursors'];
|
|
31
|
+
/**
|
|
32
|
+
* Columns of the tables published v1 adapters created for every app, empty unless the app used
|
|
33
|
+
* Knowledge. Every non-retired table must be present with only these columns before an adapter treats
|
|
34
|
+
* the layout as safely replaceable.
|
|
35
|
+
*/
|
|
36
|
+
export declare const PUBLISHED_KNOWLEDGE_V1_COLUMNS: ReadonlyMap<string, readonly string[]>;
|
|
37
|
+
/**
|
|
38
|
+
* True when `columnsByTable` (every Knowledge-prefixed table and its columns) is exactly a published
|
|
39
|
+
* v1 layout: all non-retired v1 tables present, no other tables, and each with only published columns.
|
|
40
|
+
* PostgreSQL adapters also created a `<column>Z` timestamptz shadow beside each timestamp column; pass
|
|
41
|
+
* `timestampShadows` to accept those.
|
|
42
|
+
*/
|
|
43
|
+
export declare function isPublishedKnowledgeV1Layout(columnsByTable: ReadonlyMap<string, readonly string[]>, { timestampShadows }?: {
|
|
44
|
+
timestampShadows?: boolean;
|
|
45
|
+
}): boolean;
|
|
46
|
+
/** Indexes published v1 adapters created on {@link PUBLISHED_KNOWLEDGE_V1_COLUMNS} tables. */
|
|
47
|
+
export declare const PUBLISHED_KNOWLEDGE_V1_INDEX_NAMES: ReadonlySet<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Columns of the Knowledge tables that the first canonical-model release (`@mastra/core` 1.76.0-alpha.3,
|
|
50
|
+
* `@mastra/libsql`/`@mastra/pg` from the same commit) created. That release wrote no schema marker and
|
|
51
|
+
* kept nullable v1 facade columns, so canonical storage cannot open it. Its data is not migrated.
|
|
52
|
+
*/
|
|
53
|
+
export declare const INTERIM_KNOWLEDGE_COLUMNS: ReadonlyMap<string, readonly string[]>;
|
|
54
|
+
/** Indexes the interim release created on {@link INTERIM_KNOWLEDGE_COLUMNS} tables. */
|
|
55
|
+
export declare const INTERIM_KNOWLEDGE_INDEX_NAMES: ReadonlySet<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Every column layout a published interim build created. Snapshots `0.0.0-knowledge-w1-20261008204450`
|
|
58
|
+
* onward match {@link INTERIM_KNOWLEDGE_COLUMNS}. Earlier snapshots kept extra record columns, and
|
|
59
|
+
* `0.0.0-knowledge-w1-20261006001735` also the v1 cursors table. Later builds never dropped those, so a
|
|
60
|
+
* database first initialized by an early snapshot keeps its layout; it only gains the later indexes.
|
|
61
|
+
*/
|
|
62
|
+
export declare const INTERIM_KNOWLEDGE_LAYOUTS: readonly ReadonlyMap<string, readonly string[]>[];
|
|
63
|
+
/**
|
|
64
|
+
* True when `columnsByTable` (every Knowledge-prefixed table and its columns) is exactly one of the
|
|
65
|
+
* {@link INTERIM_KNOWLEDGE_LAYOUTS}: every table present, no other tables, and each with exactly those
|
|
66
|
+
* columns. Pass `timestampShadows` for PostgreSQL, whose adapters add a `<column>Z` timestamptz shadow.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isInterimKnowledgeLayout(columnsByTable: ReadonlyMap<string, readonly string[]>, { timestampShadows }?: {
|
|
69
|
+
timestampShadows?: boolean;
|
|
70
|
+
}): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Index names a replaceable non-canonical layout may carry, or `null` when `columnsByTable` is neither
|
|
73
|
+
* the published v1 layout nor the interim layout.
|
|
74
|
+
*/
|
|
75
|
+
export declare function replaceableKnowledgeLayoutIndexNames(columnsByTable: ReadonlyMap<string, readonly string[]>, options?: {
|
|
76
|
+
timestampShadows?: boolean;
|
|
77
|
+
}): ReadonlySet<string> | null;
|
|
78
|
+
/**
|
|
79
|
+
* The warning to log when replacing a non-canonical layout discards rows, or `null` when it held none.
|
|
80
|
+
* The access-state row is bookkeeping every init writes, so it alone never warrants a warning.
|
|
81
|
+
*/
|
|
82
|
+
export declare function discardedKnowledgeRowsWarning(columnsByTable: ReadonlyMap<string, readonly string[]>, rowCounts: ReadonlyMap<string, number>, options?: {
|
|
83
|
+
timestampShadows?: boolean;
|
|
84
|
+
}): {
|
|
85
|
+
message: string;
|
|
86
|
+
details: {
|
|
87
|
+
layout: 'published-v1' | 'interim';
|
|
88
|
+
discardedRows: Record<string, number>;
|
|
89
|
+
};
|
|
90
|
+
} | null;
|
|
91
|
+
/** Tables a replaceable non-canonical layout may contain. */
|
|
92
|
+
export declare const REPLACEABLE_KNOWLEDGE_TABLE_NAMES: ReadonlySet<string>;
|
|
93
|
+
/** Appended to schema errors so callers learn the one supported way forward. */
|
|
94
|
+
export declare const KNOWLEDGE_RESET_GUIDANCE = "Existing Knowledge data is not migrated. To replace it, call `await storage.stores?.knowledge?.dangerouslyReset()`, which deletes every Knowledge row and nothing else.";
|
|
95
|
+
/** Mirrors `StorageColumn` from `@mastra/core/storage`. */
|
|
96
|
+
export interface KnowledgeStorageColumn {
|
|
97
|
+
type: 'text' | 'timestamp' | 'uuid' | 'jsonb' | 'integer' | 'float' | 'bigint' | 'boolean';
|
|
98
|
+
primaryKey?: boolean;
|
|
99
|
+
nullable?: boolean;
|
|
100
|
+
references?: {
|
|
101
|
+
table: string;
|
|
102
|
+
column: string;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export declare const KNOWLEDGE_NODE_SCOPES_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
106
|
+
export declare const KNOWLEDGE_RECORD_SCOPES_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
107
|
+
export declare const KNOWLEDGE_SCOPE_GRANTS_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
108
|
+
export declare const KNOWLEDGE_ACCESS_STATE_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
109
|
+
export declare const KNOWLEDGE_SCHEMA_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
110
|
+
export declare const KNOWLEDGE_SCOPE_ADDRESSES_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
111
|
+
export declare const KNOWLEDGE_NODE_ADDRESSES_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
112
|
+
export declare const KNOWLEDGE_IMPORT_STATE_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
113
|
+
export declare const KNOWLEDGE_IMPORT_RUNS_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
114
|
+
export declare const KNOWLEDGE_PROPOSALS_SCHEMA: Record<string, KnowledgeStorageColumn>;
|
|
115
|
+
/** Canonicalizes a node UUID. */
|
|
116
|
+
export declare function canonicalizeKnowledgeNodeId(id: string): string;
|
|
117
|
+
/** Canonicalizes a set of scope-node UUIDs. */
|
|
118
|
+
export declare function canonicalizeKnowledgeScopeIds(scopeIds: string[]): string[];
|
|
119
|
+
export declare function knowledgeScopeIdsKey(scopeIds: string[]): string;
|
|
120
|
+
/** Canonicalizes a stored `[source, scope]` importer binding key. */
|
|
121
|
+
export declare function canonicalizeKnowledgeImporterBindingKey(binding: string): string;
|
|
122
|
+
/** Scope nodes are visible through their own identity as well as their direct parent memberships. */
|
|
123
|
+
export declare function isKnowledgeNodeVisible(node: {
|
|
124
|
+
id: string;
|
|
125
|
+
isScope: boolean;
|
|
126
|
+
}, nodeScopeIds: string[], visibleScopeIds: string[]): boolean;
|
|
127
|
+
/** Knowledge runtime values adapters take from the installed `@mastra/core`. */
|
|
128
|
+
export interface KnowledgeCore {
|
|
129
|
+
KnowledgeSchemaError: new (message: string) => Error;
|
|
130
|
+
KnowledgeUnsupportedError: new (adapter?: string) => Error;
|
|
131
|
+
sanitizeKnowledgeImportError(error: unknown): string;
|
|
132
|
+
}
|
|
133
|
+
export declare function assertKnowledgeCoreSupport(features: ReadonlySet<string>): void;
|
|
134
|
+
/**
|
|
135
|
+
* Returns a coalesced loader for core's Knowledge runtime. It rejects cores without the Knowledge feature
|
|
136
|
+
* before importing anything, and retries after a failed import.
|
|
137
|
+
*/
|
|
138
|
+
export declare function createKnowledgeCoreLoader(features: ReadonlySet<string>, loadStorageModule: () => Promise<unknown>): () => Promise<KnowledgeCore>;
|
|
139
|
+
/**
|
|
140
|
+
* Importer claims (mirrors `@mastra/core/storage` so adapters run against any core with Knowledge).
|
|
141
|
+
* A claim is one importer binding's contribution to a node's memberships or a record, stored in that
|
|
142
|
+
* binding's import state and written in the same transaction as the change it describes.
|
|
143
|
+
*/
|
|
144
|
+
export interface KnowledgeImportClaimCompat {
|
|
145
|
+
importerId: string;
|
|
146
|
+
binding: string;
|
|
147
|
+
source: string;
|
|
148
|
+
targetType: 'node' | 'record';
|
|
149
|
+
targetId: string;
|
|
150
|
+
scopeIds: string[];
|
|
151
|
+
version: number;
|
|
152
|
+
}
|
|
153
|
+
export declare function knowledgeImportClaimKey(targetType: 'node' | 'record', targetId: string): string;
|
|
154
|
+
export declare function parseKnowledgeImportClaim(state: {
|
|
155
|
+
importerId: string;
|
|
156
|
+
binding: string;
|
|
157
|
+
key: string;
|
|
158
|
+
value: string;
|
|
159
|
+
}): KnowledgeImportClaimCompat | null;
|
|
160
|
+
export declare function serializeKnowledgeImportClaim(claim: {
|
|
161
|
+
source: string;
|
|
162
|
+
scopeIds: string[];
|
|
163
|
+
version: number;
|
|
164
|
+
}): string;
|
|
165
|
+
/** Memberships after one claimant replaces its claim, keeping what other claims (or no claim) hold. */
|
|
166
|
+
export declare function reconcileKnowledgeClaimScopes(input: {
|
|
167
|
+
current: string[];
|
|
168
|
+
previous: string[];
|
|
169
|
+
next: string[];
|
|
170
|
+
others: string[];
|
|
171
|
+
}): string[];
|
|
172
|
+
/**
|
|
173
|
+
* Version for the scope-less claim a release leaves on a node when no claim from the same importer and source
|
|
174
|
+
* remains, or `null` when one does. While the importer still owned the node, the marker follows the node so a moved
|
|
175
|
+
* or re-added binding can adopt it; after an outside edit it keeps the importer's last version, so the edit is still
|
|
176
|
+
* detected and never becomes importer-owned by being released.
|
|
177
|
+
*/
|
|
178
|
+
export declare function knowledgeReleaseMarkerVersion(released: {
|
|
179
|
+
importerId: string;
|
|
180
|
+
source: string;
|
|
181
|
+
version: number;
|
|
182
|
+
}, remaining: readonly {
|
|
183
|
+
importerId: string;
|
|
184
|
+
source: string;
|
|
185
|
+
}[], versionBefore: number, versionAfter: number): number | null;
|
|
186
|
+
export declare function isSameKnowledgeClaimant(left: {
|
|
187
|
+
importerId: string;
|
|
188
|
+
binding: string;
|
|
189
|
+
}, right: {
|
|
190
|
+
importerId: string;
|
|
191
|
+
binding: string;
|
|
192
|
+
}): boolean;
|
|
193
|
+
/** Most sources one `listSourcesWithVisibleRecords` call may ask about. Mirrors the current core export. */
|
|
194
|
+
export declare const KNOWLEDGE_SOURCE_PROBE_LIMIT = 1000;
|
|
195
|
+
export declare function assertKnowledgeSourceProbeLimit(sources: unknown[]): void;
|
|
196
|
+
/** Most node plus record ids one `listVisibleKnowledgeIds` call may ask about. Mirrors the current core export. */
|
|
197
|
+
export declare const KNOWLEDGE_VISIBILITY_PROBE_LIMIT = 1000;
|
|
198
|
+
export declare function assertKnowledgeVisibilityProbeLimit(input: {
|
|
199
|
+
nodeIds: string[];
|
|
200
|
+
recordIds: string[];
|
|
201
|
+
}): void;
|
|
202
|
+
//#endregion
|
|
203
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
//#region src/memory/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shared rules for observational memory lifecycle writes. Every storage adapter applies
|
|
4
|
+
* these inside its own atomic section (lock, transaction, or conditional update), so the
|
|
5
|
+
* decisions are identical across adapters.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Observational memory columns that lifecycle writes depend on. Storage adapters merge these
|
|
9
|
+
* into the table schema they get from `@mastra/core`, so the columns exist even when the
|
|
10
|
+
* installed core predates them.
|
|
11
|
+
*/
|
|
12
|
+
export declare const OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS: {
|
|
13
|
+
readonly supersededBy: {
|
|
14
|
+
readonly type: 'text';
|
|
15
|
+
readonly nullable: true;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
/** `schema` plus {@link OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS}; `undefined` when `schema` is. */
|
|
19
|
+
export declare function withObservationalMemoryLifecycleColumns<T extends object>(schema: T | undefined): (T & typeof OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS) | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Result of `commitActiveObservations`.
|
|
22
|
+
*/
|
|
23
|
+
export interface UpdateActiveObservationsResult {
|
|
24
|
+
/** Whether the observations were written. */
|
|
25
|
+
applied: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Why nothing was written: `retired` — the target record was superseded by a newer
|
|
28
|
+
* generation; `conflict` — `expectedActiveObservations` no longer matches the stored text.
|
|
29
|
+
*/
|
|
30
|
+
reason?: 'retired' | 'conflict';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Result of `appendBufferedObservations`.
|
|
34
|
+
*
|
|
35
|
+
* The append targets the head generation: when `input.id` was superseded, the chunk is
|
|
36
|
+
* appended to the current head instead. The append is skipped (`persisted: false`) when the
|
|
37
|
+
* head already holds a chunk with the same `cycleId`, or when the chunk is wholly covered by
|
|
38
|
+
* the head's cursor. Chunks carry `lastObservedAt = max message time + 1ms`, so a chunk is
|
|
39
|
+
* wholly covered iff `head.lastObservedAt >= chunk.lastObservedAt - 1ms`.
|
|
40
|
+
*/
|
|
41
|
+
export interface UpdateBufferedObservationsResult {
|
|
42
|
+
/** Whether the chunk was stored. */
|
|
43
|
+
persisted: boolean;
|
|
44
|
+
/** The record the chunk was written to (or would have been written to). */
|
|
45
|
+
recordId: string;
|
|
46
|
+
}
|
|
47
|
+
/** The fields of an observational memory record that decide head order. */
|
|
48
|
+
export interface ObservationalMemoryHeadOrderFields {
|
|
49
|
+
generationCount: number;
|
|
50
|
+
createdAt: Date | string;
|
|
51
|
+
id: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Canonical head order: `generationCount DESC, createdAt ASC, id ASC`.
|
|
55
|
+
* Returns a negative number when `a` sorts before `b` (i.e. `a` is the better head candidate).
|
|
56
|
+
*/
|
|
57
|
+
export declare function compareObservationalMemoryHeadOrder(a: ObservationalMemoryHeadOrderFields, b: ObservationalMemoryHeadOrderFields): number;
|
|
58
|
+
/**
|
|
59
|
+
* A buffered chunk stores `lastObservedAt = max message time + 1ms`. It is wholly covered
|
|
60
|
+
* (every message it observed is already at or before the cursor) iff
|
|
61
|
+
* `cursor >= chunk.lastObservedAt - 1ms`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function isBufferedChunkCoveredByCursor(chunkLastObservedAt: Date | string, cursor: Date | string | null | undefined): boolean;
|
|
64
|
+
/** The later of two cursors; `undefined` only when both are absent. */
|
|
65
|
+
export declare function maxObservationCursor(a: Date | string | null | undefined, b: Date | string | null | undefined): Date | undefined;
|
|
66
|
+
export interface ReflectionTextPlan {
|
|
67
|
+
/** `equal`: stored text equals the snapshot. `append`: observations were appended after the snapshot. */
|
|
68
|
+
mode: 'equal' | 'append';
|
|
69
|
+
observations: string;
|
|
70
|
+
tokenCount: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Decide the new generation's text when a reflection built from `snapshot` commits against
|
|
74
|
+
* the stored record.
|
|
75
|
+
*
|
|
76
|
+
* - Stored text equals the snapshot: the reflection replaces it.
|
|
77
|
+
* - Stored text extends the snapshot (activation only appends): the appended tail is kept
|
|
78
|
+
* after the reflection, and its tokens are added.
|
|
79
|
+
* - Anything else (a non-append rewrite): `null` — the reflection must not be applied.
|
|
80
|
+
*/
|
|
81
|
+
export declare function planReflectionGenerationText(input: {
|
|
82
|
+
storedObservations: string;
|
|
83
|
+
storedObservationTokenCount: number;
|
|
84
|
+
snapshotObservations: string;
|
|
85
|
+
snapshotObservationTokenCount: number;
|
|
86
|
+
reflection: string;
|
|
87
|
+
tokenCount: number;
|
|
88
|
+
}): ReflectionTextPlan | null;
|
|
89
|
+
/**
|
|
90
|
+
* Backs `updateActiveObservations` in adapters that implement `commitActiveObservations`.
|
|
91
|
+
* Callers of `updateActiveObservations` (which resolves `void`) can't see a commit result, so a
|
|
92
|
+
* write that was not applied throws instead of resolving as if it had committed.
|
|
93
|
+
*/
|
|
94
|
+
export declare function assertActiveObservationsApplied(result: UpdateActiveObservationsResult, id: string): void;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the stored text can still accept a reflection built from `snapshot`
|
|
97
|
+
* (equal, or only appended to since).
|
|
98
|
+
*/
|
|
99
|
+
export declare function isAppendOnlySince(storedObservations: string, snapshotObservations: string): boolean;
|
|
100
|
+
//#endregion
|
|
101
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-libsql
|
|
|
3
3
|
description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/libsql"
|
|
6
|
-
version: "0.0.0-knowledge-
|
|
6
|
+
version: "0.0.0-knowledge-studio-20261029065150"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -25,6 +25,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
25
25
|
- [Memory](references/docs-memory-overview.md) - Add memory to Mastra agents with message history, semantic recall, working memory, and observational memory across threads and multi-agent delegation.
|
|
26
26
|
- [Semantic recall](references/docs-memory-semantic-recall.md) - Retrieve relevant messages from past Mastra conversations with semantic recall, vector search, embeddings, metadata filters, and configurable storage.
|
|
27
27
|
- [Working memory](references/docs-memory-working-memory.md) - Persist user profiles, preferences, and application data with Mastra working memory using resource- or thread-scoped templates and storage adapters.
|
|
28
|
+
- [Signals](references/docs-signals-overview.md) - Send asynchronous input into a Mastra agent thread while Mastra manages whether the agent is active or idle.
|
|
28
29
|
- [Storage](references/docs-storage.md) - Configure Mastra storage to persist memory, workflow state, observability data, evals, schedules, and long-running agent state across restarts.
|
|
29
30
|
- [Editor](references/docs-studio-editor.md) - Use Mastra Studio Editor so collaborators can change agent instructions and tools without modifying source code, from draft testing through publication.
|
|
30
31
|
- [Snapshots](references/docs-workflows-snapshots.md) - Store and retrieve Mastra workflow snapshots so suspended executions preserve step results and state and can resume reliably across processes.
|
|
@@ -36,7 +36,7 @@ const deleteTool = createTool({
|
|
|
36
36
|
const agent = new Agent({
|
|
37
37
|
id: 'my-agent',
|
|
38
38
|
name: 'My Agent',
|
|
39
|
-
model: 'openai/gpt-
|
|
39
|
+
model: 'openai/gpt-6-luna',
|
|
40
40
|
tools: { deleteTool },
|
|
41
41
|
})
|
|
42
42
|
|
|
@@ -144,7 +144,8 @@ const stream = await agent.stream('Clean up old records', {
|
|
|
144
144
|
},
|
|
145
145
|
})
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
// A refused question has no probability, so it falls back to requiring approval.
|
|
148
|
+
return (result.answers.requiresApproval.probability ?? 1) >= 0.7
|
|
148
149
|
},
|
|
149
150
|
})
|
|
150
151
|
```
|
|
@@ -178,7 +179,7 @@ const approvedFingerprints = new Set<string>()
|
|
|
178
179
|
export const approvalBoundAgent = new Agent({
|
|
179
180
|
id: 'approval-bound-agent',
|
|
180
181
|
name: 'Approval Bound Agent',
|
|
181
|
-
model: 'openai/gpt-
|
|
182
|
+
model: 'openai/gpt-6.1-sol',
|
|
182
183
|
tools: { issueRefundTool, deleteRecordTool },
|
|
183
184
|
hooks: {
|
|
184
185
|
beforeToolCall: ({ toolName, input }) => {
|
|
@@ -409,6 +410,19 @@ const handleResume = async () => {
|
|
|
409
410
|
}
|
|
410
411
|
```
|
|
411
412
|
|
|
413
|
+
With `generate()`, the result has `finishReason: 'suspended'`. The tool's data from `suspend()` is in `suspendPayload.suspendPayload`. Call `resumeGenerate()` with the `resumeSchema` data and `runId`:
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
const output = await agent.generate("What's the weather in London?")
|
|
417
|
+
|
|
418
|
+
if (output.finishReason === 'suspended') {
|
|
419
|
+
console.log(output.suspendPayload.suspendPayload) // { reason: 'Approval required.' }
|
|
420
|
+
|
|
421
|
+
const resumed = await agent.resumeGenerate({ approved: true }, { runId: output.runId! })
|
|
422
|
+
console.log(resumed.text)
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
412
426
|
When a suspended or approval-gated tool call resumes, the stream emits a `tool-call-resumed` chunk with the same `toolCallId` before the call's `tool-result`. Its `payload.kind` is `'suspension'` or `'approval'`, and the payload repeats the original `args`, `suspendPayload`, and `resumeSchema`. The chunk is only emitted when a real suspension or approval request is cleared.
|
|
413
427
|
|
|
414
428
|
With `@mastra/ai-sdk`, it arrives as a `data-tool-call-suspended` part (or `data-tool-call-approval` part for approvals) with `resumed: true`, which replaces the original part and keeps its payload. Use this signal to mark a question as answered. Don't infer it from the shape of the tool output: when the suspension came from a sub-agent, the output of the delegation call is the sub-agent's result, not your answer.
|
|
@@ -425,7 +439,7 @@ const agent = new Agent({
|
|
|
425
439
|
id: 'my-agent',
|
|
426
440
|
name: 'My Agent',
|
|
427
441
|
instructions: 'You are a helpful assistant',
|
|
428
|
-
model: 'openai/gpt-
|
|
442
|
+
model: 'openai/gpt-6-luna',
|
|
429
443
|
tools: { weatherTool },
|
|
430
444
|
memory: new Memory(),
|
|
431
445
|
defaultOptions: {
|
|
@@ -603,7 +617,7 @@ const dataAgent = new Agent({
|
|
|
603
617
|
id: 'data-agent',
|
|
604
618
|
name: 'Data Agent',
|
|
605
619
|
description: 'Handles database queries and user data retrieval',
|
|
606
|
-
model: 'openai/gpt-
|
|
620
|
+
model: 'openai/gpt-6-luna',
|
|
607
621
|
tools: { findUserTool },
|
|
608
622
|
})
|
|
609
623
|
|
|
@@ -612,7 +626,7 @@ const supervisorAgent = new Agent({
|
|
|
612
626
|
name: 'Supervisor Agent',
|
|
613
627
|
instructions: `You coordinate data retrieval tasks.
|
|
614
628
|
Delegate to data-agent for user lookups.`,
|
|
615
|
-
model: 'openai/gpt-
|
|
629
|
+
model: 'openai/gpt-6.1-sol',
|
|
616
630
|
agents: { dataAgent },
|
|
617
631
|
memory: new Memory(),
|
|
618
632
|
})
|
|
@@ -31,7 +31,7 @@ export const routingAgent = new Agent({
|
|
|
31
31
|
name: 'Routing Agent',
|
|
32
32
|
instructions: `
|
|
33
33
|
You are a network of writers and researchers. The user will ask you to research a topic. Always respond with a complete report—no bullet points. Write in full paragraphs, like a blog post. Do not answer with incomplete or uncertain information.`,
|
|
34
|
-
model: 'openai/gpt-
|
|
34
|
+
model: 'openai/gpt-6.1-sol',
|
|
35
35
|
agents: {
|
|
36
36
|
researchAgent,
|
|
37
37
|
writingAgent,
|
|
@@ -146,7 +146,7 @@ Workers are internal infrastructure. They're not exposed to end users and don't
|
|
|
146
146
|
In a split deployment:
|
|
147
147
|
|
|
148
148
|
- **The API server is the only public-facing process**: It serves all client HTTP requests. These requests include REST endpoints and agent interactions, plus workflow triggers and custom routes.
|
|
149
|
-
- **Workers
|
|
149
|
+
- **Workers don't serve client traffic**: They pull events from the distributed PubSub backend and read/write to the shared storage database. Each worker process also listens on `PORT` (default `4111`) for internal health checks. `/health` reports readiness and `/config` returns the worker configuration to authorized callers. Keep this port on the private network.
|
|
150
150
|
- **The orchestration worker calls the API internally**: It sends step execution requests to the API over the container network using `MASTRA_STEP_EXECUTION_URL`. This is internal service-to-service communication, not a public endpoint.
|
|
151
151
|
|
|
152
152
|
All three worker types (orchestration, scheduler, background task) sit behind the API on a private network. They share access to the PubSub backend and storage database but never receive traffic directly from clients. HTTP routes for worker-related features run on the API server rather than the worker process. One example is creating a token for a voice integration.
|
|
@@ -28,13 +28,15 @@ Retrieves message history and persists new messages.
|
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
30
|
memory: new Memory({
|
|
31
|
-
|
|
31
|
+
options: {
|
|
32
|
+
lastMessages: 10,
|
|
33
|
+
},
|
|
32
34
|
})
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
**Mastra internally:**
|
|
36
38
|
|
|
37
|
-
1. Creates a `MessageHistory` processor with `
|
|
39
|
+
1. Creates a `MessageHistory` processor with `lastMessages: 10`
|
|
38
40
|
2. Adds it to the agent's input processors (runs before the LLM)
|
|
39
41
|
3. Adds it to the agent's output processors (runs after the LLM)
|
|
40
42
|
|
|
@@ -55,13 +57,15 @@ const agent = new Agent({
|
|
|
55
57
|
id: 'test-agent',
|
|
56
58
|
name: 'Test Agent',
|
|
57
59
|
instructions: 'You are a helpful assistant',
|
|
58
|
-
model: 'openai/gpt-
|
|
60
|
+
model: 'openai/gpt-6.1-sol',
|
|
59
61
|
memory: new Memory({
|
|
60
62
|
storage: new LibSQLStore({
|
|
61
63
|
id: 'memory-store',
|
|
62
64
|
url: 'file:memory.db',
|
|
63
65
|
}),
|
|
64
|
-
|
|
66
|
+
options: {
|
|
67
|
+
lastMessages: 10, // MessageHistory processor automatically added
|
|
68
|
+
},
|
|
65
69
|
}),
|
|
66
70
|
})
|
|
67
71
|
```
|
|
@@ -85,7 +89,7 @@ memory: new Memory({
|
|
|
85
89
|
1. Creates a `SemanticRecall` processor
|
|
86
90
|
2. Adds it to the agent's input processors (runs before the LLM)
|
|
87
91
|
3. Adds it to the agent's output processors (runs after the LLM)
|
|
88
|
-
4. Requires
|
|
92
|
+
4. Requires a vector store, plus an embedder unless the vector store generates embeddings itself
|
|
89
93
|
|
|
90
94
|
**What it does:**
|
|
91
95
|
|
|
@@ -105,7 +109,7 @@ import { openai } from '@ai-sdk/openai'
|
|
|
105
109
|
const agent = new Agent({
|
|
106
110
|
name: 'semantic-agent',
|
|
107
111
|
instructions: 'You are a helpful assistant with semantic memory',
|
|
108
|
-
model: 'openai/gpt-
|
|
112
|
+
model: 'openai/gpt-6.1-sol',
|
|
109
113
|
memory: new Memory({
|
|
110
114
|
storage: new LibSQLStore({
|
|
111
115
|
id: 'memory-store',
|
|
@@ -155,7 +159,7 @@ import { openai } from '@ai-sdk/openai'
|
|
|
155
159
|
const agent = new Agent({
|
|
156
160
|
name: 'working-memory-agent',
|
|
157
161
|
instructions: 'You are an assistant with working memory',
|
|
158
|
-
model: 'openai/gpt-
|
|
162
|
+
model: 'openai/gpt-6.1-sol',
|
|
159
163
|
memory: new Memory({
|
|
160
164
|
storage: new LibSQLStore({
|
|
161
165
|
id: 'memory-store',
|
|
@@ -187,10 +191,12 @@ const customMessageHistory = new MessageHistory({
|
|
|
187
191
|
const agent = new Agent({
|
|
188
192
|
name: 'custom-memory-agent',
|
|
189
193
|
instructions: 'You are a helpful assistant',
|
|
190
|
-
model: 'openai/gpt-
|
|
194
|
+
model: 'openai/gpt-6.1-sol',
|
|
191
195
|
memory: new Memory({
|
|
192
196
|
storage: new LibSQLStore({ id: 'memory-store', url: 'file:memory.db' }),
|
|
193
|
-
|
|
197
|
+
options: {
|
|
198
|
+
lastMessages: 10, // This would normally add MessageHistory(10)
|
|
199
|
+
},
|
|
194
200
|
}),
|
|
195
201
|
inputProcessors: [
|
|
196
202
|
customMessageHistory, // Your custom one is used instead
|
|
@@ -258,8 +264,8 @@ const agent = new Agent({
|
|
|
258
264
|
id: 'safe-agent',
|
|
259
265
|
name: 'safe-agent',
|
|
260
266
|
instructions: 'You are a helpful assistant',
|
|
261
|
-
model: 'openai/gpt-
|
|
262
|
-
memory: new Memory({ lastMessages: 10 }),
|
|
267
|
+
model: 'openai/gpt-6.1-sol',
|
|
268
|
+
memory: new Memory({ options: { lastMessages: 10 } }),
|
|
263
269
|
// Your guardrail runs BEFORE memory saves
|
|
264
270
|
outputProcessors: [contentBlocker],
|
|
265
271
|
})
|
|
@@ -298,8 +304,8 @@ const agent = new Agent({
|
|
|
298
304
|
id: 'validated-agent',
|
|
299
305
|
name: 'validated-agent',
|
|
300
306
|
instructions: 'You are a helpful assistant',
|
|
301
|
-
model: 'openai/gpt-
|
|
302
|
-
memory: new Memory({ lastMessages: 10 }),
|
|
307
|
+
model: 'openai/gpt-6.1-sol',
|
|
308
|
+
memory: new Memory({ options: { lastMessages: 10 } }),
|
|
303
309
|
// Your guardrail runs AFTER memory loads history
|
|
304
310
|
inputProcessors: [inputValidator],
|
|
305
311
|
})
|
|
@@ -375,8 +381,8 @@ export const supportAgent = new Agent({
|
|
|
375
381
|
id: 'support-agent',
|
|
376
382
|
name: 'Support agent',
|
|
377
383
|
instructions: 'Answer customer support questions.',
|
|
378
|
-
model: 'openai/gpt-
|
|
379
|
-
memory: new Memory({ lastMessages: 10 }),
|
|
384
|
+
model: 'openai/gpt-6.1-sol',
|
|
385
|
+
memory: new Memory({ options: { lastMessages: 10 } }),
|
|
380
386
|
inputProcessors: [new AttachmentUploader()],
|
|
381
387
|
})
|
|
382
388
|
```
|
|
@@ -10,14 +10,6 @@ You can also retrieve message history to display past conversations in your UI.
|
|
|
10
10
|
|
|
11
11
|
> **Note:** Each message belongs to a thread (the conversation) and a resource (the user or entity it's associated with). See [Threads and resources](#threads-and-resources) for more detail.
|
|
12
12
|
|
|
13
|
-
> **Warning:** When you use memory with a client application, send **only the new message** from the client instead of the full conversation history.
|
|
14
|
-
>
|
|
15
|
-
> Sending the full history is redundant because Mastra loads messages from storage. Mastra filters client-echoed history before loading stored messages and uses the stored copy as the base when message IDs match, preserving stored timestamps and provider metadata while retaining new tool results.
|
|
16
|
-
>
|
|
17
|
-
> If you assemble the request input yourself and need it processed exactly as sent, set `retainFullInput: true` on `memory.options` for that call, or in the memory constructor options to apply it agent-wide. This disables the filtering described above. History still loads underneath. Every input message that isn't already stored is saved to the thread, including few-shot examples.
|
|
18
|
-
>
|
|
19
|
-
> For an AI SDK example, see [Using Mastra Memory](https://mastra.ai/integrations/agentic-ui/ai-sdk-ui).
|
|
20
|
-
|
|
21
13
|
## Threads and resources
|
|
22
14
|
|
|
23
15
|
Mastra organizes conversations using two identifiers:
|
|
@@ -124,7 +116,22 @@ You can use this history in two ways:
|
|
|
124
116
|
- **Automatic inclusion**: Mastra automatically includes recent messages in the context window. The default of 10 messages keeps agents grounded in the conversation. Adjust it with `lastMessages` when needed.
|
|
125
117
|
- [**Manual querying**](#querying): For more control, query threads and messages directly with `recall()`. Use the results to choose which memories enter the context window or to render conversation history in your UI.
|
|
126
118
|
|
|
127
|
-
> **Note:** `lastMessages` counts every stored message, including tool calls, tool results, and [signals](https://mastra.ai/docs/
|
|
119
|
+
> **Note:** `lastMessages` counts every stored message, including tool calls, tool results, and [signals](https://mastra.ai/docs/signals/sending-signals) of any kind, so a single turn can add several messages to the count. The window also slides forward on every request: once a thread grows past the limit, the oldest message leaves context on each turn, which changes the start of the prompt and invalidates the provider prompt cache. For long-running conversations, use [Observational Memory](https://mastra.ai/docs/memory/observational-memory), which keeps the prompt prefix stable.
|
|
120
|
+
|
|
121
|
+
### Sending messages from a client
|
|
122
|
+
|
|
123
|
+
When you use memory with a client application, send **only the new message** instead of the full conversation history. Mastra loads previous messages from storage.
|
|
124
|
+
|
|
125
|
+
For an AI SDK example, see [Using Mastra Memory](https://mastra.ai/integrations/agentic-ui/ai-sdk-ui).
|
|
126
|
+
|
|
127
|
+
<details>
|
|
128
|
+
**Passing a full input history**
|
|
129
|
+
|
|
130
|
+
Mastra filters client-echoed history before loading stored messages. When message IDs match, it uses the stored copy as the base, preserving stored timestamps and provider metadata while retaining new tool results.
|
|
131
|
+
|
|
132
|
+
If you assemble the request input yourself and need it processed exactly as sent, set `retainFullInput: true` on `memory.options` for that call, or in the memory constructor options to apply it agent-wide. This disables input filtering, but stored history still loads. Every input message that isn't already stored is saved to the thread, including few-shot examples.
|
|
133
|
+
|
|
134
|
+
</details>
|
|
128
135
|
|
|
129
136
|
### Limit history by tokens
|
|
130
137
|
|
|
@@ -161,7 +168,7 @@ export const supportAgent = new Agent({
|
|
|
161
168
|
id: 'support-agent',
|
|
162
169
|
name: 'Support agent',
|
|
163
170
|
instructions: 'Answer customer support questions.',
|
|
164
|
-
model: 'openai/gpt-
|
|
171
|
+
model: 'openai/gpt-6.1-sol',
|
|
165
172
|
memory: new Memory({
|
|
166
173
|
options: {
|
|
167
174
|
generateTitle: true,
|
|
@@ -184,7 +191,7 @@ export const supportAgent = new Agent({
|
|
|
184
191
|
id: 'support-agent',
|
|
185
192
|
name: 'Support agent',
|
|
186
193
|
instructions: 'Answer customer support questions.',
|
|
187
|
-
model: 'openai/gpt-
|
|
194
|
+
model: 'openai/gpt-6.1-sol',
|
|
188
195
|
memory: new Memory({
|
|
189
196
|
options: {
|
|
190
197
|
generateTitle: {
|
|
@@ -219,11 +226,11 @@ export const supportAgent = new Agent({
|
|
|
219
226
|
id: 'support-agent',
|
|
220
227
|
name: 'Support agent',
|
|
221
228
|
instructions: 'Answer customer support questions.',
|
|
222
|
-
model: 'openai/gpt-
|
|
229
|
+
model: 'openai/gpt-6.1-sol',
|
|
223
230
|
memory: new Memory({
|
|
224
231
|
options: {
|
|
225
232
|
generateTitle: {
|
|
226
|
-
model: 'openai/gpt-
|
|
233
|
+
model: 'openai/gpt-6-luna',
|
|
227
234
|
instructions: 'Generate a one-word title.',
|
|
228
235
|
},
|
|
229
236
|
},
|
|
@@ -69,7 +69,7 @@ const memory = new Memory({
|
|
|
69
69
|
export const collabAgent = new Agent({
|
|
70
70
|
id: 'collab',
|
|
71
71
|
name: 'CollabAgent',
|
|
72
|
-
model: 'openai/gpt-
|
|
72
|
+
model: 'openai/gpt-6-luna',
|
|
73
73
|
memory,
|
|
74
74
|
instructions: `
|
|
75
75
|
You are a collaborative document assistant. Multiple users talk to you in the SAME thread.
|
|
@@ -158,7 +158,7 @@ const memory = new Memory({
|
|
|
158
158
|
})
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
-
OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`, `@mastra/mongodb`, or `@mastra/oracledb`.
|
|
161
|
+
OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`, `@mastra/mongodb`, `@mastra/mysql`, `@mastra/convex`, or `@mastra/oracledb`.
|
|
162
162
|
|
|
163
163
|
> **Note:** If you switch the Observer to a less capable model and see facts attributed to a generic `User` instead of individual participants, use [`observation.instruction`](https://mastra.ai/reference/memory/observational-memory) to explain how to interpret the `<turn>` tag.
|
|
164
164
|
|