vieval 0.0.1 → 0.0.3

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 (51) hide show
  1. package/README.md +8 -5
  2. package/dist/cli/index.d.mts +1 -1
  3. package/dist/cli/index.mjs +1204 -61
  4. package/dist/cli/index.mjs.map +1 -1
  5. package/dist/{config-D2fe1SnT.mjs → config-CHN24egi.mjs} +1 -1
  6. package/dist/{config-D2fe1SnT.mjs.map → config-CHN24egi.mjs.map} +1 -1
  7. package/dist/config.d.mts +2 -3
  8. package/dist/config.mjs +2 -2
  9. package/dist/core/assertions/index.d.mts +1 -1
  10. package/dist/core/inference-executors/index.d.mts +1 -45
  11. package/dist/core/inference-executors/index.mjs +1 -38
  12. package/dist/core/inference-executors/index.mjs.map +1 -1
  13. package/dist/core/processors/results/index.d.mts +1 -1
  14. package/dist/core/runner/index.d.mts +2 -2
  15. package/dist/core/runner/index.mjs +2 -2
  16. package/dist/env-C7X81PWa.mjs +41 -0
  17. package/dist/env-C7X81PWa.mjs.map +1 -0
  18. package/dist/env-DtpjACOW.d.mts +47 -0
  19. package/dist/expect-B2vaoRVZ.d.mts +10 -0
  20. package/dist/{expect-i9WZWGrA.mjs → expect-CaXiUkwY.mjs} +3 -3
  21. package/dist/expect-CaXiUkwY.mjs.map +1 -0
  22. package/dist/expect-extensions-BOzwV5EJ.mjs +197 -0
  23. package/dist/expect-extensions-BOzwV5EJ.mjs.map +1 -0
  24. package/dist/expect.d.mts +1 -1
  25. package/dist/expect.mjs +1 -1
  26. package/dist/{index-DP7jsORl.d.mts → index-BDMEAmf2.d.mts} +246 -3
  27. package/dist/{index-oSXhM1zx.d.mts → index-C3gPFmcR.d.mts} +2 -2
  28. package/dist/index.d.mts +326 -6
  29. package/dist/index.mjs +65 -23
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{models-D_MsBtYw.mjs → models-DIGdOUpJ.mjs} +1 -1
  32. package/dist/{models-D_MsBtYw.mjs.map → models-DIGdOUpJ.mjs.map} +1 -1
  33. package/dist/plugins/chat-models/index.d.mts +465 -6
  34. package/dist/plugins/chat-models/index.mjs +469 -6
  35. package/dist/plugins/chat-models/index.mjs.map +1 -1
  36. package/dist/{registry-ChOjjdEC.mjs → registry-CHJcTN2W.mjs} +75 -16
  37. package/dist/registry-CHJcTN2W.mjs.map +1 -0
  38. package/dist/{runner-4ZsOveoY.mjs → runner-Dpy-eivM.mjs} +177 -21
  39. package/dist/runner-Dpy-eivM.mjs.map +1 -0
  40. package/dist/testing/expect-extensions.d.mts +44 -38
  41. package/dist/testing/expect-extensions.mjs +1 -1
  42. package/package.json +11 -4
  43. package/dist/expect-0jPJ7Zio.d.mts +0 -2318
  44. package/dist/expect-extensions-CwPtgTz8.mjs +0 -13471
  45. package/dist/expect-extensions-CwPtgTz8.mjs.map +0 -1
  46. package/dist/expect-i9WZWGrA.mjs.map +0 -1
  47. package/dist/magic-string.es-CH1jwzMg.mjs +0 -1013
  48. package/dist/magic-string.es-CH1jwzMg.mjs.map +0 -1
  49. package/dist/plugin-DVaRZY2x.d.mts +0 -84
  50. package/dist/registry-ChOjjdEC.mjs.map +0 -1
  51. package/dist/runner-4ZsOveoY.mjs.map +0 -1
@@ -14,4 +14,4 @@ function defineTask(definition) {
14
14
  //#endregion
15
15
  export { defineTask as n, defineEval as t };
16
16
 
17
- //# sourceMappingURL=config-D2fe1SnT.mjs.map
17
+ //# sourceMappingURL=config-CHN24egi.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-D2fe1SnT.mjs","names":[],"sources":["../src/config/define.ts"],"sourcesContent":["import type { EvalDefinition, TaskDefinition } from './types'\n\n/**\n * Returns the provided vieval definition while preserving literal field types.\n */\nexport function defineEval<const TDefinition extends EvalDefinition>(definition: TDefinition): TDefinition {\n return definition\n}\n\n/**\n * Returns the provided task definition while preserving literal field types.\n */\nexport function defineTask<const TDefinition extends TaskDefinition>(definition: TDefinition): TDefinition {\n return definition\n}\n"],"mappings":";;;;AAKA,SAAgB,WAAqD,YAAsC;AACzG,QAAO;;;;;AAMT,SAAgB,WAAqD,YAAsC;AACzG,QAAO"}
1
+ {"version":3,"file":"config-CHN24egi.mjs","names":[],"sources":["../src/config/define.ts"],"sourcesContent":["import type { EvalDefinition, TaskDefinition } from './types'\n\n/**\n * Returns the provided vieval definition while preserving literal field types.\n */\nexport function defineEval<const TDefinition extends EvalDefinition>(definition: TDefinition): TDefinition {\n return definition\n}\n\n/**\n * Returns the provided task definition while preserving literal field types.\n */\nexport function defineTask<const TDefinition extends TaskDefinition>(definition: TDefinition): TDefinition {\n return definition\n}\n"],"mappings":";;;;AAKA,SAAgB,WAAqD,YAAsC;AACzG,QAAO;;;;;AAMT,SAAgB,WAAqD,YAAsC;AACzG,QAAO"}
package/dist/config.d.mts CHANGED
@@ -1,3 +1,2 @@
1
- import { _ as TaskDefinition, a as EvalModule, b as TaskRunOutput, c as MatrixDefinition, d as MatrixRow, f as MatrixValue, g as TaskCaseState, h as TaskCaseReporterPayload, i as EvalDefinition, l as MatrixLayer, m as TaskCaseReporterEndPayload, n as defineTask, o as EvalModuleMap, p as ScopedMatrices, r as CollectedEvalEntry, s as MatrixAxisValues, t as defineEval, u as MatrixPrimitive, v as TaskReporterHooks, y as TaskRunContext } from "./index-DP7jsORl.mjs";
2
- import { n as ModelDefinition, r as resolveModelByName, t as ConfigHookPlugin } from "./plugin-DVaRZY2x.mjs";
3
- export { CollectedEvalEntry, ConfigHookPlugin, EvalDefinition, EvalModule, EvalModuleMap, MatrixAxisValues, MatrixDefinition, MatrixLayer, MatrixPrimitive, MatrixRow, MatrixValue, ModelDefinition, ScopedMatrices, TaskCaseReporterEndPayload, TaskCaseReporterPayload, TaskCaseState, TaskDefinition, TaskReporterHooks, TaskRunContext, TaskRunOutput, defineEval, defineTask, resolveModelByName };
1
+ import { M as ModelDefinition, N as resolveModelByName, S as TaskRunOutput, _ as TaskCaseState, a as EvalDefinition, b as TaskReporterHooks, c as MatrixAxisValues, d as MatrixPrimitive, f as MatrixRow, g as TaskCaseReporterPayload, h as TaskCaseReporterEndPayload, i as CollectedEvalEntry, l as MatrixDefinition, m as ScopedMatrices, n as defineEval, o as EvalModule, p as MatrixValue, r as defineTask, s as EvalModuleMap, t as ConfigHookPlugin, u as MatrixLayer, v as TaskDefinition, x as TaskRunContext, y as TaskReporterEventPayload } from "./index-BDMEAmf2.mjs";
2
+ export { CollectedEvalEntry, ConfigHookPlugin, EvalDefinition, EvalModule, EvalModuleMap, MatrixAxisValues, MatrixDefinition, MatrixLayer, MatrixPrimitive, MatrixRow, MatrixValue, ModelDefinition, ScopedMatrices, TaskCaseReporterEndPayload, TaskCaseReporterPayload, TaskCaseState, TaskDefinition, TaskReporterEventPayload, TaskReporterHooks, TaskRunContext, TaskRunOutput, defineEval, defineTask, resolveModelByName };
package/dist/config.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as defineTask, t as defineEval } from "./config-D2fe1SnT.mjs";
2
- import { t as resolveModelByName } from "./models-D_MsBtYw.mjs";
1
+ import { n as defineTask, t as defineEval } from "./config-CHN24egi.mjs";
2
+ import { t as resolveModelByName } from "./models-DIGdOUpJ.mjs";
3
3
  export { defineEval, defineTask, resolveModelByName };
