@hiper2d/ai-agents 0.1.0
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/LICENSE +21 -0
- package/README.md +85 -0
- package/dist/index.d.mts +1191 -0
- package/dist/index.d.ts +1191 -0
- package/dist/index.js +4496 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4364 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/logger.ts","../src/cache-tier.ts","../src/text-utils.ts","../src/zod-validate.ts","../src/zod-schema-converter.ts","../src/json-response-parser.ts","../src/errors.ts","../src/thinking-utils.ts","../src/catalog.ts","../src/reasoning-effort.ts","../src/pricing/token-usage-utils.ts","../src/pricing/openai-pricing.ts","../src/pricing/deepseek-pricing.ts","../src/pricing/kimi-pricing.ts","../src/pricing/grok-pricing.ts","../src/pricing/anthropic-pricing.ts","../src/pricing/google-pricing.ts","../src/pricing/mistral-pricing.ts","../src/agents/abstract-agent.ts","../src/agents/gpt-5-agent.ts","../src/agents/anthropic-agent.ts","../src/agents/google-agent.ts","../src/agents/mistral-agent.ts","../src/agents/deepseek-v2-agent.ts","../src/agents/grok-agent.ts","../src/agents/kimi-agent.ts","../src/agents/glm-agent.ts","../src/agents/fugu-agent.ts","../src/agents/qwen-agent.ts","../src/agents/minimax-agent.ts","../src/agents/agent-factory.ts"],"sourcesContent":["/**\n * Core types shared by every agent and consumer app.\n */\n\nexport const MESSAGE_ROLE = {\n SYSTEM: \"system\" as const,\n USER: \"user\" as const,\n ASSISTANT: \"assistant\" as const\n} as const;\n\nexport interface AIMessage {\n role: 'system' | 'user' | 'assistant' | 'developer';\n content: string;\n thinking?: string; // Optional thinking content for models that support extended thinking\n anthropicThinkingSignature?: string; // Signature for Anthropic/Claude thinking (required for multi-turn)\n googleThoughtSignature?: string; // Signature for Google/Gemini thinking (required for multi-turn)\n grokEncryptedReasoning?: string; // JSON-serialized xAI encrypted reasoning items (replayed for multi-turn)\n}\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n costUSD: number;\n // Reasoning/thinking tokens, for models that report them. Already counted inside\n // outputTokens (and therefore in costUSD) — this is the breakdown, not an extra charge.\n // Omitted entirely rather than set to 0/undefined: Firestore rejects undefined values,\n // and non-reasoning models have no breakdown to record.\n reasoningTokens?: number;\n // Cached input tokens, for providers that report cache hits. Like reasoningTokens this\n // is a breakdown of inputTokens (already reflected in costUSD), omitted when the\n // provider reported nothing.\n cachedInputTokens?: number;\n // Wall-clock duration of the API call, stamped by AbstractAgent's public ask wrappers.\n // Client-measured — providers don't return processing time — so it includes network,\n // which is what the player actually waits through. Omitted when not measured.\n durationMs?: number;\n}\n\nexport interface ApiKeyMap {\n [id: string]: string\n}\n\nexport interface AgentLoggingConfig {\n enabled: boolean;\n logSystemPrompt: boolean;\n history: {\n enabled: boolean;\n maxCharactersPerMessage: number;\n };\n logCommand: boolean;\n reply: {\n mode: 'raw' | 'body-only';\n maxReplyChars: number;\n maxThinkingChars: number;\n includeReasoning: boolean;\n includeUsage: boolean;\n };\n}\n\nexport interface LoggingConfig {\n agents: AgentLoggingConfig;\n}\n\nexport const DEFAULT_LOGGING_CONFIG: LoggingConfig = {\n agents: {\n enabled: true,\n logSystemPrompt: process.env.LOG_SYSTEM_PROMPT !== 'false',\n history: {\n enabled: process.env.LOG_HISTORY !== 'false',\n maxCharactersPerMessage: parseInt(process.env.LOG_MAX_HISTORY_CHARS || '1000', 10),\n },\n logCommand: true,\n reply: {\n mode: (process.env.LOG_REPLY_MODE === 'raw' ? 'raw' : 'body-only') as 'raw' | 'body-only',\n maxReplyChars: parseInt(process.env.LOG_MAX_REPLY_CHARS || '5000', 10),\n maxThinkingChars: parseInt(process.env.LOG_MAX_THINKING_CHARS || '2000', 10),\n includeReasoning: process.env.LOG_INCLUDE_REASONING !== 'false',\n includeUsage: process.env.LOG_INCLUDE_USAGE !== 'false',\n },\n },\n};\n\nexport class BotResponseError extends Error {\n public details: string;\n public context: Record<string, any>;\n public recoverable: boolean;\n /**\n * Model-facing explanation of the rejection, set where the failure is detected and carried\n * through to the consumer's error surface. Used to enrich a user-triggered retry prompt.\n */\n public explanation?: string;\n\n constructor(\n message: string,\n details: string = '',\n context: Record<string, any> = {},\n recoverable: boolean = true,\n explanation?: string\n ) {\n super(message);\n this.name = 'BotResponseError';\n this.details = details;\n this.context = context;\n this.recoverable = recoverable;\n this.explanation = explanation;\n }\n}\n","import { AgentLoggingConfig, AIMessage, TokenUsage } from './types';\n\n/**\n * Injectable logging seam. The library logs agent activity through this interface;\n * consumers with a real logging pipeline (BetterStack, Datadog, …) plug it in via\n * `setLlmLogger` once at startup. The default implementation logs to the console.\n */\nexport interface AgentActivityData {\n gameId?: string;\n userId?: string;\n systemPrompt?: string;\n history?: AIMessage[];\n command?: string;\n reply?: any;\n thinking?: string;\n usage?: TokenUsage;\n}\n\nexport interface LlmLogger {\n debug(message: string, args?: any): void;\n info(message: string, args?: any): void;\n warn(message: string, args?: any): void;\n error(message: string, args?: any): void;\n agentActivity(\n agentName: string,\n model: string,\n activity: string,\n data: AgentActivityData,\n customConfig?: AgentLoggingConfig\n ): void;\n}\n\nconst consoleLogger: LlmLogger = {\n debug: (message, args) => console.debug(message, args ?? ''),\n info: (message, args) => console.info(message, args ?? ''),\n warn: (message, args) => console.warn(message, args ?? ''),\n error: (message, args) => console.error(message, args ?? ''),\n agentActivity: (agentName, model, activity) => {\n console.info(`Agent ${activity}: ${agentName} (${model})`);\n },\n};\n\nlet current: LlmLogger = consoleLogger;\n\n/** Replace the library's logger. Call once at app startup, before agents are created. */\nexport function setLlmLogger(replacement: LlmLogger): void {\n current = replacement;\n}\n\n/** Stable facade the library logs through; delegates to whatever setLlmLogger installed. */\nexport const logger: LlmLogger = {\n debug: (message, args) => current.debug(message, args),\n info: (message, args) => current.info(message, args),\n warn: (message, args) => current.warn(message, args),\n error: (message, args) => current.error(message, args),\n agentActivity: (agentName, model, activity, data, customConfig) =>\n current.agentActivity(agentName, model, activity, data, customConfig),\n};\n","/**\n * Sentinel that splits a system prompt into cache tiers: [shared static tier, per-agent tier].\n * AbstractAgent splits the instruction on it; providers with explicit cache breakpoints\n * (Anthropic) place one per part, everyone else relies on implicit prefix caching over the\n * joined, marker-free instruction. Consumers embed it between the stable and variable parts\n * of their system prompts.\n */\nexport const CACHE_TIER_MARKER = '\\n<<<CACHE_TIER_BREAK>>>\\n';\n","/** Strips a wrapping markdown code fence (```json … ``` or ``` … ```) from a model response. */\nexport function cleanResponse(response: string): string {\n let cleanResponse = response.trim();\n if (cleanResponse.startsWith('```json')) {\n cleanResponse = cleanResponse.slice(7);\n } else if (cleanResponse.startsWith('```')) {\n cleanResponse = cleanResponse.slice(3);\n }\n\n if (cleanResponse.endsWith('```')) {\n cleanResponse = cleanResponse.slice(0, -3);\n }\n\n return cleanResponse.trim();\n}\n\n/**\n * Stable non-cryptographic hex hash (FNV-1a, 64-bit as two 32-bit lanes).\n * For derived identifiers — provider cache keys, conversation routing ids —\n * where the only requirement is determinism. Pure JS on purpose: node:crypto\n * would drag a node builtin into browser bundles of this library (the werewolf\n * design kit bundles the catalog, and esbuild must resolve every import in the\n * graph even for code that later tree-shakes away).\n */\nexport function stableHashHex(input: string): string {\n let h1 = 0x811c9dc5, h2 = 0xcbf29ce4;\n for (let i = 0; i < input.length; i++) {\n const c = input.charCodeAt(i);\n h1 = Math.imul(h1 ^ c, 0x01000193) >>> 0;\n h2 = Math.imul(h2 ^ c, 0x01000197) >>> 0;\n }\n return h1.toString(16).padStart(8, '0') + h2.toString(16).padStart(8, '0');\n}\n","import { z } from 'zod';\n\n/**\n * Validates and parses a response using a Zod schema\n * @param schema - The Zod schema to validate against\n * @param data - The data to validate\n * @returns Parsed and validated data\n * @throws ZodError if validation fails\n */\nexport function validateResponse<T>(schema: z.ZodSchema<T>, data: unknown): T {\n return schema.parse(data);\n}\n\n/**\n * Safely validates a response, returning validation result\n * @param schema - The Zod schema to validate against\n * @param data - The data to validate\n * @returns Success/error result object\n */\nexport function safeValidateResponse<T>(schema: z.ZodSchema<T>, data: unknown): z.SafeParseReturnType<unknown, T> {\n return schema.safeParse(data);\n}\n","import { z } from 'zod';\n\nexport type ProviderType = 'openai' | 'anthropic' | 'google' | 'mistral' | 'deepseek' | 'grok' | 'kimi';\n\nexport interface JsonSchemaOptions {\n strict?: boolean;\n includeDescription?: boolean;\n additionalProperties?: boolean;\n}\n\nexport interface ProviderSchema {\n type: 'json_schema' | 'prompt_description' | 'google_schema';\n content: any;\n}\n\n/**\n * Universal schema converter that transforms Zod schemas to provider-specific formats\n */\nexport class ZodSchemaConverter {\n /**\n * Convert Zod schema to OpenAI-compatible JSON Schema\n */\n static toOpenAIJsonSchema(zodSchema: z.ZodSchema, schemaName: string): any {\n const baseSchema = this.zodToJsonSchema(zodSchema, { strict: true, includeDescription: true });\n return {\n name: schemaName,\n schema: baseSchema,\n strict: true\n };\n }\n\n /**\n * Convert Zod schema to Google Gemini responseSchema format\n * This follows the official Gemini structured output format\n */\n static toGoogleSchema(zodSchema: z.ZodSchema): any {\n return this.convertZodToGoogleType(zodSchema, true);\n }\n\n /**\n * Internal method to convert Zod types to Google schema format\n */\n private static convertZodToGoogleType(zodType: z.ZodSchema, includeDescriptions: boolean = false): any {\n // Handle ZodString\n if (zodType instanceof z.ZodString) {\n const schema: any = { type: \"string\" };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n \n // Handle ZodNumber\n if (zodType instanceof z.ZodNumber) {\n const schema: any = { type: \"number\" };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n \n // Handle ZodBoolean\n if (zodType instanceof z.ZodBoolean) {\n const schema: any = { type: \"boolean\" };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n \n // Handle ZodArray\n if (zodType instanceof z.ZodArray) {\n const schema: any = {\n type: \"array\",\n items: this.convertZodToGoogleType(zodType.element, includeDescriptions)\n };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n \n // Handle ZodObject\n if (zodType instanceof z.ZodObject) {\n const properties: { [key: string]: any } = {};\n const required: string[] = [];\n const propertyOrdering: string[] = [];\n \n const shape = zodType.shape;\n for (const [key, value] of Object.entries(shape)) {\n const zodValue = value as z.ZodSchema;\n properties[key] = this.convertZodToGoogleType(zodValue, includeDescriptions);\n propertyOrdering.push(key);\n \n // Check if field is required (not optional)\n if (!zodValue.isOptional()) {\n required.push(key);\n }\n }\n \n const schema: any = {\n type: \"object\",\n properties,\n propertyOrdering,\n additionalProperties: false\n };\n \n // Add required fields if any exist\n if (required.length > 0) {\n schema.required = required;\n }\n \n // Add description if provided\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n \n return schema;\n }\n \n // Handle ZodOptional\n if (zodType instanceof z.ZodOptional) {\n const innerSchema = this.convertZodToGoogleType(zodType._def.innerType, includeDescriptions);\n // Preserve description from the optional wrapper if it exists\n if (includeDescriptions && zodType.description) {\n innerSchema.description = zodType.description;\n }\n return innerSchema;\n }\n \n // Handle ZodNullable\n if (zodType instanceof z.ZodNullable) {\n const innerSchema = this.convertZodToGoogleType(zodType._def.innerType, includeDescriptions);\n innerSchema.nullable = true;\n return innerSchema;\n }\n \n // Handle ZodEnum\n if (zodType instanceof z.ZodEnum) {\n const schema: any = {\n type: \"string\",\n enum: zodType.options\n };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n \n // Handle ZodLiteral\n if (zodType instanceof z.ZodLiteral) {\n const value = zodType.value;\n const schema: any = {\n type: typeof value,\n const: value\n };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n \n // Handle ZodUnion (for simple unions)\n if (zodType instanceof z.ZodUnion) {\n const options = zodType._def.options;\n if (options.length > 0) {\n const schema: any = {\n oneOf: options.map((option: z.ZodSchema) => this.convertZodToGoogleType(option, includeDescriptions))\n };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n }\n \n // Fallback for other types\n console.warn(`Unsupported Zod type for Google schema: ${zodType.constructor.name}. Falling back to STRING.`);\n const schema: any = { type: \"string\" };\n if (includeDescriptions && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n\n /**\n * Convert Zod schema to standard JSON Schema format\n * Public method for external use (e.g., Grok structured outputs)\n */\n static toJsonSchema(zodSchema: z.ZodSchema, options: JsonSchemaOptions = {}): any {\n return this.zodToJsonSchema(zodSchema, options);\n }\n\n /**\n * Convert Zod schema to Mistral/DeepSeek JSON Schema format\n */\n static toMistralSchema(zodSchema: z.ZodSchema): any {\n return this.zodToJsonSchema(zodSchema, { \n strict: true,\n additionalProperties: false \n });\n }\n\n /**\n * Convert Zod schema to human-readable prompt description for Anthropic\n */\n static toPromptDescription(zodSchema: z.ZodSchema): string {\n const jsonSchema = this.zodToJsonSchema(zodSchema, { includeDescription: true });\n const description = this.buildSchemaDescription(jsonSchema, 0);\n\n return `Your response must be a valid JSON object matching this exact structure:\n\n${description}\n\nCRITICAL REQUIREMENTS:\n- Your response must be valid JSON\n- Include all required fields\n- Follow the exact data types specified\n- Do not include any additional fields not specified in the schema\n- IMPORTANT: Fields marked as \"string\" must be plain text strings, NOT nested objects or arrays. Put all your content into a single string value.`;\n }\n\n /**\n * Get provider-specific schema format\n */\n static forProvider(zodSchema: z.ZodSchema, provider: ProviderType, schemaName: string = 'response_schema'): ProviderSchema {\n switch (provider) {\n case 'openai':\n return {\n type: 'json_schema',\n content: this.toOpenAIJsonSchema(zodSchema, schemaName)\n };\n \n case 'google':\n return {\n type: 'google_schema',\n content: this.toGoogleSchema(zodSchema)\n };\n \n case 'mistral':\n case 'deepseek':\n return {\n type: 'json_schema',\n content: this.toMistralSchema(zodSchema)\n };\n \n case 'anthropic':\n return {\n type: 'prompt_description',\n content: this.toPromptDescription(zodSchema)\n };\n \n case 'grok':\n case 'kimi':\n // These are OpenAI-compatible but may need looser validation\n return {\n type: 'json_schema',\n content: this.zodToJsonSchema(zodSchema, { strict: false })\n };\n \n default:\n throw new Error(`Unsupported provider: ${provider}`);\n }\n }\n\n /**\n * Core Zod to JSON Schema conversion\n */\n private static zodToJsonSchema(zodSchema: z.ZodSchema, options: JsonSchemaOptions = {}): any {\n const { strict = true, includeDescription = false, additionalProperties } = options;\n \n const converted = this.convertZodType(zodSchema, includeDescription);\n \n if (strict && converted.type === 'object') {\n return this.makeSchemaStrict(converted, additionalProperties);\n }\n \n return converted;\n }\n\n /**\n * Convert individual Zod types to JSON Schema format\n */\n private static convertZodType(zodType: z.ZodSchema, includeDescription: boolean = false): any {\n // Handle ZodString\n if (zodType instanceof z.ZodString) {\n const schema: any = { type: \"string\" };\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n\n // Handle ZodNumber\n if (zodType instanceof z.ZodNumber) {\n const schema: any = { type: \"number\" };\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n\n // Handle ZodBoolean\n if (zodType instanceof z.ZodBoolean) {\n const schema: any = { type: \"boolean\" };\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n\n // Handle ZodArray\n if (zodType instanceof z.ZodArray) {\n const schema: any = {\n type: \"array\",\n items: this.convertZodType(zodType.element, includeDescription)\n };\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n \n // Add array constraints if present\n if (zodType._def.minLength !== null) {\n schema.minItems = zodType._def.minLength.value;\n }\n if (zodType._def.maxLength !== null) {\n schema.maxItems = zodType._def.maxLength.value;\n }\n \n return schema;\n }\n\n // Handle ZodObject\n if (zodType instanceof z.ZodObject) {\n const properties: any = {};\n const required: string[] = [];\n const shape = zodType.shape;\n\n for (const [key, value] of Object.entries(shape)) {\n const zodValue = value as z.ZodSchema;\n properties[key] = this.convertZodType(zodValue, includeDescription);\n \n // Check if field is required (not optional)\n if (!zodValue.isOptional()) {\n required.push(key);\n }\n }\n\n const schema: any = {\n type: \"object\",\n properties,\n required\n };\n\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n\n return schema;\n }\n\n // Handle ZodOptional\n if (zodType instanceof z.ZodOptional) {\n const innerSchema = this.convertZodType(zodType._def.innerType, includeDescription);\n // Preserve description from the optional wrapper if it exists\n if (includeDescription && zodType.description) {\n innerSchema.description = zodType.description;\n }\n return innerSchema;\n }\n\n // Handle ZodNullable\n if (zodType instanceof z.ZodNullable) {\n const innerSchema = this.convertZodType(zodType._def.innerType, includeDescription);\n return {\n ...innerSchema,\n nullable: true\n };\n }\n\n // Handle ZodEnum\n if (zodType instanceof z.ZodEnum) {\n const schema: any = {\n type: \"string\",\n enum: zodType.options\n };\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n\n // Handle ZodLiteral\n if (zodType instanceof z.ZodLiteral) {\n const value = zodType.value;\n const schema: any = {\n type: typeof value,\n const: value\n };\n if (includeDescription && zodType.description) {\n schema.description = zodType.description;\n }\n return schema;\n }\n\n // Handle ZodUnion (for simple unions)\n if (zodType instanceof z.ZodUnion) {\n const options = zodType._def.options;\n return {\n oneOf: options.map((option: z.ZodSchema) => this.convertZodType(option, includeDescription))\n };\n }\n\n // Fallback for other types\n console.warn(`Unsupported Zod type: ${zodType.constructor.name}. Falling back to string.`);\n return { type: \"string\" };\n }\n\n /**\n * Recursively add additionalProperties: false to all object types for strict validation\n */\n private static makeSchemaStrict(schema: any, additionalProperties: boolean = false): any {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n // Add additionalProperties: false for object types\n if (result.type === 'object') {\n result.additionalProperties = additionalProperties;\n }\n\n // Recursively process properties\n if (result.properties) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, prop]: [string, any]) => [\n key,\n this.makeSchemaStrict(prop, additionalProperties)\n ])\n );\n }\n\n // Recursively process array items\n if (result.items) {\n result.items = this.makeSchemaStrict(result.items, additionalProperties);\n }\n\n // Recursively process oneOf, anyOf, allOf\n if (result.oneOf) {\n result.oneOf = result.oneOf.map((subSchema: any) => this.makeSchemaStrict(subSchema, additionalProperties));\n }\n if (result.anyOf) {\n result.anyOf = result.anyOf.map((subSchema: any) => this.makeSchemaStrict(subSchema, additionalProperties));\n }\n if (result.allOf) {\n result.allOf = result.allOf.map((subSchema: any) => this.makeSchemaStrict(subSchema, additionalProperties));\n }\n\n return result;\n }\n\n /**\n * Build human-readable schema description for prompt-based providers\n */\n private static buildSchemaDescription(schema: any, depth: number = 0): string {\n const indent = ' '.repeat(depth);\n \n if (!schema || typeof schema !== 'object') {\n return 'any';\n }\n \n if (schema.type === 'object') {\n let result = `${indent}{\\n`;\n \n const properties = schema.properties || {};\n const required = schema.required || [];\n \n const entries = Object.entries(properties);\n for (let i = 0; i < entries.length; i++) {\n const [key, prop] = entries[i] as [string, any];\n const isRequired = required.includes(key);\n const isLast = i === entries.length - 1;\n \n const typeDesc = this.getTypeDescription(prop as any, depth + 1);\n const requiredMark = isRequired ? ' (required)' : ' (optional)';\n const description = prop.description ? ` // ${prop.description}` : '';\n \n // For nested objects, format them inline\n if (prop.type === 'object') {\n result += `${indent} \"${key}\": ${typeDesc}${requiredMark}${description}`;\n } else {\n result += `${indent} \"${key}\": ${typeDesc}${requiredMark}${description}`;\n }\n \n if (!isLast) result += ',';\n result += '\\n';\n }\n \n result += `${indent}}`;\n return result;\n }\n \n return this.getTypeDescription(schema, depth);\n }\n\n /**\n * Get type description for schema properties\n */\n private static getTypeDescription(schema: any, depth: number): string {\n if (schema.type === 'string') {\n if (schema.enum) {\n return `\"${schema.enum.join('\" | \"')}\"`;\n }\n return 'string';\n }\n \n if (schema.type === 'number') {\n return 'number';\n }\n \n if (schema.type === 'boolean') {\n return 'boolean';\n }\n \n if (schema.type === 'array') {\n const itemType = this.getTypeDescription(schema.items, depth);\n return `${itemType}[]`;\n }\n \n if (schema.type === 'object') {\n // For inline nested objects, build without indentation prefix\n return this.buildInlineObjectDescription(schema, depth);\n }\n \n if (schema.oneOf) {\n return schema.oneOf.map((s: any) => this.getTypeDescription(s, depth)).join(' | ');\n }\n \n return schema?.type || 'any';\n }\n\n /**\n * Build inline object description without leading indentation\n */\n private static buildInlineObjectDescription(schema: any, depth: number): string {\n if (!schema || typeof schema !== 'object' || schema.type !== 'object') {\n return 'any';\n }\n \n let result = '{\\n';\n \n const properties = schema.properties || {};\n const required = schema.required || [];\n const indent = ' '.repeat(depth + 1);\n \n const entries = Object.entries(properties);\n for (let i = 0; i < entries.length; i++) {\n const [key, prop] = entries[i] as [string, any];\n const isRequired = required.includes(key);\n const isLast = i === entries.length - 1;\n \n const typeDesc = this.getTypeDescription(prop as any, depth + 1);\n const requiredMark = isRequired ? ' (required)' : ' (optional)';\n const description = prop.description ? ` // ${prop.description}` : '';\n \n result += `${indent}\\\"${key}\\\": ${typeDesc}${requiredMark}${description}`;\n \n if (!isLast) result += ',';\n result += '\\n';\n }\n \n result += `${' '.repeat(depth)}}`;\n return result;\n }\n}\n\n/**\n * Helper function to generate schema instructions for any provider\n */\nexport function generateSchemaInstructions(zodSchema: z.ZodSchema, provider: ProviderType, schemaName: string = 'response'): string {\n const providerSchema = ZodSchemaConverter.forProvider(zodSchema, provider, schemaName);\n \n if (providerSchema.type === 'prompt_description') {\n return providerSchema.content;\n }\n \n // For JSON schema providers, generate basic instructions\n return `Your response must be a valid JSON object matching the provided schema. Ensure all required fields are included and data types are correct.`;\n}\n\n/**\n * Validate that a provider supports native JSON Schema\n */\nexport function supportsNativeJsonSchema(provider: ProviderType): boolean {\n return ['openai', 'google', 'mistral', 'deepseek'].includes(provider);\n}\n\n/**\n * Check if a provider needs prompt-based schema descriptions\n */\nexport function needsPromptBasedSchema(provider: ProviderType): boolean {\n return provider === 'anthropic';\n}","import { z } from 'zod';\nimport { cleanResponse } from './text-utils';\nimport { safeValidateResponse } from './zod-validate';\n\n/**\n * Extract the first balanced JSON object embedded in `text`.\n * String- and escape-aware, so braces inside string values don't break the scan.\n * If the first candidate fails to parse, scanning continues from the next '{'.\n * Returns null when no parseable object is found.\n */\nexport function extractFirstJsonObject(text: string): unknown | null {\n let searchFrom = 0;\n while (true) {\n const start = text.indexOf('{', searchFrom);\n if (start < 0) return null;\n\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) {\n try {\n return JSON.parse(text.slice(start, i + 1));\n } catch {\n break; // unbalanced-looking but unparseable — try the next '{'\n }\n }\n }\n }\n searchFrom = start + 1;\n }\n}\n\n/**\n * Models sometimes return `{ reply: { ... } }` when the schema expects\n * `{ reply: \"...\" }` (seen with Mistral on prompts with structured sections).\n * Flatten the nested object into a string so validation can succeed.\n */\nfunction normalizeNestedReply(value: unknown, log: (message: string) => void): unknown {\n if (value && typeof value === 'object' && 'reply' in value) {\n const reply = (value as Record<string, unknown>).reply;\n if (reply && typeof reply === 'object') {\n log('Converting nested reply object to string');\n return { ...(value as Record<string, unknown>), reply: JSON.stringify(reply, null, 2) };\n }\n }\n return value;\n}\n\n/**\n * Lenient parse + Zod validation of an LLM text reply, shared by all agents.\n *\n * Order of attempts:\n * 1. Strict JSON parse of the fence-stripped reply (plus a quote-unwrapped\n * variant for Gemini's quoted-JSON-string quirk).\n * 2. Extraction of the first balanced JSON object embedded in prose\n * (rescues \"Sure, here is my answer: {...}\" replies).\n * 3. Re-bracing replies that look like an object body missing its outer braces\n * (rescues MiniMax-M3's `\"who\": \"...\", \"why\": \"...\"` replies).\n * 4. Wrapping raw prose as `{ reply: ... }` for BotAnswer-shaped schemas\n * (rescues bots that \"speak in character\" instead of returning JSON).\n *\n * Throws with the same message prefixes the agents have always used\n * (\"Failed to parse JSON response:\", \"Response validation failed:\") so log\n * queries and error handling stay stable.\n */\nexport function parseAndValidateLlmJson<T>(\n rawReply: string,\n zodSchema: z.ZodSchema<T>,\n log: (message: string) => void = () => {}\n): T {\n const cleaned = cleanResponse(rawReply);\n\n const candidates: string[] = [cleaned];\n // Gemini sometimes returns the JSON string wrapped in quotes\n if (cleaned.startsWith('\"') && cleaned.endsWith('\"')) {\n candidates.push(cleaned.slice(1, -1).replace(/\\\\\"/g, '\"'));\n }\n\n let parseError: unknown = null;\n let zodError: z.ZodError | null = null;\n\n const tryValidate = (value: unknown): { data: T } | null => {\n const result = safeValidateResponse(zodSchema, normalizeNestedReply(value, log));\n if (result.success) return { data: result.data };\n zodError = zodError ?? result.error;\n return null;\n };\n\n // 1. Strict parse\n for (const candidate of candidates) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(candidate);\n } catch (error) {\n parseError = parseError ?? error;\n continue;\n }\n const validated = tryValidate(parsed);\n if (validated) return validated.data;\n }\n\n // 2. First balanced JSON object embedded in prose\n for (const candidate of candidates) {\n const extracted = extractFirstJsonObject(candidate);\n if (extracted === null) continue;\n const validated = tryValidate(extracted);\n if (validated) {\n log(`Recovered JSON embedded in prose response (${candidate.length} chars)`);\n return validated.data;\n }\n }\n\n // 3. Object body missing its outer braces: `\"who\": ...` → `{\"who\": ...}`.\n // Also try adding only the opening brace, for replies that kept the closing one.\n for (const candidate of candidates) {\n if (!candidate.startsWith('\"')) continue;\n for (const rebraced of [`{${candidate}}`, `{${candidate}`]) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(rebraced);\n } catch {\n continue;\n }\n const validated = tryValidate(parsed);\n if (validated) {\n log(`Recovered JSON missing outer braces (${candidate.length} chars)`);\n return validated.data;\n }\n }\n }\n\n // 4. Last resort: accept prose for BotAnswer-shaped schemas\n const wrapped = safeValidateResponse(zodSchema, { reply: cleaned });\n if (wrapped.success) {\n log(`Wrapped prose response as reply (${cleaned.length} chars)`);\n return wrapped.data;\n }\n\n if (zodError !== null) {\n log(`Zod validation failed: ${JSON.stringify((zodError as z.ZodError).errors)}`);\n throw new Error(`Response validation failed: ${(zodError as z.ZodError).message}`);\n }\n throw new Error(`Failed to parse JSON response: ${parseError}. First 200 chars: ${cleaned.slice(0, 200)}`);\n}\n","/**\n * Custom error classes for AI agent interactions\n */\n\nexport abstract class ModelError extends Error {\n public modelType: string;\n\n constructor(message: string, modelType: string) {\n super(message);\n this.modelType = modelType;\n }\n}\n\nexport class ModelOverloadError extends ModelError {\n public retryable: boolean;\n\n constructor(\n message: string,\n modelType: string,\n retryable: boolean = true\n ) {\n super(message, modelType);\n this.name = 'ModelOverloadError';\n this.retryable = retryable;\n }\n}\n\nexport class ModelRateLimitError extends ModelError {\n public retryAfter?: number; // seconds to wait before retrying\n\n constructor(\n message: string,\n modelType: string,\n retryAfter?: number\n ) {\n super(message, modelType);\n this.name = 'ModelRateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\nexport class ModelUnavailableError extends ModelError {\n public reason: string;\n\n constructor(\n message: string,\n modelType: string,\n reason: string = 'unknown'\n ) {\n super(message, modelType);\n this.name = 'ModelUnavailableError';\n this.reason = reason;\n }\n}\n\nexport class ModelAuthenticationError extends ModelError {\n constructor(\n message: string,\n modelType: string\n ) {\n super(message, modelType);\n this.name = 'ModelAuthenticationError';\n }\n}\n\nexport class ModelQuotaExceededError extends ModelError {\n constructor(\n message: string,\n modelType: string\n ) {\n super(message, modelType);\n this.name = 'ModelQuotaExceededError';\n }\n}\n\n/**\n * The model declined to answer: Anthropic returns `stop_reason: \"refusal\"` with no content\n * blocks when its safety layer rejects the request as a whole. Not retryable as-is — the\n * same prompt will refuse again — the caller has to change the prompt or the model.\n * Observed 2026-08-30 on Claude Fable 5: a persona system prompt plus a narrated multi-turn\n * history that ends by asking the character what it does refuses, while either half alone\n * answers; Sonnet 5 and Opus 4.8 answer the same requests.\n */\nexport class ModelRefusalError extends ModelError {\n constructor(modelType: string, message: string = `${modelType} refused to answer (stop_reason: refusal)`) {\n super(message, modelType);\n this.name = 'ModelRefusalError';\n }\n}\n","/**\n * Defense against chain-of-thought leaking into visible chat messages.\n *\n * The OpenAI-compatible reasoning providers (DeepSeek, GLM, Kimi, Qwen,\n * MiniMax, Fugu) are all documented to return thinking in a separate field\n * (`reasoning_content` / `reasoning_details`), but models occasionally\n * misbehave and inline a `<think>…</think>` block into `message.content`\n * instead — observed live with qwen-plus (2026-08), and MiniMax documents it\n * as the default without `reasoning_split`. If that text reaches the lenient\n * JSON parser, its wrap-as-reply fallback can surface the ENTIRE chain of\n * thought — secret role included — as the bot's visible message.\n *\n * Every agent that reads `choices[0].message.content` must pass it through\n * here before parsing, and merge the returned `thinking` into its thinking\n * output so nothing is silently dropped.\n */\nexport function stripInlineThinking(raw: string): { text: string; thinking: string } {\n let thinking = \"\";\n let text = raw.replace(/<think>([\\s\\S]*?)<\\/think>/g, (_, inner: string) => {\n thinking += (thinking ? \"\\n\" : \"\") + inner.trim();\n return \"\";\n });\n\n // Orphan </think>: the opening tag (and usually most of the reasoning)\n // went to the provider's separate reasoning stream, but the tail — from\n // mid-thought up to the closing tag — bled into content. Everything before\n // the first orphan </think> is thinking; the reply follows it.\n const closeIdx = text.indexOf(\"</think>\");\n if (closeIdx !== -1) {\n const before = text.slice(0, closeIdx).trim();\n if (before) thinking += (thinking ? \"\\n\" : \"\") + before;\n text = text.slice(closeIdx + \"</think>\".length);\n }\n\n // Unterminated <think>: keep anything before it, and salvage a JSON object\n // that follows it (the model \"recovered\" mid-stream) — everything between\n // is thinking.\n const openIdx = text.indexOf(\"<think>\");\n if (openIdx !== -1) {\n const after = text.slice(openIdx);\n const jsonStart = after.indexOf(\"{\");\n thinking += (thinking ? \"\\n\" : \"\") + (jsonStart === -1 ? after : after.slice(0, jsonStart)).replace(\"<think>\", \"\").trim();\n text = text.slice(0, openIdx) + (jsonStart === -1 ? \"\" : after.slice(jsonStart));\n }\n\n return { text: text.trim(), thinking };\n}\n\n/** Joins provider-reported reasoning with any inline thinking salvaged from content. */\nexport function mergeThinking(...parts: Array<string | undefined | null>): string {\n return parts.filter(Boolean).join(\"\\n\");\n}\n","/**\n * Model catalog and pricing.\n *\n * This is the library's single source of truth for how to talk to each supported model —\n * API name, key name, thinking dialect, per-model tuning defaults (temperature, reasoning\n * effort, thinking budgets, output ceilings) — and what each model costs. Tuning values are\n * operational defaults discovered against the live APIs; consumers can adjust them per model\n * via `createCatalog(overrides)`, but anything that would ever be fixed for *correctness*\n * (a model rejecting a parameter, an effort level eating the output budget) belongs here,\n * so every consumer inherits the fix with a version bump.\n *\n * App-level policy — tier limits, deprecated-id migration, markup — deliberately lives in\n * the consumer, keyed by the same stable model ids.\n */\n\nexport const API_KEY_CONSTANTS = {\n OPENAI: 'OPENAI_API_KEY',\n ANTHROPIC: 'ANTHROPIC_API_KEY',\n GOOGLE: 'GOOGLE_API_KEY',\n MISTRAL: 'MISTRAL_API_KEY',\n DEEPSEEK: 'DEEPSEEK_API_KEY',\n GROK: 'GROK_API_KEY',\n MOONSHOT: 'MOONSHOT_API_KEY',\n Z_AI: 'Z_AI_API_KEY',\n FUGU: 'FUGU_API_KEY',\n QWEN: 'QWEN_API_KEY',\n MINIMAX: 'MINIMAX_API_KEY'\n} as const;\n\nexport const SupportedAiKeyNames: Record<string, string> = {\n [API_KEY_CONSTANTS.OPENAI]: 'OpenAI',\n [API_KEY_CONSTANTS.ANTHROPIC]: 'Anthropic',\n [API_KEY_CONSTANTS.GOOGLE]: 'Google',\n [API_KEY_CONSTANTS.MISTRAL]: 'Mistral',\n [API_KEY_CONSTANTS.DEEPSEEK]: 'DeepSeek',\n [API_KEY_CONSTANTS.GROK]: 'Grok',\n [API_KEY_CONSTANTS.MOONSHOT]: 'Moonshot',\n [API_KEY_CONSTANTS.Z_AI]: 'Z.AI',\n [API_KEY_CONSTANTS.FUGU]: 'Sakana Fugu',\n [API_KEY_CONSTANTS.QWEN]: 'Qwen',\n [API_KEY_CONSTANTS.MINIMAX]: 'MiniMax'\n};\n\n// Naming rule: a constant's NAME is its id in upper snake case (CLAUDE_SONNET === 'claude-sonnet').\n// Ids are version-free on purpose — they are persisted by consumers, so a model bump changes only\n// the entry (displayName / modelApiName), never the id or the constant. Enforced by catalog.test.ts.\nexport const LLM_CONSTANTS = {\n // Thinking-only catalog since 2026-08-05: models whose API offers a thinking toggle used to\n // ship as separate with/without picker entries. The non-thinking variants were retired and\n // the surviving thinking entries took over the plain ids ('claude-opus', 'glm', …).\n // Ids are stable slot names, independent of provider version, so repointing a slot to a\n // newer model doesn't orphan ids persisted by consumers.\n CLAUDE_FABLE: 'claude-fable',\n CLAUDE_OPUS: 'claude-opus',\n CLAUDE_SONNET: 'claude-sonnet',\n CLAUDE_HAIKU: 'claude-haiku',\n DEEPSEEK_FLASH: 'deepseek-flash',\n DEEPSEEK_PRO: 'deepseek-pro',\n // GPT-5.6 family. 'gpt' and 'gpt-mini' are stable picker ids carried over from the\n // GPT-5.5 / GPT-5.4-mini era so existing consumers keep working across the repoint.\n GPT_SOL: 'gpt-sol',\n GPT: 'gpt',\n GPT_MINI: 'gpt-mini',\n GEMINI_PRO: 'gemini-pro',\n GEMINI_FLASH: 'gemini-flash',\n GEMINI_LITE: 'gemini-lite',\n MISTRAL_LARGE: 'mistral-large',\n MISTRAL_MEDIUM: 'mistral-medium',\n MISTRAL_SMALL: 'mistral-small',\n MISTRAL_MAGISTRAL: 'mistral-magistral',\n GROK: 'grok',\n KIMI: 'kimi',\n GLM: 'glm',\n GLM_FLASH: 'glm-flash',\n FUGU_ULTRA: 'fugu-ultra',\n // Qwen (QwenCloud/DashScope). Stable picker ids without the version, matching the gpt/gemini\n // pattern, so future repoints don't orphan persisted ids.\n QWEN_MAX: 'qwen-max',\n QWEN_FLASH: 'qwen-flash',\n // MiniMax. Single M3 entry; stable id without the version for the same repoint reason.\n MINIMAX: 'minimax',\n}\n\n/**\n * Per-request output ceiling for ordinary requests. Reasoning tokens are billed inside this\n * budget on every provider, so the cap has to clear thinking AND the answer — set below what\n * a request really emits and the *answer* is what gets truncated, producing malformed JSON\n * rather than a cheaper request.\n *\n * NOTE this is a blast-radius cap, not a cost lever: providers bill tokens generated, never\n * the unused ceiling. Lowering it saves nothing on a well-behaved request — it only bounds a\n * runaway one. Reasoning effort and thinking budgets are the knobs that change spend.\n */\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 8192;\n\n// Speed tags graded from live measurements (one identical prompt per model;\n// re-graded 2026-08-04, very-slow tier added 2026-08-05): very-fast < 3s, fast 3-6s,\n// slow 15-25s, very-slow > 25s (the K3 / Qwen Max / MiniMax cluster), extremely-slow = minutes\n// (Fugu Ultra exclusively). Models in the 6-13s middle carry NO speed tag on purpose — \"medium\"\n// is the unlabeled default. Single-sample measurements: trust the bucket, not fine ordering.\nexport type ModelTag = 'very-fast' | 'fast' | 'slow' | 'very-slow' | 'extremely-slow' | 'cheap' | 'expensive';\n\nexport type ReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n\n/**\n * What a catalog entry produces. Only text agents exist today; TTS, STT and image\n * generation are planned as subpath exports, and their catalog entries will carry the\n * matching modality so consumers can filter (a text-model picker must not list a voice).\n * Omitted means 'text'.\n */\nexport type Modality = 'text' | 'tts' | 'stt' | 'image';\n\nexport interface ModelConfig {\n displayName: string;\n modelApiName: string;\n apiKeyName: string;\n modality?: Modality; // Default 'text'; see Modality.\n hasThinking: boolean;\n temperature?: number; // Override agent default temperature; omit to use the agent's built-in default\n // Reasoning-depth knobs. Providers speak two dialects, so there are two fields; a model uses\n // at most one of them, and omitting it means \"provider default\" (e.g. GPT-5 runs at OpenAI's\n // default medium effort, Fugu/Grok at their fixed \"high\").\n // ReasoningEffort is the superset of provider vocabularies — each provider accepts only its\n // own slice (see reasoning-effort.ts for the per-provider types), and every effort-aware\n // agent clamps the value to the nearest level its API takes before sending. So a catalog\n // pin or a per-call override can use any level; prefer one the model natively supports\n // (Anthropic adaptive low|medium|high|xhigh|max, OpenAI minimal|low|medium|high|xhigh,\n // Gemini 3.x minimal|low|medium|high — 3.1 Pro and 3.7 Flash reject 'minimal' —, Fugu\n // high|xhigh, GLM-5.3 and DeepSeek V4 low|high|max).\n reasoningEffort?: ReasoningEffort; // Effort-based APIs (Anthropic adaptive thinking, Gemini 3.x)\n thinkingBudgetTokens?: number; // Budget-based APIs (Anthropic enabled thinking, Qwen thinking_budget)\n // Per-request output ceiling, overriding DEFAULT_MAX_OUTPUT_TOKENS. Only set it for models\n // that measurably need more room than a typical request takes (see the DeepSeek entries,\n // whose reasoning tokens share this budget). Every agent honors it via AbstractAgent.\n maxOutputTokens?: number;\n tags?: ModelTag[];\n}\n\nexport const SupportedAiModels: Record<string, ModelConfig> = {\n // Claude Fable - frontier reasoning model. Thinking is always on (no non-thinking variant).\n [LLM_CONSTANTS.CLAUDE_FABLE]: {\n displayName: 'Claude Fable 5',\n modelApiName: 'claude-fable-5',\n apiKeyName: API_KEY_CONSTANTS.ANTHROPIC,\n hasThinking: true,\n reasoningEffort: 'high',\n tags: ['expensive'],\n },\n\n // Claude models — thinking-only entries (non-thinking variants retired 2026-08-05)\n [LLM_CONSTANTS.CLAUDE_OPUS]: {\n displayName: 'Claude 5 Opus',\n modelApiName: 'claude-opus-5',\n apiKeyName: API_KEY_CONSTANTS.ANTHROPIC,\n hasThinking: true,\n reasoningEffort: 'high',\n tags: ['expensive'],\n },\n [LLM_CONSTANTS.CLAUDE_SONNET]: {\n displayName: 'Claude 5 Sonnet',\n modelApiName: 'claude-sonnet-5',\n apiKeyName: API_KEY_CONSTANTS.ANTHROPIC,\n hasThinking: true,\n reasoningEffort: 'high',\n tags: ['expensive'],\n },\n [LLM_CONSTANTS.CLAUDE_HAIKU]: {\n displayName: 'Claude 4.5 Haiku',\n modelApiName: 'claude-haiku-4-5',\n apiKeyName: API_KEY_CONSTANTS.ANTHROPIC,\n hasThinking: true,\n thinkingBudgetTokens: 1024,\n tags: ['slow', 'cheap'],\n },\n\n // DeepSeek V4 models — thinking-only entries (non-thinking variants retired 2026-08-05).\n // reasoningEffort pinned to 'low' 2026-08-30: at the provider default ('high', no budget\n // knob exists) both models emitted ~8 reasoning tokens per answer token in prod\n // (requestStats 30d: flash p50 8.9s / p90 36s, pro p50 18.9s / p90 56s) and a 15-bot story\n // took 68-105s. Latency tracks reasoning length ~linearly, so effort is the only lever.\n [LLM_CONSTANTS.DEEPSEEK_FLASH]: {\n displayName: 'DeepSeek V4 Flash',\n modelApiName: 'deepseek-v4-flash',\n apiKeyName: API_KEY_CONSTANTS.DEEPSEEK,\n hasThinking: true,\n reasoningEffort: 'low',\n // Reasoning tokens share the output budget, so leave room for both CoT and answer.\n maxOutputTokens: 65536,\n tags: ['cheap'],\n },\n [LLM_CONSTANTS.DEEPSEEK_PRO]: {\n displayName: 'DeepSeek V4 Pro',\n modelApiName: 'deepseek-v4-pro',\n apiKeyName: API_KEY_CONSTANTS.DEEPSEEK,\n hasThinking: true,\n reasoningEffort: 'low',\n // Reasoning tokens share the output budget, so leave room for both CoT and answer.\n maxOutputTokens: 65536,\n tags: ['cheap'],\n },\n\n // Models with always-on reasoning\n // GPT-5.6 family (promoted July 2026 when the limited preview opened up):\n // sol is the flagship, terra the mainline, luna the cheap tier.\n [LLM_CONSTANTS.GPT_SOL]: {\n displayName: 'GPT-5.6 Sol',\n modelApiName: 'gpt-5.6-sol',\n apiKeyName: API_KEY_CONSTANTS.OPENAI,\n hasThinking: true,\n temperature: 1,\n tags: ['expensive'],\n },\n [LLM_CONSTANTS.GPT]: {\n displayName: 'GPT-5.6 Terra',\n modelApiName: 'gpt-5.6-terra',\n apiKeyName: API_KEY_CONSTANTS.OPENAI,\n hasThinking: true,\n temperature: 1,\n tags: ['fast', 'expensive'],\n },\n [LLM_CONSTANTS.GPT_MINI]: {\n displayName: 'GPT-5.6 Luna',\n modelApiName: 'gpt-5.6-luna',\n apiKeyName: API_KEY_CONSTANTS.OPENAI,\n hasThinking: true,\n temperature: 1,\n tags: ['fast', 'cheap'],\n },\n // Gemini 3.x reasons via the effort dialect (thinkingLevel). The level is a CEILING on an\n // always-dynamic process — the model still scales actual thinking depth per request within\n // it; \"high\" is the fully open dynamic range. Levels below are each model's documented\n // default (Pro accepts low|medium|high only — no minimal). This replaced the deprecated\n // 2.5-era thinkingBudget: 1024 (2026-08-06), which HAD been binding — so Flash Lite now\n // thinks noticeably less under its \"minimal\" default (0.8s/49-token votes vs 4.5s/650\n // budgeted); bump it to 'low' if its output quality visibly drops.\n [LLM_CONSTANTS.GEMINI_PRO]: {\n displayName: 'Gemini 3.1 Pro Preview',\n modelApiName: 'gemini-3.1-pro-preview',\n apiKeyName: API_KEY_CONSTANTS.GOOGLE,\n hasThinking: true,\n reasoningEffort: 'high',\n tags: ['expensive'],\n },\n [LLM_CONSTANTS.GEMINI_FLASH]: {\n // Repointed from gemini-3.6-flash 2026-08-13 (stable picker id, same pattern as gpt).\n // 3.7 rejects thinkingLevel 'minimal' (low|medium|high only), unlike 3.5/3.6.\n displayName: 'Gemini 3.7 Flash',\n modelApiName: 'gemini-3.7-flash',\n apiKeyName: API_KEY_CONSTANTS.GOOGLE,\n hasThinking: true,\n reasoningEffort: 'medium',\n tags: ['fast'],\n },\n [LLM_CONSTANTS.GEMINI_LITE]: {\n displayName: 'Gemini 3.5 Flash Lite',\n modelApiName: 'gemini-3.5-flash-lite',\n apiKeyName: API_KEY_CONSTANTS.GOOGLE,\n hasThinking: true,\n reasoningEffort: 'minimal',\n tags: ['fast', 'cheap'],\n },\n // Always-on reasoning (xAI default effort \"high\", cannot be disabled) — no non-thinking sibling\n [LLM_CONSTANTS.GROK]: {\n displayName: 'Grok 4.6',\n modelApiName: 'grok-4.6',\n apiKeyName: API_KEY_CONSTANTS.GROK,\n hasThinking: true,\n temperature: 0.7,\n },\n\n // Mistral models\n [LLM_CONSTANTS.MISTRAL_LARGE]: {\n displayName: 'Mistral Large 3',\n modelApiName: 'mistral-large-latest',\n apiKeyName: API_KEY_CONSTANTS.MISTRAL,\n hasThinking: false,\n tags: ['fast'],\n },\n [LLM_CONSTANTS.MISTRAL_MEDIUM]: {\n displayName: 'Mistral Medium 3.5',\n modelApiName: 'mistral-medium-3',\n apiKeyName: API_KEY_CONSTANTS.MISTRAL,\n hasThinking: false,\n tags: ['very-fast', 'expensive'],\n },\n [LLM_CONSTANTS.MISTRAL_SMALL]: {\n displayName: 'Mistral 4 Small',\n modelApiName: 'mistral-small-latest',\n apiKeyName: API_KEY_CONSTANTS.MISTRAL,\n hasThinking: false,\n tags: ['very-fast', 'cheap'],\n },\n [LLM_CONSTANTS.MISTRAL_MAGISTRAL]: {\n displayName: 'Magistral Medium 1.2',\n modelApiName: 'magistral-medium-latest',\n apiKeyName: API_KEY_CONSTANTS.MISTRAL,\n hasThinking: true,\n // Measured very-fast (1.6s) because JSON response mode suppresses its thinking\n // (see mistral-agent.ts) — it effectively runs as a non-reasoning model here.\n tags: ['very-fast'],\n },\n\n // Kimi models. Single always-reasoning entry: K3 reasons by default and the only way to stop\n // it is the undocumented K2-era `thinking: disabled` toggle, which we no longer rely on.\n // K3 always reasons at max effort; ~85-90% of its output tokens are reasoning tokens billed\n // at the output rate, so real per-request cost runs well above the sticker output price.\n [LLM_CONSTANTS.KIMI]: {\n displayName: 'Kimi K3',\n modelApiName: 'kimi-k3',\n apiKeyName: API_KEY_CONSTANTS.MOONSHOT,\n hasThinking: true,\n // Temperature is omitted from the request: kimi-k3 rejects any value other than 1.\n // Speed samples: 17s (2026-08-04) and 28.9s (2026-08-05) — graded into the >25s tier.\n tags: ['very-slow', 'expensive'],\n },\n\n // Z.AI models — thinking-only entry (non-thinking variant retired 2026-08-05)\n // reasoningEffort MUST be set: GLM-5.3 forces reasoning on and defaults the effort to 'max',\n // and its reasoning tokens count against max_tokens. At 'max' a long-context request can\n // burn the whole 8192 budget on reasoning and return finish_reason 'length' with content \"\"\n // (prod empty-response incidents + live repro, 2026-08-20). 'high' answered the same test\n // prompt with ~10x fewer reasoning tokens.\n [LLM_CONSTANTS.GLM]: {\n displayName: 'GLM-5.3',\n modelApiName: 'glm-5.3',\n apiKeyName: API_KEY_CONSTANTS.Z_AI,\n hasThinking: true,\n temperature: 0.7,\n reasoningEffort: 'high',\n // Headroom for the shared reasoning+answer budget (like the DeepSeek entries), sized\n // at 2x default rather than DeepSeek's 65536 to bound worst-case latency on a slow model.\n maxOutputTokens: 16384,\n tags: ['slow'],\n },\n // GLM-5.3-Flash (added 2026-08-30): the cheap sibling. Same API contract as GLM-5.3 —\n // thinking cannot be disabled and reasoning_effort takes low|high|max only\n // (docs.z.ai/guides/llm/glm-5.3-flash, /guides/capabilities/thinking), so it gets the same\n // 'high' pin and the same reasoning+answer headroom.\n [LLM_CONSTANTS.GLM_FLASH]: {\n displayName: 'GLM-5.3 Flash',\n modelApiName: 'glm-5.3-flash',\n apiKeyName: API_KEY_CONSTANTS.Z_AI,\n hasThinking: true,\n temperature: 0.7,\n reasoningEffort: 'high',\n maxOutputTokens: 16384,\n // Live 2026-08-30 (one sample each): day-2 vote 11.8s, 15-character story 56.2s.\n tags: ['cheap'],\n },\n\n // Sakana Fugu models — OpenAI-compatible. They reason internally (and bill it as\n // \"orchestration\" tokens), but never surface reasoning to us: responses come back with\n // reasoning_tokens: 0 and no reasoning_content. So hasThinking is false — there's no\n // thinking content to show and no user-facing thinking toggle. Single entry per model.\n //\n // Base `fugu` was RETIRED 2026-08-04. It was carried as a cheap everyday option at an\n // assumed $1/$3, but reconciling token logs against the Sakana balance showed it actually\n // bills at fugu-ultra's rates: 592K prompt + 54K completion tokens over Aug 1-3 cost $4.80\n // real against $0.85 tracked, a 5.7x undercharge. It is a router with no published price,\n // so the rate is not even guaranteed stable, and its cache hit rate was 9.3% — effectively\n // zero, since every hit came from a duplicate call seconds apart rather than turn-to-turn\n // prefix reuse. Ultra costs the same and is predictable.\n [LLM_CONSTANTS.FUGU_ULTRA]: {\n displayName: 'Sakana Fugu Ultra',\n modelApiName: 'fugu-ultra',\n apiKeyName: API_KEY_CONSTANTS.FUGU,\n hasThinking: false,\n tags: ['extremely-slow', 'expensive'],\n },\n\n // Qwen models (QwenCloud, OpenAI-compatible endpoint). Added 2026-08-05 straight into the\n // thinking-only catalog: their API has an `enable_thinking` toggle, we always send true, and\n // thinking arrives in `reasoning_content` (verified live against all three, non-streaming).\n // Speed tags from the 2026-08-05 live measurements (two samples each): plus 17.4s/14.5s,\n // flash 14.3s/16.4s (both slow); max 30.6s/100.5s — its latency tracks how long it decides\n // to think (4.2K reasoning tokens on the slow run), hence the budget cap below.\n [LLM_CONSTANTS.QWEN_MAX]: {\n displayName: 'Qwen3.8 Max',\n modelApiName: 'qwen3.8-max',\n apiKeyName: API_KEY_CONSTANTS.QWEN,\n hasThinking: true,\n temperature: 0.7,\n // Caps `thinking_budget` to bound the 30–100s latency variance. The same knob works on\n // the 3.7 models (verified live) — add it to their entries if they ever need taming.\n thinkingBudgetTokens: 1024,\n // Capped it measures 25-26s → the >25s tier.\n tags: ['very-slow'],\n },\n // qwen3.8-flash replaced qwen3.7-flash on 2026-08-30 (same 1M context, 128k max output);\n // qwen3.7-plus was retired the same day — persisted 'qwen-plus' ids resolve to this entry\n // in consumers' deprecated-id maps. Live 2026-08-30 (one sample each): day-2 vote 13.8s,\n // 15-character story 26.4s — same bucket as 3.7-flash, so the tags carry over.\n [LLM_CONSTANTS.QWEN_FLASH]: {\n displayName: 'Qwen3.8 Flash',\n modelApiName: 'qwen3.8-flash',\n apiKeyName: API_KEY_CONSTANTS.QWEN,\n hasThinking: true,\n temperature: 0.7,\n // Uncapped it swung to 3K reasoning tokens (21s); same cap as its siblings.\n thinkingBudgetTokens: 1024,\n tags: ['slow', 'cheap'],\n },\n\n // MiniMax M3 (OpenAI-compatible endpoint, 1M context). Thinking-only entry: M3's `thinking`\n // param defaults to adaptive (it decides per-request how much to think) and can be disabled,\n // making it hybrid for cost purposes. The agent always sends `reasoning_split: true` so\n // thinking arrives in `reasoning_content` instead of as `<think>` tags inside the answer.\n // Note: unlike Qwen, M3 has NO thinking-budget parameter — adaptive is the only throttle.\n // Speed from the 2026-08-05 live measurement (single sample): 25.3s → the >25s tier.\n // Temperature: MiniMax range is [0,2], default 1.\n [LLM_CONSTANTS.MINIMAX]: {\n displayName: 'MiniMax M3',\n modelApiName: 'MiniMax-M3',\n apiKeyName: API_KEY_CONSTANTS.MINIMAX,\n hasThinking: true,\n temperature: 1,\n tags: ['very-slow', 'cheap'],\n },\n};\n\nexport type LLMModel = keyof typeof SupportedAiModels;\n\n/**\n * Builds a catalog from the library defaults with per-model partial overrides merged on top.\n * The merge is per-model and shallow: `{ glm: { temperature: 0.9 } }` changes only that field\n * and keeps the rest of the default entry. Ids absent from the defaults are added verbatim\n * (they must then be complete ModelConfig entries).\n */\nexport function createCatalog(overrides: Record<string, Partial<ModelConfig>> = {}): Record<string, ModelConfig> {\n const catalog: Record<string, ModelConfig> = {};\n for (const [id, config] of Object.entries(SupportedAiModels)) {\n catalog[id] = { ...config, ...(overrides[id] ?? {}) };\n }\n for (const [id, config] of Object.entries(overrides)) {\n if (!catalog[id]) {\n catalog[id] = config as ModelConfig;\n }\n }\n return catalog;\n}\n\nexport function getModelTags(modelId: string): ModelTag[] {\n return SupportedAiModels[modelId]?.tags ?? [];\n}\n\nexport function modelHasTag(modelId: string, tag: ModelTag): boolean {\n return getModelTags(modelId).includes(tag);\n}\n\n/** Speed is an ordered scale — \"fast\" filters must also admit very-fast models. */\nexport function modelIsFast(modelId: string): boolean {\n return modelHasTag(modelId, 'fast') || modelHasTag(modelId, 'very-fast');\n}\n\nexport function getModelDisplayName(modelId: string): string {\n return SupportedAiModels[modelId]?.displayName ?? modelId;\n}\n\n/** Human-readable provider name (\"Anthropic\", \"Grok\", …) for a model id, if known. */\nexport function getModelProviderName(modelId: string): string | undefined {\n const apiKeyName = SupportedAiModels[modelId]?.apiKeyName;\n return apiKeyName ? SupportedAiKeyNames[apiKeyName] : undefined;\n}\n\n/**\n * Looks up a model's config by API name. Since the catalog went thinking-only (2026-08-05) each\n * modelApiName has a single entry, so hasThinking no longer disambiguates anything; it is kept\n * for call-site compatibility and as a filter should variants ever return.\n */\nexport function getModelConfigByApiName(modelApiName: string, hasThinking?: boolean): ModelConfig | undefined {\n const candidates = Object.values(SupportedAiModels).filter(config => config.modelApiName === modelApiName);\n if (hasThinking !== undefined) {\n const exact = candidates.find(config => config.hasThinking === hasThinking);\n if (exact) {\n return exact;\n }\n }\n return candidates[0];\n}\n\n/**\n * Model pricing configuration\n * All prices are in USD per 1,000,000 tokens\n */\n/**\n * What a price is quoted per. Text models bill per million tokens; the planned TTS entries\n * bill per million characters, STT per minute of audio, image models per image (or per\n * output token, in which case they stay 'tokens'). Omitted means 'tokens'.\n */\nexport type PricingUnit = 'tokens' | 'characters' | 'minutes' | 'images';\n\nexport interface ModelPricing {\n unit?: PricingUnit; // Default 'tokens'; see PricingUnit. Per-million for tokens/characters.\n inputPrice: number; // Price per million input tokens\n outputPrice: number; // Price per million output tokens\n cacheHitPrice?: number; // Optional: Price per million cached tokens (if applicable)\n extendedContextInputPrice?: number; // Optional: Price per million input tokens when context exceeds threshold\n extendedContextOutputPrice?: number; // Optional: Price per million output tokens when context exceeds threshold\n extendedContextCacheHitPrice?: number; // Optional: Price per million cached tokens for extended contexts\n extendedContextThresholdTokens?: number; // Optional: Threshold at which extended pricing applies\n peakPricing?: PeakPricing; // Optional: time-of-day surcharge (e.g. DeepSeek peak-valley pricing)\n}\n\n/**\n * Time-of-day surcharge applied to all billing items (input, output, cache) when the\n * request falls inside one of the UTC windows.\n */\nexport interface PeakPricing {\n multiplier: number; // e.g. 2 → peak-hour prices are double the regular price\n windowsUtc: Array<[number, number]>; // [startHour, endHour) pairs in UTC, e.g. [[1, 4], [6, 10]]\n /** When set, the windows apply Monday–Friday only: a request that falls on a Saturday or\n * Sunday in the provider's local timezone (given as a UTC offset in hours) bills at the\n * base rate all day. */\n weekendOffPeak?: { utcOffsetHours: number };\n}\n\n/** True if the timestamp's UTC time-of-day falls inside any [startHour, endHour) window. */\nexport function isInPeakWindow(timestampMs: number, windowsUtc: Array<[number, number]>): boolean {\n const d = new Date(timestampMs);\n const hour = d.getUTCHours() + d.getUTCMinutes() / 60;\n return windowsUtc.some(([start, end]) => hour >= start && hour < end);\n}\n\n/** True if the timestamp falls on a Saturday or Sunday in the timezone at the given UTC offset. */\nexport function isWeekendAt(timestampMs: number, utcOffsetHours: number): boolean {\n const day = new Date(timestampMs + utcOffsetHours * 3_600_000).getUTCDay();\n return day === 0 || day === 6;\n}\n\n/** True if a request at this timestamp bills at the peak multiplier under the schedule. */\nexport function isPeakBilling(timestampMs: number, peak: PeakPricing): boolean {\n if (peak.weekendOffPeak && isWeekendAt(timestampMs, peak.weekendOffPeak.utcOffsetHours)) {\n return false;\n }\n return isInPeakWindow(timestampMs, peak.windowsUtc);\n}\n\n/** DeepSeek's peak-valley schedule: 2× during Beijing 09:00–12:00 and 14:00–18:00\n * (UTC 1–4, 6–10), Monday–Friday Beijing time only. */\nexport const DEEPSEEK_PEAK_SCHEDULE: PeakPricing = {\n multiplier: 2,\n windowsUtc: [[1, 4], [6, 10]],\n weekendOffPeak: { utcOffsetHours: 8 },\n};\n\n/**\n * Centralized pricing configuration for all AI models\n * All prices are per million (1,000,000) tokens\n */\nexport const MODEL_PRICING: Record<string, ModelPricing> = {\n // OpenAI GPT-5.6 models\n // Sol repriced 2026-08-30 (developers.openai.com/api/docs/pricing): $4/$20 short context,\n // $8/$30 past the long-context threshold — the same 272k boundary its siblings use.\n // Cache writes ($5/$10) are not modelled; OpenAI caching is automatic and we only see hits.\n [SupportedAiModels[LLM_CONSTANTS.GPT_SOL].modelApiName]: {\n inputPrice: 4.000,\n outputPrice: 20.000,\n cacheHitPrice: 0.400,\n extendedContextInputPrice: 8.000,\n extendedContextOutputPrice: 30.000,\n extendedContextCacheHitPrice: 0.800,\n extendedContextThresholdTokens: 272_000\n },\n [SupportedAiModels[LLM_CONSTANTS.GPT].modelApiName]: {\n inputPrice: 2.000,\n outputPrice: 12.000,\n cacheHitPrice: 0.200,\n extendedContextInputPrice: 4.000,\n extendedContextOutputPrice: 18.000,\n extendedContextCacheHitPrice: 0.400,\n extendedContextThresholdTokens: 272_000\n },\n [SupportedAiModels[LLM_CONSTANTS.GPT_MINI].modelApiName]: {\n inputPrice: 0.200,\n outputPrice: 1.200,\n cacheHitPrice: 0.020,\n extendedContextInputPrice: 0.400,\n extendedContextOutputPrice: 1.800,\n extendedContextCacheHitPrice: 0.040,\n extendedContextThresholdTokens: 272_000\n },\n\n // DeepSeek V4 models\n // Peak-valley pricing landed: these are the new base (off-peak) rates with a 2× surcharge\n // during UTC 1:00–4:00 and 6:00–10:00, effective provider-side 2026-08-16 16:00 UTC\n // (api-docs.deepseek.com/quick_start/pricing, fetched 2026-08-13; rates re-confirmed\n // 2026-08-30). Since 2026-08-23 00:00 Beijing (UTC+8) the surcharge is weekdays-only:\n // Saturday and Sunday Beijing time bill at the off-peak rate all day (DeepSeek notice email).\n [SupportedAiModels[LLM_CONSTANTS.DEEPSEEK_FLASH].modelApiName]: {\n inputPrice: 0.22,\n outputPrice: 0.66,\n cacheHitPrice: 0.007,\n peakPricing: DEEPSEEK_PEAK_SCHEDULE\n },\n [SupportedAiModels[LLM_CONSTANTS.DEEPSEEK_PRO].modelApiName]: {\n inputPrice: 0.66,\n outputPrice: 1.98,\n cacheHitPrice: 0.022,\n peakPricing: DEEPSEEK_PEAK_SCHEDULE\n },\n\n // Kimi/Moonshot models\n [SupportedAiModels[LLM_CONSTANTS.KIMI].modelApiName]: {\n inputPrice: 3.00,\n outputPrice: 15.00,\n cacheHitPrice: 0.30\n },\n\n // Z.AI models\n [SupportedAiModels[LLM_CONSTANTS.GLM].modelApiName]: {\n inputPrice: 1.4,\n outputPrice: 4.4,\n cacheHitPrice: 0.26\n },\n // GLM-5.3-Flash list rates (docs.z.ai/guides/overview/pricing, 2026-08-30). The page shows a\n // 50% promo ($0.075 / $0.015 / $0.25) ending 2026-09-09 24:00 UTC+8; we bill the list rate\n // rather than track a ten-day promo.\n [SupportedAiModels[LLM_CONSTANTS.GLM_FLASH].modelApiName]: {\n inputPrice: 0.15,\n outputPrice: 0.50,\n cacheHitPrice: 0.03\n },\n\n // Anthropic models\n [SupportedAiModels[LLM_CONSTANTS.CLAUDE_FABLE].modelApiName]: {\n // Full 1M context window at standard pricing (no extended-context premium)\n inputPrice: 10.0,\n outputPrice: 50.0,\n cacheHitPrice: 1.0\n },\n [SupportedAiModels[LLM_CONSTANTS.CLAUDE_OPUS].modelApiName]: {\n inputPrice: 5.0,\n outputPrice: 25.0,\n cacheHitPrice: 0.50\n },\n [SupportedAiModels[LLM_CONSTANTS.CLAUDE_SONNET].modelApiName]: {\n inputPrice: 2.0,\n outputPrice: 10.0,\n cacheHitPrice: 0.20\n },\n [SupportedAiModels[LLM_CONSTANTS.CLAUDE_HAIKU].modelApiName]: {\n inputPrice: 1.0,\n outputPrice: 5.0,\n cacheHitPrice: 0.10\n },\n\n // Google models\n [SupportedAiModels[LLM_CONSTANTS.GEMINI_PRO].modelApiName]: {\n inputPrice: 2.0,\n outputPrice: 12.0,\n cacheHitPrice: 0.20,\n extendedContextInputPrice: 4.0,\n extendedContextOutputPrice: 18.0,\n extendedContextCacheHitPrice: 0.40,\n extendedContextThresholdTokens: 200_000\n },\n [SupportedAiModels[LLM_CONSTANTS.GEMINI_FLASH].modelApiName]: {\n // Launch pricing through 2026-12-31; doubles to $1.50/$7.50/$0.15 on 2027-01-01\n // (ai.google.dev pricing page, fetched 2026-08-13) — ACTION NEEDED then: update these\n // rates.\n // Cache storage cost ($0.50 / 1M tokens per hour) is not tracked here — the\n // schema only models per-token call costs, not time-based storage.\n inputPrice: 0.75,\n outputPrice: 3.75,\n cacheHitPrice: 0.075\n },\n [SupportedAiModels[LLM_CONSTANTS.GEMINI_LITE].modelApiName]: {\n // Cache storage cost ($1.00 / 1M tokens per hour) is not tracked here — the\n // schema only models per-token call costs, not time-based storage.\n inputPrice: 0.30,\n outputPrice: 1.50,\n cacheHitPrice: 0.025\n },\n\n // Mistral models. Cached tokens bill at 10% of the input price (documented on the\n // prompt_cache_key param in the API reference; no per-model cached prices published).\n [SupportedAiModels[LLM_CONSTANTS.MISTRAL_LARGE].modelApiName]: {\n inputPrice: 0.5,\n outputPrice: 1.5,\n cacheHitPrice: 0.05\n },\n [SupportedAiModels[LLM_CONSTANTS.MISTRAL_MEDIUM].modelApiName]: {\n inputPrice: 1.5,\n outputPrice: 7.5,\n cacheHitPrice: 0.15\n },\n [SupportedAiModels[LLM_CONSTANTS.MISTRAL_SMALL].modelApiName]: {\n inputPrice: 0.15,\n outputPrice: 0.6,\n cacheHitPrice: 0.015\n },\n [SupportedAiModels[LLM_CONSTANTS.MISTRAL_MAGISTRAL].modelApiName]: {\n inputPrice: 2.0,\n outputPrice: 5.0,\n cacheHitPrice: 0.2\n },\n\n // Grok models. Cached price is per-model on xAI (not a uniform ratio):\n // grok-4.6 is $0.50/M cached vs $2.00/M input, and all rates double for prompts\n // >= 200K tokens, per docs.x.ai/developers/models (verified 2026-08-12).\n [SupportedAiModels[LLM_CONSTANTS.GROK].modelApiName]: {\n inputPrice: 2.0,\n outputPrice: 6.0,\n cacheHitPrice: 0.50,\n extendedContextInputPrice: 4.0,\n extendedContextOutputPrice: 12.0,\n extendedContextCacheHitPrice: 1.0,\n extendedContextThresholdTokens: 200_000\n },\n\n // Sakana Fugu models. Base `fugu` was retired 2026-08-04 — it had no published price and\n // measured out at these same ultra rates, so it has no pricing entry.\n // fugu-ultra has published pricing. Above 272K context the rates roughly double.\n [SupportedAiModels[LLM_CONSTANTS.FUGU_ULTRA].modelApiName]: {\n inputPrice: 5.0,\n outputPrice: 30.0,\n cacheHitPrice: 0.50,\n extendedContextInputPrice: 10.0,\n extendedContextOutputPrice: 45.0,\n extendedContextCacheHitPrice: 1.00,\n extendedContextThresholdTokens: 272_000\n },\n\n // Qwen models. Rates from the official pricing page (qwencloud.com/pricing/api, read\n // 2026-08-30 — the page is client-rendered, so it was read by eye, not WebFetch):\n // qwen3.8-max $2/$6 with implicit-cache hits at $0.25; qwen3.8-flash $0.15/$0.47, hits\n // $0.016. Neither has input-length tiers (the tier column is \"-\" for both). These\n // published cached rates supersede the 20%-of-input rule charged before 2026-08-30; we\n // still don't send explicit cache_control.\n [SupportedAiModels[LLM_CONSTANTS.QWEN_MAX].modelApiName]: {\n inputPrice: 2.0,\n outputPrice: 6.0,\n cacheHitPrice: 0.25\n },\n [SupportedAiModels[LLM_CONSTANTS.QWEN_FLASH].modelApiName]: {\n inputPrice: 0.15,\n outputPrice: 0.47,\n cacheHitPrice: 0.016\n },\n\n // MiniMax M3. Rates from platform.minimax.io/docs/guides/pricing-paygo (2026-08-05, USD,\n // \"permanent 50% off\" already applied): ≤512k and >512k input tiers. Caching is automatic\n // (≥512 input tokens), hits reported in prompt_tokens_details.cached_tokens; no write fee\n // for M3.\n [SupportedAiModels[LLM_CONSTANTS.MINIMAX].modelApiName]: {\n inputPrice: 0.30,\n outputPrice: 1.20,\n cacheHitPrice: 0.06,\n extendedContextInputPrice: 0.60,\n extendedContextOutputPrice: 2.40,\n extendedContextCacheHitPrice: 0.12,\n extendedContextThresholdTokens: 512_000\n }\n};\n\n/** modelApiNames of hybrid models: their APIs offer a thinking toggle, but the catalog ships them\n * thinking-only (non-thinking variants retired 2026-08-05). A hybrid model run with thinking on\n * burns extra reasoning tokens at the output rate, so its effective output price is a multiple\n * of the sticker price — consumers that budget on price use this to know which models that\n * applies to. This is hand-maintained: it can no longer be derived from the catalog, since no\n * non-thinking siblings exist to derive it from. */\nconst HYBRID_THINKING_API_NAMES = new Set([\n SupportedAiModels[LLM_CONSTANTS.CLAUDE_OPUS].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.CLAUDE_SONNET].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.CLAUDE_HAIKU].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.DEEPSEEK_FLASH].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.DEEPSEEK_PRO].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.GLM].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.GLM_FLASH].modelApiName,\n // Qwen ships thinking-only from day one, but the API's enable_thinking toggle makes these\n // hybrid by the same definition: we force reasoning on, so they carry the multiplier.\n SupportedAiModels[LLM_CONSTANTS.QWEN_MAX].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.QWEN_FLASH].modelApiName,\n SupportedAiModels[LLM_CONSTANTS.MINIMAX].modelApiName,\n]);\n\n/** True for hybrid thinking-only models — the ones whose effective output price is a known\n * multiple of the sticker price. Always-on reasoning models (GPT-5, Gemini, Grok, Kimi,\n * Fable, Magistral) also burn reasoning tokens, but their multiplier hasn't been measured. */\nexport function isHybridThinkingModel(modelApiName: string): boolean {\n return HYBRID_THINKING_API_NAMES.has(modelApiName);\n}\n\nexport interface CostCalculationOptions {\n cacheHitTokens?: number;\n contextTokens?: number;\n totalTokens?: number;\n timestamp?: number; // When the request was billed; defaults to now. Only affects peakPricing models.\n}\n\n/**\n * Helper function to calculate cost based on model pricing\n * @param modelApiName - The API name of the model\n * @param inputTokens - Number of input tokens\n * @param outputTokens - Number of output tokens\n * @param options - Additional calculation details (cache hits, context tokens, etc.)\n * @returns Cost in USD\n */\nexport function calculateModelCost(\n modelApiName: string,\n inputTokens: number,\n outputTokens: number,\n options: CostCalculationOptions = {}\n): number {\n const pricing = MODEL_PRICING[modelApiName];\n\n if (!pricing) {\n console.warn(`No pricing information available for model: ${modelApiName}`);\n return 0;\n }\n\n // All prices are per million tokens\n const divisor = 1_000_000;\n\n // Calculate cached vs uncached input tokens\n const cacheHitTokens = Math.max(0, options.cacheHitTokens ?? 0);\n const actualCacheHits = Math.min(cacheHitTokens, inputTokens);\n const uncachedInputTokens = Math.max(0, inputTokens - actualCacheHits);\n\n // Determine if extended context pricing applies\n const contextTokens = options.contextTokens ?? options.totalTokens ?? inputTokens;\n let activeInputPrice = pricing.inputPrice;\n let activeOutputPrice = pricing.outputPrice;\n let activeCachePrice = pricing.cacheHitPrice ?? pricing.inputPrice;\n\n if (\n pricing.extendedContextThresholdTokens !== undefined &&\n contextTokens > pricing.extendedContextThresholdTokens\n ) {\n activeInputPrice = pricing.extendedContextInputPrice ?? pricing.inputPrice;\n activeOutputPrice = pricing.extendedContextOutputPrice ?? pricing.outputPrice;\n activeCachePrice = pricing.extendedContextCacheHitPrice ?? pricing.cacheHitPrice ?? activeInputPrice;\n } else if (pricing.cacheHitPrice !== undefined) {\n activeCachePrice = pricing.cacheHitPrice;\n }\n\n if (\n pricing.peakPricing &&\n isPeakBilling(options.timestamp ?? Date.now(), pricing.peakPricing)\n ) {\n activeInputPrice *= pricing.peakPricing.multiplier;\n activeOutputPrice *= pricing.peakPricing.multiplier;\n activeCachePrice *= pricing.peakPricing.multiplier;\n }\n\n // Calculate costs\n const uncachedInputCost = (uncachedInputTokens * activeInputPrice) / divisor;\n const cachedInputCost = (actualCacheHits * activeCachePrice) / divisor;\n const outputCost = (outputTokens * activeOutputPrice) / divisor;\n\n return uncachedInputCost + cachedInputCost + outputCost;\n}\n\n/**\n * Returns provider-specific signature fields based on the model's API name prefix.\n * Used when storing messages with thinking signatures from different providers.\n * @param aiType - The model API name (e.g. \"claude-sonnet-5\", \"gemini-3.7-flash\")\n * @param signature - The thinking signature from the API response (may be undefined)\n * @returns Object with appropriate signature fields for the message\n */\nexport function getProviderSignatureFields(aiType: string, signature?: string): {\n anthropicThinkingSignature?: string;\n googleThoughtSignature?: string;\n grokEncryptedReasoning?: string;\n} {\n if (!signature) {\n return {};\n }\n\n // Check if it's an Anthropic (Claude) model\n if (aiType.startsWith('claude-')) {\n return { anthropicThinkingSignature: signature };\n }\n\n // Check if it's a Google (Gemini) model\n if (aiType.startsWith('gemini-')) {\n return { googleThoughtSignature: signature };\n }\n\n // Check if it's an xAI (Grok) model — JSON-serialized encrypted reasoning items\n if (aiType.startsWith('grok')) {\n return { grokEncryptedReasoning: signature };\n }\n\n // Other providers don't support signatures, return empty\n return {};\n}\n","import type { ReasoningEffort } from './catalog';\n\n/**\n * Per-provider reasoning-effort vocabularies.\n *\n * `ReasoningEffort` (catalog.ts) is the union of every provider's scale so a catalog entry or\n * a per-call override can name any level; each provider accepts only its own slice and most\n * reject the rest with a 400. The `to<Provider>Effort` helpers clamp a generic level to the\n * nearest one the provider takes, so a consumer can say \"high\" for every model and let the\n * agent translate. Nearest is by rank on the shared scale; a tie resolves upward (asking for\n * \"medium\" from a provider with only low|high gets high — never less reasoning than asked).\n *\n * Verified against provider docs 2026-08-30:\n * - OpenAI GPT-5.x: minimal|low|medium|high|xhigh\n * - Anthropic adaptive thinking (Fable 5 / Opus 4.8 / Sonnet 5): low|medium|high|xhigh|max\n * - Gemini 3.x thinkingLevel: minimal|low|medium|high (3.1 Pro and 3.7 Flash reject minimal)\n * - Z.AI GLM-5.3 / 5.3-Flash: low|high|max only\n * - DeepSeek V4: low|high|max (the API itself aliases medium → high)\n * - Sakana Fugu: high|xhigh\n * Qwen accepts reasoning_effort but ignores it (thinking_budget is its knob); MiniMax, Kimi,\n * Grok and Mistral expose no effort parameter.\n */\nexport type OpenAIReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\nexport type AnthropicReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';\nexport type GeminiReasoningEffort = 'minimal' | 'low' | 'medium' | 'high';\nexport type GlmReasoningEffort = 'low' | 'high' | 'max';\nexport type DeepSeekReasoningEffort = 'low' | 'high' | 'max';\nexport type FuguReasoningEffort = 'high' | 'xhigh';\n\n/** The shared scale, lowest first. */\nexport const REASONING_EFFORT_SCALE: readonly ReasoningEffort[] = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\nexport const OPENAI_REASONING_EFFORTS: readonly OpenAIReasoningEffort[] = ['minimal', 'low', 'medium', 'high', 'xhigh'];\nexport const ANTHROPIC_REASONING_EFFORTS: readonly AnthropicReasoningEffort[] = ['low', 'medium', 'high', 'xhigh', 'max'];\nexport const GEMINI_REASONING_EFFORTS: readonly GeminiReasoningEffort[] = ['minimal', 'low', 'medium', 'high'];\nexport const GLM_REASONING_EFFORTS: readonly GlmReasoningEffort[] = ['low', 'high', 'max'];\nexport const DEEPSEEK_REASONING_EFFORTS: readonly DeepSeekReasoningEffort[] = ['low', 'high', 'max'];\nexport const FUGU_REASONING_EFFORTS: readonly FuguReasoningEffort[] = ['high', 'xhigh'];\n\n/** Clamps `effort` to the nearest level in `allowed` (by rank on the shared scale, ties go up). */\nexport function clampReasoningEffort<T extends ReasoningEffort>(effort: ReasoningEffort, allowed: readonly T[]): T {\n const rank = REASONING_EFFORT_SCALE.indexOf(effort);\n let best: T = allowed[0];\n let bestDistance = Infinity;\n for (const candidate of allowed) {\n const distance = Math.abs(REASONING_EFFORT_SCALE.indexOf(candidate) - rank);\n // Strictly closer wins; an equally close candidate wins only if it ranks higher.\n if (distance < bestDistance || (distance === bestDistance && REASONING_EFFORT_SCALE.indexOf(candidate) > REASONING_EFFORT_SCALE.indexOf(best))) {\n best = candidate;\n bestDistance = distance;\n }\n }\n return best;\n}\n\nexport const toOpenAIEffort = (effort: ReasoningEffort): OpenAIReasoningEffort => clampReasoningEffort(effort, OPENAI_REASONING_EFFORTS);\nexport const toAnthropicEffort = (effort: ReasoningEffort): AnthropicReasoningEffort => clampReasoningEffort(effort, ANTHROPIC_REASONING_EFFORTS);\nexport const toGeminiEffort = (effort: ReasoningEffort): GeminiReasoningEffort => clampReasoningEffort(effort, GEMINI_REASONING_EFFORTS);\nexport const toGlmEffort = (effort: ReasoningEffort): GlmReasoningEffort => clampReasoningEffort(effort, GLM_REASONING_EFFORTS);\nexport const toDeepSeekEffort = (effort: ReasoningEffort): DeepSeekReasoningEffort => clampReasoningEffort(effort, DEEPSEEK_REASONING_EFFORTS);\nexport const toFuguEffort = (effort: ReasoningEffort): FuguReasoningEffort => clampReasoningEffort(effort, FUGU_REASONING_EFFORTS);\n","/**\n * Unified token usage utilities for all AI providers\n * This module provides a consistent interface for token usage extraction and cost calculation\n * across all supported AI providers (OpenAI, DeepSeek, Kimi, Grok, Anthropic, Google, Mistral)\n */\n\nimport { calculateModelCost, CostCalculationOptions } from '../catalog';\n\n/**\n * Generic token usage interface that covers all provider-specific fields\n */\nexport interface TokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n \n // Cache-related fields (DeepSeek, OpenAI, Kimi, Grok)\n cacheHitTokens?: number;\n cacheMissTokens?: number;\n \n // Reasoning-specific fields (DeepSeek Reasoner, OpenAI o1, etc.)\n reasoningTokens?: number;\n \n // Provider-specific fields can be added here as needed\n}\n\n/**\n * Extract token usage from any AI provider's API response\n * This function handles the common response formats used by different providers\n * @param response - The raw API response from any provider\n * @returns TokenUsage object with extracted values or null if extraction fails\n */\nexport function extractTokenUsage(response: any): TokenUsage | null {\n if (!response?.usage) {\n return null;\n }\n \n const usage = response.usage;\n const result: TokenUsage = {\n promptTokens: usage.prompt_tokens || 0,\n completionTokens: usage.completion_tokens || 0,\n totalTokens: usage.total_tokens || 0\n };\n \n // Extract cache information if available. Three wire shapes (verified against live\n // provider docs 2026-08-04): DeepSeek reports cache hits as a top-level\n // prompt_cache_hit_tokens; OpenAI, Grok, GLM and Fugu nest them under\n // prompt_tokens_details.cached_tokens; Kimi reports a top-level cached_tokens\n // (NOT nested, despite being OpenAI-compatible).\n if (usage.prompt_cache_hit_tokens !== undefined) {\n result.cacheHitTokens = usage.prompt_cache_hit_tokens;\n } else if (usage.prompt_tokens_details?.cached_tokens !== undefined) {\n result.cacheHitTokens = usage.prompt_tokens_details.cached_tokens;\n } else if (usage.cached_tokens !== undefined) {\n result.cacheHitTokens = usage.cached_tokens;\n }\n\n if (usage.prompt_cache_miss_tokens !== undefined) {\n result.cacheMissTokens = usage.prompt_cache_miss_tokens;\n }\n \n // Extract reasoning tokens if available (DeepSeek Reasoner, OpenAI o1, etc.)\n if (usage.completion_tokens_details?.reasoning_tokens !== undefined) {\n result.reasoningTokens = usage.completion_tokens_details.reasoning_tokens;\n }\n \n // Handle other provider-specific formats\n // Anthropic: uses the same format as OpenAI\n // Google: may have different field names, add handling as needed\n // Mistral: uses OpenAI-compatible format\n // Grok: uses OpenAI-compatible format\n \n return result;\n}\n\n/**\n * Calculate cost for any AI provider using the centralized pricing\n * @param modelApiName - The API name of the model (e.g., 'gpt-5.5', 'deepseek-v4-flash')\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used \n * @param options - Additional calculation details (cache hits, context tokens, etc.)\n * @returns Cost in USD\n */\nexport function calculateCost(\n modelApiName: string,\n inputTokens: number,\n outputTokens: number,\n options: CostCalculationOptions = {}\n): number {\n return calculateModelCost(modelApiName, inputTokens, outputTokens, options);\n}\n\n/**\n * Extract token usage and calculate cost in one operation\n * @param modelApiName - The API name of the model\n * @param response - The raw API response from any provider\n * @returns Object with token usage and calculated cost, or null if extraction fails\n */\nexport function extractUsageAndCalculateCost(modelApiName: string, response: any): {\n usage: TokenUsage;\n cost: number;\n} | null {\n const usage = extractTokenUsage(response);\n if (!usage) {\n return null;\n }\n \n const cost = calculateCost(modelApiName, usage.promptTokens, usage.completionTokens, {\n cacheHitTokens: usage.cacheHitTokens || 0,\n totalTokens: usage.totalTokens\n });\n \n return { usage, cost };\n}\n\n// Provider-specific extraction functions for cases where custom logic is needed\n\n/**\n * DeepSeek-specific token usage extraction\n * Handles DeepSeek's specific cache and reasoning token fields\n */\nexport function extractDeepSeekTokenUsage(response: any): TokenUsage | null {\n // Use the generic extractor as DeepSeek follows standard patterns\n return extractTokenUsage(response);\n}\n\n/**\n * OpenAI-specific token usage extraction\n * Handles OpenAI's cache tokens and reasoning tokens (for o1 models)\n */\nexport function extractOpenAITokenUsage(response: any): TokenUsage | null {\n // Use the generic extractor as OpenAI follows standard patterns\n return extractTokenUsage(response);\n}\n\n/**\n * Kimi-specific token usage extraction\n * Kimi uses OpenAI-compatible format\n */\nexport function extractKimiTokenUsage(response: any): TokenUsage | null {\n // Use the generic extractor as Kimi follows OpenAI-compatible patterns\n return extractTokenUsage(response);\n}\n\n/**\n * Grok-specific token usage extraction\n * Grok uses OpenAI-compatible format\n */\nexport function extractGrokTokenUsage(response: any): TokenUsage | null {\n // Use the generic extractor as Grok follows OpenAI-compatible patterns\n return extractTokenUsage(response);\n}\n\n/**\n * Anthropic-specific token usage extraction\n * Anthropic may have different response format\n */\nexport function extractAnthropicTokenUsage(response: any): TokenUsage | null {\n // Anthropic might use different field names, customize as needed\n if (!response?.usage) {\n return null;\n }\n \n const usage = response.usage;\n return {\n promptTokens: usage.input_tokens || 0,\n completionTokens: usage.output_tokens || 0,\n totalTokens: (usage.input_tokens || 0) + (usage.output_tokens || 0)\n };\n}\n\n/**\n * Google-specific token usage extraction\n * Google may have different response format\n */\nexport function extractGoogleTokenUsage(response: any): TokenUsage | null {\n // Google might use different field names, customize as needed\n if (!response?.usageMetadata) {\n return null;\n }\n\n const usage = response.usageMetadata;\n const result: TokenUsage = {\n promptTokens: usage.promptTokenCount || 0,\n completionTokens: usage.candidatesTokenCount || 0,\n totalTokens: usage.totalTokenCount || 0\n };\n\n // Extract cache hit tokens if available\n if (usage.cachedContentTokenCount !== undefined) {\n result.cacheHitTokens = usage.cachedContentTokenCount;\n }\n\n return result;\n}\n\n/**\n * Mistral-specific token usage extraction\n * Mistral SDK uses camelCase (promptTokens, completionTokens, totalTokens)\n * and reasoning tokens may be in additionalProperties for Magistral models\n */\nexport function extractMistralTokenUsage(response: any): TokenUsage | null {\n const usage = response?.usage;\n if (!usage) {\n return null;\n }\n\n // Mistral SDK uses camelCase field names\n const result: TokenUsage = {\n promptTokens: usage.promptTokens || 0,\n completionTokens: usage.completionTokens || 0,\n totalTokens: usage.totalTokens || 0\n };\n\n // Extract reasoning tokens from additionalProperties if available (Magistral models)\n // Magistral models may include reasoning token info in the additionalProperties field\n if (usage.additionalProperties) {\n const additionalProps = usage.additionalProperties;\n\n // Check common field names for reasoning tokens\n if (additionalProps.reasoning_tokens !== undefined) {\n result.reasoningTokens = additionalProps.reasoning_tokens;\n } else if (additionalProps.reasoningTokens !== undefined) {\n result.reasoningTokens = additionalProps.reasoningTokens;\n } else if (additionalProps.thinking_tokens !== undefined) {\n result.reasoningTokens = additionalProps.thinking_tokens;\n }\n\n // Mistral documents cached billing (10% of input via prompt_cache_key) but no usage\n // field for hits; the SDK collects unknown wire fields here, so probe the plausible\n // shapes. Whichever one actually arrives (if any) gets picked up automatically.\n if (additionalProps.prompt_cache_hit_tokens !== undefined) {\n result.cacheHitTokens = additionalProps.prompt_cache_hit_tokens;\n } else if (additionalProps.cached_tokens !== undefined) {\n result.cacheHitTokens = additionalProps.cached_tokens;\n } else if (additionalProps.prompt_tokens_details?.cached_tokens !== undefined) {\n result.cacheHitTokens = additionalProps.prompt_tokens_details.cached_tokens;\n }\n }\n\n return result;\n}\n","/**\n * OpenAI pricing utilities\n * Re-exports unified utilities with OpenAI-specific naming for backward compatibility\n */\n\nimport { calculateCost, extractOpenAITokenUsage } from './token-usage-utils';\n\n/**\n * Calculate the cost for token usage based on OpenAI pricing\n * @param model - The OpenAI model name\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used\n * @param cacheHitTokens - Number of cached input tokens (optional)\n * @returns Cost in USD\n */\nexport function calculateOpenAICost(\n model: string, \n inputTokens: number, \n outputTokens: number,\n cacheHitTokens: number = 0\n): number {\n return calculateCost(model, inputTokens, outputTokens, { cacheHitTokens });\n}\n\n/**\n * Extract token usage from OpenAI API response\n * @param response - The raw response from OpenAI API\n * @returns Token usage object with extracted values\n */\nexport interface OpenAITokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n cacheHitTokens?: number;\n reasoningTokens?: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): OpenAITokenUsage | null {\n return extractOpenAITokenUsage(response);\n}\n","/**\n * DeepSeek pricing utilities\n * Re-exports unified utilities with DeepSeek-specific naming for backward compatibility\n */\n\nimport { calculateCost, extractDeepSeekTokenUsage, type TokenUsage } from './token-usage-utils';\n\n/**\n * Calculate the cost for token usage based on DeepSeek pricing\n * @param model - The DeepSeek model name\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used\n * @param cacheHitTokens - Number of cached input tokens (optional)\n * @returns Cost in USD\n */\nexport function calculateDeepSeekCost(\n model: string, \n inputTokens: number, \n outputTokens: number,\n cacheHitTokens: number = 0\n): number {\n return calculateCost(model, inputTokens, outputTokens, { cacheHitTokens });\n}\n\n/**\n * Extract token usage from DeepSeek API response\n * @param response - The raw response from DeepSeek API\n * @returns TokenUsage object with extracted values\n */\nexport interface DeepSeekTokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n cacheHitTokens?: number;\n cacheMissTokens?: number;\n reasoningTokens?: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): DeepSeekTokenUsage | null {\n return extractDeepSeekTokenUsage(response);\n}\n","/**\n * Kimi (Moonshot AI) pricing utilities\n * Re-exports unified utilities with Kimi-specific naming for backward compatibility\n */\n\nimport { calculateCost, extractKimiTokenUsage } from './token-usage-utils';\n\n/**\n * Calculate the cost for token usage based on Kimi pricing\n * @param model - The Kimi model name\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used\n * @returns Cost in USD\n */\nexport function calculateKimiCost(model: string, inputTokens: number, outputTokens: number): number {\n return calculateCost(model, inputTokens, outputTokens);\n}\n\n/**\n * Extract token usage from Kimi API response\n * Since Kimi uses OpenAI-compatible format, the response structure should be similar\n * @param response - The raw response from Kimi API\n * @returns Token usage object with extracted values\n */\nexport interface KimiTokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): KimiTokenUsage | null {\n return extractKimiTokenUsage(response);\n}\n","/**\n * Grok (xAI) pricing utilities\n * Re-exports unified utilities with Grok-specific naming for backward compatibility\n */\n\nimport { calculateCost, extractGrokTokenUsage } from './token-usage-utils';\n\n/**\n * Calculate the cost for token usage based on Grok pricing\n * @param model - The Grok model name\n * @param inputTokens - Number of input tokens used (prompt_tokens)\n * @param outputTokens - Number of output tokens used (completion_tokens, includes reasoning_tokens)\n * @param cacheHitTokens - Number of cached input tokens (optional, when supported)\n * @returns Cost in USD\n */\nexport function calculateGrokCost(\n model: string, \n inputTokens: number, \n outputTokens: number,\n cacheHitTokens: number = 0\n): number {\n return calculateCost(model, inputTokens, outputTokens, { cacheHitTokens });\n}\n\n/**\n * Extract token usage from Grok API response\n * @param response - The raw response from Grok API\n * @returns Token usage object with extracted values\n */\nexport interface GrokTokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n cacheHitTokens?: number;\n reasoningTokens?: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): GrokTokenUsage | null {\n return extractGrokTokenUsage(response);\n}\n","/**\n * Anthropic pricing utilities\n * Re-exports unified utilities with Anthropic-specific naming for consistency\n */\n\nimport { calculateCost, extractAnthropicTokenUsage } from './token-usage-utils';\n\n/**\n * Calculate the cost for token usage based on Anthropic pricing\n * @param model - The Anthropic model name\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used\n * @param cacheHitTokens - Number of cached input tokens (optional, when supported)\n * @returns Cost in USD\n */\nexport function calculateAnthropicCost(\n model: string, \n inputTokens: number, \n outputTokens: number,\n cacheHitTokens: number = 0\n): number {\n return calculateCost(model, inputTokens, outputTokens, { cacheHitTokens });\n}\n\n/**\n * Extract token usage from Anthropic API response\n * @param response - The raw response from Anthropic API\n * @returns Token usage object with extracted values\n */\nexport interface AnthropicTokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): AnthropicTokenUsage | null {\n return extractAnthropicTokenUsage(response);\n}\n","/**\n * Google pricing utilities\n * Re-exports unified utilities with Google-specific naming for consistency\n */\n\nimport { calculateCost, extractGoogleTokenUsage } from './token-usage-utils';\nimport { CostCalculationOptions } from '../catalog';\n\n/**\n * Calculate the cost for token usage based on Google pricing\n * @param model - The Google model name\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used\n * @param cacheHitTokens - Number of cached input tokens (optional, when supported)\n * @returns Cost in USD\n */\nexport function calculateGoogleCost(\n model: string, \n inputTokens: number, \n outputTokens: number,\n options: CostCalculationOptions = {}\n): number {\n return calculateCost(model, inputTokens, outputTokens, options);\n}\n\n/**\n * Extract token usage from Google API response\n * @param response - The raw response from Google API\n * @returns Token usage object with extracted values\n */\nexport interface GoogleTokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): GoogleTokenUsage | null {\n return extractGoogleTokenUsage(response);\n}\n","/**\n * Mistral pricing utilities\n * Re-exports unified utilities with Mistral-specific naming for consistency\n */\n\nimport { calculateCost, extractMistralTokenUsage } from './token-usage-utils';\n\n/**\n * Calculate the cost for token usage based on Mistral pricing\n * @param model - The Mistral model name\n * @param inputTokens - Number of input tokens used\n * @param outputTokens - Number of output tokens used\n * @param cacheHitTokens - Number of cached input tokens (optional, when supported)\n * @returns Cost in USD\n */\nexport function calculateMistralCost(\n model: string, \n inputTokens: number, \n outputTokens: number,\n cacheHitTokens: number = 0\n): number {\n return calculateCost(model, inputTokens, outputTokens, { cacheHitTokens });\n}\n\n/**\n * Extract token usage from Mistral API response\n * @param response - The raw response from Mistral API\n * @returns Token usage object with extracted values\n */\nexport interface MistralTokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport function extractTokenUsageFromResponse(response: any): MistralTokenUsage | null {\n return extractMistralTokenUsage(response);\n}\n","import { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { z } from 'zod';\nimport { logger } from \"../logger\";\nimport { CACHE_TIER_MARKER } from \"../cache-tier\";\nimport { DEFAULT_MAX_OUTPUT_TOKENS, getModelConfigByApiName, ReasoningEffort } from \"../catalog\";\n\nexport abstract class AbstractAgent {\n name: string;\n gameId?: string;\n userId?: string;\n /**\n * Output ceiling sent with every request from this agent. Resolved once from the model's\n * catalog override, else DEFAULT_MAX_OUTPUT_TOKENS. Callers needing more room raise it\n * after construction (see story generation), the same way gameId/userId are assigned —\n * so subclasses must read it when building a request, never snapshot it at construction.\n */\n maxOutputTokens: number;\n /**\n * Reasoning-depth knobs, resolved once from the catalog like maxOutputTokens and, like it,\n * overridable per instance for calls whose profile differs from a turn (story generation\n * runs deeper). Each provider speaks one dialect — effort (DeepSeek, GLM, Gemini, Claude\n * adaptive) or a token budget (Qwen, Claude Haiku) — and reads only the field it\n * understands; the other is ignored. Subclasses read these when building a request.\n */\n reasoningEffort?: ReasoningEffort;\n thinkingBudgetTokens?: number;\n protected readonly instruction: string;\n /**\n * The instruction split on CACHE_TIER_MARKER: [shared static tier, per-bot tier].\n * Length 1 when the prompt has no marker (GM prompts, tests). Providers with\n * explicit cache breakpoints (Anthropic) place one per part; everyone else uses\n * the joined marker-free `instruction`, whose shared prefix implicit caches match.\n */\n protected readonly instructionParts: string[];\n protected readonly temperature: number;\n protected readonly model: string;\n protected readonly enableThinking: boolean;\n protected readonly agentLoggingConfig: AgentLoggingConfig;\n\n protected constructor(\n name: string,\n instruction: string,\n model: string,\n temperature: number,\n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n this.name = name;\n this.instructionParts = instruction\n .split(CACHE_TIER_MARKER)\n .filter(part => part.trim().length > 0);\n this.instruction = this.instructionParts.join('\\n\\n');\n this.temperature = temperature;\n this.model = model;\n this.enableThinking = enableThinking;\n this.agentLoggingConfig = agentLoggingConfig;\n const modelConfig = getModelConfigByApiName(model);\n this.maxOutputTokens = modelConfig?.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;\n this.reasoningEffort = modelConfig?.reasoningEffort;\n this.thinkingBudgetTokens = modelConfig?.thinkingBudgetTokens;\n }\n\n /**\n * Public ask API — template methods that time the provider call and stamp `durationMs`\n * into the returned TokenUsage. Subclasses implement doAskWithZodSchema/doAskText and\n * must NOT override these.\n */\n async askWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n const startedAt = Date.now();\n try {\n const [result, thinking, usage, signature] = await this.doAskWithZodSchema(zodSchema, messages);\n return [result, thinking, this.stampDuration(usage, startedAt), signature];\n } catch (error) {\n this.stampErrorDuration(error, startedAt);\n throw error;\n }\n }\n\n async askText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n const startedAt = Date.now();\n try {\n const [content, thinking, usage, signature] = await this.doAskText(messages);\n return [content, thinking, this.stampDuration(usage, startedAt), signature];\n } catch (error) {\n this.stampErrorDuration(error, startedAt);\n throw error;\n }\n }\n\n private stampDuration(usage: TokenUsage | undefined, startedAt: number): TokenUsage | undefined {\n return usage ? { ...usage, durationMs: Date.now() - startedAt } : usage;\n }\n\n /** Failed calls carry their duration too — a 35s provider stall that errors is still signal. */\n private stampErrorDuration(error: unknown, startedAt: number): void {\n if (error && typeof error === 'object') {\n (error as { durationMs?: number }).durationMs = Date.now() - startedAt;\n }\n }\n\n protected abstract doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]>;\n\n /**\n * Plain-text ask: no schema appended to the prompt, no JSON mode, no parsing.\n * Returns [content, thinkingContent, tokenUsage?, thinkingSignature?] — same tuple\n * shape as doAskWithZodSchema but with the raw response string as content.\n * Implementations must throw on empty content so the recoverable-error/retry UX\n * is preserved (errors surface in the UI; the user triggers retries).\n */\n protected abstract doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]>;\n\n protected logger(message: string): void {\n console.log(`[${this.name} ${this.model}]: ${message}`);\n }\n\n protected logAsking(messages: AIMessage[]): void {\n this.logger(\"==================================================\");\n this.logger(`Asking ${this.name} ${this.model} agent`);\n this.logger(\"==================================================\");\n \n logger.agentActivity(this.name, this.model, 'REQUEST', {\n gameId: this.gameId,\n userId: this.userId,\n systemPrompt: this.instruction,\n history: messages,\n command: messages.length > 0 ? messages[messages.length - 1].content : undefined\n }, this.agentLoggingConfig);\n }\n\n protected logSystemPrompt(): void {\n // No longer needed as it's included in logAsking's structured log\n // Keeping it for backward compatibility with subclasses that might call it\n }\n\n protected logMessages(messages: AIMessage[]): void {\n // Console logging still useful for local dev\n this.logger(`History for ${this.name}:`);\n messages.forEach((msg, index) => {\n const preview = msg.content.length > 1000 ? msg.content.substring(0, 1000) + '...' : msg.content;\n this.logger(` ${index + 1}. [${msg.role}]: ${preview}`);\n });\n }\n\n protected logReply(reply: any, thinking?: string, usage?: TokenUsage): void {\n const replyStr = typeof reply === 'string' ? reply : JSON.stringify(reply);\n \n // Console logging\n this.logger(`Reply from ${this.name}:`);\n if (thinking) {\n const thinkingPreview = thinking.length > 500 ? thinking.substring(0, 500) + '...' : thinking;\n this.logger(` [thinking]: ${thinkingPreview}`);\n }\n const preview = replyStr.length > 1000 ? replyStr.substring(0, 1000) + '...' : replyStr;\n this.logger(` [assistant]: ${preview}`);\n\n logger.agentActivity(this.name, this.model, 'RESPONSE', {\n gameId: this.gameId,\n userId: this.userId,\n reply,\n thinking,\n usage\n }, this.agentLoggingConfig);\n }\n\n\n /**\n * Merges consecutive user messages (e.g. a GM command followed by the detached\n * reminder postfix) into one, for providers that expect alternating roles — this\n * reproduces the pre-detachment request shape. ClaudeAgent overrides this to keep\n * them separate: Anthropic combines consecutive user turns into one turn but keeps\n * distinct content blocks, which lets its fast cache breakpoint sit on the persisted\n * command block while the throwaway reminder rides behind it.\n */\n protected prepareMessages(messages: AIMessage[]): AIMessage[] {\n const result: AIMessage[] = [];\n for (const msg of messages) {\n const prev = result[result.length - 1];\n if (prev && prev.role === 'user' && msg.role === 'user') {\n result[result.length - 1] = { ...prev, content: `${prev.content}\\n\\n${msg.content}` };\n } else {\n result.push(msg);\n }\n }\n return result;\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport OpenAI from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { calculateOpenAICost } from \"../pricing\";\nimport { z } from 'zod';\nimport { zodTextFormat } from 'openai/helpers/zod';\n\nexport class Gpt5Agent extends AbstractAgent {\n private readonly client: OpenAI;\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from OpenAI API',\n invalidFormat: 'Invalid response format from OpenAI API',\n apiError: (error: unknown) =>\n `Failed to get response from OpenAI API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n\n constructor(\n name: string, \n instruction: string, \n model: string, \n apiKey: string, \n temperature: number, \n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n apiKey: apiKey,\n });\n }\n\n\n /**\n * Structured output method using Zod with OpenAI's Responses API\n * This provides better schema handling and runtime validation\n * \n * Uses responses.parse for models that support structured outputs\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n this.logAsking(messages);\n this.logMessages(messages);\n\n // Combine system instruction with messages for the input\n const input = [\n `System: ${this.instruction}`,\n ...this.prepareMessages(messages).map(msg => `${msg.role === 'user' ? 'User' : 'Assistant'}: ${msg.content}`)\n ].join('\\n\\n');\n\n // Extend schema with thinking field if enabled\n let schemaToSend: z.ZodSchema<any> = zodSchema;\n if (this.enableThinking && zodSchema instanceof z.ZodObject) {\n schemaToSend = zodSchema.extend({\n thinking: z.string().describe(\"Your internal chain-of-thought reasoning process used to arrive at the final answer.\")\n });\n }\n\n const response = await this.client.responses.parse({\n model: this.model,\n instructions: this.instruction,\n input: input,\n max_output_tokens: this.maxOutputTokens,\n text: {\n format: zodTextFormat(schemaToSend, \"response_schema\"),\n }\n });\n\n if (!response.output_parsed) {\n this.logger(`Parsing failed. Raw content: ${response.output_text}`);\n throw new Error(this.errorMessages.invalidFormat);\n }\n\n // Extract reasoning content from output if available\n let reasoningContent = \"\";\n if (this.enableThinking && (response.output_parsed as any).thinking) {\n reasoningContent = (response.output_parsed as any).thinking;\n }\n\n // Extract token usage\n let tokenUsage: TokenUsage | undefined;\n if (response.usage) {\n // Responses API reports cache hits under input_tokens_details.cached_tokens\n // (input_tokens already INCLUDES them); bill hits at the cached rate.\n const cachedTokens = (response.usage as any).input_tokens_details?.cached_tokens ?? 0;\n const cost = calculateOpenAICost(\n this.model,\n response.usage.input_tokens,\n response.usage.output_tokens,\n cachedTokens\n );\n if (cachedTokens > 0) {\n this.logger(`💾 Prompt cache: ${cachedTokens} of ${response.usage.input_tokens} input tokens served from cache`);\n }\n\n tokenUsage = {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens || 0,\n costUSD: cost,\n ...(response.usage.output_tokens_details?.reasoning_tokens ? { reasoningTokens: response.usage.output_tokens_details.reasoning_tokens } : {}),\n ...(response.usage.input_tokens_details?.cached_tokens ? { cachedInputTokens: response.usage.input_tokens_details.cached_tokens } : {})\n };\n\n // Log reasoning token breakdown if available\n if (response.usage.output_tokens_details?.reasoning_tokens) {\n const reasoningTokens = response.usage.output_tokens_details.reasoning_tokens;\n const finalAnswerTokens = tokenUsage.outputTokens - reasoningTokens;\n this.logger(`Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`);\n }\n }\n\n if (response.output_parsed) {\n this.logReply(response.output_parsed, reasoningContent, tokenUsage);\n }\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n return [response.output_parsed, reasoningContent, tokenUsage];\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask via the Responses API: no structured-output format, raw output_text.\n * Note: askWithZodSchema surfaces \"thinking\" via a schema-injected field; that trick\n * doesn't apply to plain text, so thinking content is empty here (OpenAI does not\n * expose chain-of-thought directly).\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n this.logAsking(messages);\n this.logMessages(messages);\n\n // Combine system instruction with messages for the input\n const input = [\n `System: ${this.instruction}`,\n ...this.prepareMessages(messages).map(msg => `${msg.role === 'user' ? 'User' : 'Assistant'}: ${msg.content}`)\n ].join('\\n\\n');\n\n const response = await this.client.responses.create({\n model: this.model,\n instructions: this.instruction,\n input: input,\n max_output_tokens: this.maxOutputTokens,\n });\n\n const content = response.output_text;\n if (!content) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Extract token usage\n let tokenUsage: TokenUsage | undefined;\n if (response.usage) {\n // Responses API reports cache hits under input_tokens_details.cached_tokens\n // (input_tokens already INCLUDES them); bill hits at the cached rate.\n const cachedTokens = (response.usage as any).input_tokens_details?.cached_tokens ?? 0;\n const cost = calculateOpenAICost(\n this.model,\n response.usage.input_tokens,\n response.usage.output_tokens,\n cachedTokens\n );\n if (cachedTokens > 0) {\n this.logger(`💾 Prompt cache: ${cachedTokens} of ${response.usage.input_tokens} input tokens served from cache`);\n }\n\n tokenUsage = {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens || 0,\n costUSD: cost,\n ...(response.usage.output_tokens_details?.reasoning_tokens ? { reasoningTokens: response.usage.output_tokens_details.reasoning_tokens } : {}),\n ...(response.usage.input_tokens_details?.cached_tokens ? { cachedInputTokens: response.usage.input_tokens_details.cached_tokens } : {})\n };\n\n if (response.usage.output_tokens_details?.reasoning_tokens) {\n const reasoningTokens = response.usage.output_tokens_details.reasoning_tokens;\n const finalAnswerTokens = tokenUsage.outputTokens - reasoningTokens;\n this.logger(`Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`);\n }\n }\n\n this.logReply(content, \"\", tokenUsage);\n\n return [content, \"\", tokenUsage];\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n}","import { ModelError, ModelRefusalError } from \"../errors\";\nimport { toAnthropicEffort } from \"../reasoning-effort\";\nimport { AbstractAgent } from \"./abstract-agent\";\nimport { AIMessage, BotResponseError, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { Anthropic } from '@anthropic-ai/sdk';\nimport { calculateAnthropicCost } from \"../pricing\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\ntype AnthropicRole = 'user' | 'assistant';\n\n// Content block types for thinking-enabled messages\ninterface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n signature?: string; // Required for Claude 4+ multi-turn conversations\n}\n\ninterface TextBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n}\n\ntype ContentBlock = ThinkingBlock | TextBlock;\n\ninterface AnthropicMessage {\n role: AnthropicRole;\n content: string | ContentBlock[];\n}\n\nexport class ClaudeAgent extends AbstractAgent {\n private readonly client: Anthropic;\n // System-prompt breakpoints, one per cache tier (see CACHE_TIER_MARKER):\n // block 1 — shared static rules, byte-identical across all bots and games with the\n // same rule set, so one org-level entry serves everyone and ANY bot's call\n // refreshes its TTL;\n // block 2 — per-bot identity + game state + summaries, byte-stable from the start of\n // a game day through the end of its night (deaths/role knowledge/summaries\n // only change in startNewDay), so every call within a day reads it.\n // GM prompts have no marker → single block, same behavior as before. Haiku 4.5 needs a\n // 4096-token cacheable prefix, so tiers below that silently no-op on Haiku — expected.\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n private get defaultParams(): Omit<Anthropic.MessageCreateParams, 'messages'> {\n return {\n max_tokens: this.maxOutputTokens,\n system: this.instructionParts.map(part => (\n { type: 'text' as const, text: part, cache_control: { type: 'ephemeral' as const } }\n )),\n model: this.model,\n };\n }\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty response from Anthropic API',\n invalidFormat: 'Invalid response format from Anthropic API',\n apiError: (error: unknown) =>\n `Failed to get response from Anthropic API: ${error instanceof Error ? error.message : String(error)}`,\n unsupportedRole: (role: string) => `Unsupported role type: ${role}`,\n };\n\n\n constructor(\n name: string, \n instruction: string, \n model: string, \n apiKey: string, \n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, 0.2, enableThinking, agentLoggingConfig);\n this.client = new Anthropic({\n apiKey: apiKey,\n });\n }\n\n\n\n /**\n * Unlike the base class, does NOT merge consecutive user messages: the Messages API\n * combines consecutive user turns into a single turn while preserving separate content\n * blocks, so the trailing reminder stays out of the persisted command block and the\n * fast cache breakpoint (see applyCacheBreakpoint) lands on bytes that repeat.\n */\n protected prepareMessages(messages: AIMessage[]): AIMessage[] {\n return messages;\n }\n\n private convertToAnthropicMessages(messages: AIMessage[]): AnthropicMessage[] {\n return messages.map(msg => ({\n role: this.convertRole(msg.role),\n content: msg.content\n }));\n }\n\n /**\n * Converts messages for thinking-enabled requests.\n * Assistant messages include thinking blocks ONLY if they have valid signatures.\n * If a signature is missing, the thinking block is dropped to ensure API validity.\n */\n private convertToAnthropicMessagesWithThinking(messages: AIMessage[]): AnthropicMessage[] {\n // Track thinking stats for aggregated logging\n let assistantMsgCount = 0;\n let withThinking = 0;\n let withValidAnthropicSig = 0;\n let droppedGoogleSig = 0;\n let droppedNoSig = 0;\n\n const result = messages.map(msg => {\n const role = this.convertRole(msg.role);\n\n if (role === 'assistant') {\n assistantMsgCount++;\n\n if (msg.thinking && msg.anthropicThinkingSignature) {\n withThinking++;\n withValidAnthropicSig++;\n const thinkingBlock: ThinkingBlock = {\n type: 'thinking',\n thinking: msg.thinking,\n signature: msg.anthropicThinkingSignature\n };\n const contentBlocks: ContentBlock[] = [\n thinkingBlock,\n { type: 'text', text: msg.content }\n ];\n return { role, content: contentBlocks };\n }\n\n // Track dropped thinking\n if (msg.thinking) {\n withThinking++;\n if (msg.googleThoughtSignature) {\n droppedGoogleSig++;\n } else {\n droppedNoSig++;\n }\n }\n\n // Fallback for text-only messages or messages with missing signatures\n return { role, content: msg.content };\n }\n\n // User messages remain as simple strings\n return { role, content: msg.content };\n });\n\n // Log aggregated thinking stats once\n if (withThinking > 0) {\n const dropped = droppedGoogleSig + droppedNoSig;\n let dropReason = '';\n if (droppedGoogleSig > 0) dropReason += `${droppedGoogleSig} with Google signature`;\n if (droppedNoSig > 0) dropReason += `${droppedNoSig > 0 && droppedGoogleSig > 0 ? ', ' : ''}${droppedNoSig} without signature`;\n\n this.logger(`📊 Thinking history: ${assistantMsgCount} assistant msgs, ${withThinking} with thinking, ` +\n `${withValidAnthropicSig} included, ${dropped} dropped${dropped > 0 ? ` (${dropReason})` : ''}`);\n }\n\n return result;\n }\n\n /**\n * Breakpoint 2 (fast tier): the last message that will be re-sent byte-identically on\n * the next request. That is the SECOND-to-last message, not the last one — the final\n * user message carries unpersisted content (the reminder postfix / schema description)\n * appended to the GM command, so its bytes never repeat and a breakpoint there would be\n * a pure 1.25x write tax with no reads. The second-to-last message (the bot's previous\n * reply, or an earlier flushed block) reappears verbatim next turn, where the moved-\n * forward breakpoint finds it via the 20-block lookback.\n *\n * NOT the top-level auto-caching mode: that mode targets the LAST cacheable block,\n * which for us is exactly the never-repeated tail — every entry it wrote would be dead.\n */\n private applyCacheBreakpoint(messages: AnthropicMessage[]): void {\n if (messages.length < 2) {\n return; // one-shot call: system-prompt breakpoint still applies\n }\n const anchor = messages[messages.length - 2];\n if (typeof anchor.content === 'string') {\n if (anchor.content.length > 0) {\n anchor.content = [{ type: 'text', text: anchor.content, cache_control: { type: 'ephemeral' } }];\n }\n return;\n }\n // Thinking blocks are not cacheable — mark the last text block instead.\n for (let i = anchor.content.length - 1; i >= 0; i--) {\n const block = anchor.content[i];\n if (block.type === 'text' && block.text.length > 0) {\n block.cache_control = { type: 'ephemeral' };\n return;\n }\n }\n }\n\n /**\n * Builds TokenUsage from the response. Anthropic's input_tokens EXCLUDES cached tokens\n * (total prompt = input_tokens + cache_read + cache_creation), unlike the OpenAI-shaped\n * providers whose prompt_tokens include them — so reconstruct the full prompt size here\n * before pricing. Cache reads bill at the cacheHitPrice (~0.1x); cache writes bill at\n * 1.25x input, which MODEL_PRICING doesn't model, so written tokens are priced at the\n * plain input rate (~20% undercount on the written span only).\n */\n private buildTokenUsage(usage: Anthropic.Messages.Usage): TokenUsage {\n const cacheReadTokens = usage.cache_read_input_tokens ?? 0;\n const cacheWriteTokens = usage.cache_creation_input_tokens ?? 0;\n const uncachedInputTokens = usage.input_tokens || 0;\n const inputTokens = uncachedInputTokens + cacheReadTokens + cacheWriteTokens;\n const outputTokens = usage.output_tokens || 0;\n const cost = calculateAnthropicCost(this.model, inputTokens, outputTokens, cacheReadTokens);\n\n if (cacheReadTokens > 0 || cacheWriteTokens > 0) {\n this.logger(`💾 Prompt cache: ${cacheReadTokens} read, ${cacheWriteTokens} written, ${uncachedInputTokens} uncached`);\n }\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: cost,\n // Cache reads only — writes are a billing premium, not reuse of prior context.\n ...(cacheReadTokens > 0 ? { cachedInputTokens: cacheReadTokens } : {})\n };\n }\n\n private convertRole(role: string): AnthropicRole {\n if (role === 'system' || role === 'user') {\n return 'user';\n }\n if (role === 'assistant') {\n return 'assistant';\n }\n throw new Error(this.errorMessages.unsupportedRole(role));\n }\n\n /**\n * New method using Zod with Anthropic's Claude API\n * Since Anthropic doesn't support native JSON schemas, we generate prompt descriptions\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n // Validate roles first, before entering the main try-catch block\n const aiMessages = this.prepareMessages(messages);\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n try {\n // Generate human-readable schema description for Anthropic\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n\n // Add schema instructions to the last message\n const lastMessage = aiMessages[aiMessages.length - 1];\n const fullPrompt = `${lastMessage.content}\\n\\n${schemaDescription}`;\n\n // Update the last AI message with schema instructions before conversion\n const messagesWithSchema = [...aiMessages];\n messagesWithSchema[messagesWithSchema.length - 1] = {\n ...lastMessage,\n content: fullPrompt\n };\n\n // Use thinking if enabled for this agent\n const canUseThinking = this.enableThinking;\n\n // Convert messages - use thinking-aware conversion when thinking can be used\n const anthropicMessages = canUseThinking\n ? this.convertToAnthropicMessagesWithThinking(messagesWithSchema)\n : this.convertToAnthropicMessages(messagesWithSchema);\n this.applyCacheBreakpoint(anthropicMessages);\n\n const params: Anthropic.MessageCreateParams = {\n ...this.defaultParams,\n messages: anthropicMessages as Anthropic.MessageParam[],\n };\n\n // Add thinking config for Anthropic models with thinking mode.\n // Fable 5, Opus 4.8 and Sonnet 5 use adaptive thinking and reject the temperature param\n // (and budget_tokens) — Haiku 4.5 still uses enabled thinking with a budget.\n // Fable 5's thinking is always on: it has no non-thinking variant and rejects\n // thinking:{type:\"disabled\"}, so it only ever hits the adaptive branch below.\n const usesAdaptiveThinking = this.model.includes('fable')\n || this.model.includes('opus') || this.model.includes('sonnet');\n if (canUseThinking) {\n if (usesAdaptiveThinking) {\n // Fable 5 / Opus 4.8 / Sonnet 5: adaptive thinking with effort control.\n // display: \"summarized\" is required to surface the reasoning — these models\n // default to \"omitted\", which returns thinking blocks with an empty field.\n (params as any).thinking = { type: \"adaptive\", display: \"summarized\" };\n (params as any).output_config = { effort: toAnthropicEffort(this.reasoningEffort ?? \"high\") };\n } else {\n // Haiku 4.5 uses enabled thinking with budget\n (params as any).thinking = { type: \"enabled\", budget_tokens: this.thinkingBudgetTokens ?? 1024 };\n params.temperature = 1;\n }\n } else if (usesAdaptiveThinking) {\n // Opus 4.8 / Sonnet 5 reject a non-default temperature. Sonnet 5 also defaults to\n // adaptive thinking when `thinking` is omitted, so disable it explicitly to keep the\n // non-thinking variant from reasoning (avoiding extra thinking cost and latency).\n (params as any).thinking = { type: \"disabled\" };\n } else {\n // Older models (Haiku 4.5): no adaptive thinking; pass the configured temperature.\n params.temperature = this.temperature;\n }\n\n let response;\n try {\n response = await this.client.messages.create(params);\n } catch (apiError) {\n // Re-throw API errors immediately without wrapping them in schema validation errors\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n if ((response as any).stop_reason === 'refusal') {\n throw new ModelRefusalError(this.model);\n }\n if (!('content' in response) || !Array.isArray(response.content) || response.content.length === 0) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Handle thinking content if present and find text content\n let textContent = null;\n let thinkingContent = \"\";\n let anthropicThinkingSignature = \"\";\n\n for (const block of response.content) {\n // Extract thinking content and signature\n if (this.enableThinking && (block as any).type === 'thinking' && 'thinking' in block) {\n thinkingContent = (block as any).thinking;\n // Extract signature if present (required for Claude 4+ multi-turn)\n if ('signature' in block) {\n anthropicThinkingSignature = (block as any).signature;\n }\n }\n\n // Find the text content block\n if ('text' in block && !textContent) {\n textContent = block.text;\n }\n }\n\n if (!textContent) {\n throw new Error(this.errorMessages.invalidFormat);\n }\n\n // Parse and validate the response using the shared lenient parser\n const parsedData = parseAndValidateLlmJson(textContent, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n // Extract token usage information\n let tokenUsage: TokenUsage | undefined;\n if (response.usage) {\n tokenUsage = this.buildTokenUsage(response.usage);\n\n // Log thinking information if available\n if (this.enableThinking && thinkingContent) {\n this.logger(`Thinking enabled: ${thinkingContent.length} characters of thinking content`);\n this.logger(`Note: Thinking tokens are included in output token count and cost`);\n }\n }\n\n if (parsedData) {\n this.logReply(parsedData, thinkingContent || undefined, tokenUsage);\n }\n\n return [parsedData, thinkingContent, tokenUsage, anthropicThinkingSignature || undefined];\n\n } catch (error) {\n // Typed model errors carry their own meaning (a refusal is not retryable and not\n // an API failure) — let them through untouched, as GoogleAgent does with its\n // ModelError family.\n if (error instanceof ModelError) {\n throw error;\n }\n const errorDetails = error instanceof Error ? error.message : String(error);\n\n // Check if this is an API overload error (529) which is recoverable\n const isRecoverable = errorDetails.includes('overloaded_error') ||\n errorDetails.includes('529') ||\n errorDetails.includes('rate_limit');\n\n throw new BotResponseError(\n 'Failed to get response from Anthropic API with Zod schema',\n errorDetails,\n {\n model: this.model,\n agentName: this.name,\n apiProvider: 'Anthropic',\n schemaType: 'zod'\n },\n isRecoverable\n );\n }\n }\n\n /**\n * Plain-text ask: same request as askWithZodSchema but without a schema description\n * appended to the prompt and without JSON parsing. Thinking blocks and signatures\n * are extracted identically.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n const aiMessages = this.prepareMessages(messages);\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n try {\n const canUseThinking = this.enableThinking;\n\n const anthropicMessages = canUseThinking\n ? this.convertToAnthropicMessagesWithThinking(aiMessages)\n : this.convertToAnthropicMessages(aiMessages);\n this.applyCacheBreakpoint(anthropicMessages);\n\n const params: Anthropic.MessageCreateParams = {\n ...this.defaultParams,\n messages: anthropicMessages as Anthropic.MessageParam[],\n };\n\n // Add thinking config for Anthropic models with thinking mode.\n // Fable 5, Opus 4.8 and Sonnet 5 use adaptive thinking and have deprecated the temperature\n // param (and budget_tokens). Fable 5's thinking is always on: it rejects\n // thinking:{type:\"disabled\"}, so it only ever hits the adaptive branch below.\n const usesAdaptiveThinking = this.model.includes('fable')\n || this.model.includes('opus') || this.model.includes('sonnet');\n if (canUseThinking) {\n if (usesAdaptiveThinking) {\n (params as any).thinking = { type: \"adaptive\", display: \"summarized\" };\n (params as any).output_config = { effort: toAnthropicEffort(this.reasoningEffort ?? \"high\") };\n } else {\n (params as any).thinking = { type: \"enabled\", budget_tokens: this.thinkingBudgetTokens ?? 1024 };\n params.temperature = 1;\n }\n } else if (usesAdaptiveThinking) {\n // Opus 4.8 / Sonnet 5 reject a non-default temperature and default to adaptive\n // thinking when `thinking` is omitted; disable it explicitly for the non-thinking variant.\n (params as any).thinking = { type: \"disabled\" };\n } else {\n // Older models (Haiku 4.5): no adaptive thinking; pass the configured temperature.\n params.temperature = this.temperature;\n }\n\n let response;\n try {\n response = await this.client.messages.create(params);\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n if ((response as any).stop_reason === 'refusal') {\n throw new ModelRefusalError(this.model);\n }\n if (!('content' in response) || !Array.isArray(response.content) || response.content.length === 0) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Extract thinking and concatenate all text blocks\n const textParts: string[] = [];\n let thinkingContent = \"\";\n let anthropicThinkingSignature = \"\";\n\n for (const block of response.content) {\n if (this.enableThinking && (block as any).type === 'thinking' && 'thinking' in block) {\n thinkingContent = (block as any).thinking;\n if ('signature' in block) {\n anthropicThinkingSignature = (block as any).signature;\n }\n }\n\n if ('text' in block) {\n textParts.push(block.text);\n }\n }\n\n const textContent = textParts.join('');\n if (!textContent) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n let tokenUsage: TokenUsage | undefined;\n if (response.usage) {\n tokenUsage = this.buildTokenUsage(response.usage);\n\n if (this.enableThinking && thinkingContent) {\n this.logger(`Thinking enabled: ${thinkingContent.length} characters of thinking content`);\n this.logger(`Note: Thinking tokens are included in output token count and cost`);\n }\n }\n\n this.logReply(textContent, thinkingContent || undefined, tokenUsage);\n\n return [textContent, thinkingContent, tokenUsage, anthropicThinkingSignature || undefined];\n\n } catch (error) {\n // Typed model errors carry their own meaning (a refusal is not retryable and not\n // an API failure) — let them through untouched, as GoogleAgent does with its\n // ModelError family.\n if (error instanceof ModelError) {\n throw error;\n }\n const errorDetails = error instanceof Error ? error.message : String(error);\n\n const isRecoverable = errorDetails.includes('overloaded_error') ||\n errorDetails.includes('529') ||\n errorDetails.includes('rate_limit');\n\n throw new BotResponseError(\n 'Failed to get response from Anthropic API',\n errorDetails,\n {\n model: this.model,\n agentName: this.name,\n apiProvider: 'Anthropic',\n schemaType: 'text'\n },\n isRecoverable\n );\n }\n }\n}\n","import { toGeminiEffort } from '../reasoning-effort';\nimport { AbstractAgent } from \"./abstract-agent\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { GoogleGenAI, Type } from \"@google/genai\";\nimport { parseAndValidateLlmJson } from '../json-response-parser';\nimport { ModelOverloadError, ModelRateLimitError, ModelUnavailableError, ModelAuthenticationError, ModelQuotaExceededError } from \"../errors\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { calculateGoogleCost } from '../pricing/google-pricing';\n\ntype GoogleRole = 'model' | 'user';\n\n// Define types for the new Google GenAI SDK\ninterface Part {\n text: string;\n thought?: boolean; // Indicates this is a thinking part\n thoughtSignature?: string; // Encrypted signature for multi-turn thinking\n}\n\ninterface Content {\n role: GoogleRole;\n parts: Part[];\n}\n\nexport class GoogleAgent extends AbstractAgent {\n private readonly client: GoogleGenAI;\n private readonly defaultConfig = {\n responseMimeType: \"application/json\"\n };\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty response from Google API - check logs for detailed response info',\n invalidFormat: 'Invalid response format from Google API',\n apiError: (error: unknown) =>\n `Failed to get response from Google API: ${error instanceof Error ? error.message : String(error)}`,\n unsupportedRole: (role: string) => `Unsupported role type: ${role}`,\n };\n\n\n constructor(\n name: string, \n instruction: string, \n model: string, \n apiKey: string, \n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, 0.2, enableThinking, agentLoggingConfig);\n this.client = new GoogleGenAI({\n apiKey: apiKey\n });\n }\n\n private convertToContents(rawMessages: AIMessage[]): Content[] {\n const messages = this.prepareMessages(rawMessages);\n try {\n // Track thinking stats for aggregated logging\n let assistantMsgCount = 0;\n let withThinking = 0;\n let withValidGoogleSig = 0;\n let droppedAnthropicSig = 0;\n let droppedNoSig = 0;\n\n const contents = messages.map(msg => {\n const role = this.convertRole(msg.role);\n const parts: Part[] = [];\n\n if (role === 'model') {\n assistantMsgCount++;\n\n // Only include thinking if we have a valid Google signature\n // (don't use thinking from other providers like Anthropic)\n if (msg.thinking && msg.googleThoughtSignature) {\n withThinking++;\n withValidGoogleSig++;\n parts.push({\n text: msg.thinking,\n thought: true\n });\n\n // Attach signature to the response part\n const responsePart: Part = { text: msg.content };\n responsePart.thoughtSignature = msg.googleThoughtSignature;\n parts.push(responsePart);\n } else {\n // Track dropped thinking\n if (msg.thinking) {\n withThinking++;\n if (msg.anthropicThinkingSignature) {\n droppedAnthropicSig++;\n } else {\n droppedNoSig++;\n }\n }\n\n // Just include the text content\n parts.push({ text: msg.content });\n }\n } else {\n // Regular turn or user turn\n parts.push({ text: msg.content });\n }\n\n return {\n role: role,\n parts: parts\n };\n });\n\n // Log aggregated thinking stats once\n if (withThinking > 0) {\n const dropped = droppedAnthropicSig + droppedNoSig;\n let dropReason = '';\n if (droppedAnthropicSig > 0) dropReason += `${droppedAnthropicSig} with Anthropic signature`;\n if (droppedNoSig > 0) dropReason += `${droppedNoSig > 0 && droppedAnthropicSig > 0 ? ', ' : ''}${droppedNoSig} without signature`;\n\n this.logger(`📊 Thinking history: ${assistantMsgCount} assistant msgs, ${withThinking} with thinking, ` +\n `${withValidGoogleSig} included, ${dropped} dropped${dropped > 0 ? ` (${dropReason})` : ''}`);\n }\n\n return contents;\n } catch (error) {\n throw error;\n }\n }\n\n private convertRole(role: string): GoogleRole {\n if (role === 'assistant') {\n return 'model';\n }\n if (role === 'user' || role === 'system') {\n return 'user';\n }\n throw new Error(this.errorMessages.unsupportedRole(role));\n }\n\n private calculateCost(inputTokens: number, outputTokens: number, totalTokens: number): number {\n const contextTokens = this.deriveContextTokens(inputTokens, outputTokens, totalTokens);\n\n return calculateGoogleCost(this.model, inputTokens, outputTokens, {\n contextTokens,\n totalTokens\n });\n }\n\n private calculateCostWithCacheHits(inputTokens: number, outputTokens: number, totalTokens: number, cacheHitTokens: number): number {\n const contextTokens = this.deriveContextTokens(inputTokens, outputTokens, totalTokens);\n\n return calculateGoogleCost(this.model, inputTokens, outputTokens, {\n contextTokens,\n totalTokens,\n cacheHitTokens\n });\n }\n\n private deriveContextTokens(inputTokens: number, outputTokens: number, totalTokens: number): number {\n if (!totalTokens) {\n return inputTokens;\n }\n\n const promptAndReasoningTokens = Math.max(totalTokens - outputTokens, 0);\n return Math.max(inputTokens, promptAndReasoningTokens);\n }\n\n /**\n * New method using Zod with Google's Gemini API\n * This provides better schema handling and runtime validation\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n // Google's thinking API doesn't require signature validation like Anthropic\n // Google models decide internally whether to use thinking\n // We simply enable the thinking config if the agent has thinking enabled\n\n // Convert messages using simple conversion (Google handles thinking internally)\n const contents = this.convertToContents(messages);\n\n try {\n // Convert Zod schema to Google-compatible format using Type constants\n const googleSchema = ZodSchemaConverter.toGoogleSchema(zodSchema);\n\n const config: any = {\n temperature: this.temperature,\n responseMimeType: \"application/json\",\n responseSchema: googleSchema,\n maxOutputTokens: this.maxOutputTokens,\n systemInstruction: this.instruction\n };\n\n // Add thinking config for Google models with thinking mode.\n // Gemini 3.x effort dialect: thinkingLevel is a CEILING on an always-dynamic\n // process (the model still scales actual depth per request; \"high\" = fully open\n // range). Replaces the legacy 2.5-era thinkingBudget — which did transmit and\n // bind under SDK 1.x, but is deprecated for Gemini 3; needs SDK >=2.x, where\n // thinkingLevel is typed (1.x stripped it — verified 2026-08-06 by probe).\n // Level comes from the model config reasoningEffort, sent uppercase.\n if (this.enableThinking) {\n config.thinkingConfig = {\n includeThoughts: true,\n thinkingLevel: toGeminiEffort(this.reasoningEffort ?? 'low').toUpperCase()\n };\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let response;\n try {\n response = await this.client.models.generateContent({\n model: this.model,\n contents: contents,\n config: config\n });\n } catch (apiError) {\n // Re-throw API errors immediately without wrapping them in schema validation errors\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n // Handle thinking content and signature if present\n let thinkingContent = \"\";\n let googleThoughtSignature = \"\";\n if (this.enableThinking && (response as any).candidates?.[0]?.content?.parts) {\n const parts = (response as any).candidates[0].content.parts;\n const thinkingParts: string[] = [];\n\n for (const part of parts) {\n // Handle thinking content\n if (part.thought && part.text) {\n thinkingParts.push(part.text);\n }\n\n // Check for thoughtSignature in ANY part (it often comes with the final response, not the thought part)\n if (part.thoughtSignature) {\n googleThoughtSignature = part.thoughtSignature;\n } else if (part.thought_signature) {\n googleThoughtSignature = part.thought_signature;\n } else if (part.signature) {\n googleThoughtSignature = part.signature;\n }\n }\n thinkingContent = thinkingParts.join('\\n');\n\n if (thinkingContent && !googleThoughtSignature) {\n this.logger(`⚠️ Thinking content received but no signature found in response`);\n }\n }\n\n // Extract token usage from response metadata\n const usageMetadata = (response as any).usageMetadata;\n let tokenUsage: TokenUsage | undefined;\n if (usageMetadata) {\n const inputTokens = usageMetadata.promptTokenCount || 0;\n // candidatesTokenCount is the visible reply only; Gemini bills thinking\n // tokens at the output rate too, so fold them into outputTokens.\n // reasoningTokens stays the breakdown inside outputTokens, per the\n // TokenUsage contract.\n const reasoningTokens = usageMetadata.thoughtsTokenCount || 0;\n const outputTokens = (usageMetadata.candidatesTokenCount || 0) + reasoningTokens;\n const totalTokens = usageMetadata.totalTokenCount || 0;\n const cacheHitTokens = usageMetadata.cachedContentTokenCount || 0;\n\n // Calculate cost using the pricing utility with cache hit tokens\n const costUSD = this.calculateCostWithCacheHits(inputTokens, outputTokens, totalTokens, cacheHitTokens);\n\n tokenUsage = {\n inputTokens,\n outputTokens,\n totalTokens,\n costUSD,\n ...(reasoningTokens > 0 ? { reasoningTokens } : {}),\n ...(cacheHitTokens > 0 ? { cachedInputTokens: cacheHitTokens } : {})\n };\n }\n\n this.logger(`Zod schema response received - hasText: ${!!response.text}, textLength: ${response.text ? response.text.length : 0}`);\n\n if (!response.text) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Parse and validate the response using the shared lenient parser\n // (handles Gemini's quoted-JSON-string quirk internally)\n const parsedData = parseAndValidateLlmJson(response.text, zodSchema, (m) => this.logger(m));\n\n if (parsedData) {\n this.logReply(parsedData, thinkingContent || undefined, tokenUsage);\n }\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n return [parsedData, thinkingContent, tokenUsage, googleThoughtSignature || undefined];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n\n // Check for specific Gemini API errors\n this.handleGeminiError(error);\n\n throw error;\n }\n }\n\n /**\n * Plain-text ask: same request as askWithZodSchema but without responseSchema /\n * responseMimeType, returning the raw text. Thinking parts and thought signatures\n * are extracted identically.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n const contents = this.convertToContents(messages);\n\n try {\n const config: any = {\n temperature: this.temperature,\n maxOutputTokens: this.maxOutputTokens,\n systemInstruction: this.instruction\n };\n\n // Add thinking config for Google models with thinking mode.\n // Gemini 3.x effort dialect: thinkingLevel is a CEILING on an always-dynamic\n // process (the model still scales actual depth per request; \"high\" = fully open\n // range). Replaces the legacy 2.5-era thinkingBudget — which did transmit and\n // bind under SDK 1.x, but is deprecated for Gemini 3; needs SDK >=2.x, where\n // thinkingLevel is typed (1.x stripped it — verified 2026-08-06 by probe).\n // Level comes from the model config reasoningEffort, sent uppercase.\n if (this.enableThinking) {\n config.thinkingConfig = {\n includeThoughts: true,\n thinkingLevel: toGeminiEffort(this.reasoningEffort ?? 'low').toUpperCase()\n };\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let response;\n try {\n response = await this.client.models.generateContent({\n model: this.model,\n contents: contents,\n config: config\n });\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n // Handle thinking content and signature if present\n let thinkingContent = \"\";\n let googleThoughtSignature = \"\";\n if (this.enableThinking && (response as any).candidates?.[0]?.content?.parts) {\n const parts = (response as any).candidates[0].content.parts;\n const thinkingParts: string[] = [];\n\n for (const part of parts) {\n if (part.thought && part.text) {\n thinkingParts.push(part.text);\n }\n\n // Check for thoughtSignature in ANY part (it often comes with the final response, not the thought part)\n if (part.thoughtSignature) {\n googleThoughtSignature = part.thoughtSignature;\n } else if (part.thought_signature) {\n googleThoughtSignature = part.thought_signature;\n } else if (part.signature) {\n googleThoughtSignature = part.signature;\n }\n }\n thinkingContent = thinkingParts.join('\\n');\n\n if (thinkingContent && !googleThoughtSignature) {\n this.logger(`⚠️ Thinking content received but no signature found in response`);\n }\n }\n\n // Extract token usage from response metadata\n const usageMetadata = (response as any).usageMetadata;\n let tokenUsage: TokenUsage | undefined;\n if (usageMetadata) {\n const inputTokens = usageMetadata.promptTokenCount || 0;\n // See the schema-path extraction above: fold billed thinking tokens\n // into outputTokens and keep the breakdown.\n const reasoningTokens = usageMetadata.thoughtsTokenCount || 0;\n const outputTokens = (usageMetadata.candidatesTokenCount || 0) + reasoningTokens;\n const totalTokens = usageMetadata.totalTokenCount || 0;\n const cacheHitTokens = usageMetadata.cachedContentTokenCount || 0;\n\n const costUSD = this.calculateCostWithCacheHits(inputTokens, outputTokens, totalTokens, cacheHitTokens);\n\n tokenUsage = {\n inputTokens,\n outputTokens,\n totalTokens,\n costUSD,\n ...(reasoningTokens > 0 ? { reasoningTokens } : {}),\n ...(cacheHitTokens > 0 ? { cachedInputTokens: cacheHitTokens } : {})\n };\n }\n\n this.logger(`Plain text response received - hasText: ${!!response.text}, textLength: ${response.text ? response.text.length : 0}`);\n\n if (!response.text) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n this.logReply(response.text, thinkingContent || undefined, tokenUsage);\n\n return [response.text, thinkingContent, tokenUsage, googleThoughtSignature || undefined];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n\n // Check for specific Gemini API errors\n this.handleGeminiError(error);\n\n throw error;\n }\n }\n\n /**\n * Handles Gemini API errors and throws appropriate specific exceptions\n * @param error - The error to handle\n */\n private handleGeminiError(error: unknown): void {\n let errorMessage = '';\n let errorCode: number | undefined;\n let errorStatus = '';\n\n // Extract error information from different error formats\n if (error && typeof error === 'object') {\n // Check if it's a standard Error object with message\n if ('message' in error) {\n errorMessage = String((error as any).message);\n }\n\n // Try to parse if the message contains JSON (Gemini API format)\n try {\n const parsed = JSON.parse(errorMessage);\n if (parsed.error) {\n errorMessage = parsed.error.message || errorMessage;\n errorCode = parsed.error.code;\n errorStatus = parsed.error.status;\n }\n } catch {\n // Not JSON, use the original message\n }\n } else if (typeof error === 'string') {\n // Try to parse JSON string directly\n try {\n const parsed = JSON.parse(error);\n if (parsed.error) {\n errorMessage = parsed.error.message || error;\n errorCode = parsed.error.code;\n errorStatus = parsed.error.status;\n }\n } catch {\n errorMessage = error;\n }\n }\n\n // Throw specific exceptions based on error content\n if (errorCode === 503 || errorStatus === 'UNAVAILABLE' ||\n errorMessage.includes('model is overloaded') ||\n errorMessage.includes('overloaded')) {\n throw new ModelOverloadError(\n errorMessage || 'Model is currently overloaded. Please try again later.',\n 'Gemini'\n );\n }\n\n if (errorCode === 429 || errorMessage.includes('rate limit') || errorMessage.includes('quota')) {\n throw new ModelRateLimitError(\n errorMessage || 'Rate limit exceeded for Gemini model.',\n 'Gemini'\n );\n }\n\n if (errorCode === 401 || errorCode === 403 || errorMessage.includes('authentication') || errorMessage.includes('unauthorized')) {\n throw new ModelAuthenticationError(\n errorMessage || 'Authentication failed for Gemini model.',\n 'Gemini'\n );\n }\n\n if (errorMessage.includes('quota exceeded') || errorMessage.includes('billing')) {\n throw new ModelQuotaExceededError(\n errorMessage || 'Quota exceeded for Gemini model.',\n 'Gemini'\n );\n }\n\n if (errorCode && errorCode >= 500) {\n throw new ModelUnavailableError(\n errorMessage || 'Gemini model is temporarily unavailable.',\n 'Gemini',\n 'server_error'\n );\n }\n\n // If no specific error type is detected, don't throw - let the method return null\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport { stableHashHex } from \"../text-utils\";\nimport { Mistral } from \"@mistralai/mistralai\";\nimport { HTTPClient } from \"@mistralai/mistralai/lib/http\";\nimport { ChatCompletionResponse } from \"@mistralai/mistralai/models/components\";\nimport { AIMessage, MESSAGE_ROLE, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { cleanResponse } from \"../text-utils\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\nimport { extractMistralTokenUsage, calculateCost } from '../pricing/token-usage-utils';\n\nexport class MistralAgent extends AbstractAgent {\n private readonly client: Mistral;\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n private get defaultParams(): Omit<Parameters<Mistral['chat']['complete']>[0], 'messages'> {\n return {\n model: this.model,\n maxTokens: this.maxOutputTokens,\n temperature: this.temperature,\n };\n }\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from Mistral API',\n invalidFormat: 'Invalid response format from Mistral API',\n apiError: (error: unknown) =>\n `Failed to get response from Mistral API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n\n constructor(\n name: string, \n instruction: string, \n model: string, \n apiKey: string, \n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, 0.7, enableThinking, agentLoggingConfig);\n\n // Mistral's cache hint is the `prompt_cache_key` request param (\"use the same key\n // for requests with shared prompt prefixes ... to increase cache hits\"), but SDK\n // 1.10.0 has no typed field for it and its outbound zod schema strips unknown keys.\n // Inject it via the SDK's beforeRequest hook instead. The key is derived from bot\n // identity + system prompt, so it is stable within a game day. Any failure falls\n // back to sending the request untouched.\n const promptCacheKey = stableHashHex(`${name}\\n${instruction}`);\n const httpClient = new HTTPClient();\n httpClient.addHook(\"beforeRequest\", async (request) => {\n try {\n if (request.method === 'POST' && new URL(request.url).pathname.endsWith('/chat/completions')) {\n const body = await request.clone().text();\n const json = JSON.parse(body);\n json.prompt_cache_key = promptCacheKey;\n return new Request(request.url, {\n method: request.method,\n headers: request.headers,\n body: JSON.stringify(json),\n });\n }\n } catch {\n // fall through to the original request\n }\n return request;\n });\n this.client = new Mistral({ apiKey: apiKey, httpClient });\n\n // Note: Magistral reasoning models can generate thinking content, but only when\n // responseFormat is not set to 'json_object'. Since this game requires JSON responses,\n // thinking content will be suppressed. The models still benefit from internal reasoning\n // during generation, but thinking traces are not returned in the response.\n }\n\n\n\n private convertToMistralMessages(messages: AIMessage[]) {\n return this.prepareMessages(messages).map(msg => ({\n role: msg.role === 'developer' ? 'system' : msg.role,\n content: msg.content\n }));\n }\n\n\n private processReply(response: ChatCompletionResponse | undefined): [string, string, TokenUsage?] {\n const message = response?.choices?.[0]?.message;\n\n if (!message || !message.content) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n let reply = message.content;\n\n // Handle structured content (thinking models)\n if (Array.isArray(reply)) {\n const { content, thinking } = this.processStructuredReply(reply);\n\n // Log thinking information if available\n if (this.enableThinking && thinking) {\n this.logger(`Thinking content: ${thinking.length} characters of reasoning`);\n }\n\n return [cleanResponse(content), thinking, this.extractTokenUsage(response)];\n }\n\n // Handle string content (regular models)\n return [cleanResponse(reply), \"\", this.extractTokenUsage(response)];\n }\n\n private processStructuredReply(reply: unknown[]): { content: string; thinking: string } {\n let content = \"\";\n let thinking = \"\";\n\n // Response should have 2 parts: thinking block and text block\n for (const chunk of reply) {\n if (typeof chunk === \"object\" && chunk !== null && \"type\" in chunk) {\n if (chunk.type === \"thinking\" && \"thinking\" in chunk) {\n // Extract thinking content from the thinking block\n const thinkingArray = chunk.thinking as any[];\n thinking = thinkingArray\n .filter((item: any) => item?.type === \"text\" && item?.text)\n .map((item: any) => item.text)\n .join(\"\");\n } else if (chunk.type === \"text\" && \"text\" in chunk) {\n // Extract the final answer from the text block\n content = chunk.text as string;\n }\n }\n }\n\n return { content, thinking };\n }\n\n private extractTokenUsage(response: ChatCompletionResponse | undefined): TokenUsage | undefined {\n // Use the centralized Mistral token usage extraction\n const usage = extractMistralTokenUsage(response);\n if (!usage) return undefined;\n\n // MISTRAL_CACHE_CALIBRATION: Mistral documents cached billing but no usage field for\n // hits; the SDK parks unknown wire fields in usage.additionalProperties. Log the raw\n // usage until one real game answers whether hits are reported at all, then remove.\n this.logger(`MISTRAL_CACHE_CALIBRATION raw usage: ${JSON.stringify(response?.usage)}`);\n\n // Log reasoning tokens if available (Magistral models)\n if (usage.reasoningTokens && usage.reasoningTokens > 0) {\n this.logger(`🧠 Reasoning tokens used: ${usage.reasoningTokens}`);\n }\n\n if (usage.cacheHitTokens && usage.cacheHitTokens > 0) {\n this.logger(`💾 Prompt cache: ${usage.cacheHitTokens} of ${usage.promptTokens} input tokens served from cache`);\n }\n\n // Calculate cost using centralized pricing from ai-models.ts\n const costUSD = calculateCost(this.model, usage.promptTokens, usage.completionTokens, {\n totalTokens: usage.totalTokens,\n cacheHitTokens: usage.cacheHitTokens || 0\n });\n\n return {\n inputTokens: usage.promptTokens,\n outputTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n costUSD,\n // Omitted when absent so we never hand Firestore an undefined value.\n ...(usage.reasoningTokens ? { reasoningTokens: usage.reasoningTokens } : {}),\n ...(usage.cacheHitTokens ? { cachedInputTokens: usage.cacheHitTokens } : {})\n };\n }\n\n /**\n * New method using Zod with Mistral API\n * This provides better schema handling and runtime validation\n *\n * Uses Mistral Custom Structured Outputs (responseFormat json_schema), which\n * enforces the response shape server-side and is more reliable than plain JSON\n * mode. The human-readable schema description is still appended to the last\n * message because the enforced schema omits field descriptions/semantics.\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n // Convert Zod schema to human-readable prompt description\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n\n // Convert messages to Mistral format and add schema to last message\n const convertedMessages = this.convertToMistralMessages(messages);\n\n // Add schema description to the last message content\n if (convertedMessages.length > 0) {\n const lastMessage = convertedMessages[convertedMessages.length - 1];\n if (lastMessage && lastMessage.content) {\n lastMessage.content += `\\n\\nYour response must be a valid JSON object matching this schema:\\n${schemaDescription}`;\n }\n } else {\n // If no messages, create a default user message with schema\n convertedMessages.push({\n role: 'user',\n content: `Please respond with a valid JSON object matching this schema:\\n${schemaDescription}`\n });\n }\n\n // Prepare system message\n const systemMessage = {\n role: MESSAGE_ROLE.SYSTEM,\n content: this.instruction\n };\n\n const allMessages = [systemMessage, ...convertedMessages];\n\n // Build request parameters using Mistral Custom Structured Outputs.\n // json_schema enforces the response shape server-side; parseAndValidateLlmJson\n // below remains as a backstop for the rare case the model still drifts.\n const requestParams = {\n ...this.defaultParams,\n messages: allMessages,\n responseFormat: {\n type: 'json_schema' as const,\n jsonSchema: {\n name: 'response_schema',\n schemaDefinition: ZodSchemaConverter.toMistralSchema(zodSchema),\n strict: true\n }\n }\n };\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let response;\n try {\n response = await this.client.chat.complete(requestParams);\n } catch (apiError) {\n // Re-throw API errors immediately without wrapping them in schema validation errors\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n if (!response || !response.choices || response.choices.length === 0) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const choice = response.choices[0];\n const content = choice.message?.content;\n\n if (!content) {\n throw new Error(this.errorMessages.invalidFormat);\n }\n\n // Extract text content from structured responses (thinking models return arrays)\n let responseText: string;\n let thinkingContent = \"\";\n\n if (Array.isArray(content)) {\n // Handle structured content (thinking models)\n const { content: extractedContent, thinking } = this.processStructuredReply(content);\n responseText = extractedContent;\n thinkingContent = thinking;\n } else if (typeof content === 'string') {\n responseText = content;\n } else {\n // Fallback for unexpected content types\n responseText = JSON.stringify(content);\n }\n\n // Parse and validate the response using the shared lenient parser\n // (handles Mistral's nested-reply-object quirk internally)\n const parsedData = parseAndValidateLlmJson(responseText, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n // Extract token usage\n const tokenUsage = this.extractTokenUsage(response);\n\n if (parsedData) {\n this.logReply(parsedData, thinkingContent || undefined, tokenUsage);\n }\n\n return [parsedData, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no schema appended, no responseFormat. Note that Magistral\n * reasoning models only return thinking traces when responseFormat is NOT\n * json_object, so unlike askWithZodSchema this path can surface thinking content.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const convertedMessages = this.convertToMistralMessages(messages);\n\n const systemMessage = {\n role: MESSAGE_ROLE.SYSTEM,\n content: this.instruction\n };\n\n const requestParams = {\n ...this.defaultParams,\n messages: [systemMessage, ...convertedMessages],\n };\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let response;\n try {\n response = await this.client.chat.complete(requestParams);\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n // processReply throws on empty content and handles structured (thinking) replies\n const [content, thinkingContent, tokenUsage] = this.processReply(response);\n\n if (!content) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n this.logReply(content, thinkingContent || undefined, tokenUsage);\n\n return [content, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}","import { AbstractAgent } from \"./abstract-agent\";\nimport { toDeepSeekEffort } from \"../reasoning-effort\";\nimport { mergeThinking, stripInlineThinking } from \"../thinking-utils\";\nimport OpenAI from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { extractUsageAndCalculateCost } from \"../pricing\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\nexport class DeepSeekV2Agent extends AbstractAgent {\n private readonly client: OpenAI;\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n switchingModel: (from: string, to: string) => `Switching from ${from} to ${to} for thinking mode`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from DeepSeek API',\n invalidFormat: 'Invalid response format from DeepSeek API',\n apiError: (error: unknown) =>\n `Failed to get response from DeepSeek API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n\n constructor(\n name: string, \n instruction: string, \n model: string, \n apiKey: string, \n temperature: number, \n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n baseURL: 'https://api.deepseek.com',\n apiKey: apiKey,\n });\n }\n\n\n\n private convertToOpenAIMessages(messages: AIMessage[]): Array<{ role: string, content: string }> {\n const preparedMessages = this.prepareMessages(messages);\n return preparedMessages.map(msg => ({\n role: msg.role === 'developer' ? 'system' : msg.role === 'assistant' ? 'assistant' : 'user',\n content: msg.content\n }));\n }\n\n private addSystemInstruction(messages: Array<{ role: string, content: string }>): Array<{ role: string, content: string }> {\n // Add system instruction if no system message exists\n if (messages.length === 0 || messages[0].role !== 'system') {\n return [\n { role: 'system', content: this.instruction },\n ...messages\n ];\n }\n\n // Prepend instruction to existing system message\n const updatedMessages = [...messages];\n updatedMessages[0] = {\n ...updatedMessages[0],\n content: `${this.instruction}\\n\\n${updatedMessages[0].content}`\n };\n\n return updatedMessages;\n }\n\n /**\n * Thinking params for the request body. DeepSeek V4 toggles thinking with a top-level\n * `thinking: { type }` (the docs' `extra_body` is a Python-SDK wrapper; openai-node has no\n * such thing and sends the key literally, where the API ignores it — probed 2026-08-30:\n * `extra_body: {thinking: {type: 'disabled'}}` still reasoned, top-level `thinking` did\n * not). Thinking is on by default, so the flag matters only for turning it off.\n * `reasoning_effort` takes low|high|max (default high, no budget parameter exists); it is\n * the instance field (catalog default, per-call override) and is only sent when set.\n */\n private thinkingParams(): Record<string, unknown> {\n if (!this.enableThinking) {\n return { thinking: { type: 'disabled' } };\n }\n const effort = this.reasoningEffort;\n return {\n thinking: { type: 'enabled' },\n ...(effort ? { reasoning_effort: toDeepSeekEffort(effort) } : {}),\n };\n }\n\n /**\n * New method using Zod with DeepSeek API\n * This provides better schema handling and runtime validation\n * \n * DeepSeek V4 uses thinking toggle via extra_body. JSON mode (response_format\n * json_object) is supported with or without thinking, so we always request it.\n * Thinking additionally surfaces reasoning via reasoning_content.\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const input = this.convertToOpenAIMessages(messages);\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n // For reasoning models, add schema description to prompt\n // For non-reasoning models, use JSON schema format\n let modifiedInput = [...input];\n // Respect the model's configured output budget (resolved in AbstractAgent). An\n // 8192 cap used to truncate long replies mid-JSON on thinking models, where\n // reasoning_content shares this budget with the answer — hence the catalog\n // override on both DeepSeek entries.\n const requestParams: any = {\n model: this.model,\n messages: this.addSystemInstruction(modifiedInput),\n max_tokens: this.maxOutputTokens,\n ...(this.enableThinking ? {} : { temperature: this.temperature }),\n };\n\n // Add schema description to the last user message\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const lastMessage = modifiedInput[modifiedInput.length - 1];\n if (lastMessage && lastMessage.role === 'user') {\n modifiedInput[modifiedInput.length - 1] = {\n ...lastMessage,\n content: `${lastMessage.content}\\n\\nYour response must be a valid JSON object matching this schema:\\n${schemaDescription}`\n };\n requestParams.messages = this.addSystemInstruction(modifiedInput);\n }\n\n // JSON mode is supported by both thinking and non-thinking models, so always\n // request it for structural enforcement. Thinking is an orthogonal toggle.\n requestParams.response_format = {\n type: 'json_object'\n };\n\n Object.assign(requestParams, this.thinkingParams());\n\n let response;\n try {\n response = await this.client.chat.completions.create(requestParams);\n } catch (apiError) {\n // Re-throw API errors immediately without wrapping them in schema validation errors\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n // Extract reasoning content if available (from thinking mode)\n let thinkingContent = \"\";\n if (this.enableThinking && response.choices[0]?.message) {\n const reasoning = (response.choices[0].message as any).reasoning_content;\n if (reasoning) {\n thinkingContent = reasoning;\n }\n }\n\n const rawContent = response.choices[0]?.message?.content;\n if (!rawContent) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: content, thinking: inlineThinking } = stripInlineThinking(rawContent);\n thinkingContent = mergeThinking(thinkingContent, inlineThinking);\n if (!content) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Parse and validate the response using the shared lenient parser\n const parsedData = parseAndValidateLlmJson(content, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n // Extract token usage and calculate cost\n const usageResult = extractUsageAndCalculateCost(this.model, response);\n let tokenUsage: TokenUsage | undefined;\n\n if (usageResult) {\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {}),\n // Omitted when absent so we never hand Firestore an undefined value.\n ...(usageResult.usage.reasoningTokens ? { reasoningTokens: usageResult.usage.reasoningTokens } : {})\n };\n }\n\n if (parsedData) {\n this.logReply(parsedData, thinkingContent || undefined, tokenUsage);\n }\n\n return [parsedData, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: same request structure as askWithZodSchema but without JSON mode\n * or a schema appended to the prompt. The raw response string is returned as-is.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const input = this.convertToOpenAIMessages(messages);\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n // Respect the model's configured output budget (resolved in AbstractAgent):\n // reasoning_content shares this budget with the answer on thinking models.\n const requestParams: any = {\n model: this.model,\n messages: this.addSystemInstruction(input),\n max_tokens: this.maxOutputTokens,\n ...(this.enableThinking ? {} : { temperature: this.temperature }),\n };\n\n Object.assign(requestParams, this.thinkingParams());\n\n let response;\n try {\n response = await this.client.chat.completions.create(requestParams);\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n // Extract reasoning content if available (from thinking mode)\n let thinkingContent = \"\";\n if (this.enableThinking && response.choices[0]?.message) {\n const reasoning = (response.choices[0].message as any).reasoning_content;\n if (reasoning) {\n thinkingContent = reasoning;\n }\n }\n\n const rawContent = response.choices[0]?.message?.content;\n if (!rawContent) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: content, thinking: inlineThinking } = stripInlineThinking(rawContent);\n thinkingContent = mergeThinking(thinkingContent, inlineThinking);\n if (!content) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Extract token usage and calculate cost\n const usageResult = extractUsageAndCalculateCost(this.model, response);\n let tokenUsage: TokenUsage | undefined;\n\n if (usageResult) {\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {}),\n // Omitted when absent so we never hand Firestore an undefined value.\n ...(usageResult.usage.reasoningTokens ? { reasoningTokens: usageResult.usage.reasoningTokens } : {})\n };\n }\n\n this.logReply(content, thinkingContent || undefined, tokenUsage);\n\n return [content, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}\n","import {AbstractAgent} from \"./abstract-agent\";\nimport { stableHashHex } from \"../text-utils\";\nimport {OpenAI} from \"openai\";\nimport {AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG} from \"../types\";\nimport {parseAndValidateLlmJson} from '../json-response-parser';\nimport {calculateGrokCost} from \"../pricing\";\nimport {z} from 'zod';\nimport {ZodSchemaConverter} from '../zod-schema-converter';\n\n/**\n * xAI Grok agent on the Responses API.\n *\n * grok-4.6 is an always-on reasoning model; we do not send `reasoning_effort` and use the\n * xAI default (\"high\"). Reasoning cannot be disabled. Each response's encrypted reasoning\n * items (requested via `include: [\"reasoning.encrypted_content\"]`) are returned as the 4th\n * tuple element, stored on the game message as `grokEncryptedReasoning`, and replayed into\n * `input` on later turns so the model keeps its chain-of-thought across the conversation.\n */\nexport class GrokAgent extends AbstractAgent {\n private readonly client: OpenAI;\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from Grok API',\n invalidFormat: 'Invalid response format from Grok API',\n apiError: (error: unknown) =>\n `Failed to get response from Grok API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n constructor(\n name: string,\n instruction: string,\n model: string,\n apiKey: string,\n temperature: number,\n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n // xAI routes requests by the x-grok-conv-id header: the same id lands on the same\n // server, which is where the prompt cache lives — without it, cache hits are luck\n // of the load balancer. Derive a stable id from the bot's identity + system prompt:\n // stable within a game day (the instruction only changes at the day boundary, when\n // the cache would be cold anyway).\n const convId = stableHashHex(`${name}\\n${instruction}`);\n this.client = new OpenAI({\n apiKey: apiKey,\n baseURL: 'https://api.x.ai/v1',\n timeout: 1200000,\n defaultHeaders: { 'x-grok-conv-id': convId },\n });\n }\n\n /**\n * Structured output implementation for Grok using json_object mode with prompt\n * augmentation — more reliable than json_schema on OpenAI-compatible endpoints.\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const input = this.buildResponsesInput(this.prepareMessages(messages));\n\n // Add schema description to the last message to ensure the model follows it\n const lastMessage = input[input.length - 1];\n if (lastMessage && typeof lastMessage.content === 'string') {\n lastMessage.content += `\\n\\nYour response must be a valid JSON object matching this schema:\\n${schemaDescription}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n const response = await this.createResponse(input, true);\n const { text, reasoningSummary, encryptedReasoning } = this.extractResponseParts(response);\n if (!text) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n this.logger(`Grok Agent - Found reasoning summary: ${!!reasoningSummary}, encrypted reasoning: ${!!encryptedReasoning}`);\n\n // Parse and validate the response using the shared lenient parser\n const parsedData = parseAndValidateLlmJson(text, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n const tokenUsage = this.extractTokenUsage(response);\n\n if (parsedData) {\n this.logReply(parsedData, reasoningSummary, tokenUsage);\n }\n\n return [parsedData, reasoningSummary, tokenUsage, encryptedReasoning];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no JSON mode and no schema appended to the prompt.\n * Reasoning extraction and token accounting are identical to askWithZodSchema.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const input = this.buildResponsesInput(this.prepareMessages(messages));\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n const response = await this.createResponse(input, false);\n const { text, reasoningSummary, encryptedReasoning } = this.extractResponseParts(response);\n if (!text) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const tokenUsage = this.extractTokenUsage(response);\n\n this.logReply(text, reasoningSummary, tokenUsage);\n\n return [text, reasoningSummary, tokenUsage, encryptedReasoning];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n private createResponse(input: any[], jsonMode: boolean): Promise<any> {\n return this.client.responses.create({\n model: this.model,\n temperature: this.temperature,\n input,\n // Reasoning bills against the output budget on top of the visible answer, so this\n // has to cover both. Raise it with a catalog `maxOutputTokens` override if Grok\n // ever starts truncating — measured turns peak far below the shared default.\n max_output_tokens: this.maxOutputTokens,\n // We manage conversation state ourselves; encrypted reasoning is only\n // returned for unstored responses.\n store: false,\n include: [\"reasoning.encrypted_content\"],\n ...(jsonMode ? { text: { format: { type: 'json_object' } } } : {}),\n } as any);\n }\n\n /**\n * Converts game history to Responses API input items. The system instruction is\n * merged into the leading system message; assistant messages carrying stored\n * encrypted reasoning get their reasoning items replayed right before them.\n */\n private buildResponsesInput(messages: AIMessage[]): any[] {\n const input: any[] = [];\n\n for (const msg of messages) {\n if (msg.role === 'assistant' && msg.grokEncryptedReasoning) {\n try {\n const reasoningItems = JSON.parse(msg.grokEncryptedReasoning);\n if (Array.isArray(reasoningItems)) {\n input.push(...reasoningItems);\n }\n } catch {\n this.logger(`Failed to parse stored encrypted reasoning, replaying message without it`);\n }\n }\n input.push({ role: msg.role, content: msg.content });\n }\n\n if (input.length > 0 && input[0].role !== 'system') {\n input.unshift({ role: 'system', content: this.instruction });\n } else if (input.length > 0 && input[0].role === 'system') {\n input[0].content = `${this.instruction}\\n\\n${input[0].content}`;\n }\n\n return input;\n }\n\n /**\n * Walks the response output items: reasoning items yield the human-readable summary\n * plus the encrypted items (serialized for storage/replay); message items yield text.\n */\n private extractResponseParts(response: any): { text: string; reasoningSummary: string; encryptedReasoning?: string } {\n const textParts: string[] = [];\n const summaryParts: string[] = [];\n const encryptedItems: any[] = [];\n\n for (const item of response?.output ?? []) {\n if (!item) {\n continue;\n }\n if (item.type === 'reasoning') {\n for (const summary of item.summary ?? []) {\n if (typeof summary?.text === 'string' && summary.text) {\n summaryParts.push(summary.text);\n }\n }\n if (item.encrypted_content) {\n encryptedItems.push(item);\n }\n } else if (item.type === 'message') {\n for (const part of item.content ?? []) {\n if (part?.type === 'output_text' && typeof part.text === 'string') {\n textParts.push(part.text);\n }\n }\n }\n }\n\n return {\n text: textParts.join('\\n').trim(),\n reasoningSummary: summaryParts.join('\\n').trim(),\n encryptedReasoning: encryptedItems.length > 0 ? JSON.stringify(encryptedItems) : undefined,\n };\n }\n\n private extractTokenUsage(response: any): TokenUsage | undefined {\n const usage = response?.usage;\n if (!usage) {\n return undefined;\n }\n\n const inputTokens = usage.input_tokens || 0;\n // Responses API output_tokens already includes reasoning tokens\n const outputTokens = usage.output_tokens || 0;\n const reasoningTokens = usage.output_tokens_details?.reasoning_tokens || 0;\n const cachedTokens = usage.input_tokens_details?.cached_tokens || 0;\n\n const cost = calculateGrokCost(this.model, inputTokens, outputTokens, cachedTokens);\n\n if (reasoningTokens > 0) {\n this.logger(`Output breakdown: ${reasoningTokens} reasoning tokens, ${outputTokens - reasoningTokens} final answer tokens, ${outputTokens} total output tokens`);\n }\n if (cachedTokens > 0) {\n this.logger(`Input breakdown: ${cachedTokens} cached tokens of ${inputTokens} input tokens`);\n }\n\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUSD: cost,\n // Omitted when zero so we never hand Firestore an undefined value.\n ...(reasoningTokens > 0 ? { reasoningTokens } : {}),\n ...(cachedTokens > 0 ? { cachedInputTokens: cachedTokens } : {})\n };\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport { mergeThinking, stripInlineThinking } from \"../thinking-utils\";\nimport { OpenAI } from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { extractUsageAndCalculateCost } from \"../pricing\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\n// Kimi K3 agent. The Moonshot API is OpenAI-compatible (https://api.moonshot.ai/v1).\n//\n// K3 always reasons: reasoning is on by default, and `reasoning_effort` — whose only accepted\n// value today is \"max\" — selects the level. We send it explicitly so the model stays pinned at\n// max should Moonshot ship lower levels with a different default. Sending it is otherwise a no-op.\n//\n// The K2-era `thinking: { type: 'disabled' }` toggle does still suppress reasoning on kimi-k3,\n// but it is undocumented for K3 and could disappear without notice, so we don't rely on it: this\n// agent has a single always-reasoning mode. Reasoning surfaces as `message.reasoning_content`,\n// counted in `usage.completion_tokens_details.reasoning_tokens` (already part of completion_tokens).\nexport class KimiAgent extends AbstractAgent {\n private readonly client: OpenAI;\n // kimi-k3 rejects any temperature other than 1, so we never send the field.\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n private get defaultParams(): Omit<Parameters<OpenAI['chat']['completions']['create']>[0], 'messages'> {\n return {\n model: this.model,\n stream: false,\n max_tokens: this.maxOutputTokens,\n // Moonshot's only accepted level; \"max\" is not in the OpenAI SDK's ReasoningEffort union.\n reasoning_effort: 'max' as any,\n };\n }\n\n // Log message templates\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n // Error message templates\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from Kimi API',\n invalidFormat: 'Invalid response format from Kimi API',\n apiError: (error: unknown) =>\n `Failed to get response from Kimi API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n\n constructor(\n name: string, \n instruction: string, \n model: string, \n apiKey: string, \n temperature: number, \n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n apiKey: apiKey,\n baseURL: 'https://api.moonshot.ai/v1',\n });\n }\n\n\n\n\n private convertToOpenAIMessages(messages: AIMessage[]): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n return messages.map(msg => ({\n role: msg.role as 'system' | 'user' | 'assistant',\n content: msg.content\n }));\n }\n\n private extractThinkingAndUsage(\n completion: OpenAI.Chat.Completions.ChatCompletion\n ): { thinkingContent: string; tokenUsage?: TokenUsage } {\n let thinkingContent = \"\";\n const message = completion.choices[0]?.message as any;\n\n if (message?.reasoning_content) {\n thinkingContent = message.reasoning_content;\n this.logger(`Captured reasoning_content (${thinkingContent.length} characters)`);\n }\n\n let tokenUsage: TokenUsage | undefined;\n const usageResult = extractUsageAndCalculateCost(this.model, completion);\n\n if (usageResult) {\n const reasoningTokens = usageResult.usage.reasoningTokens;\n\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {}),\n // Only present when reasoning ran; the key is omitted otherwise so we never\n // hand Firestore an undefined value.\n ...(reasoningTokens ? { reasoningTokens } : {})\n };\n\n if (reasoningTokens) {\n const finalAnswerTokens = Math.max(0, tokenUsage.outputTokens - reasoningTokens);\n this.logger(\n `Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`\n );\n }\n }\n\n return { thinkingContent, tokenUsage };\n }\n\n /**\n * New method using Zod with Kimi/Moonshot AI API\n * This provides better schema handling and runtime validation\n * \n * Kimi/Moonshot AI API is OpenAI-compatible, so we try JSON mode first,\n * and fall back to prompt-based schema if not supported\n */\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n // First, try with JSON mode (OpenAI-compatible)\n try {\n const kimiSchema = ZodSchemaConverter.toOpenAIJsonSchema(zodSchema, 'response_schema');\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n response_format: {\n type: 'json_schema',\n json_schema: kimiSchema\n }\n };\n\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n // Re-throw API errors immediately without wrapping them in schema validation errors\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Parse and validate the response using the shared lenient parser\n const parsedData = parseAndValidateLlmJson(reply, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema (JSON mode)`);\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n if (parsedData) {\n this.logReply(parsedData, thinkingContent, tokenUsage);\n }\n\n return [parsedData, thinkingContent, tokenUsage];\n\n } catch (jsonModeError) {\n // If JSON mode fails, fall back to prompt-based schema\n this.logger(`JSON mode failed, falling back to prompt-based schema: ${jsonModeError}`);\n\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const lastMessage = openAIMessages[openAIMessages.length - 1];\n\n if (lastMessage) {\n lastMessage.content += `\\n\\nYour response must be a valid JSON object matching this schema:\\n${schemaDescription}`;\n }\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages\n };\n\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n // Re-throw API errors immediately without wrapping them in schema validation errors\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n // Parse and validate the response using the shared lenient parser\n const parsedData = parseAndValidateLlmJson(reply, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema (prompt mode)`);\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n if (parsedData) {\n this.logReply(parsedData, thinkingContent, tokenUsage);\n }\n\n return [parsedData, thinkingContent, tokenUsage];\n }\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no JSON mode (and therefore no prompt-based schema fallback).\n * Thinking toggle and reasoning_content extraction are identical to askWithZodSchema.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages\n };\n\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n this.logReply(reply, thinkingContent, tokenUsage);\n\n return [reply, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport { toGlmEffort } from \"../reasoning-effort\";\nimport { mergeThinking, stripInlineThinking } from \"../thinking-utils\";\nimport { OpenAI } from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { extractUsageAndCalculateCost } from \"../pricing\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\n// Z.AI / GLM-5.3 agent. The API is OpenAI-compatible (https://api.z.ai/api/paas/v4/),\n// so we use the OpenAI SDK with a custom baseURL. GLM-5.3 rejects requests with\n// `thinking: { type: 'disabled' }` (reasoning is always on), so we always send 'enabled';\n// `enableThinking` only controls whether reasoning_content is surfaced to the game.\n// `reasoning_effort` comes from the catalog and must never be omitted: the server default\n// is 'max', whose reasoning tokens count against max_tokens and can exhaust the whole\n// budget before any content is emitted (see the GLM entry in ai-models.ts).\nexport class GlmAgent extends AbstractAgent {\n private readonly client: OpenAI;\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n // `reasoning_effort` is re-declared as string: the OpenAI SDK's union lacks Z.AI's 'max'.\n private get defaultParams(): Omit<Parameters<OpenAI['chat']['completions']['create']>[0], 'messages' | 'reasoning_effort'> & {\n thinking: { type: 'enabled' };\n reasoning_effort: string;\n } {\n return {\n model: this.model,\n temperature: this.temperature,\n stream: false,\n max_tokens: this.maxOutputTokens,\n thinking: { type: 'enabled' },\n reasoning_effort: toGlmEffort(this.reasoningEffort ?? 'high'),\n };\n }\n\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n private readonly errorMessages = {\n emptyResponse: (finishReason: string | undefined) =>\n `Empty or undefined response from Z.AI API (finish_reason: ${finishReason ?? 'unknown'})`,\n invalidFormat: 'Invalid response format from Z.AI API',\n apiError: (error: unknown) =>\n `Failed to get response from Z.AI API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n constructor(\n name: string,\n instruction: string,\n model: string,\n apiKey: string,\n temperature: number,\n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n apiKey: apiKey,\n baseURL: 'https://api.z.ai/api/paas/v4/',\n });\n }\n\n private convertToOpenAIMessages(messages: AIMessage[]): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n return messages.map(msg => ({\n role: msg.role as 'system' | 'user' | 'assistant',\n content: msg.content\n }));\n }\n\n private extractThinkingAndUsage(\n completion: OpenAI.Chat.Completions.ChatCompletion\n ): { thinkingContent: string; tokenUsage?: TokenUsage } {\n let thinkingContent = \"\";\n const message = completion.choices[0]?.message as any;\n\n if (this.enableThinking && message?.reasoning_content) {\n thinkingContent = message.reasoning_content;\n this.logger(`Captured reasoning_content (${thinkingContent.length} characters)`);\n }\n\n let tokenUsage: TokenUsage | undefined;\n const usageResult = extractUsageAndCalculateCost(this.model, completion);\n\n if (usageResult) {\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {})\n };\n\n if (this.enableThinking && usageResult.usage.reasoningTokens) {\n const reasoningTokens = usageResult.usage.reasoningTokens;\n const finalAnswerTokens = Math.max(0, tokenUsage.outputTokens - reasoningTokens);\n this.logger(\n `Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`\n );\n }\n }\n\n return { thinkingContent, tokenUsage };\n }\n\n /**\n * Robust schema-aware coercion of a model reply.\n * Order: strict JSON parse → embedded {…} extraction → wrap-as-reply (BotAnswer-shaped schemas).\n * Returns the validated value or throws.\n */\n private parseAndValidate<T>(rawReply: string, zodSchema: z.ZodSchema<T>): T {\n return parseAndValidateLlmJson(rawReply, zodSchema, (m) => this.logger(m));\n }\n\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n // Z.AI's JSON mode is `{ type: 'json_object' }` (OpenAI's older shape) — it does NOT\n // accept `{ type: 'json_schema', json_schema: ... }`. Schema constraints must be\n // conveyed in-prompt. See https://docs.z.ai → Structured Output.\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const lastMessage = openAIMessages[openAIMessages.length - 1];\n if (lastMessage) {\n lastMessage.content += `\\n\\nIMPORTANT: Respond with ONLY a valid JSON object matching this schema. Do NOT write narration, roleplay actions, asterisks, or commentary outside the JSON. Output the JSON object and nothing else.\\n${schemaDescription}`;\n }\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n response_format: { type: 'json_object' }\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse(completion.choices[0]?.finish_reason));\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse(completion.choices[0]?.finish_reason));\n }\n\n const validated = this.parseAndValidate(reply, zodSchema);\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n if (validated) {\n this.logReply(validated, thinkingContent, tokenUsage);\n }\n\n return [validated, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no JSON mode and no schema appended to the prompt.\n * Thinking toggle and reasoning_content extraction are identical to askWithZodSchema.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse(completion.choices[0]?.finish_reason));\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse(completion.choices[0]?.finish_reason));\n }\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n this.logReply(reply, thinkingContent, tokenUsage);\n\n return [reply, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport { mergeThinking, stripInlineThinking } from \"../thinking-utils\";\nimport { OpenAI } from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { extractUsageAndCalculateCost } from \"../pricing\";\nimport { logger } from \"../logger\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\n// Sakana Fugu agent. The API is OpenAI-compatible (https://api.sakana.ai/v1), so we use the\n// OpenAI SDK with a custom baseURL. Both `fugu` and `fugu-ultra` always reason; the API exposes\n// two effort levels (\"high\" — the default — and \"xhigh\"/\"max\"). We expose a single picker entry\n// per model at the default \"high\" effort, so we do NOT send `reasoning_effort` (omitting it keeps\n// the request minimal and avoids param-rejection on this endpoint; \"high\" is applied by default).\n// Reasoning content, when returned, surfaces as `message.reasoning_content` (OpenAI-compatible).\nexport class FuguAgent extends AbstractAgent {\n private readonly client: OpenAI;\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n private get defaultParams(): Omit<Parameters<OpenAI['chat']['completions']['create']>[0], 'messages'> {\n return {\n model: this.model,\n stream: false,\n // Caps visible output only. Server-side orchestration/reasoning tokens are\n // separate and unaffected by this.\n max_tokens: this.maxOutputTokens,\n };\n }\n\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from Sakana Fugu API',\n invalidFormat: 'Invalid response format from Sakana Fugu API',\n apiError: (error: unknown) =>\n `Failed to get response from Sakana Fugu API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n constructor(\n name: string,\n instruction: string,\n model: string,\n apiKey: string,\n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n // Fugu is a reasoning model and ignores temperature, so we pass a neutral default upstream.\n super(name, instruction, model, 1, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n apiKey: apiKey,\n baseURL: 'https://api.sakana.ai/v1',\n timeout: 1200000,\n });\n }\n\n private convertToOpenAIMessages(messages: AIMessage[]): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n return messages.map(msg => ({\n role: msg.role as 'system' | 'user' | 'assistant',\n content: msg.content\n }));\n }\n\n // ───────────────────────────────────────────────────────────────────────────────────────\n // TEMPORARY (cost calibration). Base `fugu` is a dynamic router with no published per-token\n // price and Sakana returns NO cost field in the response — only token counts. Crucially the\n // response also reports \"orchestration tokens\" (billed at input/output rates per Sakana's\n // pricing page) that our standard TokenUsage drops. This logs the full raw breakdown to\n // BetterStack under a distinctive tag so we can sum real tokens per game and, combined with\n // the Sakana billing dashboard total, derive the true per-token rate. REMOVE AFTER CALIBRATION.\n private logRawUsageForCalibration(completion: OpenAI.Chat.Completions.ChatCompletion): void {\n const usage: any = completion?.usage;\n if (!usage) return;\n logger.info('FUGU_COST_CALIBRATION', {\n tag: 'FUGU_COST_CALIBRATION',\n model: this.model,\n agentName: this.name,\n gameId: this.gameId,\n userId: this.userId,\n promptTokens: usage.prompt_tokens ?? 0,\n completionTokens: usage.completion_tokens ?? 0,\n totalTokens: usage.total_tokens ?? 0,\n cachedTokens: usage.prompt_tokens_details?.cached_tokens ?? 0,\n orchestrationInputTokens: usage.prompt_tokens_details?.orchestration_input_tokens ?? 0,\n orchestrationInputCachedTokens: usage.prompt_tokens_details?.orchestration_input_cached_tokens ?? 0,\n reasoningTokens: usage.completion_tokens_details?.reasoning_tokens ?? 0,\n orchestrationOutputTokens: usage.completion_tokens_details?.orchestration_output_tokens ?? 0,\n rawUsage: usage,\n });\n }\n\n private extractThinkingAndUsage(\n completion: OpenAI.Chat.Completions.ChatCompletion\n ): { thinkingContent: string; tokenUsage?: TokenUsage } {\n let thinkingContent = \"\";\n const message = completion.choices[0]?.message as any;\n\n if (message?.reasoning_content) {\n thinkingContent = message.reasoning_content;\n this.logger(`Captured reasoning_content (${thinkingContent.length} characters)`);\n }\n\n let tokenUsage: TokenUsage | undefined;\n const usageResult = extractUsageAndCalculateCost(this.model, completion);\n\n if (usageResult) {\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {})\n };\n\n if (usageResult.usage.reasoningTokens) {\n const reasoningTokens = usageResult.usage.reasoningTokens;\n const finalAnswerTokens = Math.max(0, tokenUsage.outputTokens - reasoningTokens);\n this.logger(\n `Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`\n );\n }\n }\n\n return { thinkingContent, tokenUsage };\n }\n\n private prependSystemInstruction(openAIMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[]): void {\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({ role: 'system', content: this.instruction });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n }\n\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n this.prependSystemInstruction(openAIMessages);\n\n // Sakana's docs don't advertise structured output, but probing the live API shows it\n // accepts OpenAI's `json_object` mode (returns clean JSON; without it the model wraps\n // replies in ```json fences). We use json_object for a clean reply and still describe\n // the schema in-prompt for shape, parsing with the shared lenient parser. (Strict\n // `json_schema` mode also works but is avoided — like GlmAgent/GrokAgent — since the\n // game's optional/union Zod schemas don't satisfy strict-mode requirements.)\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const lastMessage = openAIMessages[openAIMessages.length - 1];\n if (lastMessage) {\n lastMessage.content += `\\n\\nIMPORTANT: Respond with ONLY a valid JSON object matching this schema. Do NOT write narration, roleplay actions, asterisks, or commentary outside the JSON. Output the JSON object and nothing else.\\n${schemaDescription}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n response_format: { type: 'json_object' },\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n this.logRawUsageForCalibration(completion); // TEMPORARY — remove after cost calibration\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const validated = parseAndValidateLlmJson(reply, zodSchema, (m) => this.logger(m));\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n if (validated) {\n this.logReply(validated, thinkingContent, tokenUsage);\n }\n\n return [validated, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no schema appended to the prompt. Reasoning extraction and token\n * accounting are identical to askWithZodSchema.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n this.prependSystemInstruction(openAIMessages);\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n this.logRawUsageForCalibration(completion); // TEMPORARY — remove after cost calibration\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n this.logReply(reply, thinkingContent, tokenUsage);\n\n return [reply, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport { stripInlineThinking } from \"../thinking-utils\";\nimport { OpenAI } from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { extractUsageAndCalculateCost } from \"../pricing\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\n// Qwen (QwenCloud/DashScope) agent. The API is OpenAI-compatible\n// (https://dashscope-intl.aliyuncs.com/compatible-mode/v1), so we use the OpenAI SDK with a\n// custom baseURL. Thinking is toggled with a top-level `enable_thinking` boolean and arrives in\n// `message.reasoning_content` — verified live 2026-08-05 against qwen3.8-max / 3.7-plus /\n// 3.7-flash, all of which accept non-streaming thinking requests.\n//\n// Structured output: Qwen's `response_format: json_object` is NOT supported in thinking mode,\n// and we always think — so schema constraints are conveyed in-prompt and parsed leniently,\n// never via response_format.\nexport class QwenAgent extends AbstractAgent {\n private readonly client: OpenAI;\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n private get defaultParams(): Omit<Parameters<OpenAI['chat']['completions']['create']>[0], 'messages'> {\n return {\n model: this.model,\n temperature: this.temperature,\n stream: false,\n // Reasoning tokens share the completion budget on Qwen, so this has to leave room\n // for both CoT and answer — too small cuts the JSON mid-object.\n max_tokens: this.maxOutputTokens,\n };\n }\n\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from Qwen API',\n invalidFormat: 'Invalid response format from Qwen API',\n apiError: (error: unknown) =>\n `Failed to get response from Qwen API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n constructor(\n name: string,\n instruction: string,\n model: string,\n apiKey: string,\n temperature: number,\n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n apiKey: apiKey,\n baseURL: 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1',\n });\n }\n\n /**\n * Thinking params for the request body. `thinking_budget` caps reasoning length and is only\n * sent when the instance has one (catalog default, or a per-call override like story\n * generation); without it the model thinks at the provider default, and qwen3.8-max's\n * latency then swings 30–100s.\n *\n * `reasoning_effort` is deliberately NOT sent. Probed live 2026-08-30 on qwen3.8-flash and\n * qwen3.8-max: every value low..max is accepted, but reasoning length doesn't track it\n * (max: low → 1,686 reasoning tokens / 44s, high → 226 / 7s, xhigh → 1,102 / 30s), while\n * thinking_budget bounds it reliably (≤340 at 1024). The docs also call the two mutually\n * exclusive on qwen3.8-max. So on Qwen the budget IS the effort knob; `reasoningEffort`\n * on this agent is ignored.\n */\n private thinkingParams(): Record<string, unknown> {\n const budget = this.thinkingBudgetTokens;\n return {\n enable_thinking: this.enableThinking,\n ...(this.enableThinking && budget !== undefined ? { thinking_budget: budget } : {}),\n };\n }\n\n private convertToOpenAIMessages(messages: AIMessage[]): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n return messages.map(msg => ({\n role: msg.role as 'system' | 'user' | 'assistant',\n content: msg.content\n }));\n }\n\n private extractThinkingAndUsage(\n completion: OpenAI.Chat.Completions.ChatCompletion\n ): { thinkingContent: string; tokenUsage?: TokenUsage } {\n let thinkingContent = \"\";\n const message = completion.choices[0]?.message as any;\n\n if (this.enableThinking && message?.reasoning_content) {\n thinkingContent = message.reasoning_content;\n this.logger(`Captured reasoning_content (${thinkingContent.length} characters)`);\n }\n\n let tokenUsage: TokenUsage | undefined;\n const usageResult = extractUsageAndCalculateCost(this.model, completion);\n\n if (usageResult) {\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {})\n };\n\n if (this.enableThinking && usageResult.usage.reasoningTokens) {\n const reasoningTokens = usageResult.usage.reasoningTokens;\n const finalAnswerTokens = Math.max(0, tokenUsage.outputTokens - reasoningTokens);\n this.logger(\n `Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`\n );\n }\n }\n\n return { thinkingContent, tokenUsage };\n }\n\n /**\n * Robust schema-aware coercion of a model reply.\n * Order: strict JSON parse → embedded {…} extraction → wrap-as-reply (BotAnswer-shaped schemas).\n * Returns the validated value or throws.\n */\n private parseAndValidate<T>(rawReply: string, zodSchema: z.ZodSchema<T>): T {\n return parseAndValidateLlmJson(rawReply, zodSchema, (m) => this.logger(m));\n }\n\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n // No response_format here on purpose: Qwen rejects JSON mode when thinking is\n // enabled, so the schema is enforced in-prompt + by the lenient parser.\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const lastMessage = openAIMessages[openAIMessages.length - 1];\n if (lastMessage) {\n lastMessage.content += `\\n\\nIMPORTANT: Respond with ONLY a valid JSON object matching this schema. Do NOT write narration, roleplay actions, asterisks, or commentary outside the JSON. Output the JSON object and nothing else.\\n${schemaDescription}`;\n }\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n ...this.thinkingParams()\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const validated = this.parseAndValidate(reply, zodSchema);\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = [reasoningContent, inlineThinking].filter(Boolean).join(\"\\n\");\n\n if (validated) {\n this.logReply(validated, thinkingContent, tokenUsage);\n }\n\n return [validated, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no schema appended to the prompt.\n * Thinking toggle and reasoning_content extraction are identical to askWithZodSchema.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n ...this.thinkingParams()\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const rawReply = completion.choices[0]?.message?.content;\n if (!rawReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: reply, thinking: inlineThinking } = stripInlineThinking(rawReply);\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = [reasoningContent, inlineThinking].filter(Boolean).join(\"\\n\");\n\n this.logReply(reply, thinkingContent, tokenUsage);\n\n return [reply, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}\n","import { AbstractAgent } from \"./abstract-agent\";\nimport { mergeThinking, stripInlineThinking } from \"../thinking-utils\";\nimport { OpenAI } from \"openai\";\nimport { AIMessage, TokenUsage, AgentLoggingConfig, DEFAULT_LOGGING_CONFIG } from \"../types\";\nimport { extractUsageAndCalculateCost } from \"../pricing\";\nimport { z } from 'zod';\nimport { ZodSchemaConverter } from '../zod-schema-converter';\nimport { parseAndValidateLlmJson } from '../json-response-parser';\n\n// MiniMax M3 agent. The API is OpenAI-compatible (https://api.minimax.io/v1), so we use the\n// OpenAI SDK with a custom baseURL. M3's `thinking` param is `{type: 'adaptive'}` by default\n// (the model decides per-request how much to think) and `{type: 'disabled'}` turns it off.\n//\n// We always send `reasoning_split: true`: without it, thinking arrives as `<think>` tags INSIDE\n// message.content and would poison JSON parsing; with it, thinking arrives separately in\n// `message.reasoning_content` (same field as Qwen/GLM/DeepSeek). We still strip stray <think>\n// blocks from the answer defensively.\n//\n// Structured output: the M-series Chat Completions API has no `response_format` at all, so\n// schema constraints are conveyed in-prompt and parsed leniently. MiniMax's Anthropic-compatible\n// endpoint was evaluated as an alternative (forced tool_choice, arguments as a parsed object) and\n// rejected: it removes JSON syntax errors but MiniMax does no constrained decoding, so required\n// fields are still dropped (observed live: story generation omitting a required field from all 15\n// players), and tool_choice is not always honored. It needs the same in-prompt schema description\n// and the same lenient parsing, for a second client against a second endpoint.\nexport class MiniMaxAgent extends AbstractAgent {\n private readonly client: OpenAI;\n // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field\n // initializer would snapshot the default and silently ignore the override.\n private get defaultParams(): Omit<Parameters<OpenAI['chat']['completions']['create']>[0], 'messages'> {\n return {\n model: this.model,\n temperature: this.temperature,\n stream: false,\n // MiniMax deprecates max_tokens in favor of max_completion_tokens (M3 max is 512K,\n // far above anything a turn needs).\n max_completion_tokens: this.maxOutputTokens,\n };\n }\n\n private readonly logTemplates = {\n error: (name: string, error: unknown) => `Error in ${name} agent: ${error}`,\n };\n\n private readonly errorMessages = {\n emptyResponse: 'Empty or undefined response from MiniMax API',\n invalidFormat: 'Invalid response format from MiniMax API',\n apiError: (error: unknown) =>\n `Failed to get response from MiniMax API: ${error instanceof Error ? error.message : String(error)}`,\n };\n\n constructor(\n name: string,\n instruction: string,\n model: string,\n apiKey: string,\n temperature: number,\n enableThinking: boolean = false,\n agentLoggingConfig: AgentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents\n ) {\n super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);\n this.client = new OpenAI({\n apiKey: apiKey,\n baseURL: 'https://api.minimax.io/v1',\n });\n }\n\n private thinkingParams(): Record<string, unknown> {\n return {\n thinking: { type: this.enableThinking ? 'adaptive' : 'disabled' },\n reasoning_split: true,\n };\n }\n\n private convertToOpenAIMessages(messages: AIMessage[]): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n return messages.map(msg => ({\n role: msg.role as 'system' | 'user' | 'assistant',\n content: msg.content\n }));\n }\n\n private extractThinkingAndUsage(\n completion: OpenAI.Chat.Completions.ChatCompletion\n ): { thinkingContent: string; tokenUsage?: TokenUsage } {\n let thinkingContent = \"\";\n const message = completion.choices[0]?.message as any;\n\n if (this.enableThinking && message?.reasoning_content) {\n thinkingContent = message.reasoning_content;\n this.logger(`Captured reasoning_content (${thinkingContent.length} characters)`);\n }\n\n let tokenUsage: TokenUsage | undefined;\n const usageResult = extractUsageAndCalculateCost(this.model, completion);\n\n if (usageResult) {\n tokenUsage = {\n inputTokens: usageResult.usage.promptTokens,\n outputTokens: usageResult.usage.completionTokens,\n totalTokens: usageResult.usage.totalTokens,\n costUSD: usageResult.cost,\n ...(usageResult.usage.cacheHitTokens !== undefined ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {})\n };\n\n if (this.enableThinking && usageResult.usage.reasoningTokens) {\n const reasoningTokens = usageResult.usage.reasoningTokens;\n const finalAnswerTokens = Math.max(0, tokenUsage.outputTokens - reasoningTokens);\n this.logger(\n `Output breakdown: ${reasoningTokens} reasoning tokens, ${finalAnswerTokens} final answer tokens`\n );\n }\n }\n\n return { thinkingContent, tokenUsage };\n }\n\n /**\n * Robust schema-aware coercion of a model reply.\n * Order: strict JSON parse → embedded {…} extraction → wrap-as-reply (BotAnswer-shaped schemas).\n * Returns the validated value or throws.\n */\n private parseAndValidate<T>(rawReply: string, zodSchema: z.ZodSchema<T>): T {\n return parseAndValidateLlmJson(rawReply, zodSchema, (m) => this.logger(m));\n }\n\n async doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n // No response_format on purpose: the M-series API doesn't support it, so the schema\n // is enforced in-prompt + by the lenient parser.\n const schemaDescription = ZodSchemaConverter.toPromptDescription(zodSchema);\n const lastMessage = openAIMessages[openAIMessages.length - 1];\n if (lastMessage) {\n lastMessage.content += `\\n\\nIMPORTANT: Respond with ONLY a valid JSON object matching this schema. Do NOT write narration, roleplay actions, asterisks, or commentary outside the JSON. Output the JSON object and nothing else.\\n${schemaDescription}`;\n }\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n ...this.thinkingParams()\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const reply = completion.choices[0]?.message?.content;\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: cleanReply, thinking: inlineThinking } = stripInlineThinking(reply);\n const validated = this.parseAndValidate(cleanReply, zodSchema);\n\n this.logger(`✅ Response validated successfully with Zod schema`);\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n if (validated) {\n this.logReply(validated, thinkingContent, tokenUsage);\n }\n\n return [validated, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n\n /**\n * Plain-text ask: no schema appended to the prompt.\n * Thinking handling and reasoning_content extraction are identical to askWithZodSchema.\n */\n async doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage?, string?]> {\n try {\n const preparedMessages = this.prepareMessages(messages);\n const openAIMessages = this.convertToOpenAIMessages(preparedMessages);\n\n // Add system instruction if needed\n if (openAIMessages.length > 0 && openAIMessages[0].role !== 'system') {\n openAIMessages.unshift({\n role: 'system',\n content: this.instruction\n });\n } else if (openAIMessages.length > 0 && openAIMessages[0].role === 'system') {\n openAIMessages[0].content = `${this.instruction}\\n\\n${openAIMessages[0].content}`;\n }\n\n this.logAsking(messages);\n this.logMessages(messages);\n\n let completion;\n try {\n const params: any = {\n ...this.defaultParams,\n messages: openAIMessages,\n ...this.thinkingParams()\n };\n completion = await this.client.chat.completions.create(params) as OpenAI.Chat.Completions.ChatCompletion;\n } catch (apiError) {\n this.logger(this.logTemplates.error(this.name, apiError));\n throw new Error(this.errorMessages.apiError(apiError));\n }\n\n const reply = completion.choices[0]?.message?.content;\n if (!reply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { text: cleanReply, thinking: inlineThinking } = stripInlineThinking(reply);\n if (!cleanReply) {\n throw new Error(this.errorMessages.emptyResponse);\n }\n\n const { thinkingContent: reasoningContent, tokenUsage } = this.extractThinkingAndUsage(completion);\n const thinkingContent = mergeThinking(reasoningContent, inlineThinking);\n\n this.logReply(cleanReply, thinkingContent, tokenUsage);\n\n return [cleanReply, thinkingContent, tokenUsage];\n\n } catch (error) {\n this.logger(this.logTemplates.error(this.name, error));\n throw new Error(this.errorMessages.apiError(error));\n }\n }\n}\n","import { ApiKeyMap } from '../types';\nimport { AbstractAgent } from \"./abstract-agent\";\nimport { Gpt5Agent } from \"./gpt-5-agent\";\nimport { LLM_CONSTANTS, SupportedAiModels } from \"../catalog\";\nimport { ClaudeAgent } from \"./anthropic-agent\";\nimport { GoogleAgent } from \"./google-agent\";\nimport { MistralAgent } from \"./mistral-agent\";\nimport { DeepSeekV2Agent } from \"./deepseek-v2-agent\";\nimport { GrokAgent } from \"./grok-agent\";\nimport { KimiAgent } from \"./kimi-agent\";\nimport { GlmAgent } from \"./glm-agent\";\nimport { FuguAgent } from \"./fugu-agent\";\nimport { QwenAgent } from \"./qwen-agent\";\nimport { MiniMaxAgent } from \"./minimax-agent\";\n\nexport class AgentFactory {\n\n static createAgent(\n name: string,\n instruction: string,\n llmType: string,\n apiKeys: ApiKeyMap,\n enableThinking: boolean = false\n ): AbstractAgent {\n const modelName = this.validateLlmTypeAndGet(llmType)\n const model = SupportedAiModels[modelName]\n const apiKeyName = model.apiKeyName\n const key = apiKeys[apiKeyName]\n\n // Determine if thinking should be enabled based on model configuration\n const shouldEnableThinking = model.hasThinking;\n\n switch (modelName) {\n // Claude models — thinking-only since 2026-08-05\n case LLM_CONSTANTS.CLAUDE_FABLE:\n case LLM_CONSTANTS.CLAUDE_OPUS:\n case LLM_CONSTANTS.CLAUDE_SONNET:\n case LLM_CONSTANTS.CLAUDE_HAIKU:\n return new ClaudeAgent(name, instruction, model.modelApiName, key, shouldEnableThinking);\n\n // Always-on reasoning models\n case LLM_CONSTANTS.GPT_SOL:\n case LLM_CONSTANTS.GPT:\n case LLM_CONSTANTS.GPT_MINI:\n return new Gpt5Agent(name, instruction, model.modelApiName, key, model.temperature!, shouldEnableThinking);\n case LLM_CONSTANTS.GEMINI_PRO:\n case LLM_CONSTANTS.GEMINI_FLASH:\n case LLM_CONSTANTS.GEMINI_LITE:\n return new GoogleAgent(name, instruction, model.modelApiName, key, shouldEnableThinking);\n case LLM_CONSTANTS.GROK:\n return new GrokAgent(name, instruction, model.modelApiName, key, model.temperature!, shouldEnableThinking);\n\n // DeepSeek V4 models — thinking-only since 2026-08-05\n case LLM_CONSTANTS.DEEPSEEK_FLASH:\n case LLM_CONSTANTS.DEEPSEEK_PRO:\n return new DeepSeekV2Agent(name, instruction, model.modelApiName, key, model.temperature ?? 0, shouldEnableThinking);\n\n // Mistral models\n case LLM_CONSTANTS.MISTRAL_MEDIUM:\n case LLM_CONSTANTS.MISTRAL_SMALL:\n case LLM_CONSTANTS.MISTRAL_LARGE:\n case LLM_CONSTANTS.MISTRAL_MAGISTRAL:\n return new MistralAgent(name, instruction, model.modelApiName, key, shouldEnableThinking);\n case LLM_CONSTANTS.KIMI:\n // Kimi K3 rejects any temperature but 1; the agent never sends the field.\n return new KimiAgent(name, instruction, model.modelApiName, key, 0, shouldEnableThinking);\n\n // Z.AI models — thinking-only since 2026-08-05\n case LLM_CONSTANTS.GLM:\n case LLM_CONSTANTS.GLM_FLASH:\n return new GlmAgent(name, instruction, model.modelApiName, key, model.temperature!, shouldEnableThinking);\n\n // Sakana Fugu models — always-on reasoning, no temperature (ignored by the model)\n case LLM_CONSTANTS.FUGU_ULTRA:\n return new FuguAgent(name, instruction, model.modelApiName, key, shouldEnableThinking);\n\n // Qwen models — thinking-only (enable_thinking always sent)\n case LLM_CONSTANTS.QWEN_MAX:\n case LLM_CONSTANTS.QWEN_FLASH:\n return new QwenAgent(name, instruction, model.modelApiName, key, model.temperature!, shouldEnableThinking);\n\n // MiniMax M3 — adaptive thinking (the model decides per-request)\n case LLM_CONSTANTS.MINIMAX:\n return new MiniMaxAgent(name, instruction, model.modelApiName, key, model.temperature!, shouldEnableThinking);\n default:\n throw new Error(`Unknown Key: ${modelName}`);\n }\n }\n\n private static validateLlmTypeAndGet(llmType: string): string {\n // Deprecated-id migration and RANDOM resolution are consumer concerns — resolve\n // both before calling the library factory. Ids here must be live catalog ids.\n const llmValues = Object.values(LLM_CONSTANTS) as string[];\n if (!llmValues.includes(llmType)) {\n throw new Error(`Invalid llmType: ${llmType}`);\n }\n return llmType;\n }\n}\n"],"mappings":"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","names":["cleanResponse","schema","extractTokenUsageFromResponse","extractTokenUsageFromResponse","extractTokenUsageFromResponse","extractTokenUsageFromResponse","extractTokenUsageFromResponse","extractTokenUsageFromResponse","z","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI","OpenAI"]}
|