vieval 0.0.8 → 0.0.9
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/README.md +24 -2
- package/dist/core/inference-executors/index.d.mts +1 -1
- package/dist/core/inference-executors/index.mjs +10 -4
- package/dist/core/inference-executors/index.mjs.map +1 -1
- package/dist/{env-BeHv_5mo.d.mts → env-DfWZy_n4.d.mts} +14 -9
- package/dist/env-nV5rVErX.mjs +35 -0
- package/dist/env-nV5rVErX.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/chat-models/index.mjs +15 -13
- package/dist/plugins/chat-models/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/env-BFSjny07.mjs +0 -41
- package/dist/env-BFSjny07.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -25,7 +25,9 @@ Vitest-style evaluation framework for agents, models, and task pipelines.
|
|
|
25
25
|
|
|
26
26
|
```ts
|
|
27
27
|
// vieval.config.ts
|
|
28
|
-
import {
|
|
28
|
+
import { cwd } from 'node:process'
|
|
29
|
+
|
|
30
|
+
import { defineConfig, loadEnv, requiredEnvFrom } from 'vieval'
|
|
29
31
|
import { chatModelFrom, ChatModels } from 'vieval/plugins/chat-models'
|
|
30
32
|
|
|
31
33
|
export default defineConfig({
|
|
@@ -34,12 +36,17 @@ export default defineConfig({
|
|
|
34
36
|
models: [
|
|
35
37
|
chatModelFrom({
|
|
36
38
|
aliases: ['agent-mini', 'judge-mini'],
|
|
39
|
+
apiKey: config => requiredEnvFrom(config.env, {
|
|
40
|
+
name: 'OPENAI_API_KEY',
|
|
41
|
+
type: 'string',
|
|
42
|
+
}),
|
|
37
43
|
inferenceExecutor: 'openai',
|
|
38
44
|
model: 'gpt-4.1-mini',
|
|
39
45
|
}),
|
|
40
46
|
],
|
|
41
47
|
}),
|
|
42
48
|
],
|
|
49
|
+
env: loadEnv('test', cwd(), ''),
|
|
43
50
|
projects: [
|
|
44
51
|
{
|
|
45
52
|
name: 'default',
|
|
@@ -162,7 +169,9 @@ Each scheduled task receives stable matrix metadata:
|
|
|
162
169
|
## Config Example
|
|
163
170
|
|
|
164
171
|
```ts
|
|
165
|
-
import {
|
|
172
|
+
import { cwd } from 'node:process'
|
|
173
|
+
|
|
174
|
+
import { defineConfig, loadEnv, requiredEnvFrom } from 'vieval'
|
|
166
175
|
import { chatModelFrom, ChatModels } from 'vieval/plugins/chat-models'
|
|
167
176
|
|
|
168
177
|
export default defineConfig({
|
|
@@ -171,22 +180,35 @@ export default defineConfig({
|
|
|
171
180
|
models: [
|
|
172
181
|
chatModelFrom({
|
|
173
182
|
aliases: ['agent-mini', 'judge-mini'],
|
|
183
|
+
apiKey: config => requiredEnvFrom(config.env, {
|
|
184
|
+
name: 'OPENAI_API_KEY',
|
|
185
|
+
type: 'string',
|
|
186
|
+
}),
|
|
174
187
|
inferenceExecutor: 'openai',
|
|
175
188
|
model: 'gpt-4.1-mini',
|
|
176
189
|
}),
|
|
177
190
|
chatModelFrom({
|
|
178
191
|
aliases: ['agent-large', 'judge-large'],
|
|
192
|
+
apiKey: config => requiredEnvFrom(config.env, {
|
|
193
|
+
name: 'OPENAI_API_KEY',
|
|
194
|
+
type: 'string',
|
|
195
|
+
}),
|
|
179
196
|
inferenceExecutor: 'openai',
|
|
180
197
|
model: 'gpt-4.1',
|
|
181
198
|
}),
|
|
182
199
|
chatModelFrom({
|
|
183
200
|
aliases: ['agent-openrouter-mini'],
|
|
201
|
+
apiKey: config => requiredEnvFrom(config.env, {
|
|
202
|
+
name: 'OPENROUTER_API_KEY',
|
|
203
|
+
type: 'string',
|
|
204
|
+
}),
|
|
184
205
|
inferenceExecutor: 'openrouter',
|
|
185
206
|
model: 'openai/gpt-4.1-mini',
|
|
186
207
|
}),
|
|
187
208
|
],
|
|
188
209
|
}),
|
|
189
210
|
],
|
|
211
|
+
env: loadEnv('test', cwd(), ''),
|
|
190
212
|
projects: [
|
|
191
213
|
{
|
|
192
214
|
name: 'chat-evals',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as requiredEnvFrom, i as envFrom, n as EnvValueType, r as RequiredEnvFromOptions, t as EnvFromOptions } from "../../env-
|
|
1
|
+
import { a as requiredEnvFrom, i as envFrom, n as EnvValueType, r as RequiredEnvFromOptions, t as EnvFromOptions } from "../../env-DfWZy_n4.mjs";
|
|
2
2
|
import { createOpenAI } from "@xsai-ext/providers/create";
|
|
3
3
|
|
|
4
4
|
//#region src/core/inference-executors/retry-policy.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as requiredEnvFrom, t as envFrom } from "../../env-
|
|
1
|
+
import { n as requiredEnvFrom, t as envFrom } from "../../env-nV5rVErX.mjs";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { errorMessageFrom, errorNameFrom, sleep } from "@moeru/std";
|
|
4
4
|
import { createOpenAI } from "@xsai-ext/providers/create";
|
|
@@ -150,15 +150,21 @@ function createOpenAIFromEnv(source = {}, defaults = {}) {
|
|
|
150
150
|
const apiKeyEnvKey = source.apiKey ?? "OPENAI_API_KEY";
|
|
151
151
|
const baseURLEnvKey = source.baseURL ?? "OPENAI_BASE_URL";
|
|
152
152
|
const modelEnvKey = source.model ?? "OPENAI_MODEL";
|
|
153
|
-
const
|
|
153
|
+
const envWithDefaults = {
|
|
154
|
+
...defaults.apiKey == null ? {} : { [apiKeyEnvKey]: defaults.apiKey },
|
|
155
|
+
...defaults.baseURL == null ? {} : { [baseURLEnvKey]: defaults.baseURL },
|
|
156
|
+
...defaults.model == null ? {} : { [modelEnvKey]: defaults.model },
|
|
157
|
+
...env
|
|
158
|
+
};
|
|
159
|
+
const apiKey = requiredEnvFrom(envWithDefaults, {
|
|
154
160
|
name: apiKeyEnvKey,
|
|
155
161
|
type: "string"
|
|
156
162
|
});
|
|
157
|
-
const model = requiredEnvFrom(
|
|
163
|
+
const model = requiredEnvFrom(envWithDefaults, {
|
|
158
164
|
name: modelEnvKey,
|
|
159
165
|
type: "string"
|
|
160
166
|
});
|
|
161
|
-
const baseURL = envFrom(
|
|
167
|
+
const baseURL = envFrom(envWithDefaults, {
|
|
162
168
|
name: baseURLEnvKey,
|
|
163
169
|
type: "string"
|
|
164
170
|
});
|
|
@@ -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/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
|
+
{"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 envWithDefaults = {\n ...(defaults.apiKey == null ? {} : { [apiKeyEnvKey]: defaults.apiKey }),\n ...(defaults.baseURL == null ? {} : { [baseURLEnvKey]: defaults.baseURL }),\n ...(defaults.model == null ? {} : { [modelEnvKey]: defaults.model }),\n ...env,\n }\n\n const apiKey = requiredEnvFrom(envWithDefaults, {\n name: apiKeyEnvKey,\n type: 'string',\n })\n const model = requiredEnvFrom(envWithDefaults, {\n name: modelEnvKey,\n type: 'string',\n })\n const baseURL = envFrom(envWithDefaults, {\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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"}
|
|
@@ -7,6 +7,10 @@ type EnvValueType = 'string';
|
|
|
7
7
|
* Common options for env readers.
|
|
8
8
|
*/
|
|
9
9
|
interface EnvFromOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Env key to read and use in error messages.
|
|
12
|
+
*/
|
|
13
|
+
name: string;
|
|
10
14
|
/**
|
|
11
15
|
* Expected env value type.
|
|
12
16
|
*/
|
|
@@ -17,10 +21,6 @@ interface EnvFromOptions {
|
|
|
17
21
|
* @default false
|
|
18
22
|
*/
|
|
19
23
|
required?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Optional key name used for clearer error messages.
|
|
22
|
-
*/
|
|
23
|
-
name?: string;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Env options used by the required helper.
|
|
@@ -28,20 +28,25 @@ interface EnvFromOptions {
|
|
|
28
28
|
* `required` is intentionally omitted because this helper is always required.
|
|
29
29
|
*/
|
|
30
30
|
type RequiredEnvFromOptions = Omit<EnvFromOptions, 'required'>;
|
|
31
|
+
type EnvSource = Record<string, string | undefined>;
|
|
31
32
|
/**
|
|
32
33
|
* Parses one env value with optional required behavior.
|
|
33
34
|
*
|
|
34
35
|
* Example:
|
|
35
|
-
* `const apiKey = envFrom(process.env
|
|
36
|
+
* `const apiKey = envFrom(process.env, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`
|
|
36
37
|
*/
|
|
37
|
-
declare function envFrom(
|
|
38
|
+
declare function envFrom<TEnv extends EnvSource>(env: TEnv, options: EnvFromOptions & {
|
|
39
|
+
name: keyof TEnv & string;
|
|
40
|
+
}): string | undefined;
|
|
38
41
|
/**
|
|
39
42
|
* Parses one required env value.
|
|
40
43
|
*
|
|
41
44
|
* Example:
|
|
42
|
-
* `const apiKey = requiredEnvFrom(process.env
|
|
45
|
+
* `const apiKey = requiredEnvFrom(process.env, { type: 'string', name: 'OPENAI_API_KEY' })`
|
|
43
46
|
*/
|
|
44
|
-
declare function requiredEnvFrom(
|
|
47
|
+
declare function requiredEnvFrom<TEnv extends EnvSource>(env: TEnv, options: RequiredEnvFromOptions & {
|
|
48
|
+
name: keyof TEnv & string;
|
|
49
|
+
}): string;
|
|
45
50
|
//#endregion
|
|
46
51
|
export { requiredEnvFrom as a, envFrom as i, EnvValueType as n, RequiredEnvFromOptions as r, EnvFromOptions as t };
|
|
47
|
-
//# sourceMappingURL=env-
|
|
52
|
+
//# sourceMappingURL=env-DfWZy_n4.d.mts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
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) throw new Error(`Missing required ${options.name}.`);
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parses one env value with optional required behavior.
|
|
11
|
+
*
|
|
12
|
+
* Example:
|
|
13
|
+
* `const apiKey = envFrom(process.env, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`
|
|
14
|
+
*/
|
|
15
|
+
function envFrom(env, options) {
|
|
16
|
+
if (options.type === "string") return assertNonEmptyString(env[options.name], options);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parses one required env value.
|
|
20
|
+
*
|
|
21
|
+
* Example:
|
|
22
|
+
* `const apiKey = requiredEnvFrom(process.env, { type: 'string', name: 'OPENAI_API_KEY' })`
|
|
23
|
+
*/
|
|
24
|
+
function requiredEnvFrom(env, options) {
|
|
25
|
+
const parsed = envFrom(env, {
|
|
26
|
+
...options,
|
|
27
|
+
required: true
|
|
28
|
+
});
|
|
29
|
+
if (parsed == null) throw new Error(`Missing required ${options.name}.`);
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { requiredEnvFrom as n, envFrom as t };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=env-nV5rVErX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-nV5rVErX.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 * Env key to read and use in error messages.\n */\n name: string\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\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\ntype EnvSource = Record<string, string | undefined>\n\nfunction assertNonEmptyString(value: string | undefined, options: EnvFromOptions): string | undefined {\n if (value == null || value.trim().length === 0) {\n if (options.required === true) {\n throw new Error(`Missing required ${options.name}.`)\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, { type: 'string', required: true, name: 'OPENAI_API_KEY' })`\n */\nexport function envFrom<TEnv extends EnvSource>(\n env: TEnv,\n options: EnvFromOptions & { name: keyof TEnv & string },\n): string | undefined {\n if (options.type === 'string') {\n return assertNonEmptyString(env[options.name], options)\n }\n\n return undefined\n}\n\n/**\n * Parses one required env value.\n *\n * Example:\n * `const apiKey = requiredEnvFrom(process.env, { type: 'string', name: 'OPENAI_API_KEY' })`\n */\nexport function requiredEnvFrom<TEnv extends EnvSource>(\n env: TEnv,\n options: RequiredEnvFromOptions & { name: keyof TEnv & string },\n): string {\n const parsed = envFrom(env, {\n ...options,\n required: true,\n })\n\n if (parsed == null) {\n throw new Error(`Missing required ${options.name}.`)\n }\n\n return parsed\n}\n"],"mappings":";AAkCA,SAAS,qBAAqB,OAA2B,SAA6C;AACpG,KAAI,SAAS,QAAQ,MAAM,MAAM,CAAC,WAAW,GAAG;AAC9C,MAAI,QAAQ,aAAa,KACvB,OAAM,IAAI,MAAM,oBAAoB,QAAQ,KAAK,GAAG;AAGtD;;AAGF,QAAO;;;;;;;;AAST,SAAgB,QACd,KACA,SACoB;AACpB,KAAI,QAAQ,SAAS,SACnB,QAAO,qBAAqB,IAAI,QAAQ,OAAO,QAAQ;;;;;;;;AAY3D,SAAgB,gBACd,KACA,SACQ;CACR,MAAM,SAAS,QAAQ,KAAK;EAC1B,GAAG;EACH,UAAU;EACX,CAAC;AAEF,KAAI,UAAU,KACZ,OAAM,IAAI,MAAM,oBAAoB,QAAQ,KAAK,GAAG;AAGtD,QAAO"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $ as InferenceExecutor, D as TaskRunContext, I as TaskExecutionContext, J as RunResult, O as TaskRunOutput, R as ModelDefinition, S as TaskConcurrencyConfig, X as RunScoreKind, f as MatrixDefinition, k as TelemetryAttributeValue, o as CliReportingConfig, p as MatrixLayer, rt as ScheduledTask, t as ConfigHookPlugin, w as TaskExecutionPolicy } from "./index-BkjyCInx.mjs";
|
|
2
|
-
import { a as requiredEnvFrom } from "./env-
|
|
2
|
+
import { a as requiredEnvFrom } from "./env-DfWZy_n4.mjs";
|
|
3
3
|
import { expect } from "./expect.mjs";
|
|
4
4
|
import * as _$c12 from "c12";
|
|
5
5
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as registerEvalDefinition, l as loadEnv, o as createNoopTelemetryRuntime, s as defineConfig } from "./registry-BHGMxjpA.mjs";
|
|
2
2
|
import { t as createSchedulerQueue } from "./queue-DsZQkZO_.mjs";
|
|
3
|
-
import { n as requiredEnvFrom } from "./env-
|
|
3
|
+
import { n as requiredEnvFrom } from "./env-nV5rVErX.mjs";
|
|
4
4
|
import { defineEval, defineTask } from "./config.mjs";
|
|
5
5
|
import { expect } from "./expect.mjs";
|
|
6
6
|
import { errorMessageFrom, sleep } from "@moeru/std";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as requiredEnvFrom, t as envFrom } from "../../env-
|
|
1
|
+
import { n as requiredEnvFrom, t as envFrom } from "../../env-nV5rVErX.mjs";
|
|
2
2
|
import { t as resolveModelByName } from "../../models-pBSRUZhY.mjs";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { errorMessageFrom } from "@moeru/std";
|
|
@@ -8,15 +8,19 @@ function getParameters(model) {
|
|
|
8
8
|
}
|
|
9
9
|
function parseOptionalStringParameter(parameters, key, modelId) {
|
|
10
10
|
const value = parameters[key];
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const normalized = value == null ? void 0 : String(value);
|
|
12
|
+
const name = `${modelId}.parameters.${key}`;
|
|
13
|
+
return envFrom({ [name]: normalized }, {
|
|
14
|
+
name,
|
|
13
15
|
type: "string"
|
|
14
16
|
});
|
|
15
17
|
}
|
|
16
18
|
function parseRequiredStringParameter(parameters, key, modelId) {
|
|
17
19
|
const value = parameters[key];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
const normalized = value == null ? void 0 : String(value);
|
|
21
|
+
const name = `${modelId}.parameters.${key}`;
|
|
22
|
+
return requiredEnvFrom({ [name]: normalized }, {
|
|
23
|
+
name,
|
|
20
24
|
type: "string"
|
|
21
25
|
});
|
|
22
26
|
}
|
|
@@ -333,30 +337,28 @@ async function resolveChatModelResolverValue(value, context) {
|
|
|
333
337
|
return value;
|
|
334
338
|
}
|
|
335
339
|
function resolveRequiredStringValue(value, name) {
|
|
336
|
-
return requiredEnvFrom(value, {
|
|
340
|
+
return requiredEnvFrom({ [name]: value }, {
|
|
337
341
|
name,
|
|
338
342
|
type: "string"
|
|
339
343
|
});
|
|
340
344
|
}
|
|
341
345
|
function resolveOptionalStringValue(value, name) {
|
|
342
|
-
return envFrom(value, {
|
|
346
|
+
return envFrom({ [name]: value }, {
|
|
343
347
|
name,
|
|
344
348
|
type: "string"
|
|
345
349
|
});
|
|
346
350
|
}
|
|
347
351
|
function resolveOptionalEnvValue(env, envKey) {
|
|
348
|
-
|
|
352
|
+
return envFrom(env, {
|
|
349
353
|
name: envKey,
|
|
350
354
|
type: "string"
|
|
351
|
-
};
|
|
352
|
-
return envFrom(env[envKey], options);
|
|
355
|
+
});
|
|
353
356
|
}
|
|
354
357
|
function resolveRequiredEnvValue(env, envKey) {
|
|
355
|
-
|
|
358
|
+
return requiredEnvFrom(env, {
|
|
356
359
|
name: envKey,
|
|
357
360
|
type: "string"
|
|
358
|
-
};
|
|
359
|
-
return requiredEnvFrom(env[envKey], options);
|
|
361
|
+
});
|
|
360
362
|
}
|
|
361
363
|
function resolveProviderParameters(provider, env) {
|
|
362
364
|
const parameters = { ...provider.parameters };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/chat-models/runtime-config.ts","../../../src/plugins/chat-models/telemetry.ts","../../../src/plugins/chat-models/index.ts"],"sourcesContent":["import type { ModelDefinition } from '../../config/models'\nimport type { ChatModelHeaders } from './index'\n\nimport { envFrom, requiredEnvFrom } from '../../core/inference-executors/env'\n\n/**\n * Runtime config consumed by OpenAI-compatible provider constructors.\n */\nexport interface OpenAIChatModelRuntimeConfig {\n /**\n * Resolved inference executor kind.\n */\n inferenceExecutor: 'openai'\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Required API key.\n */\n apiKey: string\n /**\n * Optional base URL override.\n */\n baseURL?: string\n /**\n * Optional request headers.\n */\n headers?: ChatModelHeaders\n}\n\n/**\n * Runtime config consumed by Ollama provider constructors.\n */\nexport interface OllamaChatModelRuntimeConfig {\n /**\n * Resolved inference executor kind.\n */\n inferenceExecutor: 'ollama'\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Optional base URL override.\n */\n baseURL?: string\n /**\n * Optional request headers.\n */\n headers?: ChatModelHeaders\n}\n\n/**\n * Runtime config consumed by OpenRouter provider constructors.\n */\nexport interface OpenRouterChatModelRuntimeConfig {\n /**\n * Resolved inference executor kind.\n */\n inferenceExecutor: 'openrouter'\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Required API key.\n */\n apiKey: string\n /**\n * Optional base URL override.\n */\n baseURL?: string\n /**\n * Optional request headers.\n */\n headers?: ChatModelHeaders\n}\n\n/**\n * Union of normalized runtime configs for supported chat-model executors.\n */\nexport type ChatModelRuntimeConfig\n = OpenAIChatModelRuntimeConfig\n | OllamaChatModelRuntimeConfig\n | OpenRouterChatModelRuntimeConfig\n\nfunction getParameters(model: ModelDefinition): Record<string, unknown> {\n return model.parameters ?? {}\n}\n\nfunction parseOptionalStringParameter(\n parameters: Record<string, unknown>,\n key: string,\n modelId: string,\n): string | undefined {\n const value = parameters[key]\n const normalized = value == null ? undefined : String(value)\n\n return envFrom(normalized, {\n name: `${modelId}.parameters.${key}`,\n type: 'string',\n })\n}\n\nfunction parseRequiredStringParameter(\n parameters: Record<string, unknown>,\n key: string,\n modelId: string,\n): string {\n const value = parameters[key]\n const normalized = value == null ? undefined : String(value)\n\n return requiredEnvFrom(normalized, {\n name: `${modelId}.parameters.${key}`,\n type: 'string',\n })\n}\n\nfunction parseHeadersParameter(\n parameters: Record<string, unknown>,\n modelId: string,\n): ChatModelHeaders | undefined {\n const headers = parameters.headers\n if (headers == null) {\n return undefined\n }\n\n if (typeof headers !== 'object' || Array.isArray(headers)) {\n throw new TypeError(`Invalid ${modelId}.parameters.headers: expected an object.`)\n }\n\n const normalized: Record<string, string | string[]> = {}\n for (const [key, value] of Object.entries(headers as Record<string, unknown>)) {\n if (typeof value === 'string') {\n normalized[key] = value\n continue\n }\n\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n normalized[key] = value\n continue\n }\n\n throw new Error(`Invalid ${modelId}.parameters.headers.${key}: expected string or string[].`)\n }\n\n return normalized\n}\n\n/**\n * Normalizes one configured chat model into runtime executor config.\n *\n * Use when:\n * - eval code needs typed provider constructor options from a resolved model\n * - model parameters should be validated once with clear error messages\n *\n * Expects:\n * - `model.inferenceExecutorId` to be one of the supported executor ids\n * - required OpenAI fields (apiKey) to exist in `model.parameters`\n *\n * Returns:\n * - validated runtime config union for OpenAI or Ollama\n */\nexport function toChatModelRuntimeConfig(model: ModelDefinition): ChatModelRuntimeConfig {\n const parameters = getParameters(model)\n\n if (model.inferenceExecutorId === 'openai') {\n return {\n apiKey: parseRequiredStringParameter(parameters, 'apiKey', model.id),\n baseURL: parseOptionalStringParameter(parameters, 'baseURL', model.id),\n headers: parseHeadersParameter(parameters, model.id),\n inferenceExecutor: 'openai',\n model: model.model,\n }\n }\n\n if (model.inferenceExecutorId === 'ollama') {\n return {\n baseURL: parseOptionalStringParameter(parameters, 'baseURL', model.id),\n headers: parseHeadersParameter(parameters, model.id),\n inferenceExecutor: 'ollama',\n model: model.model,\n }\n }\n\n if (model.inferenceExecutorId === 'openrouter') {\n return {\n apiKey: parseRequiredStringParameter(parameters, 'apiKey', model.id),\n baseURL: parseOptionalStringParameter(parameters, 'baseURL', model.id),\n headers: parseHeadersParameter(parameters, model.id),\n inferenceExecutor: 'openrouter',\n model: model.model,\n }\n }\n\n throw new Error(`Unsupported chat inference executor \"${model.inferenceExecutorId}\" for model \"${model.id}\".`)\n}\n\n/**\n * Resolves OpenAI runtime config from one resolved run-context model.\n *\n * Use when:\n * - task execution already has a model resolved through chat-model helpers\n * - eval code wants typed OpenAI provider options with a concise helper name\n *\n * Expects:\n * - `model` to resolve to an OpenAI-backed chat model\n *\n * Returns:\n * - validated OpenAI runtime config\n */\nexport function openaiFromRunContext(model: ModelDefinition): OpenAIChatModelRuntimeConfig {\n const runtimeConfig = toChatModelRuntimeConfig(model)\n if (runtimeConfig.inferenceExecutor !== 'openai') {\n throw new Error(`Expected openai model, got \"${runtimeConfig.inferenceExecutor}\" for \"${model.id}\".`)\n }\n\n return runtimeConfig\n}\n\n/**\n * Resolves Ollama runtime config from one resolved run-context model.\n *\n * Use when:\n * - task execution already has a model resolved through chat-model helpers\n * - eval code wants typed Ollama provider options with a concise helper name\n *\n * Expects:\n * - `model` to resolve to an Ollama-backed chat model\n *\n * Returns:\n * - validated Ollama runtime config\n */\nexport function ollamaFromRunContext(model: ModelDefinition): OllamaChatModelRuntimeConfig {\n const runtimeConfig = toChatModelRuntimeConfig(model)\n if (runtimeConfig.inferenceExecutor !== 'ollama') {\n throw new Error(`Expected ollama model, got \"${runtimeConfig.inferenceExecutor}\" for \"${model.id}\".`)\n }\n\n return runtimeConfig\n}\n\n/**\n * Resolves OpenRouter runtime config from one resolved run-context model.\n *\n * Use when:\n * - task execution already has a model resolved through chat-model helpers\n * - eval code wants typed OpenRouter provider options with a concise helper name\n *\n * Expects:\n * - `model` to resolve to an OpenRouter-backed chat model\n *\n * Returns:\n * - validated OpenRouter runtime config\n */\nexport function openrouterFromRunContext(model: ModelDefinition): OpenRouterChatModelRuntimeConfig {\n const runtimeConfig = toChatModelRuntimeConfig(model)\n if (runtimeConfig.inferenceExecutor !== 'openrouter') {\n throw new Error(`Expected openrouter model, got \"${runtimeConfig.inferenceExecutor}\" for \"${model.id}\".`)\n }\n\n return runtimeConfig\n}\n","import type { TaskRunContext } from '../../config/types'\n\nimport { errorMessageFrom } from '@moeru/std'\n\n/**\n * Represents one normalized chat-model tool call.\n *\n * Use when:\n * - report events need tool-call level payloads that remain provider-neutral\n *\n * Expects:\n * - `name` to be stable enough for aggregation and assertion checks\n * - `args` to be JSON-serializable\n */\nexport interface ChatModelToolCall {\n /**\n * Optional provider-assigned tool-call identifier.\n */\n id?: string\n /**\n * Tool name.\n */\n name: string\n /**\n * Parsed tool arguments object/value.\n */\n args: unknown\n}\n\n/**\n * Provider identity attached to chat-model telemetry events.\n */\nexport interface ChatModelTelemetryProvider {\n /**\n * Provider id, for example `openai`.\n */\n id: string\n /**\n * Optional concrete model id/name.\n */\n model?: string\n}\n\n/**\n * Input options for response telemetry emission.\n */\nexport interface EmitChatModelResponseTelemetryOptions {\n /**\n * Optional case id for case-scoped telemetry events.\n */\n caseId?: string\n /**\n * Optional response latency in milliseconds.\n */\n latencyMs?: number\n /**\n * Optional provider identity payload.\n */\n provider?: ChatModelTelemetryProvider\n /**\n * Raw chat-model response object from the inference library/provider.\n */\n response: unknown\n}\n\n/**\n * Input options for request telemetry emission.\n */\nexport interface EmitChatModelRequestTelemetryOptions {\n /**\n * Optional case id for case-scoped telemetry events.\n */\n caseId?: string\n /**\n * Optional request payload metadata.\n */\n data?: unknown\n /**\n * Optional provider identity payload.\n */\n provider?: ChatModelTelemetryProvider\n}\n\n/**\n * Input options for error telemetry emission.\n */\nexport interface EmitChatModelErrorTelemetryOptions {\n /**\n * Optional case id for case-scoped telemetry events.\n */\n caseId?: string\n /**\n * Error payload emitted by the inference client/runtime.\n */\n error: unknown\n /**\n * Optional provider identity payload.\n */\n provider?: ChatModelTelemetryProvider\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (value == null || typeof value !== 'object') {\n return undefined\n }\n\n return value as Record<string, unknown>\n}\n\nfunction parseMaybeJson(value: unknown): unknown {\n if (typeof value !== 'string') {\n return value\n }\n\n try {\n return JSON.parse(value)\n }\n catch {\n return value\n }\n}\n\n/**\n * Extracts normalized tool calls from one chat-model response shape.\n *\n * Use when:\n * - downstream scoring, reporting, or analysis should inspect tool call usage\n * - provider payload differences should stay hidden behind one stable shape\n *\n * Returns:\n * - normalized list of `{ id?, name, args }` tool calls\n */\nexport function extractChatModelToolCalls(response: unknown): ChatModelToolCall[] {\n const responseRecord = asRecord(response)\n if (responseRecord == null) {\n return []\n }\n\n const rawToolCalls = responseRecord.toolCalls ?? responseRecord.tool_calls\n if (!Array.isArray(rawToolCalls)) {\n return []\n }\n\n const toolCalls: ChatModelToolCall[] = []\n\n for (const rawToolCall of rawToolCalls) {\n const toolCallRecord = asRecord(rawToolCall)\n if (toolCallRecord == null) {\n continue\n }\n\n const functionPayload = asRecord(toolCallRecord.function)\n const name = typeof toolCallRecord.name === 'string'\n ? toolCallRecord.name\n : typeof functionPayload?.name === 'string'\n ? functionPayload.name\n : undefined\n\n if (name == null || name.length === 0) {\n continue\n }\n\n const rawArgs = toolCallRecord.args\n ?? toolCallRecord.arguments\n ?? functionPayload?.args\n ?? functionPayload?.arguments\n\n toolCalls.push({\n args: parseMaybeJson(rawArgs),\n id: typeof toolCallRecord.id === 'string' ? toolCallRecord.id : undefined,\n name,\n })\n }\n\n return toolCalls\n}\n\n/**\n * Extracts numeric metering dimensions from one chat-model response usage block.\n *\n * Use when:\n * - report events should capture usage dimensions in a modality-neutral map\n *\n * Returns:\n * - numeric dimensions keyed by provider usage field names\n */\nexport function extractMeteringDimensions(response: unknown): Record<string, number> {\n const responseRecord = asRecord(response)\n const usage = asRecord(responseRecord?.usage)\n if (usage == null) {\n return {}\n }\n\n const dimensions: Record<string, number> = {}\n\n for (const [key, value] of Object.entries(usage)) {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n continue\n }\n\n dimensions[key] = value\n }\n\n return dimensions\n}\n\n/**\n * Emits chat-model response telemetry as reportable task events.\n *\n * Use when:\n * - task code receives one chat-model response and wants standardized report events\n * - `ToolCall*` and metering metrics should be persisted in `events.jsonl`\n *\n * Expects:\n * - `context.reporterHooks?.onEvent` to be available in CLI execution paths\n *\n * Returns:\n * - no return value; this is a best-effort reporting helper\n */\nexport function emitChatModelResponseTelemetry(\n context: TaskRunContext,\n options: EmitChatModelResponseTelemetryOptions,\n): void {\n const toolCalls = extractChatModelToolCalls(options.response)\n const meteringDimensions = extractMeteringDimensions(options.response)\n\n if (toolCalls.length > 0) {\n meteringDimensions.tool_call_count = toolCalls.length\n }\n\n const data = {\n metering: {\n dimensions: meteringDimensions,\n latency_ms: options.latencyMs,\n },\n metrics: {\n 'vieval.chat.tool_call_count': toolCalls.length,\n },\n modality: 'chat',\n provider: options.provider,\n toolCalls,\n }\n\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data,\n event: 'InferenceResponse',\n })\n\n for (const toolCall of toolCalls) {\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n modality: 'chat',\n provider: options.provider,\n toolCall,\n },\n event: 'ToolCallStarted',\n })\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n modality: 'chat',\n provider: options.provider,\n toolCall,\n },\n event: 'ToolCallEnded',\n })\n }\n}\n\n/**\n * Emits chat-model request telemetry as a reportable task event.\n *\n * Use when:\n * - task code submits one model request and wants request-side traceability\n *\n * Expects:\n * - `context.reporterHooks?.onEvent` to be available in CLI execution paths\n */\nexport function emitChatModelRequestTelemetry(\n context: TaskRunContext,\n options: EmitChatModelRequestTelemetryOptions,\n): void {\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n data: options.data,\n modality: 'chat',\n provider: options.provider,\n },\n event: 'InferenceRequest',\n })\n}\n\n/**\n * Emits chat-model failure telemetry as a reportable task event.\n *\n * Use when:\n * - one inference call fails and report artifacts should include normalized error context\n *\n * Expects:\n * - `context.reporterHooks?.onEvent` to be available in CLI execution paths\n */\nexport function emitChatModelErrorTelemetry(\n context: TaskRunContext,\n options: EmitChatModelErrorTelemetryOptions,\n): void {\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n error: errorMessageFrom(options.error) ?? 'Unknown inference error.',\n modality: 'chat',\n provider: options.provider,\n },\n event: 'InferenceError',\n })\n}\n","import type { MatrixDefinition, TaskExecutionPolicy } from '../../config'\nimport type { ModelDefinition } from '../../config/models'\nimport type { ConfigHookPlugin } from '../../config/plugin'\nimport type { TaskRunContext } from '../../config/types'\nimport type { EnvFromOptions, RequiredEnvFromOptions } from '../../core/inference-executors/env'\n\nimport process from 'node:process'\n\nimport { resolveModelByName } from '../../config/models'\nimport { envFrom, requiredEnvFrom } from '../../core/inference-executors/env'\n\n/**\n * Minimal inference-executor shape expected by chat model runtime callers.\n */\nexport interface ChatModelExecutorLike {\n chat: (model: string) => Record<string, unknown>\n}\n\n/**\n * Inference-executor input accepted by `chatModelFrom`.\n */\nexport type ChatModelExecutorInput = string | ChatModelExecutorLike\n\n/**\n * Chat-model header payload accepted by executor parameters.\n */\nexport type ChatModelHeaders = Record<string, string | string[]>\n\n/**\n * Runtime env context passed to model callback resolvers.\n */\nexport interface ChatModelResolverContext {\n env: Record<string, string>\n}\n\n/**\n * Value-or-callback resolver used by model runtime fields.\n */\nexport type ChatModelResolverValue<TValue> = TValue | ((config: ChatModelResolverContext) => Promise<TValue> | TValue)\n\n/**\n * OpenAI-specific inference executor config shape.\n */\nexport interface OpenAIChatModelInferenceExecutor {\n inferenceExecutor: 'openai'\n apiKey?: ChatModelResolverValue<string>\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n}\n\n/**\n * Ollama-specific inference executor config shape.\n */\nexport interface OllamaChatModelInferenceExecutor {\n inferenceExecutor: 'ollama'\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n}\n\n/**\n * OpenRouter-specific inference executor config shape.\n */\nexport interface OpenRouterChatModelInferenceExecutor {\n inferenceExecutor: 'openrouter'\n apiKey?: ChatModelResolverValue<string>\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n}\n\n/**\n * Generic inference executor config shape.\n */\nexport interface GenericChatModelInferenceExecutor {\n inferenceExecutor?: ChatModelExecutorInput\n}\n\n/**\n * Union of supported inference executor config shapes for `chatModelFrom`.\n */\nexport type ChatModelInferenceExecutor\n = OpenAIChatModelInferenceExecutor\n | OllamaChatModelInferenceExecutor\n | OpenRouterChatModelInferenceExecutor\n | GenericChatModelInferenceExecutor\n\n/**\n * Common builder input fields for `chatModelFrom`.\n */\nexport interface ChatModelFromBaseOptions {\n /**\n * Provider id registered through `ChatProviders`.\n *\n * Use when:\n * - model runtime transport and credentials should be delegated to a named provider preset\n *\n * Expects:\n * - one `ChatProviders` plugin entry to expose the same id\n */\n provider?: string\n /**\n * Inference-executor id or inference-executor instance.\n */\n inferenceExecutor?: ChatModelExecutorInput\n /**\n * Optional explicit inference-executor id for inference-executor instances.\n *\n * @default 'custom'\n */\n inferenceExecutorId?: string\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Optional stable model id.\n *\n * @default `${inferenceExecutorId}:${model}`\n */\n id?: string\n /**\n * Alias names used by `resolveModelByName`.\n */\n aliases?: string[]\n /**\n * Optional execution policy hints attached to this model.\n */\n executionPolicy?: TaskExecutionPolicy\n /**\n * Additional retries allowed within the current attempt.\n *\n * @default 0\n */\n autoRetry?: number\n /**\n * Delay in milliseconds before a retry starts.\n *\n * @default retryIndex => 500 * 2 ** (retryIndex - 1)\n */\n autoRetryDelay?: TaskExecutionPolicy['autoRetryDelay']\n /**\n * Additional full task attempts allowed after the current attempt settles.\n *\n * @default 0\n */\n autoAttempt?: number\n /**\n * Timeout in milliseconds for model-backed work.\n */\n timeout?: number\n /**\n * Optional model-level call parameters.\n */\n parameters?: Record<string, unknown>\n}\n\n/**\n * Builder input for `chatModelFrom`.\n */\nexport type ChatModelFromOptions = ChatModelInferenceExecutor & ChatModelFromBaseOptions\n\n/**\n * Chat-model specific specialization of the canonical `ModelDefinition`.\n */\nexport type ChatModelDefinition = Omit<ModelDefinition, 'inferenceExecutor'> & {\n inferenceExecutor: ChatModelExecutorInput\n provider?: string\n runtimeResolvers?: {\n apiKey?: ChatModelResolverValue<string>\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n }\n}\n\nfunction normalizeExecutionPolicy(\n policy: TaskExecutionPolicy | undefined,\n): TaskExecutionPolicy | undefined {\n if (policy == null) {\n return undefined\n }\n\n const normalized = {\n autoAttempt: policy.autoAttempt,\n autoRetry: policy.autoRetry,\n autoRetryDelay: policy.autoRetryDelay,\n timeout: policy.timeout,\n }\n\n return Object.values(normalized).some(value => value != null)\n ? normalized\n : undefined\n}\n\nfunction hasJudgeAlias(model: Pick<ChatModelFromBaseOptions, 'aliases' | 'id' | 'model'>): boolean {\n return [\n ...(model.aliases ?? []),\n ...(model.id == null ? [] : [model.id]),\n model.model,\n ].some(value => value.toLowerCase().includes('judge'))\n}\n\nfunction resolveModelExecutionPolicy(options: ChatModelFromOptions): TaskExecutionPolicy | undefined {\n const explicitPolicy = normalizeExecutionPolicy({\n autoAttempt: options.autoAttempt ?? options.executionPolicy?.autoAttempt,\n autoRetry: options.autoRetry ?? options.executionPolicy?.autoRetry,\n autoRetryDelay: options.autoRetryDelay ?? options.executionPolicy?.autoRetryDelay,\n timeout: options.timeout ?? options.executionPolicy?.timeout,\n })\n\n if (explicitPolicy != null && Object.keys(explicitPolicy).length > 0) {\n return explicitPolicy\n }\n\n if (hasJudgeAlias(options)) {\n return {\n autoRetry: 3,\n }\n }\n\n return undefined\n}\n\n/**\n * Env-key map for optional provider parameters.\n *\n * Use when:\n * - provider parameter values should be read from env keys\n * - missing keys should resolve to `undefined`\n */\nexport type OptionalProviderEnvMap = Record<string, string>\n\n/**\n * Env-key map for required provider parameters.\n *\n * Use when:\n * - provider parameter values must exist before model execution\n * - missing keys should throw with key-aware error messages\n */\nexport type RequiredProviderEnvMap = Record<string, string>\n\n/**\n * One provider definition consumed by chat model presets.\n */\nexport interface ChatProviderDefinition {\n /**\n * Stable provider id referenced by `chatModelFrom({ provider })`.\n */\n id: string\n /**\n * Inference-executor id or instance used by this provider preset.\n */\n inferenceExecutor: ChatModelExecutorInput\n /**\n * Optional explicit inference-executor id for inference-executor instances.\n *\n * @default 'custom'\n */\n inferenceExecutorId?: string\n /**\n * Optional literal provider-level parameters.\n */\n parameters?: Record<string, unknown>\n /**\n * Optional provider parameters resolved via `envFrom`.\n *\n * Expects:\n * - map key is the provider parameter name\n * - map value is the env key name\n */\n optionalEnv?: OptionalProviderEnvMap\n /**\n * Required provider parameters resolved via `requiredEnvFrom`.\n *\n * Expects:\n * - map key is the provider parameter name\n * - map value is the env key name\n */\n requiredEnv?: RequiredProviderEnvMap\n}\n\n/**\n * Builder input for `chatProviderFrom`.\n */\nexport interface ChatProviderFromOptions extends ChatProviderDefinition {\n}\n\n/**\n * Options for the built-in `ChatProviders` plugin.\n */\nexport interface ChatProvidersPluginOptions {\n /**\n * Provider definitions to append to config.\n */\n providers: readonly ChatProviderDefinition[]\n /**\n * Optional explicit env source used for env-backed provider parameters.\n *\n * @default process.env\n */\n env?: NodeJS.ProcessEnv\n}\n\n/**\n * Partial config shape needed by the chat models plugin.\n */\nexport interface PluginConfig {\n env?: NodeJS.ProcessEnv\n chatProviders?: ChatProviderDefinition[]\n models?: ModelDefinition[]\n}\n\n/**\n * Plugin type bound to the minimal config shape used by model plugins.\n */\nexport type Plugin = ConfigHookPlugin<PluginConfig>\n\nfunction normalizeInferenceExecutorId(\n inferenceExecutor: ChatModelExecutorInput,\n inferenceExecutorId: string | undefined,\n): string {\n if (typeof inferenceExecutor === 'string') {\n return inferenceExecutor\n }\n\n return inferenceExecutorId ?? 'custom'\n}\n\nfunction createDefaultModelId(inferenceExecutorId: string, model: string): string {\n return `${inferenceExecutorId}:${model}`\n}\n\nfunction normalizeEnvRecord(env: NodeJS.ProcessEnv): Record<string, string> {\n const normalized: Record<string, string> = {}\n for (const [key, value] of Object.entries(env)) {\n if (typeof value === 'string') {\n normalized[key] = value\n }\n }\n\n return normalized\n}\n\nasync function resolveChatModelResolverValue<TValue>(\n value: ChatModelResolverValue<TValue>,\n context: ChatModelResolverContext,\n): Promise<TValue> {\n if (typeof value === 'function') {\n const resolver = value as (config: ChatModelResolverContext) => Promise<TValue> | TValue\n return await resolver(context)\n }\n\n return value\n}\n\nfunction resolveRequiredStringValue(value: string | undefined, name: string): string {\n return requiredEnvFrom(value, {\n name,\n type: 'string',\n })\n}\n\nfunction resolveOptionalStringValue(value: string | undefined, name: string): string | undefined {\n return envFrom(value, {\n name,\n type: 'string',\n })\n}\n\nfunction resolveOptionalEnvValue(\n env: NodeJS.ProcessEnv,\n envKey: string,\n): string | undefined {\n const options: EnvFromOptions = {\n name: envKey,\n type: 'string',\n }\n\n return envFrom(env[envKey], options)\n}\n\nfunction resolveRequiredEnvValue(\n env: NodeJS.ProcessEnv,\n envKey: string,\n): string {\n const options: RequiredEnvFromOptions = {\n name: envKey,\n type: 'string',\n }\n\n return requiredEnvFrom(env[envKey], options)\n}\n\nfunction resolveProviderParameters(\n provider: ChatProviderDefinition,\n env: NodeJS.ProcessEnv,\n): Record<string, unknown> | undefined {\n const parameters: Record<string, unknown> = {\n ...provider.parameters,\n }\n\n for (const [parameterName, envKey] of Object.entries(provider.optionalEnv ?? {})) {\n const resolved = resolveOptionalEnvValue(env, envKey)\n if (resolved != null) {\n parameters[parameterName] = resolved\n }\n }\n\n for (const [parameterName, envKey] of Object.entries(provider.requiredEnv ?? {})) {\n parameters[parameterName] = resolveRequiredEnvValue(env, envKey)\n }\n\n return Object.keys(parameters).length > 0 ? parameters : undefined\n}\n\nfunction normalizeChatProviderDefinition(\n provider: ChatProviderDefinition,\n env: NodeJS.ProcessEnv,\n): ChatProviderDefinition {\n return {\n id: provider.id,\n inferenceExecutor: provider.inferenceExecutor,\n inferenceExecutorId: normalizeInferenceExecutorId(provider.inferenceExecutor, provider.inferenceExecutorId),\n optionalEnv: provider.optionalEnv,\n parameters: resolveProviderParameters(provider, env),\n requiredEnv: provider.requiredEnv,\n }\n}\n\nfunction createProviderMap(config: PluginConfig): Map<string, ChatProviderDefinition> {\n const providerMap = new Map<string, ChatProviderDefinition>()\n for (const provider of config.chatProviders ?? []) {\n providerMap.set(provider.id, provider)\n }\n\n return providerMap\n}\n\nfunction resolveModelProvider(\n model: ChatModelDefinition,\n providerMap: ReadonlyMap<string, ChatProviderDefinition>,\n): ChatModelDefinition {\n if (model.provider == null) {\n return model\n }\n\n const provider = providerMap.get(model.provider)\n if (provider == null) {\n throw new Error(`Unknown chat provider \"${model.provider}\" referenced by model \"${model.id}\".`)\n }\n\n return {\n ...model,\n inferenceExecutor: provider.inferenceExecutor,\n inferenceExecutorId: provider.inferenceExecutorId ?? normalizeInferenceExecutorId(provider.inferenceExecutor, provider.inferenceExecutorId),\n parameters: {\n ...provider.parameters,\n ...model.parameters,\n },\n }\n}\n\nasync function resolveModelRuntimeResolvers(\n model: ChatModelDefinition,\n context: ChatModelResolverContext,\n): Promise<Record<string, unknown> | undefined> {\n if (model.runtimeResolvers == null) {\n return undefined\n }\n\n const resolvedParameters: Record<string, unknown> = {}\n\n if (model.runtimeResolvers.apiKey != null) {\n const resolvedApiKey = await resolveChatModelResolverValue(model.runtimeResolvers.apiKey, context)\n resolvedParameters.apiKey = resolveRequiredStringValue(resolvedApiKey, `${model.id}.apiKey`)\n }\n\n if (model.runtimeResolvers.baseURL != null) {\n const resolvedBaseURL = await resolveChatModelResolverValue(model.runtimeResolvers.baseURL, context)\n const normalizedBaseURL = resolveOptionalStringValue(resolvedBaseURL, `${model.id}.baseURL`)\n if (normalizedBaseURL != null) {\n resolvedParameters.baseURL = normalizedBaseURL\n }\n }\n\n if (model.runtimeResolvers.headers != null) {\n const resolvedHeaders = await resolveChatModelResolverValue(model.runtimeResolvers.headers, context)\n resolvedParameters.headers = resolvedHeaders\n }\n\n return Object.keys(resolvedParameters).length > 0 ? resolvedParameters : undefined\n}\n\nasync function resolveChatModelDefinition(\n model: ChatModelDefinition,\n config: PluginConfig,\n): Promise<ChatModelDefinition> {\n const providerResolvedModel = resolveModelProvider(model, createProviderMap(config))\n const resolvedRuntimeParameters = await resolveModelRuntimeResolvers(providerResolvedModel, {\n env: normalizeEnvRecord(config.env ?? process.env),\n })\n\n if (resolvedRuntimeParameters == null) {\n return providerResolvedModel\n }\n\n return {\n ...providerResolvedModel,\n parameters: {\n ...providerResolvedModel.parameters,\n ...resolvedRuntimeParameters,\n },\n }\n}\n\nfunction isOpenAIChatModelInferenceExecutor(\n options: ChatModelFromOptions,\n): options is ChatModelFromBaseOptions & OpenAIChatModelInferenceExecutor {\n return options.inferenceExecutor === 'openai'\n}\n\nfunction isOllamaChatModelInferenceExecutor(\n options: ChatModelFromOptions,\n): options is ChatModelFromBaseOptions & OllamaChatModelInferenceExecutor {\n return options.inferenceExecutor === 'ollama'\n}\n\nfunction isOpenRouterChatModelInferenceExecutor(\n options: ChatModelFromOptions,\n): options is ChatModelFromBaseOptions & OpenRouterChatModelInferenceExecutor {\n return options.inferenceExecutor === 'openrouter'\n}\n\n/**\n * Builds one normalized chat model definition.\n *\n * Use when:\n * - registering chat models through config plugins\n * - a single model needs aliases for matrix selection or judge lookup\n */\nexport function chatModelFrom(options: ChatModelFromOptions): ChatModelDefinition {\n const fallbackInferenceExecutor = options.inferenceExecutor ?? options.provider ?? 'custom'\n const inferenceExecutorId = normalizeInferenceExecutorId(fallbackInferenceExecutor, options.inferenceExecutorId)\n const runtimeResolvers = isOpenAIChatModelInferenceExecutor(options)\n ? {\n apiKey: options.apiKey,\n baseURL: options.baseURL,\n headers: options.headers,\n }\n : isOllamaChatModelInferenceExecutor(options)\n ? {\n baseURL: options.baseURL,\n headers: options.headers,\n }\n : isOpenRouterChatModelInferenceExecutor(options)\n ? {\n apiKey: options.apiKey,\n baseURL: options.baseURL,\n headers: options.headers,\n }\n : undefined\n\n return {\n aliases: options.aliases ?? [],\n executionPolicy: resolveModelExecutionPolicy(options),\n id: options.id ?? createDefaultModelId(inferenceExecutorId, options.model),\n inferenceExecutor: fallbackInferenceExecutor,\n inferenceExecutorId,\n model: options.model,\n parameters: options.parameters,\n provider: options.provider,\n runtimeResolvers,\n }\n}\n\n/**\n * Builds one normalized chat provider definition.\n *\n * Use when:\n * - one provider preset should be reused across multiple chat models\n * - provider configuration should support required/optional env-backed parameters\n */\nexport function chatProviderFrom(options: ChatProviderFromOptions): ChatProviderDefinition {\n return {\n id: options.id,\n inferenceExecutor: options.inferenceExecutor,\n inferenceExecutorId: normalizeInferenceExecutorId(options.inferenceExecutor, options.inferenceExecutorId),\n optionalEnv: options.optionalEnv,\n parameters: options.parameters,\n requiredEnv: options.requiredEnv,\n }\n}\n\n/**\n * Options for the built-in `ChatModels` plugin.\n */\nexport interface ChatModelsPluginOptions {\n /**\n * Chat model definitions to append to config.\n */\n models: readonly ChatModelDefinition[]\n}\n\n/**\n * Matrix scope that can carry a chat model selector.\n */\nexport type MatrixModelScope = 'eval' | 'run'\n\n/**\n * Options for resolving a chat model from a matrix axis.\n */\nexport interface ModelFromMatrixOptions {\n /**\n * Matrix axis whose selected value is a model id, model name, or alias.\n */\n axis: string\n}\n\ntype MatrixModelContext = Pick<TaskRunContext, 'models' | 'task'>\n\n/**\n * Resolves a configured chat model from one scoped matrix axis.\n *\n * Use when:\n * - a matrix axis selects the agent, judge, or another chat model role\n * - eval code should keep model lookup semantics inside the chat-models plugin\n *\n * Expects:\n * - `scope` to identify `context.task.matrix.run` or `context.task.matrix.eval`\n * - `options.axis` to exist and contain a model id, model name, or alias\n *\n * Returns:\n * - the configured model matching the selected matrix value\n */\nexport function modelFromMatrix(\n context: MatrixModelContext,\n scope: MatrixModelScope,\n options: ModelFromMatrixOptions,\n): ModelDefinition {\n const selectedModelName = context.task.matrix[scope][options.axis]\n\n if (selectedModelName == null) {\n throw new Error(`Missing ${scope} matrix axis \"${options.axis}\".`)\n }\n\n const model = resolveModelByName(context.models, selectedModelName)\n if (model == null) {\n throw new Error(`Unknown configured chat model \"${selectedModelName}\" from ${scope} matrix axis \"${options.axis}\".`)\n }\n\n return model\n}\n\n/**\n * Resolves a configured chat model from one run-matrix axis.\n *\n * Use when:\n * - run matrix selects the model used by the system under evaluation\n * - callers want the scoped helper instead of passing `scope: 'run'`\n *\n * Expects:\n * - `options.axis` to exist in `context.task.matrix.run`\n *\n * Returns:\n * - the configured model matching the selected run-matrix value\n */\nexport function modelFromRun(\n context: MatrixModelContext,\n options: ModelFromMatrixOptions,\n): ModelDefinition {\n return modelFromMatrix(context, 'run', options)\n}\n\n/**\n * Resolves a configured chat model from one eval-matrix axis.\n *\n * Use when:\n * - eval matrix selects a judge, rubric, or evaluator model\n * - callers want the scoped helper instead of passing `scope: 'eval'`\n *\n * Expects:\n * - `options.axis` to exist in `context.task.matrix.eval`\n *\n * Returns:\n * - the configured model matching the selected eval-matrix value\n */\nexport function modelFromEval(\n context: MatrixModelContext,\n options: ModelFromMatrixOptions,\n): ModelDefinition {\n return modelFromMatrix(context, 'eval', options)\n}\n\n/**\n * Creates a run-matrix `model` axis from configured chat model names.\n *\n * Use when:\n * - run matrix should iterate over explicit chat model ids/aliases\n * - project configs want a concise model-axis helper\n *\n * Expects:\n * - each provided name to match a configured model id or alias at runtime\n *\n * Returns:\n * - matrix axis object compatible with `runMatrix.extend/override`\n */\nexport function chatModelMatrix(...names: string[]): MatrixDefinition {\n return {\n model: Array.from(new Set(names)),\n }\n}\n\n/**\n * Built-in chat providers plugin that contributes provider presets to config.\n *\n * Use when:\n * - provider runtime config should be centralized and reusable\n * - provider parameters should be resolved from env via `envFrom`/`requiredEnvFrom`\n */\nexport function ChatProviders(options: ChatProvidersPluginOptions): Plugin {\n return {\n configVieval(config) {\n const env = config.env ?? options.env ?? process.env\n const normalizedProviders = options.providers.map(provider => normalizeChatProviderDefinition(provider, env))\n\n return {\n ...config,\n chatProviders: [\n ...(config.chatProviders ?? []),\n ...normalizedProviders,\n ],\n }\n },\n name: 'vieval:chat-providers',\n }\n}\n\n/**\n * Built-in chat models plugin that contributes model definitions to vieval config.\n *\n * Use when:\n * - chat-model registration should stay in config-level plugin setup\n * - tasks and assertions resolve models by name or alias at runtime\n */\nexport function ChatModels(options: ChatModelsPluginOptions): Plugin {\n return {\n async configVieval(config) {\n const resolvedModels = await Promise.all(options.models.map(async model => resolveChatModelDefinition(model, config)))\n\n return {\n ...config,\n models: [\n ...(config.models ?? []),\n ...resolvedModels,\n ],\n }\n },\n name: 'vieval:chat-models',\n }\n}\n\nexport * from './runtime-config'\nexport * from './telemetry'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/chat-models/runtime-config.ts","../../../src/plugins/chat-models/telemetry.ts","../../../src/plugins/chat-models/index.ts"],"sourcesContent":["import type { ModelDefinition } from '../../config/models'\nimport type { ChatModelHeaders } from './index'\n\nimport { envFrom, requiredEnvFrom } from '../../core/inference-executors/env'\n\n/**\n * Runtime config consumed by OpenAI-compatible provider constructors.\n */\nexport interface OpenAIChatModelRuntimeConfig {\n /**\n * Resolved inference executor kind.\n */\n inferenceExecutor: 'openai'\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Required API key.\n */\n apiKey: string\n /**\n * Optional base URL override.\n */\n baseURL?: string\n /**\n * Optional request headers.\n */\n headers?: ChatModelHeaders\n}\n\n/**\n * Runtime config consumed by Ollama provider constructors.\n */\nexport interface OllamaChatModelRuntimeConfig {\n /**\n * Resolved inference executor kind.\n */\n inferenceExecutor: 'ollama'\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Optional base URL override.\n */\n baseURL?: string\n /**\n * Optional request headers.\n */\n headers?: ChatModelHeaders\n}\n\n/**\n * Runtime config consumed by OpenRouter provider constructors.\n */\nexport interface OpenRouterChatModelRuntimeConfig {\n /**\n * Resolved inference executor kind.\n */\n inferenceExecutor: 'openrouter'\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Required API key.\n */\n apiKey: string\n /**\n * Optional base URL override.\n */\n baseURL?: string\n /**\n * Optional request headers.\n */\n headers?: ChatModelHeaders\n}\n\n/**\n * Union of normalized runtime configs for supported chat-model executors.\n */\nexport type ChatModelRuntimeConfig\n = OpenAIChatModelRuntimeConfig\n | OllamaChatModelRuntimeConfig\n | OpenRouterChatModelRuntimeConfig\n\nfunction getParameters(model: ModelDefinition): Record<string, unknown> {\n return model.parameters ?? {}\n}\n\nfunction parseOptionalStringParameter(\n parameters: Record<string, unknown>,\n key: string,\n modelId: string,\n): string | undefined {\n const value = parameters[key]\n const normalized = value == null ? undefined : String(value)\n const name = `${modelId}.parameters.${key}`\n\n return envFrom({ [name]: normalized }, {\n name,\n type: 'string',\n })\n}\n\nfunction parseRequiredStringParameter(\n parameters: Record<string, unknown>,\n key: string,\n modelId: string,\n): string {\n const value = parameters[key]\n const normalized = value == null ? undefined : String(value)\n const name = `${modelId}.parameters.${key}`\n\n return requiredEnvFrom({ [name]: normalized }, {\n name,\n type: 'string',\n })\n}\n\nfunction parseHeadersParameter(\n parameters: Record<string, unknown>,\n modelId: string,\n): ChatModelHeaders | undefined {\n const headers = parameters.headers\n if (headers == null) {\n return undefined\n }\n\n if (typeof headers !== 'object' || Array.isArray(headers)) {\n throw new TypeError(`Invalid ${modelId}.parameters.headers: expected an object.`)\n }\n\n const normalized: Record<string, string | string[]> = {}\n for (const [key, value] of Object.entries(headers as Record<string, unknown>)) {\n if (typeof value === 'string') {\n normalized[key] = value\n continue\n }\n\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n normalized[key] = value\n continue\n }\n\n throw new Error(`Invalid ${modelId}.parameters.headers.${key}: expected string or string[].`)\n }\n\n return normalized\n}\n\n/**\n * Normalizes one configured chat model into runtime executor config.\n *\n * Use when:\n * - eval code needs typed provider constructor options from a resolved model\n * - model parameters should be validated once with clear error messages\n *\n * Expects:\n * - `model.inferenceExecutorId` to be one of the supported executor ids\n * - required OpenAI fields (apiKey) to exist in `model.parameters`\n *\n * Returns:\n * - validated runtime config union for OpenAI or Ollama\n */\nexport function toChatModelRuntimeConfig(model: ModelDefinition): ChatModelRuntimeConfig {\n const parameters = getParameters(model)\n\n if (model.inferenceExecutorId === 'openai') {\n return {\n apiKey: parseRequiredStringParameter(parameters, 'apiKey', model.id),\n baseURL: parseOptionalStringParameter(parameters, 'baseURL', model.id),\n headers: parseHeadersParameter(parameters, model.id),\n inferenceExecutor: 'openai',\n model: model.model,\n }\n }\n\n if (model.inferenceExecutorId === 'ollama') {\n return {\n baseURL: parseOptionalStringParameter(parameters, 'baseURL', model.id),\n headers: parseHeadersParameter(parameters, model.id),\n inferenceExecutor: 'ollama',\n model: model.model,\n }\n }\n\n if (model.inferenceExecutorId === 'openrouter') {\n return {\n apiKey: parseRequiredStringParameter(parameters, 'apiKey', model.id),\n baseURL: parseOptionalStringParameter(parameters, 'baseURL', model.id),\n headers: parseHeadersParameter(parameters, model.id),\n inferenceExecutor: 'openrouter',\n model: model.model,\n }\n }\n\n throw new Error(`Unsupported chat inference executor \"${model.inferenceExecutorId}\" for model \"${model.id}\".`)\n}\n\n/**\n * Resolves OpenAI runtime config from one resolved run-context model.\n *\n * Use when:\n * - task execution already has a model resolved through chat-model helpers\n * - eval code wants typed OpenAI provider options with a concise helper name\n *\n * Expects:\n * - `model` to resolve to an OpenAI-backed chat model\n *\n * Returns:\n * - validated OpenAI runtime config\n */\nexport function openaiFromRunContext(model: ModelDefinition): OpenAIChatModelRuntimeConfig {\n const runtimeConfig = toChatModelRuntimeConfig(model)\n if (runtimeConfig.inferenceExecutor !== 'openai') {\n throw new Error(`Expected openai model, got \"${runtimeConfig.inferenceExecutor}\" for \"${model.id}\".`)\n }\n\n return runtimeConfig\n}\n\n/**\n * Resolves Ollama runtime config from one resolved run-context model.\n *\n * Use when:\n * - task execution already has a model resolved through chat-model helpers\n * - eval code wants typed Ollama provider options with a concise helper name\n *\n * Expects:\n * - `model` to resolve to an Ollama-backed chat model\n *\n * Returns:\n * - validated Ollama runtime config\n */\nexport function ollamaFromRunContext(model: ModelDefinition): OllamaChatModelRuntimeConfig {\n const runtimeConfig = toChatModelRuntimeConfig(model)\n if (runtimeConfig.inferenceExecutor !== 'ollama') {\n throw new Error(`Expected ollama model, got \"${runtimeConfig.inferenceExecutor}\" for \"${model.id}\".`)\n }\n\n return runtimeConfig\n}\n\n/**\n * Resolves OpenRouter runtime config from one resolved run-context model.\n *\n * Use when:\n * - task execution already has a model resolved through chat-model helpers\n * - eval code wants typed OpenRouter provider options with a concise helper name\n *\n * Expects:\n * - `model` to resolve to an OpenRouter-backed chat model\n *\n * Returns:\n * - validated OpenRouter runtime config\n */\nexport function openrouterFromRunContext(model: ModelDefinition): OpenRouterChatModelRuntimeConfig {\n const runtimeConfig = toChatModelRuntimeConfig(model)\n if (runtimeConfig.inferenceExecutor !== 'openrouter') {\n throw new Error(`Expected openrouter model, got \"${runtimeConfig.inferenceExecutor}\" for \"${model.id}\".`)\n }\n\n return runtimeConfig\n}\n","import type { TaskRunContext } from '../../config/types'\n\nimport { errorMessageFrom } from '@moeru/std'\n\n/**\n * Represents one normalized chat-model tool call.\n *\n * Use when:\n * - report events need tool-call level payloads that remain provider-neutral\n *\n * Expects:\n * - `name` to be stable enough for aggregation and assertion checks\n * - `args` to be JSON-serializable\n */\nexport interface ChatModelToolCall {\n /**\n * Optional provider-assigned tool-call identifier.\n */\n id?: string\n /**\n * Tool name.\n */\n name: string\n /**\n * Parsed tool arguments object/value.\n */\n args: unknown\n}\n\n/**\n * Provider identity attached to chat-model telemetry events.\n */\nexport interface ChatModelTelemetryProvider {\n /**\n * Provider id, for example `openai`.\n */\n id: string\n /**\n * Optional concrete model id/name.\n */\n model?: string\n}\n\n/**\n * Input options for response telemetry emission.\n */\nexport interface EmitChatModelResponseTelemetryOptions {\n /**\n * Optional case id for case-scoped telemetry events.\n */\n caseId?: string\n /**\n * Optional response latency in milliseconds.\n */\n latencyMs?: number\n /**\n * Optional provider identity payload.\n */\n provider?: ChatModelTelemetryProvider\n /**\n * Raw chat-model response object from the inference library/provider.\n */\n response: unknown\n}\n\n/**\n * Input options for request telemetry emission.\n */\nexport interface EmitChatModelRequestTelemetryOptions {\n /**\n * Optional case id for case-scoped telemetry events.\n */\n caseId?: string\n /**\n * Optional request payload metadata.\n */\n data?: unknown\n /**\n * Optional provider identity payload.\n */\n provider?: ChatModelTelemetryProvider\n}\n\n/**\n * Input options for error telemetry emission.\n */\nexport interface EmitChatModelErrorTelemetryOptions {\n /**\n * Optional case id for case-scoped telemetry events.\n */\n caseId?: string\n /**\n * Error payload emitted by the inference client/runtime.\n */\n error: unknown\n /**\n * Optional provider identity payload.\n */\n provider?: ChatModelTelemetryProvider\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (value == null || typeof value !== 'object') {\n return undefined\n }\n\n return value as Record<string, unknown>\n}\n\nfunction parseMaybeJson(value: unknown): unknown {\n if (typeof value !== 'string') {\n return value\n }\n\n try {\n return JSON.parse(value)\n }\n catch {\n return value\n }\n}\n\n/**\n * Extracts normalized tool calls from one chat-model response shape.\n *\n * Use when:\n * - downstream scoring, reporting, or analysis should inspect tool call usage\n * - provider payload differences should stay hidden behind one stable shape\n *\n * Returns:\n * - normalized list of `{ id?, name, args }` tool calls\n */\nexport function extractChatModelToolCalls(response: unknown): ChatModelToolCall[] {\n const responseRecord = asRecord(response)\n if (responseRecord == null) {\n return []\n }\n\n const rawToolCalls = responseRecord.toolCalls ?? responseRecord.tool_calls\n if (!Array.isArray(rawToolCalls)) {\n return []\n }\n\n const toolCalls: ChatModelToolCall[] = []\n\n for (const rawToolCall of rawToolCalls) {\n const toolCallRecord = asRecord(rawToolCall)\n if (toolCallRecord == null) {\n continue\n }\n\n const functionPayload = asRecord(toolCallRecord.function)\n const name = typeof toolCallRecord.name === 'string'\n ? toolCallRecord.name\n : typeof functionPayload?.name === 'string'\n ? functionPayload.name\n : undefined\n\n if (name == null || name.length === 0) {\n continue\n }\n\n const rawArgs = toolCallRecord.args\n ?? toolCallRecord.arguments\n ?? functionPayload?.args\n ?? functionPayload?.arguments\n\n toolCalls.push({\n args: parseMaybeJson(rawArgs),\n id: typeof toolCallRecord.id === 'string' ? toolCallRecord.id : undefined,\n name,\n })\n }\n\n return toolCalls\n}\n\n/**\n * Extracts numeric metering dimensions from one chat-model response usage block.\n *\n * Use when:\n * - report events should capture usage dimensions in a modality-neutral map\n *\n * Returns:\n * - numeric dimensions keyed by provider usage field names\n */\nexport function extractMeteringDimensions(response: unknown): Record<string, number> {\n const responseRecord = asRecord(response)\n const usage = asRecord(responseRecord?.usage)\n if (usage == null) {\n return {}\n }\n\n const dimensions: Record<string, number> = {}\n\n for (const [key, value] of Object.entries(usage)) {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n continue\n }\n\n dimensions[key] = value\n }\n\n return dimensions\n}\n\n/**\n * Emits chat-model response telemetry as reportable task events.\n *\n * Use when:\n * - task code receives one chat-model response and wants standardized report events\n * - `ToolCall*` and metering metrics should be persisted in `events.jsonl`\n *\n * Expects:\n * - `context.reporterHooks?.onEvent` to be available in CLI execution paths\n *\n * Returns:\n * - no return value; this is a best-effort reporting helper\n */\nexport function emitChatModelResponseTelemetry(\n context: TaskRunContext,\n options: EmitChatModelResponseTelemetryOptions,\n): void {\n const toolCalls = extractChatModelToolCalls(options.response)\n const meteringDimensions = extractMeteringDimensions(options.response)\n\n if (toolCalls.length > 0) {\n meteringDimensions.tool_call_count = toolCalls.length\n }\n\n const data = {\n metering: {\n dimensions: meteringDimensions,\n latency_ms: options.latencyMs,\n },\n metrics: {\n 'vieval.chat.tool_call_count': toolCalls.length,\n },\n modality: 'chat',\n provider: options.provider,\n toolCalls,\n }\n\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data,\n event: 'InferenceResponse',\n })\n\n for (const toolCall of toolCalls) {\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n modality: 'chat',\n provider: options.provider,\n toolCall,\n },\n event: 'ToolCallStarted',\n })\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n modality: 'chat',\n provider: options.provider,\n toolCall,\n },\n event: 'ToolCallEnded',\n })\n }\n}\n\n/**\n * Emits chat-model request telemetry as a reportable task event.\n *\n * Use when:\n * - task code submits one model request and wants request-side traceability\n *\n * Expects:\n * - `context.reporterHooks?.onEvent` to be available in CLI execution paths\n */\nexport function emitChatModelRequestTelemetry(\n context: TaskRunContext,\n options: EmitChatModelRequestTelemetryOptions,\n): void {\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n data: options.data,\n modality: 'chat',\n provider: options.provider,\n },\n event: 'InferenceRequest',\n })\n}\n\n/**\n * Emits chat-model failure telemetry as a reportable task event.\n *\n * Use when:\n * - one inference call fails and report artifacts should include normalized error context\n *\n * Expects:\n * - `context.reporterHooks?.onEvent` to be available in CLI execution paths\n */\nexport function emitChatModelErrorTelemetry(\n context: TaskRunContext,\n options: EmitChatModelErrorTelemetryOptions,\n): void {\n context.reporterHooks?.onEvent?.({\n caseId: options.caseId,\n data: {\n error: errorMessageFrom(options.error) ?? 'Unknown inference error.',\n modality: 'chat',\n provider: options.provider,\n },\n event: 'InferenceError',\n })\n}\n","import type { MatrixDefinition, TaskExecutionPolicy } from '../../config'\nimport type { ModelDefinition } from '../../config/models'\nimport type { ConfigHookPlugin } from '../../config/plugin'\nimport type { TaskRunContext } from '../../config/types'\nimport type { EnvFromOptions, RequiredEnvFromOptions } from '../../core/inference-executors/env'\n\nimport process from 'node:process'\n\nimport { resolveModelByName } from '../../config/models'\nimport { envFrom, requiredEnvFrom } from '../../core/inference-executors/env'\n\n/**\n * Minimal inference-executor shape expected by chat model runtime callers.\n */\nexport interface ChatModelExecutorLike {\n chat: (model: string) => Record<string, unknown>\n}\n\n/**\n * Inference-executor input accepted by `chatModelFrom`.\n */\nexport type ChatModelExecutorInput = string | ChatModelExecutorLike\n\n/**\n * Chat-model header payload accepted by executor parameters.\n */\nexport type ChatModelHeaders = Record<string, string | string[]>\n\n/**\n * Runtime env context passed to model callback resolvers.\n */\nexport interface ChatModelResolverContext {\n env: Record<string, string>\n}\n\n/**\n * Value-or-callback resolver used by model runtime fields.\n */\nexport type ChatModelResolverValue<TValue> = TValue | ((config: ChatModelResolverContext) => Promise<TValue> | TValue)\n\n/**\n * OpenAI-specific inference executor config shape.\n */\nexport interface OpenAIChatModelInferenceExecutor {\n inferenceExecutor: 'openai'\n apiKey?: ChatModelResolverValue<string>\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n}\n\n/**\n * Ollama-specific inference executor config shape.\n */\nexport interface OllamaChatModelInferenceExecutor {\n inferenceExecutor: 'ollama'\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n}\n\n/**\n * OpenRouter-specific inference executor config shape.\n */\nexport interface OpenRouterChatModelInferenceExecutor {\n inferenceExecutor: 'openrouter'\n apiKey?: ChatModelResolverValue<string>\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n}\n\n/**\n * Generic inference executor config shape.\n */\nexport interface GenericChatModelInferenceExecutor {\n inferenceExecutor?: ChatModelExecutorInput\n}\n\n/**\n * Union of supported inference executor config shapes for `chatModelFrom`.\n */\nexport type ChatModelInferenceExecutor\n = OpenAIChatModelInferenceExecutor\n | OllamaChatModelInferenceExecutor\n | OpenRouterChatModelInferenceExecutor\n | GenericChatModelInferenceExecutor\n\n/**\n * Common builder input fields for `chatModelFrom`.\n */\nexport interface ChatModelFromBaseOptions {\n /**\n * Provider id registered through `ChatProviders`.\n *\n * Use when:\n * - model runtime transport and credentials should be delegated to a named provider preset\n *\n * Expects:\n * - one `ChatProviders` plugin entry to expose the same id\n */\n provider?: string\n /**\n * Inference-executor id or inference-executor instance.\n */\n inferenceExecutor?: ChatModelExecutorInput\n /**\n * Optional explicit inference-executor id for inference-executor instances.\n *\n * @default 'custom'\n */\n inferenceExecutorId?: string\n /**\n * Concrete model name.\n */\n model: string\n /**\n * Optional stable model id.\n *\n * @default `${inferenceExecutorId}:${model}`\n */\n id?: string\n /**\n * Alias names used by `resolveModelByName`.\n */\n aliases?: string[]\n /**\n * Optional execution policy hints attached to this model.\n */\n executionPolicy?: TaskExecutionPolicy\n /**\n * Additional retries allowed within the current attempt.\n *\n * @default 0\n */\n autoRetry?: number\n /**\n * Delay in milliseconds before a retry starts.\n *\n * @default retryIndex => 500 * 2 ** (retryIndex - 1)\n */\n autoRetryDelay?: TaskExecutionPolicy['autoRetryDelay']\n /**\n * Additional full task attempts allowed after the current attempt settles.\n *\n * @default 0\n */\n autoAttempt?: number\n /**\n * Timeout in milliseconds for model-backed work.\n */\n timeout?: number\n /**\n * Optional model-level call parameters.\n */\n parameters?: Record<string, unknown>\n}\n\n/**\n * Builder input for `chatModelFrom`.\n */\nexport type ChatModelFromOptions = ChatModelInferenceExecutor & ChatModelFromBaseOptions\n\n/**\n * Chat-model specific specialization of the canonical `ModelDefinition`.\n */\nexport type ChatModelDefinition = Omit<ModelDefinition, 'inferenceExecutor'> & {\n inferenceExecutor: ChatModelExecutorInput\n provider?: string\n runtimeResolvers?: {\n apiKey?: ChatModelResolverValue<string>\n baseURL?: ChatModelResolverValue<string>\n headers?: ChatModelResolverValue<ChatModelHeaders>\n }\n}\n\nfunction normalizeExecutionPolicy(\n policy: TaskExecutionPolicy | undefined,\n): TaskExecutionPolicy | undefined {\n if (policy == null) {\n return undefined\n }\n\n const normalized = {\n autoAttempt: policy.autoAttempt,\n autoRetry: policy.autoRetry,\n autoRetryDelay: policy.autoRetryDelay,\n timeout: policy.timeout,\n }\n\n return Object.values(normalized).some(value => value != null)\n ? normalized\n : undefined\n}\n\nfunction hasJudgeAlias(model: Pick<ChatModelFromBaseOptions, 'aliases' | 'id' | 'model'>): boolean {\n return [\n ...(model.aliases ?? []),\n ...(model.id == null ? [] : [model.id]),\n model.model,\n ].some(value => value.toLowerCase().includes('judge'))\n}\n\nfunction resolveModelExecutionPolicy(options: ChatModelFromOptions): TaskExecutionPolicy | undefined {\n const explicitPolicy = normalizeExecutionPolicy({\n autoAttempt: options.autoAttempt ?? options.executionPolicy?.autoAttempt,\n autoRetry: options.autoRetry ?? options.executionPolicy?.autoRetry,\n autoRetryDelay: options.autoRetryDelay ?? options.executionPolicy?.autoRetryDelay,\n timeout: options.timeout ?? options.executionPolicy?.timeout,\n })\n\n if (explicitPolicy != null && Object.keys(explicitPolicy).length > 0) {\n return explicitPolicy\n }\n\n if (hasJudgeAlias(options)) {\n return {\n autoRetry: 3,\n }\n }\n\n return undefined\n}\n\n/**\n * Env-key map for optional provider parameters.\n *\n * Use when:\n * - provider parameter values should be read from env keys\n * - missing keys should resolve to `undefined`\n */\nexport type OptionalProviderEnvMap = Record<string, string>\n\n/**\n * Env-key map for required provider parameters.\n *\n * Use when:\n * - provider parameter values must exist before model execution\n * - missing keys should throw with key-aware error messages\n */\nexport type RequiredProviderEnvMap = Record<string, string>\n\n/**\n * One provider definition consumed by chat model presets.\n */\nexport interface ChatProviderDefinition {\n /**\n * Stable provider id referenced by `chatModelFrom({ provider })`.\n */\n id: string\n /**\n * Inference-executor id or instance used by this provider preset.\n */\n inferenceExecutor: ChatModelExecutorInput\n /**\n * Optional explicit inference-executor id for inference-executor instances.\n *\n * @default 'custom'\n */\n inferenceExecutorId?: string\n /**\n * Optional literal provider-level parameters.\n */\n parameters?: Record<string, unknown>\n /**\n * Optional provider parameters resolved via `envFrom`.\n *\n * Expects:\n * - map key is the provider parameter name\n * - map value is the env key name\n */\n optionalEnv?: OptionalProviderEnvMap\n /**\n * Required provider parameters resolved via `requiredEnvFrom`.\n *\n * Expects:\n * - map key is the provider parameter name\n * - map value is the env key name\n */\n requiredEnv?: RequiredProviderEnvMap\n}\n\n/**\n * Builder input for `chatProviderFrom`.\n */\nexport interface ChatProviderFromOptions extends ChatProviderDefinition {\n}\n\n/**\n * Options for the built-in `ChatProviders` plugin.\n */\nexport interface ChatProvidersPluginOptions {\n /**\n * Provider definitions to append to config.\n */\n providers: readonly ChatProviderDefinition[]\n /**\n * Optional explicit env source used for env-backed provider parameters.\n *\n * @default process.env\n */\n env?: NodeJS.ProcessEnv\n}\n\n/**\n * Partial config shape needed by the chat models plugin.\n */\nexport interface PluginConfig {\n env?: NodeJS.ProcessEnv\n chatProviders?: ChatProviderDefinition[]\n models?: ModelDefinition[]\n}\n\n/**\n * Plugin type bound to the minimal config shape used by model plugins.\n */\nexport type Plugin = ConfigHookPlugin<PluginConfig>\n\nfunction normalizeInferenceExecutorId(\n inferenceExecutor: ChatModelExecutorInput,\n inferenceExecutorId: string | undefined,\n): string {\n if (typeof inferenceExecutor === 'string') {\n return inferenceExecutor\n }\n\n return inferenceExecutorId ?? 'custom'\n}\n\nfunction createDefaultModelId(inferenceExecutorId: string, model: string): string {\n return `${inferenceExecutorId}:${model}`\n}\n\nfunction normalizeEnvRecord(env: NodeJS.ProcessEnv): Record<string, string> {\n const normalized: Record<string, string> = {}\n for (const [key, value] of Object.entries(env)) {\n if (typeof value === 'string') {\n normalized[key] = value\n }\n }\n\n return normalized\n}\n\nasync function resolveChatModelResolverValue<TValue>(\n value: ChatModelResolverValue<TValue>,\n context: ChatModelResolverContext,\n): Promise<TValue> {\n if (typeof value === 'function') {\n const resolver = value as (config: ChatModelResolverContext) => Promise<TValue> | TValue\n return await resolver(context)\n }\n\n return value\n}\n\nfunction resolveRequiredStringValue(value: string | undefined, name: string): string {\n return requiredEnvFrom({ [name]: value }, {\n name,\n type: 'string',\n })\n}\n\nfunction resolveOptionalStringValue(value: string | undefined, name: string): string | undefined {\n return envFrom({ [name]: value }, {\n name,\n type: 'string',\n })\n}\n\nfunction resolveOptionalEnvValue(\n env: NodeJS.ProcessEnv,\n envKey: string,\n): string | undefined {\n const options: EnvFromOptions = {\n name: envKey,\n type: 'string',\n }\n\n return envFrom(env, options)\n}\n\nfunction resolveRequiredEnvValue(\n env: NodeJS.ProcessEnv,\n envKey: string,\n): string {\n const options: RequiredEnvFromOptions = {\n name: envKey,\n type: 'string',\n }\n\n return requiredEnvFrom(env, options)\n}\n\nfunction resolveProviderParameters(\n provider: ChatProviderDefinition,\n env: NodeJS.ProcessEnv,\n): Record<string, unknown> | undefined {\n const parameters: Record<string, unknown> = {\n ...provider.parameters,\n }\n\n for (const [parameterName, envKey] of Object.entries(provider.optionalEnv ?? {})) {\n const resolved = resolveOptionalEnvValue(env, envKey)\n if (resolved != null) {\n parameters[parameterName] = resolved\n }\n }\n\n for (const [parameterName, envKey] of Object.entries(provider.requiredEnv ?? {})) {\n parameters[parameterName] = resolveRequiredEnvValue(env, envKey)\n }\n\n return Object.keys(parameters).length > 0 ? parameters : undefined\n}\n\nfunction normalizeChatProviderDefinition(\n provider: ChatProviderDefinition,\n env: NodeJS.ProcessEnv,\n): ChatProviderDefinition {\n return {\n id: provider.id,\n inferenceExecutor: provider.inferenceExecutor,\n inferenceExecutorId: normalizeInferenceExecutorId(provider.inferenceExecutor, provider.inferenceExecutorId),\n optionalEnv: provider.optionalEnv,\n parameters: resolveProviderParameters(provider, env),\n requiredEnv: provider.requiredEnv,\n }\n}\n\nfunction createProviderMap(config: PluginConfig): Map<string, ChatProviderDefinition> {\n const providerMap = new Map<string, ChatProviderDefinition>()\n for (const provider of config.chatProviders ?? []) {\n providerMap.set(provider.id, provider)\n }\n\n return providerMap\n}\n\nfunction resolveModelProvider(\n model: ChatModelDefinition,\n providerMap: ReadonlyMap<string, ChatProviderDefinition>,\n): ChatModelDefinition {\n if (model.provider == null) {\n return model\n }\n\n const provider = providerMap.get(model.provider)\n if (provider == null) {\n throw new Error(`Unknown chat provider \"${model.provider}\" referenced by model \"${model.id}\".`)\n }\n\n return {\n ...model,\n inferenceExecutor: provider.inferenceExecutor,\n inferenceExecutorId: provider.inferenceExecutorId ?? normalizeInferenceExecutorId(provider.inferenceExecutor, provider.inferenceExecutorId),\n parameters: {\n ...provider.parameters,\n ...model.parameters,\n },\n }\n}\n\nasync function resolveModelRuntimeResolvers(\n model: ChatModelDefinition,\n context: ChatModelResolverContext,\n): Promise<Record<string, unknown> | undefined> {\n if (model.runtimeResolvers == null) {\n return undefined\n }\n\n const resolvedParameters: Record<string, unknown> = {}\n\n if (model.runtimeResolvers.apiKey != null) {\n const resolvedApiKey = await resolveChatModelResolverValue(model.runtimeResolvers.apiKey, context)\n resolvedParameters.apiKey = resolveRequiredStringValue(resolvedApiKey, `${model.id}.apiKey`)\n }\n\n if (model.runtimeResolvers.baseURL != null) {\n const resolvedBaseURL = await resolveChatModelResolverValue(model.runtimeResolvers.baseURL, context)\n const normalizedBaseURL = resolveOptionalStringValue(resolvedBaseURL, `${model.id}.baseURL`)\n if (normalizedBaseURL != null) {\n resolvedParameters.baseURL = normalizedBaseURL\n }\n }\n\n if (model.runtimeResolvers.headers != null) {\n const resolvedHeaders = await resolveChatModelResolverValue(model.runtimeResolvers.headers, context)\n resolvedParameters.headers = resolvedHeaders\n }\n\n return Object.keys(resolvedParameters).length > 0 ? resolvedParameters : undefined\n}\n\nasync function resolveChatModelDefinition(\n model: ChatModelDefinition,\n config: PluginConfig,\n): Promise<ChatModelDefinition> {\n const providerResolvedModel = resolveModelProvider(model, createProviderMap(config))\n const resolvedRuntimeParameters = await resolveModelRuntimeResolvers(providerResolvedModel, {\n env: normalizeEnvRecord(config.env ?? process.env),\n })\n\n if (resolvedRuntimeParameters == null) {\n return providerResolvedModel\n }\n\n return {\n ...providerResolvedModel,\n parameters: {\n ...providerResolvedModel.parameters,\n ...resolvedRuntimeParameters,\n },\n }\n}\n\nfunction isOpenAIChatModelInferenceExecutor(\n options: ChatModelFromOptions,\n): options is ChatModelFromBaseOptions & OpenAIChatModelInferenceExecutor {\n return options.inferenceExecutor === 'openai'\n}\n\nfunction isOllamaChatModelInferenceExecutor(\n options: ChatModelFromOptions,\n): options is ChatModelFromBaseOptions & OllamaChatModelInferenceExecutor {\n return options.inferenceExecutor === 'ollama'\n}\n\nfunction isOpenRouterChatModelInferenceExecutor(\n options: ChatModelFromOptions,\n): options is ChatModelFromBaseOptions & OpenRouterChatModelInferenceExecutor {\n return options.inferenceExecutor === 'openrouter'\n}\n\n/**\n * Builds one normalized chat model definition.\n *\n * Use when:\n * - registering chat models through config plugins\n * - a single model needs aliases for matrix selection or judge lookup\n */\nexport function chatModelFrom(options: ChatModelFromOptions): ChatModelDefinition {\n const fallbackInferenceExecutor = options.inferenceExecutor ?? options.provider ?? 'custom'\n const inferenceExecutorId = normalizeInferenceExecutorId(fallbackInferenceExecutor, options.inferenceExecutorId)\n const runtimeResolvers = isOpenAIChatModelInferenceExecutor(options)\n ? {\n apiKey: options.apiKey,\n baseURL: options.baseURL,\n headers: options.headers,\n }\n : isOllamaChatModelInferenceExecutor(options)\n ? {\n baseURL: options.baseURL,\n headers: options.headers,\n }\n : isOpenRouterChatModelInferenceExecutor(options)\n ? {\n apiKey: options.apiKey,\n baseURL: options.baseURL,\n headers: options.headers,\n }\n : undefined\n\n return {\n aliases: options.aliases ?? [],\n executionPolicy: resolveModelExecutionPolicy(options),\n id: options.id ?? createDefaultModelId(inferenceExecutorId, options.model),\n inferenceExecutor: fallbackInferenceExecutor,\n inferenceExecutorId,\n model: options.model,\n parameters: options.parameters,\n provider: options.provider,\n runtimeResolvers,\n }\n}\n\n/**\n * Builds one normalized chat provider definition.\n *\n * Use when:\n * - one provider preset should be reused across multiple chat models\n * - provider configuration should support required/optional env-backed parameters\n */\nexport function chatProviderFrom(options: ChatProviderFromOptions): ChatProviderDefinition {\n return {\n id: options.id,\n inferenceExecutor: options.inferenceExecutor,\n inferenceExecutorId: normalizeInferenceExecutorId(options.inferenceExecutor, options.inferenceExecutorId),\n optionalEnv: options.optionalEnv,\n parameters: options.parameters,\n requiredEnv: options.requiredEnv,\n }\n}\n\n/**\n * Options for the built-in `ChatModels` plugin.\n */\nexport interface ChatModelsPluginOptions {\n /**\n * Chat model definitions to append to config.\n */\n models: readonly ChatModelDefinition[]\n}\n\n/**\n * Matrix scope that can carry a chat model selector.\n */\nexport type MatrixModelScope = 'eval' | 'run'\n\n/**\n * Options for resolving a chat model from a matrix axis.\n */\nexport interface ModelFromMatrixOptions {\n /**\n * Matrix axis whose selected value is a model id, model name, or alias.\n */\n axis: string\n}\n\ntype MatrixModelContext = Pick<TaskRunContext, 'models' | 'task'>\n\n/**\n * Resolves a configured chat model from one scoped matrix axis.\n *\n * Use when:\n * - a matrix axis selects the agent, judge, or another chat model role\n * - eval code should keep model lookup semantics inside the chat-models plugin\n *\n * Expects:\n * - `scope` to identify `context.task.matrix.run` or `context.task.matrix.eval`\n * - `options.axis` to exist and contain a model id, model name, or alias\n *\n * Returns:\n * - the configured model matching the selected matrix value\n */\nexport function modelFromMatrix(\n context: MatrixModelContext,\n scope: MatrixModelScope,\n options: ModelFromMatrixOptions,\n): ModelDefinition {\n const selectedModelName = context.task.matrix[scope][options.axis]\n\n if (selectedModelName == null) {\n throw new Error(`Missing ${scope} matrix axis \"${options.axis}\".`)\n }\n\n const model = resolveModelByName(context.models, selectedModelName)\n if (model == null) {\n throw new Error(`Unknown configured chat model \"${selectedModelName}\" from ${scope} matrix axis \"${options.axis}\".`)\n }\n\n return model\n}\n\n/**\n * Resolves a configured chat model from one run-matrix axis.\n *\n * Use when:\n * - run matrix selects the model used by the system under evaluation\n * - callers want the scoped helper instead of passing `scope: 'run'`\n *\n * Expects:\n * - `options.axis` to exist in `context.task.matrix.run`\n *\n * Returns:\n * - the configured model matching the selected run-matrix value\n */\nexport function modelFromRun(\n context: MatrixModelContext,\n options: ModelFromMatrixOptions,\n): ModelDefinition {\n return modelFromMatrix(context, 'run', options)\n}\n\n/**\n * Resolves a configured chat model from one eval-matrix axis.\n *\n * Use when:\n * - eval matrix selects a judge, rubric, or evaluator model\n * - callers want the scoped helper instead of passing `scope: 'eval'`\n *\n * Expects:\n * - `options.axis` to exist in `context.task.matrix.eval`\n *\n * Returns:\n * - the configured model matching the selected eval-matrix value\n */\nexport function modelFromEval(\n context: MatrixModelContext,\n options: ModelFromMatrixOptions,\n): ModelDefinition {\n return modelFromMatrix(context, 'eval', options)\n}\n\n/**\n * Creates a run-matrix `model` axis from configured chat model names.\n *\n * Use when:\n * - run matrix should iterate over explicit chat model ids/aliases\n * - project configs want a concise model-axis helper\n *\n * Expects:\n * - each provided name to match a configured model id or alias at runtime\n *\n * Returns:\n * - matrix axis object compatible with `runMatrix.extend/override`\n */\nexport function chatModelMatrix(...names: string[]): MatrixDefinition {\n return {\n model: Array.from(new Set(names)),\n }\n}\n\n/**\n * Built-in chat providers plugin that contributes provider presets to config.\n *\n * Use when:\n * - provider runtime config should be centralized and reusable\n * - provider parameters should be resolved from env via `envFrom`/`requiredEnvFrom`\n */\nexport function ChatProviders(options: ChatProvidersPluginOptions): Plugin {\n return {\n configVieval(config) {\n const env = config.env ?? options.env ?? process.env\n const normalizedProviders = options.providers.map(provider => normalizeChatProviderDefinition(provider, env))\n\n return {\n ...config,\n chatProviders: [\n ...(config.chatProviders ?? []),\n ...normalizedProviders,\n ],\n }\n },\n name: 'vieval:chat-providers',\n }\n}\n\n/**\n * Built-in chat models plugin that contributes model definitions to vieval config.\n *\n * Use when:\n * - chat-model registration should stay in config-level plugin setup\n * - tasks and assertions resolve models by name or alias at runtime\n */\nexport function ChatModels(options: ChatModelsPluginOptions): Plugin {\n return {\n async configVieval(config) {\n const resolvedModels = await Promise.all(options.models.map(async model => resolveChatModelDefinition(model, config)))\n\n return {\n ...config,\n models: [\n ...(config.models ?? []),\n ...resolvedModels,\n ],\n }\n },\n name: 'vieval:chat-models',\n }\n}\n\nexport * from './runtime-config'\nexport * from './telemetry'\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/dist/env-BFSjny07.mjs
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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-BFSjny07.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env-BFSjny07.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"}
|