@attest-ai/core 1.0.0-rc.3 → 1.0.0-rc.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/esm/index.js CHANGED
@@ -219,8 +219,8 @@ function extractId(response) {
219
219
  }
220
220
 
221
221
  // src/version.ts
222
- var VERSION = "1.0.0-rc.3";
223
- var ENGINE_VERSION = "1.0.0-rc.3";
222
+ var VERSION = "1.0.0-rc.5";
223
+ var ENGINE_VERSION = "1.0.0-rc.5";
224
224
 
225
225
  // src/engine-manager.ts
226
226
  import { spawn, spawnSync } from "child_process";
@@ -288,7 +288,7 @@ function httpsGet(url, redirectCount = 0) {
288
288
  new Error(`Too many redirects (>${MAX_REDIRECTS}) following ${url}`)
289
289
  );
290
290
  }
291
- return new Promise((resolve4, reject) => {
291
+ return new Promise((resolve5, reject) => {
292
292
  const client = url.startsWith("https:") ? https : http;
293
293
  client.get(url, (res) => {
294
294
  const status = res.statusCode ?? 0;
@@ -299,7 +299,7 @@ function httpsGet(url, redirectCount = 0) {
299
299
  return;
300
300
  }
301
301
  res.resume();
302
- resolve4(httpsGet(location, redirectCount + 1));
302
+ resolve5(httpsGet(location, redirectCount + 1));
303
303
  return;
304
304
  }
305
305
  if (status < 200 || status >= 300) {
@@ -309,7 +309,7 @@ function httpsGet(url, redirectCount = 0) {
309
309
  }
310
310
  const chunks = [];
311
311
  res.on("data", (chunk) => chunks.push(chunk));
312
- res.on("end", () => resolve4(Buffer.concat(chunks)));
312
+ res.on("end", () => resolve5(Buffer.concat(chunks)));
313
313
  res.on("error", reject);
314
314
  }).on("error", reject);
315
315
  });
@@ -536,11 +536,11 @@ var EngineManager = class {
536
536
  }
537
537
  this.requestId += 1;
538
538
  const requestStr = encodeRequest(this.requestId, method, params);
539
- return new Promise((resolve4, reject) => {
539
+ return new Promise((resolve5, reject) => {
540
540
  const onLine = (line) => {
541
541
  try {
542
542
  const response = decodeResponse(line);
543
- resolve4(extractResult(response));
543
+ resolve5(extractResult(response));
544
544
  } catch (err) {
545
545
  reject(err);
546
546
  }
@@ -907,12 +907,12 @@ var AttestClient = class {
907
907
  throw new Error("Engine process not started.");
908
908
  }
909
909
  let capturedReqId;
910
- const requestPromise = new Promise((resolve4, reject) => {
910
+ const requestPromise = new Promise((resolve5, reject) => {
911
911
  this.writeChain = this.writeChain.then(() => {
912
912
  this.requestId += 1;
913
913
  const reqId = this.requestId;
914
914
  capturedReqId = reqId;
915
- this.pending.set(reqId, { resolve: resolve4, reject });
915
+ this.pending.set(reqId, { resolve: resolve5, reject });
916
916
  const requestStr = encodeRequest(reqId, method, params);
917
917
  cp.stdin.write(requestStr, (err) => {
918
918
  if (err) {
@@ -937,7 +937,8 @@ var AttestClient = class {
937
937
  const params = {
938
938
  trace,
939
939
  assertions: [...assertions],
940
- ...options2?.budget !== void 0 ? { budget: options2.budget } : {}
940
+ ...options2?.budget !== void 0 ? { budget: options2.budget } : {},
941
+ ...options2?.context !== void 0 ? { context: options2.context } : {}
941
942
  };
942
943
  const raw = await this.sendRequest(
943
944
  "evaluate_batch",
@@ -1026,6 +1027,26 @@ function requireSimulationCapability(init) {
1026
1027
 
1027
1028
  // src/trace.ts
1028
1029
  import { randomUUID } from "crypto";
1030
+
1031
+ // src/simulation/context.ts
1032
+ import { AsyncLocalStorage } from "async_hooks";
1033
+ var activeMockRegistry = new AsyncLocalStorage();
1034
+ function createRng(seed) {
1035
+ if (seed === void 0) return Math.random;
1036
+ let state = seed >>> 0;
1037
+ return () => {
1038
+ state = state + 1831565813 >>> 0;
1039
+ let t = state;
1040
+ t = Math.imul(t ^ t >>> 15, t | 1);
1041
+ t ^= t + Math.imul(t ^ t >>> 7, t | 61);
1042
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
1043
+ };
1044
+ }
1045
+ function sleep(ms) {
1046
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
1047
+ }
1048
+
1049
+ // src/trace.ts
1029
1050
  var TraceBuilder = class {
1030
1051
  traceId;
1031
1052
  agentId;
@@ -1057,11 +1078,22 @@ var TraceBuilder = class {
1057
1078
  return this;
1058
1079
  }
1059
1080
  addToolCall(name, options2) {
1081
+ const mock = activeMockRegistry.getStore()?.get(name);
1082
+ let result = options2?.result;
1083
+ if (mock !== void 0) {
1084
+ const mocked = mock(options2?.args ?? {});
1085
+ if (typeof mocked?.then === "function") {
1086
+ throw new Error(`mock for tool '${name}' returned a Promise; mock tools must be synchronous`);
1087
+ }
1088
+ if (typeof mocked === "object" && mocked !== null && !Array.isArray(mocked)) {
1089
+ result = mocked;
1090
+ }
1091
+ }
1060
1092
  this.steps.push({
1061
1093
  type: STEP_TOOL_CALL,
1062
1094
  name,
1063
1095
  args: options2?.args,
1064
- result: options2?.result,
1096
+ result,
1065
1097
  metadata: options2?.metadata
1066
1098
  });
1067
1099
  return this;
@@ -2716,18 +2748,18 @@ function serve(engine, args) {
2716
2748
  let stdout = "";
2717
2749
  let stderr = "";
2718
2750
  let resolveReady = () => void 0;
2719
- const ready = new Promise((resolve4) => {
2720
- resolveReady = resolve4;
2751
+ const ready = new Promise((resolve5) => {
2752
+ resolveReady = resolve5;
2721
2753
  });
2722
- const exited = new Promise((resolve4) => {
2754
+ const exited = new Promise((resolve5) => {
2723
2755
  child.on("close", (code, signal) => {
2724
2756
  resolveReady(null);
2725
- resolve4({ code, signal });
2757
+ resolve5({ code, signal });
2726
2758
  });
2727
2759
  child.on("error", (err) => {
2728
2760
  stderr += err.message;
2729
2761
  resolveReady(null);
2730
- resolve4({ code: null, signal: null });
2762
+ resolve5({ code: null, signal: null });
2731
2763
  });
2732
2764
  });
2733
2765
  child.stdout.setEncoding("utf8").on("data", (chunk) => {
@@ -2984,18 +3016,18 @@ async function start(name, mode, opts) {
2984
3016
  let stdout = "";
2985
3017
  let stderr = "";
2986
3018
  let resolveReady = () => void 0;
2987
- const ready = new Promise((resolve4) => {
2988
- resolveReady = resolve4;
3019
+ const ready = new Promise((resolve5) => {
3020
+ resolveReady = resolve5;
2989
3021
  });
2990
- const exited = new Promise((resolve4) => {
3022
+ const exited = new Promise((resolve5) => {
2991
3023
  child.on("close", (code) => {
2992
3024
  resolveReady(null);
2993
- resolve4(code);
3025
+ resolve5(code);
2994
3026
  });
2995
3027
  child.on("error", (err) => {
2996
3028
  stderr += err.message;
2997
3029
  resolveReady(null);
2998
- resolve4(null);
3030
+ resolve5(null);
2999
3031
  });
3000
3032
  });
3001
3033
  child.stdout.setEncoding("utf8").on("data", (chunk) => {
@@ -3120,18 +3152,18 @@ async function start2(file, opts) {
3120
3152
  let stdout = "";
3121
3153
  let stderr = "";
3122
3154
  let resolveReady = () => void 0;
3123
- const ready = new Promise((resolve4) => {
3124
- resolveReady = resolve4;
3155
+ const ready = new Promise((resolve5) => {
3156
+ resolveReady = resolve5;
3125
3157
  });
3126
- const exited = new Promise((resolve4) => {
3158
+ const exited = new Promise((resolve5) => {
3127
3159
  child.on("close", (code) => {
3128
3160
  resolveReady(null);
3129
- resolve4(code);
3161
+ resolve5(code);
3130
3162
  });
3131
3163
  child.on("error", (err) => {
3132
3164
  stderr += err.message;
3133
3165
  resolveReady(null);
3134
- resolve4(null);
3166
+ resolve5(null);
3135
3167
  });
3136
3168
  });
3137
3169
  child.stdout.setEncoding("utf8").on("data", (chunk) => {
@@ -3212,8 +3244,8 @@ function parseFinal(out) {
3212
3244
  }
3213
3245
 
3214
3246
  // src/context.ts
3215
- import { AsyncLocalStorage } from "async_hooks";
3216
- var activeBuilder = new AsyncLocalStorage();
3247
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
3248
+ var activeBuilder = new AsyncLocalStorage2();
3217
3249
 
3218
3250
  // src/agent.ts
3219
3251
  var Agent = class {
@@ -3300,6 +3332,9 @@ function tier(level) {
3300
3332
  }
3301
3333
 
3302
3334
  // src/plugins.ts
3335
+ import { existsSync as existsSync2, readFileSync as readFileSync2, realpathSync } from "fs";
3336
+ import { dirname as dirname2, join as join4, relative as relative2, resolve as resolve4, isAbsolute, sep as sep2 } from "path";
3337
+ import { pathToFileURL } from "url";
3303
3338
  var PluginRegistry = class {
3304
3339
  plugins = /* @__PURE__ */ new Map();
3305
3340
  register(name, plugin) {
@@ -3330,10 +3365,19 @@ var PluginRegistry = class {
3330
3365
  };
3331
3366
  async function executePluginAssertion(plugin, trace, spec, client, traceId2, assertionId2, timeoutMs = 3e4) {
3332
3367
  const resultPromise = Promise.resolve(plugin.execute(trace, spec));
3368
+ let timer;
3333
3369
  const timeoutPromise = new Promise((_, reject) => {
3334
- setTimeout(() => reject(new Error(`Plugin '${plugin.name}' timed out after ${timeoutMs}ms`)), timeoutMs);
3370
+ timer = setTimeout(
3371
+ () => reject(new Error(`Plugin '${plugin.name}' timed out after ${timeoutMs}ms`)),
3372
+ timeoutMs
3373
+ );
3335
3374
  });
3336
- const result = await Promise.race([resultPromise, timeoutPromise]);
3375
+ let result;
3376
+ try {
3377
+ result = await Promise.race([resultPromise, timeoutPromise]);
3378
+ } finally {
3379
+ clearTimeout(timer);
3380
+ }
3337
3381
  await client.submitPluginResult(
3338
3382
  traceId2,
3339
3383
  plugin.name,
@@ -3344,6 +3388,100 @@ async function executePluginAssertion(plugin, trace, spec, client, traceId2, ass
3344
3388
  );
3345
3389
  return result;
3346
3390
  }
3391
+ function registerPlugin(registry, name, plugin) {
3392
+ registry.register(name, plugin);
3393
+ }
3394
+ function isAttestPlugin(value) {
3395
+ if (typeof value !== "object" || value === null) return false;
3396
+ const v = value;
3397
+ return typeof v["name"] === "string" && typeof v["pluginType"] === "string" && typeof v["execute"] === "function";
3398
+ }
3399
+ function readJson(path5) {
3400
+ return JSON.parse(readFileSync2(path5, "utf8"));
3401
+ }
3402
+ function findInstalledPackage(projectRoot, name) {
3403
+ let dir = resolve4(projectRoot);
3404
+ for (; ; ) {
3405
+ const candidate = join4(dir, "node_modules", name);
3406
+ if (existsSync2(join4(candidate, "package.json"))) return candidate;
3407
+ const parent = dirname2(dir);
3408
+ if (parent === dir) return void 0;
3409
+ dir = parent;
3410
+ }
3411
+ }
3412
+ function declaredPluginPaths(pkgJson, dep) {
3413
+ const attest = pkgJson["attest"];
3414
+ if (attest === void 0) return [];
3415
+ const plugins = typeof attest === "object" && attest !== null ? attest["plugins"] : void 0;
3416
+ if (plugins === void 0) return [];
3417
+ if (!Array.isArray(plugins) || !plugins.every((p) => typeof p === "string")) {
3418
+ throw new Error(`'${dep}': "attest.plugins" must be an array of strings`);
3419
+ }
3420
+ return plugins;
3421
+ }
3422
+ function pluginsOf(mod) {
3423
+ const def = mod["default"];
3424
+ const nested = typeof def === "object" && def !== null ? def : void 0;
3425
+ for (const candidate of [def, nested?.["default"]]) {
3426
+ if (isAttestPlugin(candidate)) return [candidate];
3427
+ }
3428
+ return [.../* @__PURE__ */ new Set([...Object.values(mod), ...Object.values(nested ?? {})])].filter(isAttestPlugin);
3429
+ }
3430
+ function isInside(root, file) {
3431
+ const within = (r, f) => {
3432
+ const rel = relative2(r, f);
3433
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep2}`) && !isAbsolute(rel);
3434
+ };
3435
+ return within(root, file) && within(realpathSync(root), realpathSync(file));
3436
+ }
3437
+ async function loadPackagePlugins(registry, projectRoot = process.cwd()) {
3438
+ let project;
3439
+ try {
3440
+ project = readJson(join4(projectRoot, "package.json"));
3441
+ } catch (err) {
3442
+ console.error(`attest: cannot read ${join4(projectRoot, "package.json")}; no plugins loaded:`, err);
3443
+ return 0;
3444
+ }
3445
+ const depNames = /* @__PURE__ */ new Set();
3446
+ for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
3447
+ const deps = project[field];
3448
+ if (typeof deps === "object" && deps !== null) {
3449
+ for (const dep of Object.keys(deps)) depNames.add(dep);
3450
+ }
3451
+ }
3452
+ let loaded = 0;
3453
+ for (const dep of depNames) {
3454
+ const pkgDir = findInstalledPackage(projectRoot, dep);
3455
+ if (pkgDir === void 0) continue;
3456
+ let entries;
3457
+ try {
3458
+ entries = declaredPluginPaths(readJson(join4(pkgDir, "package.json")), dep);
3459
+ } catch (err) {
3460
+ console.error(`attest: failed to read plugins declared by '${dep}':`, err);
3461
+ continue;
3462
+ }
3463
+ for (const entry of entries) {
3464
+ try {
3465
+ const file = resolve4(pkgDir, entry);
3466
+ if (!isInside(pkgDir, file)) {
3467
+ throw new Error(`plugin path '${entry}' escapes package '${dep}'`);
3468
+ }
3469
+ const mod = await import(pathToFileURL(file).href);
3470
+ const plugins = pluginsOf(mod);
3471
+ if (plugins.length === 0) {
3472
+ throw new Error(`'${entry}' exports no plugin (name, pluginType, execute)`);
3473
+ }
3474
+ for (const plugin of plugins) {
3475
+ registry.register(plugin.name, plugin);
3476
+ loaded++;
3477
+ }
3478
+ } catch (err) {
3479
+ console.error(`attest: failed to load plugin '${entry}' from '${dep}':`, err);
3480
+ }
3481
+ }
3482
+ }
3483
+ return loaded;
3484
+ }
3347
3485
 
3348
3486
  // src/continuous.ts
3349
3487
  import { EventEmitter } from "events";
@@ -3723,6 +3861,172 @@ the assistant's response meets your needs. Keep responses concise (1-3 sentences
3723
3861
  max_tokens: 200
3724
3862
  };
3725
3863
 
3864
+ // src/simulation/mock-tools.ts
3865
+ var MockToolRegistry = class {
3866
+ tools = /* @__PURE__ */ new Map();
3867
+ register(name, fn) {
3868
+ this.tools.set(name, fn);
3869
+ }
3870
+ /**
3871
+ * Run `fn` with the registered mocks active. `TraceBuilder.addToolCall`
3872
+ * returns the mock's result for a registered tool name. Scopes are
3873
+ * isolated per async call chain (AsyncLocalStorage).
3874
+ */
3875
+ run(fn) {
3876
+ return activeMockRegistry.run(new Map(this.tools), fn);
3877
+ }
3878
+ };
3879
+ function mockTool(name, fn) {
3880
+ const wrapper = ((args) => fn(args));
3881
+ return Object.assign(wrapper, { mockToolName: name });
3882
+ }
3883
+
3884
+ // src/simulation/fault-inject.ts
3885
+ function faultInject(options2, fn) {
3886
+ const errorRate = options2.errorRate ?? 0;
3887
+ const latencyJitterMs = options2.latencyJitterMs ?? 0;
3888
+ const rng = createRng(options2.seed);
3889
+ return async (...args) => {
3890
+ if (errorRate > 0 && rng() < errorRate) {
3891
+ throw new Error(`Injected fault in ${fn.name || "anonymous"}`);
3892
+ }
3893
+ if (latencyJitterMs > 0) {
3894
+ await sleep(rng() * latencyJitterMs);
3895
+ }
3896
+ return fn(...args);
3897
+ };
3898
+ }
3899
+
3900
+ // src/simulation/verdict.ts
3901
+ function aggregateOutcomes(outcomes) {
3902
+ if (outcomes.includes(OUTCOME_FAIL)) return OUTCOME_FAIL;
3903
+ if (outcomes.includes(OUTCOME_SKIP)) return OUTCOME_SKIP;
3904
+ return OUTCOME_PASS;
3905
+ }
3906
+ function sumNotEvaluatedReasons(results) {
3907
+ const counts = {};
3908
+ for (const r of results) {
3909
+ for (const [reason, n] of Object.entries(r.notEvaluatedReasons)) {
3910
+ counts[reason] = (counts[reason] ?? 0) + n;
3911
+ }
3912
+ }
3913
+ return counts;
3914
+ }
3915
+ function formatSkipReason(counts) {
3916
+ const parts = Object.entries(counts).map(([reason, n]) => n === 1 ? reason : `${reason} \xD7${n}`);
3917
+ return `not evaluated: ${parts.join(", ")}`;
3918
+ }
3919
+ function renderVerdictDiagnostics(verdict, color = false) {
3920
+ return verdict instanceof AgentResult ? renderDiagnostics(verdict, { color }) : verdict.renderDiagnostics?.({ color }) ?? "";
3921
+ }
3922
+ function verdictsDiagnostics(results, label, color = false) {
3923
+ const blocks = results.flatMap(
3924
+ (r, i) => r.outcome() === OUTCOME_PASS ? [] : [`${label} ${i + 1}/${results.length}:${renderVerdictDiagnostics(r, color)}`]
3925
+ );
3926
+ return blocks.length > 0 ? blocks.join("\n") : ` (no failing ${label}s)
3927
+ `;
3928
+ }
3929
+
3930
+ // src/simulation/repeat.ts
3931
+ var RepeatResult = class {
3932
+ results;
3933
+ constructor(results = []) {
3934
+ this.results = results;
3935
+ }
3936
+ get count() {
3937
+ return this.results.length;
3938
+ }
3939
+ /** Trials skipped because an assertion was not evaluated. */
3940
+ get notEvaluated() {
3941
+ return this.results.filter((r) => r.outcome() === OUTCOME_SKIP).length;
3942
+ }
3943
+ /** Passing / evaluated trials; null when no trial was evaluated. */
3944
+ get passRate() {
3945
+ const evaluated = this.count - this.notEvaluated;
3946
+ if (evaluated === 0) return null;
3947
+ return this.results.filter((r) => r.outcome() === OUTCOME_PASS).length / evaluated;
3948
+ }
3949
+ /** True when every trial's outcome is pass (soft failures included). */
3950
+ get allPassed() {
3951
+ return this.results.every((r) => r.outcome() === OUTCOME_PASS);
3952
+ }
3953
+ outcome(options2) {
3954
+ return aggregateOutcomes(this.results.map((r) => r.outcome(options2)));
3955
+ }
3956
+ get notEvaluatedReasons() {
3957
+ return sumNotEvaluatedReasons(this.results);
3958
+ }
3959
+ skipReason() {
3960
+ return formatSkipReason(this.notEvaluatedReasons);
3961
+ }
3962
+ renderDiagnostics(options2) {
3963
+ return verdictsDiagnostics(this.results, "trial", options2?.color);
3964
+ }
3965
+ };
3966
+ function repeat(n, fn) {
3967
+ return async (...args) => {
3968
+ const results = [];
3969
+ for (let i = 0; i < n; i++) {
3970
+ results.push(await fn(...args));
3971
+ }
3972
+ return new RepeatResult(results);
3973
+ };
3974
+ }
3975
+
3976
+ // src/simulation/scenario.ts
3977
+ var ScenarioResult = class {
3978
+ config;
3979
+ results;
3980
+ constructor(config2, results = []) {
3981
+ this.config = config2;
3982
+ this.results = results;
3983
+ }
3984
+ /** True when the aggregate `outcome()` is pass. */
3985
+ get passed() {
3986
+ return this.outcome() === OUTCOME_PASS;
3987
+ }
3988
+ outcome(options2) {
3989
+ return aggregateOutcomes(this.results.map((r) => r.outcome(options2)));
3990
+ }
3991
+ get notEvaluatedReasons() {
3992
+ return sumNotEvaluatedReasons(this.results);
3993
+ }
3994
+ skipReason() {
3995
+ return formatSkipReason(this.notEvaluatedReasons);
3996
+ }
3997
+ renderDiagnostics(options2) {
3998
+ return verdictsDiagnostics(this.results, "turn", options2?.color);
3999
+ }
4000
+ };
4001
+ function scenario(options2, fn) {
4002
+ const config2 = {
4003
+ persona: options2.persona,
4004
+ mockTools: { ...options2.mockTools },
4005
+ faultErrorRate: options2.faultErrorRate ?? 0,
4006
+ faultLatencyJitterMs: options2.faultLatencyJitterMs ?? 0,
4007
+ maxTurns: options2.maxTurns ?? 1,
4008
+ seed: options2.seed
4009
+ };
4010
+ return async (...args) => {
4011
+ const run = async () => {
4012
+ const results = [];
4013
+ const rng = createRng(config2.seed);
4014
+ for (let turn = 0; turn < config2.maxTurns; turn++) {
4015
+ if (config2.faultErrorRate > 0 && rng() < config2.faultErrorRate) {
4016
+ throw new Error(`Injected fault at turn ${turn}`);
4017
+ }
4018
+ if (config2.faultLatencyJitterMs > 0) {
4019
+ await sleep(rng() * config2.faultLatencyJitterMs);
4020
+ }
4021
+ results.push(await fn({ persona: config2.persona, turn }, ...args));
4022
+ }
4023
+ return new ScenarioResult(config2, results);
4024
+ };
4025
+ const mocks = new Map(Object.entries(config2.mockTools));
4026
+ return mocks.size > 0 ? activeMockRegistry.run(mocks, run) : run();
4027
+ };
4028
+ }
4029
+
3726
4030
  // src/adapters/manual.ts
3727
4031
  var ManualAdapter = class {
3728
4032
  agentId;
@@ -3934,7 +4238,7 @@ var OTelAdapter = class _OTelAdapter {
3934
4238
  }
3935
4239
  };
3936
4240
  function runConvert(engine, args, payload) {
3937
- return new Promise((resolve4, reject) => {
4241
+ return new Promise((resolve5, reject) => {
3938
4242
  const child = spawn5(engine, args, { stdio: ["pipe", "pipe", "pipe"] });
3939
4243
  let timer;
3940
4244
  child.on("error", (e) => {
@@ -3987,7 +4291,7 @@ function runConvert(engine, args, payload) {
3987
4291
  );
3988
4292
  return;
3989
4293
  }
3990
- resolve4(Buffer.concat(out).toString("utf8"));
4294
+ resolve5(Buffer.concat(out).toString("utf8"));
3991
4295
  });
3992
4296
  stdin.end(payload);
3993
4297
  });
@@ -4154,6 +4458,7 @@ export {
4154
4458
  GeminiAdapter,
4155
4459
  LangChainAdapter,
4156
4460
  ManualAdapter,
4461
+ MockToolRegistry,
4157
4462
  OTLPConversionError,
4158
4463
  OTelAdapter,
4159
4464
  OUTCOME_FAIL,
@@ -4173,6 +4478,7 @@ export {
4173
4478
  REASON_REPLAY_MISS,
4174
4479
  REASON_SHORT_CIRCUITED,
4175
4480
  REASON_SIMULATION,
4481
+ RepeatResult,
4176
4482
  ReplayError,
4177
4483
  ReplayMissError,
4178
4484
  ReplayNotEvaluatedError,
@@ -4185,6 +4491,7 @@ export {
4185
4491
  STEP_RETRIEVAL,
4186
4492
  STEP_TOOL_CALL,
4187
4493
  Sampler,
4494
+ ScenarioResult,
4188
4495
  TIER_1,
4189
4496
  TIER_2,
4190
4497
  TIER_3,
@@ -4219,6 +4526,7 @@ export {
4219
4526
  executePluginAssertion,
4220
4527
  extractId,
4221
4528
  extractResult,
4529
+ faultInject,
4222
4530
  firstMiss,
4223
4531
  formatUsage,
4224
4532
  getSampleRate,
@@ -4230,17 +4538,23 @@ export {
4230
4538
  loadFixture,
4231
4539
  loadLabelsCSV,
4232
4540
  loadLabelsJSONL,
4541
+ loadPackagePlugins,
4542
+ mockTool,
4233
4543
  parseUsage,
4234
4544
  previewLine,
4235
4545
  promptHash,
4236
4546
  record,
4547
+ registerPlugin,
4237
4548
  renderAssertionFailure,
4238
4549
  renderDiagnostics,
4239
4550
  renderSummary,
4551
+ renderVerdictDiagnostics,
4240
4552
  renderVitest,
4553
+ repeat,
4241
4554
  requireSimulationCapability,
4242
4555
  resetConfig,
4243
4556
  resolveMode,
4557
+ scenario,
4244
4558
  simulationEnvEnabled,
4245
4559
  startReplay,
4246
4560
  startWorld,