@mastra/pg 1.32.0 → 1.33.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/dist/_types/@internal_core/dist/knowledge-compat/index.d.ts +48 -48
  2. package/dist/_types/@internal_core/dist/memory/index.d.ts +12 -13
  3. package/dist/docs/SKILL.md +1 -1
  4. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  5. package/dist/docs/references/docs-memory-semantic-recall.md +2 -2
  6. package/dist/docs/references/docs-memory-working-memory.md +2 -2
  7. package/dist/docs/references/docs-storage.md +1 -1
  8. package/dist/docs/references/integrations-databases-postgresql.md +1 -1
  9. package/dist/docs/references/reference-memory-memory-class.md +3 -3
  10. package/dist/docs/references/reference-processors-message-history-processor.md +2 -2
  11. package/dist/docs/references/reference-processors-semantic-recall-processor.md +2 -2
  12. package/dist/docs/references/reference-processors-working-memory-processor.md +2 -2
  13. package/dist/docs/references/reference-rag-chunking-and-embedding.md +1 -1
  14. package/dist/docs/references/reference-rag-metadata-filters.md +1 -1
  15. package/dist/docs/references/reference-rag-retrieval.md +13 -13
  16. package/dist/docs/references/reference-storage-retention.md +1 -1
  17. package/dist/docs/references/reference-tools-vector-query-tool.md +1 -1
  18. package/dist/docs/references/reference-vectors-pg.md +1 -1
  19. package/dist/index.cjs +151 -34
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.js +152 -35
  22. package/dist/index.js.map +1 -1
  23. package/dist/storage/domains/observability/v-next/index.d.ts +3 -2
  24. package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
  25. package/dist/storage/domains/observability/v-next/span-query.d.ts +9 -0
  26. package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -1
  27. package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts +7 -1
  28. package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts.map +1 -1
  29. package/dist/storage/domains/workflows/index.d.ts +5 -2
  30. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  31. package/package.json +9 -9
