@replayci/replay 0.1.11 → 0.1.13

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.cjs CHANGED
@@ -2578,6 +2578,22 @@ function evaluatePrecondition(precondition, sessionState, currentArguments) {
2578
2578
  detail: `Prior tool output assertion failed: ${assertion.path} \u2014 expected ${JSON.stringify(assertion.equals)}, got ${JSON.stringify(value)}`
2579
2579
  };
2580
2580
  }
2581
+ if (assertion.gte !== void 0) {
2582
+ if (typeof value !== "number" || value < assertion.gte) {
2583
+ return {
2584
+ satisfied: false,
2585
+ detail: `Prior tool output assertion failed: ${assertion.path} \u2014 expected >= ${assertion.gte}, got ${JSON.stringify(value)}`
2586
+ };
2587
+ }
2588
+ }
2589
+ if (assertion.lte !== void 0) {
2590
+ if (typeof value !== "number" || value > assertion.lte) {
2591
+ return {
2592
+ satisfied: false,
2593
+ detail: `Prior tool output assertion failed: ${assertion.path} \u2014 expected <= ${assertion.lte}, got ${JSON.stringify(value)}`
2594
+ };
2595
+ }
2596
+ }
2581
2597
  }
2582
2598
  }
2583
2599
  }
@@ -4081,26 +4097,27 @@ function matchesTool(toolName, filter) {
4081
4097
  if (typeof filter === "string") return filter === toolName;
4082
4098
  return filter.includes(toolName);
4083
4099
  }
