@mastra/spanner 1.6.2-alpha.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3650,8 +3650,11 @@ var DatasetsSpanner = class DatasetsSpanner extends DatasetsStorage {
3650
3650
  if (args.datasetVersion !== void 0) {
3651
3651
  sql = `SELECT * FROM ${tableName}
3652
3652
  WHERE ${quoteIdent("id", "column name")} = @id
3653
- AND ${quoteIdent("datasetVersion", "column name")} = @datasetVersion
3654
- AND ${quoteIdent("isDeleted", "column name")} = FALSE LIMIT 1`;
3653
+ AND ${quoteIdent("datasetVersion", "column name")} <= @datasetVersion
3654
+ AND (${quoteIdent("validTo", "column name")} IS NULL OR ${quoteIdent("validTo", "column name")} > @datasetVersion)
3655
+ AND ${quoteIdent("isDeleted", "column name")} = FALSE
3656
+ ORDER BY ${quoteIdent("datasetVersion", "column name")} DESC
3657
+ LIMIT 1`;
3655
3658
  params.datasetVersion = args.datasetVersion;
3656
3659
  } else sql = `SELECT * FROM ${tableName}
3657
3660
  WHERE ${quoteIdent("id", "column name")} = @id
@@ -3982,8 +3985,9 @@ function rowToExperiment(row) {
3982
3985
  datasetVersion: t.datasetVersion == null ? null : Number(t.datasetVersion),
3983
3986
  organizationId: t.organizationId ?? null,
3984
3987
  projectId: t.projectId ?? null,
3985
- targetType: t.targetType,
3986
- targetId: String(t.targetId),
3988
+ targetType: t.targetType ?? null,
3989
+ targetId: t.targetId == null ? null : String(t.targetId),
3990
+ scorerIds: t.scorerIds ?? null,
3987
3991
  status: t.status,
3988
3992
  totalItems: Number(t.totalItems ?? 0),
3989
3993
  succeededCount: Number(t.succeededCount ?? 0),
@@ -4015,6 +4019,7 @@ function rowToExperimentResult(row) {
4015
4019
  startedAt: toDate(t.startedAt),
4016
4020
  completedAt: toDate(t.completedAt),
4017
4021
  retryCount: Number(t.retryCount ?? 0),
4022
+ attempt: t.attempt == null ? 0 : Number(t.attempt),
4018
4023
  traceId: t.traceId ?? null,
4019
4024
  status: t.status ?? null,
4020
4025
  tags: t.tags ?? null,
@@ -4067,7 +4072,8 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4067
4072
  "experimentSetId",
4068
4073
  "comparisonId",
4069
4074
  "variantId",
4070
- "trialIndex"
4075
+ "trialIndex",
4076
+ "scorerIds"
4071
4077
  ]
4072
4078
  });
4073
4079
  await this.db.alterTable({
@@ -4076,7 +4082,8 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4076
4082
  ifNotExists: [
4077
4083
  "comment",
4078
4084
  "organizationId",
4079
- "projectId"
4085
+ "projectId",
4086
+ "attempt"
4080
4087
  ]
4081
4088
  });
4082
4089
  await this.createDefaultIndexes();
@@ -4105,9 +4112,13 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4105
4112
  columns: ["experimentId", "startedAt"]
4106
4113
  },
4107
4114
  {
4108
- name: "mastra_experiment_results_exp_item_idx",
4115
+ name: "mastra_experiment_results_exp_item_attempt_idx",
4109
4116
  table: TABLE_EXPERIMENT_RESULTS,
4110
- columns: ["experimentId", "itemId"],
4117
+ columns: [
4118
+ "experimentId",
4119
+ "itemId",
4120
+ "attempt"
4121
+ ],
4111
4122
  unique: true
4112
4123
  },
4113
4124
  {
@@ -4124,6 +4135,7 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4124
4135
  }
4125
4136
  async createDefaultIndexes() {
4126
4137
  if (this.skipDefaultIndexes) return;
4138
+ await this.db.dropIndex("mastra_experiment_results_exp_item_idx").catch(() => {});
4127
4139
  await this.db.createIndexes(this.getDefaultIndexDefinitions());
4128
4140
  }