@@ -148,7 +148,7 @@ const queryTool = createVectorQueryTool({
148
148
  indexName: 'documentation',
149
149
  model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
150
150
  reranker: {
151
- model: 'openai/gpt-5.6-sol',
151
+ model: 'openai/gpt-6.1-sol',
152
152
  options: {
153
153
  weights: {
154
154
  semantic: 0.5, // Semantic relevance weight
@@ -412,7 +412,7 @@ export const pgAgent = new Agent({
412
412
  name: 'PG Agent',
413
413
  instructions:
414
414
  'You are an AI agent with the ability to automatically recall memories from previous interactions.',
415
- model: 'openai/gpt-5.6-sol',
415
+ model: 'openai/gpt-6.1-sol',
416
416
  memory: new Memory({
417
417
  storage: new PostgresStore({
418
418
  id: 'pg-agent-storage',
package/dist/index.cjs CHANGED
@@ -20280,7 +20280,12 @@ function afterCursor(plan, values) {
20280
20280
  }
20281
20281
  return `(${terms.join(" OR ")})`;
20282
20282
  }
20283
- function compilePostgresSpanQuery(schema, plan) {
20283
+ /**
20284
+ * The spans `querySpans()` pages through, as a `selected` CTE: the latest completed copy of each
20285
+ * span that starts in the window and matches `where`. `aggregateSpans()` groups the same CTE.
20286
+ * `values` holds the CTEs' parameters; callers append their own.
20287
+ */
20288
+ function compilePostgresSpanSelection(schema, plan) {
20284
20289
  const values = [plan.timeRange.from, plan.timeRange.to];
20285
20290
  const scope = [];
20286
20291
  if (plan.scope) {
@@ -20296,17 +20301,17 @@ function compilePostgresSpanQuery(schema, plan) {
20296
20301
  values: []
20297
20302
  };
20298
20303
  values.push(...predicate.values);
20299
- const after = afterCursor(plan, values);
20300
- values.push(plan.limit + 1);
20301
20304
  const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
20302
20305
  const legacyModelFields = _mastra_core_storage.SPAN_QUERY_FIELD_REGISTRY ? "" : `CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
20303
20306
  CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,`;
20304
20307
  return {
20305
- text: `WITH candidate_ids AS MATERIALIZED (
20308
+ ctes: [
20309
+ `candidate_ids AS MATERIALIZED (
20306
20310
  SELECT DISTINCT ${identities} FROM ${table}
20307
20311
  WHERE "startedAt" >= $1 AND "startedAt" < $2 AND "endedAt" >= $1 AND NOT "isPending"
20308
20312
  ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
20309
- ), current_spans AS MATERIALIZED (
20313
+ )`,
20314
+ `current_spans AS MATERIALIZED (
20310
20315
  SELECT DISTINCT ON (${identities})
20311
20316
  ${fields.map((field) => `"${field}"`).join(", ")}, "startedAt", "endedAt", "cursorId"::text AS version,
20312
20317
  ${legacyModelFields}
@@ -20320,9 +20325,23 @@ function compilePostgresSpanQuery(schema, plan) {
20320
20325
  SELECT "organizationId" IS NULL, COALESCE("organizationId", ''), "resourceId" IS NULL, COALESCE("resourceId", ''), "traceId", "spanId" FROM candidate_ids
20321
20326
  ) ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
20322
20327
  ORDER BY ${identities}, "endedAt" DESC, "cursorId" DESC
20323
- ), candidates AS (
20328
+ )`,
20329
+ `candidates AS (
20324
20330
  SELECT *, CASE WHEN "hasError" THEN 'error' ELSE NULL END AS error FROM current_spans
20325
- )
20331
+ )`,
20332
+ `selected AS (
20333
+ SELECT * FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql})
20334
+ )`
20335
+ ],
20336
+ values
20337
+ };
20338
+ }
20339
+ function compilePostgresSpanQuery(schema, plan) {
20340
+ const { ctes, values } = compilePostgresSpanSelection(schema, plan);
20341
+ const after = afterCursor(plan, values);
20342
+ values.push(plan.limit + 1);
20343
+ return {
20344
+ text: `WITH ${ctes.join(", ")}
20326
20345
  SELECT ${[
20327
20346
  ...fields,
20328
20347
  "startedAt",
@@ -20331,7 +20350,7 @@ function compilePostgresSpanQuery(schema, plan) {
20331
20350
  "status",
20332
20351
  "version"
20333
20352
  ].map((field) => `s."${field}"`).join(", ")}
20334
- FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql}) AND ${after}
20353
+ FROM selected s WHERE ${after}
20335
20354
  ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST, ${identityOrder}
20336
20355
  LIMIT $${values.length}`,
20337
20356
  values
@@ -20665,6 +20684,28 @@ const DIMENSION_SQL = {
20665
20684
  organizationId: "r.\"organizationId\"",
20666
20685
  experimentId: "r.\"experimentId\""
20667
20686
  };
20687
+ /** Span column expressions (alias `r`, a `selected` span row) for each groupable span dimension. */
20688
+ const SPAN_DIMENSION_SQL = Object.fromEntries([
20689
+ "name",
20690
+ "spanType",
20691
+ "entityType",
20692
+ "entityId",
20693
+ "entityName",
20694
+ "parentEntityType",
20695
+ "parentEntityName",
20696
+ "rootEntityType",
20697
+ "rootEntityName",
20698
+ "environment",
20699
+ "status",
20700
+ "serviceName",
20701
+ "executionSource",
20702
+ "threadId",
20703
+ "resourceId",
20704
+ "userId",
20705
+ "sessionId",
20706
+ "organizationId",
20707
+ "experimentId"
20708
+ ].map((field) => [field, `r."${field}"`]));
20668
20709
  const PERCENTILES = {
20669
20710
  "duration.p50": .5,
20670
20711
  "duration.p90": .9,
@@ -20690,16 +20731,43 @@ const COMPARISON_SQL = {
20690
20731
  */
20691
20732
  function compilePostgresTraceAggregate(schema, plan) {
20692
20733
  const { ctes, values } = compilePostgresTraceCandidates(schema, plan, "r.*");
20734
+ return compilePostgresAggregate(schema, plan, {
20735
+ ctes,
20736
+ values,
20737
+ from: "candidates",
20738
+ dimensionSql: (field, param) => {
20739
+ if (field.startsWith("metadata.")) return traceMetadataValueSql(param(field.slice(9)));
20740
+ return lookupDimensionSql(DIMENSION_SQL, field);
20741
+ },
20742
+ usageKey: ["traceId"]
20743
+ });
20744
+ }
20745
+ /**
20746
+ * Compiles a trusted span aggregate plan over the spans `querySpans()` selects. Usage is
20747
+ * attributed by `(traceId, spanId)`, so only the span that recorded a metric row carries it.
20748
+ */
20749
+ function compilePostgresSpanAggregate(schema, plan) {
20750
+ const { ctes, values } = compilePostgresSpanSelection(schema, plan);
20751
+ return compilePostgresAggregate(schema, plan, {
20752
+ ctes,
20753
+ values,
20754
+ from: "selected",
20755
+ dimensionSql: (field) => lookupDimensionSql(SPAN_DIMENSION_SQL, field),
20756
+ usageKey: ["traceId", "spanId"]
20757
+ });
20758
+ }
20759
+ function lookupDimensionSql(columns, field) {
20760
+ const sql = Object.hasOwn(columns, field) ? columns[field] : void 0;
20761
+ if (sql === void 0) throw new Error(`Unsupported trusted aggregate field: ${field}`);
20762
+ return sql;
20763
+ }
20764
+ function compilePostgresAggregate(schema, plan, source) {
20765
+ const { ctes, values } = source;
20693
20766
  const param = (value) => {
20694
20767
  values.push(value);
20695
20768
  return `$${values.length}`;
20696
20769
  };
20697
- const dimensionSql = (field) => {
20698
- if (field.startsWith("metadata.")) return traceMetadataValueSql(param(field.slice(9)));
20699
- const sql = Object.hasOwn(DIMENSION_SQL, field) ? DIMENSION_SQL[field] : void 0;
20700
- if (sql === void 0) throw new Error(`Unsupported trusted trace-aggregate field: ${field}`);
20701
- return sql;
20702
- };
20770
+ const dimensionSql = (field) => source.dimensionSql(field, param);
20703
20771
  const distinctSql = (field) => field === "traceId" ? "r.\"traceId\"" : dimensionSql(field);
20704
20772
  const dimensionColumns = plan.dimensions.map((_, index) => `"d${index}"`);
20705
20773
  const distinctColumns = /* @__PURE__ */ new Map();
@@ -20720,14 +20788,14 @@ function compilePostgresTraceAggregate(schema, plan) {
20720
20788
  const hasCost = measureKinds.has("cost");
20721
20789
  let usageJoin = "";
20722
20790
  if (hasCost || measureKinds.has("tokens")) {
20723
- ctes.push(...compileUsageCtes(schema, plan, param));
20724
- usageJoin = "\n LEFT JOIN usage u ON u.\"traceId\" = r.\"traceId\"";
20791
+ ctes.push(...compileUsageCtes(schema, plan, source, param));
20792
+ usageJoin = `\n LEFT JOIN usage u ON ${source.usageKey.map((key) => `u."${key}" = r."${key}"`).join(" AND ")}`;
20725
20793
  USAGE_METRIC_NAMES.forEach((_, index) => factColumns.push(`CASE WHEN u."traceId" IS NOT NULL THEN COALESCE(u."t${index}", 0) END AS "t${index}"`));
20726
20794
  factColumns.push(`u."traceId" IS NOT NULL AS "usageBearing"`, `CASE WHEN u."priced" THEN u."cost" END AS "traceCost"`, `COALESCE(u."priced" AND NOT u."pricingFailure", FALSE) AS "covered"`, `u."unitMin"`, `u."unitMax"`);
20727
20795
  }
20728
20796
  ctes.push(`facts AS (
20729
20797
  SELECT ${factColumns.join(",\n ")}
20730
- FROM candidates r${usageJoin}
20798
+ FROM ${source.from} r${usageJoin}
20731
20799
  )`);
20732
20800
  const mixedUnitsSql = (alias) => `MIN(${alias}"unitMin" COLLATE "C") <> MAX(${alias}"unitMax" COLLATE "C")`;
20733
20801
  const measureSql = (name, alias = "") => {
@@ -20843,36 +20911,39 @@ function usageMetricIndex(name) {
20843
20911
  return index;
20844
20912
  }
20845
20913
  /**
20846
- * Builds `usage`: one row per candidate trace that has at least one token metric row, holding
20847
- * per-name token sums (`t<i>`, indexed by `TRACE_AGGREGATE_USAGE_METRIC_NAMES`) and the trace's
20848
- * pricing state. Metric rows are matched by traceId, usage metric name, tenant scope, and
20849
- * `timestamp >= from` only: a trace that starts in the window can emit metrics after `to`, and
20850
- * the candidates semi-join already bounds the scan.
20914
+ * Builds `usage`: one row per population row (trace, or span) that has at least one token metric
20915
+ * row, holding per-name token sums (`t<i>`, indexed by `TRACE_AGGREGATE_USAGE_METRIC_NAMES`) and
20916
+ * its pricing state. Metric rows are matched by the source's usage key, usage metric name, tenant
20917
+ * scope, and `timestamp >= from` only: a trace or span that starts in the window can emit metrics
20918
+ * after `to`, and the population semi-join already bounds the scan.
20851
20919
  *
20852
20920
  * Rows are deduplicated on `metricId` alone. The primary key is (`metricId`, `timestamp`)
20853
20921
  * because the table is partitioned by timestamp, so retried copies with different timestamps
20854
20922
  * are both stored.
20855
20923
  */
20856
- function compileUsageCtes(schema, plan, param) {
20924
+ function compileUsageCtes(schema, plan, source, param) {
20925
+ const key = source.usageKey.map((column) => `"${column}"`).join(", ");
20926
+ const metricKey = source.usageKey.map((column) => `m."${column}"`).join(", ");
20857
20927
  const scopeConditions = plan.scope ? [`m."organizationId" = ${param(plan.scope.organizationId)}`, ...plan.scope.resourceId === void 0 ? [] : [`m."resourceId" = ${param(plan.scope.resourceId)}`]] : [];
20858
20928
  const rowConditions = [
20859
- `m."traceId" IN (SELECT "traceId" FROM candidates)`,
20929
+ `${source.usageKey.length === 1 ? metricKey : `(${metricKey})`} IN (SELECT ${key} FROM ${source.from})`,
20860
20930
  `m."name" = ANY(${param(USAGE_METRIC_NAMES)}::text[])`,
20861
20931
  `m."timestamp" >= ${param(plan.timeRange.from)}::timestamptz`,
20862
20932
  ...scopeConditions
20863
20933
  ];
20864
20934
  const costRow = `"name" = ANY(${param(_mastra_core_storage.TRACE_AGGREGATE_COST_METRIC_NAMES)}::text[])`;
20865
- const priced = `${costRow} AND "estimatedCost" IS NOT NULL AND "costUnit" IS NOT NULL AND NOT "hasError"`;
20935
+ const priced = `${costRow} AND "estimatedCost" IS NOT NULL AND "costUnit" IS NOT NULL AND (NOT "hasError" OR "partialCost")`;
20866
20936
  const failed = `${costRow} AND ("hasError" OR ("estimatedCost" IS NOT NULL AND "costUnit" IS NULL))`;
20867
20937
  const tokenColumns = USAGE_METRIC_NAMES.map((name, index) => `SUM("value") FILTER (WHERE "name" = ${param(name)}) AS "t${index}"`);
20868
20938
  return [`usage_rows AS (
20869
- SELECT DISTINCT ON (m."metricId") m."traceId", m."name", m."value", m."estimatedCost", m."costUnit",
20870
- COALESCE(jsonb_typeof(m."costMetadata" -> 'error'), 'null') <> 'null' AS "hasError"
20939
+ SELECT DISTINCT ON (m."metricId") ${metricKey}, m."name", m."value", m."estimatedCost", m."costUnit",
20940
+ COALESCE(jsonb_typeof(m."costMetadata" -> 'error'), 'null') <> 'null' AS "hasError",
20941
+ COALESCE(m."costMetadata" ->> 'error' = 'partial_cost', FALSE) AS "partialCost"
20871
20942
  FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)} m
20872
20943
  WHERE ${rowConditions.join("\n AND ")}
20873
20944
  ORDER BY m."metricId", m."timestamp"
20874
20945
  )`, `usage AS (
20875
- SELECT "traceId",
20946
+ SELECT ${key},
20876
20947
  ${tokenColumns.join(",\n ")},
20877
20948
  SUM("estimatedCost") FILTER (WHERE ${priced}) AS "cost",
20878
20949
  bool_or(${priced}) AS "priced",
@@ -20880,7 +20951,7 @@ function compileUsageCtes(schema, plan, param) {
20880
20951
  MIN("costUnit" COLLATE "C") FILTER (WHERE ${priced}) AS "unitMin",
20881
20952
  MAX("costUnit" COLLATE "C") FILTER (WHERE ${priced}) AS "unitMax"
20882
20953
  FROM usage_rows
20883
- GROUP BY "traceId"
20954
+ GROUP BY ${key}
20884
20955
  )`];
20885
20956
  }
20886
20957
  function nullableNumber(value) {
@@ -20890,7 +20961,12 @@ function toIsoTimestamp(value) {
20890
20961
  return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
20891
20962
  }
20892
20963
  async function aggregateTraces(client, schema, plan, timeoutMs) {
20893
- const compiled = compilePostgresTraceAggregate(schema, plan);
20964
+ return runAggregate(client, plan, compilePostgresTraceAggregate(schema, plan), timeoutMs);
20965
+ }
20966
+ async function aggregateSpans(client, schema, plan, timeoutMs) {
20967
+ return runAggregate(client, plan, compilePostgresSpanAggregate(schema, plan), timeoutMs);
20968
+ }
20969
+ async function runAggregate(client, plan, compiled, timeoutMs) {
20894
20970
  const result = await runWithPostgresTraceQueryTimeout(client, timeoutMs, (transaction) => transaction.any(compiled.text, compiled.values));
20895
20971
  let truncated;
20896
20972
  let resultRows;
@@ -21686,6 +21762,7 @@ async function dangerouslyClearTracing(client, schema) {
21686
21762
  * Use it through `MastraCompositeStore` with a dedicated Postgres connection.
21687
21763
  */
21688
21764
  const spanQueryFeatures = typeof _mastra_core_storage.planSpanQuery === "function" ? ["span-query", "span-query-context-fields"] : [];
21765
+ const spanAggregateFeatures = typeof _mastra_core_storage.planSpanAggregate === "function" ? ["span-aggregate"] : [];
21689
21766
  function wrapError(op, error, details) {
21690
21767
  if (error instanceof _mastra_core_error.MastraError || error instanceof _mastra_core_storage.TraceQueryCursorError || error instanceof _mastra_core_storage.TraceQueryExecutionError || error instanceof _mastra_core_storage.TraceQueryResourceLimitError) throw error;
21691
21768
  throw new _mastra_core_error.MastraError({
@@ -21876,6 +21953,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
21876
21953
  "trace-query",
21877
21954
  "trace-aggregate",
21878
21955
  ...spanQueryFeatures,
21956
+ ...spanAggregateFeatures,
21879
21957
  ...typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
21880
21958
  "trace-query-root-duration",
21881
21959
  "trace-query-discovery",
@@ -21900,6 +21978,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
21900
21978
  "trace-query",
21901
21979
  "trace-aggregate",
21902
21980
  ...spanQueryFeatures,
21981
+ ...spanAggregateFeatures,
21903
21982
  ...typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
21904
21983
  "trace-query-root-duration",
21905
21984
  "trace-query-discovery",
@@ -21964,6 +22043,9 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
21964
22043
  async aggregateTraces(plan) {
21965
22044
  return this.#run("AGGREGATE_TRACES", () => aggregateTraces(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
21966
22045
  }
22046
+ async aggregateSpans(plan) {
22047
+ return this.#run("AGGREGATE_SPANS", () => aggregateSpans(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
22048
+ }
21967
22049
  async getTraceQueryObservedFields(plan) {
21968
22050
  return this.#run("GET_TRACE_QUERY_OBSERVED_FIELDS", () => getTraceQueryObservedFields(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
21969
22051
  }
@@ -25826,7 +25908,10 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
25826
25908
  throw this.#ownershipError("GET_RUN_OWNERSHIP", runId, error);
25827
25909
  }
25828
25910
  }
25829
- async updateWorkflowResults({ workflowName, runId, stepId, result, requestContext, state, fence: explicitFence }) {
25911
+ supportsWorkflowStepGuards() {
25912
+ return true;
25913
+ }
25914
+ async updateWorkflowResults({ workflowName, runId, stepId, result, requestContext, state, fence: explicitFence, startGuard, completionGuard }) {
25830
25915
  const fence = (0, _mastra_core_storage.resolveRunFence)(this, explicitFence, runId);
25831
25916
  try {
25832
25917
  return await this.#db.client.tx(async (t) => {
@@ -25836,16 +25921,48 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
25836
25921
  schemaName: getSchemaName(this.#schema)
25837
25922
  });
25838
25923
  const existingSnapshotResult = await t.oneOrNone(`SELECT snapshot FROM ${tableName} WHERE workflow_name = $1 AND run_id = $2 FOR UPDATE`, [workflowName, runId]);
25839
- if (!existingSnapshotResult) return {};
25924
+ if (!existingSnapshotResult) {
25925
+ (0, _mastra_core_storage.assertWorkflowStepGuard)({
25926
+ snapshot: null,
25927
+ stepId,
25928
+ startGuard,
25929
+ completionGuard
25930
+ });
25931
+ return {};
25932
+ }
25840
25933
  const existingSnapshot = existingSnapshotResult.snapshot;
25841
25934
  const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
25842
- (0, _mastra_core_storage.mergeWorkflowStepResult)({
25935
+ (0, _mastra_core_storage.assertWorkflowStepGuard)({
25936
+ snapshot,
25937
+ stepId,
25938
+ startGuard,
25939
+ completionGuard
25940
+ });
25941
+ if (completionGuard?.pruneOnly) snapshot.context[stepId] = {
25942
+ ...result,
25943
+ metadata: {
25944
+ ...snapshot.context[stepId]?.metadata,
25945
+ ...result.metadata,
25946
+ __continuationStarted: true
25947
+ }
25948
+ };
25949
+ else (0, _mastra_core_storage.mergeWorkflowStepResult)({
25843
25950
  snapshot,
25844
25951
  stepId,
25845
25952
  result,
25846
25953
  requestContext,
25847
25954
  state
25848
25955
  });
25956
+ const previous = startGuard?.previousStep;
25957
+ const previousResult = previous && snapshot.context[previous.stepId];
25958
+ if (previous && previous.stepId !== stepId && previousResult?.status === "success" && previousResult.metadata?.startedBy === previous.eventId) snapshot.context[previous.stepId] = {
25959
+ ...previous.result,
25960
+ metadata: {
25961
+ ...previousResult.metadata,
25962
+ ...previous.result.metadata,
25963
+ __continuationStarted: true
25964
+ }
25965
+ };
25849
25966
  const now = /* @__PURE__ */ new Date();
25850
25967
  const sanitizedSnapshot = toPgJson(snapshot);
25851
25968
  await t.none(`INSERT INTO ${tableName}
@@ -25864,7 +25981,7 @@ var WorkflowsPG = class WorkflowsPG extends _mastra_core_storage.WorkflowsStorag
25864
25981
  return snapshot.context;
25865
25982
  });
25866
25983
  } catch (error) {
25867
- if ((0, _mastra_core_storage.isRunFenceConflictError)(error)) throw error;
25984
+ if ((0, _mastra_core_storage.isRunFenceConflictError)(error) || (0, _mastra_core_storage.isWorkflowStepConflictError)(error)) throw error;
25868
25985
  throw new _mastra_core_error.MastraError({
25869
25986
  id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
25870
25987
  domain: _mastra_core_error.ErrorDomain.STORAGE,