4084
- function speculativeCheck(toolName, parsedArgs, aggregates, definitions) {
4100
+ function speculativeCheck(toolName, parsedArgs, aggregates, definitions, bindings) {
4085
4101
  const failures = [];
4086
4102
  for (const def of definitions) {
4087
4103
  if (!matchesTool(toolName, def.tool)) continue;
4088
4104
  const current = aggregates.get(def.name);
4089
4105
  if (!current) continue;
4106
+ const resolved = resolveBounds(def, bindings);
4090
4107
  const currentValue = current.currentValue;
4091
4108
  if (def.metric === "count") {
4092
4109
  const speculative2 = currentValue + 1;
4093
- if (def.lte !== void 0 && speculative2 > def.lte) {
4110
+ if (resolved.lte !== void 0 && speculative2 > resolved.lte) {
4094
4111
  failures.push({
4095
4112
  aggregate: def.name,
4096
4113
  reason: "aggregate_limit_exceeded",
4097
- detail: `${def.reason} (count ${speculative2} > lte ${def.lte})`,
4114
+ detail: `${def.reason} (count ${speculative2} > lte ${resolved.lte})`,
4098
4115
  current: currentValue,
4099
4116
  speculative: speculative2,
4100
- bound: { lte: def.lte }
4117
+ bound: { lte: resolved.lte }
4101
4118
  });
4102
4119
  }
4103
- if (def.gte !== void 0 && speculative2 < def.gte) {
4120
+ if (resolved.gte !== void 0 && speculative2 < resolved.gte) {
4104
4121
  }
4105
4122
  continue;
4106
4123
  }
@@ -4182,21 +4199,21 @@ function speculativeCheck(toolName, parsedArgs, aggregates, definitions) {
4182
4199
  default:
4183
4200
  continue;
4184
4201
  }
4185
- if (def.lte !== void 0 && speculative > def.lte) {
4202
+ if (resolved.lte !== void 0 && speculative > resolved.lte) {
4186
4203
  failures.push({
4187
4204
  aggregate: def.name,
4188
4205
  reason: "aggregate_limit_exceeded",
4189
- detail: `${def.reason} (${def.metric} ${speculative} > lte ${def.lte})`,
4206
+ detail: `${def.reason} (${def.metric} ${speculative} > lte ${resolved.lte})`,
4190
4207
  current: currentValue,
4191
4208
  speculative,
4192
- bound: { lte: def.lte }
4209
+ bound: { lte: resolved.lte }
4193
4210
  });
4194
4211
  }
4195
- if (def.gte !== void 0 && speculative < def.gte) {
4212
+ if (resolved.gte !== void 0 && speculative < resolved.gte) {
4196
4213
  failures.push({
4197
4214
  aggregate: def.name,
4198
4215
  reason: "aggregate_limit_exceeded",
4199
- detail: `${def.reason} (${def.metric} ${speculative} < gte ${def.gte})`,
4216
+ detail: `${def.reason} (${def.metric} ${speculative} < gte ${resolved.gte})`,
4200
4217
  current: currentValue,
4201
4218
  speculative,
4202
4219
  bound: { gte: def.gte }
@@ -4248,6 +4265,34 @@ function commitAggregate(toolName, parsedArgs, aggregates, definitions) {
4248
4265
  }
4249
4266
  return updated;
4250
4267
  }
4268
+ function resolveBounds(def, bindings) {
4269
+ if (!def.when || def.when.length === 0 || !bindings) {
4270
+ return { gte: def.gte, lte: def.lte };
4271
+ }
4272
+ for (const cond of def.when) {
4273
+ const bound = bindings.get(cond.binding);
4274
+ if (!bound) continue;
4275
+ const val = bound.value;
4276
+ if (!matchesCondition(val, cond)) continue;
4277
+ return {
4278
+ gte: cond.then_gte ?? def.gte,
4279
+ lte: cond.then_lte ?? def.lte
4280
+ };
4281
+ }
4282
+ return { gte: def.gte, lte: def.lte };
4283
+ }
4284
+ function matchesCondition(value, cond) {
4285
+ if (cond.equals !== void 0) {
4286
+ if (JSON.stringify(value) !== JSON.stringify(cond.equals)) return false;
4287
+ }
4288
+ if (cond.gte !== void 0) {
4289
+ if (typeof value !== "number" || value < cond.gte) return false;
4290
+ }
4291
+ if (cond.lte !== void 0) {
4292
+ if (typeof value !== "number" || value > cond.lte) return false;
4293
+ }
4294
+ return true;
4295
+ }
4251
4296
 
4252
4297
  // src/envelopes.ts
4253
4298
  function initializeEnvelopes(definitions) {
@@ -6221,7 +6266,7 @@ function replay(client, opts = {}) {
6221
6266
  } catch {
6222
6267
  parsedArgs = {};
6223
6268
  }
6224
- const aggResult = speculativeCheck(tc.name, parsedArgs, workingAggregates, compiledSession.aggregates);
6269
+ const aggResult = speculativeCheck(tc.name, parsedArgs, workingAggregates, compiledSession.aggregates, sessionState.bindings);
6225
6270
  if (!aggResult.passed) {
6226
6271
  for (const f of aggResult.failures) {
6227
6272
  trace.push({
package/dist/index.js CHANGED
@@ -2558,6 +2558,22 @@ function evaluatePrecondition(precondition, sessionState, currentArguments) {
2558
2558
  detail: `Prior tool output assertion failed: ${assertion.path} \u2014 expected ${JSON.stringify(assertion.equals)}, got ${JSON.stringify(value)}`
2559
2559
  };
2560
2560
  }
2561
+ if (assertion.gte !== void 0) {
2562
+ if (typeof value !== "number" || value < assertion.gte) {
2563
+ return {
2564
+ satisfied: false,
2565
+ detail: `Prior tool output assertion failed: ${assertion.path} \u2014 expected >= ${assertion.gte}, got ${JSON.stringify(value)}`
2566
+ };
2567
+ }
2568
+ }
2569
+ if (assertion.lte !== void 0) {
2570
+ if (typeof value !== "number" || value > assertion.lte) {
2571
+ return {
2572
+ satisfied: false,
2573
+ detail: `Prior tool output assertion failed: ${assertion.path} \u2014 expected <= ${assertion.lte}, got ${JSON.stringify(value)}`
2574
+ };
2575
+ }
2576
+ }
2561
2577
  }
2562
2578
  }
2563
2579
  }
@@ -4070,26 +4086,27 @@ function matchesTool(toolName, filter) {
4070
4086
  if (typeof filter === "string") return filter === toolName;
4071
4087
  return filter.includes(toolName);
4072
4088
  }
4073
- function speculativeCheck(toolName, parsedArgs, aggregates, definitions) {
4089
+ function speculativeCheck(toolName, parsedArgs, aggregates, definitions, bindings) {
4074
4090
  const failures = [];
4075
4091
  for (const def of definitions) {
4076
4092
  if (!matchesTool(toolName, def.tool)) continue;
4077
4093
  const current = aggregates.get(def.name);
4078
4094
  if (!current) continue;
4095
+ const resolved = resolveBounds(def, bindings);
4079
4096
  const currentValue = current.currentValue;
4080
4097
  if (def.metric === "count") {
4081
4098
  const speculative2 = currentValue + 1;
4082
- if (def.lte !== void 0 && speculative2 > def.lte) {
4099
+ if (resolved.lte !== void 0 && speculative2 > resolved.lte) {
4083
4100
  failures.push({
4084
4101
  aggregate: def.name,
4085
4102
  reason: "aggregate_limit_exceeded",
4086
- detail: `${def.reason} (count ${speculative2} > lte ${def.lte})`,
4103
+ detail: `${def.reason} (count ${speculative2} > lte ${resolved.lte})`,
4087
4104
  current: currentValue,
4088
4105
  speculative: speculative2,
4089
- bound: { lte: def.lte }
4106
+ bound: { lte: resolved.lte }
4090
4107
  });
4091
4108
  }
4092
- if (def.gte !== void 0 && speculative2 < def.gte) {
4109
+ if (resolved.gte !== void 0 && speculative2 < resolved.gte) {
4093
4110
  }
4094
4111
  continue;
4095
4112
  }
@@ -4171,21 +4188,21 @@ function speculativeCheck(toolName, parsedArgs, aggregates, definitions) {
4171
4188
  default:
4172
4189
  continue;
4173
4190
  }
4174
- if (def.lte !== void 0 && speculative > def.lte) {
4191
+ if (resolved.lte !== void 0 && speculative > resolved.lte) {
4175
4192
  failures.push({
4176
4193
  aggregate: def.name,
4177
4194
  reason: "aggregate_limit_exceeded",
4178
- detail: `${def.reason} (${def.metric} ${speculative} > lte ${def.lte})`,
4195
+ detail: `${def.reason} (${def.metric} ${speculative} > lte ${resolved.lte})`,
4179
4196
  current: currentValue,
4180
4197
  speculative,
4181
- bound: { lte: def.lte }
4198
+ bound: { lte: resolved.lte }
4182
4199
  });
4183
4200
  }
4184
- if (def.gte !== void 0 && speculative < def.gte) {
4201
+ if (resolved.gte !== void 0 && speculative < resolved.gte) {
4185
4202
  failures.push({
4186
4203
  aggregate: def.name,
4187
4204
  reason: "aggregate_limit_exceeded",
4188
- detail: `${def.reason} (${def.metric} ${speculative} < gte ${def.gte})`,
4205
+ detail: `${def.reason} (${def.metric} ${speculative} < gte ${resolved.gte})`,
4189
4206
  current: currentValue,
4190
4207
  speculative,
4191
4208
  bound: { gte: def.gte }
@@ -4237,6 +4254,34 @@ function commitAggregate(toolName, parsedArgs, aggregates, definitions) {
4237
4254
  }
4238
4255
  return updated;
4239
4256
  }
4257
+ function resolveBounds(def, bindings) {
4258
+ if (!def.when || def.when.length === 0 || !bindings) {
4259
+ return { gte: def.gte, lte: def.lte };
4260
+ }
4261
+ for (const cond of def.when) {
4262
+ const bound = bindings.get(cond.binding);
4263
+ if (!bound) continue;
4264
+ const val = bound.value;
4265
+ if (!matchesCondition(val, cond)) continue;
4266
+ return {
4267
+ gte: cond.then_gte ?? def.gte,
4268
+ lte: cond.then_lte ?? def.lte
4269
+ };
4270
+ }
4271
+ return { gte: def.gte, lte: def.lte };
4272
+ }
4273
+ function matchesCondition(value, cond) {
4274
+ if (cond.equals !== void 0) {
4275
+ if (JSON.stringify(value) !== JSON.stringify(cond.equals)) return false;
4276
+ }
4277
+ if (cond.gte !== void 0) {
4278
+ if (typeof value !== "number" || value < cond.gte) return false;
4279
+ }
4280
+ if (cond.lte !== void 0) {
4281
+ if (typeof value !== "number" || value > cond.lte) return false;
4282
+ }
4283
+ return true;
4284
+ }
4240
4285
 
4241
4286
  // src/envelopes.ts
4242
4287
  function initializeEnvelopes(definitions) {
@@ -6212,7 +6257,7 @@ function replay(client, opts = {}) {
6212
6257
  } catch {
6213
6258
  parsedArgs = {};
6214
6259
  }
6215
- const aggResult = speculativeCheck(tc.name, parsedArgs, workingAggregates, compiledSession.aggregates);
6260
+ const aggResult = speculativeCheck(tc.name, parsedArgs, workingAggregates, compiledSession.aggregates, sessionState.bindings);
6216
6261
  if (!aggResult.passed) {
6217
6262
  for (const f of aggResult.failures) {
6218
6263
  trace.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replayci/replay",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "ReplayCI SDK for deterministic tool-call validation and observation.",
5
5
  "license": "ISC",
6
6
  "author": "ReplayCI",