@hiper2d/ai-agents 0.5.2 → 0.6.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/dist/index.d.mts CHANGED
@@ -363,10 +363,8 @@ declare const LLM_CONSTANTS: {
363
363
  GEMINI_PRO: string;
364
364
  GEMINI_FLASH: string;
365
365
  GEMINI_LITE: string;
366
- MISTRAL_LARGE: string;
367
366
  MISTRAL_MEDIUM: string;
368
367
  MISTRAL_SMALL: string;
369
- MISTRAL_MAGISTRAL: string;
370
368
  GROK: string;
371
369
  KIMI: string;
372
370
  GLM: string;
@@ -482,7 +480,7 @@ declare const DEEPSEEK_PEAK_SCHEDULE: PeakPricing;
482
480
  declare const MODEL_PRICING: Record<string, ModelPricing>;
483
481
  /** True for hybrid thinking-only models — the ones whose effective output price is a known
484
482
  * multiple of the sticker price. Always-on reasoning models (GPT-5, Gemini, Grok, Kimi,
485
- * Fable, Magistral) also burn reasoning tokens, but their multiplier hasn't been measured. */
483
+ * Fable) also burn reasoning tokens, but their multiplier hasn't been measured. */
486
484
  declare function isHybridThinkingModel(modelApiName: string): boolean;