4129
4141
  async createCustomIndexes() {
@@ -4153,8 +4165,9 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4153
4165
  datasetVersion: input.datasetVersion ?? null,
4154
4166
  organizationId: input.organizationId ?? null,
4155
4167
  projectId: input.projectId ?? null,
4156
- targetType: input.targetType,
4157
- targetId: input.targetId,
4168
+ targetType: input.targetType ?? null,
4169
+ targetId: input.targetId ?? null,
4170
+ scorerIds: input.scorerIds ?? null,
4158
4171
  status: "pending",
4159
4172
  totalItems: input.totalItems,
4160
4173
  succeededCount: 0,
@@ -4185,6 +4198,7 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4185
4198
  projectId: experiment.projectId,
4186
4199
  targetType: experiment.targetType,
4187
4200
  targetId: experiment.targetId,
4201
+ scorerIds: experiment.scorerIds,
4188
4202
  status: experiment.status,
4189
4203
  totalItems: experiment.totalItems,
4190
4204
  succeededCount: 0,
@@ -4464,6 +4478,7 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4464
4478
  startedAt: input.startedAt,
4465
4479
  completedAt: input.completedAt,
4466
4480
  retryCount: input.retryCount,
4481
+ attempt: input.attempt ?? 0,
4467
4482
  traceId: input.traceId ?? null,
4468
4483
  status: input.status ?? null,
4469
4484
  tags: input.tags ?? null,
@@ -4486,6 +4501,7 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4486
4501
  startedAt: result.startedAt,
4487
4502
  completedAt: result.completedAt,
4488
4503
  retryCount: result.retryCount,
4504
+ attempt: result.attempt,
4489
4505
  traceId: result.traceId,
4490
4506
  status: result.status,
4491
4507
  tags: result.tags,
@@ -4506,6 +4522,116 @@ var ExperimentsSpanner = class ExperimentsSpanner extends ExperimentsStorage {
4506
4522
  }, error);
4507
4523
  }
4508
4524
  }
