@mastra/pg 1.32.0-alpha.3 → 1.32.0-alpha.5
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/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-semantic-recall.md +20 -0
- package/dist/docs/references/reference-memory-memory-class.md +2 -0
- package/dist/index.cjs +36 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36 -16
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +10 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/docs/SKILL.md
CHANGED
|
@@ -405,6 +405,26 @@ Multilingual E5 produces 1024-dimensional vectors. Your vector index must be cre
|
|
|
405
405
|
|
|
406
406
|
FastEmbed models embed at most 512 tokens per input (roughly 2,000 to 2,500 characters of English text). Longer inputs are truncated, so text past the limit doesn't affect the embedding and can't be found by semantic recall. The AI SDK v3 FastEmbed models return a warning when this happens. The legacy v1 and v2 models don't. If you embed long documents with FastEmbed, chunk them to fit the window, for example with `maxSize: 1500` in `MDocument.chunk()`.
|
|
407
407
|
|
|
408
|
+
### Setting the embedding dimension
|
|
409
|
+
|
|
410
|
+
To name the vector index, Memory needs the embedder's output dimension. By default it finds the dimension by embedding a short probe string the first time semantic recall is set up, once per `Memory` instance. If you already know the dimension, set `embeddingDimension`. Memory then skips the probe, so startup makes no embedding call and doesn't depend on the embedding provider being reachable:
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
import { Memory } from '@mastra/memory'
|
|
414
|
+
|
|
415
|
+
const memory = new Memory({
|
|
416
|
+
embedder: 'openai/text-embedding-3-small',
|
|
417
|
+
embeddingDimension: 1536,
|
|
418
|
+
options: {
|
|
419
|
+
semanticRecall: true,
|
|
420
|
+
},
|
|
421
|
+
})
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
The index name is the same whether the dimension is configured or probed, so existing indexes keep working.
|
|
425
|
+
|
|
426
|
+
The value must match the vectors the embedder returns. Memory compares it with the first real embedding, and on a mismatch it throws a `MASTRA_MEMORY_EMBEDDING_DIMENSION_MISMATCH` error naming both values before creating or querying any index. Update `embeddingDimension` whenever you change the embedding model or its output dimension.
|
|
427
|
+
|
|
408
428
|
## PostgreSQL index optimization
|
|
409
429
|
|
|
410
430
|
When using PostgreSQL as your vector store, you can optimize semantic recall performance by configuring the vector index. This is particularly important for large-scale deployments with thousands of messages.
|
|
@@ -37,6 +37,8 @@ export const agent = new Agent({
|
|
|
37
37
|
|
|
38
38
|
**embedder** (`EmbeddingModel<string> | EmbeddingModelV2<string>`): Embedder instance for vector embeddings. Required when semantic recall is enabled.
|
|
39
39
|
|
|
40
|
+
**embeddingDimension** (`number`): Output dimension of the embedder, as a positive integer. When set, Memory uses it to name the semantic recall index instead of embedding a probe string on first use. It must match the vectors the embedder returns: a mismatch throws a MASTRA\_MEMORY\_EMBEDDING\_DIMENSION\_MISMATCH error before any index is created. See Setting the embedding dimension.
|
|
41
|
+
|
|
40
42
|
**options** (`MemoryConfig`): Memory configuration options.
|
|
41
43
|
|
|
42
44
|
**options.lastMessages** (`number | false`): Number of most recent messages to include in context. Set to false to disable the message history feature entirely (messages are not loaded into context or saved). Use Number.MAX\_SAFE\_INTEGER to retrieve all messages with no limit. To load messages without saving new ones, use the readOnly option. The window slides forward on every request, so once a thread exceeds the limit, each turn invalidates the provider prompt cache. For long-running conversations, use Observational Memory instead.
|
package/dist/index.cjs
CHANGED
|
@@ -19211,7 +19211,26 @@ async function getScorePercentiles(client, schema, args) {
|
|
|
19211
19211
|
const TRACE_STATUS_SQL = `CASE WHEN r."error" IS NOT NULL THEN 'error' ELSE 'success' END`;
|
|
19212
19212
|
/** Core versions without the field reject it in strict query results, so it is only returned when core knows it. */
|
|
19213
19213
|
const timeToFirstChunkSupported = "timeToFirstChunkMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
19214
|
-
|
|
19214
|
+
/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
|
|
19215
|
+
const timeToFirstChunkSortSupported = _mastra_core_storage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstChunkMs") === true;
|
|
19216
|
+
const timeToFirstChunkFeatures = [...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [], ...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : []];
|
|
19217
|
+
/**
|
|
19218
|
+
* Keyset bounds for a cursor's sort value: terms for rows strictly past it in `direction`, and the
|
|
19219
|
+
* condition for rows level with it. Empty values sort last in both directions, so they are past
|
|
19220
|
+
* every value and level only with each other.
|
|
19221
|
+
*/
|
|
19222
|
+
function keysetSortBounds(field, direction, sortValue, values) {
|
|
19223
|
+
if (sortValue === null) return {
|
|
19224
|
+
past: [],
|
|
19225
|
+
level: `${field} IS NULL`
|
|
19226
|
+
};
|
|
19227
|
+
values.push(sortValue);
|
|
19228
|
+
const parameter = `$${values.length}::${typeof sortValue === "number" ? "float8" : "timestamptz"}`;
|
|
19229
|
+
return {
|
|
19230
|
+
past: [`${field} ${direction === "asc" ? ">" : "<"} ${parameter}`, `${field} IS NULL`],
|
|
19231
|
+
level: `${field} = ${parameter}`
|
|
19232
|
+
};
|
|
19233
|
+
}
|
|
19215
19234
|
function durationMsSql(startedAt, endedAt) {
|
|
19216
19235
|
return `EXTRACT(EPOCH FROM (${endedAt} - ${startedAt}))::numeric * 1000`;
|
|
19217
19236
|
}
|
|
@@ -19227,6 +19246,7 @@ const TRACE_FIELDS = {
|
|
|
19227
19246
|
endedAt: "r.\"endedAt\"",
|
|
19228
19247
|
durationMs: durationMsSql("r.\"startedAt\"", "r.\"endedAt\""),
|
|
19229
19248
|
timeToFirstChunkMs: "r.\"timeToFirstChunkMs\"",
|
|
19249
|
+
entityId: "r.\"entityId\"",
|
|
19230
19250
|
entityName: "r.\"entityName\"",
|
|
19231
19251
|
entityType: "r.\"entityType\"",
|
|
19232
19252
|
name: "r.\"name\"",
|
|
@@ -19528,6 +19548,7 @@ const ROOT_PUSHDOWN_FIELDS = /* @__PURE__ */ new Set([
|
|
|
19528
19548
|
"organizationId",
|
|
19529
19549
|
"startedAt",
|
|
19530
19550
|
"endedAt",
|
|
19551
|
+
"entityId",
|
|
19531
19552
|
"entityName",
|
|
19532
19553
|
"entityType",
|
|
19533
19554
|
"name",
|
|
@@ -19803,8 +19824,8 @@ LIMIT $${values.length}`,
|
|
|
19803
19824
|
values
|
|
19804
19825
|
};
|
|
19805
19826
|
}
|
|
19806
|
-
const orderField = plan.orderBy.field
|
|
19807
|
-
const direction = plan.orderBy.direction === "asc" ? "ASC" : "DESC"
|
|
19827
|
+
const orderField = `"${plan.orderBy.field}"`;
|
|
19828
|
+
const direction = `${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST`;
|
|
19808
19829
|
if (plan.paginationMode === "page") {
|
|
19809
19830
|
values.push(plan.perPage, plan.page * plan.perPage);
|
|
19810
19831
|
return {
|
|
@@ -19818,10 +19839,9 @@ LIMIT $${values.length - 1} OFFSET $${values.length}`,
|
|
|
19818
19839
|
}
|
|
19819
19840
|
let pageCondition = "";
|
|
19820
19841
|
if (plan.cursor) {
|
|
19821
|
-
const
|
|
19822
|
-
|
|
19823
|
-
pageCondition = `WHERE (${
|
|
19824
|
-
values.push(plan.cursor.sortValue, plan.cursor.traceId);
|
|
19842
|
+
const { past, level } = keysetSortBounds(orderField, plan.orderBy.direction, plan.cursor.sortValue, values);
|
|
19843
|
+
values.push(plan.cursor.traceId);
|
|
19844
|
+
pageCondition = `WHERE (${[...past, `(${level} AND "traceId" > $${values.length})`].join(" OR ")})`;
|
|
19825
19845
|
}
|
|
19826
19846
|
values.push(plan.limit + 1);
|
|
19827
19847
|
return {
|
|
@@ -20154,7 +20174,7 @@ async function queryTraces(client, schema, plan, timeoutMs) {
|
|
|
20154
20174
|
traces,
|
|
20155
20175
|
page: { next: rows.length > plan.limit && last ? _mastra_core_storage.encodeTraceQueryCursor(plan, {
|
|
20156
20176
|
result: "traces",
|
|
20157
|
-
sortValue: last[plan.orderBy.field],
|
|
20177
|
+
sortValue: last[plan.orderBy.field] ?? null,
|
|
20158
20178
|
traceId: last.traceId
|
|
20159
20179
|
}) : null }
|
|
20160
20180
|
});
|
|
@@ -20226,11 +20246,8 @@ function selectedKeys(rows, values) {
|
|
|
20226
20246
|
function afterCursor(plan, values) {
|
|
20227
20247
|
if (!plan.cursor) return "TRUE";
|
|
20228
20248
|
const cursor = plan.cursor;
|
|
20229
|
-
|
|
20230
|
-
const
|
|
20231
|
-
const field = `s."${plan.orderBy.field}"`;
|
|
20232
|
-
const terms = [`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${timestamp}`];
|
|
20233
|
-
const equal = [`${field} = ${timestamp}`];
|
|
20249
|
+
const { past: terms, level } = keysetSortBounds(`s."${plan.orderBy.field}"`, plan.orderBy.direction, cursor.sortValue, values);
|
|
20250
|
+
const equal = [level];
|
|
20234
20251
|
for (const key of identityFields) {
|
|
20235
20252
|
const ref = `s."${key}" COLLATE "C"`;
|
|
20236
20253
|
const value = cursor[key];
|
|
@@ -20296,7 +20313,7 @@ function compilePostgresSpanQuery(schema, plan) {
|
|
|
20296
20313
|
"version"
|
|
20297
20314
|
].map((field) => `s."${field}"`).join(", ")}
|
|
20298
20315
|
FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql}) AND ${after}
|
|
20299
|
-
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"}, ${identityOrder}
|
|
20316
|
+
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST, ${identityOrder}
|
|
20300
20317
|
LIMIT $${values.length}`,
|
|
20301
20318
|
values
|
|
20302
20319
|
};
|
|
@@ -20617,6 +20634,7 @@ const DIMENSION_SQL = {
|
|
|
20617
20634
|
entityName: "r.\"entityName\"",
|
|
20618
20635
|
name: "r.\"name\"",
|
|
20619
20636
|
spanType: "r.\"spanType\"",
|
|
20637
|
+
entityId: "r.\"entityId\"",
|
|
20620
20638
|
environment: "r.\"environment\"",
|
|
20621
20639
|
status: TRACE_STATUS_SQL,
|
|
20622
20640
|
serviceName: "r.\"serviceName\"",
|
|
@@ -21851,7 +21869,8 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21851
21869
|
"feedback",
|
|
21852
21870
|
"trace-query-context-ids",
|
|
21853
21871
|
...timeToFirstChunkFeatures,
|
|
21854
|
-
"trace-query-root-span-fields"
|
|
21872
|
+
"trace-query-root-span-fields",
|
|
21873
|
+
"trace-query-root-entity-id"
|
|
21855
21874
|
];
|
|
21856
21875
|
return [
|
|
21857
21876
|
"metrics",
|
|
@@ -21874,7 +21893,8 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21874
21893
|
"feedback",
|
|
21875
21894
|
"trace-query-context-ids",
|
|
21876
21895
|
...timeToFirstChunkFeatures,
|
|
21877
|
-
"trace-query-root-span-fields"
|
|
21896
|
+
"trace-query-root-span-fields",
|
|
21897
|
+
"trace-query-root-entity-id"
|
|
21878
21898
|
];
|
|
21879
21899
|
}
|
|
21880
21900
|
async #run(op, fn, details) {
|