487
485
  interface CostCalculationOptions {
488
486
  cacheHitTokens?: number;
@@ -532,8 +530,13 @@ declare function getProviderSignatureFields(aiType: string, signature?: string):
532
530
  * - Sakana Fugu: high|xhigh
533
531
  * - Meta Muse Spark (verified 2026-09-12): minimal|low|medium|high|xhigh|max ("none" → 400; max is
534
532
  * Standard tier only)
535
- * Qwen accepts reasoning_effort but ignores it (thinking_budget is its knob); MiniMax, Kimi,
536
- * Grok and Mistral expose no effort parameter.
533
+ * - Mistral Small 4 / Medium 3.5 (verified 2026-09-18): the API enum is
534
+ * none|minimal|low|medium|high|xhigh, with reasoning OFF unless the field is sent. "none" is
535
+ * not on the shared scale and means "don't reason", which an agent expresses by omitting the
536
+ * field, so the exported slice starts at minimal. Only "high" is documented to return the
537
+ * thinking chunk; the intermediate levels are accepted but unverified.
538
+ * Qwen accepts reasoning_effort but ignores it (thinking_budget is its knob); MiniMax, Kimi and
539
+ * Grok expose no effort parameter.
537
540
  */
538
541
  type OpenAIReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
539
542
  type AnthropicReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
@@ -542,6 +545,7 @@ type GlmReasoningEffort = 'low' | 'high' | 'max';
542
545
  type DeepSeekReasoningEffort = 'low' | 'high' | 'max';
543
546
  type FuguReasoningEffort = 'high' | 'xhigh';
544
547
  type MetaReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
548
+ type MistralReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
545
549
  /** The shared scale, lowest first. */
546
550
  declare const REASONING_EFFORT_SCALE: readonly ReasoningEffort[];
547
551
  declare const OPENAI_REASONING_EFFORTS: readonly OpenAIReasoningEffort[];
@@ -551,6 +555,7 @@ declare const GLM_REASONING_EFFORTS: readonly GlmReasoningEffort[];
551
555
  declare const DEEPSEEK_REASONING_EFFORTS: readonly DeepSeekReasoningEffort[];
552
556
  declare const FUGU_REASONING_EFFORTS: readonly FuguReasoningEffort[];
553
557
  declare const META_REASONING_EFFORTS: readonly MetaReasoningEffort[];
558
+ declare const MISTRAL_REASONING_EFFORTS: readonly MistralReasoningEffort[];
554
559
  /** Clamps `effort` to the nearest level in `allowed` (by rank on the shared scale, ties go up). */
555
560
  declare function clampReasoningEffort<T extends ReasoningEffort>(effort: ReasoningEffort, allowed: readonly T[]): T;
556
561
  declare const toOpenAIEffort: (effort: ReasoningEffort) => OpenAIReasoningEffort;
@@ -560,6 +565,7 @@ declare const toGlmEffort: (effort: ReasoningEffort) => GlmReasoningEffort;
560
565
  declare const toDeepSeekEffort: (effort: ReasoningEffort) => DeepSeekReasoningEffort;
561
566
  declare const toMetaEffort: (effort: ReasoningEffort) => MetaReasoningEffort;
562
567
  declare const toFuguEffort: (effort: ReasoningEffort) => FuguReasoningEffort;
568
+ declare const toMistralEffort: (effort: ReasoningEffort) => MistralReasoningEffort;
563
569
 
564
570
  /**
565
571
  * Unified token usage utilities for all AI providers
@@ -641,8 +647,10 @@ declare function extractAnthropicTokenUsage(response: any): TokenUsage | null;
641
647
  declare function extractGoogleTokenUsage(response: any): TokenUsage | null;
642
648
  /**
643
649
  * Mistral-specific token usage extraction
644
- * Mistral SDK uses camelCase (promptTokens, completionTokens, totalTokens)
645
- * and reasoning tokens may be in additionalProperties for Magistral models
650
+ * Mistral SDK uses camelCase (promptTokens, completionTokens, totalTokens). Reasoning tokens
651
+ * are not itemised today (they sit inside completionTokens, observed 2026-09-18 on Small 4 and
652
+ * Medium 3.5 with reasoning_effort: high); the additionalProperties probe below stays in case
653
+ * a reasoning_tokens field ever appears.
646
654
  */
647
655
  declare function extractMistralTokenUsage(response: any): TokenUsage | null;
648
656
 
@@ -1417,12 +1425,36 @@ declare class GoogleAgent extends AbstractAgent {
1417
1425
  private handleGeminiError;
1418
1426
  }
1419
1427
 
1428
+ /**
1429
+ * Mistral agent (Mistral SDK chat.complete) for the hybrid Small 4 / Medium 3.5 models.
1430
+ *
1431
+ * Reasoning is off on the API by default and switched on per request with `reasoning_effort`
1432
+ * (docs.mistral.ai/studio/conversations/reasoning). SDK 1.x has no typed field for it, so it is
1433
+ * injected into the wire body by the same beforeRequest hook that adds `prompt_cache_key`.
1434
+ * With it set, the assistant message comes back as content chunks — a `thinking` chunk (a list
1435
+ * of text chunks holding the trace) followed by the `text` answer — and this works together
1436
+ * with json_schema structured output (verified live 2026-09-18 on both models). Without the
1437
+ * field the reply is a plain string and no trace exists.
1438
+ *
1439
+ * Multi-turn: Mistral asks that the full assistant message, thinking chunk included, be
1440
+ * replayed into history ("stripping reasoning traces degrades performance"). The trace is
1441
+ * plain text, so it rides on `AIMessage.thinking` — no provider signature field — and
1442
+ * convertToMistralMessages rebuilds each prior assistant turn as [thinking, text] chunks.
1443
+ *
1444
+ * Reasoning tokens are counted inside completion_tokens; no separate reasoning_tokens field
1445
+ * arrives, so cost accounting on the output rate already covers the trace.
1446
+ */
1420
1447
  declare class MistralAgent extends AbstractAgent {
1421
1448
  private readonly client;
1422
1449
  private get defaultParams();
1423
1450
  private readonly logTemplates;
1424
1451
  private readonly errorMessages;
1425
1452
  constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1453
+ /**
1454
+ * History in Mistral's shape. A prior assistant turn that carries a stored trace is
1455
+ * replayed as [thinking, text] chunks, as Mistral's multi-turn guidance asks; every other
1456
+ * turn is a plain string.
1457
+ */
1426
1458
  private convertToMistralMessages;
1427
1459
  private processReply;
1428
1460
  private processStructuredReply;
@@ -1438,9 +1470,8 @@ declare class MistralAgent extends AbstractAgent {
1438
1470
  */
1439
1471
  doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1440
1472
  /**
1441
- * Plain-text ask: no schema appended, no responseFormat. Note that Magistral
1442
- * reasoning models only return thinking traces when responseFormat is NOT
1443
- * json_object, so unlike askWithZodSchema this path can surface thinking content.
1473
+ * Plain-text ask: no schema appended, no responseFormat. Reasoning (and the trace) works
1474
+ * the same way as on the schema path.
1444
1475
  */
1445
1476
  doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1446
1477
  }
@@ -1690,4 +1721,4 @@ declare class MiniMaxAgent extends AbstractAgent {
1690
1721
  doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1691
1722
  }
1692
1723
 
1693
- export { type AIMessage, ANTHROPIC_REASONING_EFFORTS, API_KEY_CONSTANTS, AbstractAgent, type AgentActivityData, AgentFactory, type AgentLoggingConfig, type AnthropicReasoningEffort, type AnthropicTokenUsage, type ApiKeyMap, type BeforeAskHook, BotResponseError, BudgetController, type BudgetControllerOptions, BudgetExceededError, type BudgetLimit, type BudgetVerdict, 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_AUDIO_TOKENS_PER_SECOND, GEMINI_REASONING_EFFORTS, GLM_REASONING_EFFORTS, type GeminiReasoningEffort, GlmAgent, type GlmReasoningEffort, GoogleAgent, type GoogleSttOptions, type GoogleSttResult, type GoogleTokenUsage, type GoogleTtsAudioOptions, type GoogleTtsResult, GoogleVoiceAgent, Gpt5Agent, GrokAgent, type GrokTokenUsage, InMemorySpendStore, type JsonSchemaOptions, KimiAgent, type KimiTokenUsage, type LLMModel, LLM_CONSTANTS, type LlmLogger, type LoggingConfig, MESSAGE_ROLE, META_REASONING_EFFORTS, MODEL_PRICING, MetaAgent, type MetaReasoningEffort, type MetaTokenUsage, MiniMaxAgent, MistralAgent, type MistralTokenUsage, type Modality, ModelAuthenticationError, type ModelConfig, ModelError, ModelInvalidResponseError, ModelOverloadError, type ModelPricing, ModelQuotaExceededError, ModelRateLimitError, ModelRefusalError, type ModelTag, ModelUnavailableError, OPENAI_REASONING_EFFORTS, type OpenAIReasoningEffort, type OpenAITokenUsage, type OpenAiSttOptions, type OpenAiSttResult, type OpenAiTtsAudioOptions, type OpenAiTtsVoice, OpenAiVoiceAgent, type PeakPricing, type PricingUnit, type ProviderSchema, type TokenUsage as ProviderTokenUsage, type ProviderType, QwenAgent, REASONING_EFFORT_SCALE, type ReasoningEffort, SUPPORTED_VOICE_PROVIDERS, type SpeechRequest, type SpeechResult, type SpeechUsage, type SpendInput, type SpendKind, type SpendLedger, type SpendLedgers, type SpendStore, type SpendWindow, SupportedAiKeyNames, SupportedAiModels, type TokenPairUsage, type TokenUsage$1 as TokenUsage, type TranscriptionRequest, type TranscriptionResult, type TranscriptionUsage, VOICE_MODEL_CONSTANTS, VOICE_MODEL_PRICING, VOICE_PROVIDER_API_KEY, type VoiceAgent, VoiceAgentFactory, type VoiceModelPricing, type VoiceProvider, ZodSchemaConverter, applySpend, buildGoogleTtsPrompt, calculateAnthropicCost, calculateCost, calculateDeepSeekCost, calculateGeminiSttCost, calculateGeminiTtsCost, calculateGoogleCost, calculateGrokCost, calculateKimiCost, calculateMetaCost, calculateMistralCost, calculateModelCost, calculateOpenAICost, calculateOpenAiSttCost, calculateOpenAiTtsCost, clampReasoningEffort, cleanResponse, createCatalog, createVoiceAgent, describeEmptyTtsResponse, evaluateBudget, extractAnthropicTokenUsage, extractTokenUsageFromResponse$2 as extractAnthropicTokenUsageFromResponse, extractDeepSeekTokenUsage, extractTokenUsageFromResponse$6 as extractDeepSeekTokenUsageFromResponse, extractFirstJsonObject, extractGoogleTokenUsage, extractTokenUsageFromResponse$1 as extractGoogleTokenUsageFromResponse, extractGrokTokenUsage, extractTokenUsageFromResponse$4 as extractGrokTokenUsageFromResponse, extractKimiTokenUsage, extractTokenUsageFromResponse$5 as extractKimiTokenUsageFromResponse, extractMetaTokenUsage, extractTokenUsageFromResponse$3 as extractMetaTokenUsageFromResponse, extractMistralTokenUsage, extractTokenUsageFromResponse as extractMistralTokenUsageFromResponse, extractOpenAITokenUsage, extractTokenUsageFromResponse$7 as extractOpenAITokenUsageFromResponse, extractTokenUsage, extractUsageAndCalculateCost, firstRefusal, generateGoogleTtsAudio, generateOpenAiTtsAudio, generateSchemaInstructions, getModelConfigByApiName, getModelDisplayName, getModelProviderName, getModelTags, getProviderSignatureFields, isBudgetExceededError, isHybridThinkingModel, isInPeakWindow, isPeakBilling, isWeekendAt, ledgerSpend, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, parseAndValidateLlmJson, pcmToWav, periodEnd, periodKey, safeValidateResponse, setBeforeAskHook, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toMetaEffort, toOpenAIEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
1724
+ export { type AIMessage, ANTHROPIC_REASONING_EFFORTS, API_KEY_CONSTANTS, AbstractAgent, type AgentActivityData, AgentFactory, type AgentLoggingConfig, type AnthropicReasoningEffort, type AnthropicTokenUsage, type ApiKeyMap, type BeforeAskHook, BotResponseError, BudgetController, type BudgetControllerOptions, BudgetExceededError, type BudgetLimit, type BudgetVerdict, 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_AUDIO_TOKENS_PER_SECOND, GEMINI_REASONING_EFFORTS, GLM_REASONING_EFFORTS, type GeminiReasoningEffort, GlmAgent, type GlmReasoningEffort, GoogleAgent, type GoogleSttOptions, type GoogleSttResult, type GoogleTokenUsage, type GoogleTtsAudioOptions, type GoogleTtsResult, GoogleVoiceAgent, Gpt5Agent, GrokAgent, type GrokTokenUsage, InMemorySpendStore, type JsonSchemaOptions, KimiAgent, type KimiTokenUsage, type LLMModel, LLM_CONSTANTS, type LlmLogger, type LoggingConfig, MESSAGE_ROLE, META_REASONING_EFFORTS, MISTRAL_REASONING_EFFORTS, MODEL_PRICING, MetaAgent, type MetaReasoningEffort, type MetaTokenUsage, MiniMaxAgent, MistralAgent, type MistralReasoningEffort, type MistralTokenUsage, type Modality, ModelAuthenticationError, type ModelConfig, ModelError, ModelInvalidResponseError, ModelOverloadError, type ModelPricing, ModelQuotaExceededError, ModelRateLimitError, ModelRefusalError, type ModelTag, ModelUnavailableError, OPENAI_REASONING_EFFORTS, type OpenAIReasoningEffort, type OpenAITokenUsage, type OpenAiSttOptions, type OpenAiSttResult, type OpenAiTtsAudioOptions, type OpenAiTtsVoice, OpenAiVoiceAgent, type PeakPricing, type PricingUnit, type ProviderSchema, type TokenUsage as ProviderTokenUsage, type ProviderType, QwenAgent, REASONING_EFFORT_SCALE, type ReasoningEffort, SUPPORTED_VOICE_PROVIDERS, type SpeechRequest, type SpeechResult, type SpeechUsage, type SpendInput, type SpendKind, type SpendLedger, type SpendLedgers, type SpendStore, type SpendWindow, SupportedAiKeyNames, SupportedAiModels, type TokenPairUsage, type TokenUsage$1 as TokenUsage, type TranscriptionRequest, type TranscriptionResult, type TranscriptionUsage, VOICE_MODEL_CONSTANTS, VOICE_MODEL_PRICING, VOICE_PROVIDER_API_KEY, type VoiceAgent, VoiceAgentFactory, type VoiceModelPricing, type VoiceProvider, ZodSchemaConverter, applySpend, buildGoogleTtsPrompt, calculateAnthropicCost, calculateCost, calculateDeepSeekCost, calculateGeminiSttCost, calculateGeminiTtsCost, calculateGoogleCost, calculateGrokCost, calculateKimiCost, calculateMetaCost, calculateMistralCost, calculateModelCost, calculateOpenAICost, calculateOpenAiSttCost, calculateOpenAiTtsCost, clampReasoningEffort, cleanResponse, createCatalog, createVoiceAgent, describeEmptyTtsResponse, evaluateBudget, extractAnthropicTokenUsage, extractTokenUsageFromResponse$2 as extractAnthropicTokenUsageFromResponse, extractDeepSeekTokenUsage, extractTokenUsageFromResponse$6 as extractDeepSeekTokenUsageFromResponse, extractFirstJsonObject, extractGoogleTokenUsage, extractTokenUsageFromResponse$1 as extractGoogleTokenUsageFromResponse, extractGrokTokenUsage, extractTokenUsageFromResponse$4 as extractGrokTokenUsageFromResponse, extractKimiTokenUsage, extractTokenUsageFromResponse$5 as extractKimiTokenUsageFromResponse, extractMetaTokenUsage, extractTokenUsageFromResponse$3 as extractMetaTokenUsageFromResponse, extractMistralTokenUsage, extractTokenUsageFromResponse as extractMistralTokenUsageFromResponse, extractOpenAITokenUsage, extractTokenUsageFromResponse$7 as extractOpenAITokenUsageFromResponse, extractTokenUsage, extractUsageAndCalculateCost, firstRefusal, generateGoogleTtsAudio, generateOpenAiTtsAudio, generateSchemaInstructions, getModelConfigByApiName, getModelDisplayName, getModelProviderName, getModelTags, getProviderSignatureFields, isBudgetExceededError, isHybridThinkingModel, isInPeakWindow, isPeakBilling, isWeekendAt, ledgerSpend, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, parseAndValidateLlmJson, pcmToWav, periodEnd, periodKey, safeValidateResponse, setBeforeAskHook, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toMetaEffort, toMistralEffort, toOpenAIEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
package/dist/index.d.ts CHANGED
@@ -363,10 +363,8 @@ declare const LLM_CONSTANTS: {
363
363
  GEMINI_PRO: string;
364
364
  GEMINI_FLASH: string;
365
365
  GEMINI_LITE: string;
366
- MISTRAL_LARGE: string;
367
366
  MISTRAL_MEDIUM: string;
368
367
  MISTRAL_SMALL: string;
369
- MISTRAL_MAGISTRAL: string;
370
368
  GROK: string;
371
369
  KIMI: string;
372
370
  GLM: string;
@@ -482,7 +480,7 @@ declare const DEEPSEEK_PEAK_SCHEDULE: PeakPricing;
482
480
  declare const MODEL_PRICING: Record<string, ModelPricing>;
483
481
  /** True for hybrid thinking-only models — the ones whose effective output price is a known
484
482
  * multiple of the sticker price. Always-on reasoning models (GPT-5, Gemini, Grok, Kimi,
485
- * Fable, Magistral) also burn reasoning tokens, but their multiplier hasn't been measured. */
483
+ * Fable) also burn reasoning tokens, but their multiplier hasn't been measured. */
486
484
  declare function isHybridThinkingModel(modelApiName: string): boolean;
487
485
  interface CostCalculationOptions {
488
486
  cacheHitTokens?: number;
@@ -532,8 +530,13 @@ declare function getProviderSignatureFields(aiType: string, signature?: string):
532
530
  * - Sakana Fugu: high|xhigh
533
531
  * - Meta Muse Spark (verified 2026-09-12): minimal|low|medium|high|xhigh|max ("none" → 400; max is
534
532
  * Standard tier only)
535
- * Qwen accepts reasoning_effort but ignores it (thinking_budget is its knob); MiniMax, Kimi,
536
- * Grok and Mistral expose no effort parameter.
533
+ * - Mistral Small 4 / Medium 3.5 (verified 2026-09-18): the API enum is
534
+ * none|minimal|low|medium|high|xhigh, with reasoning OFF unless the field is sent. "none" is
535
+ * not on the shared scale and means "don't reason", which an agent expresses by omitting the
536
+ * field, so the exported slice starts at minimal. Only "high" is documented to return the
537
+ * thinking chunk; the intermediate levels are accepted but unverified.
538
+ * Qwen accepts reasoning_effort but ignores it (thinking_budget is its knob); MiniMax, Kimi and
539
+ * Grok expose no effort parameter.
537
540
  */
538
541
  type OpenAIReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
539
542
  type AnthropicReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
@@ -542,6 +545,7 @@ type GlmReasoningEffort = 'low' | 'high' | 'max';
542
545
  type DeepSeekReasoningEffort = 'low' | 'high' | 'max';
543
546
  type FuguReasoningEffort = 'high' | 'xhigh';
544
547
  type MetaReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
548
+ type MistralReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
545
549
  /** The shared scale, lowest first. */
546
550
  declare const REASONING_EFFORT_SCALE: readonly ReasoningEffort[];
547
551
  declare const OPENAI_REASONING_EFFORTS: readonly OpenAIReasoningEffort[];
@@ -551,6 +555,7 @@ declare const GLM_REASONING_EFFORTS: readonly GlmReasoningEffort[];
551
555
  declare const DEEPSEEK_REASONING_EFFORTS: readonly DeepSeekReasoningEffort[];
552
556
  declare const FUGU_REASONING_EFFORTS: readonly FuguReasoningEffort[];
553
557
  declare const META_REASONING_EFFORTS: readonly MetaReasoningEffort[];
558
+ declare const MISTRAL_REASONING_EFFORTS: readonly MistralReasoningEffort[];
554
559
  /** Clamps `effort` to the nearest level in `allowed` (by rank on the shared scale, ties go up). */
555
560
  declare function clampReasoningEffort<T extends ReasoningEffort>(effort: ReasoningEffort, allowed: readonly T[]): T;
556
561
  declare const toOpenAIEffort: (effort: ReasoningEffort) => OpenAIReasoningEffort;
@@ -560,6 +565,7 @@ declare const toGlmEffort: (effort: ReasoningEffort) => GlmReasoningEffort;
560
565
  declare const toDeepSeekEffort: (effort: ReasoningEffort) => DeepSeekReasoningEffort;
561
566
  declare const toMetaEffort: (effort: ReasoningEffort) => MetaReasoningEffort;
562
567
  declare const toFuguEffort: (effort: ReasoningEffort) => FuguReasoningEffort;
568
+ declare const toMistralEffort: (effort: ReasoningEffort) => MistralReasoningEffort;
563
569
 
564
570
  /**
565
571
  * Unified token usage utilities for all AI providers
@@ -641,8 +647,10 @@ declare function extractAnthropicTokenUsage(response: any): TokenUsage | null;
641
647
  declare function extractGoogleTokenUsage(response: any): TokenUsage | null;
642
648
  /**
643
649
  * Mistral-specific token usage extraction
644
- * Mistral SDK uses camelCase (promptTokens, completionTokens, totalTokens)
645
- * and reasoning tokens may be in additionalProperties for Magistral models
650
+ * Mistral SDK uses camelCase (promptTokens, completionTokens, totalTokens). Reasoning tokens
651
+ * are not itemised today (they sit inside completionTokens, observed 2026-09-18 on Small 4 and
652
+ * Medium 3.5 with reasoning_effort: high); the additionalProperties probe below stays in case
653
+ * a reasoning_tokens field ever appears.
646
654
  */
647
655
  declare function extractMistralTokenUsage(response: any): TokenUsage | null;
648
656
 
@@ -1417,12 +1425,36 @@ declare class GoogleAgent extends AbstractAgent {
1417
1425
  private handleGeminiError;
1418
1426
  }
1419
1427
 
1428
+ /**
1429
+ * Mistral agent (Mistral SDK chat.complete) for the hybrid Small 4 / Medium 3.5 models.
1430
+ *
1431
+ * Reasoning is off on the API by default and switched on per request with `reasoning_effort`
1432
+ * (docs.mistral.ai/studio/conversations/reasoning). SDK 1.x has no typed field for it, so it is
1433
+ * injected into the wire body by the same beforeRequest hook that adds `prompt_cache_key`.
1434
+ * With it set, the assistant message comes back as content chunks — a `thinking` chunk (a list
1435
+ * of text chunks holding the trace) followed by the `text` answer — and this works together
1436
+ * with json_schema structured output (verified live 2026-09-18 on both models). Without the
1437
+ * field the reply is a plain string and no trace exists.
1438
+ *
1439
+ * Multi-turn: Mistral asks that the full assistant message, thinking chunk included, be
1440
+ * replayed into history ("stripping reasoning traces degrades performance"). The trace is
1441
+ * plain text, so it rides on `AIMessage.thinking` — no provider signature field — and
1442
+ * convertToMistralMessages rebuilds each prior assistant turn as [thinking, text] chunks.
1443
+ *
1444
+ * Reasoning tokens are counted inside completion_tokens; no separate reasoning_tokens field
1445
+ * arrives, so cost accounting on the output rate already covers the trace.
1446
+ */
1420
1447
  declare class MistralAgent extends AbstractAgent {
1421
1448
  private readonly client;
1422
1449
  private get defaultParams();
1423
1450
  private readonly logTemplates;
1424
1451
  private readonly errorMessages;
1425
1452
  constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
1453
+ /**
1454
+ * History in Mistral's shape. A prior assistant turn that carries a stored trace is
1455
+ * replayed as [thinking, text] chunks, as Mistral's multi-turn guidance asks; every other
1456
+ * turn is a plain string.
1457
+ */
1426
1458
  private convertToMistralMessages;
1427
1459
  private processReply;
1428
1460
  private processStructuredReply;
@@ -1438,9 +1470,8 @@ declare class MistralAgent extends AbstractAgent {
1438
1470
  */
1439
1471
  doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
1440
1472
  /**
1441
- * Plain-text ask: no schema appended, no responseFormat. Note that Magistral
1442
- * reasoning models only return thinking traces when responseFormat is NOT
1443
- * json_object, so unlike askWithZodSchema this path can surface thinking content.
1473
+ * Plain-text ask: no schema appended, no responseFormat. Reasoning (and the trace) works
1474
+ * the same way as on the schema path.
1444
1475
  */
1445
1476
  doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1446
1477
  }
@@ -1690,4 +1721,4 @@ declare class MiniMaxAgent extends AbstractAgent {
1690
1721
  doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1691
1722
  }
1692
1723
 
1693
- export { type AIMessage, ANTHROPIC_REASONING_EFFORTS, API_KEY_CONSTANTS, AbstractAgent, type AgentActivityData, AgentFactory, type AgentLoggingConfig, type AnthropicReasoningEffort, type AnthropicTokenUsage, type ApiKeyMap, type BeforeAskHook, BotResponseError, BudgetController, type BudgetControllerOptions, BudgetExceededError, type BudgetLimit, type BudgetVerdict, 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_AUDIO_TOKENS_PER_SECOND, GEMINI_REASONING_EFFORTS, GLM_REASONING_EFFORTS, type GeminiReasoningEffort, GlmAgent, type GlmReasoningEffort, GoogleAgent, type GoogleSttOptions, type GoogleSttResult, type GoogleTokenUsage, type GoogleTtsAudioOptions, type GoogleTtsResult, GoogleVoiceAgent, Gpt5Agent, GrokAgent, type GrokTokenUsage, InMemorySpendStore, type JsonSchemaOptions, KimiAgent, type KimiTokenUsage, type LLMModel, LLM_CONSTANTS, type LlmLogger, type LoggingConfig, MESSAGE_ROLE, META_REASONING_EFFORTS, MODEL_PRICING, MetaAgent, type MetaReasoningEffort, type MetaTokenUsage, MiniMaxAgent, MistralAgent, type MistralTokenUsage, type Modality, ModelAuthenticationError, type ModelConfig, ModelError, ModelInvalidResponseError, ModelOverloadError, type ModelPricing, ModelQuotaExceededError, ModelRateLimitError, ModelRefusalError, type ModelTag, ModelUnavailableError, OPENAI_REASONING_EFFORTS, type OpenAIReasoningEffort, type OpenAITokenUsage, type OpenAiSttOptions, type OpenAiSttResult, type OpenAiTtsAudioOptions, type OpenAiTtsVoice, OpenAiVoiceAgent, type PeakPricing, type PricingUnit, type ProviderSchema, type TokenUsage as ProviderTokenUsage, type ProviderType, QwenAgent, REASONING_EFFORT_SCALE, type ReasoningEffort, SUPPORTED_VOICE_PROVIDERS, type SpeechRequest, type SpeechResult, type SpeechUsage, type SpendInput, type SpendKind, type SpendLedger, type SpendLedgers, type SpendStore, type SpendWindow, SupportedAiKeyNames, SupportedAiModels, type TokenPairUsage, type TokenUsage$1 as TokenUsage, type TranscriptionRequest, type TranscriptionResult, type TranscriptionUsage, VOICE_MODEL_CONSTANTS, VOICE_MODEL_PRICING, VOICE_PROVIDER_API_KEY, type VoiceAgent, VoiceAgentFactory, type VoiceModelPricing, type VoiceProvider, ZodSchemaConverter, applySpend, buildGoogleTtsPrompt, calculateAnthropicCost, calculateCost, calculateDeepSeekCost, calculateGeminiSttCost, calculateGeminiTtsCost, calculateGoogleCost, calculateGrokCost, calculateKimiCost, calculateMetaCost, calculateMistralCost, calculateModelCost, calculateOpenAICost, calculateOpenAiSttCost, calculateOpenAiTtsCost, clampReasoningEffort, cleanResponse, createCatalog, createVoiceAgent, describeEmptyTtsResponse, evaluateBudget, extractAnthropicTokenUsage, extractTokenUsageFromResponse$2 as extractAnthropicTokenUsageFromResponse, extractDeepSeekTokenUsage, extractTokenUsageFromResponse$6 as extractDeepSeekTokenUsageFromResponse, extractFirstJsonObject, extractGoogleTokenUsage, extractTokenUsageFromResponse$1 as extractGoogleTokenUsageFromResponse, extractGrokTokenUsage, extractTokenUsageFromResponse$4 as extractGrokTokenUsageFromResponse, extractKimiTokenUsage, extractTokenUsageFromResponse$5 as extractKimiTokenUsageFromResponse, extractMetaTokenUsage, extractTokenUsageFromResponse$3 as extractMetaTokenUsageFromResponse, extractMistralTokenUsage, extractTokenUsageFromResponse as extractMistralTokenUsageFromResponse, extractOpenAITokenUsage, extractTokenUsageFromResponse$7 as extractOpenAITokenUsageFromResponse, extractTokenUsage, extractUsageAndCalculateCost, firstRefusal, generateGoogleTtsAudio, generateOpenAiTtsAudio, generateSchemaInstructions, getModelConfigByApiName, getModelDisplayName, getModelProviderName, getModelTags, getProviderSignatureFields, isBudgetExceededError, isHybridThinkingModel, isInPeakWindow, isPeakBilling, isWeekendAt, ledgerSpend, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, parseAndValidateLlmJson, pcmToWav, periodEnd, periodKey, safeValidateResponse, setBeforeAskHook, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toMetaEffort, toOpenAIEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
1724
+ export { type AIMessage, ANTHROPIC_REASONING_EFFORTS, API_KEY_CONSTANTS, AbstractAgent, type AgentActivityData, AgentFactory, type AgentLoggingConfig, type AnthropicReasoningEffort, type AnthropicTokenUsage, type ApiKeyMap, type BeforeAskHook, BotResponseError, BudgetController, type BudgetControllerOptions, BudgetExceededError, type BudgetLimit, type BudgetVerdict, 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_AUDIO_TOKENS_PER_SECOND, GEMINI_REASONING_EFFORTS, GLM_REASONING_EFFORTS, type GeminiReasoningEffort, GlmAgent, type GlmReasoningEffort, GoogleAgent, type GoogleSttOptions, type GoogleSttResult, type GoogleTokenUsage, type GoogleTtsAudioOptions, type GoogleTtsResult, GoogleVoiceAgent, Gpt5Agent, GrokAgent, type GrokTokenUsage, InMemorySpendStore, type JsonSchemaOptions, KimiAgent, type KimiTokenUsage, type LLMModel, LLM_CONSTANTS, type LlmLogger, type LoggingConfig, MESSAGE_ROLE, META_REASONING_EFFORTS, MISTRAL_REASONING_EFFORTS, MODEL_PRICING, MetaAgent, type MetaReasoningEffort, type MetaTokenUsage, MiniMaxAgent, MistralAgent, type MistralReasoningEffort, type MistralTokenUsage, type Modality, ModelAuthenticationError, type ModelConfig, ModelError, ModelInvalidResponseError, ModelOverloadError, type ModelPricing, ModelQuotaExceededError, ModelRateLimitError, ModelRefusalError, type ModelTag, ModelUnavailableError, OPENAI_REASONING_EFFORTS, type OpenAIReasoningEffort, type OpenAITokenUsage, type OpenAiSttOptions, type OpenAiSttResult, type OpenAiTtsAudioOptions, type OpenAiTtsVoice, OpenAiVoiceAgent, type PeakPricing, type PricingUnit, type ProviderSchema, type TokenUsage as ProviderTokenUsage, type ProviderType, QwenAgent, REASONING_EFFORT_SCALE, type ReasoningEffort, SUPPORTED_VOICE_PROVIDERS, type SpeechRequest, type SpeechResult, type SpeechUsage, type SpendInput, type SpendKind, type SpendLedger, type SpendLedgers, type SpendStore, type SpendWindow, SupportedAiKeyNames, SupportedAiModels, type TokenPairUsage, type TokenUsage$1 as TokenUsage, type TranscriptionRequest, type TranscriptionResult, type TranscriptionUsage, VOICE_MODEL_CONSTANTS, VOICE_MODEL_PRICING, VOICE_PROVIDER_API_KEY, type VoiceAgent, VoiceAgentFactory, type VoiceModelPricing, type VoiceProvider, ZodSchemaConverter, applySpend, buildGoogleTtsPrompt, calculateAnthropicCost, calculateCost, calculateDeepSeekCost, calculateGeminiSttCost, calculateGeminiTtsCost, calculateGoogleCost, calculateGrokCost, calculateKimiCost, calculateMetaCost, calculateMistralCost, calculateModelCost, calculateOpenAICost, calculateOpenAiSttCost, calculateOpenAiTtsCost, clampReasoningEffort, cleanResponse, createCatalog, createVoiceAgent, describeEmptyTtsResponse, evaluateBudget, extractAnthropicTokenUsage, extractTokenUsageFromResponse$2 as extractAnthropicTokenUsageFromResponse, extractDeepSeekTokenUsage, extractTokenUsageFromResponse$6 as extractDeepSeekTokenUsageFromResponse, extractFirstJsonObject, extractGoogleTokenUsage, extractTokenUsageFromResponse$1 as extractGoogleTokenUsageFromResponse, extractGrokTokenUsage, extractTokenUsageFromResponse$4 as extractGrokTokenUsageFromResponse, extractKimiTokenUsage, extractTokenUsageFromResponse$5 as extractKimiTokenUsageFromResponse, extractMetaTokenUsage, extractTokenUsageFromResponse$3 as extractMetaTokenUsageFromResponse, extractMistralTokenUsage, extractTokenUsageFromResponse as extractMistralTokenUsageFromResponse, extractOpenAITokenUsage, extractTokenUsageFromResponse$7 as extractOpenAITokenUsageFromResponse, extractTokenUsage, extractUsageAndCalculateCost, firstRefusal, generateGoogleTtsAudio, generateOpenAiTtsAudio, generateSchemaInstructions, getModelConfigByApiName, getModelDisplayName, getModelProviderName, getModelTags, getProviderSignatureFields, isBudgetExceededError, isHybridThinkingModel, isInPeakWindow, isPeakBilling, isWeekendAt, ledgerSpend, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, parseAndValidateLlmJson, pcmToWav, periodEnd, periodKey, safeValidateResponse, setBeforeAskHook, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toMetaEffort, toMistralEffort, toOpenAIEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ __export(src_exports, {
59
59
  LLM_CONSTANTS: () => LLM_CONSTANTS,
60
60
  MESSAGE_ROLE: () => MESSAGE_ROLE,
61
61
  META_REASONING_EFFORTS: () => META_REASONING_EFFORTS,
62
+ MISTRAL_REASONING_EFFORTS: () => MISTRAL_REASONING_EFFORTS,
62
63
  MODEL_PRICING: () => MODEL_PRICING,
63
64
  MetaAgent: () => MetaAgent,
64
65
  MiniMaxAgent: () => MiniMaxAgent,
@@ -160,6 +161,7 @@ __export(src_exports, {
160
161
  toGeminiEffort: () => toGeminiEffort,
161
162
  toGlmEffort: () => toGlmEffort,
162
163
  toMetaEffort: () => toMetaEffort,
164
+ toMistralEffort: () => toMistralEffort,
163
165
  toOpenAIEffort: () => toOpenAIEffort,
164
166
  transcribeWithGemini: () => transcribeWithGemini,
165
167
  transcribeWithOpenAi: () => transcribeWithOpenAi,
@@ -967,10 +969,8 @@ var LLM_CONSTANTS = {
967
969
  GEMINI_PRO: "gemini-pro",
968
970
  GEMINI_FLASH: "gemini-flash",
969
971
  GEMINI_LITE: "gemini-lite",
970
- MISTRAL_LARGE: "mistral-large",
971
972
  MISTRAL_MEDIUM: "mistral-medium",
972
973
  MISTRAL_SMALL: "mistral-small",
973
- MISTRAL_MAGISTRAL: "mistral-magistral",
974
974
  GROK: "grok",
975
975
  KIMI: "kimi",
976
976
  GLM: "glm",
@@ -1128,36 +1128,40 @@ var SupportedAiModels = {
1128
1128
  hasThinking: true,
1129
1129
  temperature: 0.7
1130
1130
  },
1131
- // Mistral models
1132
- [LLM_CONSTANTS.MISTRAL_LARGE]: {
1133
- displayName: "Mistral Large 3",
1134
- modelApiName: "mistral-large-latest",
1135
- apiKeyName: API_KEY_CONSTANTS.MISTRAL,
1136
- hasThinking: false,
1137
- tags: ["fast"]
1138
- },
1131
+ // Mistral models. Two hybrid entries since 2026-09-18: reasoning is off by default on the
1132
+ // API and switched on per request with `reasoning_effort` (see mistral-agent.ts); the trace
1133
+ // comes back as a `thinking` content chunk and works with json_schema structured output
1134
+ // (verified live 2026-09-18 on both). Pinned to 'high' — the only level Mistral's docs
1135
+ // describe ("full thinking chunk before the final answer"); Small is cheap enough that the
1136
+ // extra tokens don't matter, Medium's are priced into its free-tier band via the hybrid
1137
+ // multiplier. Live 2026-09-18 (one short schema ask each): Small 1.7s with a ~600-char
1138
+ // trace, Medium 3.8s with ~2000 chars — Medium's trace ran ~15x its answer length.
1139
+ //
1140
+ // Mistral Large 3 and Magistral Medium 1.2 were dropped 2026-09-18. Large 3 was retired by
1141
+ // Mistral on 2026-08-31 (the `-latest` alias still answered, but its capabilities say
1142
+ // reasoning: false and `reasoning_effort` is a 400 on it). Magistral was retired 2026-07-31
1143
+ // and `magistral-medium-latest` is now literally an alias of Medium 3.5 — the model list
1144
+ // returns `mistral-medium-3-5`, `mistral-medium-3`, `mistral-medium-latest` and
1145
+ // `magistral-medium-latest` as one entry — so Magistral seats had silently become Medium
1146
+ // seats already. Consumers map both retired ids onto the surviving pair.
1139
1147
  [LLM_CONSTANTS.MISTRAL_MEDIUM]: {
1140
1148
  displayName: "Mistral Medium 3.5",
1141
- modelApiName: "mistral-medium-3",
1149
+ // The docs' explicit 3.5 id. It was `mistral-medium-3` until 2026-09-18, which Mistral
1150
+ // now serves as an alias of the same model (Medium 3 itself retired 2026-08-31).
1151
+ modelApiName: "mistral-medium-3-5",
1142
1152
  apiKeyName: API_KEY_CONSTANTS.MISTRAL,
1143
- hasThinking: false,
1144
- tags: ["very-fast", "expensive"]
1153
+ hasThinking: true,
1154
+ reasoningEffort: "high",
1155
+ tags: ["fast", "expensive"]
1145
1156
  },
1146
1157
  [LLM_CONSTANTS.MISTRAL_SMALL]: {
1147
1158
  displayName: "Mistral 4 Small",
1159
+ // Resolves to mistral-small-2603 (Small 4), which also carries the magistral-small alias.
1148
1160
  modelApiName: "mistral-small-latest",
1149
1161
  apiKeyName: API_KEY_CONSTANTS.MISTRAL,
1150
- hasThinking: false,
1151
- tags: ["very-fast", "cheap"]
1152
- },
1153
- [LLM_CONSTANTS.MISTRAL_MAGISTRAL]: {
1154
- displayName: "Magistral Medium 1.2",
1155
- modelApiName: "magistral-medium-latest",
1156
- apiKeyName: API_KEY_CONSTANTS.MISTRAL,
1157
1162
  hasThinking: true,
1158
- // Measured very-fast (1.6s) because JSON response mode suppresses its thinking
1159
- // (see mistral-agent.ts) — it effectively runs as a non-reasoning model here.
1160
- tags: ["very-fast"]
1163
+ reasoningEffort: "high",
1164
+ tags: ["very-fast", "cheap"]
1161
1165
  },
1162
1166
  // Kimi models. Single always-reasoning entry: K3 reasons by default and the only way to stop
1163
1167
  // it is the undocumented K2-era `thinking: disabled` toggle, which we no longer rely on.
@@ -1485,13 +1489,10 @@ var MODEL_PRICING = {
1485
1489
  outputPrice: 1.5,
1486
1490
  cacheHitPrice: 0.025
1487
1491
  },
1488
- // Mistral models. Cached tokens bill at 10% of the input price (documented on the
1489
- // prompt_cache_key param in the API reference; no per-model cached prices published).
1490
- [SupportedAiModels[LLM_CONSTANTS.MISTRAL_LARGE].modelApiName]: {
1491
- inputPrice: 0.5,
1492
- outputPrice: 1.5,
1493
- cacheHitPrice: 0.05
1494
- },
1492
+ // Mistral models (mistral.ai/pricing/api, verified 2026-09-18). Cached tokens bill at 10% of
1493
+ // the input price (documented on the prompt_cache_key param; no per-model cached prices
1494
+ // published). Reasoning tokens are counted inside completion_tokens — no separate
1495
+ // reasoning_tokens field — so the output rate already covers the trace.
1495
1496
  [SupportedAiModels[LLM_CONSTANTS.MISTRAL_MEDIUM].modelApiName]: {
1496
1497
  inputPrice: 1.5,
1497
1498
  outputPrice: 7.5,
@@ -1502,11 +1503,6 @@ var MODEL_PRICING = {
1502
1503
  outputPrice: 0.6,
1503
1504
  cacheHitPrice: 0.015
1504
1505
  },
1505
- [SupportedAiModels[LLM_CONSTANTS.MISTRAL_MAGISTRAL].modelApiName]: {
1506
- inputPrice: 2,
1507
- outputPrice: 5,
1508
- cacheHitPrice: 0.2
1509
- },
1510
1506
  // Grok models. Cached price is per-model on xAI (not a uniform ratio):
1511
1507
  // grok-4.6 is $0.50/M cached vs $2.00/M input, and all rates double for prompts
1512
1508
  // >= 200K tokens, per docs.x.ai/developers/models (verified 2026-08-12).
@@ -1581,7 +1577,11 @@ var HYBRID_THINKING_API_NAMES = /* @__PURE__ */ new Set([
1581
1577
  // hybrid by the same definition: we force reasoning on, so they carry the multiplier.
1582
1578
  SupportedAiModels[LLM_CONSTANTS.QWEN_MAX].modelApiName,
1583
1579
  SupportedAiModels[LLM_CONSTANTS.QWEN_FLASH].modelApiName,
1584
- SupportedAiModels[LLM_CONSTANTS.MINIMAX].modelApiName
1580
+ SupportedAiModels[LLM_CONSTANTS.MINIMAX].modelApiName,
1581
+ // Mistral reasons only when asked (`reasoning_effort`), and we always ask — hybrid by the
1582
+ // same definition as Qwen. Added 2026-09-18 when the two entries went thinking-on.
1583
+ SupportedAiModels[LLM_CONSTANTS.MISTRAL_MEDIUM].modelApiName,
1584
+ SupportedAiModels[LLM_CONSTANTS.MISTRAL_SMALL].modelApiName
1585
1585
  ]);
1586
1586
  function isHybridThinkingModel(modelApiName) {
1587
1587
  return HYBRID_THINKING_API_NAMES.has(modelApiName);
@@ -1645,6 +1645,7 @@ var GLM_REASONING_EFFORTS = ["low", "high", "max"];
1645
1645
  var DEEPSEEK_REASONING_EFFORTS = ["low", "high", "max"];
1646
1646
  var FUGU_REASONING_EFFORTS = ["high", "xhigh"];
1647
1647
  var META_REASONING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh", "max"];
1648
+ var MISTRAL_REASONING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh"];
1648
1649
  function clampReasoningEffort(effort, allowed) {
1649
1650
  const rank = REASONING_EFFORT_SCALE.indexOf(effort);
1650
1651
  let best = allowed[0];
@@ -1665,6 +1666,7 @@ var toGlmEffort = (effort) => clampReasoningEffort(effort, GLM_REASONING_EFFORTS
1665
1666
  var toDeepSeekEffort = (effort) => clampReasoningEffort(effort, DEEPSEEK_REASONING_EFFORTS);
1666
1667
  var toMetaEffort = (effort) => clampReasoningEffort(effort, META_REASONING_EFFORTS);
1667
1668
  var toFuguEffort = (effort) => clampReasoningEffort(effort, FUGU_REASONING_EFFORTS);
1669
+ var toMistralEffort = (effort) => clampReasoningEffort(effort, MISTRAL_REASONING_EFFORTS);
1668
1670
 
1669
1671
  // src/pricing/token-usage-utils.ts
1670
1672
  function extractTokenUsage(response) {
@@ -3397,6 +3399,9 @@ ${instruction}`);
3397
3399
  const body = await request.clone().text();
3398
3400
  const json = JSON.parse(body);
3399
3401
  json.prompt_cache_key = promptCacheKey;
3402
+ if (this.enableThinking && this.reasoningEffort) {
3403
+ json.reasoning_effort = toMistralEffort(this.reasoningEffort);
3404
+ }
3400
3405
  return new Request(request.url, {
3401
3406
  method: request.method,
3402
3407
  headers: request.headers,
@@ -3409,11 +3414,25 @@ ${instruction}`);
3409
3414
  });
3410
3415
  this.client = new import_mistralai.Mistral({ apiKey, httpClient });
3411
3416
  }
3417
+ /**
3418
+ * History in Mistral's shape. A prior assistant turn that carries a stored trace is
3419
+ * replayed as [thinking, text] chunks, as Mistral's multi-turn guidance asks; every other
3420
+ * turn is a plain string.
3421
+ */
3412
3422
  convertToMistralMessages(messages) {
3413
- return this.prepareMessages(messages).map((msg) => ({
3414
- role: msg.role === "developer" ? "system" : msg.role,
3415
- content: msg.content
3416
- }));
3423
+ return this.prepareMessages(messages).map((msg) => {
3424
+ if (msg.role === "assistant" && msg.thinking) {
3425
+ const chunks = [
3426
+ { type: "thinking", thinking: [{ type: "text", text: msg.thinking }] },
3427
+ { type: "text", text: msg.content }
3428
+ ];
3429
+ return { role: "assistant", content: chunks };
3430
+ }
3431
+ return {
3432
+ role: msg.role === "developer" ? "system" : msg.role,
3433
+ content: msg.content
3434
+ };
3435
+ });
3417
3436
  }
3418
3437
  processReply(response) {
3419
3438
  const message = response?.choices?.[0]?.message;
@@ -3448,7 +3467,6 @@ ${instruction}`);
3448
3467
  extractTokenUsage(response) {
3449
3468
  const usage = extractMistralTokenUsage(response);
3450
3469
  if (!usage) return void 0;
3451
- this.logger(`MISTRAL_CACHE_CALIBRATION raw usage: ${JSON.stringify(response?.usage)}`);
3452
3470
  if (usage.reasoningTokens && usage.reasoningTokens > 0) {
3453
3471
  this.logger(`\u{1F9E0} Reasoning tokens used: ${usage.reasoningTokens}`);
3454
3472
  }
@@ -3484,7 +3502,7 @@ ${instruction}`);
3484
3502
  const convertedMessages = this.convertToMistralMessages(messages);
3485
3503
  if (convertedMessages.length > 0) {
3486
3504
  const lastMessage = convertedMessages[convertedMessages.length - 1];
3487
- if (lastMessage && lastMessage.content) {
3505
+ if (lastMessage && typeof lastMessage.content === "string" && lastMessage.content) {
3488
3506
  lastMessage.content += `
3489
3507
 
3490
3508
  Your response must be a valid JSON object matching this schema:
@@ -3555,9 +3573,8 @@ ${schemaDescription}`
3555
3573
  }
3556
3574
  }
3557
3575
  /**
3558
- * Plain-text ask: no schema appended, no responseFormat. Note that Magistral
3559
- * reasoning models only return thinking traces when responseFormat is NOT
3560
- * json_object, so unlike askWithZodSchema this path can surface thinking content.
3576
+ * Plain-text ask: no schema appended, no responseFormat. Reasoning (and the trace) works
3577
+ * the same way as on the schema path.
3561
3578
  */
3562
3579
  async doAskText(messages) {
3563
3580
  try {
@@ -4581,6 +4598,18 @@ ${schemaDescription}`;
4581
4598
 
4582
4599
  // src/agents/qwen-agent.ts
4583
4600
  var import_openai9 = require("openai");
4601
+ function qwenRefusalFrom(model, apiError) {
4602
+ const message = apiError instanceof Error ? apiError.message : String(apiError);
4603
+ if (!/DataInspectionFailed|inappropriate content/i.test(message)) {
4604
+ return void 0;
4605
+ }
4606
+ const detail = message.replace(/^[\s\S]*DataInspectionFailed:\s*/, "").trim();
4607
+ return new ModelRefusalError(
4608
+ model,
4609
+ `${model} refused the prompt (refusalReason: DataInspectionFailed${detail ? `; ${detail}` : ""})`,
4610
+ "DataInspectionFailed"
4611
+ );
4612
+ }
4584
4613
  var QwenAgent = class extends AbstractAgent {
4585
4614
  client;
4586
4615
  // A getter, not a field: `maxOutputTokens` can be raised after construction, and a field
@@ -4705,7 +4734,7 @@ ${schemaDescription}`;
4705
4734
  completion = await this.client.chat.completions.create(params);
4706
4735
  } catch (apiError) {
4707
4736
  this.logger(this.logTemplates.error(this.name, apiError));
4708
- throw new Error(this.errorMessages.apiError(apiError));
4737
+ throw qwenRefusalFrom(this.model, apiError) ?? new Error(this.errorMessages.apiError(apiError));
4709
4738
  }
4710
4739
  const rawReply = completion.choices[0]?.message?.content;
4711
4740
  if (!rawReply) {
@@ -4725,6 +4754,9 @@ ${schemaDescription}`;
4725
4754
  return [validated, thinkingContent, tokenUsage];
4726
4755
  } catch (error) {
4727
4756
  this.logger(this.logTemplates.error(this.name, error));
4757
+ if (error instanceof ModelError) {
4758
+ throw error;
4759
+ }
4728
4760
  throw new Error(this.errorMessages.apiError(error));
4729
4761
  }
4730
4762
  }
@@ -4758,7 +4790,7 @@ ${openAIMessages[0].content}`;
4758
4790
  completion = await this.client.chat.completions.create(params);
4759
4791
  } catch (apiError) {
4760
4792
  this.logger(this.logTemplates.error(this.name, apiError));
4761
- throw new Error(this.errorMessages.apiError(apiError));
4793
+ throw qwenRefusalFrom(this.model, apiError) ?? new Error(this.errorMessages.apiError(apiError));
4762
4794
  }
4763
4795
  const rawReply = completion.choices[0]?.message?.content;
4764
4796
  if (!rawReply) {
@@ -4774,6 +4806,9 @@ ${openAIMessages[0].content}`;
4774
4806
  return [reply, thinkingContent, tokenUsage];
4775
4807
  } catch (error) {
4776
4808
  this.logger(this.logTemplates.error(this.name, error));
4809
+ if (error instanceof ModelError) {
4810
+ throw error;
4811
+ }
4777
4812
  throw new Error(this.errorMessages.apiError(error));
4778
4813
  }
4779
4814
  }
@@ -5211,8 +5246,6 @@ var AgentFactory = class {
5211
5246
  // Mistral models
5212
5247
  case LLM_CONSTANTS.MISTRAL_MEDIUM:
5213
5248
  case LLM_CONSTANTS.MISTRAL_SMALL:
5214
- case LLM_CONSTANTS.MISTRAL_LARGE:
5215
- case LLM_CONSTANTS.MISTRAL_MAGISTRAL:
5216
5249
  return new MistralAgent(name, instruction, model.modelApiName, key, shouldEnableThinking);
5217
5250
  case LLM_CONSTANTS.KIMI:
5218
5251
  return new KimiAgent(name, instruction, model.modelApiName, key, 0, shouldEnableThinking);
@@ -5276,6 +5309,7 @@ var AgentFactory = class {
5276
5309
  LLM_CONSTANTS,
5277
5310
  MESSAGE_ROLE,
5278
5311
  META_REASONING_EFFORTS,
5312
+ MISTRAL_REASONING_EFFORTS,
5279
5313
  MODEL_PRICING,
5280
5314
  MetaAgent,
5281
5315
  MiniMaxAgent,
@@ -5377,6 +5411,7 @@ var AgentFactory = class {
5377
5411
  toGeminiEffort,
5378
5412
  toGlmEffort,
5379
5413
  toMetaEffort,
5414
+ toMistralEffort,
5380
5415
  toOpenAIEffort,
5381
5416
  transcribeWithGemini,
5382
5417
  transcribeWithOpenAi,