4525
+ async upsertExperimentResult(input) {
4526
+ try {
4527
+ const attempt = input.attempt ?? 0;
4528
+ const [rows] = await this.database.run({
4529
+ sql: `SELECT ${quoteIdent("id", "column name")} FROM ${quoteIdent(TABLE_EXPERIMENT_RESULTS, "table name")}
4530
+ WHERE ${quoteIdent("experimentId", "column name")} = @experimentId
4531
+ AND ${quoteIdent("itemId", "column name")} = @itemId
4532
+ AND COALESCE(${quoteIdent("attempt", "column name")}, 0) = @attempt`,
4533
+ params: {
4534
+ experimentId: input.experimentId,
4535
+ itemId: input.itemId,
4536
+ attempt
4537
+ },
4538
+ json: true
4539
+ });
4540
+ let existingId = rows[0]?.id;
4541
+ if (!existingId) try {
4542
+ return await this.addExperimentResult({
4543
+ ...input,
4544
+ attempt
4545
+ });
4546
+ } catch (insertError) {
4547
+ if (!hasErrorCode(insertError, /* @__PURE__ */ new Set([6]))) throw insertError;
4548
+ const [winnerRows] = await this.database.run({
4549
+ sql: `SELECT ${quoteIdent("id", "column name")} FROM ${quoteIdent(TABLE_EXPERIMENT_RESULTS, "table name")}
4550
+ WHERE ${quoteIdent("experimentId", "column name")} = @experimentId
4551
+ AND ${quoteIdent("itemId", "column name")} = @itemId
4552
+ AND COALESCE(${quoteIdent("attempt", "column name")}, 0) = @attempt`,
4553
+ params: {
4554
+ experimentId: input.experimentId,
4555
+ itemId: input.itemId,
4556
+ attempt
4557
+ },
4558
+ json: true
4559
+ });
4560
+ existingId = winnerRows[0]?.id;
4561
+ if (!existingId) throw insertError;
4562
+ }
4563
+ await this.db.runDml({
4564
+ sql: `UPDATE ${quoteIdent(TABLE_EXPERIMENT_RESULTS, "table name")} SET
4565
+ ${quoteIdent("itemDatasetVersion", "column name")} = @itemDatasetVersion,
4566
+ ${quoteIdent("organizationId", "column name")} = @organizationId,
4567
+ ${quoteIdent("projectId", "column name")} = @projectId,
4568
+ ${quoteIdent("input", "column name")} = @input,
4569
+ ${quoteIdent("output", "column name")} = @output,
4570
+ ${quoteIdent("groundTruth", "column name")} = @groundTruth,
4571
+ ${quoteIdent("error", "column name")} = @error,
4572
+ ${quoteIdent("startedAt", "column name")} = @startedAt,
4573
+ ${quoteIdent("completedAt", "column name")} = @completedAt,
4574
+ ${quoteIdent("retryCount", "column name")} = @retryCount,
4575
+ ${quoteIdent("attempt", "column name")} = @attempt,
4576
+ ${quoteIdent("traceId", "column name")} = @traceId,
4577
+ ${quoteIdent("status", "column name")} = @status,
4578
+ ${quoteIdent("tags", "column name")} = @tags,
4579
+ ${quoteIdent("toolMockReport", "column name")} = @toolMockReport
4580
+ WHERE ${quoteIdent("id", "column name")} = @id`,
4581
+ params: {
4582
+ id: existingId,
4583
+ itemDatasetVersion: input.itemDatasetVersion ?? null,
4584
+ organizationId: input.organizationId ?? null,
4585
+ projectId: input.projectId ?? null,
4586
+ input: JSON.stringify(input.input),
4587
+ output: input.output == null ? null : JSON.stringify(input.output),
4588
+ groundTruth: input.groundTruth == null ? null : JSON.stringify(input.groundTruth),
4589
+ error: input.error == null ? null : JSON.stringify(input.error),
4590
+ startedAt: input.startedAt,
4591
+ completedAt: input.completedAt,
4592
+ retryCount: input.retryCount,
4593
+ attempt,
4594
+ traceId: input.traceId ?? null,
4595
+ status: input.status ?? null,
4596
+ tags: input.tags == null ? null : JSON.stringify(input.tags),
4597
+ toolMockReport: input.toolMockReport == null ? null : JSON.stringify(input.toolMockReport)
4598
+ },
4599
+ types: {
4600
+ itemDatasetVersion: "int64",
4601
+ organizationId: "string",
4602
+ projectId: "string",
4603
+ input: "json",
4604
+ output: "json",
4605
+ groundTruth: "json",
4606
+ error: "json",
4607
+ traceId: "string",
4608
+ status: "string",
4609
+ tags: "json",
4610
+ toolMockReport: "json"
4611
+ }
4612
+ });
4613
+ const updated = await this.getExperimentResultById({ id: existingId });
4614
+ if (!updated) throw new MastraError({
4615
+ id: createStorageErrorId("SPANNER", "UPSERT_EXPERIMENT_RESULT", "NOT_FOUND"),
4616
+ domain: ErrorDomain.STORAGE,
4617
+ category: ErrorCategory.USER,
4618
+ text: `Experiment result ${existingId} not found after upsert`,
4619
+ details: { id: existingId }
4620
+ });
4621
+ return updated;
4622
+ } catch (error) {
4623
+ if (error instanceof MastraError) throw error;
4624
+ throw new MastraError({
4625
+ id: createStorageErrorId("SPANNER", "UPSERT_EXPERIMENT_RESULT", "FAILED"),
4626
+ domain: ErrorDomain.STORAGE,
4627
+ category: ErrorCategory.THIRD_PARTY,
4628
+ details: {
4629
+ experimentId: input.experimentId,
4630
+ itemId: input.itemId
4631
+ }
4632
+ }, error);
4633
+ }
4634
+ }
4509
4635
  async updateExperimentResult(input) {
4510
4636
  try {
4511
4637
  if (input.status === void 0 && input.tags === void 0 && input.comment === void 0) {
@@ -10799,9 +10925,10 @@ var ScoresSpanner = class ScoresSpanner extends ScoresStorage {
10799
10925
  }, error);
10800
10926
  }
10801
10927
  try {
10802
- const scoreId = randomUUID();
10928
+ const suppliedId = validatedScore.id;
10929
+ const scoreId = suppliedId ?? randomUUID();
10803
10930
  const now = /* @__PURE__ */ new Date();
10804
- const { scorer, preprocessStepResult, analyzeStepResult, metadata, input, output, additionalContext, requestContext, entity, ...rest } = validatedScore;
10931
+ const { id: _suppliedId, scorer, preprocessStepResult, analyzeStepResult, metadata, input, output, additionalContext, requestContext, entity, ...rest } = validatedScore;
10805
10932
  const insertedRecord = {
10806
10933
  id: scoreId,
10807
10934
  ...rest,
@@ -10817,7 +10944,11 @@ var ScoresSpanner = class ScoresSpanner extends ScoresStorage {
10817
10944
  createdAt: now,
10818
10945
  updatedAt: now
10819
10946
  };
10820
- await this.db.insert({
10947
+ if (suppliedId) await this.db.upsert({
10948
+ tableName: TABLE_SCORERS,
10949
+ record: insertedRecord
10950
+ });
10951
+ else await this.db.insert({
10821
10952
  tableName: TABLE_SCORERS,
10822
10953
  record: insertedRecord
10823
10954
  });