@hiper2d/ai-agents 0.14.1 → 0.16.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/README.md CHANGED
@@ -69,10 +69,10 @@ const { audio, costUSD } = await voice.speak({ text: 'Night falls.', voice: 'Kor
69
69
  const { text } = await voice.transcribe({ audio: recording, mimeType: 'audio/webm' });
70
70
  ```
71
71
 
72
- `openai` runs gpt-4o-mini-tts + Whisper, `google` runs Gemini 3.1 Flash TTS + Gemini 3.5
72
+ `openai` runs gpt-4o-mini-tts + Whisper, `google` runs Gemini 3.8 Flash-Lite TTS + Gemini 3.5
73
73
  Transcribe (`VOICE_MODEL_CONSTANTS`, prices in `VOICE_MODEL_PRICING`). The `voiceStyle`
74
- direction works for both providers: OpenAI takes it as instructions, Gemini gets it folded
75
- into the prompt ("Say gravely: …").
74
+ direction works for both providers: OpenAI takes it as instructions, Gemini as the part's
75
+ `speechMetadata.style` (3.8 TTS reads the text verbatim, so no inline "Say X:" prefix).
76
76
 
77
77
  ### Images and portrait sheets (`@hiper2d/ai-agents/images`)
78
78
 
package/dist/index.d.mts CHANGED
@@ -907,6 +907,8 @@ interface SpeechResult {
907
907
  audio: ArrayBuffer;
908
908
  costUSD: number;
909
909
  usage: SpeechUsage;
910
+ /** Gemini only: the styled request was safety-blocked, so the line was read without its style. */
911
+ styleDropped?: boolean;
910
912
  }
911
913
  interface TranscriptionRequest {
912
914
  audio: ArrayBuffer;
@@ -943,7 +945,7 @@ interface VoiceAgent {
943
945
  declare const VOICE_MODEL_CONSTANTS: {
944
946
  readonly OPENAI_TTS: "gpt-4o-mini-tts";
945
947
  readonly OPENAI_STT: "whisper-1";
946
- readonly GOOGLE_TTS: "gemini-3.1-flash-tts-preview";
948
+ readonly GOOGLE_TTS: "gemini-3.8-flash-lite-tts";
947
949
  readonly GOOGLE_STT: "gemini-3.5-transcribe";
948
950
  };
949
951
  declare const SUPPORTED_VOICE_PROVIDERS: readonly VoiceProvider[];
@@ -1006,7 +1008,7 @@ declare class OpenAiVoiceAgent implements VoiceAgent {
1006
1008
  declare class GoogleVoiceAgent implements VoiceAgent {
1007
1009
  private readonly apiKey;
1008
1010
  readonly provider: "google";
1009
- readonly ttsModel: "gemini-3.1-flash-tts-preview";
1011
+ readonly ttsModel: "gemini-3.8-flash-lite-tts";
1010
1012
  readonly sttModel: "gemini-3.5-transcribe";
1011
1013
  constructor(apiKey: string);
1012
1014
  speak(request: SpeechRequest): Promise<SpeechResult>;
@@ -1042,7 +1044,7 @@ declare function transcribeWithOpenAi(audioBuffer: ArrayBuffer, apiKey: string,
1042
1044
  interface GoogleTtsAudioOptions {
1043
1045
  /** e.g. "Kore", "Puck" */
1044
1046
  voiceName: string;
1045
- /** "mysteriously", "excitedly", or a longer direction */
1047
+ /** "mysteriously", "excitedly", or a longer direction; sent as speechMetadata.style */
1046
1048
  voiceStyle?: string;
1047
1049
  }
1048
1050
  interface GoogleTtsResult {
@@ -1053,15 +1055,16 @@ interface GoogleTtsResult {
1053
1055
  inputTokens: number;
1054
1056
  outputTokens: number;
1055
1057
  };
1058
+ /** True when the styled request was safety-blocked and the line was read without its style. */
1059
+ styleDropped?: boolean;
1056
1060
  }
1057
1061
  /**
1058
- * Gemini TTS has no instruction field: delivery is directed in the text itself
1059
- * ("Say cheerfully: Have a wonderful day!" in the docs). A short style (1-3
1060
- * words) becomes that "Say X:" prefix; a longer direction is used as written,
1061
- * ending in the colon that separates it from the line to read. The same style
1062
- * value feeds OpenAI's `instructions`, so one field serves both providers.
1062
+ * Gemini 3.8 TTS reads the part text as a verbatim transcript: an inline
1063
+ * "Say cheerfully:" prefix (the 3.1 convention) may be spoken aloud. Delivery
1064
+ * direction goes in the part's `speechMetadata.style` instead, short adverb or
1065
+ * longer sentence alike. Trailing punctuation is trimmed; blank means none.
1063
1066
  */
1064
- declare function buildGoogleTtsPrompt(text: string, voiceStyle?: string): string;
1067
+ declare function normalizeTtsStyle(voiceStyle?: string): string | undefined;
1065
1068
  /** Wraps raw 16-bit mono PCM in a WAV header. */
1066
1069
  declare function pcmToWav(pcmData: Uint8Array, sampleRate?: number): ArrayBuffer;
1067
1070
  /**
@@ -1071,12 +1074,22 @@ declare function pcmToWav(pcmData: Uint8Array, sampleRate?: number): ArrayBuffer
1071
1074
  * difference between a diagnosable log line and "no audio data".
1072
1075
  */
1073
1076
  declare function describeEmptyTtsResponse(response: any): string;
1077
+ /**
1078
+ * A safety block on the prompt or the candidate. The 3.1 preview model
1079
+ * false-positived on volume directions ("Say quietly: <harmless line>" blocked
1080
+ * 4 of 6 on 2026-09-24); 3.8 Flash-Lite with the style in speechMetadata passed
1081
+ * the same lines 9 of 9, but the fallback below stays as a net.
1082
+ */
1083
+ declare function isSafetyBlocked(response: any): boolean;
1074
1084
  /**
1075
1085
  * Core Gemini TTS call: text + API key in, WAV + token usage out.
1076
1086
  *
1077
- * Uses generateContent rather than the newer Interactions API the docs show:
1078
- * both serve the 3.1 TTS model (verified 2026-09-05), and this one is typed in
1079
- * the SDK and reports usageMetadata, which billing needs.
1087
+ * 3.8 TTS returns WAV with a RIFF header by default (3.1 returned headerless
1088
+ * audio/l16); raw PCM is still wrapped if a response ever carries it.
1089
+ *
1090
+ * When a styled request comes back safety-blocked, the line is read once more
1091
+ * without the style: a block on the direction should not silence the line. An
1092
+ * unstyled block is not repeated.
1080
1093
  */
1081
1094
  declare function generateGoogleTtsAudio(text: string, apiKey: string, options: GoogleTtsAudioOptions): Promise<GoogleTtsResult>;
1082
1095
 
@@ -1791,4 +1804,4 @@ declare class MiniMaxAgent extends AbstractAgent {
1791
1804
  doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1792
1805
  }
1793
1806
 
1794
- 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, KIMI_REASONING_EFFORTS, KimiAgent, type KimiReasoningEffort, 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, XAI_REASONING_EFFORTS, type XaiReasoningEffort, 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, toKimiEffort, toMetaEffort, toMistralEffort, toOpenAIEffort, toXaiEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
1807
+ 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, KIMI_REASONING_EFFORTS, KimiAgent, type KimiReasoningEffort, 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, XAI_REASONING_EFFORTS, type XaiReasoningEffort, ZodSchemaConverter, applySpend, 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, isSafetyBlocked, isWeekendAt, ledgerSpend, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, normalizeTtsStyle, parseAndValidateLlmJson, pcmToWav, periodEnd, periodKey, safeValidateResponse, setBeforeAskHook, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toKimiEffort, toMetaEffort, toMistralEffort, toOpenAIEffort, toXaiEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
package/dist/index.d.ts CHANGED
@@ -907,6 +907,8 @@ interface SpeechResult {
907
907
  audio: ArrayBuffer;
908
908
  costUSD: number;
909
909
  usage: SpeechUsage;
910
+ /** Gemini only: the styled request was safety-blocked, so the line was read without its style. */
911
+ styleDropped?: boolean;
910
912
  }
911
913
  interface TranscriptionRequest {
912
914
  audio: ArrayBuffer;
@@ -943,7 +945,7 @@ interface VoiceAgent {
943
945
  declare const VOICE_MODEL_CONSTANTS: {
944
946
  readonly OPENAI_TTS: "gpt-4o-mini-tts";
945
947
  readonly OPENAI_STT: "whisper-1";
946
- readonly GOOGLE_TTS: "gemini-3.1-flash-tts-preview";
948
+ readonly GOOGLE_TTS: "gemini-3.8-flash-lite-tts";
947
949
  readonly GOOGLE_STT: "gemini-3.5-transcribe";
948
950
  };
949
951
  declare const SUPPORTED_VOICE_PROVIDERS: readonly VoiceProvider[];
@@ -1006,7 +1008,7 @@ declare class OpenAiVoiceAgent implements VoiceAgent {
1006
1008
  declare class GoogleVoiceAgent implements VoiceAgent {
1007
1009
  private readonly apiKey;
1008
1010
  readonly provider: "google";
1009
- readonly ttsModel: "gemini-3.1-flash-tts-preview";
1011
+ readonly ttsModel: "gemini-3.8-flash-lite-tts";
1010
1012
  readonly sttModel: "gemini-3.5-transcribe";
1011
1013
  constructor(apiKey: string);
1012
1014
  speak(request: SpeechRequest): Promise<SpeechResult>;
@@ -1042,7 +1044,7 @@ declare function transcribeWithOpenAi(audioBuffer: ArrayBuffer, apiKey: string,
1042
1044
  interface GoogleTtsAudioOptions {
1043
1045
  /** e.g. "Kore", "Puck" */
1044
1046
  voiceName: string;
1045
- /** "mysteriously", "excitedly", or a longer direction */
1047
+ /** "mysteriously", "excitedly", or a longer direction; sent as speechMetadata.style */
1046
1048
  voiceStyle?: string;
1047
1049
  }
1048
1050
  interface GoogleTtsResult {
@@ -1053,15 +1055,16 @@ interface GoogleTtsResult {
1053
1055
  inputTokens: number;
1054
1056
  outputTokens: number;
1055
1057
  };
1058
+ /** True when the styled request was safety-blocked and the line was read without its style. */
1059
+ styleDropped?: boolean;
1056
1060
  }
1057
1061
  /**
1058
- * Gemini TTS has no instruction field: delivery is directed in the text itself
1059
- * ("Say cheerfully: Have a wonderful day!" in the docs). A short style (1-3
1060
- * words) becomes that "Say X:" prefix; a longer direction is used as written,
1061
- * ending in the colon that separates it from the line to read. The same style
1062
- * value feeds OpenAI's `instructions`, so one field serves both providers.
1062
+ * Gemini 3.8 TTS reads the part text as a verbatim transcript: an inline
1063
+ * "Say cheerfully:" prefix (the 3.1 convention) may be spoken aloud. Delivery
1064
+ * direction goes in the part's `speechMetadata.style` instead, short adverb or
1065
+ * longer sentence alike. Trailing punctuation is trimmed; blank means none.
1063
1066
  */
1064
- declare function buildGoogleTtsPrompt(text: string, voiceStyle?: string): string;
1067
+ declare function normalizeTtsStyle(voiceStyle?: string): string | undefined;
1065
1068
  /** Wraps raw 16-bit mono PCM in a WAV header. */
1066
1069
  declare function pcmToWav(pcmData: Uint8Array, sampleRate?: number): ArrayBuffer;
1067
1070
  /**
@@ -1071,12 +1074,22 @@ declare function pcmToWav(pcmData: Uint8Array, sampleRate?: number): ArrayBuffer
1071
1074
  * difference between a diagnosable log line and "no audio data".
1072
1075
  */
1073
1076
  declare function describeEmptyTtsResponse(response: any): string;
1077
+ /**
1078
+ * A safety block on the prompt or the candidate. The 3.1 preview model
1079
+ * false-positived on volume directions ("Say quietly: <harmless line>" blocked
1080
+ * 4 of 6 on 2026-09-24); 3.8 Flash-Lite with the style in speechMetadata passed
1081
+ * the same lines 9 of 9, but the fallback below stays as a net.
1082
+ */
1083
+ declare function isSafetyBlocked(response: any): boolean;
1074
1084
  /**
1075
1085
  * Core Gemini TTS call: text + API key in, WAV + token usage out.
1076
1086
  *
1077
- * Uses generateContent rather than the newer Interactions API the docs show:
1078
- * both serve the 3.1 TTS model (verified 2026-09-05), and this one is typed in
1079
- * the SDK and reports usageMetadata, which billing needs.
1087
+ * 3.8 TTS returns WAV with a RIFF header by default (3.1 returned headerless
1088
+ * audio/l16); raw PCM is still wrapped if a response ever carries it.
1089
+ *
1090
+ * When a styled request comes back safety-blocked, the line is read once more
1091
+ * without the style: a block on the direction should not silence the line. An
1092
+ * unstyled block is not repeated.
1080
1093
  */
1081
1094
  declare function generateGoogleTtsAudio(text: string, apiKey: string, options: GoogleTtsAudioOptions): Promise<GoogleTtsResult>;
1082
1095
 
@@ -1791,4 +1804,4 @@ declare class MiniMaxAgent extends AbstractAgent {
1791
1804
  doAskText(messages: AIMessage[]): Promise<[string, string, TokenUsage$1?, string?]>;
1792
1805
  }
1793
1806
 
1794
- 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, KIMI_REASONING_EFFORTS, KimiAgent, type KimiReasoningEffort, 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, XAI_REASONING_EFFORTS, type XaiReasoningEffort, 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, toKimiEffort, toMetaEffort, toMistralEffort, toOpenAIEffort, toXaiEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
1807
+ 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, KIMI_REASONING_EFFORTS, KimiAgent, type KimiReasoningEffort, 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, XAI_REASONING_EFFORTS, type XaiReasoningEffort, ZodSchemaConverter, applySpend, 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, isSafetyBlocked, isWeekendAt, ledgerSpend, logger, mergeThinking, modelHasTag, modelIsFast, needsPromptBasedSchema, normalizeTtsStyle, parseAndValidateLlmJson, pcmToWav, periodEnd, periodKey, safeValidateResponse, setBeforeAskHook, setLlmLogger, stableHashHex, stripInlineThinking, supportsNativeJsonSchema, toAnthropicEffort, toDeepSeekEffort, toFuguEffort, toGeminiEffort, toGlmEffort, toKimiEffort, toMetaEffort, toMistralEffort, toOpenAIEffort, toXaiEffort, transcribeWithGemini, transcribeWithOpenAi, validateResponse };
package/dist/index.js CHANGED
@@ -87,7 +87,6 @@ __export(src_exports, {
87
87
  XAI_REASONING_EFFORTS: () => XAI_REASONING_EFFORTS,
88
88
  ZodSchemaConverter: () => ZodSchemaConverter,
89
89
  applySpend: () => applySpend,
90
- buildGoogleTtsPrompt: () => buildGoogleTtsPrompt,
91
90
  calculateAnthropicCost: () => calculateAnthropicCost,
92
91
  calculateCost: () => calculateCost,
93
92
  calculateDeepSeekCost: () => calculateDeepSeekCost,
@@ -140,6 +139,7 @@ __export(src_exports, {
140
139
  isHybridThinkingModel: () => isHybridThinkingModel,
141
140
  isInPeakWindow: () => isInPeakWindow,
142
141
  isPeakBilling: () => isPeakBilling,
142
+ isSafetyBlocked: () => isSafetyBlocked,
143
143
  isWeekendAt: () => isWeekendAt,
144
144
  ledgerSpend: () => ledgerSpend,
145
145
  logger: () => logger,
@@ -147,6 +147,7 @@ __export(src_exports, {
147
147
  modelHasTag: () => modelHasTag,
148
148
  modelIsFast: () => modelIsFast,
149
149
  needsPromptBasedSchema: () => needsPromptBasedSchema,
150
+ normalizeTtsStyle: () => normalizeTtsStyle,
150
151
  parseAndValidateLlmJson: () => parseAndValidateLlmJson,
151
152
  pcmToWav: () => pcmToWav,
152
153
  periodEnd: () => periodEnd,
@@ -1240,10 +1241,15 @@ var SupportedAiModels = {
1240
1241
  // Live 2026-08-30 (one sample each): day-2 vote 11.8s, 15-character story 56.2s.
1241
1242
  tags: ["cheap"]
1242
1243
  },
1243
- // Sakana Fugu models — OpenAI-compatible. They reason internally (and bill it as
1244
- // "orchestration" tokens), but never surface reasoning to us: responses come back with
1245
- // reasoning_tokens: 0 and no reasoning_content. So hasThinking is false — there's no
1246
- // thinking content to show and no user-facing thinking toggle. Single entry per model.
1244
+ // Sakana Fugu models — OpenAI-compatible. They reason internally, but Chat Completions
1245
+ // (what FuguAgent uses) never returns the text: reasoning_tokens are reported and billed,
1246
+ // there is no reasoning_content. So hasThinking is false. Single entry per model.
1247
+ // The Messages and Responses APIs DO return reasoning (thinking blocks with an empty
1248
+ // signature / reasoning items, some with encrypted_content), but probed 2026-09-24 on
1249
+ // fugu-max it isn't worth switching for, since we keep reasoning only to replay it: the
1250
+ // returned text is often a vague status summary or empty rather than the actual
1251
+ // reasoning, and replayed reasoning reaches the model distorted (a planted "4817" came
1252
+ // back as "4829" on both APIs, presumably rewritten by the orchestrator).
1247
1253
  //
1248
1254
  // Base `fugu` was RETIRED 2026-08-04. It was carried as a cheap everyday option at an
1249
1255
  // assumed $1/$3, but reconciling token logs against the Sakana balance showed it actually
@@ -1926,8 +1932,9 @@ function extractTokenUsageFromResponse8(response) {
1926
1932
  var VOICE_MODEL_CONSTANTS = {
1927
1933
  OPENAI_TTS: "gpt-4o-mini-tts",
1928
1934
  OPENAI_STT: "whisper-1",
1929
- // ai.google.dev/gemini-api/docs/speech-generation
1930
- GOOGLE_TTS: "gemini-3.1-flash-tts-preview",
1935
+ // ai.google.dev/gemini-api/docs/speech-generation — Google's named replacement
1936
+ // for gemini-3.1-flash-tts-preview (2026-09-24: ~6 s vs ~15 s per line, ~4x cheaper)
1937
+ GOOGLE_TTS: "gemini-3.8-flash-lite-tts",
1931
1938
  // ai.google.dev/gemini-api/docs/transcribe — Interactions API only (see google-stt.ts)
1932
1939
  GOOGLE_STT: "gemini-3.5-transcribe"
1933
1940
  };
@@ -1939,9 +1946,9 @@ var VOICE_PROVIDER_API_KEY = {
1939
1946
  var VOICE_MODEL_PRICING = {
1940
1947
  [VOICE_MODEL_CONSTANTS.OPENAI_TTS]: { pricePerMillionCharacters: 15 },
1941
1948
  [VOICE_MODEL_CONSTANTS.OPENAI_STT]: { pricePerMinute: 6e-3 },
1942
- // Measured 2026-09-05: ~32 audio tokens per second of speech, so a 15-second
1943
- // line is ~$0.01 — about 3-5x an OpenAI line of the same length.
1944
- [VOICE_MODEL_CONSTANTS.GOOGLE_TTS]: { textInputPricePerM: 1, audioOutputPricePerM: 20 },
1949
+ // ~32 audio tokens per second of speech, so a 15-second line is ~$0.003.
1950
+ // Google doubles both rates to $1 / $12 on 2027-01-01 — update then.
1951
+ [VOICE_MODEL_CONSTANTS.GOOGLE_TTS]: { textInputPricePerM: 0.5, audioOutputPricePerM: 6 },
1945
1952
  // ~25 audio tokens per second in, ~175 text tokens per minute out: ≈ $0.005/min.
1946
1953
  [VOICE_MODEL_CONSTANTS.GOOGLE_STT]: { audioInputPricePerM: 2, textOutputPricePerM: 12 }
1947
1954
  };
@@ -2048,12 +2055,10 @@ var import_genai = require("@google/genai");
2048
2055
  var AUDIO_TOKENS_PER_SECOND = 32;
2049
2056
  var SAMPLE_RATE = 24e3;
2050
2057
  var PCM_BYTES_PER_SECOND = SAMPLE_RATE * 2;
2051
- function buildGoogleTtsPrompt(text, voiceStyle) {
2058
+ var WAV_HEADER_BYTES = 44;
2059
+ function normalizeTtsStyle(voiceStyle) {
2052
2060
  const style = voiceStyle?.trim().replace(/[:.!,;\s]+$/, "");
2053
- if (!style) return text;
2054
- const isShort = style.split(/\s+/).length <= 3 && !/[.!?,;]/.test(style);
2055
- return isShort ? `Say ${style}: ${text}` : `${style}:
2056
- ${text}`;
2061
+ return style || void 0;
2057
2062
  }
2058
2063
  function pcmToWav(pcmData, sampleRate = SAMPLE_RATE) {
2059
2064
  const numChannels = 1;
@@ -2097,28 +2102,51 @@ function describeEmptyTtsResponse(response) {
2097
2102
  if (!parts.length) bits.push("no parts");
2098
2103
  return bits.join(", ");
2099
2104
  }
2105
+ function isSafetyBlocked(response) {
2106
+ const finish = response?.candidates?.[0]?.finishReason;
2107
+ return finish === "SAFETY" || finish === "PROHIBITED_CONTENT" || !!response?.promptFeedback?.blockReason;
2108
+ }
2109
+ function findAudioPart(response) {
2110
+ const parts = response?.candidates?.[0]?.content?.parts ?? [];
2111
+ const inline = parts.find((part) => part.inlineData?.mimeType?.startsWith("audio/") && part.inlineData?.data)?.inlineData;
2112
+ return inline ? { data: inline.data, mimeType: inline.mimeType } : void 0;
2113
+ }
2100
2114
  async function generateGoogleTtsAudio(text, apiKey, options) {
2101
2115
  const client = new import_genai.GoogleGenAI({ apiKey });
2102
- const response = await client.models.generateContent({
2116
+ const request = (style2) => client.models.generateContent({
2103
2117
  model: VOICE_MODEL_CONSTANTS.GOOGLE_TTS,
2104
- contents: [{ parts: [{ text: buildGoogleTtsPrompt(text, options.voiceStyle) }] }],
2118
+ contents: [{ parts: [style2 ? { text, speechMetadata: { style: style2 } } : { text }] }],
2105
2119
  config: {
2106
2120
  responseModalities: ["AUDIO"],
2107
2121
  speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: options.voiceName } } }
2108
2122
  }
2109
2123
  });
2110
- const candidate = response.candidates?.[0];
2111
- const parts = candidate?.content?.parts ?? [];
2112
- const audioPart = parts.find((part) => part.inlineData?.mimeType?.startsWith("audio/"));
2113
- if (!audioPart?.inlineData?.data) {
2114
- throw new Error(`No audio data in Google TTS response (${describeEmptyTtsResponse(response)})`);
2115
- }
2116
- const pcmData = new Uint8Array(Buffer.from(audioPart.inlineData.data, "base64"));
2124
+ const style = normalizeTtsStyle(options.voiceStyle);
2125
+ let response = await request(style);
2126
+ let styleDropped = false;
2127
+ let blockedInputTokens = 0;
2128
+ if (!findAudioPart(response) && style && isSafetyBlocked(response)) {
2129
+ blockedInputTokens = response?.usageMetadata?.promptTokenCount ?? 0;
2130
+ response = await request(void 0);
2131
+ styleDropped = true;
2132
+ }
2133
+ const audioPart = findAudioPart(response);
2134
+ if (!audioPart) {
2135
+ throw new Error(`No audio data in Google TTS response (${describeEmptyTtsResponse(response)}${styleDropped ? ", also without the style" : ""})`);
2136
+ }
2137
+ const bytes = new Uint8Array(Buffer.from(audioPart.data, "base64"));
2138
+ const isWav = /^audio\/(x-)?wav/i.test(audioPart.mimeType);
2139
+ const audio = isWav ? bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) : pcmToWav(bytes);
2140
+ const pcmBytes = isWav ? Math.max(0, bytes.length - WAV_HEADER_BYTES) : bytes.length;
2117
2141
  const usageMetadata = response.usageMetadata ?? {};
2118
- const inputTokens = usageMetadata.promptTokenCount ?? 0;
2142
+ const inputTokens = (usageMetadata.promptTokenCount ?? 0) + blockedInputTokens;
2119
2143
  const reportedOutput = usageMetadata.candidatesTokenCount;
2120
- const outputTokens = reportedOutput && reportedOutput > 0 ? reportedOutput : Math.ceil(pcmData.length / PCM_BYTES_PER_SECOND * AUDIO_TOKENS_PER_SECOND);
2121
- return { audio: pcmToWav(pcmData), usage: { inputTokens, outputTokens } };
2144
+ const outputTokens = reportedOutput && reportedOutput > 0 ? reportedOutput : Math.ceil(pcmBytes / PCM_BYTES_PER_SECOND * AUDIO_TOKENS_PER_SECOND);
2145
+ return {
2146
+ audio,
2147
+ usage: { inputTokens, outputTokens },
2148
+ ...styleDropped ? { styleDropped } : {}
2149
+ };
2122
2150
  }
2123
2151
 
2124
2152
  // src/voice/google-stt.ts
@@ -2149,11 +2177,11 @@ var GoogleVoiceAgent = class {
2149
2177
  ttsModel = VOICE_MODEL_CONSTANTS.GOOGLE_TTS;
2150
2178
  sttModel = VOICE_MODEL_CONSTANTS.GOOGLE_STT;
2151
2179
  async speak(request) {
2152
- const { audio, usage } = await generateGoogleTtsAudio(request.text, this.apiKey, {
2180
+ const { audio, usage, styleDropped } = await generateGoogleTtsAudio(request.text, this.apiKey, {
2153
2181
  voiceName: request.voice,
2154
2182
  voiceStyle: request.voiceStyle
2155
2183
  });
2156
- return { audio, costUSD: calculateGeminiTtsCost(usage), usage };
2184
+ return { audio, costUSD: calculateGeminiTtsCost(usage), usage, ...styleDropped ? { styleDropped } : {} };
2157
2185
  }
2158
2186
  async transcribe(request) {
2159
2187
  const { text, durationSeconds, usage } = await transcribeWithGemini(request.audio, this.apiKey, { mimeType: request.mimeType });
@@ -4909,7 +4937,11 @@ ${schemaDescription}`;
4909
4937
  const params = {
4910
4938
  ...this.defaultParams,
4911
4939
  messages: openAIMessages,
4912
- ...this.thinkingParams()
4940
+ ...this.thinkingParams(),
4941
+ response_format: {
4942
+ type: "json_schema",
4943
+ json_schema: ZodSchemaConverter.toOpenAIJsonSchema(zodSchema, "response_schema")
4944
+ }
4913
4945
  };
4914
4946
  completion = await this.client.chat.completions.create(params);
4915
4947
  } catch (apiError) {
@@ -5518,7 +5550,6 @@ var AgentFactory = class {
5518
5550
  XAI_REASONING_EFFORTS,
5519
5551
  ZodSchemaConverter,
5520
5552
  applySpend,
5521
- buildGoogleTtsPrompt,
5522
5553
  calculateAnthropicCost,
5523
5554
  calculateCost,
5524
5555
  calculateDeepSeekCost,
@@ -5571,6 +5602,7 @@ var AgentFactory = class {
5571
5602
  isHybridThinkingModel,
5572
5603
  isInPeakWindow,
5573
5604
  isPeakBilling,
5605
+ isSafetyBlocked,
5574
5606
  isWeekendAt,
5575
5607
  ledgerSpend,
5576
5608
  logger,
@@ -5578,6 +5610,7 @@ var AgentFactory = class {
5578
5610
  modelHasTag,
5579
5611
  modelIsFast,
5580
5612
  needsPromptBasedSchema,
5613
+ normalizeTtsStyle,
5581
5614
  parseAndValidateLlmJson,
5582
5615
  pcmToWav,
5583
5616
  periodEnd,