@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.
@@ -0,0 +1,1191 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Core types shared by every agent and consumer app.
5
+ */
6
+ declare const MESSAGE_ROLE: {
7
+ readonly SYSTEM: "system";
8
+ readonly USER: "user";
9
+ readonly ASSISTANT: "assistant";
10
+ };
11
+ interface AIMessage {
12
+ role: 'system' | 'user' | 'assistant' | 'developer';
13
+ content: string;
14
+ thinking?: string;
15
+ anthropicThinkingSignature?: string;
16
+ googleThoughtSignature?: string;
17
+ grokEncryptedReasoning?: string;
18
+ }
19
+ interface TokenUsage$1 {
20
+ inputTokens: number;
21
+ outputTokens: number;
22
+ totalTokens: number;
23
+ costUSD: number;
24
+ reasoningTokens?: number;
25
+ cachedInputTokens?: number;
26
+ durationMs?: number;
27
+ }
28
+ interface ApiKeyMap {
29
+ [id: string]: string;
30
+ }
31
+ interface AgentLoggingConfig {
32
+ enabled: boolean;
33
+ logSystemPrompt: boolean;
34
+ history: {
35
+ enabled: boolean;
36
+ maxCharactersPerMessage: number;
37
+ };
38
+ logCommand: boolean;
39
+ reply: {
40
+ mode: 'raw' | 'body-only';
41
+ maxReplyChars: number;
42
+ maxThinkingChars: number;
43
+ includeReasoning: boolean;
44
+ includeUsage: boolean;
45
+ };
46
+ }
47
+ interface LoggingConfig {
48
+ agents: AgentLoggingConfig;
49
+ }
50
+ declare const DEFAULT_LOGGING_CONFIG: LoggingConfig;
51
+ declare class BotResponseError extends Error {
52
+ details: string;
53
+ context: Record<string, any>;
54
+ recoverable: boolean;
55
+ /**
56
+ * Model-facing explanation of the rejection, set where the failure is detected and carried
57
+ * through to the consumer's error surface. Used to enrich a user-triggered retry prompt.
58
+ */
59
+ explanation?: string;
60
+ constructor(message: string, details?: string, context?: Record<string, any>, recoverable?: boolean, explanation?: string);
61
+ }
62
+
63
+ /**
64
+ * Injectable logging seam. The library logs agent activity through this interface;
65
+ * consumers with a real logging pipeline (BetterStack, Datadog, …) plug it in via
66
+ * `setLlmLogger` once at startup. The default implementation logs to the console.
67
+ */
68
+ interface AgentActivityData {
69
+ gameId?: string;
70
+ userId?: string;
71
+ systemPrompt?: string;
72
+ history?: AIMessage[];
73
+ command?: string;
74
+ reply?: any;
75
+ thinking?: string;
76
+ usage?: TokenUsage$1;
77
+ }
78
+ interface LlmLogger {
79
+ debug(message: string, args?: any): void;
80
+ info(message: string, args?: any): void;
81
+ warn(message: string, args?: any): void;
82
+ error(message: string, args?: any): void;
83
+ agentActivity(agentName: string, model: string, activity: string, data: AgentActivityData, customConfig?: AgentLoggingConfig): void;
84
+ }
85
+ /** Replace the library's logger. Call once at app startup, before agents are created. */
86
+ declare function setLlmLogger(replacement: LlmLogger): void;
87
+ /** Stable facade the library logs through; delegates to whatever setLlmLogger installed. */
88
+ declare const logger: LlmLogger;
89
+
90
+ /**
91
+ * Sentinel that splits a system prompt into cache tiers: [shared static tier, per-agent tier].
92
+ * AbstractAgent splits the instruction on it; providers with explicit cache breakpoints
93
+ * (Anthropic) place one per part, everyone else relies on implicit prefix caching over the
94
+ * joined, marker-free instruction. Consumers embed it between the stable and variable parts
95
+ * of their system prompts.
96
+ */
97
+ declare const CACHE_TIER_MARKER = "\n<<<CACHE_TIER_BREAK>>>\n";
98
+
99
+ /** Strips a wrapping markdown code fence (```json … ``` or ``` … ```) from a model response. */
100
+ declare function cleanResponse(response: string): string;
101
+ /**
102
+ * Stable non-cryptographic hex hash (FNV-1a, 64-bit as two 32-bit lanes).
103
+ * For derived identifiers — provider cache keys, conversation routing ids —
104
+ * where the only requirement is determinism. Pure JS on purpose: node:crypto
105
+ * would drag a node builtin into browser bundles of this library (the werewolf
106
+ * design kit bundles the catalog, and esbuild must resolve every import in the
107
+ * graph even for code that later tree-shakes away).
108
+ */
109
+ declare function stableHashHex(input: string): string;
110
+
111
+ /**
112
+ * Validates and parses a response using a Zod schema
113
+ * @param schema - The Zod schema to validate against
114
+ * @param data - The data to validate
115
+ * @returns Parsed and validated data
116
+ * @throws ZodError if validation fails
117
+ */
118
+ declare function validateResponse<T>(schema: z.ZodSchema<T>, data: unknown): T;
119
+ /**
120
+ * Safely validates a response, returning validation result
121
+ * @param schema - The Zod schema to validate against
122
+ * @param data - The data to validate
123
+ * @returns Success/error result object
124
+ */
125
+ declare function safeValidateResponse<T>(schema: z.ZodSchema<T>, data: unknown): z.SafeParseReturnType<unknown, T>;
126
+
127
+ type ProviderType = 'openai' | 'anthropic' | 'google' | 'mistral' | 'deepseek' | 'grok' | 'kimi';
128
+ interface JsonSchemaOptions {
129
+ strict?: boolean;
130
+ includeDescription?: boolean;
131
+ additionalProperties?: boolean;
132
+ }
133
+ interface ProviderSchema {
134
+ type: 'json_schema' | 'prompt_description' | 'google_schema';
135
+ content: any;
136
+ }
137
+ /**
138
+ * Universal schema converter that transforms Zod schemas to provider-specific formats
139
+ */
140
+ declare class ZodSchemaConverter {
141
+ /**
142
+ * Convert Zod schema to OpenAI-compatible JSON Schema
143
+ */
144
+ static toOpenAIJsonSchema(zodSchema: z.ZodSchema, schemaName: string): any;
145
+ /**
146
+ * Convert Zod schema to Google Gemini responseSchema format
147
+ * This follows the official Gemini structured output format
148
+ */
149
+ static toGoogleSchema(zodSchema: z.ZodSchema): any;
150
+ /**
151
+ * Internal method to convert Zod types to Google schema format
152
+ */
153
+ private static convertZodToGoogleType;
154
+ /**
155
+ * Convert Zod schema to standard JSON Schema format
156
+ * Public method for external use (e.g., Grok structured outputs)
157
+ */
158
+ static toJsonSchema(zodSchema: z.ZodSchema, options?: JsonSchemaOptions): any;
159
+ /**
160
+ * Convert Zod schema to Mistral/DeepSeek JSON Schema format
161
+ */
162
+ static toMistralSchema(zodSchema: z.ZodSchema): any;
163
+ /**
164
+ * Convert Zod schema to human-readable prompt description for Anthropic
165
+ */
166
+ static toPromptDescription(zodSchema: z.ZodSchema): string;
167
+ /**
168
+ * Get provider-specific schema format
169
+ */
170
+ static forProvider(zodSchema: z.ZodSchema, provider: ProviderType, schemaName?: string): ProviderSchema;
171
+ /**
172
+ * Core Zod to JSON Schema conversion
173
+ */
174
+ private static zodToJsonSchema;
175
+ /**
176
+ * Convert individual Zod types to JSON Schema format
177
+ */
178
+ private static convertZodType;
179
+ /**
180
+ * Recursively add additionalProperties: false to all object types for strict validation
181
+ */
182
+ private static makeSchemaStrict;
183
+ /**
184
+ * Build human-readable schema description for prompt-based providers
185
+ */
186
+ private static buildSchemaDescription;
187
+ /**
188
+ * Get type description for schema properties
189
+ */
190
+ private static getTypeDescription;
191
+ /**
192
+ * Build inline object description without leading indentation
193
+ */
194
+ private static buildInlineObjectDescription;
195
+ }
196
+ /**
197
+ * Helper function to generate schema instructions for any provider
198
+ */
199
+ declare function generateSchemaInstructions(zodSchema: z.ZodSchema, provider: ProviderType, schemaName?: string): string;
200
+ /**
201
+ * Validate that a provider supports native JSON Schema
202
+ */
203
+ declare function supportsNativeJsonSchema(provider: ProviderType): boolean;
204
+ /**
205
+ * Check if a provider needs prompt-based schema descriptions
206
+ */
207
+ declare function needsPromptBasedSchema(provider: ProviderType): boolean;
208
+
209
+ /**
210
+ * Extract the first balanced JSON object embedded in `text`.
211
+ * String- and escape-aware, so braces inside string values don't break the scan.
212
+ * If the first candidate fails to parse, scanning continues from the next '{'.
213
+ * Returns null when no parseable object is found.
214
+ */
215
+ declare function extractFirstJsonObject(text: string): unknown | null;
216
+ /**
217
+ * Lenient parse + Zod validation of an LLM text reply, shared by all agents.
218
+ *
219
+ * Order of attempts:
220
+ * 1. Strict JSON parse of the fence-stripped reply (plus a quote-unwrapped
221
+ * variant for Gemini's quoted-JSON-string quirk).
222
+ * 2. Extraction of the first balanced JSON object embedded in prose
223
+ * (rescues "Sure, here is my answer: {...}" replies).
224
+ * 3. Re-bracing replies that look like an object body missing its outer braces
225
+ * (rescues MiniMax-M3's `"who": "...", "why": "..."` replies).
226
+ * 4. Wrapping raw prose as `{ reply: ... }` for BotAnswer-shaped schemas
227
+ * (rescues bots that "speak in character" instead of returning JSON).
228
+ *
229
+ * Throws with the same message prefixes the agents have always used
230
+ * ("Failed to parse JSON response:", "Response validation failed:") so log
231
+ * queries and error handling stay stable.
232
+ */
233
+ declare function parseAndValidateLlmJson<T>(rawReply: string, zodSchema: z.ZodSchema<T>, log?: (message: string) => void): T;
234
+
235
+ /**
236
+ * Custom error classes for AI agent interactions
237
+ */
238
+ declare abstract class ModelError extends Error {
239
+ modelType: string;
240
+ constructor(message: string, modelType: string);
241
+ }
242
+ declare class ModelOverloadError extends ModelError {
243
+ retryable: boolean;
244
+ constructor(message: string, modelType: string, retryable?: boolean);
245
+ }
246
+ declare class ModelRateLimitError extends ModelError {
247
+ retryAfter?: number;
248
+ constructor(message: string, modelType: string, retryAfter?: number);
249
+ }
250
+ declare class ModelUnavailableError extends ModelError {
251
+ reason: string;
252
+ constructor(message: string, modelType: string, reason?: string);
253
+ }
254
+ declare class ModelAuthenticationError extends ModelError {
255
+ constructor(message: string, modelType: string);
256
+ }
257
+ declare class ModelQuotaExceededError extends ModelError {
258
+ constructor(message: string, modelType: string);
259
+ }
260
+ /**
261
+ * The model declined to answer: Anthropic returns `stop_reason: "refusal"` with no content
262
+ * blocks when its safety layer rejects the request as a whole. Not retryable as-is — the
263
+ * same prompt will refuse again — the caller has to change the prompt or the model.
264
+ * Observed 2026-08-30 on Claude Fable 5: a persona system prompt plus a narrated multi-turn
265
+ * history that ends by asking the character what it does refuses, while either half alone
266
+ * answers; Sonnet 5 and Opus 4.8 answer the same requests.
267
+ */
268
+ declare class ModelRefusalError extends ModelError {
269
+ constructor(modelType: string, message?: string);
270
+ }
271
+
272
+ /**
273
+ * Defense against chain-of-thought leaking into visible chat messages.
274
+ *
275
+ * The OpenAI-compatible reasoning providers (DeepSeek, GLM, Kimi, Qwen,
276
+ * MiniMax, Fugu) are all documented to return thinking in a separate field
277
+ * (`reasoning_content` / `reasoning_details`), but models occasionally
278
+ * misbehave and inline a `<think>…</think>` block into `message.content`
279
+ * instead — observed live with qwen-plus (2026-08), and MiniMax documents it
280
+ * as the default without `reasoning_split`. If that text reaches the lenient
281
+ * JSON parser, its wrap-as-reply fallback can surface the ENTIRE chain of
282
+ * thought — secret role included — as the bot's visible message.
283
+ *
284
+ * Every agent that reads `choices[0].message.content` must pass it through
285
+ * here before parsing, and merge the returned `thinking` into its thinking
286
+ * output so nothing is silently dropped.
287
+ */
288
+ declare function stripInlineThinking(raw: string): {
289
+ text: string;
290
+ thinking: string;
291
+ };
292
+ /** Joins provider-reported reasoning with any inline thinking salvaged from content. */
293
+ declare function mergeThinking(...parts: Array<string | undefined | null>): string;
294
+
295
+ /**
296
+ * Model catalog and pricing.
297
+ *
298
+ * This is the library's single source of truth for how to talk to each supported model —
299
+ * API name, key name, thinking dialect, per-model tuning defaults (temperature, reasoning
300
+ * effort, thinking budgets, output ceilings) — and what each model costs. Tuning values are
301
+ * operational defaults discovered against the live APIs; consumers can adjust them per model
302
+ * via `createCatalog(overrides)`, but anything that would ever be fixed for *correctness*
303
+ * (a model rejecting a parameter, an effort level eating the output budget) belongs here,
304
+ * so every consumer inherits the fix with a version bump.
305
+ *
306
+ * App-level policy — tier limits, deprecated-id migration, markup — deliberately lives in
307
+ * the consumer, keyed by the same stable model ids.
308
+ */
309
+ declare const API_KEY_CONSTANTS: {
310
+ readonly OPENAI: "OPENAI_API_KEY";
311
+ readonly ANTHROPIC: "ANTHROPIC_API_KEY";
312
+ readonly GOOGLE: "GOOGLE_API_KEY";
313
+ readonly MISTRAL: "MISTRAL_API_KEY";
314
+ readonly DEEPSEEK: "DEEPSEEK_API_KEY";
315
+ readonly GROK: "GROK_API_KEY";
316
+ readonly MOONSHOT: "MOONSHOT_API_KEY";
317
+ readonly Z_AI: "Z_AI_API_KEY";
318
+ readonly FUGU: "FUGU_API_KEY";
319
+ readonly QWEN: "QWEN_API_KEY";
320
+ readonly MINIMAX: "MINIMAX_API_KEY";
321
+ };
322
+ declare const SupportedAiKeyNames: Record<string, string>;
323
+ declare const LLM_CONSTANTS: {
324
+ CLAUDE_FABLE: string;
325
+ CLAUDE_OPUS: string;
326
+ CLAUDE_SONNET: string;
327
+ CLAUDE_HAIKU: string;
328
+ DEEPSEEK_FLASH: string;
329
+ DEEPSEEK_PRO: string;
330
+ GPT_SOL: string;
331
+ GPT: string;
332
+ GPT_MINI: string;
333
+ GEMINI_PRO: string;
334
+ GEMINI_FLASH: string;
335
+ GEMINI_LITE: string;
336
+ MISTRAL_LARGE: string;
337
+ MISTRAL_MEDIUM: string;
338
+ MISTRAL_SMALL: string;
339
+ MISTRAL_MAGISTRAL: string;
340
+ GROK: string;
341
+ KIMI: string;
342
+ GLM: string;
343
+ GLM_FLASH: string;
344
+ FUGU_ULTRA: string;
345
+ QWEN_MAX: string;
346
+ QWEN_FLASH: string;
347
+ MINIMAX: string;
348
+ };
349
+ /**
350
+ * Per-request output ceiling for ordinary requests. Reasoning tokens are billed inside this
351
+ * budget on every provider, so the cap has to clear thinking AND the answer — set below what
352
+ * a request really emits and the *answer* is what gets truncated, producing malformed JSON
353
+ * rather than a cheaper request.
354
+ *
355
+ * NOTE this is a blast-radius cap, not a cost lever: providers bill tokens generated, never
356
+ * the unused ceiling. Lowering it saves nothing on a well-behaved request — it only bounds a
357
+ * runaway one. Reasoning effort and thinking budgets are the knobs that change spend.
358
+ */
359
+ declare const DEFAULT_MAX_OUTPUT_TOKENS = 8192;
360
+ type ModelTag = 'very-fast' | 'fast' | 'slow' | 'very-slow' | 'extremely-slow' | 'cheap' | 'expensive';
361
+ type ReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
362
+ /**
363
+ * What a catalog entry produces. Only text agents exist today; TTS, STT and image
364
+ * generation are planned as subpath exports, and their catalog entries will carry the
365
+ * matching modality so consumers can filter (a text-model picker must not list a voice).
366
+ * Omitted means 'text'.
367
+ */
368
+ type Modality = 'text' | 'tts' | 'stt' | 'image';
369
+ interface ModelConfig {
370
+ displayName: string;
371
+ modelApiName: string;
372
+ apiKeyName: string;
373
+ modality?: Modality;
374
+ hasThinking: boolean;
375
+ temperature?: number;
376
+ reasoningEffort?: ReasoningEffort;
377
+ thinkingBudgetTokens?: number;
378
+ maxOutputTokens?: number;
379
+ tags?: ModelTag[];
380
+ }
381
+ declare const SupportedAiModels: Record<string, ModelConfig>;
382
+ type LLMModel = keyof typeof SupportedAiModels;
383
+ /**
384
+ * Builds a catalog from the library defaults with per-model partial overrides merged on top.
385
+ * The merge is per-model and shallow: `{ glm: { temperature: 0.9 } }` changes only that field
386
+ * and keeps the rest of the default entry. Ids absent from the defaults are added verbatim
387
+ * (they must then be complete ModelConfig entries).
388
+ */
389
+ declare function createCatalog(overrides?: Record<string, Partial<ModelConfig>>): Record<string, ModelConfig>;
390
+ declare function getModelTags(modelId: string): ModelTag[];
391
+ declare function modelHasTag(modelId: string, tag: ModelTag): boolean;
392
+ /** Speed is an ordered scale — "fast" filters must also admit very-fast models. */
393
+ declare function modelIsFast(modelId: string): boolean;
394
+ declare function getModelDisplayName(modelId: string): string;
395
+ /** Human-readable provider name ("Anthropic", "Grok", …) for a model id, if known. */
396
+ declare function getModelProviderName(modelId: string): string | undefined;
397
+ /**
398
+ * Looks up a model's config by API name. Since the catalog went thinking-only (2026-08-05) each
399
+ * modelApiName has a single entry, so hasThinking no longer disambiguates anything; it is kept
400
+ * for call-site compatibility and as a filter should variants ever return.
401
+ */
402
+ declare function getModelConfigByApiName(modelApiName: string, hasThinking?: boolean): ModelConfig | undefined;
403
+ /**
404
+ * Model pricing configuration
405
+ * All prices are in USD per 1,000,000 tokens
406
+ */
407
+ /**
408
+ * What a price is quoted per. Text models bill per million tokens; the planned TTS entries
409
+ * bill per million characters, STT per minute of audio, image models per image (or per
410
+ * output token, in which case they stay 'tokens'). Omitted means 'tokens'.
411
+ */
412
+ type PricingUnit = 'tokens' | 'characters' | 'minutes' | 'images';
413
+ interface ModelPricing {
414
+ unit?: PricingUnit;
415
+ inputPrice: number;
416
+ outputPrice: number;
417
+ cacheHitPrice?: number;
418
+ extendedContextInputPrice?: number;
419
+ extendedContextOutputPrice?: number;
420
+ extendedContextCacheHitPrice?: number;
421
+ extendedContextThresholdTokens?: number;
422
+ peakPricing?: PeakPricing;
423
+ }
424
+ /**
425
+ * Time-of-day surcharge applied to all billing items (input, output, cache) when the
426
+ * request falls inside one of the UTC windows.
427
+ */
428
+ interface PeakPricing {
429
+ multiplier: number;
430
+ windowsUtc: Array<[number, number]>;
431
+ /** When set, the windows apply Monday–Friday only: a request that falls on a Saturday or
432
+ * Sunday in the provider's local timezone (given as a UTC offset in hours) bills at the
433
+ * base rate all day. */
434
+ weekendOffPeak?: {
435
+ utcOffsetHours: number;
436
+ };
437
+ }
438
+ /** True if the timestamp's UTC time-of-day falls inside any [startHour, endHour) window. */
439
+ declare function isInPeakWindow(timestampMs: number, windowsUtc: Array<[number, number]>): boolean;
440
+ /** True if the timestamp falls on a Saturday or Sunday in the timezone at the given UTC offset. */
441
+ declare function isWeekendAt(timestampMs: number, utcOffsetHours: number): boolean;
442
+ /** True if a request at this timestamp bills at the peak multiplier under the schedule. */
443
+ declare function isPeakBilling(timestampMs: number, peak: PeakPricing): boolean;
444
+ /** DeepSeek's peak-valley schedule: 2× during Beijing 09:00–12:00 and 14:00–18:00
445
+ * (UTC 1–4, 6–10), Monday–Friday Beijing time only. */
446
+ declare const DEEPSEEK_PEAK_SCHEDULE: PeakPricing;
447
+ /**
448
+ * Centralized pricing configuration for all AI models
449
+ * All prices are per million (1,000,000) tokens
450
+ */
451
+ declare const MODEL_PRICING: Record<string, ModelPricing>;
452
+ /** True for hybrid thinking-only models — the ones whose effective output price is a known
453
+ * multiple of the sticker price. Always-on reasoning models (GPT-5, Gemini, Grok, Kimi,
454
+ * Fable, Magistral) also burn reasoning tokens, but their multiplier hasn't been measured. */
455
+ declare function isHybridThinkingModel(modelApiName: string): boolean;
456
+ interface CostCalculationOptions {
457
+ cacheHitTokens?: number;
458
+ contextTokens?: number;
459
+ totalTokens?: number;
460
+ timestamp?: number;
461
+ }
462
+ /**
463
+ * Helper function to calculate cost based on model pricing
464
+ * @param modelApiName - The API name of the model
465
+ * @param inputTokens - Number of input tokens
466
+ * @param outputTokens - Number of output tokens
467
+ * @param options - Additional calculation details (cache hits, context tokens, etc.)
468
+ * @returns Cost in USD
469
+ */
470
+ declare function calculateModelCost(modelApiName: string, inputTokens: number, outputTokens: number, options?: CostCalculationOptions): number;
471
+ /**
472
+ * Returns provider-specific signature fields based on the model's API name prefix.
473
+ * Used when storing messages with thinking signatures from different providers.
474
+ * @param aiType - The model API name (e.g. "claude-sonnet-5", "gemini-3.7-flash")
475
+ * @param signature - The thinking signature from the API response (may be undefined)
476
+ * @returns Object with appropriate signature fields for the message
477
+ */
478
+ declare function getProviderSignatureFields(aiType: string, signature?: string): {
479
+ anthropicThinkingSignature?: string;
480
+ googleThoughtSignature?: string;
481
+ grokEncryptedReasoning?: string;
482
+ };
483
+
484
+ /**
485
+ * Per-provider reasoning-effort vocabularies.
486
+ *
487
+ * `ReasoningEffort` (catalog.ts) is the union of every provider's scale so a catalog entry or
488
+ * a per-call override can name any level; each provider accepts only its own slice and most
489
+ * reject the rest with a 400. The `to<Provider>Effort` helpers clamp a generic level to the
490
+ * nearest one the provider takes, so a consumer can say "high" for every model and let the
491
+ * agent translate. Nearest is by rank on the shared scale; a tie resolves upward (asking for
492
+ * "medium" from a provider with only low|high gets high — never less reasoning than asked).
493
+ *
494
+ * Verified against provider docs 2026-08-30:
495
+ * - OpenAI GPT-5.x: minimal|low|medium|high|xhigh
496
+ * - Anthropic adaptive thinking (Fable 5 / Opus 4.8 / Sonnet 5): low|medium|high|xhigh|max
497
+ * - Gemini 3.x thinkingLevel: minimal|low|medium|high (3.1 Pro and 3.7 Flash reject minimal)
498
+ * - Z.AI GLM-5.3 / 5.3-Flash: low|high|max only
499
+ * - DeepSeek V4: low|high|max (the API itself aliases medium → high)
500
+ * - Sakana Fugu: high|xhigh
501
+ * Qwen accepts reasoning_effort but ignores it (thinking_budget is its knob); MiniMax, Kimi,
502
+ * Grok and Mistral expose no effort parameter.
503
+ */
504
+ type OpenAIReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
505
+ type AnthropicReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
506
+ type GeminiReasoningEffort = 'minimal' | 'low' | 'medium' | 'high';
507
+ type GlmReasoningEffort = 'low' | 'high' | 'max';
508
+ type DeepSeekReasoningEffort = 'low' | 'high' | 'max';
509
+ type FuguReasoningEffort = 'high' | 'xhigh';
510
+ /** The shared scale, lowest first. */
511
+ declare const REASONING_EFFORT_SCALE: readonly ReasoningEffort[];
512
+ declare const OPENAI_REASONING_EFFORTS: readonly OpenAIReasoningEffort[];
513
+ declare const ANTHROPIC_REASONING_EFFORTS: readonly AnthropicReasoningEffort[];
514
+ declare const GEMINI_REASONING_EFFORTS: readonly GeminiReasoningEffort[];
515
+ declare const GLM_REASONING_EFFORTS: readonly GlmReasoningEffort[];
516
+ declare const DEEPSEEK_REASONING_EFFORTS: readonly DeepSeekReasoningEffort[];
517
+ declare const FUGU_REASONING_EFFORTS: readonly FuguReasoningEffort[];
518
+ /** Clamps `effort` to the nearest level in `allowed` (by rank on the shared scale, ties go up). */
519
+ declare function clampReasoningEffort<T extends ReasoningEffort>(effort: ReasoningEffort, allowed: readonly T[]): T;
520
+ declare const toOpenAIEffort: (effort: ReasoningEffort) => OpenAIReasoningEffort;
521
+ declare const toAnthropicEffort: (effort: ReasoningEffort) => AnthropicReasoningEffort;
522
+ declare const toGeminiEffort: (effort: ReasoningEffort) => GeminiReasoningEffort;
523
+ declare const toGlmEffort: (effort: ReasoningEffort) => GlmReasoningEffort;
524
+ declare const toDeepSeekEffort: (effort: ReasoningEffort) => DeepSeekReasoningEffort;
525
+ declare const toFuguEffort: (effort: ReasoningEffort) => FuguReasoningEffort;
526
+
527
+ /**
528
+ * Unified token usage utilities for all AI providers
529
+ * This module provides a consistent interface for token usage extraction and cost calculation
530
+ * across all supported AI providers (OpenAI, DeepSeek, Kimi, Grok, Anthropic, Google, Mistral)
531
+ */
532
+
533
+ /**
534
+ * Generic token usage interface that covers all provider-specific fields
535
+ */
536
+ interface TokenUsage {
537
+ promptTokens: number;
538
+ completionTokens: number;
539
+ totalTokens: number;
540
+ cacheHitTokens?: number;
541
+ cacheMissTokens?: number;
542
+ reasoningTokens?: number;
543
+ }
544
+ /**
545
+ * Extract token usage from any AI provider's API response
546
+ * This function handles the common response formats used by different providers
547
+ * @param response - The raw API response from any provider
548
+ * @returns TokenUsage object with extracted values or null if extraction fails
549
+ */
550
+ declare function extractTokenUsage(response: any): TokenUsage | null;
551
+ /**
552
+ * Calculate cost for any AI provider using the centralized pricing
553
+ * @param modelApiName - The API name of the model (e.g., 'gpt-5.5', 'deepseek-v4-flash')
554
+ * @param inputTokens - Number of input tokens used
555
+ * @param outputTokens - Number of output tokens used
556
+ * @param options - Additional calculation details (cache hits, context tokens, etc.)
557
+ * @returns Cost in USD
558
+ */
559
+ declare function calculateCost(modelApiName: string, inputTokens: number, outputTokens: number, options?: CostCalculationOptions): number;
560
+ /**
561
+ * Extract token usage and calculate cost in one operation
562
+ * @param modelApiName - The API name of the model
563
+ * @param response - The raw API response from any provider
564
+ * @returns Object with token usage and calculated cost, or null if extraction fails
565
+ */
566
+ declare function extractUsageAndCalculateCost(modelApiName: string, response: any): {
567
+ usage: TokenUsage;
568
+ cost: number;
569
+ } | null;
570
+ /**
571
+ * DeepSeek-specific token usage extraction
572
+ * Handles DeepSeek's specific cache and reasoning token fields
573
+ */
574
+ declare function extractDeepSeekTokenUsage(response: any): TokenUsage | null;
575
+ /**
576
+ * OpenAI-specific token usage extraction
577
+ * Handles OpenAI's cache tokens and reasoning tokens (for o1 models)
578
+ */
579
+ declare function extractOpenAITokenUsage(response: any): TokenUsage | null;
580
+ /**
581
+ * Kimi-specific token usage extraction
582
+ * Kimi uses OpenAI-compatible format
583
+ */
584
+ declare function extractKimiTokenUsage(response: any): TokenUsage | null;
585
+ /**
586
+ * Grok-specific token usage extraction
587
+ * Grok uses OpenAI-compatible format
588
+ */
589
+ declare function extractGrokTokenUsage(response: any): TokenUsage | null;
590
+ /**
591
+ * Anthropic-specific token usage extraction
592
+ * Anthropic may have different response format
593
+ */
594
+ declare function extractAnthropicTokenUsage(response: any): TokenUsage | null;
595
+ /**
596
+ * Google-specific token usage extraction
597
+ * Google may have different response format
598
+ */
599
+ declare function extractGoogleTokenUsage(response: any): TokenUsage | null;
600
+ /**
601
+ * Mistral-specific token usage extraction
602
+ * Mistral SDK uses camelCase (promptTokens, completionTokens, totalTokens)
603
+ * and reasoning tokens may be in additionalProperties for Magistral models
604
+ */
605
+ declare function extractMistralTokenUsage(response: any): TokenUsage | null;
606
+
607
+ /**
608
+ * OpenAI pricing utilities
609
+ * Re-exports unified utilities with OpenAI-specific naming for backward compatibility
610
+ */
611
+ /**
612
+ * Calculate the cost for token usage based on OpenAI pricing
613
+ * @param model - The OpenAI model name
614
+ * @param inputTokens - Number of input tokens used
615
+ * @param outputTokens - Number of output tokens used
616
+ * @param cacheHitTokens - Number of cached input tokens (optional)
617
+ * @returns Cost in USD
618
+ */
619
+ declare function calculateOpenAICost(model: string, inputTokens: number, outputTokens: number, cacheHitTokens?: number): number;
620
+ /**
621
+ * Extract token usage from OpenAI API response
622
+ * @param response - The raw response from OpenAI API
623
+ * @returns Token usage object with extracted values
624
+ */
625
+ interface OpenAITokenUsage {
626
+ promptTokens: number;
627
+ completionTokens: number;
628
+ totalTokens: number;
629
+ cacheHitTokens?: number;
630
+ reasoningTokens?: number;
631
+ }
632
+ declare function extractTokenUsageFromResponse$6(response: any): OpenAITokenUsage | null;
633
+
634
+ /**
635
+ * DeepSeek pricing utilities
636
+ * Re-exports unified utilities with DeepSeek-specific naming for backward compatibility
637
+ */
638
+ /**
639
+ * Calculate the cost for token usage based on DeepSeek pricing
640
+ * @param model - The DeepSeek model name
641
+ * @param inputTokens - Number of input tokens used
642
+ * @param outputTokens - Number of output tokens used
643
+ * @param cacheHitTokens - Number of cached input tokens (optional)
644
+ * @returns Cost in USD
645
+ */
646
+ declare function calculateDeepSeekCost(model: string, inputTokens: number, outputTokens: number, cacheHitTokens?: number): number;
647
+ /**
648
+ * Extract token usage from DeepSeek API response
649
+ * @param response - The raw response from DeepSeek API
650
+ * @returns TokenUsage object with extracted values
651
+ */
652
+ interface DeepSeekTokenUsage {
653
+ promptTokens: number;
654
+ completionTokens: number;
655
+ totalTokens: number;
656
+ cacheHitTokens?: number;
657
+ cacheMissTokens?: number;
658
+ reasoningTokens?: number;
659
+ }
660
+ declare function extractTokenUsageFromResponse$5(response: any): DeepSeekTokenUsage | null;
661
+
662
+ /**
663
+ * Kimi (Moonshot AI) pricing utilities
664
+ * Re-exports unified utilities with Kimi-specific naming for backward compatibility
665
+ */
666
+ /**
667
+ * Calculate the cost for token usage based on Kimi pricing
668
+ * @param model - The Kimi model name
669
+ * @param inputTokens - Number of input tokens used
670
+ * @param outputTokens - Number of output tokens used
671
+ * @returns Cost in USD
672
+ */
673
+ declare function calculateKimiCost(model: string, inputTokens: number, outputTokens: number): number;
674
+ /**
675
+ * Extract token usage from Kimi API response
676
+ * Since Kimi uses OpenAI-compatible format, the response structure should be similar
677
+ * @param response - The raw response from Kimi API
678
+ * @returns Token usage object with extracted values
679
+ */
680
+ interface KimiTokenUsage {
681
+ promptTokens: number;
682
+ completionTokens: number;
683
+ totalTokens: number;
684
+ }
685
+ declare function extractTokenUsageFromResponse$4(response: any): KimiTokenUsage | null;
686
+
687
+ /**
688
+ * Grok (xAI) pricing utilities
689
+ * Re-exports unified utilities with Grok-specific naming for backward compatibility
690
+ */
691
+ /**
692
+ * Calculate the cost for token usage based on Grok pricing
693
+ * @param model - The Grok model name
694
+ * @param inputTokens - Number of input tokens used (prompt_tokens)
695
+ * @param outputTokens - Number of output tokens used (completion_tokens, includes reasoning_tokens)
696
+ * @param cacheHitTokens - Number of cached input tokens (optional, when supported)
697
+ * @returns Cost in USD
698
+ */
699
+ declare function calculateGrokCost(model: string, inputTokens: number, outputTokens: number, cacheHitTokens?: number): number;
700
+ /**
701
+ * Extract token usage from Grok API response
702
+ * @param response - The raw response from Grok API
703
+ * @returns Token usage object with extracted values
704
+ */
705
+ interface GrokTokenUsage {
706
+ promptTokens: number;
707
+ completionTokens: number;
708
+ totalTokens: number;
709
+ cacheHitTokens?: number;
710
+ reasoningTokens?: number;
711
+ }
712
+ declare function extractTokenUsageFromResponse$3(response: any): GrokTokenUsage | null;
713
+
714
+ /**
715
+ * Anthropic pricing utilities
716
+ * Re-exports unified utilities with Anthropic-specific naming for consistency
717
+ */
718
+ /**
719
+ * Calculate the cost for token usage based on Anthropic pricing
720
+ * @param model - The Anthropic model name
721
+ * @param inputTokens - Number of input tokens used
722
+ * @param outputTokens - Number of output tokens used
723
+ * @param cacheHitTokens - Number of cached input tokens (optional, when supported)
724
+ * @returns Cost in USD
725
+ */
726
+ declare function calculateAnthropicCost(model: string, inputTokens: number, outputTokens: number, cacheHitTokens?: number): number;
727
+ /**
728
+ * Extract token usage from Anthropic API response
729
+ * @param response - The raw response from Anthropic API
730
+ * @returns Token usage object with extracted values
731
+ */
732
+ interface AnthropicTokenUsage {
733
+ promptTokens: number;
734
+ completionTokens: number;
735
+ totalTokens: number;
736
+ }
737
+ declare function extractTokenUsageFromResponse$2(response: any): AnthropicTokenUsage | null;
738
+
739
+ /**
740
+ * Google pricing utilities
741
+ * Re-exports unified utilities with Google-specific naming for consistency
742
+ */
743
+
744
+ /**
745
+ * Calculate the cost for token usage based on Google pricing
746
+ * @param model - The Google model name
747
+ * @param inputTokens - Number of input tokens used
748
+ * @param outputTokens - Number of output tokens used
749
+ * @param cacheHitTokens - Number of cached input tokens (optional, when supported)
750
+ * @returns Cost in USD
751
+ */
752
+ declare function calculateGoogleCost(model: string, inputTokens: number, outputTokens: number, options?: CostCalculationOptions): number;
753
+ /**
754
+ * Extract token usage from Google API response
755
+ * @param response - The raw response from Google API
756
+ * @returns Token usage object with extracted values
757
+ */
758
+ interface GoogleTokenUsage {
759
+ promptTokens: number;
760
+ completionTokens: number;
761
+ totalTokens: number;
762
+ }
763
+ declare function extractTokenUsageFromResponse$1(response: any): GoogleTokenUsage | null;
764
+
765
+ /**
766
+ * Mistral pricing utilities
767
+ * Re-exports unified utilities with Mistral-specific naming for consistency
768
+ */
769
+ /**
770
+ * Calculate the cost for token usage based on Mistral pricing
771
+ * @param model - The Mistral model name
772
+ * @param inputTokens - Number of input tokens used
773
+ * @param outputTokens - Number of output tokens used
774
+ * @param cacheHitTokens - Number of cached input tokens (optional, when supported)
775
+ * @returns Cost in USD
776
+ */
777
+ declare function calculateMistralCost(model: string, inputTokens: number, outputTokens: number, cacheHitTokens?: number): number;
778
+ /**
779
+ * Extract token usage from Mistral API response
780
+ * @param response - The raw response from Mistral API
781
+ * @returns Token usage object with extracted values
782
+ */
783
+ interface MistralTokenUsage {
784
+ promptTokens: number;
785
+ completionTokens: number;
786
+ totalTokens: number;
787
+ }
788
+ declare function extractTokenUsageFromResponse(response: any): MistralTokenUsage | null;
789
+
790
+ declare abstract class AbstractAgent {
791
+ name: string;
792
+ gameId?: string;
793
+ userId?: string;
794
+ /**
795
+ * Output ceiling sent with every request from this agent. Resolved once from the model's
796
+ * catalog override, else DEFAULT_MAX_OUTPUT_TOKENS. Callers needing more room raise it
797
+ * after construction (see story generation), the same way gameId/userId are assigned —
798
+ * so subclasses must read it when building a request, never snapshot it at construction.
799
+ */
800
+ maxOutputTokens: number;
801
+ /**
802
+ * Reasoning-depth knobs, resolved once from the catalog like maxOutputTokens and, like it,
803
+ * overridable per instance for calls whose profile differs from a turn (story generation
804
+ * runs deeper). Each provider speaks one dialect — effort (DeepSeek, GLM, Gemini, Claude
805
+ * adaptive) or a token budget (Qwen, Claude Haiku) — and reads only the field it
806
+ * understands; the other is ignored. Subclasses read these when building a request.
807
+ */
808
+ reasoningEffort?: ReasoningEffort;
809
+ thinkingBudgetTokens?: number;
810
+ protected readonly instruction: string;
811
+ /**
812
+ * The instruction split on CACHE_TIER_MARKER: [shared static tier, per-bot tier].
813
+ * Length 1 when the prompt has no marker (GM prompts, tests). Providers with
814
+ * explicit cache breakpoints (Anthropic) place one per part; everyone else uses
815
+ * the joined marker-free `instruction`, whose shared prefix implicit caches match.
816
+ */
817
+ protected readonly instructionParts: string[];
818
+ protected readonly temperature: number;
819
+ protected readonly model: string;
820
+ protected readonly enableThinking: boolean;
821
+ protected readonly agentLoggingConfig: AgentLoggingConfig;
822
+ protected constructor(name: string, instruction: string, model: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
823
+ /**
824
+ * Public ask API — template methods that time the provider call and stamp `durationMs`
825
+ * into the returned TokenUsage. Subclasses implement doAskWithZodSchema/doAskText and
826
+ * must NOT override these.
827
+ */
828
+ askWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
829
+ askText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
830
+ private stampDuration;
831
+ /** Failed calls carry their duration too — a 35s provider stall that errors is still signal. */
832
+ private stampErrorDuration;
833
+ protected abstract doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
834
+ /**
835
+ * Plain-text ask: no schema appended to the prompt, no JSON mode, no parsing.
836
+ * Returns [content, thinkingContent, tokenUsage?, thinkingSignature?] — same tuple
837
+ * shape as doAskWithZodSchema but with the raw response string as content.
838
+ * Implementations must throw on empty content so the recoverable-error/retry UX
839
+ * is preserved (errors surface in the UI; the user triggers retries).
840
+ */
841
+ protected abstract doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
842
+ protected logger(message: string): void;
843
+ protected logAsking(messages: AIMessage[]): void;
844
+ protected logSystemPrompt(): void;
845
+ protected logMessages(messages: AIMessage[]): void;
846
+ protected logReply(reply: any, thinking?: string, usage?: TokenUsage$1): void;
847
+ /**
848
+ * Merges consecutive user messages (e.g. a GM command followed by the detached
849
+ * reminder postfix) into one, for providers that expect alternating roles — this
850
+ * reproduces the pre-detachment request shape. ClaudeAgent overrides this to keep
851
+ * them separate: Anthropic combines consecutive user turns into one turn but keeps
852
+ * distinct content blocks, which lets its fast cache breakpoint sit on the persisted
853
+ * command block while the throwaway reminder rides behind it.
854
+ */
855
+ protected prepareMessages(messages: AIMessage[]): AIMessage[];
856
+ }
857
+
858
+ declare class AgentFactory {
859
+ static createAgent(name: string, instruction: string, llmType: string, apiKeys: ApiKeyMap, enableThinking?: boolean): AbstractAgent;
860
+ private static validateLlmTypeAndGet;
861
+ }
862
+
863
+ declare class ClaudeAgent extends AbstractAgent {
864
+ private readonly client;
865
+ private get defaultParams();
866
+ private readonly logTemplates;
867
+ private readonly errorMessages;
868
+ constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
869
+ /**
870
+ * Unlike the base class, does NOT merge consecutive user messages: the Messages API
871
+ * combines consecutive user turns into a single turn while preserving separate content
872
+ * blocks, so the trailing reminder stays out of the persisted command block and the
873
+ * fast cache breakpoint (see applyCacheBreakpoint) lands on bytes that repeat.
874
+ */
875
+ protected prepareMessages(messages: AIMessage[]): AIMessage[];
876
+ private convertToAnthropicMessages;
877
+ /**
878
+ * Converts messages for thinking-enabled requests.
879
+ * Assistant messages include thinking blocks ONLY if they have valid signatures.
880
+ * If a signature is missing, the thinking block is dropped to ensure API validity.
881
+ */
882
+ private convertToAnthropicMessagesWithThinking;
883
+ /**
884
+ * Breakpoint 2 (fast tier): the last message that will be re-sent byte-identically on
885
+ * the next request. That is the SECOND-to-last message, not the last one — the final
886
+ * user message carries unpersisted content (the reminder postfix / schema description)
887
+ * appended to the GM command, so its bytes never repeat and a breakpoint there would be
888
+ * a pure 1.25x write tax with no reads. The second-to-last message (the bot's previous
889
+ * reply, or an earlier flushed block) reappears verbatim next turn, where the moved-
890
+ * forward breakpoint finds it via the 20-block lookback.
891
+ *
892
+ * NOT the top-level auto-caching mode: that mode targets the LAST cacheable block,
893
+ * which for us is exactly the never-repeated tail — every entry it wrote would be dead.
894
+ */
895
+ private applyCacheBreakpoint;
896
+ /**
897
+ * Builds TokenUsage from the response. Anthropic's input_tokens EXCLUDES cached tokens
898
+ * (total prompt = input_tokens + cache_read + cache_creation), unlike the OpenAI-shaped
899
+ * providers whose prompt_tokens include them — so reconstruct the full prompt size here
900
+ * before pricing. Cache reads bill at the cacheHitPrice (~0.1x); cache writes bill at
901
+ * 1.25x input, which MODEL_PRICING doesn't model, so written tokens are priced at the
902
+ * plain input rate (~20% undercount on the written span only).
903
+ */
904
+ private buildTokenUsage;
905
+ private convertRole;
906
+ /**
907
+ * New method using Zod with Anthropic's Claude API
908
+ * Since Anthropic doesn't support native JSON schemas, we generate prompt descriptions
909
+ */
910
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
911
+ /**
912
+ * Plain-text ask: same request as askWithZodSchema but without a schema description
913
+ * appended to the prompt and without JSON parsing. Thinking blocks and signatures
914
+ * are extracted identically.
915
+ */
916
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
917
+ }
918
+
919
+ declare class Gpt5Agent extends AbstractAgent {
920
+ private readonly client;
921
+ private readonly logTemplates;
922
+ private readonly errorMessages;
923
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
924
+ /**
925
+ * Structured output method using Zod with OpenAI's Responses API
926
+ * This provides better schema handling and runtime validation
927
+ *
928
+ * Uses responses.parse for models that support structured outputs
929
+ */
930
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
931
+ /**
932
+ * Plain-text ask via the Responses API: no structured-output format, raw output_text.
933
+ * Note: askWithZodSchema surfaces "thinking" via a schema-injected field; that trick
934
+ * doesn't apply to plain text, so thinking content is empty here (OpenAI does not
935
+ * expose chain-of-thought directly).
936
+ */
937
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
938
+ }
939
+
940
+ declare class GoogleAgent extends AbstractAgent {
941
+ private readonly client;
942
+ private readonly defaultConfig;
943
+ private readonly logTemplates;
944
+ private readonly errorMessages;
945
+ constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
946
+ private convertToContents;
947
+ private convertRole;
948
+ private calculateCost;
949
+ private calculateCostWithCacheHits;
950
+ private deriveContextTokens;
951
+ /**
952
+ * New method using Zod with Google's Gemini API
953
+ * This provides better schema handling and runtime validation
954
+ */
955
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
956
+ /**
957
+ * Plain-text ask: same request as askWithZodSchema but without responseSchema /
958
+ * responseMimeType, returning the raw text. Thinking parts and thought signatures
959
+ * are extracted identically.
960
+ */
961
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
962
+ /**
963
+ * Handles Gemini API errors and throws appropriate specific exceptions
964
+ * @param error - The error to handle
965
+ */
966
+ private handleGeminiError;
967
+ }
968
+
969
+ declare class MistralAgent extends AbstractAgent {
970
+ private readonly client;
971
+ private get defaultParams();
972
+ private readonly logTemplates;
973
+ private readonly errorMessages;
974
+ constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
975
+ private convertToMistralMessages;
976
+ private processReply;
977
+ private processStructuredReply;
978
+ private extractTokenUsage;
979
+ /**
980
+ * New method using Zod with Mistral API
981
+ * This provides better schema handling and runtime validation
982
+ *
983
+ * Uses Mistral Custom Structured Outputs (responseFormat json_schema), which
984
+ * enforces the response shape server-side and is more reliable than plain JSON
985
+ * mode. The human-readable schema description is still appended to the last
986
+ * message because the enforced schema omits field descriptions/semantics.
987
+ */
988
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
989
+ /**
990
+ * Plain-text ask: no schema appended, no responseFormat. Note that Magistral
991
+ * reasoning models only return thinking traces when responseFormat is NOT
992
+ * json_object, so unlike askWithZodSchema this path can surface thinking content.
993
+ */
994
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
995
+ }
996
+
997
+ declare class DeepSeekV2Agent extends AbstractAgent {
998
+ private readonly client;
999
+ private readonly logTemplates;
1000
+ private readonly errorMessages;
1001
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1002
+ private convertToOpenAIMessages;
1003
+ private addSystemInstruction;
1004
+ /**
1005
+ * Thinking params for the request body. DeepSeek V4 toggles thinking with a top-level
1006
+ * `thinking: { type }` (the docs' `extra_body` is a Python-SDK wrapper; openai-node has no
1007
+ * such thing and sends the key literally, where the API ignores it — probed 2026-08-30:
1008
+ * `extra_body: {thinking: {type: 'disabled'}}` still reasoned, top-level `thinking` did
1009
+ * not). Thinking is on by default, so the flag matters only for turning it off.
1010
+ * `reasoning_effort` takes low|high|max (default high, no budget parameter exists); it is
1011
+ * the instance field (catalog default, per-call override) and is only sent when set.
1012
+ */
1013
+ private thinkingParams;
1014
+ /**
1015
+ * New method using Zod with DeepSeek API
1016
+ * This provides better schema handling and runtime validation
1017
+ *
1018
+ * DeepSeek V4 uses thinking toggle via extra_body. JSON mode (response_format
1019
+ * json_object) is supported with or without thinking, so we always request it.
1020
+ * Thinking additionally surfaces reasoning via reasoning_content.
1021
+ */
1022
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1023
+ /**
1024
+ * Plain-text ask: same request structure as askWithZodSchema but without JSON mode
1025
+ * or a schema appended to the prompt. The raw response string is returned as-is.
1026
+ */
1027
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1028
+ }
1029
+
1030
+ /**
1031
+ * xAI Grok agent on the Responses API.
1032
+ *
1033
+ * grok-4.6 is an always-on reasoning model; we do not send `reasoning_effort` and use the
1034
+ * xAI default ("high"). Reasoning cannot be disabled. Each response's encrypted reasoning
1035
+ * items (requested via `include: ["reasoning.encrypted_content"]`) are returned as the 4th
1036
+ * tuple element, stored on the game message as `grokEncryptedReasoning`, and replayed into
1037
+ * `input` on later turns so the model keeps its chain-of-thought across the conversation.
1038
+ */
1039
+ declare class GrokAgent extends AbstractAgent {
1040
+ private readonly client;
1041
+ private readonly logTemplates;
1042
+ private readonly errorMessages;
1043
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1044
+ /**
1045
+ * Structured output implementation for Grok using json_object mode with prompt
1046
+ * augmentation — more reliable than json_schema on OpenAI-compatible endpoints.
1047
+ */
1048
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1049
+ /**
1050
+ * Plain-text ask: no JSON mode and no schema appended to the prompt.
1051
+ * Reasoning extraction and token accounting are identical to askWithZodSchema.
1052
+ */
1053
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1054
+ private createResponse;
1055
+ /**
1056
+ * Converts game history to Responses API input items. The system instruction is
1057
+ * merged into the leading system message; assistant messages carrying stored
1058
+ * encrypted reasoning get their reasoning items replayed right before them.
1059
+ */
1060
+ private buildResponsesInput;
1061
+ /**
1062
+ * Walks the response output items: reasoning items yield the human-readable summary
1063
+ * plus the encrypted items (serialized for storage/replay); message items yield text.
1064
+ */
1065
+ private extractResponseParts;
1066
+ private extractTokenUsage;
1067
+ }
1068
+
1069
+ declare class KimiAgent extends AbstractAgent {
1070
+ private readonly client;
1071
+ private get defaultParams();
1072
+ private readonly logTemplates;
1073
+ private readonly errorMessages;
1074
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1075
+ private convertToOpenAIMessages;
1076
+ private extractThinkingAndUsage;
1077
+ /**
1078
+ * New method using Zod with Kimi/Moonshot AI API
1079
+ * This provides better schema handling and runtime validation
1080
+ *
1081
+ * Kimi/Moonshot AI API is OpenAI-compatible, so we try JSON mode first,
1082
+ * and fall back to prompt-based schema if not supported
1083
+ */
1084
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1085
+ /**
1086
+ * Plain-text ask: no JSON mode (and therefore no prompt-based schema fallback).
1087
+ * Thinking toggle and reasoning_content extraction are identical to askWithZodSchema.
1088
+ */
1089
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1090
+ }
1091
+
1092
+ declare class GlmAgent extends AbstractAgent {
1093
+ private readonly client;
1094
+ private get defaultParams();
1095
+ private readonly logTemplates;
1096
+ private readonly errorMessages;
1097
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1098
+ private convertToOpenAIMessages;
1099
+ private extractThinkingAndUsage;
1100
+ /**
1101
+ * Robust schema-aware coercion of a model reply.
1102
+ * Order: strict JSON parse → embedded {…} extraction → wrap-as-reply (BotAnswer-shaped schemas).
1103
+ * Returns the validated value or throws.
1104
+ */
1105
+ private parseAndValidate;
1106
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1107
+ /**
1108
+ * Plain-text ask: no JSON mode and no schema appended to the prompt.
1109
+ * Thinking toggle and reasoning_content extraction are identical to askWithZodSchema.
1110
+ */
1111
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1112
+ }
1113
+
1114
+ declare class FuguAgent extends AbstractAgent {
1115
+ private readonly client;
1116
+ private get defaultParams();
1117
+ private readonly logTemplates;
1118
+ private readonly errorMessages;
1119
+ constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1120
+ private convertToOpenAIMessages;
1121
+ private logRawUsageForCalibration;
1122
+ private extractThinkingAndUsage;
1123
+ private prependSystemInstruction;
1124
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1125
+ /**
1126
+ * Plain-text ask: no schema appended to the prompt. Reasoning extraction and token
1127
+ * accounting are identical to askWithZodSchema.
1128
+ */
1129
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1130
+ }
1131
+
1132
+ declare class QwenAgent extends AbstractAgent {
1133
+ private readonly client;
1134
+ private get defaultParams();
1135
+ private readonly logTemplates;
1136
+ private readonly errorMessages;
1137
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1138
+ /**
1139
+ * Thinking params for the request body. `thinking_budget` caps reasoning length and is only
1140
+ * sent when the instance has one (catalog default, or a per-call override like story
1141
+ * generation); without it the model thinks at the provider default, and qwen3.8-max's
1142
+ * latency then swings 30–100s.
1143
+ *
1144
+ * `reasoning_effort` is deliberately NOT sent. Probed live 2026-08-30 on qwen3.8-flash and
1145
+ * qwen3.8-max: every value low..max is accepted, but reasoning length doesn't track it
1146
+ * (max: low → 1,686 reasoning tokens / 44s, high → 226 / 7s, xhigh → 1,102 / 30s), while
1147
+ * thinking_budget bounds it reliably (≤340 at 1024). The docs also call the two mutually
1148
+ * exclusive on qwen3.8-max. So on Qwen the budget IS the effort knob; `reasoningEffort`
1149
+ * on this agent is ignored.
1150
+ */
1151
+ private thinkingParams;
1152
+ private convertToOpenAIMessages;
1153
+ private extractThinkingAndUsage;
1154
+ /**
1155
+ * Robust schema-aware coercion of a model reply.
1156
+ * Order: strict JSON parse → embedded {…} extraction → wrap-as-reply (BotAnswer-shaped schemas).
1157
+ * Returns the validated value or throws.
1158
+ */
1159
+ private parseAndValidate;
1160
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1161
+ /**
1162
+ * Plain-text ask: no schema appended to the prompt.
1163
+ * Thinking toggle and reasoning_content extraction are identical to askWithZodSchema.
1164
+ */
1165
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1166
+ }
1167
+
1168
+ declare class MiniMaxAgent extends AbstractAgent {
1169
+ private readonly client;
1170
+ private get defaultParams();
1171
+ private readonly logTemplates;
1172
+ private readonly errorMessages;
1173
+ constructor(name: string, instruction: string, model: string, apiKey: string, temperature: number, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1174
+ private thinkingParams;
1175
+ private convertToOpenAIMessages;
1176
+ private extractThinkingAndUsage;
1177
+ /**
1178
+ * Robust schema-aware coercion of a model reply.
1179
+ * Order: strict JSON parse → embedded {…} extraction → wrap-as-reply (BotAnswer-shaped schemas).
1180
+ * Returns the validated value or throws.
1181
+ */
1182
+ private parseAndValidate;
1183
+ doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1184
+ /**
1185
+ * Plain-text ask: no schema appended to the prompt.
1186
+ * Thinking handling and reasoning_content extraction are identical to askWithZodSchema.
1187
+ */
1188
+ doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1189
+ }
1190
+
1191
+ export { type AIMessage, ANTHROPIC_REASONING_EFFORTS, API_KEY_CONSTANTS, AbstractAgent, type AgentActivityData, AgentFactory, type AgentLoggingConfig, type AnthropicReasoningEffort, type AnthropicTokenUsage, type ApiKeyMap, BotResponseError, CACHE_TIER_MARKER, ClaudeAgent, type CostCalculationOptions, DEEPSEEK_PEAK_SCHEDULE, DEEPSEEK_REASONING_EFFORTS, DEFAULT_LOGGING_CONFIG, DEFAULT_MAX_OUTPUT_TOKENS, type DeepSeekReasoningEffort, type DeepSeekTokenUsage, DeepSeekV2Agent, FUGU_REASONING_EFFORTS, FuguAgent, type FuguReasoningEffort, GEMINI_REASONING_EFFORTS, GLM_REASONING_EFFORTS, type GeminiReasoningEffort, GlmAgent, type GlmReasoningEffort, GoogleAgent, type GoogleTokenUsage, Gpt5Agent, GrokAgent, type GrokTokenUsage, type JsonSchemaOptions, KimiAgent, type KimiTokenUsage, type LLMModel, LLM_CONSTANTS, type LlmLogger, type LoggingConfig, MESSAGE_ROLE, MODEL_PRICING, MiniMaxAgent, MistralAgent, type MistralTokenUsage, type Modality, ModelAuthenticationError, type ModelConfig, ModelError, ModelOverloadError, type ModelPricing, ModelQuotaExceededError, ModelRateLimitError, ModelRefusalError, type ModelTag, ModelUnavailableError, OPENAI_REASONING_EFFORTS, type OpenAIReasoningEffort, type OpenAITokenUsage, type PeakPricing, type PricingUnit, type ProviderSchema, type TokenUsage as ProviderTokenUsage, type ProviderType, QwenAgent, REASONING_EFFORT_SCALE, type ReasoningEffort, SupportedAiKeyNames, SupportedAiModels, type TokenUsage$1 as TokenUsage, ZodSchemaConverter, calculateAnthropicCost, calculateCost, calculateDeepSeekCost, calculateGoogleCost, calculateGrokCost, calculateKimiCost, calculateMistralCost, calculateModelCost, calculateOpenAICost, clampReasoningEffort, cleanResponse, createCatalog, extractAnthropicTokenUsage, extractTokenUsageFromResponse$2 as extractAnthropicTokenUsageFromResponse, extractDeepSeekTokenUsage, extractTokenUsageFromResponse$5 as extractDeepSeekTokenUsageFromResponse, extractFirstJsonObject, extractGoogleTokenUsage, extractTokenUsageFromResponse$1 as extractGoogleTokenUsageFromResponse, extractGrokTokenUsage, extractTokenUsageFromResponse$3 as extractGrokTokenUsageFromResponse, extractKimiTokenUsage, extractTokenUsageFromResponse$4 as extractKimiTokenUsageFromResponse, extractMistralTokenUsage, extractTokenUsageFromResponse as extractMistralTokenUsageFromResponse, extractOpenAITokenUsage, extractTokenUsageFromResponse$6 as extractOpenAITokenUsageFromResponse, extractTokenUsage, extractUsageAndCalculateCost, generateSchemaInstructions, getModelConfigByApiName, getModelDisplayName, getModelProviderName, getModelTags, getProviderSignatureFields, isHybridThinkingModel, isInPeakWindow, isPeakBilling, isWeekendAt, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, parseAndValidateLlmJson, safeValidateResponse, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toOpenAIEffort, validateResponse };