@@ -1,2 +1,2 @@
1
- import { C as expectToolCallArgs, S as expectStructuredOutput, T as toRunScores, _ as expectMustExclude, a as CustomAssertionOptions, b as expectRegex, c as RegexAssertionOptions, d as StructuredOutputAssertionOptions, f as ToolCall, g as expectCustom, h as evaluateAssertions, i as AssertionState, l as RubricAssertionOptions, m as collectFailedAssertions, n as AssertionContext, o as MustExcludeAssertionOptions, p as ToolCallArgsAssertionOptions, r as AssertionOutcome, s as MustIncludeAssertionOptions, t as Assertion, u as RubricJudgeResult, v as expectMustInclude, w as normalizeMatchText, x as expectRubric, y as expectNot } from "../../index-oSXhM1zx.mjs";
1
+ import { C as expectToolCallArgs, S as expectStructuredOutput, T as toRunScores, _ as expectMustExclude, a as CustomAssertionOptions, b as expectRegex, c as RegexAssertionOptions, d as StructuredOutputAssertionOptions, f as ToolCall, g as expectCustom, h as evaluateAssertions, i as AssertionState, l as RubricAssertionOptions, m as collectFailedAssertions, n as AssertionContext, o as MustExcludeAssertionOptions, p as ToolCallArgsAssertionOptions, r as AssertionOutcome, s as MustIncludeAssertionOptions, t as Assertion, u as RubricJudgeResult, v as expectMustInclude, w as normalizeMatchText, x as expectRubric, y as expectNot } from "../../index-C3gPFmcR.mjs";
2
2
  export { Assertion, AssertionContext, AssertionOutcome, AssertionState, CustomAssertionOptions, MustExcludeAssertionOptions, MustIncludeAssertionOptions, RegexAssertionOptions, RubricAssertionOptions, RubricJudgeResult, StructuredOutputAssertionOptions, ToolCall, ToolCallArgsAssertionOptions, collectFailedAssertions, evaluateAssertions, expectCustom, expectMustExclude, expectMustInclude, expectNot, expectRegex, expectRubric, expectStructuredOutput, expectToolCallArgs, normalizeMatchText, toRunScores };
@@ -1,3 +1,4 @@
1
+ import { a as requiredEnvFrom, i as envFrom, n as EnvValueType, r as RequiredEnvFromOptions, t as EnvFromOptions } from "../../env-DtpjACOW.mjs";
1
2
  import { createOpenAI } from "@xsai-ext/providers/create";
2
3
 
3
4
  //#region src/core/inference-executors/retry-policy.d.ts
