Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/main/presenter/agentRuntimePresenter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
supportsOpenAIImageGenerationSettings
} from '@shared/imageGenerationSettings'
import { isDeepSeekSeriesModelId } from '@shared/model'
import { isTtsModelConfig, isTtsModelId } from '@shared/ttsSettings'
import { nanoid } from 'nanoid'
import type { SQLitePresenter } from '../sqlitePresenter'
import { eventBus, SendTarget } from '@/eventbus'
Expand Down Expand Up @@ -1963,6 +1964,9 @@ export class AgentRuntimePresenter implements IAgentImplementation {
try {
let providerMessages = injectedMessages
let providerMaxTokens = requestMaxTokens
const isTtsRequest =
isTtsModelConfig(requestModelConfig) || isTtsModelId(requestModelId)
const effectiveRequestTools: MCPToolDefinition[] = isTtsRequest ? [] : requestTools

if (!bypassContextBudget) {
const protectedSteerTailCount =
Expand All @@ -1971,7 +1975,7 @@ export class AgentRuntimePresenter implements IAgentImplementation {
: 0
let requestPreflight = preflightRequestContext({
messages: injectedMessages,
tools: requestTools,
tools: effectiveRequestTools,
contextLength: requestModelConfig.contextLength,
requestedMaxTokens: requestMaxTokens,
minimumProtectedTailCount: protectedSteerTailCount
Expand All @@ -1988,7 +1992,7 @@ export class AgentRuntimePresenter implements IAgentImplementation {
baseSystemPrompt,
contextLength: requestModelConfig.contextLength,
requestedMaxTokens: requestPreflight.requestedMaxTokens,
tools: requestTools,
tools: effectiveRequestTools,
supportsVision,
supportsAudioInput,
interleavedReasoning,
Expand All @@ -2001,7 +2005,7 @@ export class AgentRuntimePresenter implements IAgentImplementation {
}
requestPreflight = preflightRequestContext({
messages: requestMessages,
tools: requestTools,
tools: effectiveRequestTools,
contextLength: requestModelConfig.contextLength,
requestedMaxTokens: requestMaxTokens,
minimumProtectedTailCount: protectedSteerTailCount
Expand Down Expand Up @@ -2041,7 +2045,7 @@ export class AgentRuntimePresenter implements IAgentImplementation {
requestModelConfig,
requestTemperature,
providerMaxTokens,
requestTools
effectiveRequestTools
)) {
if (!didConsumeSteerBatch && claimedSteerBatch.length > 0) {
pendingInputCoordinator.consumeClaimedSteerBatch(sessionId)
Expand Down
18 changes: 14 additions & 4 deletions src/main/presenter/llmProviderPresenter/aiSdk/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import type { LLMCoreStreamEvent } from '@shared/types/core/llm-events'
import { mcpToolsToAISDKTools } from './toolMapper'
import { mapMessagesToModelMessages } from './messageMapper'
import { buildProviderOptions } from './providerOptionsMapper'
import { ProxyAgent } from 'undici'
import { proxyConfig } from '../../proxyConfig'
import { type AiSdkProviderKind, createAiSdkProviderContext } from './providerFactory'
import { adaptAiSdkStream } from './streamAdapter'

Expand Down Expand Up @@ -228,9 +230,11 @@ async function executeTtsPatternA(

const controller = new AbortController()
const timeoutId = timeout ? setTimeout(() => controller.abort(), timeout) : undefined
const proxyUrl = proxyConfig.getProxyUrl()
const dispatcher = proxyUrl ? new ProxyAgent(proxyUrl) : undefined

try {
const response = await fetch(url, {
const fetchInit: RequestInit & { dispatcher?: ProxyAgent } = {
method: 'POST',
headers: {
...defaultHeaders,
Expand All @@ -239,7 +243,9 @@ async function executeTtsPatternA(
},
body: JSON.stringify(body),
signal: controller.signal
})
}
if (dispatcher) fetchInit.dispatcher = dispatcher
const response = await fetch(url, fetchInit)

if (!response.ok) {
const errText = await response.text().catch(() => '')
Expand Down Expand Up @@ -283,9 +289,11 @@ async function executeTtsPatternB(

const controller = new AbortController()
const timeoutId = timeout ? setTimeout(() => controller.abort(), timeout) : undefined
const proxyUrl = proxyConfig.getProxyUrl()
const dispatcher = proxyUrl ? new ProxyAgent(proxyUrl) : undefined

try {
const response = await fetch(url, {
const fetchInit: RequestInit & { dispatcher?: ProxyAgent } = {
method: 'POST',
headers: {
...defaultHeaders,
Expand All @@ -294,7 +302,9 @@ async function executeTtsPatternB(
},
body: JSON.stringify(body),
signal: controller.signal
})
}
if (dispatcher) fetchInit.dispatcher = dispatcher
const response = await fetch(url, fetchInit)

if (!response.ok) {
const errText = await response.text().catch(() => '')
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/settings/components/ProviderModelList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ const hasModelCapability = (model: RENDERER_MODEL_META, capability: ModelCapabil

const getModelTypeLabel = (type: ModelType) => {
if (type === ModelType.TTS) {
return t('settings.provider.voiceai.title')
return t('settings.provider.tts.title')
}
return t(`model.filter.typeOptions.${type}`)
}
Expand Down
36 changes: 18 additions & 18 deletions src/renderer/settings/components/VoiceAIProviderConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<Icon icon="lucide:audio-waveform" class="h-5 w-5" />
</div>
<div class="space-y-1">
<p class="text-sm font-medium">{{ t('settings.provider.voiceai.title') }}</p>
<p class="text-sm font-medium">{{ t('settings.provider.tts.title') }}</p>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.description') }}
{{ t('settings.provider.tts.description') }}
</p>
</div>
</div>
Expand All @@ -18,11 +18,11 @@
<div class="grid gap-4 md:grid-cols-2">
<div class="space-y-2">
<Label :for="`${provider.id}-audio-format`" class="text-xs font-medium">
{{ t('settings.provider.voiceai.audioFormat.label') }}
{{ t('settings.provider.tts.audioFormat.label') }}
</Label>
<Select v-model="audioFormat" :disabled="isHydrating">
<SelectTrigger :id="`${provider.id}-audio-format`">
<SelectValue :placeholder="t('settings.provider.voiceai.audioFormat.placeholder')" />
<SelectValue :placeholder="t('settings.provider.tts.audioFormat.placeholder')" />
</SelectTrigger>
<SelectContent>
<SelectItem value="mp3">MP3</SelectItem>
Expand All @@ -31,17 +31,17 @@
</SelectContent>
</Select>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.audioFormat.helper') }}
{{ t('settings.provider.tts.audioFormat.helper') }}
</p>
</div>

<div class="space-y-2">
<Label :for="`${provider.id}-language`" class="text-xs font-medium">
{{ t('settings.provider.voiceai.language.label') }}
{{ t('settings.provider.tts.language.label') }}
</Label>
<Select v-model="language" :disabled="isHydrating">
<SelectTrigger :id="`${provider.id}-language`">
<SelectValue :placeholder="t('settings.provider.voiceai.language.placeholder')" />
<SelectValue :placeholder="t('settings.provider.tts.language.placeholder')" />
</SelectTrigger>
<SelectContent>
<SelectItem
Expand All @@ -54,37 +54,37 @@
</SelectContent>
</Select>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.language.helper') }}
{{ t('settings.provider.tts.language.helper') }}
</p>
</div>

<div class="space-y-2 md:col-span-2">
<Label :for="`${provider.id}-tts-model`" class="text-xs font-medium">
{{ t('settings.provider.voiceai.model.label') }}
{{ t('settings.provider.tts.model.label') }}
</Label>
<Input
:id="`${provider.id}-tts-model`"
v-model="ttsModel"
:placeholder="t('settings.provider.voiceai.model.placeholder')"
:placeholder="t('settings.provider.tts.model.placeholder')"
:disabled="isHydrating"
/>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.model.helper') }}
{{ t('settings.provider.tts.model.helper') }}
</p>
</div>

<div class="space-y-2 md:col-span-2">
<Label :for="`${provider.id}-agent-id`" class="text-xs font-medium">
{{ t('settings.provider.voiceai.agentId.label') }}
{{ t('settings.provider.tts.agentId.label') }}
</Label>
<Input
:id="`${provider.id}-agent-id`"
v-model="agentId"
:placeholder="t('settings.provider.voiceai.agentId.placeholder')"
:placeholder="t('settings.provider.tts.agentId.placeholder')"
:disabled="isHydrating"
/>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.agentId.helper') }}
{{ t('settings.provider.tts.agentId.helper') }}
</p>
</div>
</div>
Expand All @@ -95,7 +95,7 @@
<div class="space-y-2">
<div class="flex items-center justify-between">
<Label :for="`${provider.id}-temperature`" class="text-xs font-medium">
{{ t('settings.provider.voiceai.temperature.label') }}
{{ t('settings.provider.tts.temperature.label') }}
</Label>
<span class="text-xs text-muted-foreground">{{ temperature.toFixed(2) }}</span>
</div>
Expand All @@ -108,14 +108,14 @@
@update:model-value="onTemperatureChange"
/>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.temperature.helper') }}
{{ t('settings.provider.tts.temperature.helper') }}
</p>
</div>

<div class="space-y-2">
<div class="flex items-center justify-between">
<Label :for="`${provider.id}-top-p`" class="text-xs font-medium">
{{ t('settings.provider.voiceai.topP.label') }}
{{ t('settings.provider.tts.topP.label') }}
</Label>
<span class="text-xs text-muted-foreground">{{ topP.toFixed(2) }}</span>
</div>
Expand All @@ -128,7 +128,7 @@
@update:model-value="onTopPChange"
/>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.topP.helper') }}
{{ t('settings.provider.tts.topP.helper') }}
</p>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/components/settings/ModelConfigDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
{{ t('settings.model.modelConfig.type.options.imageGeneration') }}
</SelectItem>
<SelectItem value="tts">
{{ t('settings.provider.voiceai.title') }}
{{ t('settings.provider.tts.title') }}
</SelectItem>
</SelectContent>
</Select>
Expand Down Expand Up @@ -241,7 +241,7 @@
{{ t('settings.model.modelConfig.apiEndpoint.options.image') }}
</SelectItem>
<SelectItem value="audio-speech">
{{ t('settings.provider.voiceai.title') }}
{{ t('settings.provider.tts.title') }}
</SelectItem>
</SelectContent>
</Select>
Expand Down
16 changes: 8 additions & 8 deletions src/renderer/src/components/settings/TtsSettingsFields.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
<template>
<div class="space-y-4">
<div class="space-y-2">
<Label>{{ t('settings.provider.voiceai.title') }}</Label>
<Label>{{ t('settings.provider.tts.title') }}</Label>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.description') }}
{{ t('settings.provider.tts.description') }}
</p>
</div>

<div class="space-y-2">
<Label>{{ t('settings.provider.voiceai.agentId.label') }}</Label>
<Label>{{ t('settings.provider.tts.agentId.label') }}</Label>
<Input
:model-value="tts.voice ?? ''"
:placeholder="t('settings.provider.voiceai.agentId.placeholder')"
:placeholder="t('settings.provider.tts.agentId.placeholder')"
@update:model-value="onVoiceInput"
/>
</div>

<div class="space-y-2">
<Label>{{ t('settings.provider.voiceai.audioFormat.label') }}</Label>
<Label>{{ t('settings.provider.tts.audioFormat.label') }}</Label>
<Select
:model-value="optionSelectValue(tts.responseFormat)"
@update:model-value="onResponseFormatSelect"
>
<SelectTrigger>
<SelectValue :placeholder="t('settings.provider.voiceai.audioFormat.placeholder')" />
<SelectValue :placeholder="t('settings.provider.tts.audioFormat.placeholder')" />
</SelectTrigger>
<SelectContent>
<SelectItem :value="DEFAULT_SELECT_VALUE">
Expand All @@ -37,7 +37,7 @@
</div>

<div class="space-y-2">
<Label>{{ t('settings.provider.voiceai.temperature.label') }}</Label>
<Label>{{ t('settings.provider.tts.temperature.label') }}</Label>
<Input
:model-value="speedDraft"
inputmode="decimal"
Expand All @@ -47,7 +47,7 @@
@keydown.enter.prevent="commitSpeed"
/>
<p class="text-xs text-muted-foreground">
{{ t('settings.provider.voiceai.temperature.helper') }}
{{ t('settings.provider.tts.temperature.helper') }}
</p>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/da-DK/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -579,8 +579,8 @@
"stopModel": "Stop model",
"pulling": "Henter...",
"runModel": "Kør model",
"voiceai": {
"title": "Voice.ai tekst-til-tale",
"tts": {
"title": "Tekst-til-tale (TTS)",
"description": "Generér tale fra tekst. Stemmer vises i modellisten nedenfor.",
"audioFormat": {
"label": "Lydformat",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/en-US/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -907,8 +907,8 @@
"verifyFailed": "Verification failed",
"verifySuccess": "Verification is successful"
},
"voiceai": {
"title": "Voice.ai Text-to-Speech",
"tts": {
"title": "Text-to-Speech (TTS)",
"description": "Generate speech from text. Voices appear in the model list below.",
"audioFormat": {
"label": "Audio Format",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/fa-IR/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,8 @@
"stopModel": "ایست مدل",
"pulling": "در حال دریافت...",
"runModel": "اجرای مدل",
"voiceai": {
"title": "تبدیل متن به گفتار Voice.ai",
"tts": {
"title": "تبدیل متن به گفتار (TTS)",
"description": "گفتار را از متن تولید کنید. صداها در فهرست مدل‌ها در پایین نمایش داده می‌شوند.",
"audioFormat": {
"label": "قالب صوتی",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/fr-FR/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,8 @@
"stopModel": "Arrêter le modèle",
"pulling": "Récupération...",
"runModel": "Exécuter le modèle",
"voiceai": {
"title": "Synthèse vocale Voice.ai",
"tts": {
"title": "Synthese vocale (TTS)",
Comment thread
zhangmo8 marked this conversation as resolved.
"description": "Générez de la parole à partir du texte. Les voix apparaissent dans la liste des modèles ci-dessous.",
"audioFormat": {
"label": "Format audio",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/he-IL/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,8 @@
"stopModel": "עצור מודל",
"pulling": "מושך...",
"runModel": "הרץ מודל",
"voiceai": {
"title": "המרת טקסט לדיבור של Voice.ai",
"tts": {
"title": "המרת טקסט לדיבור (TTS)",
"description": "יצירת דיבור מטקסט. קולות יופיעו ברשימת המודלים למטה.",
"audioFormat": {
"label": "פורמט שמע",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/ja-JP/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,8 @@
"stopModel": "モデルを停止",
"pulling": "取得中...",
"runModel": "モデルを実行",
"voiceai": {
"title": "Voice.ai テキスト読み上げ",
"tts": {
"title": "テキスト読み上げ (TTS)",
"description": "テキストから音声を生成します。音声は下のモデル一覧に表示されます。",
"audioFormat": {
"label": "音声形式",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/i18n/ko-KR/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -652,8 +652,8 @@
"stopModel": "모델 중지",
"pulling": "가져오는 중...",
"runModel": "모델 실행",
"voiceai": {
"title": "Voice.ai 텍스트 음성 변환",
"tts": {
"title": "텍스트 음성 변환 (TTS)",
"description": "텍스트로부터 음성을 생성합니다. 음성은 아래 모델 목록에 표시됩니다.",
"audioFormat": {
"label": "오디오 형식",
Expand Down
Loading