axiom
Version:
Axiom AI SDK provides - an API to wrap your AI calls with observability instrumentation. - offline evals
1 lines • 349 kB
Source Map (JSON)
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.0_jiti@2.6.1_postcss@8.5.6_tsx@4.20.4_typescript@5.9.2/node_modules/tsup/assets/cjs_shims.js","../src/evals/context/manager.ts","../src/evals/context/global-flags.ts","../src/cli/utils/format-zod-errors.ts","../src/util/zod-internals.ts","../src/util/dot-path.ts","../src/util/deep-partial-schema.ts","../src/validate-flags.ts","../src/otel/utils/to-otel-attribute.ts","../src/otel/withSpanBaggageKey.ts","../src/otel/semconv/eval_proposal.ts","../src/otel/semconv/attributes.ts","../src/schema.ts","../src/otel/startActiveSpan.ts","../package.json","../src/otel/utils/redaction.ts","../src/otel/initAxiomAI.ts","../src/otel/utils/wrapperUtils.ts","../src/util/name-validation-runtime.ts","../src/otel/withSpan.ts","../src/otel/utils/contentSanitizer.ts","../src/otel/completionUtils.ts","../src/util/promptUtils.ts","../src/otel/utils/normalized.ts","../src/util/currentUnixTime.ts","../src/otel/streaming/aggregators.ts","../src/otel/middleware.ts","../src/otel/AxiomWrappedLanguageModelV1.ts","../src/otel/AxiomWrappedLanguageModelV2.ts","../src/otel/vercel.ts","../src/otel/index.ts","../src/app-scope.ts","../src/evals/context/storage.ts","../src/context.ts","../src/cli/utils/eval-context-runner.ts","../src/cli/utils/parse-flag-overrides.ts","../src/cli/utils/glob-utils.ts","../src/util/errors.ts","../src/cli/auth/types.ts","../src/cli/auth/config.ts","../src/cli/auth/oauth.ts","../src/cli/auth/api.ts","../src/cli/auth/callback-server.ts","../src/cli/auth/global-auth.ts","../src/cli/auth/index.ts","../src/config/index.ts","../src/config/loader.ts","../../../node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js","../../../node_modules/.pnpm/tinyrainbow@2.0.0/node_modules/tinyrainbow/dist/node.js","../src/evals/reporter.console-utils.ts","../src/config/resolver.ts","../src/evals/reporter.ts","../src/evals/instrument.ts","../src/evals/run-vitest.ts","../src/cli/commands/eval.command.ts","../src/bin.ts","../src/cli/commands/auth.command.ts","../src/cli/commands/auth-login.command.ts","../src/cli/commands/auth-logout.command.ts","../src/cli/commands/auth-status.command.ts","../src/cli/commands/auth-switch.command.ts","../src/cli/commands/version.command.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { createRequire } from 'node:module';\n\ninterface ContextManager<T = any> {\n getStore(): T | undefined;\n run<R>(value: T, fn: () => R): R;\n}\n\nconst CONTEXT_MANAGER_SYMBOL = Symbol.for('axiom.context_manager');\n\nfunction getGlobalContextManager(): ContextManager | undefined {\n return (globalThis as any)[CONTEXT_MANAGER_SYMBOL];\n}\n\nfunction setGlobalContextManager(manager: ContextManager): void {\n (globalThis as any)[CONTEXT_MANAGER_SYMBOL] = manager;\n}\n\nconst isNodeJS = typeof process !== 'undefined' && !!process.versions?.node;\n\nfunction getContextManager(): ContextManager {\n // Check global Symbol registry cache first (shared across VM contexts)\n const existing = getGlobalContextManager();\n if (existing) return existing;\n\n let manager: ContextManager;\n\n if (isNodeJS) {\n try {\n // Resolve AsyncLocalStorage in both ESM and CJS Node contexts without bundler interference\n let AsyncLocalStorage: any;\n\n // Use createRequire to obtain a require in ESM\n const req = createRequire(import.meta.url);\n try {\n AsyncLocalStorage = req('node:async_hooks').AsyncLocalStorage;\n } catch {\n AsyncLocalStorage = req('async_hooks').AsyncLocalStorage;\n }\n\n manager = new AsyncLocalStorage();\n } catch (error) {\n // Fallback if AsyncLocalStorage cannot be loaded\n console.warn('AsyncLocalStorage not available, using fallback context manager:', error);\n manager = createFallbackManager();\n }\n } else {\n // Browser/CF Workers - simple fallback (no warning needed here)\n console.warn('AsyncLocalStorage not available, using fallback context manager');\n manager = createFallbackManager();\n }\n\n // Cache using Symbol to share across VM contexts\n setGlobalContextManager(manager);\n\n return manager;\n}\n\nfunction createFallbackManager(): ContextManager {\n let currentContext: any = null;\n return {\n getStore: () => currentContext,\n run: <R>(value: any, fn: () => R): R => {\n const prev = currentContext;\n currentContext = value;\n try {\n return fn();\n } finally {\n currentContext = prev;\n }\n },\n };\n}\n\nexport function createAsyncHook<T>(_name: string) {\n return {\n get(): T | undefined {\n const manager = getContextManager();\n if (manager.getStore) {\n return manager.getStore();\n }\n return undefined;\n },\n run<R>(value: T, fn: () => R): R {\n const manager = getContextManager();\n return manager.run(value, fn);\n },\n };\n}\n\n/**\n * Reset the context manager singleton for tests.\n * This clears the global cache and forces a new AsyncLocalStorage instance to be created.\n * Useful for test isolation when needed.\n */\nexport function __resetContextManagerForTests(): void {\n delete (globalThis as any)[CONTEXT_MANAGER_SYMBOL];\n}\n","/**\n * Global flag overrides storage for CLI flag functionality.\n * Uses globalThis for process-wide flag persistence.\n */\n\nconst GLOBAL_OVERRIDES_SYMBOL = Symbol.for('axiom.global_flag_overrides');\n\nfunction getRoot(): Record<string, any> {\n return (globalThis as any)[GLOBAL_OVERRIDES_SYMBOL] ?? {};\n}\n\nfunction setRoot(val: Record<string, any>): void {\n (globalThis as any)[GLOBAL_OVERRIDES_SYMBOL] = val;\n}\n\n/**\n * Set global flag overrides (called by CLI) - persists until cleared\n */\nexport function setGlobalFlagOverrides(overrides: Record<string, any>): void {\n setRoot(overrides);\n}\n\n/**\n * Get global flag overrides (called by flag functions)\n */\nexport function getGlobalFlagOverrides(): Record<string, any> {\n return getRoot();\n}\n\n/**\n * Clear global flag overrides (for testing)\n */\nexport function clearGlobalFlagOverrides(): void {\n setRoot({});\n}\n","import { type ZodError } from 'zod';\nimport type { ZodIssue } from 'zod/v3';\nimport type { $ZodIssue } from 'zod/v4/core';\n\n/**\n * Format ZodError issues into user-friendly CLI error messages\n */\nexport function formatZodErrors(error: ZodError): string {\n const issues = error.issues;\n const messages: string[] = [];\n\n for (const issue of issues) {\n const path = issue.path.join('.');\n const message = formatIssueMessage(issue, path);\n messages.push(` • ${message}`);\n }\n\n return messages.join('\\n');\n}\n\nfunction formatIssueMessage(issue: any, path: string): string {\n switch (issue.code) {\n case 'invalid_type':\n return `flag '${path}' expected ${issue.expected}, got ${JSON.stringify(issue.received)} (${typeof issue.received})`;\n\n case 'too_small':\n if (issue.type === 'number' || issue.origin === 'number') {\n return `flag '${path}' must be >= ${issue.minimum}, got ${issue.received}`;\n }\n return `flag '${path}' is too small: ${issue.message}`;\n\n case 'too_big':\n if (issue.type === 'number') {\n return `flag '${path}' must be <= ${issue.maximum}, got ${issue.received}`;\n }\n return `flag '${path}' is too big: ${issue.message}`;\n\n case 'invalid_enum_value':\n const options = issue.options.map((opt: any) => `\"${opt}\"`).join(', ');\n return `flag '${path}' must be one of: ${options}, got \"${issue.received}\"`;\n\n case 'invalid_value':\n // Handle enum validation errors\n if (issue.values && Array.isArray(issue.values)) {\n const values = issue.values.map((val: any) => `\"${val}\"`).join(', ');\n return `flag '${path}' must be one of: ${values}`;\n }\n return `flag '${path}': ${issue.message}`;\n\n case 'unrecognized_keys':\n // Handle unrecognized keys properly, especially when path is empty\n const keys = issue.keys || [];\n if (keys.length === 1) {\n return `unrecognized flag '${keys[0]}'`;\n } else if (keys.length > 1) {\n const keysList = keys.map((key: string) => `'${key}'`).join(', ');\n return `unrecognized flags ${keysList}`;\n }\n return `unrecognized keys in flags`;\n\n case 'custom':\n return `flag '${path}': ${issue.message}`;\n\n default:\n return `flag '${path}': ${issue.message}`;\n }\n}\n\n/**\n * Create helpful examples for CLI usage based on validation errors\n */\nexport function generateFlagExamples(error: ZodError): string[] {\n const examples: string[] = [];\n\n for (const issue of error.issues) {\n const path = issue.path.join('.');\n const example = generateExampleForIssue(issue, path);\n if (example && !examples.includes(example)) {\n examples.push(example);\n }\n }\n\n return examples.slice(0, 3); // Limit to 3 examples\n}\n\nfunction generateExampleForIssue(issue: ZodIssue | $ZodIssue, path: string): string | null {\n switch (issue.code) {\n case 'invalid_type':\n if (issue.expected === 'number') {\n return `--flag.${path}=0.7`;\n }\n if (issue.expected === 'boolean') {\n return `--flag.${path}=true`;\n }\n if (issue.expected === 'string') {\n return `--flag.${path}=\"value\"`;\n }\n break;\n\n case 'too_small':\n if (typeof issue.minimum === 'number' || typeof issue.minimum === 'bigint') {\n return `--flag.${path}=${issue.minimum}`;\n }\n break;\n\n case 'too_big':\n if (typeof issue.maximum === 'number' || typeof issue.maximum === 'bigint') {\n return `--flag.${path}=${issue.maximum}`;\n }\n break;\n\n case 'invalid_enum_value':\n if (issue.options.length > 0) {\n return `--flag.${path}=${issue.options[0]}`;\n }\n break;\n\n case 'invalid_value':\n if (issue.values && Array.isArray(issue.values) && issue.values.length > 0) {\n return `--flag.${path}=${String(issue.values[0])}`;\n }\n break;\n }\n\n return null;\n}\n","import type { ZodObject, ZodType } from 'zod';\n\n/**\n * Detect if a schema is from Zod v4.\n * v4 schemas have `_zod`, v3 schemas only have `_def`.\n */\nexport function isZodV4Schema(schema: unknown): boolean {\n if (!schema || typeof schema !== 'object') return false;\n const s = schema as Record<string, unknown>;\n return '_zod' in s;\n}\n\n/**\n * Assert that a schema is from Zod v4, throwing a helpful error if it isn't.\n */\nexport function assertZodV4(schema: unknown, context: string): void {\n if (!isZodV4Schema(schema)) {\n throw new Error(\n `[AxiomAI] Zod v4 schemas are required (detected in ${context}). Found unsupported Zod version.`,\n );\n }\n}\n\n/** Normalized schema kinds we care about */\nexport type ZodKind =\n | 'object'\n | 'optional'\n | 'default'\n | 'nullable'\n | 'readonly'\n | 'prefault'\n | 'nonoptional'\n | 'catch'\n | 'array'\n | 'record'\n | 'union'\n | 'discriminatedunion'\n | 'other';\n\n/** Minimal internal def shape we access (Zod v4) */\ninterface ZodInternalDef {\n type?: unknown;\n innerType?: ZodType<unknown>;\n element?: ZodType<unknown>;\n defaultValue?: unknown;\n shape?: Record<string, ZodType<unknown>>;\n valueType?: ZodType<unknown>;\n}\n\n/**\n * Get the internal def object from a Zod v4 schema.\n */\nexport function getDef(schema: unknown): ZodInternalDef | undefined {\n if (!schema || typeof schema !== 'object') return undefined;\n\n const s = schema as Record<string, unknown>;\n\n if (s._zod && typeof s._zod === 'object') {\n const zod = s._zod as Record<string, unknown>;\n if (zod.def && typeof zod.def === 'object') {\n return zod.def as ZodInternalDef;\n }\n }\n\n return undefined;\n}\n\n/**\n * Get the raw type string from a def (Zod v4).\n */\nfunction getDefRawType(def: ZodInternalDef | undefined): string | undefined {\n if (!def) return undefined;\n const raw = def.type;\n if (raw == null) return undefined;\n return typeof raw === 'string' ? raw : String(raw);\n}\n\nconst KNOWN_KINDS = new Set<ZodKind>([\n 'object',\n 'optional',\n 'default',\n 'nullable',\n 'readonly',\n 'prefault',\n 'nonoptional',\n 'catch',\n 'array',\n 'record',\n 'union',\n 'discriminatedunion',\n]);\n\n/**\n * Get the normalized ZodKind from a schema or def (Zod v4).\n */\nexport function getKind(schemaOrDef: unknown): ZodKind | undefined {\n // If it looks like a def already (has type), use it directly\n const def =\n schemaOrDef && typeof schemaOrDef === 'object' && 'type' in schemaOrDef\n ? (schemaOrDef as ZodInternalDef)\n : getDef(schemaOrDef);\n\n const raw = getDefRawType(def);\n if (!raw) return undefined;\n\n const normalized = raw.toLowerCase();\n return KNOWN_KINDS.has(normalized as ZodKind) ? (normalized as ZodKind) : 'other';\n}\n\n/**\n * Check if a schema is an object schema (has shape).\n */\nexport function isObjectSchema(schema: unknown): schema is ZodObject<Record<string, ZodType>> {\n if (!schema || typeof schema !== 'object') return false;\n\n if ('shape' in schema && typeof (schema as Record<string, unknown>).shape === 'object') {\n return true;\n }\n\n return getKind(schema) === 'object';\n}\n\n/**\n * Get the innerType from wrapper schemas (optional, nullable, default).\n */\nexport function getInnerType(schema: unknown): ZodType<unknown> | undefined {\n const def = getDef(schema);\n return def?.innerType;\n}\n\n/**\n * Get the element type from array schemas.\n */\nexport function getArrayElement(schema: unknown): ZodType<unknown> | undefined {\n const def = getDef(schema);\n return def?.element;\n}\n\n/**\n * Get the shape from an object schema (Zod v4).\n */\nexport function getShape(schema: unknown): Record<string, ZodType<unknown>> | undefined {\n if (!schema || typeof schema !== 'object') return undefined;\n\n // Direct shape property (Zod v4)\n const s = schema as Record<string, unknown>;\n if (s.shape && typeof s.shape === 'object') {\n return s.shape as Record<string, ZodType<unknown>>;\n }\n\n return undefined;\n}\n\n/**\n * Get the default value from a schema wrapped in ZodDefault.\n */\nexport function getDefaultValue(schema: unknown): unknown {\n const def = getDef(schema);\n return def?.defaultValue;\n}\n\nconst TRANSPARENT_WRAPPERS = [\n 'optional',\n 'nullable',\n 'default',\n 'readonly',\n 'prefault',\n 'nonoptional',\n 'catch', // transparent for schema structure, but alters error behavior\n];\n\n/**\n * Unwrap transparent wrappers (optional, nullable, default) to get the core schema.\n * Useful when you need to check the underlying type.\n */\nexport function unwrapTransparent(schema: ZodType<unknown>): ZodType<unknown> {\n let current: unknown = schema;\n\n for (let i = 0; i < 10; i++) {\n const kind = getKind(current);\n if (!kind) break;\n\n if (TRANSPARENT_WRAPPERS.includes(kind)) {\n const inner = getInnerType(current);\n if (!inner) break;\n current = inner;\n continue;\n }\n break;\n }\n\n return current as ZodType<unknown>;\n}\n","import { type ZodObject, type ZodSchema, type ZodType, z } from 'zod';\nimport { getDef, getShape, isObjectSchema, unwrapTransparent } from './zod-internals';\n\n/**\n * Parse a dot notation path into segments.\n * @param path - Dot notation path like \"ui.theme\" or \"api.timeout\"\n * @returns Array of path segments\n */\nexport function parsePath(path: string): string[] {\n return path.split('.');\n}\n\n/**\n * Transform dot notation object to nested object structure.\n * Example: {\"ui.theme\": \"dark\", \"config.name\": \"test\"}\n * -> {ui: {theme: \"dark\"}, config: {name: \"test\"}}\n */\nexport function dotNotationToNested(\n dotNotationObject: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [dotPath, value] of Object.entries(dotNotationObject)) {\n const segments = parsePath(dotPath);\n let current: Record<string, unknown> = result;\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n\n if (i === segments.length - 1) {\n // Last segment - set the value\n current[segment] = value;\n } else {\n // Intermediate segment - ensure object exists\n if (!(segment in current) || typeof current[segment] !== 'object') {\n current[segment] = {};\n }\n current = current[segment] as Record<string, unknown>;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Flatten nested object to dot notation.\n * Example: {ui: {theme: \"dark\"}, config: {name: \"test\"}}\n * -> {\"ui.theme\": \"dark\", \"config.name\": \"test\"}\n */\nexport function flattenObject(obj: Record<string, unknown>, prefix = ''): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const newKey = prefix ? `${prefix}.${key}` : key;\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n Object.assign(result, flattenObject(value as Record<string, unknown>, newKey));\n } else {\n result[newKey] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Check if a dot notation path exists in the schema.\n */\nexport function isValidPath(\n schema: ZodObject<Record<string, ZodType>>,\n segments: string[],\n): boolean {\n let currentSchema: ZodType = schema;\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n const shape = getShape(currentSchema);\n\n if (!shape || !(segment in shape)) {\n return false;\n }\n\n if (i < segments.length - 1) {\n // Not the last segment, should be a ZodObject\n const nextSchema = shape[segment];\n\n // Handle wrapped schemas (ZodDefault, ZodOptional, etc.)\n const unwrappedSchema = unwrapTransparent(nextSchema);\n\n if (!isObjectSchema(unwrappedSchema)) {\n return false;\n }\n\n currentSchema = unwrappedSchema;\n }\n }\n\n return true;\n}\n\n/**\n * Get value at a specific path in a nested object.\n */\nexport function getValueAtPath(obj: unknown, segments: string[]): unknown {\n let current = obj;\n for (const segment of segments) {\n if (current == null || typeof current !== 'object' || !(segment in current)) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\n/**\n * Helper function to traverse schema object to find the field schema at a specific path.\n */\nexport function findSchemaAtPath(\n rootSchema: ZodObject<Record<string, ZodType>> | undefined,\n segments: string[],\n): ZodSchema | undefined {\n if (!rootSchema || segments.length === 0) return undefined;\n\n let current: ZodType = rootSchema;\n\n // ZodObject root - start with the shape\n if (segments.length > 0) {\n const rootShape = getShape(current);\n if (!rootShape || !(segments[0] in rootShape)) {\n return undefined;\n }\n current = rootShape[segments[0]];\n\n // Continue with remaining segments starting from index 1\n for (let i = 1; i < segments.length; i++) {\n const segment = segments[i];\n const def = getDef(current);\n if (!def) {\n return undefined;\n }\n\n // Unwrap transparent wrappers (ZodDefault, ZodOptional, ZodNullable, etc.)\n current = unwrapTransparent(current);\n if (!isObjectSchema(current)) {\n return undefined;\n }\n const shape = getShape(current);\n if (!shape) {\n return undefined;\n }\n const nextSchema = shape[segment];\n if (!nextSchema) {\n return undefined;\n }\n current = nextSchema;\n }\n return current as ZodSchema;\n }\n\n return current as ZodSchema;\n}\n\n/**\n * Build a schema that validates only a specific path within a larger schema structure.\n * This allows validation of partial nested objects where only the target field is required.\n *\n * For example, for path \"ui.theme.colors.primary\":\n * - Creates: z.object({ ui: z.object({ theme: z.object({ colors: z.object({ primary: leafSchema }).partial() }).partial() }).partial() }).strict()\n * - This allows recording just { ui: { theme: { colors: { primary: value } } } } without requiring siblings\n *\n * @param rootSchema - The root ZodObject schema\n * @param segments - Path segments (e.g. ['ui', 'theme', 'colors', 'primary'])\n * @returns A schema that validates the specific path with partial validation for siblings\n */\nexport function buildSchemaForPath(\n rootSchema: ZodObject<Record<string, ZodType>>,\n segments: string[],\n): ZodSchema {\n const pathKey = segments.join('.');\n\n // Find the leaf schema for the target field\n const leafSchema = findSchemaAtPath(rootSchema, segments);\n if (!leafSchema) {\n throw new Error(`Cannot find schema for path: ${pathKey}`);\n }\n\n // Build the schema from leaf back to root, making siblings optional at each level\n let currentSchema: ZodSchema = leafSchema;\n\n // Work backwards through the segments\n for (let i = segments.length - 1; i >= 0; i--) {\n const segment = segments[i];\n\n // Create an object schema with just this segment\n const objectSchema = z.object({ [segment]: currentSchema });\n\n // Make it partial (so siblings aren't required) and strict (so unknown keys are rejected)\n currentSchema = objectSchema.partial().strict();\n }\n\n return currentSchema;\n}\n","import { type ZodObject, type ZodType, z } from 'zod';\nimport {\n getKind,\n getInnerType,\n getArrayElement,\n isObjectSchema,\n getDefaultValue,\n} from './zod-internals';\n\n/**\n * Recursively makes all properties of a ZodObject schema optional (deep partial).\n * This is needed because Zod 4 removed the deprecated `.deepPartial()` method.\n *\n * When validating CLI flag overrides, we only want to validate the flags that are\n * provided, not require all nested objects to be fully specified.\n */\nexport function makeDeepPartial(schema: ZodObject<Record<string, ZodType>>): ZodType {\n const shape = schema.shape;\n const newShape: Record<string, ZodType> = {};\n\n for (const [key, value] of Object.entries(shape)) {\n newShape[key] = makeDeepPartialField(value as ZodType);\n }\n\n return z.object(newShape);\n}\n\n/**\n * Apply deep partial semantics to a single field of an object shape.\n */\nfunction makeDeepPartialField(fieldSchema: ZodType): ZodType {\n const kind = getKind(fieldSchema);\n\n // Plain object field - recurse and make optional\n if (isObjectSchema(fieldSchema)) {\n const partialObject = makeDeepPartial(fieldSchema as ZodObject<Record<string, ZodType>>);\n return partialObject.optional();\n }\n\n // Optional wrapper - check if inner type is an object\n if (kind === 'optional') {\n const inner = getInnerType(fieldSchema);\n if (inner && isObjectSchema(inner)) {\n const partialInner = makeDeepPartial(inner as ZodObject<Record<string, ZodType>>);\n return partialInner.optional();\n }\n // Already optional and not an object - preserve as-is\n return fieldSchema;\n }\n\n // Nullable wrapper - check if inner type is an object\n if (kind === 'nullable') {\n const inner = getInnerType(fieldSchema);\n if (inner && isObjectSchema(inner)) {\n const partialInner = makeDeepPartial(inner as ZodObject<Record<string, ZodType>>);\n return partialInner.nullable().optional();\n }\n // Nullable non-object - just make optional\n return fieldSchema.optional();\n }\n\n // Default wrapper - check if inner type is an object\n if (kind === 'default') {\n const inner = getInnerType(fieldSchema);\n const defaultValue = getDefaultValue(fieldSchema);\n\n if (inner && isObjectSchema(inner)) {\n const partialInner = makeDeepPartial(inner as ZodObject<Record<string, ZodType>>);\n // Reapply the default on the deep-partialled object, preserving function references for lazy defaults\n return (partialInner as ZodObject<Record<string, ZodType>>).default(defaultValue as any);\n }\n // Non-object with default - make optional to allow partial validation\n return fieldSchema.optional();\n }\n\n // Array wrapper - deep partial the element type if it's an object\n if (kind === 'array') {\n const element = getArrayElement(fieldSchema);\n if (element && isObjectSchema(element)) {\n const partialElement = makeDeepPartial(element as ZodObject<Record<string, ZodType>>);\n return z.array(partialElement).optional();\n }\n // Array of non-objects - just make optional\n return fieldSchema.optional();\n }\n\n // All other field types - just make optional\n return fieldSchema.optional();\n}\n","import { type ZodObject } from 'zod';\nimport { getGlobalFlagOverrides } from './evals/context/global-flags';\nimport { formatZodErrors, generateFlagExamples } from './cli/utils/format-zod-errors';\nimport { dotNotationToNested, isValidPath, parsePath } from './util/dot-path';\nimport { makeDeepPartial } from './util/deep-partial-schema';\nimport { assertZodV4 } from './util/zod-internals';\n\n/**\n * Validate CLI flag overrides against a schema early in eval execution.\n * Call this at the top of your eval file to fail fast on invalid flags.\n *\n * @param flagSchema - Zod schema to validate CLI flags against\n * @throws Error with helpful message if validation fails\n */\nexport function validateCliFlags(flagSchema: ZodObject<any>): void {\n assertZodV4(flagSchema, 'flagSchema');\n const globalOverrides = getGlobalFlagOverrides();\n\n if (Object.keys(globalOverrides).length === 0) {\n // No CLI flags provided, nothing to validate\n return;\n }\n\n validateFlags(flagSchema, globalOverrides);\n}\n\nfunction validateFlags(flagSchema: ZodObject<any>, globalOverrides: Record<string, any>): void {\n // First pass: check all paths exist in schema\n for (const [dotPath, _value] of Object.entries(globalOverrides)) {\n const segments = parsePath(dotPath);\n if (!isValidPath(flagSchema, segments)) {\n console.error('❌ Invalid CLI flags:');\n console.error(` • flag '${dotPath}': Invalid flag path`);\n console.error('\\n🔧 Fix your CLI flags and try again.\\n');\n process.exit(1);\n }\n }\n\n // Second pass: validate values using nested object approach with deep partial\n // This allows providing only some flags without requiring all nested objects\n const nestedObject = dotNotationToNested(globalOverrides);\n const deepPartialSchema = makeDeepPartial(flagSchema);\n const result = deepPartialSchema.safeParse(nestedObject);\n\n if (!result.success) {\n console.error('❌ Invalid CLI flags:');\n console.error(formatZodErrors(result.error));\n\n const examples = generateFlagExamples(result.error);\n if (examples.length > 0) {\n console.error('\\n💡 Valid examples:');\n examples.forEach((example) => console.error(` ${example}`));\n }\n\n console.error('\\n🔧 Fix your CLI flags and try again.\\n');\n process.exit(1);\n }\n}\n","import { type AttributeValue } from '@opentelemetry/api';\n\nfunction toHomogeneousArray(input: unknown[]): AttributeValue | undefined {\n if (input.length === 0) return undefined;\n\n const converted: (string | number | boolean)[] = [];\n const types = new Set<string>();\n\n for (const item of input) {\n const converted_item = toOtelPrimitive(item);\n if (converted_item !== undefined) {\n converted.push(converted_item);\n types.add(typeof converted_item);\n }\n }\n\n if (converted.length === 0) return undefined;\n\n if (types.size > 1) {\n return converted.map((item) => String(item)) as AttributeValue;\n }\n\n return converted as AttributeValue;\n}\n\nfunction toOtelPrimitive(v: unknown): string | number | boolean | undefined {\n switch (typeof v) {\n case 'string':\n return v;\n case 'number':\n return Number.isFinite(v) ? v : undefined;\n case 'boolean':\n return v;\n case 'bigint':\n if (v >= Number.MIN_SAFE_INTEGER && v <= Number.MAX_SAFE_INTEGER) {\n return Number(v);\n }\n return v.toString();\n case 'function':\n case 'symbol':\n case 'undefined':\n return undefined;\n case 'object':\n if (v === null) return undefined;\n if (v instanceof Date) return v.toISOString();\n if (v instanceof Error) return v.message;\n // fallback: stringify object-ish values\n return safeStringify(v);\n }\n}\n\nfunction safeStringify(obj: unknown): string | undefined {\n try {\n // Convert BigInt -> Number inside objects so JSON.stringify won't throw.\n // Functions/undefined are dropped by JSON rules.\n const s = JSON.stringify(obj, (_k, val) =>\n typeof val === 'bigint' ? Number(val) : val instanceof Date ? val.toISOString() : val,\n );\n // Avoid empty/meaningless \"{}\" for Map/Set—stringify those explicitly\n if (s === '{}') {\n if (obj instanceof Map) {\n return JSON.stringify(Object.fromEntries(obj));\n }\n if (obj instanceof Set) {\n return JSON.stringify(Array.from(obj));\n }\n }\n return s ?? undefined;\n } catch {\n // As a last resort, use toString() if present\n try {\n const t = (obj as any)?.toString?.();\n return typeof t === 'string' ? t : undefined;\n } catch {\n return undefined;\n }\n }\n}\n\nexport function toOtelAttribute(input: unknown): AttributeValue | undefined {\n // primitives fast-path\n switch (typeof input) {\n case 'string':\n return input;\n case 'number':\n return Number.isFinite(input) ? input : undefined;\n case 'boolean':\n return input;\n case 'bigint':\n if (input >= Number.MIN_SAFE_INTEGER && input <= Number.MAX_SAFE_INTEGER) {\n return Number(input);\n }\n return input.toString();\n case 'function':\n case 'symbol':\n case 'undefined':\n return undefined;\n }\n\n // arrays -> homogeneous array of primitives\n if (Array.isArray(input)) {\n return toHomogeneousArray(input);\n }\n\n // date -> ISO string\n if (input instanceof Date) {\n return input.toISOString();\n }\n\n // null / objects -> JSON string\n if (input === null) return undefined;\n return safeStringify(input);\n}\n","/**\n * We need a way to know that we're inside `withSpan`\n * Because we don't own `generateText` and similar functions,\n * we use OTel Baggage to propagate this information. Another\n * consideration might be to use AsyncLocalStorage in Node and\n * some kind of KV in workerd.\n */\nexport const WITHSPAN_BAGGAGE_KEY = '__withspan_gen_ai_call';\nexport const WITHSPAN_REDACTION_POLICY_KEY = '__withspan_redaction_policy';\n","// experiment\nexport const ATTR_EVAL_ID = 'eval.id' as const;\nexport const ATTR_EVAL_NAME = 'eval.name' as const;\nexport const ATTR_EVAL_VERSION = 'eval.version' as const;\nexport const ATTR_EVAL_TYPE = 'eval.type' as const;\nexport const ATTR_EVAL_TAGS = 'eval.tags' as const;\nexport const ATTR_EVAL_BASELINE_ID = 'eval.baseline.id' as const;\nexport const ATTR_EVAL_BASELINE_NAME = 'eval.baseline.name' as const;\nexport const ATTR_EVAL_BASELINE_VERSION = 'eval.baseline.version' as const;\nexport const ATTR_EVAL_METADATA = 'eval.metadata' as const;\n// capability\nexport const ATTR_EVAL_CAPABILITY_NAME = 'eval.capability.name' as const;\nexport const ATTR_EVAL_STEP_NAME = 'eval.step.name' as const;\n// collection\nexport const ATTR_EVAL_COLLECTION_ID = 'eval.collection.id' as const;\nexport const ATTR_EVAL_COLLECTION_SIZE = 'eval.collection.size' as const;\nexport const ATTR_EVAL_COLLECTION_NAME = 'eval.collection.name' as const;\n// config\nexport const ATTR_EVAL_CONFIG_FLAGS = 'eval.config.flags' as const;\n// case\nexport const ATTR_EVAL_CASE_INDEX = 'eval.case.index' as const;\nexport const ATTR_EVAL_CASE_INPUT = 'eval.case.input' as const;\nexport const ATTR_EVAL_CASE_OUTPUT = 'eval.case.output' as const;\nexport const ATTR_EVAL_CASE_EXPECTED = 'eval.case.expected' as const;\nexport const ATTR_EVAL_CASE_SCORES = 'eval.case.scores' as const;\nexport const ATTR_EVAL_CASE_METADATA = 'eval.case.metadata' as const;\n// task\nexport const ATTR_EVAL_TASK_OUTPUT = 'eval.task.output' as const;\nexport const ATTR_EVAL_TASK_NAME = 'eval.task.name' as const;\nexport const ATTR_EVAL_TASK_TYPE = 'eval.task.type' as const;\n// run\nexport const ATTR_EVAL_RUN_ID = 'eval.run.id' as const;\n// score\nexport const ATTR_EVAL_SCORE_NAME = 'eval.score.name' as const;\nexport const ATTR_EVAL_SCORE_VALUE = 'eval.score.value' as const;\nexport const ATTR_EVAL_SCORE_THRESHOLD = 'eval.score.threshold' as const;\nexport const ATTR_EVAL_SCORE_PASSED = 'eval.score.passed' as const;\nexport const ATTR_EVAL_SCORE_IS_BOOLEAN = 'eval.score.is_boolean' as const;\nexport const ATTR_EVAL_SCORE_SCORER = 'eval.score.scorer' as const;\nexport const ATTR_EVAL_SCORE_METADATA = 'eval.score.metadata' as const;\n// user\nexport const ATTR_EVAL_USER_NAME = 'eval.user.name';\nexport const ATTR_EVAL_USER_EMAIL = 'eval.user.email';\n","import {\n ATTR_ERROR_TYPE,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n} from '@opentelemetry/semantic-conventions';\n\nimport {\n ATTR_EVAL_CASE_INDEX,\n ATTR_EVAL_CASE_EXPECTED,\n ATTR_EVAL_CASE_INPUT,\n ATTR_EVAL_CASE_OUTPUT,\n ATTR_EVAL_CASE_METADATA,\n ATTR_EVAL_CASE_SCORES,\n ATTR_EVAL_SCORE_PASSED,\n ATTR_EVAL_SCORE_IS_BOOLEAN,\n ATTR_EVAL_SCORE_VALUE,\n ATTR_EVAL_SCORE_NAME,\n ATTR_EVAL_SCORE_THRESHOLD,\n ATTR_EVAL_SCORE_METADATA,\n ATTR_EVAL_TASK_TYPE,\n ATTR_EVAL_TASK_NAME,\n ATTR_EVAL_TASK_OUTPUT,\n ATTR_EVAL_COLLECTION_NAME,\n ATTR_EVAL_COLLECTION_SIZE,\n ATTR_EVAL_ID,\n ATTR_EVAL_BASELINE_ID,\n ATTR_EVAL_BASELINE_NAME,\n ATTR_EVAL_BASELINE_VERSION,\n ATTR_EVAL_NAME,\n ATTR_EVAL_TAGS,\n ATTR_EVAL_TYPE,\n ATTR_EVAL_COLLECTION_ID,\n ATTR_EVAL_USER_NAME,\n ATTR_EVAL_USER_EMAIL,\n ATTR_EVAL_VERSION,\n ATTR_EVAL_RUN_ID,\n ATTR_EVAL_METADATA,\n ATTR_EVAL_CONFIG_FLAGS,\n ATTR_EVAL_CAPABILITY_NAME,\n ATTR_EVAL_STEP_NAME,\n} from './eval_proposal';\n\nimport {\n ATTR_ERROR_MESSAGE,\n ATTR_GEN_AI_AGENT_DESCRIPTION,\n ATTR_GEN_AI_AGENT_ID,\n ATTR_GEN_AI_AGENT_NAME,\n ATTR_GEN_AI_CONVERSATION_ID,\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OPERATION_NAME,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_OUTPUT_TYPE,\n ATTR_GEN_AI_PROVIDER_NAME,\n ATTR_GEN_AI_REQUEST_CHOICE_COUNT,\n ATTR_GEN_AI_REQUEST_ENCODING_FORMATS,\n ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY,\n ATTR_GEN_AI_REQUEST_MAX_TOKENS,\n ATTR_GEN_AI_REQUEST_MODEL,\n ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY,\n ATTR_GEN_AI_REQUEST_SEED,\n ATTR_GEN_AI_REQUEST_STOP_SEQUENCES,\n ATTR_GEN_AI_REQUEST_TEMPERATURE,\n ATTR_GEN_AI_REQUEST_TOP_K,\n ATTR_GEN_AI_REQUEST_TOP_P,\n ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ATTR_GEN_AI_RESPONSE_ID,\n ATTR_GEN_AI_RESPONSE_MODEL,\n ATTR_GEN_AI_TOOL_CALL_ID,\n ATTR_GEN_AI_TOOL_DESCRIPTION,\n ATTR_GEN_AI_TOOL_NAME,\n ATTR_GEN_AI_TOOL_TYPE,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n GEN_AI_OPERATION_NAME_VALUE_CHAT,\n GEN_AI_OPERATION_NAME_VALUE_CREATE_AGENT,\n GEN_AI_OPERATION_NAME_VALUE_EMBEDDINGS,\n GEN_AI_OPERATION_NAME_VALUE_EXECUTE_TOOL,\n GEN_AI_OPERATION_NAME_VALUE_GENERATE_CONTENT,\n GEN_AI_OPERATION_NAME_VALUE_INVOKE_AGENT,\n GEN_AI_OUTPUT_TYPE_VALUE_IMAGE,\n GEN_AI_OUTPUT_TYPE_VALUE_JSON,\n GEN_AI_OUTPUT_TYPE_VALUE_SPEECH,\n GEN_AI_OUTPUT_TYPE_VALUE_TEXT,\n GEN_AI_PROVIDER_NAME_VALUE_ANTHROPIC,\n GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK,\n GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_INFERENCE,\n GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_OPENAI,\n GEN_AI_PROVIDER_NAME_VALUE_COHERE,\n GEN_AI_PROVIDER_NAME_VALUE_DEEPSEEK,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_VERTEX_AI,\n GEN_AI_PROVIDER_NAME_VALUE_GROQ,\n GEN_AI_PROVIDER_NAME_VALUE_IBM_WATSONX_AI,\n GEN_AI_PROVIDER_NAME_VALUE_MISTRAL_AI,\n GEN_AI_PROVIDER_NAME_VALUE_OPENAI,\n GEN_AI_PROVIDER_NAME_VALUE_PERPLEXITY,\n GEN_AI_PROVIDER_NAME_VALUE_X_AI,\n} from '@opentelemetry/semantic-conventions/incubating';\n\n/**\n * PROPRIETARY ATTRIBUTES (o11y)\n *\n * @see: https://axiom.co/docs/ai-engineering/semantic-conventions\n */\n\nconst ATTR_AXIOM_GEN_AI_SCHEMA_URL = 'axiom.gen_ai.schema_url';\nconst ATTR_AXIOM_GEN_AI_SDK_NAME = 'axiom.gen_ai.sdk.name';\nconst ATTR_AXIOM_GEN_AI_SDK_VERSION = 'axiom.gen_ai.sdk.version';\nconst ATTR_GEN_AI_CAPABILITY_NAME = 'gen_ai.capability.name';\nconst ATTR_GEN_AI_STEP_NAME = 'gen_ai.step.name';\nconst ATTR_GEN_AI_TOOL_ARGUMENTS = 'gen_ai.tool.arguments'; // deprecated by OTel\nconst ATTR_GEN_AI_TOOL_MESSAGE = 'gen_ai.tool.message'; // deprecated by OTel\n\nconst GEN_AI_PROVIDER_NAME_VALUE_ASSEMBLYAI = 'assemblyai';\nconst GEN_AI_PROVIDER_NAME_VALUE_CEREBRAS = 'cerebras';\nconst GEN_AI_PROVIDER_NAME_VALUE_DEEPGRAM = 'deepgram';\nconst GEN_AI_PROVIDER_NAME_VALUE_DEEPINFRA = 'deepinfra';\nconst GEN_AI_PROVIDER_NAME_VALUE_ELEVENLABS = 'elevenlabs';\nconst GEN_AI_PROVIDER_NAME_VALUE_FAL = 'fal';\nconst GEN_AI_PROVIDER_NAME_VALUE_FIREWORKS = 'fireworks';\nconst GEN_AI_PROVIDER_NAME_VALUE_GLADIA = 'gladia';\nconst GEN_AI_PROVIDER_NAME_VALUE_HUME = 'hume';\nconst GEN_AI_PROVIDER_NAME_VALUE_LMNT = 'lmnt';\nconst GEN_AI_PROVIDER_NAME_VALUE_LUMA = 'luma';\nconst GEN_AI_PROVIDER_NAME_VALUE_REPLICATE = 'replicate';\nconst GEN_AI_PROVIDER_NAME_VALUE_REVAI = 'revai';\nconst GEN_AI_PROVIDER_NAME_VALUE_TOGETHERAI = 'togetherai';\nconst GEN_AI_PROVIDER_NAME_VALUE_VERCEL = 'vercel';\n\n/**\n * When adding something new here, please:\n * 1. Make sure it doesn't already exist as part of OTel Semantic Conventions (use that instead)\n * 2. Make sure to use standard naming schema, ie snake_case\n * 3. If a specific feature has an attribute you would like to use, extract it to the shared section\n *\n * Also Experimental Attributes should always be imported here and then used from the CustomAttributes object\n * because they are unstable.\n *\n * @see: https://github.com/open-telemetry/opentelemetry-js/tree/c89cb38d0fec39d54cf3fcb35c429a8129e9c909/semantic-conventions#unstable-semconv\n */\nexport const Attr = {\n __EXPERIMENTAL_Flag: (flagName: string) => `flag.${flagName}`,\n __EXPERIMENTAL_Fact: (factName: string) => `fact.${factName}`,\n Axiom: {\n GenAI: {\n SchemaURL: ATTR_AXIOM_GEN_AI_SCHEMA_URL,\n SDK: {\n Name: ATTR_AXIOM_GEN_AI_SDK_NAME,\n Version: ATTR_AXIOM_GEN_AI_SDK_VERSION,\n },\n },\n },\n GenAI: {\n PromptMetadata: {\n ID: 'axiom.gen_ai.prompt.id',\n Name: 'axiom.gen_ai.prompt.name',\n Slug: 'axiom.gen_ai.prompt.slug',\n Version: 'axiom.gen_ai.prompt.version',\n },\n /**\n * These two are used to identify the span\n */\n Capability: {\n Name: ATTR_GEN_AI_CAPABILITY_NAME,\n },\n Step: {\n Name: ATTR_GEN_AI_STEP_NAME,\n },\n Provider: {\n Name: ATTR_GEN_AI_PROVIDER_NAME,\n Name_Values: {\n Anthropic: GEN_AI_PROVIDER_NAME_VALUE_ANTHROPIC,\n AssemblyAI: GEN_AI_PROVIDER_NAME_VALUE_ASSEMBLYAI,\n AWSBedrock: GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK,\n AzureAIInference: GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_INFERENCE,\n AzureAIOpenAI: GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_OPENAI,\n Cerebras: GEN_AI_PROVIDER_NAME_VALUE_CEREBRAS,\n Cohere: GEN_AI_PROVIDER_NAME_VALUE_COHERE,\n Deepgram: GEN_AI_PROVIDER_NAME_VALUE_DEEPGRAM,\n DeepInfra: GEN_AI_PROVIDER_NAME_VALUE_DEEPINFRA,\n Deepseek: GEN_AI_PROVIDER_NAME_VALUE_DEEPSEEK,\n ElevenLabs: GEN_AI_PROVIDER_NAME_VALUE_ELEVENLABS,\n Fal: GEN_AI_PROVIDER_NAME_VALUE_FAL,\n Fireworks: GEN_AI_PROVIDER_NAME_VALUE_FIREWORKS,\n GCPGemini: GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI,\n GCPGenAI: GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI,\n GCPVertexAI: GEN_AI_PROVIDER_NAME_VALUE_GCP_VERTEX_AI,\n Gladia: GEN_AI_PROVIDER_NAME_VALUE_GLADIA,\n Groq: GEN_AI_PROVIDER_NAME_VALUE_GROQ,\n Hume: GEN_AI_PROVIDER_NAME_VALUE_HUME,\n IBMWatsonxAI: GEN_AI_PROVIDER_NAME_VALUE_IBM_WATSONX_AI,\n Lmnt: GEN_AI_PROVIDER_NAME_VALUE_LMNT,\n Luma: GEN_AI_PROVIDER_NAME_VALUE_LUMA,\n MistralAI: GEN_AI_PROVIDER_NAME_VALUE_MISTRAL_AI,\n OpenAI: GEN_AI_PROVIDER_NAME_VALUE_OPENAI,\n Perplexity: GEN_AI_PROVIDER_NAME_VALUE_PERPLEXITY,\n Replicate: GEN_AI_PROVIDER_NAME_VALUE_REPLICATE,\n RevAI: GEN_AI_PROVIDER_NAME_VALUE_REVAI,\n TogetherAI: GEN_AI_PROVIDER_NAME_VALUE_TOGETHERAI,\n Vercel: GEN_AI_PROVIDER_NAME_VALUE_VERCEL,\n XAI: GEN_AI_PROVIDER_NAME_VALUE_X_AI,\n },\n },\n /**\n * Regular attributes\n */\n Agent: {\n Description: ATTR_GEN_AI_AGENT_DESCRIPTION, // not yet used by axiom-ai\n ID: ATTR_GEN_AI_AGENT_ID, // not yet used by axiom-ai\n Name: ATTR_GEN_AI_AGENT_NAME, // not yet used by axiom-ai\n },\n Conversation: {\n ID: ATTR_GEN_AI_CONVERSATION_ID, // not yet used by axiom-ai, anyway probably needs to be provided by user\n },\n Input: {\n Messages: ATTR_GEN_AI_INPUT_MESSAGES,\n },\n Operation: {\n Name: ATTR_GEN_AI_OPERATION_NAME,\n Name_Values: {\n /**\n * Note that \"text_completion\" is deprecated in favor of \"chat\" for both OpenAI and Anthropic\n */\n Chat: GEN_AI_OPERATION_NAME_VALUE_CHAT,\n CreateAgent: GEN_AI_OPERATION_NAME_VALUE_CREATE_AGENT,\n Embeddings: GEN_AI_OPERATION_NAME_VALUE_EMBEDDINGS,\n ExecuteTool: GEN_AI_OPERATION_NAME_VALUE_EXECUTE_TOOL,\n GenerateContent: GEN_AI_OPERATION_NAME_VALUE_GENERATE_CONTENT,\n InvokeAgent: GEN_AI_OPERATION_NAME_VALUE_INVOKE_AGENT,\n },\n },\n Output: {\n Messages: ATTR_GEN_AI_OUTPUT_MESSAGES,\n Type: ATTR_GEN_AI_OUTPUT_TYPE,\n Type_Values: {\n Text: GEN_AI_OUTPUT_TYPE_VALUE_TEXT,\n Json: GEN_AI_OUTPUT_TYPE_VALUE_JSON,\n Image: GEN_AI_OUTPUT_TYPE_VALUE_IMAGE,\n Speech: GEN_AI_OUTPUT_TYPE_VALUE_SPEECH,\n },\n },\n /**\n * The provider that is hosting the model, eg AWS Bedrock\n * There doesn't seem to be a semconv for this\n */\n Request: {\n ChoiceCount: ATTR_GEN_AI_REQUEST_CHOICE_COUNT, // not yet used by axiom-ai\n EncodingFormats: ATTR_GEN_AI_REQUEST_ENCODING_FORMATS, // not yet used by axiom-ai\n FrequencyPenalty: ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY,\n MaxTokens: ATTR_GEN_AI_REQUEST_MAX_TOKENS,\n /**\n * The model you asked for\n */\n Model: ATTR_GEN_AI_REQUEST_MODEL,\n PresencePenalty: ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY,\n Seed: ATTR_GEN_AI_REQUEST_SEED,\n StopSequences: ATTR_GEN_AI_REQUEST_STOP_SEQUENCES,\n Temperature: ATTR_GEN_AI_REQUEST_TEMPERATURE,\n TopK: ATTR_GEN_AI_REQUEST_TOP_K,\n TopP: ATTR_GEN_AI_REQUEST_TOP_P,\n },\n Response: {\n FinishReasons: ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ID: ATTR_GEN_AI_RESPONSE_ID,\n /**\n * The model that was actually used (might be different bc routing) - only ever get this from the response, otherwise omit\n */\n Model: ATTR_GEN_AI_RESPONSE_MODEL, // somehow not landing on the span for google models? check up on this...\n },\n Tool: {\n CallID: ATTR_GEN_AI_TOOL_CALL_ID,\n Description: ATTR_GEN_AI_TOOL_DESCRIPTION,\n Name: ATTR_GEN_AI_TOOL_NAME,\n Type: ATTR_GEN_AI_TOOL_TYPE,\n /**\n * Note, OTel Semantic Convention suggest only putting tool inputs/outputs on the parent chat span\n * But we at least want to give users THE OPTION to put them on the tool spans themselves as well\n * Because it enables a lot of things with querying\n * @see https://github.com/open-telemetry/semantic-conventions/releases/tag/v1.37.0\n */\n Arguments: ATTR_GEN_AI_TOOL_ARGUMENTS,\n /**\n * Note, OTel Semantic Convention suggest only putting tool inputs/outputs on the parent chat span\n * But we at least want to give users THE OPTION to put them on the tool spans themselves as well\n * Because it enables a lot of things with querying\n * @see https://github.com/open-telemetry/semantic-conventions/releases/tag/v1.37.0\n */\n Message: ATTR_GEN_AI_TOOL_MESSAGE,\n },\n Usage: {\n InputTokens: ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n OutputTokens: ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n },\n },\n Eval: {\n ID: ATTR_EVAL_ID,\n Name: ATTR_EVAL_NAME,\n Version: ATTR_EVAL_VERSION,\n Type: ATTR_EVAL_TYPE,\n Baseline: {\n ID: ATTR_EVAL_BASELINE_ID,\n Name: ATTR_EVAL_BASELINE_NAME,\n Version: ATTR_EVAL_BASELINE_VERSION,\n },\n Capability: {\n Name: ATTR_EVAL_CAPABILITY_NAME,\n },\n Step: {\n Name: ATTR_EVAL_STEP_NAME,\n },\n Tags: ATTR_EVAL_TAGS,\n Metadata: ATTR_EVAL_METADATA,\n Collection: {\n ID: ATTR_EVAL_COLLECTION_ID,\n Name: ATTR_EVAL_COLLECTION_NAME,\n Size: ATTR_EVAL_COLLECTION_SIZE,\n },\n Config: {\n Flags: ATTR_EVAL_CONFIG_FLAGS,\n },\n Run: {\n ID: ATTR_EVAL_RUN_ID,\n },\n Case: {\n Index: ATTR_EVAL_CASE_INDEX,\n Input: ATTR_EVAL_CASE_INPUT,\n Output: ATTR_EVAL_CASE_OUTPUT,\n Expected: ATTR_EVAL_CASE_EXPECTED,\n Scores: ATTR_EVAL_CASE_SCORES,\n Metadata: ATTR_EVAL_CASE_METADATA,\n },\n Task: {\n Output: ATTR_EVAL_TASK_OUTPUT,\n Name: ATTR_EVAL_TASK_NAME,\n Type: ATTR_EVAL_TASK_TYPE,\n },\n Score: {\n Name: ATTR_EVAL_SCORE_NAME,\n Value: ATTR_EVAL_SCORE_VALUE,\n Threshold: ATTR_EVAL_SCORE_THRESHOLD,\n Passed: ATTR_EVAL_SCORE_PASSED,\n IsBoolean: ATTR_EVAL_SCORE_IS_BOOLEAN,\n Metadata: ATTR_EVAL_SCORE_METADATA,\n },\n User: {\n Name: ATTR_EVAL_USER_NAME,\n Email: ATTR_EVAL_USER_EMAIL,\n },\n },\n Error: {\n Type: ATTR_ERROR_TYPE,\n Message: ATTR_ERROR_MESSAGE,\n },\n HTTP: {\n Response: {\n StatusCode: ATTR_HTTP_RESPONSE_STATUS_CODE,\n },\n },\n} as const;\n","export const SCHEMA_VERSION = '0.0.2';\nexport const SCHEMA_BASE_URL = 'https://axiom.co/ai/schemas/';\nexport const SCHEMA_URL = `${SCHEMA_BASE_URL}${SCHEMA_VERSION}`;\n","import { type Span, type SpanOptions, SpanStatusCode, type Tracer } from '@opentelemetry/api';\n\ninterface Callbacks {\n onSuccess?: (span: Span) => void;\n onError?: (error: unknown, span: Span) => void;\n onFinally?: (span: Span) => void;\n /**\n * If true, the operation will call span.end() manually.\n * Used for streaming operations where the span should remain open until stream consumption completes.\n */\n manualEnd?: boolean;\n}\n\nexport const createStartActiveSpan =\n (tracer: Tracer) =>\n async <T>(\n name: string,\n options: SpanOptions | null,\n fn: (span: Span) => Promise<T>,\n callbacks?: Callbacks,\n ): Promise<T> => {\n return tracer.startActiveSpan(name, { ...(options ?? {}) }, async (span) => {\n try {\n const result = await fn(span);\n\n callbacks?.onSuccess?.(span);\n\n return result;\n } catch (error) {\n callbacks?.onError?.(error, span);\n\n if (error instanceof Error) {\n span.recordException(error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error.message,\n });\n }\n\n throw error;\n } finally {\n callbacks?.onFinally?.(span);\n\n // Only auto-end the span if manualEnd is not set\n // For streaming operations, the operation itself will call span.end() when the stream completes\n if (!callbacks?.manualEnd) {\n span.end();\n }\n }\n });\n };\n","{\n \"name\": \"axiom\",\n \"version\": \"0.37.0\",\n \"type\": \"module\",\n \"author\": \"Axiom, Inc.\",\n \"contributors\": [\n \"Islam Shehata <islam@axiom.co>\",\n \"Chris Ehrlich <chris@axiom.co>\",\n \"Gabriel de Andrade <gabriel@axiom.co>\"\n ],\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup && chmod +x dist/bin.js\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\",\n \"lint\": \"eslint './**/*.{js,ts}'\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest --watch\",\n \"publint\": \"npx publint\"\n },\n \"types\": \"./dist/index.d.ts\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"bin\": {\n \"axiom\": \"./dist/bin.js\"\n },\n \"exports\": {\n \"./ai\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./ai/evals\": {\n \"import\": {\n \"types\": \"./dist/evals.d.ts\",\n \"default\": \"./dist/evals.js\"\n },\n \"require\": {\n \"types\": \"./dist/evals.d.cts\",\n \"default\": \"./dist/evals.cjs\"\n }\n },\n \"./ai/config\": {\n \"import\": {\n \"types\": \"./dist/config.d.ts\",\n \"default\": \"./dist/config.js\"\n },\n \"require