@@ -116,51 +117,6 @@ interface ProviderAdapter<TProvider> {
116
117
  */
117
118
  declare function createProviderAdapter<TProvider>(provider: TProvider, options?: RetryPolicyOptions): ProviderAdapter<TProvider>;
118
119
  //#endregion
119
- //#region src/core/inference-executors/env.d.ts
120
- /**
121
- * Supported env value coercion types.
122
- */
123
- type EnvValueType = 'string';
124
- /**
125
- * Common options for env readers.
126
- */
127
- interface EnvFromOptions {
128
- /**
129
- * Expected env value type.
130
- */
131
- type: EnvValueType;
132
- /**
133
- * Whether an empty or missing value should throw.
134
- *
135
- * @default false
136
- */
137
- required?: boolean;
138
- /**
139
- * Optional key name used for clearer error messages.
140
- */
141
- name?: string;
142
- }
143
- /**
144
- * Env options used by the required helper.
145
- *
146
- * `required` is intentionally omitted because this helper is always required.
147
- */
148
- type RequiredEnvFromOptions = Omit<EnvFromOptions, 'required'>;
149
- /**
150
- * Parses one env value with optional required behavior.
151
- *
152
- * Example:
153
- * `const apiKey = envFrom(process.env.OPENAI_API_KEY, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`
154
- */
155
- declare function envFrom(value: string | undefined, options: EnvFromOptions): string | undefined;
156
- /**
157
- * Parses one required env value.
158
- *
159
- * Example:
160
- * `const apiKey = requiredEnvFrom(process.env.OPENAI_API_KEY, { type: 'string', name: 'OPENAI_API_KEY' })`
161
- */
162
- declare function requiredEnvFrom(value: string | undefined, options: RequiredEnvFromOptions): string;
163
- //#endregion
164
120
  //#region src/core/inference-executors/remote-providers/openai/index.d.ts
165
121
  /**
166
122
  * Represents the OpenAI provider instance returned by xsai.
@@ -1,3 +1,4 @@
1
+ import { n as requiredEnvFrom, t as envFrom } from "../../env-C7X81PWa.mjs";
1
2
  import process from "node:process";
2
3
  import { errorMessageFrom, errorNameFrom, sleep } from "@moeru/std";
3
4
  import { createOpenAI } from "@xsai-ext/providers/create";
@@ -125,44 +126,6 @@ function createProviderAdapter(provider, options = {}) {
125
126
  };
126
127
  }
127
128
  //#endregion
128
- //#region src/core/inference-executors/env.ts
129
- function assertNonEmptyString(value, options) {
130
- if (value == null || value.trim().length === 0) {
131
- if (options.required === true) {
132
- const label = options.name ?? "environment variable";
133
- throw new Error(`Missing required ${label}.`);
134
- }
135
- return;
136
- }
137
- return value;
138
- }
139
- /**
140
- * Parses one env value with optional required behavior.
141
- *
142
- * Example:
143
- * `const apiKey = envFrom(process.env.OPENAI_API_KEY, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`
144
- */
145
- function envFrom(value, options) {
146
- if (options.type === "string") return assertNonEmptyString(value, options);
147
- }
148
- /**
149
- * Parses one required env value.
150
- *
151
- * Example:
152
- * `const apiKey = requiredEnvFrom(process.env.OPENAI_API_KEY, { type: 'string', name: 'OPENAI_API_KEY' })`
153
- */
154
- function requiredEnvFrom(value, options) {
155
- const parsed = envFrom(value, {
156
- ...options,
157
- required: true
158
- });
159
- if (parsed == null) {
160
- const label = options.name ?? "environment variable";
161
- throw new Error(`Missing required ${label}.`);
162
- }
163
- return parsed;
164
- }
165
- //#endregion
166
129
  //#region src/core/inference-executors/remote-providers/openai/index.ts
167
130
  /**
168
131
  * Normalizes provider text output to a safe string.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["defaultSleep"],"sources":["../../../src/core/inference-executors/retry-policy.ts","../../../src/core/inference-executors/adapters.ts","../../../src/core/inference-executors/env.ts","../../../src/core/inference-executors/remote-providers/openai/index.ts"],"sourcesContent":["import { sleep as defaultSleep, errorMessageFrom, errorNameFrom } from '@moeru/std'\n\n/**\n * Describes how provider retries should behave.\n *\n * ASCII flow:\n * attempt -> run request -> success return\n * attempt -> run request -> retriable failure -> sleep -> next attempt\n * attempt -> run request -> non-retriable failure -> throw\n */\nexport interface RetryPolicy {\n /**\n * Maximum number of total attempts, including the first try.\n */\n maxAttempts: number\n /**\n * Returns the wait time for a retry attempt.\n */\n delayMs: (attempt: number) => number\n /**\n * Determines whether an error can be retried safely.\n */\n shouldRetry: (error: unknown) => boolean\n /**\n * Suspends execution between retries.\n */\n sleep: (milliseconds: number) => Promise<void>\n}\n\n/**\n * Configures a retry policy before a provider call is executed.\n *\n * Use when:\n * - you want the default retry classifier but need to tune attempts or delay\n * - you need to replace the sleeper in tests\n *\n * Expects:\n * - `maxAttempts` to be a finite integer greater than or equal to `1`\n * - `delayMs` to return a non-negative wait time in milliseconds\n */\nexport interface RetryPolicyOptions {\n /**\n * Maximum total attempts, including the first request.\n *\n * @default 3\n */\n maxAttempts?: number\n /**\n * Computes the delay for a retry attempt.\n *\n * The attempt number starts at `1` for the first retry.\n */\n delayMs?: (attempt: number) => number\n /**\n * Overrides the retry classifier.\n */\n shouldRetry?: (error: unknown) => boolean\n /**\n * Overrides the sleeper used between attempts.\n */\n sleep?: (milliseconds: number) => Promise<void>\n}\n\nconst retryableStatusCodes = new Set([408, 425, 429, 500, 502, 503, 504])\nconst retryableErrorNames = new Set(['TimeoutError', 'FetchError'])\nconst retryableMessagePatterns = [\n /rate limit/i,\n /rate-limited/i,\n /temporarily unavailable/i,\n /service unavailable/i,\n /server error/i,\n /fetch failed/i,\n /network error/i,\n /socket hang up/i,\n /econnreset/i,\n /econnrefused/i,\n /eai_again/i,\n /etimedout/i,\n /timed out/i,\n /timeout/i,\n]\n\nfunction getStatusCode(error: unknown): number | undefined {\n if (error == null || typeof error !== 'object') {\n return undefined\n }\n\n const maybeStatusCode = (error as { statusCode?: unknown }).statusCode\n if (typeof maybeStatusCode === 'number') {\n return maybeStatusCode\n }\n\n const maybeStatus = (error as { status?: unknown }).status\n if (typeof maybeStatus === 'number') {\n return maybeStatus\n }\n\n const response = (error as { response?: unknown }).response\n if (response == null || typeof response !== 'object') {\n return undefined\n }\n\n const responseStatus = (response as { status?: unknown }).status\n return typeof responseStatus === 'number' ? responseStatus : undefined\n}\n\n/**\n * Returns true when a provider failure is temporary and a retry is reasonable.\n *\n * Use when:\n * - the upstream failure is a transport problem or a 5xx/429 response\n *\n * Expects:\n * - provider errors to expose a status code, name, or message when possible\n */\nexport function isRetriableProviderError(error: unknown): boolean {\n const statusCode = getStatusCode(error)\n\n if (statusCode != null) {\n return retryableStatusCodes.has(statusCode)\n }\n\n const errorName = errorNameFrom(error)\n if (errorName != null && retryableErrorNames.has(errorName)) {\n return true\n }\n\n const errorMessage = errorMessageFrom(error)\n if (errorMessage == null) {\n return false\n }\n\n return retryableMessagePatterns.some(pattern => pattern.test(errorMessage))\n}\n\nfunction defaultDelayMs(attempt: number): number {\n return 500 * 2 ** (attempt - 1)\n}\n\n/**\n * Creates a retry policy for provider work.\n *\n * Use when:\n * - you need a reusable retry runner for eval-time provider calls\n * - you want to keep retry behavior deterministic in tests\n *\n * Expects:\n * - callers to treat `maxAttempts` as total attempts, not retries\n *\n * Throws:\n * - `RangeError` when `maxAttempts` is not a finite integer greater than or equal to `1`\n */\nfunction assertValidMaxAttempts(value: number): number {\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {\n throw new RangeError('maxAttempts must be a finite integer greater than or equal to 1.')\n }\n\n return value\n}\n\nexport function createRetryPolicy(options: RetryPolicyOptions = {}): RetryPolicy {\n const maxAttempts = assertValidMaxAttempts(options.maxAttempts ?? 3)\n\n return {\n maxAttempts,\n delayMs: options.delayMs ?? defaultDelayMs,\n shouldRetry: options.shouldRetry ?? isRetriableProviderError,\n sleep: options.sleep ?? defaultSleep,\n }\n}\n\n/**\n * Runs an operation with bounded retries.\n *\n * Use when:\n * - you are calling an LLM provider or other temporary upstream dependency\n * - non-retriable failures should bubble immediately\n *\n * Expects:\n * - the operation to be idempotent across attempts\n */\nexport async function runWithRetry<T>(operation: () => Promise<T>, policy: RetryPolicy = createRetryPolicy()): Promise<T> {\n for (let attempt = 1; attempt <= policy.maxAttempts; attempt += 1) {\n try {\n return await operation()\n }\n catch (error) {\n if (attempt >= policy.maxAttempts || !policy.shouldRetry(error)) {\n throw error\n }\n\n const delayMilliseconds = policy.delayMs(attempt)\n if (delayMilliseconds > 0) {\n await policy.sleep(delayMilliseconds)\n }\n }\n }\n\n throw new Error('Retry loop exited without returning a value.')\n}\n","import type { RetryPolicy, RetryPolicyOptions } from './retry-policy'\n\nimport { createRetryPolicy, runWithRetry } from './retry-policy'\n\n/**\n * Bundles a provider with the retry policy used to call it.\n *\n * Use when:\n * - a provider instance should travel with the retry runner that governs it\n * - you want call sites to share one retry configuration object\n */\nexport interface ProviderAdapter<TProvider> {\n /**\n * The underlying provider instance.\n */\n provider: TProvider\n /**\n * The retry policy used for provider calls.\n */\n retryPolicy: RetryPolicy\n /**\n * Runs a provider-dependent operation with the adapter retry policy.\n */\n runWithRetry: <TResult>(operation: () => Promise<TResult>) => Promise<TResult>\n}\n\n/**\n * Creates a provider adapter with the default retry policy.\n *\n * Use when:\n * - you have a provider instance and want a consistent retry wrapper\n *\n * Expects:\n * - the provider to be safe to reuse across attempts\n */\nexport function createProviderAdapter<TProvider>(provider: TProvider, options: RetryPolicyOptions = {}): ProviderAdapter<TProvider> {\n const retryPolicy = createRetryPolicy(options)\n\n return {\n provider,\n retryPolicy,\n runWithRetry: operation => runWithRetry(operation, retryPolicy),\n }\n}\n","/**\n * Supported env value coercion types.\n */\nexport type EnvValueType = 'string'\n\n/**\n * Common options for env readers.\n */\nexport interface EnvFromOptions {\n /**\n * Expected env value type.\n */\n type: EnvValueType\n /**\n * Whether an empty or missing value should throw.\n *\n * @default false\n */\n required?: boolean\n /**\n * Optional key name used for clearer error messages.\n */\n name?: string\n}\n\n/**\n * Env options used by the required helper.\n *\n * `required` is intentionally omitted because this helper is always required.\n */\nexport type RequiredEnvFromOptions = Omit<EnvFromOptions, 'required'>\n\nfunction assertNonEmptyString(value: string | undefined, options: EnvFromOptions): string | undefined {\n if (value == null || value.trim().length === 0) {\n if (options.required === true) {\n const label = options.name ?? 'environment variable'\n throw new Error(`Missing required ${label}.`)\n }\n\n return undefined\n }\n\n return value\n}\n\n/**\n * Parses one env value with optional required behavior.\n *\n * Example:\n * `const apiKey = envFrom(process.env.OPENAI_API_KEY, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`\n */\nexport function envFrom(\n value: string | undefined,\n options: EnvFromOptions,\n): string | undefined {\n if (options.type === 'string') {\n return assertNonEmptyString(value, options)\n }\n\n return undefined\n}\n\n/**\n * Parses one required env value.\n *\n * Example:\n * `const apiKey = requiredEnvFrom(process.env.OPENAI_API_KEY, { type: 'string', name: 'OPENAI_API_KEY' })`\n */\nexport function requiredEnvFrom(\n value: string | undefined,\n options: RequiredEnvFromOptions,\n): string {\n const parsed = envFrom(value, {\n ...options,\n required: true,\n })\n\n if (parsed == null) {\n const label = options.name ?? 'environment variable'\n throw new Error(`Missing required ${label}.`)\n }\n\n return parsed\n}\n","import type { ProviderAdapter } from '../../adapters'\nimport type { RetryPolicyOptions } from '../../retry-policy'\n\nimport process from 'node:process'\n\nimport { createOpenAI } from '@xsai-ext/providers/create'\n\nimport { createProviderAdapter } from '../../adapters'\nimport { envFrom, requiredEnvFrom } from '../../env'\n\n/**\n * Represents the OpenAI provider instance returned by xsai.\n */\nexport type OpenAIProvider = ReturnType<typeof createOpenAI>\n\n/**\n * Represents the OpenAI adapter used by vieval.\n */\nexport type OpenAIProviderAdapter = ProviderAdapter<OpenAIProvider>\n\n/**\n * Configures env key names and source for OpenAI provider setup.\n */\nexport interface OpenAIEnvSourceOptions {\n /**\n * Environment object used for variable lookup.\n *\n * @default process.env\n */\n env?: NodeJS.ProcessEnv\n /**\n * Env key name for API key.\n *\n * @default 'OPENAI_API_KEY'\n */\n apiKey?: string\n /**\n * Env key name for base URL.\n *\n * @default 'OPENAI_BASE_URL'\n */\n baseURL?: string\n /**\n * Env key name for model.\n *\n * @default 'OPENAI_MODEL'\n */\n model?: string\n}\n\n/**\n * Configures fallback defaults when env values are missing.\n */\nexport interface OpenAIFromEnvDefaultOptions {\n /**\n * API key fallback value.\n */\n apiKey?: string\n /**\n * Base URL fallback value.\n */\n baseURL?: string\n /**\n * Model fallback value.\n */\n model?: string\n /**\n * Retry policy override passed to provider adapter.\n */\n retryOptions?: RetryPolicyOptions\n}\n\n/**\n * Result produced by `createOpenAIFromEnv`.\n */\nexport interface OpenAIFromEnvResult {\n adapter: OpenAIProviderAdapter\n apiKey: string\n baseURL?: string\n model: string\n}\n\n/**\n * Minimal response shape returned by text-generation calls.\n */\nexport interface OpenAITextGenerationResult {\n /**\n * Text output from the provider.\n *\n * Some OpenAI-compatible implementations may return `null`.\n */\n text?: string | null\n}\n\n/**\n * Normalizes provider text output to a safe string.\n *\n * Before: `{ text: null }`\n * After: `''`\n *\n * Before: `{ text: 'hello' }`\n * After: `'hello'`\n */\nexport function normalizeOpenAITextOutput(result: OpenAITextGenerationResult): string {\n return typeof result.text === 'string' ? result.text : ''\n}\n\n/**\n * Creates an OpenAI provider adapter using environment variables with defaults.\n *\n * Example:\n * `const runtime = createOpenAIFromEnv({}, { model: 'gpt-4.1-mini' })`\n */\nexport function createOpenAIFromEnv(\n source: OpenAIEnvSourceOptions = {},\n defaults: OpenAIFromEnvDefaultOptions = {},\n): OpenAIFromEnvResult {\n const env = source.env ?? process.env\n const apiKeyEnvKey = source.apiKey ?? 'OPENAI_API_KEY'\n const baseURLEnvKey = source.baseURL ?? 'OPENAI_BASE_URL'\n const modelEnvKey = source.model ?? 'OPENAI_MODEL'\n\n const apiKey = requiredEnvFrom(env[apiKeyEnvKey] ?? defaults.apiKey, {\n name: apiKeyEnvKey,\n type: 'string',\n })\n const model = requiredEnvFrom(env[modelEnvKey] ?? defaults.model, {\n name: modelEnvKey,\n type: 'string',\n })\n const baseURL = envFrom(env[baseURLEnvKey] ?? defaults.baseURL, {\n name: baseURLEnvKey,\n type: 'string',\n })\n const adapter = createOpenAIProviderAdapter(apiKey, baseURL, defaults.retryOptions)\n\n return {\n adapter,\n apiKey,\n baseURL,\n model,\n }\n}\n\n/**\n * Creates an OpenAI provider adapter for eval-time requests.\n *\n * Use when:\n * - an eval needs the OpenAI SDK surface plus the shared retry runner\n *\n * Expects:\n * - `apiKey` and `baseURL` to point at an OpenAI-compatible endpoint\n * - `retryOptions` to follow the same invariants as `createRetryPolicy`\n */\nexport function createOpenAIProviderAdapter(apiKey: string, baseURL?: string, retryOptions: RetryPolicyOptions = {}): OpenAIProviderAdapter {\n return createProviderAdapter(createOpenAI(apiKey, baseURL), retryOptions)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["defaultSleep"],"sources":["../../../src/core/inference-executors/retry-policy.ts","../../../src/core/inference-executors/adapters.ts","../../../src/core/inference-executors/remote-providers/openai/index.ts"],"sourcesContent":["import { sleep as defaultSleep, errorMessageFrom, errorNameFrom } from '@moeru/std'\n\n/**\n * Describes how provider retries should behave.\n *\n * ASCII flow:\n * attempt -> run request -> success return\n * attempt -> run request -> retriable failure -> sleep -> next attempt\n * attempt -> run request -> non-retriable failure -> throw\n */\nexport interface RetryPolicy {\n /**\n * Maximum number of total attempts, including the first try.\n */\n maxAttempts: number\n /**\n * Returns the wait time for a retry attempt.\n */\n delayMs: (attempt: number) => number\n /**\n * Determines whether an error can be retried safely.\n */\n shouldRetry: (error: unknown) => boolean\n /**\n * Suspends execution between retries.\n */\n sleep: (milliseconds: number) => Promise<void>\n}\n\n/**\n * Configures a retry policy before a provider call is executed.\n *\n * Use when:\n * - you want the default retry classifier but need to tune attempts or delay\n * - you need to replace the sleeper in tests\n *\n * Expects:\n * - `maxAttempts` to be a finite integer greater than or equal to `1`\n * - `delayMs` to return a non-negative wait time in milliseconds\n */\nexport interface RetryPolicyOptions {\n /**\n * Maximum total attempts, including the first request.\n *\n * @default 3\n */\n maxAttempts?: number\n /**\n * Computes the delay for a retry attempt.\n *\n * The attempt number starts at `1` for the first retry.\n */\n delayMs?: (attempt: number) => number\n /**\n * Overrides the retry classifier.\n */\n shouldRetry?: (error: unknown) => boolean\n /**\n * Overrides the sleeper used between attempts.\n */\n sleep?: (milliseconds: number) => Promise<void>\n}\n\nconst retryableStatusCodes = new Set([408, 425, 429, 500, 502, 503, 504])\nconst retryableErrorNames = new Set(['TimeoutError', 'FetchError'])\nconst retryableMessagePatterns = [\n /rate limit/i,\n /rate-limited/i,\n /temporarily unavailable/i,\n /service unavailable/i,\n /server error/i,\n /fetch failed/i,\n /network error/i,\n /socket hang up/i,\n /econnreset/i,\n /econnrefused/i,\n /eai_again/i,\n /etimedout/i,\n /timed out/i,\n /timeout/i,\n]\n\nfunction getStatusCode(error: unknown): number | undefined {\n if (error == null || typeof error !== 'object') {\n return undefined\n }\n\n const maybeStatusCode = (error as { statusCode?: unknown }).statusCode\n if (typeof maybeStatusCode === 'number') {\n return maybeStatusCode\n }\n\n const maybeStatus = (error as { status?: unknown }).status\n if (typeof maybeStatus === 'number') {\n return maybeStatus\n }\n\n const response = (error as { response?: unknown }).response\n if (response == null || typeof response !== 'object') {\n return undefined\n }\n\n const responseStatus = (response as { status?: unknown }).status\n return typeof responseStatus === 'number' ? responseStatus : undefined\n}\n\n/**\n * Returns true when a provider failure is temporary and a retry is reasonable.\n *\n * Use when:\n * - the upstream failure is a transport problem or a 5xx/429 response\n *\n * Expects:\n * - provider errors to expose a status code, name, or message when possible\n */\nexport function isRetriableProviderError(error: unknown): boolean {\n const statusCode = getStatusCode(error)\n\n if (statusCode != null) {\n return retryableStatusCodes.has(statusCode)\n }\n\n const errorName = errorNameFrom(error)\n if (errorName != null && retryableErrorNames.has(errorName)) {\n return true\n }\n\n const errorMessage = errorMessageFrom(error)\n if (errorMessage == null) {\n return false\n }\n\n return retryableMessagePatterns.some(pattern => pattern.test(errorMessage))\n}\n\nfunction defaultDelayMs(attempt: number): number {\n return 500 * 2 ** (attempt - 1)\n}\n\n/**\n * Creates a retry policy for provider work.\n *\n * Use when:\n * - you need a reusable retry runner for eval-time provider calls\n * - you want to keep retry behavior deterministic in tests\n *\n * Expects:\n * - callers to treat `maxAttempts` as total attempts, not retries\n *\n * Throws:\n * - `RangeError` when `maxAttempts` is not a finite integer greater than or equal to `1`\n */\nfunction assertValidMaxAttempts(value: number): number {\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1) {\n throw new RangeError('maxAttempts must be a finite integer greater than or equal to 1.')\n }\n\n return value\n}\n\nexport function createRetryPolicy(options: RetryPolicyOptions = {}): RetryPolicy {\n const maxAttempts = assertValidMaxAttempts(options.maxAttempts ?? 3)\n\n return {\n maxAttempts,\n delayMs: options.delayMs ?? defaultDelayMs,\n shouldRetry: options.shouldRetry ?? isRetriableProviderError,\n sleep: options.sleep ?? defaultSleep,\n }\n}\n\n/**\n * Runs an operation with bounded retries.\n *\n * Use when:\n * - you are calling an LLM provider or other temporary upstream dependency\n * - non-retriable failures should bubble immediately\n *\n * Expects:\n * - the operation to be idempotent across attempts\n */\nexport async function runWithRetry<T>(operation: () => Promise<T>, policy: RetryPolicy = createRetryPolicy()): Promise<T> {\n for (let attempt = 1; attempt <= policy.maxAttempts; attempt += 1) {\n try {\n return await operation()\n }\n catch (error) {\n if (attempt >= policy.maxAttempts || !policy.shouldRetry(error)) {\n throw error\n }\n\n const delayMilliseconds = policy.delayMs(attempt)\n if (delayMilliseconds > 0) {\n await policy.sleep(delayMilliseconds)\n }\n }\n }\n\n throw new Error('Retry loop exited without returning a value.')\n}\n","import type { RetryPolicy, RetryPolicyOptions } from './retry-policy'\n\nimport { createRetryPolicy, runWithRetry } from './retry-policy'\n\n/**\n * Bundles a provider with the retry policy used to call it.\n *\n * Use when:\n * - a provider instance should travel with the retry runner that governs it\n * - you want call sites to share one retry configuration object\n */\nexport interface ProviderAdapter<TProvider> {\n /**\n * The underlying provider instance.\n */\n provider: TProvider\n /**\n * The retry policy used for provider calls.\n */\n retryPolicy: RetryPolicy\n /**\n * Runs a provider-dependent operation with the adapter retry policy.\n */\n runWithRetry: <TResult>(operation: () => Promise<TResult>) => Promise<TResult>\n}\n\n/**\n * Creates a provider adapter with the default retry policy.\n *\n * Use when:\n * - you have a provider instance and want a consistent retry wrapper\n *\n * Expects:\n * - the provider to be safe to reuse across attempts\n */\nexport function createProviderAdapter<TProvider>(provider: TProvider, options: RetryPolicyOptions = {}): ProviderAdapter<TProvider> {\n const retryPolicy = createRetryPolicy(options)\n\n return {\n provider,\n retryPolicy,\n runWithRetry: operation => runWithRetry(operation, retryPolicy),\n }\n}\n","import type { ProviderAdapter } from '../../adapters'\nimport type { RetryPolicyOptions } from '../../retry-policy'\n\nimport process from 'node:process'\n\nimport { createOpenAI } from '@xsai-ext/providers/create'\n\nimport { createProviderAdapter } from '../../adapters'\nimport { envFrom, requiredEnvFrom } from '../../env'\n\n/**\n * Represents the OpenAI provider instance returned by xsai.\n */\nexport type OpenAIProvider = ReturnType<typeof createOpenAI>\n\n/**\n * Represents the OpenAI adapter used by vieval.\n */\nexport type OpenAIProviderAdapter = ProviderAdapter<OpenAIProvider>\n\n/**\n * Configures env key names and source for OpenAI provider setup.\n */\nexport interface OpenAIEnvSourceOptions {\n /**\n * Environment object used for variable lookup.\n *\n * @default process.env\n */\n env?: NodeJS.ProcessEnv\n /**\n * Env key name for API key.\n *\n * @default 'OPENAI_API_KEY'\n */\n apiKey?: string\n /**\n * Env key name for base URL.\n *\n * @default 'OPENAI_BASE_URL'\n */\n baseURL?: string\n /**\n * Env key name for model.\n *\n * @default 'OPENAI_MODEL'\n */\n model?: string\n}\n\n/**\n * Configures fallback defaults when env values are missing.\n */\nexport interface OpenAIFromEnvDefaultOptions {\n /**\n * API key fallback value.\n */\n apiKey?: string\n /**\n * Base URL fallback value.\n */\n baseURL?: string\n /**\n * Model fallback value.\n */\n model?: string\n /**\n * Retry policy override passed to provider adapter.\n */\n retryOptions?: RetryPolicyOptions\n}\n\n/**\n * Result produced by `createOpenAIFromEnv`.\n */\nexport interface OpenAIFromEnvResult {\n adapter: OpenAIProviderAdapter\n apiKey: string\n baseURL?: string\n model: string\n}\n\n/**\n * Minimal response shape returned by text-generation calls.\n */\nexport interface OpenAITextGenerationResult {\n /**\n * Text output from the provider.\n *\n * Some OpenAI-compatible implementations may return `null`.\n */\n text?: string | null\n}\n\n/**\n * Normalizes provider text output to a safe string.\n *\n * Before: `{ text: null }`\n * After: `''`\n *\n * Before: `{ text: 'hello' }`\n * After: `'hello'`\n */\nexport function normalizeOpenAITextOutput(result: OpenAITextGenerationResult): string {\n return typeof result.text === 'string' ? result.text : ''\n}\n\n/**\n * Creates an OpenAI provider adapter using environment variables with defaults.\n *\n * Example:\n * `const runtime = createOpenAIFromEnv({}, { model: 'gpt-4.1-mini' })`\n */\nexport function createOpenAIFromEnv(\n source: OpenAIEnvSourceOptions = {},\n defaults: OpenAIFromEnvDefaultOptions = {},\n): OpenAIFromEnvResult {\n const env = source.env ?? process.env\n const apiKeyEnvKey = source.apiKey ?? 'OPENAI_API_KEY'\n const baseURLEnvKey = source.baseURL ?? 'OPENAI_BASE_URL'\n const modelEnvKey = source.model ?? 'OPENAI_MODEL'\n\n const apiKey = requiredEnvFrom(env[apiKeyEnvKey] ?? defaults.apiKey, {\n name: apiKeyEnvKey,\n type: 'string',\n })\n const model = requiredEnvFrom(env[modelEnvKey] ?? defaults.model, {\n name: modelEnvKey,\n type: 'string',\n })\n const baseURL = envFrom(env[baseURLEnvKey] ?? defaults.baseURL, {\n name: baseURLEnvKey,\n type: 'string',\n })\n const adapter = createOpenAIProviderAdapter(apiKey, baseURL, defaults.retryOptions)\n\n return {\n adapter,\n apiKey,\n baseURL,\n model,\n }\n}\n\n/**\n * Creates an OpenAI provider adapter for eval-time requests.\n *\n * Use when:\n * - an eval needs the OpenAI SDK surface plus the shared retry runner\n *\n * Expects:\n * - `apiKey` and `baseURL` to point at an OpenAI-compatible endpoint\n * - `retryOptions` to follow the same invariants as `createRetryPolicy`\n */\nexport function createOpenAIProviderAdapter(apiKey: string, baseURL?: string, retryOptions: RetryPolicyOptions = {}): OpenAIProviderAdapter {\n return createProviderAdapter(createOpenAI(apiKey, baseURL), retryOptions)\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { I as AggregatedRunResults } from "../../../index-DP7jsORl.mjs";
1
+ import { B as AggregatedRunResults } from "../../../index-BDMEAmf2.mjs";
2
2
 
3
3
  //#region src/core/processors/results/policies/hybrid-threshold.d.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { A as asProjectRelativePath, B as RunScoreKind, C as RunnerTaskState, D as TaskExecutionContext, E as CreateTaskExecutionContextOptions, F as AggregatedProviderSummary, G as RunnerMatrixInput, H as CreateRunnerScheduleOptions, I as AggregatedRunResults, J as ScheduledTaskMatrix, K as RunnerMatrixSelection, L as AggregatedRunSummary, M as CreateVievalRunnerRuntimeContextOptions, N as RunnerRuntimeContext, O as TaskModelSelectionOptions, P as createRunnerRuntimeContext, R as RunResult, S as RunnerExecutionError, T as runScheduledTasks, U as InferenceExecutor, V as aggregateRunResults, W as RunnerMatrixDefinition, X as createRunnerSchedule, Y as ScheduledTaskMatrixMeta, j as collectEvalEntries, k as createTaskExecutionContext, q as ScheduledTask, w as ScheduledTaskExecutor, x as RunScheduledTasksOptions, z as RunScore } from "../../index-DP7jsORl.mjs";
2
- export { AggregatedProviderSummary, AggregatedRunResults, AggregatedRunSummary, CreateRunnerScheduleOptions, CreateTaskExecutionContextOptions, CreateVievalRunnerRuntimeContextOptions, InferenceExecutor, RunResult, RunScheduledTasksOptions, RunScore, RunScoreKind, RunnerExecutionError, RunnerMatrixDefinition, RunnerMatrixInput, RunnerMatrixSelection, RunnerRuntimeContext, RunnerTaskState, ScheduledTask, ScheduledTaskExecutor, ScheduledTaskMatrix, ScheduledTaskMatrixMeta, TaskExecutionContext, TaskModelSelectionOptions, aggregateRunResults, asProjectRelativePath, collectEvalEntries, createRunnerRuntimeContext, createRunnerSchedule, createTaskExecutionContext, runScheduledTasks };
1
+ import { $ as ScheduledTaskMatrixMeta, A as TaskModelSelectionOptions, B as AggregatedRunResults, C as RunScheduledTasksOptions, D as runScheduledTasks, E as ScheduledTaskExecutor, F as collectEvalEntries, G as aggregateRunResults, H as RunResult, I as CreateVievalRunnerRuntimeContextOptions, J as RunnerMatrixDefinition, K as CreateRunnerScheduleOptions, L as RunnerRuntimeContext, O as CreateTaskExecutionContextOptions, P as asProjectRelativePath, Q as ScheduledTaskMatrix, R as createRunnerRuntimeContext, T as RunnerTaskState, U as RunScore, V as AggregatedRunSummary, W as RunScoreKind, X as RunnerMatrixSelection, Y as RunnerMatrixInput, Z as ScheduledTask, at as CacheFileOptions, et as createRunnerSchedule, it as CacheFileHandle, j as createTaskExecutionContext, k as TaskExecutionContext, nt as createFilesystemTaskCacheRuntime, ot as CacheNamespace, q as InferenceExecutor, rt as normalizeCacheFilePathSegments, st as TaskCacheRuntime, tt as CreateFilesystemTaskCacheRuntimeOptions, w as RunnerExecutionError, z as AggregatedProviderSummary } from "../../index-BDMEAmf2.mjs";
2
+ export { AggregatedProviderSummary, AggregatedRunResults, AggregatedRunSummary, CacheFileHandle, CacheFileOptions, CacheNamespace, CreateFilesystemTaskCacheRuntimeOptions, CreateRunnerScheduleOptions, CreateTaskExecutionContextOptions, CreateVievalRunnerRuntimeContextOptions, InferenceExecutor, RunResult, RunScheduledTasksOptions, RunScore, RunScoreKind, RunnerExecutionError, RunnerMatrixDefinition, RunnerMatrixInput, RunnerMatrixSelection, RunnerRuntimeContext, RunnerTaskState, ScheduledTask, ScheduledTaskExecutor, ScheduledTaskMatrix, ScheduledTaskMatrixMeta, TaskCacheRuntime, TaskExecutionContext, TaskModelSelectionOptions, aggregateRunResults, asProjectRelativePath, collectEvalEntries, createFilesystemTaskCacheRuntime, createRunnerRuntimeContext, createRunnerSchedule, createTaskExecutionContext, normalizeCacheFilePathSegments, runScheduledTasks };
@@ -1,2 +1,2 @@
1
- import { a as runScheduledTasks, c as aggregateRunResults, i as RunnerExecutionError, n as createRunnerSchedule, o as asProjectRelativePath, r as createRunnerRuntimeContext, s as collectEvalEntries, t as createTaskExecutionContext } from "../../runner-4ZsOveoY.mjs";
2
- export { RunnerExecutionError, aggregateRunResults, asProjectRelativePath, collectEvalEntries, createRunnerRuntimeContext, createRunnerSchedule, createTaskExecutionContext, runScheduledTasks };
1
+ import { a as runScheduledTasks, c as aggregateRunResults, i as RunnerExecutionError, l as createFilesystemTaskCacheRuntime, n as createRunnerSchedule, o as asProjectRelativePath, r as createRunnerRuntimeContext, s as collectEvalEntries, t as createTaskExecutionContext, u as normalizeCacheFilePathSegments } from "../../runner-Dpy-eivM.mjs";
2
+ export { RunnerExecutionError, aggregateRunResults, asProjectRelativePath, collectEvalEntries, createFilesystemTaskCacheRuntime, createRunnerRuntimeContext, createRunnerSchedule, createTaskExecutionContext, normalizeCacheFilePathSegments, runScheduledTasks };
@@ -0,0 +1,41 @@
1
+ //#region src/core/inference-executors/env.ts
2
+ function assertNonEmptyString(value, options) {
3
+ if (value == null || value.trim().length === 0) {
4
+ if (options.required === true) {
5
+ const label = options.name ?? "environment variable";
6
+ throw new Error(`Missing required ${label}.`);
7
+ }
8
+ return;
9
+ }
10
+ return value;
11
+ }
12
+ /**
13
+ * Parses one env value with optional required behavior.
14
+ *
15
+ * Example:
16
+ * `const apiKey = envFrom(process.env.OPENAI_API_KEY, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`
17
+ */
18
+ function envFrom(value, options) {
19
+ if (options.type === "string") return assertNonEmptyString(value, options);
20
+ }
21
+ /**
22
+ * Parses one required env value.
23
+ *
24
+ * Example:
25
+ * `const apiKey = requiredEnvFrom(process.env.OPENAI_API_KEY, { type: 'string', name: 'OPENAI_API_KEY' })`
26
+ */
27
+ function requiredEnvFrom(value, options) {
28
+ const parsed = envFrom(value, {
29
+ ...options,
30
+ required: true
31
+ });
32
+ if (parsed == null) {
33
+ const label = options.name ?? "environment variable";
34
+ throw new Error(`Missing required ${label}.`);
35
+ }
36
+ return parsed;
37
+ }
38
+ //#endregion
39
+ export { requiredEnvFrom as n, envFrom as t };
40
+
41
+ //# sourceMappingURL=env-C7X81PWa.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-C7X81PWa.mjs","names":[],"sources":["../src/core/inference-executors/env.ts"],"sourcesContent":["/**\n * Supported env value coercion types.\n */\nexport type EnvValueType = 'string'\n\n/**\n * Common options for env readers.\n */\nexport interface EnvFromOptions {\n /**\n * Expected env value type.\n */\n type: EnvValueType\n /**\n * Whether an empty or missing value should throw.\n *\n * @default false\n */\n required?: boolean\n /**\n * Optional key name used for clearer error messages.\n */\n name?: string\n}\n\n/**\n * Env options used by the required helper.\n *\n * `required` is intentionally omitted because this helper is always required.\n */\nexport type RequiredEnvFromOptions = Omit<EnvFromOptions, 'required'>\n\nfunction assertNonEmptyString(value: string | undefined, options: EnvFromOptions): string | undefined {\n if (value == null || value.trim().length === 0) {\n if (options.required === true) {\n const label = options.name ?? 'environment variable'\n throw new Error(`Missing required ${label}.`)\n }\n\n return undefined\n }\n\n return value\n}\n\n/**\n * Parses one env value with optional required behavior.\n *\n * Example:\n * `const apiKey = envFrom(process.env.OPENAI_API_KEY, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`\n */\nexport function envFrom(\n value: string | undefined,\n options: EnvFromOptions,\n): string | undefined {\n if (options.type === 'string') {\n return assertNonEmptyString(value, options)\n }\n\n return undefined\n}\n\n/**\n * Parses one required env value.\n *\n * Example:\n * `const apiKey = requiredEnvFrom(process.env.OPENAI_API_KEY, { type: 'string', name: 'OPENAI_API_KEY' })`\n */\nexport function requiredEnvFrom(\n value: string | undefined,\n options: RequiredEnvFromOptions,\n): string {\n const parsed = envFrom(value, {\n ...options,\n required: true,\n })\n\n if (parsed == null) {\n const label = options.name ?? 'environment variable'\n throw new Error(`Missing required ${label}.`)\n }\n\n return parsed\n}\n"],"mappings":";AAgCA,SAAS,qBAAqB,OAA2B,SAA6C;AACpG,KAAI,SAAS,QAAQ,MAAM,MAAM,CAAC,WAAW,GAAG;AAC9C,MAAI,QAAQ,aAAa,MAAM;GAC7B,MAAM,QAAQ,QAAQ,QAAQ;AAC9B,SAAM,IAAI,MAAM,oBAAoB,MAAM,GAAG;;AAG/C;;AAGF,QAAO;;;;;;;;AAST,SAAgB,QACd,OACA,SACoB;AACpB,KAAI,QAAQ,SAAS,SACnB,QAAO,qBAAqB,OAAO,QAAQ;;;;;;;;AAY/C,SAAgB,gBACd,OACA,SACQ;CACR,MAAM,SAAS,QAAQ,OAAO;EAC5B,GAAG;EACH,UAAU;EACX,CAAC;AAEF,KAAI,UAAU,MAAM;EAClB,MAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAM,IAAI,MAAM,oBAAoB,MAAM,GAAG;;AAG/C,QAAO"}
@@ -0,0 +1,47 @@
1
+ //#region src/core/inference-executors/env.d.ts
2
+ /**
3
+ * Supported env value coercion types.
4
+ */
5
+ type EnvValueType = 'string';
6
+ /**
7
+ * Common options for env readers.
8
+ */
9
+ interface EnvFromOptions {
10
+ /**
11
+ * Expected env value type.
12
+ */
13
+ type: EnvValueType;
14
+ /**
15
+ * Whether an empty or missing value should throw.
16
+ *
17
+ * @default false
18
+ */
19
+ required?: boolean;
20
+ /**
21
+ * Optional key name used for clearer error messages.
22
+ */
23
+ name?: string;
24
+ }
25
+ /**
26
+ * Env options used by the required helper.
27
+ *
28
+ * `required` is intentionally omitted because this helper is always required.
29
+ */
30
+ type RequiredEnvFromOptions = Omit<EnvFromOptions, 'required'>;
31
+ /**
32
+ * Parses one env value with optional required behavior.
33
+ *
34
+ * Example:
35
+ * `const apiKey = envFrom(process.env.OPENAI_API_KEY, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`
36
+ */
37
+ declare function envFrom(value: string | undefined, options: EnvFromOptions): string | undefined;
38
+ /**
39
+ * Parses one required env value.
40
+ *
41
+ * Example:
42
+ * `const apiKey = requiredEnvFrom(process.env.OPENAI_API_KEY, { type: 'string', name: 'OPENAI_API_KEY' })`
43
+ */
44
+ declare function requiredEnvFrom(value: string | undefined, options: RequiredEnvFromOptions): string;
45
+ //#endregion
46
+ export { requiredEnvFrom as a, envFrom as i, EnvValueType as n, RequiredEnvFromOptions as r, EnvFromOptions as t };
47
+ //# sourceMappingURL=env-DtpjACOW.d.mts.map
@@ -0,0 +1,10 @@
1
+ import * as _$vitest from "vitest";
2
+
3
+ //#region src/expect.d.ts
4
+ /**
5
+ * Re-exported expect with vieval custom matchers pre-installed.
6
+ */
7
+ declare const expect: _$vitest.ExpectStatic;
8
+ //#endregion
9
+ export { expect as t };
10
+ //# sourceMappingURL=expect-B2vaoRVZ.d.mts.map
@@ -1,4 +1,4 @@
1
- import { n as globalExpect, t as installVievalExpectMatchers } from "./expect-extensions-CwPtgTz8.mjs";
1
+ import { n as getRuntimeExpect, t as installVievalExpectMatchers } from "./expect-extensions-BOzwV5EJ.mjs";
2
2
  //#region src/expect.ts
3
3
  let isInstalled = false;
4
4
  function ensureExpectMatchersInstalled() {
@@ -10,8 +10,8 @@ ensureExpectMatchersInstalled();
10
10
  /**
11
11
  * Re-exported expect with vieval custom matchers pre-installed.
12
12
  */
13
- const expect = globalExpect;
13
+ const expect = getRuntimeExpect();
14
14
  //#endregion
15
15
  export { expect as t };
16
16
 
17
- //# sourceMappingURL=expect-i9WZWGrA.mjs.map
17
+ //# sourceMappingURL=expect-CaXiUkwY.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect-CaXiUkwY.mjs","names":[],"sources":["../src/expect.ts"],"sourcesContent":["import { installVievalExpectMatchers } from './testing/expect-extensions'\nimport { getRuntimeExpect } from './testing/runtime-expect'\n\nlet isInstalled = false\n\nfunction ensureExpectMatchersInstalled(): void {\n if (isInstalled) {\n return\n }\n\n installVievalExpectMatchers()\n isInstalled = true\n}\n\nensureExpectMatchersInstalled()\n\n/**\n * Re-exported expect with vieval custom matchers pre-installed.\n */\nexport const expect = getRuntimeExpect()\n"],"mappings":";;AAGA,IAAI,cAAc;AAElB,SAAS,gCAAsC;AAC7C,KAAI,YACF;AAGF,8BAA6B;AAC7B,eAAc;;AAGhB,+BAA+B;;;;AAK/B,MAAa,SAAS,kBAAkB"}
@@ -0,0 +1,197 @@
1
+ import { d as normalizeMatchText } from "./assertions-DcAjfVDA.mjs";
2
+ import { ASYMMETRIC_MATCHERS_OBJECT, ChaiStyleAssertions, GLOBAL_EXPECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, addCustomEqualityTesters, chai, customMatchers, getState, setState } from "@vitest/expect";
3
+ //#region src/testing/runtime-expect.ts
4
+ let isPluginInstalled = false;
5
+ let runtimeExpectInstance;
6
+ /**
7
+ * Installs Vitest expect plugins once for process-local runtime assertions.
8
+ *
9
+ * Use when:
10
+ * - running eval tasks outside Vitest worker runtime
11
+ * - building an `expect` instance that does not rely on Vitest internal state
12
+ *
13
+ * Expects:
14
+ * - `@vitest/expect` is available in runtime dependencies
15
+ *
16
+ * Returns:
17
+ * - nothing; side-effects are applied to `chai`
18
+ */
19
+ function ensureRuntimeExpectPluginsInstalled() {
20
+ if (isPluginInstalled) return;
21
+ chai.use(JestExtend);
22
+ chai.use(JestChaiExpect);
23
+ chai.use(ChaiStyleAssertions);
24
+ chai.use(JestAsymmetricMatchers);
25
+ isPluginInstalled = true;
26
+ }
27
+ /**
28
+ * Creates a Vitest-compatible `expect` instance without worker-state coupling.
29
+ *
30
+ * Use when:
31
+ * - CLI runtime needs assertion helpers from `vieval/expect`
32
+ * - code is executed outside `vitest run`
33
+ *
34
+ * Expects:
35
+ * - plugins from {@link ensureRuntimeExpectPluginsInstalled} are installed
36
+ * - callers do not depend on Vitest worker-only features (snapshot/poll internals)
37
+ *
38
+ * Returns:
39
+ * - standalone expect instance with core matcher APIs and `extend`
40
+ */
41
+ function createRuntimeExpect() {
42
+ ensureRuntimeExpectPluginsInstalled();
43
+ const runtimeExpect = ((value, message) => {
44
+ setState({ assertionCalls: getState(runtimeExpect).assertionCalls + 1 }, runtimeExpect);
45
+ return chai.expect(value, message);
46
+ });
47
+ Object.assign(runtimeExpect, chai.expect);
48
+ Object.assign(runtimeExpect, globalThis[ASYMMETRIC_MATCHERS_OBJECT]);
49
+ runtimeExpect.getState = () => getState(runtimeExpect);
50
+ runtimeExpect.setState = (state) => setState(state, runtimeExpect);
51
+ runtimeExpect.assert = chai.assert;
52
+ const chaiExpectWithExtend = chai.expect;
53
+ runtimeExpect.extend = (matchers) => chaiExpectWithExtend.extend(runtimeExpect, matchers);
54
+ runtimeExpect.addEqualityTesters = (customTesters) => addCustomEqualityTesters(customTesters);
55
+ runtimeExpect.unreachable = (message) => {
56
+ chai.assert.fail(`expected${message ? ` "${message}" ` : " "}not to be reached`);
57
+ };
58
+ runtimeExpect.setState({
59
+ assertionCalls: 0,
60
+ currentTestName: "",
61
+ expectedAssertionsNumber: null,
62
+ expectedAssertionsNumberErrorGen: null,
63
+ isExpectingAssertions: false,
64
+ isExpectingAssertionsError: null
65
+ });
66
+ runtimeExpect.extend(customMatchers);
67
+ return runtimeExpect;
68
+ }
69
+ /**
70
+ * Returns process-local runtime `expect` instance used by Vieval.
71
+ *
72
+ * Use when:
73
+ * - you need matcher assertions in eval files and CLI runtime
74
+ * - importing from `vitest` would crash outside Vitest worker contexts
75
+ *
76
+ * Expects:
77
+ * - single-process usage (instance is memoized per process)
78
+ *
79
+ * Returns:
80
+ * - memoized runtime `expect` instance
81
+ */
82
+ function getRuntimeExpect() {
83
+ if (runtimeExpectInstance != null) return runtimeExpectInstance;
84
+ runtimeExpectInstance = createRuntimeExpect();
85
+ Object.defineProperty(globalThis, GLOBAL_EXPECT, {
86
+ configurable: true,
87
+ value: runtimeExpectInstance,
88
+ writable: true
89
+ });
90
+ return runtimeExpectInstance;
91
+ }
92
+ //#endregion
93
+ //#region src/testing/expect-extensions.ts
94
+ function toKeywordArray(keywords) {
95
+ if (typeof keywords === "string") return [keywords];
96
+ return keywords;
97
+ }
98
+ /**
99
+ * Registers vieval custom matchers on Vitest `expect`.
100
+ *
101
+ * Call stack:
102
+ *
103
+ * {@link installVievalExpectMatchers}
104
+ * -> `expect.extend(...)`
105
+ * -> `expect(received).toMustInclude(...)`
106
+ * -> `expect(received).toScoreRubricGreaterThan(...)`
107
+ *
108
+ * Use when:
109
+ * - eval suites need domain assertions while preserving native Vitest ergonomics
110
+ * - callers want native `.not` chaining with the same matchers
111
+ */
112
+ function installVievalExpectMatchers() {
113
+ getRuntimeExpect().extend({
114
+ toMustExclude(received, keywords, options = {}) {
115
+ const keywordList = toKeywordArray(keywords);
116
+ if (typeof received !== "string") return {
117
+ message: () => "Expected received value to be a string.",
118
+ pass: false
119
+ };
120
+ const normalizedText = normalizeMatchText(received, options.caseSensitive ?? false);
121
+ const forbiddenMatches = keywordList.filter((keyword) => {
122
+ return normalizedText.includes(normalizeMatchText(keyword, options.caseSensitive ?? false));
123
+ });
124
+ const pass = forbiddenMatches.length === 0;
125
+ return {
126
+ message: () => {
127
+ if (pass) return `Expected text to include forbidden keywords: ${keywordList.join(", ")}`;
128
+ return `Expected text not to include forbidden keywords, but matched: ${forbiddenMatches.join(", ")}`;
129
+ },
130
+ pass
131
+ };
132
+ },
133
+ toMustInclude(received, keywords, options = {}) {
134
+ const keywordList = toKeywordArray(keywords);
135
+ if (typeof received !== "string") return {
136
+ message: () => "Expected received value to be a string.",
137
+ pass: false
138
+ };
139
+ const normalizedText = normalizeMatchText(received, options.caseSensitive ?? false);
140
+ const matches = keywordList.filter((keyword) => {
141
+ return normalizedText.includes(normalizeMatchText(keyword, options.caseSensitive ?? false));
142
+ });
143
+ const mode = options.mode ?? "all";
144
+ const pass = mode === "all" ? matches.length === keywordList.length : matches.length > 0;
145
+ return {
146
+ message: () => {
147
+ if (pass) return `Expected text not to match required keywords, but matched: ${matches.join(", ")}`;
148
+ return `Expected text to match required keywords (${mode}), but matched ${matches.length}/${keywordList.length}.`;
149
+ },
150
+ pass
151
+ };
152
+ },
153
+ toScoreRubricGreaterThan(received, threshold) {
154
+ const score = typeof received === "number" ? received : received?.score;
155
+ if (typeof score !== "number") return {
156
+ message: () => "Expected received value to be a number or RubricJudgeResult.",
157
+ pass: false
158
+ };
159
+ const pass = score > threshold;
160
+ return {
161
+ message: () => {
162
+ if (pass) return `Expected rubric score ${score} to be less than or equal to ${threshold}.`;
163
+ return `Expected rubric score ${score} to be greater than ${threshold}.`;
164
+ },
165
+ pass
166
+ };
167
+ },
168
+ toSatisfyStructuredOutput(received, validator) {
169
+ const pass = validator(received);
170
+ return {
171
+ message: () => pass ? "Expected structured output validator to fail." : "Expected structured output validator to pass.",
172
+ pass
173
+ };
174
+ },
175
+ toSatisfyToolCallArgs(received, toolName, validator) {
176
+ const toolCalls = received?.toolCalls;
177
+ if (toolCalls == null) return {
178
+ message: () => "Expected received value to provide toolCalls array.",
179
+ pass: false
180
+ };
181
+ const targetCall = toolCalls.find((call) => call.name === toolName);
182
+ if (targetCall == null) return {
183
+ message: () => `Expected tool call ${toolName} to exist.`,
184
+ pass: false
185
+ };
186
+ const pass = validator(targetCall.args);
187
+ return {
188
+ message: () => pass ? `Expected tool call args for ${toolName} to fail validation.` : `Expected tool call args for ${toolName} to pass validation.`,
189
+ pass
190
+ };
191
+ }
192
+ });
193
+ }
194
+ //#endregion
195
+ export { getRuntimeExpect as n, installVievalExpectMatchers as t };
196
+
197
+ //# sourceMappingURL=expect-extensions-BOzwV5EJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expect-extensions-BOzwV5EJ.mjs","names":[],"sources":["../src/testing/runtime-expect.ts","../src/testing/expect-extensions.ts"],"sourcesContent":["import type { ExpectStatic, MatchersObject, MatcherState, Tester } from '@vitest/expect'\n\nimport {\n addCustomEqualityTesters,\n ASYMMETRIC_MATCHERS_OBJECT,\n chai,\n ChaiStyleAssertions,\n customMatchers,\n getState,\n GLOBAL_EXPECT,\n JestAsymmetricMatchers,\n JestChaiExpect,\n JestExtend,\n setState,\n} from '@vitest/expect'\n\nlet isPluginInstalled = false\nlet runtimeExpectInstance: ExpectStatic | undefined\n\n/**\n * Installs Vitest expect plugins once for process-local runtime assertions.\n *\n * Use when:\n * - running eval tasks outside Vitest worker runtime\n * - building an `expect` instance that does not rely on Vitest internal state\n *\n * Expects:\n * - `@vitest/expect` is available in runtime dependencies\n *\n * Returns:\n * - nothing; side-effects are applied to `chai`\n */\nfunction ensureRuntimeExpectPluginsInstalled(): void {\n if (isPluginInstalled) {\n return\n }\n\n chai.use(JestExtend)\n chai.use(JestChaiExpect)\n chai.use(ChaiStyleAssertions)\n chai.use(JestAsymmetricMatchers)\n isPluginInstalled = true\n}\n\n/**\n * Creates a Vitest-compatible `expect` instance without worker-state coupling.\n *\n * Use when:\n * - CLI runtime needs assertion helpers from `vieval/expect`\n * - code is executed outside `vitest run`\n *\n * Expects:\n * - plugins from {@link ensureRuntimeExpectPluginsInstalled} are installed\n * - callers do not depend on Vitest worker-only features (snapshot/poll internals)\n *\n * Returns:\n * - standalone expect instance with core matcher APIs and `extend`\n */\nfunction createRuntimeExpect(): ExpectStatic {\n ensureRuntimeExpectPluginsInstalled()\n\n const runtimeExpect = ((value: unknown, message?: string) => {\n const currentState = getState(runtimeExpect)\n setState({ assertionCalls: currentState.assertionCalls + 1 }, runtimeExpect)\n return chai.expect(value, message)\n }) as unknown as ExpectStatic\n\n Object.assign(runtimeExpect, chai.expect)\n Object.assign(runtimeExpect, (globalThis as Record<PropertyKey, unknown>)[ASYMMETRIC_MATCHERS_OBJECT] as object)\n\n runtimeExpect.getState = () => getState(runtimeExpect)\n runtimeExpect.setState = (state: Partial<MatcherState>) => setState(state, runtimeExpect)\n runtimeExpect.assert = chai.assert\n // NOTICE:\n // Chai's public `ExpectStatic` type does not expose Vitest's plugin-added `extend`.\n // Runtime `chai.expect.extend` exists after `JestExtend` plugin installation.\n // Source/context: `@vitest/expect` plugin pipeline in `dist/index.js`.\n // Removal condition: remove this cast if upstream exposes `extend` on Chai expect types.\n const chaiExpectWithExtend = chai.expect as unknown as {\n extend: (expect: ExpectStatic, matchers: MatchersObject) => void\n }\n runtimeExpect.extend = (matchers: MatchersObject) => chaiExpectWithExtend.extend(runtimeExpect, matchers)\n runtimeExpect.addEqualityTesters = (customTesters: Tester[]) => addCustomEqualityTesters(customTesters)\n runtimeExpect.unreachable = (message?: string) => {\n chai.assert.fail(`expected${message ? ` \"${message}\" ` : ' '}not to be reached`)\n }\n\n runtimeExpect.setState({\n assertionCalls: 0,\n currentTestName: '',\n expectedAssertionsNumber: null,\n expectedAssertionsNumberErrorGen: null,\n isExpectingAssertions: false,\n isExpectingAssertionsError: null,\n })\n\n runtimeExpect.extend(customMatchers)\n\n return runtimeExpect\n}\n\n/**\n * Returns process-local runtime `expect` instance used by Vieval.\n *\n * Use when:\n * - you need matcher assertions in eval files and CLI runtime\n * - importing from `vitest` would crash outside Vitest worker contexts\n *\n * Expects:\n * - single-process usage (instance is memoized per process)\n *\n * Returns:\n * - memoized runtime `expect` instance\n */\nexport function getRuntimeExpect(): ExpectStatic {\n if (runtimeExpectInstance != null) {\n return runtimeExpectInstance\n }\n\n runtimeExpectInstance = createRuntimeExpect()\n Object.defineProperty(globalThis, GLOBAL_EXPECT, {\n configurable: true,\n value: runtimeExpectInstance,\n writable: true,\n })\n\n return runtimeExpectInstance\n}\n","import type { RubricJudgeResult, ToolCall } from '../core/assertions'\n\nimport { normalizeMatchText } from '../core/assertions'\nimport { getRuntimeExpect } from './runtime-expect'\n\n/**\n * Options for keyword-based matcher behavior.\n */\nexport interface KeywordMatcherOptions {\n /**\n * Case-sensitive matching toggle.\n *\n * @default false\n */\n caseSensitive?: boolean\n /**\n * Match mode.\n *\n * @default 'all'\n */\n mode?: 'all' | 'any'\n}\n\n/**\n * Shape used by tool-call matchers.\n */\nexport interface ToolCallContainer {\n /**\n * Tool calls to inspect.\n */\n toolCalls?: readonly ToolCall[]\n}\n\nfunction toKeywordArray(keywords: string | readonly string[]): readonly string[] {\n if (typeof keywords === 'string') {\n return [keywords]\n }\n\n return keywords\n}\n\n/**\n * Registers vieval custom matchers on Vitest `expect`.\n *\n * Call stack:\n *\n * {@link installVievalExpectMatchers}\n * -> `expect.extend(...)`\n * -> `expect(received).toMustInclude(...)`\n * -> `expect(received).toScoreRubricGreaterThan(...)`\n *\n * Use when:\n * - eval suites need domain assertions while preserving native Vitest ergonomics\n * - callers want native `.not` chaining with the same matchers\n */\nexport function installVievalExpectMatchers(): void {\n const expect = getRuntimeExpect()\n\n expect.extend({\n toMustExclude(received: unknown, keywords: string | readonly string[], options: KeywordMatcherOptions = {}) {\n const keywordList = toKeywordArray(keywords)\n\n if (typeof received !== 'string') {\n return {\n message: () => 'Expected received value to be a string.',\n pass: false,\n }\n }\n\n const normalizedText = normalizeMatchText(received, options.caseSensitive ?? false)\n const forbiddenMatches = keywordList.filter((keyword) => {\n return normalizedText.includes(normalizeMatchText(keyword, options.caseSensitive ?? false))\n })\n\n const pass = forbiddenMatches.length === 0\n\n return {\n message: () => {\n if (pass) {\n return `Expected text to include forbidden keywords: ${keywordList.join(', ')}`\n }\n\n return `Expected text not to include forbidden keywords, but matched: ${forbiddenMatches.join(', ')}`\n },\n pass,\n }\n },\n\n toMustInclude(received: unknown, keywords: string | readonly string[], options: KeywordMatcherOptions = {}) {\n const keywordList = toKeywordArray(keywords)\n\n if (typeof received !== 'string') {\n return {\n message: () => 'Expected received value to be a string.',\n pass: false,\n }\n }\n\n const normalizedText = normalizeMatchText(received, options.caseSensitive ?? false)\n const matches = keywordList.filter((keyword) => {\n return normalizedText.includes(normalizeMatchText(keyword, options.caseSensitive ?? false))\n })\n\n const mode = options.mode ?? 'all'\n const pass = mode === 'all' ? matches.length === keywordList.length : matches.length > 0\n\n return {\n message: () => {\n if (pass) {\n return `Expected text not to match required keywords, but matched: ${matches.join(', ')}`\n }\n\n return `Expected text to match required keywords (${mode}), but matched ${matches.length}/${keywordList.length}.`\n },\n pass,\n }\n },\n\n toScoreRubricGreaterThan(received: unknown, threshold: number) {\n const score = typeof received === 'number'\n ? received\n : (received as RubricJudgeResult | null)?.score\n\n if (typeof score !== 'number') {\n return {\n message: () => 'Expected received value to be a number or RubricJudgeResult.',\n pass: false,\n }\n }\n\n const pass = score > threshold\n\n return {\n message: () => {\n if (pass) {\n return `Expected rubric score ${score} to be less than or equal to ${threshold}.`\n }\n\n return `Expected rubric score ${score} to be greater than ${threshold}.`\n },\n pass,\n }\n },\n\n toSatisfyStructuredOutput<T>(received: unknown, validator: (value: unknown) => value is T) {\n const pass = validator(received)\n\n return {\n message: () => pass\n ? 'Expected structured output validator to fail.'\n : 'Expected structured output validator to pass.',\n pass,\n }\n },\n\n toSatisfyToolCallArgs(\n received: unknown,\n toolName: string,\n validator: (args: unknown) => boolean,\n ) {\n const toolCalls = (received as ToolCallContainer | null)?.toolCalls\n\n if (toolCalls == null) {\n return {\n message: () => 'Expected received value to provide toolCalls array.',\n pass: false,\n }\n }\n\n const targetCall = toolCalls.find(call => call.name === toolName)\n if (targetCall == null) {\n return {\n message: () => `Expected tool call ${toolName} to exist.`,\n pass: false,\n }\n }\n\n const pass = validator(targetCall.args)\n\n return {\n message: () => pass\n ? `Expected tool call args for ${toolName} to fail validation.`\n : `Expected tool call args for ${toolName} to pass validation.`,\n pass,\n }\n },\n })\n}\n\ninterface VievalCustomMatchers {\n /**\n * Asserts that text includes required keywords.\n *\n * Example:\n * `expect('calm answer').toMustInclude(['calm'])`\n */\n toMustInclude: (keywords: string | readonly string[], options?: KeywordMatcherOptions) => void\n /**\n * Asserts that text excludes forbidden keywords.\n *\n * Example:\n * `expect('calm answer').toMustExclude(['bestmove'])`\n */\n toMustExclude: (keywords: string | readonly string[], options?: KeywordMatcherOptions) => void\n /**\n * Asserts rubric score is greater than a threshold.\n *\n * Example:\n * `expect({ score: 0.91 }).toScoreRubricGreaterThan(0.8)`\n */\n toScoreRubricGreaterThan: (threshold: number) => void\n /**\n * Asserts structured output satisfies a validator.\n *\n * Example:\n * `expect(value).toSatisfyStructuredOutput(isMyShape)`\n */\n toSatisfyStructuredOutput: <TValue>(validator: (value: unknown) => value is TValue) => void\n /**\n * Asserts selected tool-call args satisfy validator.\n *\n * Example:\n * `expect({ toolCalls }).toSatisfyToolCallArgs('builtIn_sparkCommand', isSparkArgs)`\n */\n toSatisfyToolCallArgs: (toolName: string, validator: (args: unknown) => boolean) => void\n}\n\n/* eslint-disable unused-imports/no-unused-vars */\ndeclare module '@vitest/expect' {\n interface Matchers<T = any> extends VievalCustomMatchers {}\n interface Assertion<T = any> extends VievalCustomMatchers {}\n}\n\ndeclare module 'vitest' {\n interface Assertion extends VievalCustomMatchers {}\n interface Matchers<T = any> extends VievalCustomMatchers {}\n}\n/* eslint-enable unused-imports/no-unused-vars */\n"],"mappings":"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"}
package/dist/expect.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { t as expect } from "./expect-0jPJ7Zio.mjs";
1
+ import { t as expect } from "./expect-B2vaoRVZ.mjs";
2
2
  export { expect };
package/dist/expect.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as expect } from "./expect-i9WZWGrA.mjs";
1
+ import { t as expect } from "./expect-CaXiUkwY.mjs";
2
2
  export { expect };