@xopcai/xopc 0.0.75 → 0.0.77

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.
Files changed (53) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agents-Bq-2L2z0.js → agents-DN3vr8pb.js} +2 -2
  4. package/dist/gateway/static/root/assets/{agents-Bq-2L2z0.js.map → agents-DN3vr8pb.js.map} +1 -1
  5. package/dist/gateway/static/root/assets/{apps-page-DitlAmYZ.js → apps-page-BUn41aPi.js} +2 -2
  6. package/dist/gateway/static/root/assets/{apps-page-DitlAmYZ.js.map → apps-page-BUn41aPi.js.map} +1 -1
  7. package/dist/gateway/static/root/assets/{channels-settings-BzJYkjyh.js → channels-settings-CYMmWDtP.js} +2 -2
  8. package/dist/gateway/static/root/assets/{channels-settings-BzJYkjyh.js.map → channels-settings-CYMmWDtP.js.map} +1 -1
  9. package/dist/gateway/static/root/assets/{channels-status-swr-CiY7i2IN.js → channels-status-swr-sJj4ueTp.js} +2 -2
  10. package/dist/gateway/static/root/assets/{channels-status-swr-CiY7i2IN.js.map → channels-status-swr-sJj4ueTp.js.map} +1 -1
  11. package/dist/gateway/static/root/assets/{cron-api-S4gy4e5e.js → cron-api-CLxnaHdq.js} +2 -2
  12. package/dist/gateway/static/root/assets/{cron-api-S4gy4e5e.js.map → cron-api-CLxnaHdq.js.map} +1 -1
  13. package/dist/gateway/static/root/assets/{cron-page-7uMZvuju.js → cron-page-BAQ8xSnJ.js} +2 -2
  14. package/dist/gateway/static/root/assets/{cron-page-7uMZvuju.js.map → cron-page-BAQ8xSnJ.js.map} +1 -1
  15. package/dist/gateway/static/root/assets/{dist-DXGDHevt.js → dist-BfJYxiK5.js} +2 -2
  16. package/dist/gateway/static/root/assets/{dist-DXGDHevt.js.map → dist-BfJYxiK5.js.map} +1 -1
  17. package/dist/gateway/static/root/assets/{extension-debug-page-DYLqqlXt.js → extension-debug-page-bgvVs-Sy.js} +2 -2
  18. package/dist/gateway/static/root/assets/{extension-debug-page-DYLqqlXt.js.map → extension-debug-page-bgvVs-Sy.js.map} +1 -1
  19. package/dist/gateway/static/root/assets/{extension-page-H9Odxw56.js → extension-page-SG4TVv-u.js} +2 -2
  20. package/dist/gateway/static/root/assets/{extension-page-H9Odxw56.js.map → extension-page-SG4TVv-u.js.map} +1 -1
  21. package/dist/gateway/static/root/assets/{extension-settings-page-Ch6vY8Uy.js → extension-settings-page-CJZRTsjF.js} +2 -2
  22. package/dist/gateway/static/root/assets/{extension-settings-page-Ch6vY8Uy.js.map → extension-settings-page-CJZRTsjF.js.map} +1 -1
  23. package/dist/gateway/static/root/assets/{field-primitives-CrexIsCD.js → field-primitives-Z76hyBYS.js} +2 -2
  24. package/dist/gateway/static/root/assets/{field-primitives-CrexIsCD.js.map → field-primitives-Z76hyBYS.js.map} +1 -1
  25. package/dist/gateway/static/root/assets/{heartbeat-config-api-CVGIOMMM.js → heartbeat-config-api-BqfDabSI.js} +2 -2
  26. package/dist/gateway/static/root/assets/{heartbeat-config-api-CVGIOMMM.js.map → heartbeat-config-api-BqfDabSI.js.map} +1 -1
  27. package/dist/gateway/static/root/assets/{index-S3bgG2JF.js → index-ChiUhJAs.js} +44 -41
  28. package/dist/gateway/static/root/assets/{index-S3bgG2JF.js.map → index-ChiUhJAs.js.map} +1 -1
  29. package/dist/gateway/static/root/assets/{logs-page-BKpRWihz.js → logs-page-DrIMhDE2.js} +2 -2
  30. package/dist/gateway/static/root/assets/{logs-page-BKpRWihz.js.map → logs-page-DrIMhDE2.js.map} +1 -1
  31. package/dist/gateway/static/root/assets/{sessions-page-BRFJ-djK.js → sessions-page-B-RGO3N0.js} +2 -2
  32. package/dist/gateway/static/root/assets/{sessions-page-BRFJ-djK.js.map → sessions-page-B-RGO3N0.js.map} +1 -1
  33. package/dist/gateway/static/root/assets/{settings-form-section-cS13ImiU.js → settings-form-section-Csvl1iL6.js} +2 -2
  34. package/dist/gateway/static/root/assets/{settings-form-section-cS13ImiU.js.map → settings-form-section-Csvl1iL6.js.map} +1 -1
  35. package/dist/gateway/static/root/assets/{settings-page-D99K6Jjx.js → settings-page-nxAc0ta1.js} +2 -2
  36. package/dist/gateway/static/root/assets/{settings-page-D99K6Jjx.js.map → settings-page-nxAc0ta1.js.map} +1 -1
  37. package/dist/gateway/static/root/assets/{skills-page-CjBO9BH2.js → skills-page-dHwx2vh0.js} +2 -2
  38. package/dist/gateway/static/root/assets/{skills-page-CjBO9BH2.js.map → skills-page-dHwx2vh0.js.map} +1 -1
  39. package/dist/gateway/static/root/assets/{utils-DVw8OvAC.js → utils-COYrNFF7.js} +2 -2
  40. package/dist/gateway/static/root/assets/{utils-DVw8OvAC.js.map → utils-COYrNFF7.js.map} +1 -1
  41. package/dist/gateway/static/root/assets/{voice-api-key-field-BIh7mDN6.js → voice-api-key-field-5WZZaxH3.js} +2 -2
  42. package/dist/gateway/static/root/assets/{voice-api-key-field-BIh7mDN6.js.map → voice-api-key-field-5WZZaxH3.js.map} +1 -1
  43. package/dist/gateway/static/root/index.html +1 -1
  44. package/dist/package.js +1 -1
  45. package/dist/src/agent/embedded/session-manager-init.js +5 -1
  46. package/dist/src/agent/embedded/session-manager-init.js.map +1 -1
  47. package/dist/src/channels/index.js +1 -1
  48. package/dist/src/channels/manager.js +1 -1
  49. package/dist/src/cli/commands/channels.js +1 -1
  50. package/dist/src/gateway/heartbeat/service.js +1 -1
  51. package/dist/src/gateway/service.js +1 -1
  52. package/dist/src/heartbeat/index.js +1 -1
  53. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"voice-api-key-field-BIh7mDN6.js","names":["IMAGE_PROVIDERS_SWR_KEY","fetchJson","apiUrl","IMAGE_PROVIDERS_SWR_KEY","ImageGenProviderCredentialSummary","fetchImageProvidersList","Promise","res","ok","payload","providers","isMaskedKey","revalidateGatewayConfig","fetchJson","apiUrl","ImageProviderCredRow","apiKey","region","baseUrl","imageBaseUrl","emptyImageProviderCredRow","SafeProviderAuthEntry","maskedApiKeyDisplay","safe","imageProviderCredRowsFromConfigRoot","config","imageProviderIds","Record","pc","undefined","v","providersConfig","Array","isArray","out","id","optionalStringField","draft","baseline","key","Pick","d","trim","b","apiKeyPatchValue","draftKey","baselineKey","buildImageProvidersConfigPatch","patch","JSON","stringify","entry","keyDelta","Object","keys","length","RevealImageProviderApiKeyPayload","source","revealImageProviderConfigApiKey","providerId","Promise","data","ok","payload","error","message","encodeURIComponent","method","headers","body","Error","patchImageProvidersConfig","useCallback","useReducer","useRef","isMaskedKey","copyTextToClipboard","MaskedApiKeyUiState","showKey","revealed","revealLoading","revealErr","copied","MaskedApiKeyUiAction","type","value","message","initialMaskedApiKeyUi","undefined","maskedApiKeyUiReducer","state","action","useMaskedApiKeyField","options","reveal","Promise","loadFailedLabel","ui","dispatch","masked","revealRef","current","trackedMaskedRef","inputValue","inputType","const","copyEnabled","trim","length","Boolean","copyKey","text","ok","window","setTimeout","toggleEye","plaintext","e","Error","onInputChange","next","onChange","CheckCircle2","Copy","ExternalLink","Eye","EyeOff","Loader2","useCallback","revealImageProviderConfigApiKey","ApiKeyLinkKind","providerApiKeyLinkLabel","ProvidersSettingsMessages","settingsInputFocusClass","interaction","cn","useMaskedApiKeyField","ImageProviderApiKeyFieldLabels","apiKeyLabel","optionalPlaceholder","maskedHelp","copy","copied","show","hide","notInConfigFile","loadFailed","ImageProviderApiKeyField","t0","$","_c","providerId","value","onChange","labels","apiKeyLinks","apiKeyLinkLabels","t1","then","_temp","reveal","t2","loadFailedLabel","masked","showKey","revealed","revealLoading","revealErr","inputValue","inputType","copyEnabled","copyKey","toggleEye","onInputChange","t3","t4","t5","length","map","link","kind","href","t6","t7","t8","Symbol","for","t9","t10","e","target","t11","t12","transition","press","focusRingPanel","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","payload","apiKey","ChevronDown","ExternalLink","Loader2","Save","useMemo","useState","Link","Button","ImageProviderApiKeyField","emptyImageProviderCredRow","ImageProviderCredRow","getOrderedApiKeyLinks","ImageGenProviderCredentialSummary","ImageProviderUiMetadata","ProvidersSettingsMessages","settingsInputFocusClass","StoredLanguage","cn","inputClass","selectClass","CUSTOM_SENTINEL","dashscopeSelectValue","row","regions","NonNullable","region","trim","imageBaseUrl","r","toLowerCase","some","x","value","baseUrlSelectValue","presets","b","baseUrl","replace","norm","map","p","idx","indexOf","ImageProviderCredentialsPanelMessages","credentialsIntro","regionHint","endpointPresetsHint","apiKeyLabel","optionalPlaceholder","regionLabel","baseUrlLabel","imageBaseUrlLabel","saveCredentials","savingCredentials","credentialsSaved","discardCredentials","credentialsNothingToSave","credentialsSaveError","regionPresetDefault","regionPresetCustom","baseUrlPresetDefault","baseUrlPresetCustom","openExtensionSettings","openImageModelsPage","extensionSettingsLinkTitle","imageModelsLinkTitle","configured","missingKey","unsavedChanges","expandProvider","collapseProvider","defaultModel","modelsLabel","modelCountOne","modelCountMany","imageBaseUrlPresetHint","dashscopeRegion_beijing","dashscopeRegion_singapore","dashscopeRegion_us","apiKeyMaskedHelp","apiKeyCopy","apiKeyCopied","apiKeyShow","apiKeyHide","apiKeyNotInConfigFile","apiKeyRevealFailed","minimaxClusterLabel","minimaxClusterHint","falQueueBaseLabel","falQueueBaseHint","translateDashscopeRegion","m","serverLabel","baseUrlPresetBlockTitle","t","kind","baseUrlPresetBlockHint","isProviderRowDirty","draft","baseline","JSON","stringify","formatModelCount","count","String","ImageProviderCredentialsPanel","t0","$","_c","summaries","credDraft","credBaseline","credDirty","credSaving","credError","credSavedFlash","credNoopFlash","updateCredRow","onDiscardCredentials","onSaveCredentials","extensionIds","showExtensionLinks","showImageModelsLink","hideActions","t1","language","apiKeyLinkLabels","messages","undefined","t2","_temp","anyRegionUi","t3","_temp2","anyBaseUrlPresets","manualExpandedIds","setManualExpandedIds","_temp3","manualCollapsedIds","setManualCollapsedIds","_temp4","ids","Set","summary","draftRow","id","baselineRow","add","dirtyProviderIds","t4","has","isProviderExpanded","t5","id_0","expanded","current","current_0","next","delete","current_1","next_0","current_2","toggleProviderExpanded","length","t6","t7","t8","t9","t10","t11","t12","t13","t14","ui","extPath","encodeURIComponent","baselineRow_0","isDirty","isExpanded","providerName","label","modelCountLabel","models","modelId","join","apiKey","next_1","maskedHelp","copy","copied","show","hide","notInConfigFile","loadFailed","e","v","target","opt","find","e_0","e_1","baseUrlPresets","baseUrlPresetKind","e_2","v_0","_temp5","e_3","t15","s_0","s","useCallback","useMemo","useRef","useState","mutate","useGatewayConfigSwr","buildImageProvidersConfigPatch","emptyImageProviderCredRow","imageProviderCredRowsFromConfigRoot","patchImageProvidersConfig","ImageProviderCredRow","IMAGE_PROVIDERS_SWR_KEY","apiUrl","useGatewayStore","ImageProviderUiRegionOption","value","label","imageBaseUrl","ImageProviderUiBaseUrlPreset","ImageProviderUiMetadata","regions","baseUrlPresets","baseUrlPresetKind","ImageGenProviderCredentialSummary","id","defaultModel","models","configured","ui","useImageProviderCredentials","summaries","hasToken","s","Boolean","token","gwSwr","gwCfg","data","ids","map","dirtyRef","localDraft","setLocalDraft","Record","credSaving","setCredSaving","credError","setCredError","credSavedFlash","setCredSavedFlash","credNoopFlash","setCredNoopFlash","credRowsFromServer","payload","config","credDraft","credBaseline","credDirty","JSON","stringify","updateCredRow","patch","Partial","current","prev","base","row","onDiscardCredentials","saveCredentials","errorFallback","Object","keys","length","window","setTimeout","updated","e","Error","message","revalidateGatewayConfig","fetchJson","apiUrl","SttSettings","SttProvidersPayload","TtsSettings","VoiceModelsPayload","VoiceSettingsState","VoiceProvidersPayload","TtsProviderListEntry","SttProviderListEntry","defaultStt","enabled","provider","alibaba","model","openai","fallback","order","defaultTts","trigger","maxTextLength","timeoutMs","voice","edge","minimax","command","outputFormat","isRecord","v","Record","Array","isArray","normalizeSttProvider","trim","length","mergeStt","raw","d","baseFallback","filter","x","providers","Object","fromEntries","entries","map","key","value","undefined","Boolean","normalizeTtsProvider","mergeTts","localCliRaw","Number","isFinite","normalizeVoiceSettings","config","c","stt","tts","fetchVoiceSettings","Promise","res","ok","payload","patchVoiceSettings","state","method","body","JSON","stringify","fetchVoiceModels","models","Error","fetchVoiceProviders","fetchVoiceSttProviders","RevealVoiceApiKeyPayload","kind","apiKey","source","revealVoiceConfigApiKey","args","Check","Copy","Eye","EyeOff","Loader2","useCallback","Button","revealVoiceConfigApiKey","settingsInputFocusClass","cn","useMaskedApiKeyField","VoiceApiKeyFieldLabels","maskedHelp","copy","copied","show","hide","notInConfigFile","loadFailed","VoiceApiKeyField","t0","$","_c","kind","providerId","fieldId","value","onChange","labels","placeholder","t1","className","undefined","t2","provider","then","_temp","reveal","t3","loadFailedLabel","masked","showKey","revealed","revealLoading","revealErr","inputValue","inputType","copyEnabled","copyKey","toggleEye","onInputChange","t4","t5","t6","Symbol","for","t7","t8","e","target","t9","t10","t11","t12","t13","t14","t15","t16","t17","t18","payload","apiKey"],"sources":["../../../../../web/src/features/settings/image-providers-swr-key.ts","../../../../../web/src/features/settings/fetch-image-providers.ts","../../../../../web/src/features/settings/image-providers-config-api.ts","../../../../../web/src/lib/use-masked-api-key-field.ts","../../../../../web/src/features/settings/image-provider-api-key-field.tsx","../../../../../web/src/features/settings/image-provider-credentials-panel.tsx","../../../../../web/src/features/settings/use-image-provider-credentials.ts","../../../../../web/src/features/settings/voice-config-api.ts","../../../../../web/src/features/settings/voice-api-key-field.tsx"],"sourcesContent":["/** Shared SWR key for GET `/api/image/providers` (image settings + extension image pages). */\nexport const IMAGE_PROVIDERS_SWR_KEY = '/api/image/providers';\n","import { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport { IMAGE_PROVIDERS_SWR_KEY } from '@/features/settings/image-providers-swr-key';\nimport type { ImageGenProviderCredentialSummary } from '@/features/settings/use-image-provider-credentials';\n\nexport async function fetchImageProvidersList(): Promise<ImageGenProviderCredentialSummary[]> {\n const res = await fetchJson<{\n ok?: boolean;\n payload?: { providers?: ImageGenProviderCredentialSummary[] };\n }>(apiUrl(IMAGE_PROVIDERS_SWR_KEY));\n return res?.payload?.providers ?? [];\n}\n","import { isMaskedKey } from '@/features/settings/providers-api';\nimport { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\n/** One row of image-provider credential fields (matches PATCH `providersConfig` subset). */\nexport type ImageProviderCredRow = {\n apiKey: string;\n region: string;\n baseUrl: string;\n imageBaseUrl: string;\n};\n\nexport function emptyImageProviderCredRow(): ImageProviderCredRow {\n return { apiKey: '', region: '', baseUrl: '', imageBaseUrl: '' };\n}\n\nexport type SafeProviderAuthEntry = {\n apiKey: string;\n region?: string;\n baseUrl?: string;\n imageBaseUrl?: string;\n};\n\nfunction maskedApiKeyDisplay(safe?: SafeProviderAuthEntry): string {\n if (!safe?.apiKey) return '';\n return '••••••••••••';\n}\n\n/** Read `payload.config.providersConfig` from GET /api/config (masked). */\nexport function imageProviderCredRowsFromConfigRoot(\n config: unknown,\n imageProviderIds: string[],\n): Record<string, ImageProviderCredRow> {\n const pc = (() => {\n if (!config || typeof config !== 'object' || !('providersConfig' in config)) return undefined;\n const v = (config as { providersConfig?: unknown }).providersConfig;\n if (!v || typeof v !== 'object' || Array.isArray(v)) return undefined;\n return v as Record<string, SafeProviderAuthEntry>;\n })();\n\n const out: Record<string, ImageProviderCredRow> = {};\n for (const id of imageProviderIds) {\n const safe = pc?.[id];\n out[id] = {\n apiKey: maskedApiKeyDisplay(safe),\n region: safe?.region ?? '',\n baseUrl: safe?.baseUrl ?? '',\n imageBaseUrl: safe?.imageBaseUrl ?? '',\n };\n }\n return out;\n}\n\nfunction optionalStringField(\n draft: ImageProviderCredRow,\n baseline: ImageProviderCredRow,\n key: keyof Pick<ImageProviderCredRow, 'region' | 'baseUrl' | 'imageBaseUrl'>,\n): string | null | undefined {\n const d = draft[key].trim();\n const b = baseline[key].trim();\n if (d === b) return undefined;\n if (!d) return null;\n return d;\n}\n\nfunction apiKeyPatchValue(draftKey: string, baselineKey: string): string | null | undefined {\n const d = draftKey.trim();\n const b = baselineKey.trim();\n if (d === b) return undefined;\n if (isMaskedKey(d) && isMaskedKey(b)) return undefined;\n if (!d) {\n if (!b) return undefined;\n return null;\n }\n return d;\n}\n\n/**\n * Build `providersConfig` PATCH entries only for image providers whose row changed.\n * Omits `apiKey` when unchanged (still masked); sends `null` to clear stored key.\n */\nexport function buildImageProvidersConfigPatch(\n imageProviderIds: string[],\n draft: Record<string, ImageProviderCredRow>,\n baseline: Record<string, ImageProviderCredRow>,\n): Record<string, Record<string, unknown>> {\n const patch: Record<string, Record<string, unknown>> = {};\n for (const id of imageProviderIds) {\n const d = draft[id] ?? emptyImageProviderCredRow();\n const b = baseline[id] ?? emptyImageProviderCredRow();\n if (JSON.stringify(d) === JSON.stringify(b)) continue;\n\n const entry: Record<string, unknown> = {};\n const keyDelta = apiKeyPatchValue(d.apiKey, b.apiKey);\n if (keyDelta !== undefined) {\n entry.apiKey = keyDelta;\n }\n const region = optionalStringField(d, b, 'region');\n if (region !== undefined) entry.region = region;\n const baseUrl = optionalStringField(d, b, 'baseUrl');\n if (baseUrl !== undefined) entry.baseUrl = baseUrl;\n const imageBaseUrl = optionalStringField(d, b, 'imageBaseUrl');\n if (imageBaseUrl !== undefined) entry.imageBaseUrl = imageBaseUrl;\n\n if (Object.keys(entry).length > 0) {\n patch[id] = entry;\n }\n }\n return patch;\n}\n\nexport type RevealImageProviderApiKeyPayload = {\n id: string;\n apiKey: string | null;\n source: 'config' | 'none';\n};\n\n/** POST /api/image/providers/:id/reveal-api-key — plaintext only when stored in config file. */\nexport async function revealImageProviderConfigApiKey(providerId: string): Promise<RevealImageProviderApiKeyPayload> {\n const data = await fetchJson<{\n ok?: boolean;\n payload?: RevealImageProviderApiKeyPayload;\n error?: { message?: string };\n }>(apiUrl(`/api/image/providers/${encodeURIComponent(providerId)}/reveal-api-key`), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: '{}',\n });\n if (!data.ok || !data.payload) {\n throw new Error(data.error?.message ?? 'Reveal failed');\n }\n return data.payload;\n}\n\nexport async function patchImageProvidersConfig(\n patch: Record<string, Record<string, unknown>>,\n): Promise<void> {\n if (Object.keys(patch).length === 0) return;\n await fetchJson(apiUrl('/api/config'), {\n method: 'PATCH',\n body: JSON.stringify({ providersConfig: patch }),\n });\n await revalidateGatewayConfig();\n}\n","import { useCallback, useReducer, useRef } from 'react';\n\nimport { isMaskedKey } from '@/features/settings/providers-api';\nimport { copyTextToClipboard } from '@/lib/copy-to-clipboard';\n\ntype MaskedApiKeyUiState = {\n showKey: boolean;\n /** `undefined` = not fetched; `null` = fetched, not in config file; string = plaintext from config */\n revealed: string | null | undefined;\n revealLoading: boolean;\n revealErr: string | null;\n copied: boolean;\n};\n\ntype MaskedApiKeyUiAction =\n | { type: 'reset-reveal' }\n | { type: 'toggle-show' }\n | { type: 'reveal-start' }\n | { type: 'reveal-success'; value: string | null }\n | { type: 'reveal-error'; message: string }\n | { type: 'copied' }\n | { type: 'clear-copied' }\n | { type: 'invalidate-reveal' };\n\nconst initialMaskedApiKeyUi: MaskedApiKeyUiState = {\n showKey: false,\n revealed: undefined,\n revealLoading: false,\n revealErr: null,\n copied: false,\n};\n\nfunction maskedApiKeyUiReducer(\n state: MaskedApiKeyUiState,\n action: MaskedApiKeyUiAction,\n): MaskedApiKeyUiState {\n switch (action.type) {\n case 'reset-reveal':\n return { ...state, showKey: false, revealed: undefined, revealErr: null };\n case 'toggle-show':\n return { ...state, showKey: !state.showKey };\n case 'reveal-start':\n return { ...state, revealLoading: true, revealErr: null };\n case 'reveal-success':\n return {\n ...state,\n revealed: action.value,\n revealLoading: false,\n showKey: true,\n revealErr: null,\n };\n case 'reveal-error':\n return {\n ...state,\n revealed: null,\n revealLoading: false,\n revealErr: action.message,\n };\n case 'copied':\n return { ...state, copied: true };\n case 'clear-copied':\n return { ...state, copied: false };\n case 'invalidate-reveal':\n return { ...state, revealed: undefined, showKey: false };\n }\n}\n\nexport function useMaskedApiKeyField(options: {\n value: string;\n reveal: () => Promise<string | null>;\n loadFailedLabel: string;\n}) {\n const { value, reveal, loadFailedLabel } = options;\n const [ui, dispatch] = useReducer(maskedApiKeyUiReducer, initialMaskedApiKeyUi);\n\n const masked = isMaskedKey(value);\n const revealRef = useRef(reveal);\n revealRef.current = reveal;\n\n const trackedMaskedRef = useRef({ masked, value });\n if (\n !masked &&\n (trackedMaskedRef.current.masked || trackedMaskedRef.current.value !== value)\n ) {\n dispatch({ type: 'reset-reveal' });\n }\n trackedMaskedRef.current = { masked, value };\n\n const inputValue = (() => {\n if (!masked) return value;\n if (ui.showKey && typeof ui.revealed === 'string') return ui.revealed;\n return value;\n })();\n\n const inputType =\n !masked || (masked && ui.showKey && typeof ui.revealed === 'string')\n ? ('text' as const)\n : ('password' as const);\n\n const copyEnabled =\n (!masked && value.trim().length > 0 && !isMaskedKey(value)) ||\n (Boolean(ui.showKey) && typeof ui.revealed === 'string' && ui.revealed.length > 0);\n\n const copyKey = useCallback(async () => {\n const text =\n !masked && value.trim() && !isMaskedKey(value)\n ? value.trim()\n : typeof ui.revealed === 'string' && ui.revealed.length > 0\n ? ui.revealed\n : '';\n if (!text) return;\n const ok = await copyTextToClipboard(text);\n if (!ok) return;\n dispatch({ type: 'copied' });\n window.setTimeout(() => dispatch({ type: 'clear-copied' }), 2000);\n }, [masked, ui.revealed, value]);\n\n const toggleEye = useCallback(async () => {\n if (!masked) {\n dispatch({ type: 'toggle-show' });\n return;\n }\n if (ui.revealed !== undefined) {\n dispatch({ type: 'toggle-show' });\n return;\n }\n dispatch({ type: 'reveal-start' });\n try {\n const plaintext = await revealRef.current();\n dispatch({ type: 'reveal-success', value: plaintext });\n } catch (e) {\n dispatch({\n type: 'reveal-error',\n message: e instanceof Error ? e.message : loadFailedLabel,\n });\n }\n }, [loadFailedLabel, masked, ui.revealed]);\n\n const onInputChange = useCallback(\n (next: string, onChange: (value: string) => void) => {\n if (masked && typeof ui.revealed === 'string' && ui.showKey && next !== ui.revealed) {\n dispatch({ type: 'invalidate-reveal' });\n }\n onChange(next);\n },\n [masked, ui.revealed, ui.showKey],\n );\n\n return {\n masked,\n showKey: ui.showKey,\n revealed: ui.revealed,\n revealLoading: ui.revealLoading,\n revealErr: ui.revealErr,\n copied: ui.copied,\n inputValue,\n inputType,\n copyEnabled,\n copyKey,\n toggleEye,\n onInputChange,\n };\n}\n","import { CheckCircle2, Copy, ExternalLink, Eye, EyeOff, Loader2 } from 'lucide-react';\nimport { useCallback } from 'react';\n\nimport { revealImageProviderConfigApiKey } from '@/features/settings/image-providers-config-api';\nimport type { ApiKeyLinkKind } from '@/features/settings/provider-enrichment';\nimport { providerApiKeyLinkLabel } from '@/features/settings/provider-enrichment';\nimport type { ProvidersSettingsMessages } from '@/i18n/messages';\nimport { settingsInputFocusClass } from '@/lib/form-field-width';\nimport { interaction } from '@/lib/interaction';\nimport { cn } from '@/lib/cn';\nimport { useMaskedApiKeyField } from '@/lib/use-masked-api-key-field';\n\nexport type ImageProviderApiKeyFieldLabels = {\n apiKeyLabel: string;\n optionalPlaceholder: string;\n maskedHelp: string;\n copy: string;\n copied: string;\n show: string;\n hide: string;\n notInConfigFile: string;\n loadFailed: string;\n};\n\nexport function ImageProviderApiKeyField({\n providerId,\n value,\n onChange,\n labels,\n apiKeyLinks,\n apiKeyLinkLabels,\n}: {\n providerId: string;\n value: string;\n onChange: (next: string) => void;\n labels: ImageProviderApiKeyFieldLabels;\n apiKeyLinks: { href: string; kind: ApiKeyLinkKind }[];\n apiKeyLinkLabels: Pick<ProvidersSettingsMessages, 'getApiKey' | 'getApiKeyIntl' | 'getApiKeyCn'>;\n}) {\n const reveal = useCallback(\n () => revealImageProviderConfigApiKey(providerId).then((payload) => payload.apiKey ?? null),\n [providerId],\n );\n\n const {\n masked,\n showKey,\n revealed,\n revealLoading,\n revealErr,\n copied,\n inputValue,\n inputType,\n copyEnabled,\n copyKey,\n toggleEye,\n onInputChange,\n } = useMaskedApiKeyField({ value, reveal, loadFailedLabel: labels.loadFailed });\n\n return (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-key-${providerId}`}>\n {labels.apiKeyLabel}\n </label>\n {apiKeyLinks.length > 0 ? (\n <div className=\"flex flex-col gap-1\">\n {apiKeyLinks.map((link) => (\n <a\n key={`${link.kind}-${link.href}`}\n href={link.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex w-fit items-center gap-1 text-xs font-medium text-accent-fg hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n >\n {providerApiKeyLinkLabel(link.kind, apiKeyLinkLabels)}\n <ExternalLink className=\"size-3\" aria-hidden />\n </a>\n ))}\n </div>\n ) : null}\n {masked ? <p className=\"text-[11px] text-fg-subtle\">{labels.maskedHelp}</p> : null}\n <div className=\"relative min-w-0\">\n <input\n id={`img-cred-key-${providerId}`}\n type={inputType}\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(\n 'w-full rounded-lg border border-edge bg-surface-panel py-2 pl-3 pr-24 font-mono text-sm text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n )}\n value={inputValue}\n placeholder={masked ? '••••••••' : labels.optionalPlaceholder}\n onChange={(e) => onInputChange(e.target.value, onChange)}\n />\n <div className=\"absolute right-1 top-1/2 flex -translate-y-1/2 gap-0.5\">\n {copyEnabled ? (\n <button\n type=\"button\"\n className={cn(\n 'rounded p-1.5 text-fg-subtle hover:bg-surface-hover hover:text-fg',\n interaction.transition,\n interaction.press,\n interaction.focusRingPanel,\n )}\n title={copied ? labels.copied : labels.copy}\n aria-label={copied ? labels.copied : labels.copy}\n onClick={() => void copyKey()}\n >\n {copied ? <CheckCircle2 className=\"size-4\" /> : <Copy className=\"size-4\" />}\n </button>\n ) : null}\n <button\n type=\"button\"\n className={cn(\n 'rounded p-1.5 text-fg-subtle hover:bg-surface-hover hover:text-fg disabled:opacity-40',\n interaction.transition,\n interaction.press,\n interaction.focusRingPanel,\n )}\n title={showKey ? labels.hide : labels.show}\n aria-label={showKey ? labels.hide : labels.show}\n disabled={revealLoading}\n onClick={() => void toggleEye()}\n >\n {revealLoading ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n ) : showKey ? (\n <EyeOff className=\"size-4\" aria-hidden />\n ) : (\n <Eye className=\"size-4\" aria-hidden />\n )}\n </button>\n </div>\n </div>\n {masked && showKey && revealed === null && !revealErr ? (\n <p className=\"text-xs text-amber-700 dark:text-amber-400/90\">{labels.notInConfigFile}</p>\n ) : null}\n {revealErr ? <p className=\"text-xs text-red-600 dark:text-red-400\">{revealErr}</p> : null}\n </div>\n );\n}\n","import { ChevronDown, ExternalLink, Loader2, Save } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport { Link } from 'react-router-dom';\n\nimport { Button } from '@/components/ui/button';\nimport { ImageProviderApiKeyField } from '@/features/settings/image-provider-api-key-field';\nimport { emptyImageProviderCredRow, type ImageProviderCredRow } from '@/features/settings/image-providers-config-api';\nimport { getOrderedApiKeyLinks } from '@/features/settings/provider-enrichment';\nimport type {\n ImageGenProviderCredentialSummary,\n ImageProviderUiMetadata,\n} from '@/features/settings/use-image-provider-credentials';\nimport type { ProvidersSettingsMessages } from '@/i18n/messages';\nimport { settingsInputFocusClass } from '@/lib/form-field-width';\nimport type { StoredLanguage } from '@/lib/storage';\nimport { cn } from '@/lib/cn';\n\nfunction inputClass(): string {\n return cn(\n 'w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n );\n}\n\nfunction selectClass(): string {\n return cn(inputClass(), 'appearance-none bg-[length:1rem] bg-[right_0.5rem_center] bg-no-repeat pr-9');\n}\n\nconst CUSTOM_SENTINEL = '__custom__';\n\nfunction dashscopeSelectValue(\n row: ImageProviderCredRow,\n regions: NonNullable<ImageProviderUiMetadata['regions']>,\n): string {\n if (!row.region.trim() && !row.imageBaseUrl.trim()) return '';\n const r = row.region.trim().toLowerCase();\n if (regions.some((x) => x.value === r)) return r;\n return CUSTOM_SENTINEL;\n}\n\nfunction baseUrlSelectValue(\n row: ImageProviderCredRow,\n presets: NonNullable<ImageProviderUiMetadata['baseUrlPresets']>,\n): string {\n const b = row.baseUrl.trim().replace(/\\/+$/, '');\n if (!b) return '';\n const norm = presets.map((p) => p.value.replace(/\\/+$/, ''));\n const idx = norm.indexOf(b);\n if (idx >= 0) return presets[idx].value;\n return CUSTOM_SENTINEL;\n}\n\nexport type ImageProviderCredentialsPanelMessages = {\n credentialsIntro: string;\n regionHint: string;\n endpointPresetsHint: string;\n apiKeyLabel: string;\n optionalPlaceholder: string;\n regionLabel: string;\n baseUrlLabel: string;\n imageBaseUrlLabel: string;\n saveCredentials: string;\n savingCredentials: string;\n credentialsSaved: string;\n discardCredentials: string;\n credentialsNothingToSave: string;\n credentialsSaveError: string;\n regionPresetDefault: string;\n regionPresetCustom: string;\n baseUrlPresetDefault: string;\n baseUrlPresetCustom: string;\n openExtensionSettings: string;\n openImageModelsPage: string;\n extensionSettingsLinkTitle: string;\n imageModelsLinkTitle: string;\n configured: string;\n missingKey: string;\n unsavedChanges: string;\n expandProvider: string;\n collapseProvider: string;\n defaultModel: string;\n modelsLabel: string;\n modelCountOne: string;\n modelCountMany: string;\n imageBaseUrlPresetHint: string;\n dashscopeRegion_beijing: string;\n dashscopeRegion_singapore: string;\n dashscopeRegion_us: string;\n apiKeyMaskedHelp: string;\n apiKeyCopy: string;\n apiKeyCopied: string;\n apiKeyShow: string;\n apiKeyHide: string;\n apiKeyNotInConfigFile: string;\n apiKeyRevealFailed: string;\n minimaxClusterLabel: string;\n minimaxClusterHint: string;\n falQueueBaseLabel: string;\n falQueueBaseHint: string;\n};\n\nfunction translateDashscopeRegion(m: ImageProviderCredentialsPanelMessages, value: string, serverLabel: string) {\n if (value === 'beijing') return m.dashscopeRegion_beijing;\n if (value === 'singapore') return m.dashscopeRegion_singapore;\n if (value === 'us') return m.dashscopeRegion_us;\n return serverLabel;\n}\n\nfunction baseUrlPresetBlockTitle(\n t: ImageProviderCredentialsPanelMessages,\n kind: ImageProviderUiMetadata['baseUrlPresetKind'],\n): string {\n if (kind === 'minimax') return t.minimaxClusterLabel;\n if (kind === 'fal') return t.falQueueBaseLabel;\n return t.baseUrlLabel;\n}\n\nfunction baseUrlPresetBlockHint(\n t: ImageProviderCredentialsPanelMessages,\n kind: ImageProviderUiMetadata['baseUrlPresetKind'],\n): string | null {\n if (kind === 'minimax') return t.minimaxClusterHint;\n if (kind === 'fal') return t.falQueueBaseHint;\n return null;\n}\n\nfunction isProviderRowDirty(\n draft: ImageProviderCredRow,\n baseline: ImageProviderCredRow,\n): boolean {\n return JSON.stringify(draft) !== JSON.stringify(baseline);\n}\n\nfunction formatModelCount(t: ImageProviderCredentialsPanelMessages, count: number): string {\n if (count === 1) return t.modelCountOne;\n return t.modelCountMany.replace('{count}', String(count));\n}\n\nexport function ImageProviderCredentialsPanel({\n summaries,\n credDraft,\n credBaseline,\n credDirty,\n credSaving,\n credError,\n credSavedFlash,\n credNoopFlash,\n updateCredRow,\n onDiscardCredentials,\n onSaveCredentials,\n extensionIds,\n showExtensionLinks,\n showImageModelsLink,\n hideActions = false,\n language,\n apiKeyLinkLabels,\n messages: t,\n}: {\n summaries: ImageGenProviderCredentialSummary[];\n credDraft: Record<string, ImageProviderCredRow>;\n credBaseline: Record<string, ImageProviderCredRow>;\n credDirty: boolean;\n credSaving: boolean;\n credError: string | null;\n credSavedFlash: boolean;\n credNoopFlash: boolean;\n updateCredRow: (id: string, patch: Partial<ImageProviderCredRow>) => void;\n onDiscardCredentials: () => void;\n onSaveCredentials: () => void;\n /** Extension ids present in gateway discovery (for deep links). */\n extensionIds: Set<string>;\n showExtensionLinks: boolean;\n showImageModelsLink: boolean;\n /** When true, hides the inline Discard/Save buttons (caller uses a global Save bar instead). */\n hideActions?: boolean;\n language: StoredLanguage;\n apiKeyLinkLabels: Pick<ProvidersSettingsMessages, 'getApiKey' | 'getApiKeyIntl' | 'getApiKeyCn'>;\n messages: ImageProviderCredentialsPanelMessages;\n}) {\n const anyRegionUi = summaries.some((s) => (s.ui?.regions?.length ?? 0) > 0);\n const anyBaseUrlPresets = summaries.some((s) => (s.ui?.baseUrlPresets?.length ?? 0) > 0);\n const [manualExpandedIds, setManualExpandedIds] = useState<Set<string>>(() => new Set());\n const [manualCollapsedIds, setManualCollapsedIds] = useState<Set<string>>(() => new Set());\n\n const dirtyProviderIds = useMemo(() => {\n const ids = new Set<string>();\n for (const summary of summaries) {\n const draftRow = credDraft[summary.id] ?? emptyImageProviderCredRow();\n const baselineRow = credBaseline[summary.id] ?? emptyImageProviderCredRow();\n if (isProviderRowDirty(draftRow, baselineRow)) {\n ids.add(summary.id);\n }\n }\n return ids;\n }, [summaries, credDraft, credBaseline]);\n\n const isProviderExpanded = (id: string) => {\n if (manualCollapsedIds.has(id)) return false;\n if (manualExpandedIds.has(id)) return true;\n return dirtyProviderIds.has(id);\n };\n\n const toggleProviderExpanded = (id: string) => {\n const expanded = isProviderExpanded(id);\n if (expanded) {\n setManualCollapsedIds((current) => new Set(current).add(id));\n setManualExpandedIds((current) => {\n const next = new Set(current);\n next.delete(id);\n return next;\n });\n return;\n }\n setManualCollapsedIds((current) => {\n const next = new Set(current);\n next.delete(id);\n return next;\n });\n setManualExpandedIds((current) => new Set(current).add(id));\n };\n\n if (summaries.length === 0) {\n return null;\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1 text-xs leading-relaxed text-fg-muted\">\n <p>{t.credentialsIntro}</p>\n {anyRegionUi ? <p className=\"text-fg-subtle\">{t.regionHint}</p> : null}\n {anyBaseUrlPresets ? <p className=\"text-fg-subtle\">{t.endpointPresetsHint}</p> : null}\n {showImageModelsLink ? (\n <p>\n <Link\n to=\"/settings/image-models\"\n className=\"font-medium text-accent hover:underline\"\n title={t.imageModelsLinkTitle}\n >\n {t.openImageModelsPage}\n </Link>\n </p>\n ) : null}\n </div>\n {credError ? (\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-700 dark:text-red-300\">\n {credError}\n </div>\n ) : null}\n {hideActions ? null : (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {credSavedFlash ? (\n <span className=\"text-sm text-fg-muted\">{t.credentialsSaved}</span>\n ) : null}\n {credNoopFlash ? (\n <span className=\"text-sm text-fg-muted\">{t.credentialsNothingToSave}</span>\n ) : null}\n <Button type=\"button\" variant=\"secondary\" onClick={onDiscardCredentials} disabled={!credDirty || credSaving}>\n {t.discardCredentials}\n </Button>\n <Button type=\"button\" variant=\"primary\" onClick={onSaveCredentials} disabled={!credDirty || credSaving}>\n {credSaving ? (\n <>\n <Loader2 className=\"size-3.5 animate-spin\" />\n <span className=\"ml-1.5\">{t.savingCredentials}</span>\n </>\n ) : (\n <>\n <Save className=\"size-3.5\" />\n <span className=\"ml-1.5\">{t.saveCredentials}</span>\n </>\n )}\n </Button>\n </div>\n )}\n <div className=\"flex flex-col gap-4\">\n {summaries.map((p) => {\n const row = credDraft[p.id] ?? emptyImageProviderCredRow();\n const ui = p.ui;\n const extPath =\n showExtensionLinks && extensionIds.has(p.id)\n ? `/settings/ext/${encodeURIComponent(p.id)}`\n : null;\n const baselineRow = credBaseline[p.id] ?? emptyImageProviderCredRow();\n const isDirty = isProviderRowDirty(row, baselineRow);\n const isExpanded = isProviderExpanded(p.id);\n const providerName = p.label ?? p.id;\n const modelCountLabel = formatModelCount(t, p.models.length);\n return (\n <section\n key={p.id}\n className={cn(\n 'overflow-hidden rounded-xl border bg-surface-panel shadow-sm transition-colors dark:shadow-none',\n isDirty ? 'border-accent/50' : 'border-edge',\n )}\n >\n <button\n type=\"button\"\n className=\"flex w-full items-start justify-between gap-3 px-4 py-3 text-left hover:bg-surface-hover/70\"\n aria-expanded={isExpanded}\n aria-controls={`img-provider-credentials-${p.id}`}\n onClick={() => toggleProviderExpanded(p.id)}\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2\">\n <span className=\"truncate text-sm font-semibold text-fg\">{providerName}</span>\n <span className=\"rounded-full bg-surface-subtle px-2 py-0.5 text-[11px] font-medium text-fg-muted\">\n {p.id}\n </span>\n {isDirty ? (\n <span className=\"rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg\">\n {t.unsavedChanges}\n </span>\n ) : null}\n {p.configured ? (\n <span className=\"rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg\">\n {t.configured}\n </span>\n ) : (\n <span className=\"rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-700 dark:text-amber-300\">\n {t.missingKey}\n </span>\n )}\n </div>\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs text-fg-subtle\">\n <span>{modelCountLabel}</span>\n {p.defaultModel ? (\n <span className=\"min-w-0 truncate\">\n <span className=\"text-fg-muted\">{t.defaultModel}:</span> {p.id}/{p.defaultModel}\n </span>\n ) : null}\n </div>\n </div>\n <ChevronDown\n className={cn(\n 'mt-0.5 size-4 shrink-0 text-fg-subtle transition-transform',\n isExpanded ? 'rotate-180' : 'rotate-0',\n )}\n aria-hidden=\"true\"\n />\n <span className=\"sr-only\">{isExpanded ? t.collapseProvider : t.expandProvider}</span>\n </button>\n\n {isExpanded ? (\n <div id={`img-provider-credentials-${p.id}`} className=\"border-t border-edge px-4 py-4\">\n {extPath ? (\n <Link\n to={extPath}\n className=\"mb-3 inline-flex items-center gap-1 text-xs font-medium text-accent hover:underline\"\n title={t.extensionSettingsLinkTitle}\n >\n <ExternalLink className=\"size-3\" />\n {t.openExtensionSettings}\n </Link>\n ) : null}\n {p.models.length > 0 ? (\n <p className=\"mb-3 text-xs leading-relaxed text-fg-subtle\">\n <span className=\"text-fg-muted\">{t.modelsLabel}:</span>{' '}\n {p.models.map((modelId) => `${p.id}/${modelId}`).join(', ')}\n </p>\n ) : null}\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <ImageProviderApiKeyField\n providerId={p.id}\n value={row.apiKey}\n onChange={(next) => updateCredRow(p.id, { apiKey: next })}\n apiKeyLinks={getOrderedApiKeyLinks(p.id, language)}\n apiKeyLinkLabels={apiKeyLinkLabels}\n labels={{\n apiKeyLabel: t.apiKeyLabel,\n optionalPlaceholder: t.optionalPlaceholder,\n maskedHelp: t.apiKeyMaskedHelp,\n copy: t.apiKeyCopy,\n copied: t.apiKeyCopied,\n show: t.apiKeyShow,\n hide: t.apiKeyHide,\n notInConfigFile: t.apiKeyNotInConfigFile,\n loadFailed: t.apiKeyRevealFailed,\n }}\n />\n\n {ui?.regions?.length ? (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-region-preset-${p.id}`}>\n {t.regionLabel}\n </label>\n <select\n id={`img-cred-region-preset-${p.id}`}\n className={selectClass()}\n value={dashscopeSelectValue(row, ui.regions)}\n onChange={(e) => {\n const v = e.target.value;\n if (v === '') {\n updateCredRow(p.id, { region: '', imageBaseUrl: '' });\n return;\n }\n if (v === CUSTOM_SENTINEL) {\n updateCredRow(p.id, { region: '', imageBaseUrl: '' });\n return;\n }\n const opt = ui.regions!.find((x) => x.value === v);\n if (opt) {\n updateCredRow(p.id, { region: opt.value, imageBaseUrl: opt.imageBaseUrl });\n }\n }}\n >\n <option value=\"\">{t.regionPresetDefault}</option>\n {ui.regions.map((r) => (\n <option key={r.value} value={r.value}>\n {translateDashscopeRegion(t, r.value, r.label)}\n </option>\n ))}\n <option value={CUSTOM_SENTINEL}>{t.regionPresetCustom}</option>\n </select>\n {dashscopeSelectValue(row, ui.regions) === CUSTOM_SENTINEL ? (\n <div className=\"mt-2 grid gap-2 sm:grid-cols-2\">\n <input\n type=\"text\"\n className={inputClass()}\n value={row.region}\n placeholder=\"region\"\n onChange={(e) => updateCredRow(p.id, { region: e.target.value })}\n />\n <input\n type=\"url\"\n className={inputClass()}\n value={row.imageBaseUrl}\n placeholder={t.imageBaseUrlLabel}\n onChange={(e) => updateCredRow(p.id, { imageBaseUrl: e.target.value })}\n />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {ui?.baseUrlPresets?.length ? (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-base-preset-${p.id}`}>\n {baseUrlPresetBlockTitle(t, ui.baseUrlPresetKind)}\n </label>\n {baseUrlPresetBlockHint(t, ui.baseUrlPresetKind) ? (\n <p className=\"text-[11px] text-fg-subtle\">{baseUrlPresetBlockHint(t, ui.baseUrlPresetKind)}</p>\n ) : null}\n <select\n id={`img-cred-base-preset-${p.id}`}\n className={selectClass()}\n value={baseUrlSelectValue(row, ui.baseUrlPresets)}\n onChange={(e) => {\n const v = e.target.value;\n if (v === '') {\n updateCredRow(p.id, { baseUrl: '' });\n return;\n }\n if (v === CUSTOM_SENTINEL) {\n updateCredRow(p.id, { baseUrl: '' });\n return;\n }\n updateCredRow(p.id, { baseUrl: v.replace(/\\/+$/, '') });\n }}\n >\n <option value=\"\">{t.baseUrlPresetDefault}</option>\n {ui.baseUrlPresets.map((b) => (\n <option key={b.value} value={b.value}>\n {b.label}\n </option>\n ))}\n <option value={CUSTOM_SENTINEL}>{t.baseUrlPresetCustom}</option>\n </select>\n {baseUrlSelectValue(row, ui.baseUrlPresets) === CUSTOM_SENTINEL ? (\n <input\n type=\"url\"\n className={cn(inputClass(), 'mt-2')}\n value={row.baseUrl}\n placeholder=\"https://…\"\n onChange={(e) => updateCredRow(p.id, { baseUrl: e.target.value })}\n />\n ) : null}\n </div>\n ) : null}\n\n {ui?.regions?.length && dashscopeSelectValue(row, ui.regions) !== CUSTOM_SENTINEL ? (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-imgbase-ro-${p.id}`}>\n {t.imageBaseUrlLabel}\n </label>\n <input\n id={`img-cred-imgbase-ro-${p.id}`}\n type=\"url\"\n readOnly\n className={cn(inputClass(), 'cursor-not-allowed opacity-90')}\n value={row.imageBaseUrl}\n title={t.imageBaseUrlPresetHint}\n />\n <p className=\"text-[11px] text-fg-subtle\">{t.imageBaseUrlPresetHint}</p>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </section>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useCallback, useMemo, useRef, useState } from 'react';\nimport { mutate } from 'swr';\n\nimport { useGatewayConfigSwr } from '@/features/gateway/gateway-config-swr';\nimport {\n buildImageProvidersConfigPatch,\n emptyImageProviderCredRow,\n imageProviderCredRowsFromConfigRoot,\n patchImageProvidersConfig,\n type ImageProviderCredRow,\n} from '@/features/settings/image-providers-config-api';\nimport { IMAGE_PROVIDERS_SWR_KEY } from '@/features/settings/image-providers-swr-key';\nimport { apiUrl } from '@/lib/url';\nimport { useGatewayStore } from '@/stores/gateway-store';\n\nexport type ImageProviderUiRegionOption = {\n value: string;\n label: string;\n imageBaseUrl: string;\n};\n\nexport type ImageProviderUiBaseUrlPreset = {\n value: string;\n label: string;\n};\n\nexport type ImageProviderUiMetadata = {\n regions?: ImageProviderUiRegionOption[];\n baseUrlPresets?: ImageProviderUiBaseUrlPreset[];\n baseUrlPresetKind?: 'fal' | 'minimax' | 'google' | 'openai';\n};\n\nexport type ImageGenProviderCredentialSummary = {\n id: string;\n label?: string;\n defaultModel?: string;\n models: string[];\n configured?: boolean;\n ui?: ImageProviderUiMetadata;\n};\n\nexport function useImageProviderCredentials(summaries: ImageGenProviderCredentialSummary[]) {\n const hasToken = useGatewayStore((s) => Boolean(s.token));\n const gwSwr = useGatewayConfigSwr(hasToken);\n const gwCfg = gwSwr.data;\n\n const ids = useMemo(() => summaries.map((s) => s.id), [summaries]);\n\n const dirtyRef = useRef(false);\n const [localDraft, setLocalDraft] = useState<Record<string, ImageProviderCredRow> | null>(null);\n const [credSaving, setCredSaving] = useState(false);\n const [credError, setCredError] = useState<string | null>(null);\n const [credSavedFlash, setCredSavedFlash] = useState(false);\n const [credNoopFlash, setCredNoopFlash] = useState(false);\n\n const credRowsFromServer = useMemo(\n () => imageProviderCredRowsFromConfigRoot(gwCfg?.payload?.config, ids),\n [gwCfg?.payload?.config, ids],\n );\n\n const credDraft = localDraft ?? credRowsFromServer;\n const credBaseline = credRowsFromServer;\n\n const credDirty = useMemo(\n () => JSON.stringify(credDraft) !== JSON.stringify(credBaseline),\n [credDraft, credBaseline],\n );\n\n const updateCredRow = useCallback((id: string, patch: Partial<ImageProviderCredRow>) => {\n dirtyRef.current = true;\n setLocalDraft((prev) => {\n const base = prev ?? credRowsFromServer;\n const row = base[id] ?? emptyImageProviderCredRow();\n return { ...base, [id]: { ...row, ...patch } };\n });\n }, [credRowsFromServer]);\n\n const onDiscardCredentials = useCallback(() => {\n dirtyRef.current = false;\n setLocalDraft(null);\n setCredError(null);\n setCredSavedFlash(false);\n setCredNoopFlash(false);\n }, []);\n\n const saveCredentials = useCallback(\n async (errorFallback: string) => {\n const patch = buildImageProvidersConfigPatch(ids, credDraft, credBaseline);\n if (Object.keys(patch).length === 0) {\n setCredNoopFlash(true);\n window.setTimeout(() => setCredNoopFlash(false), 2200);\n return;\n }\n setCredSaving(true);\n setCredError(null);\n setCredSavedFlash(false);\n try {\n await patchImageProvidersConfig(patch);\n const updated = await gwSwr.mutate?.();\n void mutate(apiUrl(IMAGE_PROVIDERS_SWR_KEY));\n void updated;\n dirtyRef.current = false;\n setLocalDraft(null);\n setCredSavedFlash(true);\n window.setTimeout(() => setCredSavedFlash(false), 2000);\n } catch (e) {\n setCredError(e instanceof Error ? e.message : errorFallback);\n } finally {\n setCredSaving(false);\n }\n },\n [ids, credDraft, credBaseline, gwSwr],\n );\n\n return {\n gwSwr,\n credDraft,\n credBaseline,\n credDirty,\n credSaving,\n credError,\n credSavedFlash,\n credNoopFlash,\n updateCredRow,\n onDiscardCredentials,\n saveCredentials,\n };\n}\n","import { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport type { SttSettings, SttProvidersPayload, TtsSettings, VoiceModelsPayload, VoiceSettingsState, VoiceProvidersPayload } from './voice-settings.types';\n\nexport type { SttSettings, TtsSettings, VoiceModelsPayload, VoiceSettingsState, VoiceProvidersPayload, SttProvidersPayload, TtsProviderListEntry, SttProviderListEntry } from './voice-settings.types';\n\nfunction defaultStt(): SttSettings {\n return {\n enabled: false,\n provider: 'alibaba',\n alibaba: { model: 'paraformer-v2' },\n openai: { model: 'whisper-1' },\n fallback: { enabled: true, order: ['alibaba', 'openai'] },\n };\n}\n\n// Defaults intentionally mirror src/config/schema.ts (TTSConfigSchema /\n// TTSEdgeConfigSchema) and extensions/tts-local-cli/xopc.extension.json so a\n// PATCH /api/config round-trip never silently overrides backend defaults.\nfunction defaultTts(): TtsSettings {\n return {\n enabled: false,\n provider: 'openai',\n trigger: 'always',\n maxTextLength: 512,\n timeoutMs: 60000,\n alibaba: { model: 'qwen-tts', voice: 'Cherry' },\n openai: { model: 'tts-1', voice: 'alloy' },\n edge: { voice: 'en-US-MichelleNeural' },\n minimax: { model: 'speech-2.8-hd', voice: 'male-qn-qingse' },\n 'tts-local-cli': {\n command: '',\n outputFormat: 'wav',\n },\n };\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction normalizeSttProvider(v: unknown): string {\n return typeof v === 'string' && v.trim().length > 0 ? v.trim() : 'alibaba';\n}\n\nfunction mergeStt(raw: unknown): SttSettings {\n const d = defaultStt();\n if (!isRecord(raw)) return d;\n const provider = normalizeSttProvider(raw.provider);\n const alibaba = isRecord(raw.alibaba) ? { ...d.alibaba, ...raw.alibaba } : d.alibaba;\n const openai = isRecord(raw.openai) ? { ...d.openai, ...raw.openai } : d.openai;\n const baseFallback = d.fallback ?? { enabled: true, order: ['alibaba', 'openai'] };\n let fallback = baseFallback;\n if (isRecord(raw.fallback)) {\n const order = Array.isArray(raw.fallback.order)\n ? raw.fallback.order.filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n : fallback.order;\n fallback = {\n enabled: typeof raw.fallback.enabled === 'boolean' ? raw.fallback.enabled : fallback.enabled,\n order: order.length ? order : fallback.order,\n };\n }\n\n const providers = isRecord(raw.providers)\n ? Object.fromEntries(\n Object.entries(raw.providers).map(([key, value]) => [\n key,\n isRecord(value) ? { ...value } : {},\n ]),\n )\n : undefined;\n\n return {\n enabled: Boolean(raw.enabled),\n provider,\n alibaba,\n openai,\n ...(providers ? { providers } : {}),\n fallback,\n };\n}\n\n/** Provider id is open string — extension SpeechProviderPlugins (e.g. tts-local-cli) are allowed. */\nfunction normalizeTtsProvider(v: unknown): string {\n return typeof v === 'string' && v.trim().length > 0 ? v.trim() : 'openai';\n}\n\nfunction mergeTts(raw: unknown): TtsSettings {\n const d = defaultTts();\n if (!isRecord(raw)) return d;\n const provider = normalizeTtsProvider(raw.provider);\n const trigger =\n raw.trigger === 'off' ||\n raw.trigger === 'always' ||\n raw.trigger === 'inbound' ||\n raw.trigger === 'tagged'\n ? raw.trigger\n : 'always';\n // Per-provider buckets: keep built-in defaults, plus passthrough for any\n // extension-provider key (e.g. `tts-local-cli`) so unknown plugins survive\n // a round-trip through the UI without losing their config.\n const localCliRaw = raw['tts-local-cli'];\n return {\n enabled: Boolean(raw.enabled),\n provider,\n trigger,\n maxTextLength:\n typeof raw.maxTextLength === 'number' && Number.isFinite(raw.maxTextLength)\n ? raw.maxTextLength\n : d.maxTextLength,\n timeoutMs:\n typeof raw.timeoutMs === 'number' && Number.isFinite(raw.timeoutMs) ? raw.timeoutMs : d.timeoutMs,\n alibaba: isRecord(raw.alibaba) ? { ...d.alibaba, ...raw.alibaba } : d.alibaba,\n openai: isRecord(raw.openai) ? { ...d.openai, ...raw.openai } : d.openai,\n edge: isRecord(raw.edge) ? { ...d.edge, ...raw.edge } : d.edge,\n minimax: isRecord(raw.minimax) ? { ...d.minimax, ...raw.minimax } : d.minimax,\n 'tts-local-cli': isRecord(localCliRaw)\n ? { ...d['tts-local-cli'], ...localCliRaw }\n : d['tts-local-cli'],\n };\n}\n\nexport function normalizeVoiceSettings(config: unknown): VoiceSettingsState {\n const c = isRecord(config) ? config : {};\n return {\n stt: mergeStt(c.stt),\n tts: mergeTts(c.tts),\n };\n}\n\nexport async function fetchVoiceSettings(): Promise<VoiceSettingsState> {\n const res = await fetchJson<{ ok?: boolean; payload?: { config?: unknown } }>(apiUrl('/api/config'));\n return normalizeVoiceSettings(res.payload?.config ?? {});\n}\n\nexport async function patchVoiceSettings(state: VoiceSettingsState): Promise<void> {\n await fetchJson(apiUrl('/api/config'), {\n method: 'PATCH',\n body: JSON.stringify({ stt: state.stt, tts: state.tts }),\n });\n void revalidateGatewayConfig();\n}\n\nexport async function fetchVoiceModels(): Promise<VoiceModelsPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: { models?: VoiceModelsPayload } }>(\n apiUrl('/api/voice/models'),\n );\n if (!res.payload?.models) {\n throw new Error('Missing voice models payload');\n }\n return res.payload.models;\n}\n\nexport async function fetchVoiceProviders(): Promise<VoiceProvidersPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: VoiceProvidersPayload }>(\n apiUrl('/api/voice/providers'),\n );\n if (!res.payload?.providers) {\n throw new Error('Missing voice providers payload');\n }\n return res.payload;\n}\n\nexport async function fetchVoiceSttProviders(): Promise<SttProvidersPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: SttProvidersPayload }>(\n apiUrl('/api/voice/stt-providers'),\n );\n if (!res.payload?.providers) {\n throw new Error('Missing STT providers payload');\n }\n return res.payload;\n}\n\nexport type RevealVoiceApiKeyPayload = {\n kind: 'stt' | 'tts';\n provider: string;\n apiKey: string | null;\n source: 'config' | 'none';\n};\n\n/** POST /api/voice/reveal-api-key — plaintext only when stored in config file. */\nexport async function revealVoiceConfigApiKey(args: {\n kind: 'stt' | 'tts';\n provider: string;\n}): Promise<RevealVoiceApiKeyPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: RevealVoiceApiKeyPayload }>(\n apiUrl('/api/voice/reveal-api-key'),\n {\n method: 'POST',\n body: JSON.stringify(args),\n },\n );\n if (!res.payload) {\n throw new Error('Missing reveal payload');\n }\n return res.payload;\n}\n","import { Check, Copy, Eye, EyeOff, Loader2 } from 'lucide-react';\nimport { useCallback } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { revealVoiceConfigApiKey } from '@/features/settings/voice-config-api';\nimport { settingsInputFocusClass } from '@/lib/form-field-width';\nimport { cn } from '@/lib/cn';\nimport { useMaskedApiKeyField } from '@/lib/use-masked-api-key-field';\n\nexport type VoiceApiKeyFieldLabels = {\n maskedHelp: string;\n copy: string;\n copied: string;\n show: string;\n hide: string;\n notInConfigFile: string;\n loadFailed: string;\n};\n\nexport function VoiceApiKeyField({\n kind,\n providerId,\n fieldId,\n value,\n onChange,\n labels,\n placeholder = 'sk-...',\n className,\n}: {\n kind: 'stt' | 'tts';\n providerId: string;\n fieldId: string;\n value: string;\n onChange: (next: string) => void;\n labels: VoiceApiKeyFieldLabels;\n placeholder?: string;\n className?: string;\n}) {\n const reveal = useCallback(\n () =>\n revealVoiceConfigApiKey({ kind, provider: providerId }).then((payload) => payload.apiKey ?? null),\n [kind, providerId],\n );\n\n const {\n masked,\n showKey,\n revealed,\n revealLoading,\n revealErr,\n copied,\n inputValue,\n inputType,\n copyEnabled,\n copyKey,\n toggleEye,\n onInputChange,\n } = useMaskedApiKeyField({ value, reveal, loadFailedLabel: labels.loadFailed });\n\n return (\n <div className={cn('flex min-w-0 flex-col gap-1.5', className)}>\n {masked ? <p className=\"text-xs text-fg-subtle\">{labels.maskedHelp}</p> : null}\n <div className=\"flex flex-wrap gap-2\">\n <input\n id={fieldId}\n type={inputType}\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(\n 'w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n 'dark:border-edge',\n 'min-w-0 flex-1 font-mono text-xs',\n )}\n value={inputValue}\n placeholder={masked ? '••••••••' : placeholder}\n onChange={(e) => onInputChange(e.target.value, onChange)}\n />\n {copyEnabled ? (\n <Button type=\"button\" variant=\"secondary\" className=\"px-2 py-1 text-xs\" onClick={() => void copyKey()}>\n {copied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {copied ? labels.copied : labels.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n disabled={revealLoading}\n onClick={() => void toggleEye()}\n >\n {revealLoading ? (\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n ) : showKey ? (\n <EyeOff className=\"size-3.5\" />\n ) : (\n <Eye className=\"size-3.5\" />\n )}\n {showKey ? labels.hide : labels.show}\n </Button>\n </div>\n {masked && showKey && revealed === null && !revealErr ? (\n <p className=\"text-xs text-amber-700 dark:text-amber-400/90\">{labels.notInConfigFile}</p>\n ) : null}\n {revealErr ? <p className=\"text-xs text-red-600 dark:text-red-400\">{revealErr}</p> : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"voice-api-key-field-5WZZaxH3.js","names":["IMAGE_PROVIDERS_SWR_KEY","fetchJson","apiUrl","IMAGE_PROVIDERS_SWR_KEY","ImageGenProviderCredentialSummary","fetchImageProvidersList","Promise","res","ok","payload","providers","isMaskedKey","revalidateGatewayConfig","fetchJson","apiUrl","ImageProviderCredRow","apiKey","region","baseUrl","imageBaseUrl","emptyImageProviderCredRow","SafeProviderAuthEntry","maskedApiKeyDisplay","safe","imageProviderCredRowsFromConfigRoot","config","imageProviderIds","Record","pc","undefined","v","providersConfig","Array","isArray","out","id","optionalStringField","draft","baseline","key","Pick","d","trim","b","apiKeyPatchValue","draftKey","baselineKey","buildImageProvidersConfigPatch","patch","JSON","stringify","entry","keyDelta","Object","keys","length","RevealImageProviderApiKeyPayload","source","revealImageProviderConfigApiKey","providerId","Promise","data","ok","payload","error","message","encodeURIComponent","method","headers","body","Error","patchImageProvidersConfig","useCallback","useReducer","useRef","isMaskedKey","copyTextToClipboard","MaskedApiKeyUiState","showKey","revealed","revealLoading","revealErr","copied","MaskedApiKeyUiAction","type","value","message","initialMaskedApiKeyUi","undefined","maskedApiKeyUiReducer","state","action","useMaskedApiKeyField","options","reveal","Promise","loadFailedLabel","ui","dispatch","masked","revealRef","current","trackedMaskedRef","inputValue","inputType","const","copyEnabled","trim","length","Boolean","copyKey","text","ok","window","setTimeout","toggleEye","plaintext","e","Error","onInputChange","next","onChange","CheckCircle2","Copy","ExternalLink","Eye","EyeOff","Loader2","useCallback","revealImageProviderConfigApiKey","ApiKeyLinkKind","providerApiKeyLinkLabel","ProvidersSettingsMessages","settingsInputFocusClass","interaction","cn","useMaskedApiKeyField","ImageProviderApiKeyFieldLabels","apiKeyLabel","optionalPlaceholder","maskedHelp","copy","copied","show","hide","notInConfigFile","loadFailed","ImageProviderApiKeyField","t0","$","_c","providerId","value","onChange","labels","apiKeyLinks","apiKeyLinkLabels","t1","then","_temp","reveal","t2","loadFailedLabel","masked","showKey","revealed","revealLoading","revealErr","inputValue","inputType","copyEnabled","copyKey","toggleEye","onInputChange","t3","t4","t5","length","map","link","kind","href","t6","t7","t8","Symbol","for","t9","t10","e","target","t11","t12","transition","press","focusRingPanel","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","payload","apiKey","ChevronDown","ExternalLink","Loader2","Save","useMemo","useState","Link","Button","ImageProviderApiKeyField","emptyImageProviderCredRow","ImageProviderCredRow","getOrderedApiKeyLinks","ImageGenProviderCredentialSummary","ImageProviderUiMetadata","ProvidersSettingsMessages","settingsInputFocusClass","StoredLanguage","cn","inputClass","selectClass","CUSTOM_SENTINEL","dashscopeSelectValue","row","regions","NonNullable","region","trim","imageBaseUrl","r","toLowerCase","some","x","value","baseUrlSelectValue","presets","b","baseUrl","replace","norm","map","p","idx","indexOf","ImageProviderCredentialsPanelMessages","credentialsIntro","regionHint","endpointPresetsHint","apiKeyLabel","optionalPlaceholder","regionLabel","baseUrlLabel","imageBaseUrlLabel","saveCredentials","savingCredentials","credentialsSaved","discardCredentials","credentialsNothingToSave","credentialsSaveError","regionPresetDefault","regionPresetCustom","baseUrlPresetDefault","baseUrlPresetCustom","openExtensionSettings","openImageModelsPage","extensionSettingsLinkTitle","imageModelsLinkTitle","configured","missingKey","unsavedChanges","expandProvider","collapseProvider","defaultModel","modelsLabel","modelCountOne","modelCountMany","imageBaseUrlPresetHint","dashscopeRegion_beijing","dashscopeRegion_singapore","dashscopeRegion_us","apiKeyMaskedHelp","apiKeyCopy","apiKeyCopied","apiKeyShow","apiKeyHide","apiKeyNotInConfigFile","apiKeyRevealFailed","minimaxClusterLabel","minimaxClusterHint","falQueueBaseLabel","falQueueBaseHint","translateDashscopeRegion","m","serverLabel","baseUrlPresetBlockTitle","t","kind","baseUrlPresetBlockHint","isProviderRowDirty","draft","baseline","JSON","stringify","formatModelCount","count","String","ImageProviderCredentialsPanel","t0","$","_c","summaries","credDraft","credBaseline","credDirty","credSaving","credError","credSavedFlash","credNoopFlash","updateCredRow","onDiscardCredentials","onSaveCredentials","extensionIds","showExtensionLinks","showImageModelsLink","hideActions","t1","language","apiKeyLinkLabels","messages","undefined","t2","_temp","anyRegionUi","t3","_temp2","anyBaseUrlPresets","manualExpandedIds","setManualExpandedIds","_temp3","manualCollapsedIds","setManualCollapsedIds","_temp4","ids","Set","summary","draftRow","id","baselineRow","add","dirtyProviderIds","t4","has","isProviderExpanded","t5","id_0","expanded","current","current_0","next","delete","current_1","next_0","current_2","toggleProviderExpanded","length","t6","t7","t8","t9","t10","t11","t12","t13","t14","ui","extPath","encodeURIComponent","baselineRow_0","isDirty","isExpanded","providerName","label","modelCountLabel","models","modelId","join","apiKey","next_1","maskedHelp","copy","copied","show","hide","notInConfigFile","loadFailed","e","v","target","opt","find","e_0","e_1","baseUrlPresets","baseUrlPresetKind","e_2","v_0","_temp5","e_3","t15","s_0","s","useCallback","useMemo","useRef","useState","mutate","useGatewayConfigSwr","buildImageProvidersConfigPatch","emptyImageProviderCredRow","imageProviderCredRowsFromConfigRoot","patchImageProvidersConfig","ImageProviderCredRow","IMAGE_PROVIDERS_SWR_KEY","apiUrl","useGatewayStore","ImageProviderUiRegionOption","value","label","imageBaseUrl","ImageProviderUiBaseUrlPreset","ImageProviderUiMetadata","regions","baseUrlPresets","baseUrlPresetKind","ImageGenProviderCredentialSummary","id","defaultModel","models","configured","ui","useImageProviderCredentials","summaries","hasToken","s","Boolean","token","gwSwr","gwCfg","data","ids","map","dirtyRef","localDraft","setLocalDraft","Record","credSaving","setCredSaving","credError","setCredError","credSavedFlash","setCredSavedFlash","credNoopFlash","setCredNoopFlash","credRowsFromServer","payload","config","credDraft","credBaseline","credDirty","JSON","stringify","updateCredRow","patch","Partial","current","prev","base","row","onDiscardCredentials","saveCredentials","errorFallback","Object","keys","length","window","setTimeout","updated","e","Error","message","revalidateGatewayConfig","fetchJson","apiUrl","SttSettings","SttProvidersPayload","TtsSettings","VoiceModelsPayload","VoiceSettingsState","VoiceProvidersPayload","TtsProviderListEntry","SttProviderListEntry","defaultStt","enabled","provider","alibaba","model","openai","fallback","order","defaultTts","trigger","maxTextLength","timeoutMs","voice","edge","minimax","command","outputFormat","isRecord","v","Record","Array","isArray","normalizeSttProvider","trim","length","mergeStt","raw","d","baseFallback","filter","x","providers","Object","fromEntries","entries","map","key","value","undefined","Boolean","normalizeTtsProvider","mergeTts","localCliRaw","Number","isFinite","normalizeVoiceSettings","config","c","stt","tts","fetchVoiceSettings","Promise","res","ok","payload","patchVoiceSettings","state","method","body","JSON","stringify","fetchVoiceModels","models","Error","fetchVoiceProviders","fetchVoiceSttProviders","RevealVoiceApiKeyPayload","kind","apiKey","source","revealVoiceConfigApiKey","args","Check","Copy","Eye","EyeOff","Loader2","useCallback","Button","revealVoiceConfigApiKey","settingsInputFocusClass","cn","useMaskedApiKeyField","VoiceApiKeyFieldLabels","maskedHelp","copy","copied","show","hide","notInConfigFile","loadFailed","VoiceApiKeyField","t0","$","_c","kind","providerId","fieldId","value","onChange","labels","placeholder","t1","className","undefined","t2","provider","then","_temp","reveal","t3","loadFailedLabel","masked","showKey","revealed","revealLoading","revealErr","inputValue","inputType","copyEnabled","copyKey","toggleEye","onInputChange","t4","t5","t6","Symbol","for","t7","t8","e","target","t9","t10","t11","t12","t13","t14","t15","t16","t17","t18","payload","apiKey"],"sources":["../../../../../web/src/features/settings/image-providers-swr-key.ts","../../../../../web/src/features/settings/fetch-image-providers.ts","../../../../../web/src/features/settings/image-providers-config-api.ts","../../../../../web/src/lib/use-masked-api-key-field.ts","../../../../../web/src/features/settings/image-provider-api-key-field.tsx","../../../../../web/src/features/settings/image-provider-credentials-panel.tsx","../../../../../web/src/features/settings/use-image-provider-credentials.ts","../../../../../web/src/features/settings/voice-config-api.ts","../../../../../web/src/features/settings/voice-api-key-field.tsx"],"sourcesContent":["/** Shared SWR key for GET `/api/image/providers` (image settings + extension image pages). */\nexport const IMAGE_PROVIDERS_SWR_KEY = '/api/image/providers';\n","import { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport { IMAGE_PROVIDERS_SWR_KEY } from '@/features/settings/image-providers-swr-key';\nimport type { ImageGenProviderCredentialSummary } from '@/features/settings/use-image-provider-credentials';\n\nexport async function fetchImageProvidersList(): Promise<ImageGenProviderCredentialSummary[]> {\n const res = await fetchJson<{\n ok?: boolean;\n payload?: { providers?: ImageGenProviderCredentialSummary[] };\n }>(apiUrl(IMAGE_PROVIDERS_SWR_KEY));\n return res?.payload?.providers ?? [];\n}\n","import { isMaskedKey } from '@/features/settings/providers-api';\nimport { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\n/** One row of image-provider credential fields (matches PATCH `providersConfig` subset). */\nexport type ImageProviderCredRow = {\n apiKey: string;\n region: string;\n baseUrl: string;\n imageBaseUrl: string;\n};\n\nexport function emptyImageProviderCredRow(): ImageProviderCredRow {\n return { apiKey: '', region: '', baseUrl: '', imageBaseUrl: '' };\n}\n\nexport type SafeProviderAuthEntry = {\n apiKey: string;\n region?: string;\n baseUrl?: string;\n imageBaseUrl?: string;\n};\n\nfunction maskedApiKeyDisplay(safe?: SafeProviderAuthEntry): string {\n if (!safe?.apiKey) return '';\n return '••••••••••••';\n}\n\n/** Read `payload.config.providersConfig` from GET /api/config (masked). */\nexport function imageProviderCredRowsFromConfigRoot(\n config: unknown,\n imageProviderIds: string[],\n): Record<string, ImageProviderCredRow> {\n const pc = (() => {\n if (!config || typeof config !== 'object' || !('providersConfig' in config)) return undefined;\n const v = (config as { providersConfig?: unknown }).providersConfig;\n if (!v || typeof v !== 'object' || Array.isArray(v)) return undefined;\n return v as Record<string, SafeProviderAuthEntry>;\n })();\n\n const out: Record<string, ImageProviderCredRow> = {};\n for (const id of imageProviderIds) {\n const safe = pc?.[id];\n out[id] = {\n apiKey: maskedApiKeyDisplay(safe),\n region: safe?.region ?? '',\n baseUrl: safe?.baseUrl ?? '',\n imageBaseUrl: safe?.imageBaseUrl ?? '',\n };\n }\n return out;\n}\n\nfunction optionalStringField(\n draft: ImageProviderCredRow,\n baseline: ImageProviderCredRow,\n key: keyof Pick<ImageProviderCredRow, 'region' | 'baseUrl' | 'imageBaseUrl'>,\n): string | null | undefined {\n const d = draft[key].trim();\n const b = baseline[key].trim();\n if (d === b) return undefined;\n if (!d) return null;\n return d;\n}\n\nfunction apiKeyPatchValue(draftKey: string, baselineKey: string): string | null | undefined {\n const d = draftKey.trim();\n const b = baselineKey.trim();\n if (d === b) return undefined;\n if (isMaskedKey(d) && isMaskedKey(b)) return undefined;\n if (!d) {\n if (!b) return undefined;\n return null;\n }\n return d;\n}\n\n/**\n * Build `providersConfig` PATCH entries only for image providers whose row changed.\n * Omits `apiKey` when unchanged (still masked); sends `null` to clear stored key.\n */\nexport function buildImageProvidersConfigPatch(\n imageProviderIds: string[],\n draft: Record<string, ImageProviderCredRow>,\n baseline: Record<string, ImageProviderCredRow>,\n): Record<string, Record<string, unknown>> {\n const patch: Record<string, Record<string, unknown>> = {};\n for (const id of imageProviderIds) {\n const d = draft[id] ?? emptyImageProviderCredRow();\n const b = baseline[id] ?? emptyImageProviderCredRow();\n if (JSON.stringify(d) === JSON.stringify(b)) continue;\n\n const entry: Record<string, unknown> = {};\n const keyDelta = apiKeyPatchValue(d.apiKey, b.apiKey);\n if (keyDelta !== undefined) {\n entry.apiKey = keyDelta;\n }\n const region = optionalStringField(d, b, 'region');\n if (region !== undefined) entry.region = region;\n const baseUrl = optionalStringField(d, b, 'baseUrl');\n if (baseUrl !== undefined) entry.baseUrl = baseUrl;\n const imageBaseUrl = optionalStringField(d, b, 'imageBaseUrl');\n if (imageBaseUrl !== undefined) entry.imageBaseUrl = imageBaseUrl;\n\n if (Object.keys(entry).length > 0) {\n patch[id] = entry;\n }\n }\n return patch;\n}\n\nexport type RevealImageProviderApiKeyPayload = {\n id: string;\n apiKey: string | null;\n source: 'config' | 'none';\n};\n\n/** POST /api/image/providers/:id/reveal-api-key — plaintext only when stored in config file. */\nexport async function revealImageProviderConfigApiKey(providerId: string): Promise<RevealImageProviderApiKeyPayload> {\n const data = await fetchJson<{\n ok?: boolean;\n payload?: RevealImageProviderApiKeyPayload;\n error?: { message?: string };\n }>(apiUrl(`/api/image/providers/${encodeURIComponent(providerId)}/reveal-api-key`), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: '{}',\n });\n if (!data.ok || !data.payload) {\n throw new Error(data.error?.message ?? 'Reveal failed');\n }\n return data.payload;\n}\n\nexport async function patchImageProvidersConfig(\n patch: Record<string, Record<string, unknown>>,\n): Promise<void> {\n if (Object.keys(patch).length === 0) return;\n await fetchJson(apiUrl('/api/config'), {\n method: 'PATCH',\n body: JSON.stringify({ providersConfig: patch }),\n });\n await revalidateGatewayConfig();\n}\n","import { useCallback, useReducer, useRef } from 'react';\n\nimport { isMaskedKey } from '@/features/settings/providers-api';\nimport { copyTextToClipboard } from '@/lib/copy-to-clipboard';\n\ntype MaskedApiKeyUiState = {\n showKey: boolean;\n /** `undefined` = not fetched; `null` = fetched, not in config file; string = plaintext from config */\n revealed: string | null | undefined;\n revealLoading: boolean;\n revealErr: string | null;\n copied: boolean;\n};\n\ntype MaskedApiKeyUiAction =\n | { type: 'reset-reveal' }\n | { type: 'toggle-show' }\n | { type: 'reveal-start' }\n | { type: 'reveal-success'; value: string | null }\n | { type: 'reveal-error'; message: string }\n | { type: 'copied' }\n | { type: 'clear-copied' }\n | { type: 'invalidate-reveal' };\n\nconst initialMaskedApiKeyUi: MaskedApiKeyUiState = {\n showKey: false,\n revealed: undefined,\n revealLoading: false,\n revealErr: null,\n copied: false,\n};\n\nfunction maskedApiKeyUiReducer(\n state: MaskedApiKeyUiState,\n action: MaskedApiKeyUiAction,\n): MaskedApiKeyUiState {\n switch (action.type) {\n case 'reset-reveal':\n return { ...state, showKey: false, revealed: undefined, revealErr: null };\n case 'toggle-show':\n return { ...state, showKey: !state.showKey };\n case 'reveal-start':\n return { ...state, revealLoading: true, revealErr: null };\n case 'reveal-success':\n return {\n ...state,\n revealed: action.value,\n revealLoading: false,\n showKey: true,\n revealErr: null,\n };\n case 'reveal-error':\n return {\n ...state,\n revealed: null,\n revealLoading: false,\n revealErr: action.message,\n };\n case 'copied':\n return { ...state, copied: true };\n case 'clear-copied':\n return { ...state, copied: false };\n case 'invalidate-reveal':\n return { ...state, revealed: undefined, showKey: false };\n }\n}\n\nexport function useMaskedApiKeyField(options: {\n value: string;\n reveal: () => Promise<string | null>;\n loadFailedLabel: string;\n}) {\n const { value, reveal, loadFailedLabel } = options;\n const [ui, dispatch] = useReducer(maskedApiKeyUiReducer, initialMaskedApiKeyUi);\n\n const masked = isMaskedKey(value);\n const revealRef = useRef(reveal);\n revealRef.current = reveal;\n\n const trackedMaskedRef = useRef({ masked, value });\n if (\n !masked &&\n (trackedMaskedRef.current.masked || trackedMaskedRef.current.value !== value)\n ) {\n dispatch({ type: 'reset-reveal' });\n }\n trackedMaskedRef.current = { masked, value };\n\n const inputValue = (() => {\n if (!masked) return value;\n if (ui.showKey && typeof ui.revealed === 'string') return ui.revealed;\n return value;\n })();\n\n const inputType =\n !masked || (masked && ui.showKey && typeof ui.revealed === 'string')\n ? ('text' as const)\n : ('password' as const);\n\n const copyEnabled =\n (!masked && value.trim().length > 0 && !isMaskedKey(value)) ||\n (Boolean(ui.showKey) && typeof ui.revealed === 'string' && ui.revealed.length > 0);\n\n const copyKey = useCallback(async () => {\n const text =\n !masked && value.trim() && !isMaskedKey(value)\n ? value.trim()\n : typeof ui.revealed === 'string' && ui.revealed.length > 0\n ? ui.revealed\n : '';\n if (!text) return;\n const ok = await copyTextToClipboard(text);\n if (!ok) return;\n dispatch({ type: 'copied' });\n window.setTimeout(() => dispatch({ type: 'clear-copied' }), 2000);\n }, [masked, ui.revealed, value]);\n\n const toggleEye = useCallback(async () => {\n if (!masked) {\n dispatch({ type: 'toggle-show' });\n return;\n }\n if (ui.revealed !== undefined) {\n dispatch({ type: 'toggle-show' });\n return;\n }\n dispatch({ type: 'reveal-start' });\n try {\n const plaintext = await revealRef.current();\n dispatch({ type: 'reveal-success', value: plaintext });\n } catch (e) {\n dispatch({\n type: 'reveal-error',\n message: e instanceof Error ? e.message : loadFailedLabel,\n });\n }\n }, [loadFailedLabel, masked, ui.revealed]);\n\n const onInputChange = useCallback(\n (next: string, onChange: (value: string) => void) => {\n if (masked && typeof ui.revealed === 'string' && ui.showKey && next !== ui.revealed) {\n dispatch({ type: 'invalidate-reveal' });\n }\n onChange(next);\n },\n [masked, ui.revealed, ui.showKey],\n );\n\n return {\n masked,\n showKey: ui.showKey,\n revealed: ui.revealed,\n revealLoading: ui.revealLoading,\n revealErr: ui.revealErr,\n copied: ui.copied,\n inputValue,\n inputType,\n copyEnabled,\n copyKey,\n toggleEye,\n onInputChange,\n };\n}\n","import { CheckCircle2, Copy, ExternalLink, Eye, EyeOff, Loader2 } from 'lucide-react';\nimport { useCallback } from 'react';\n\nimport { revealImageProviderConfigApiKey } from '@/features/settings/image-providers-config-api';\nimport type { ApiKeyLinkKind } from '@/features/settings/provider-enrichment';\nimport { providerApiKeyLinkLabel } from '@/features/settings/provider-enrichment';\nimport type { ProvidersSettingsMessages } from '@/i18n/messages';\nimport { settingsInputFocusClass } from '@/lib/form-field-width';\nimport { interaction } from '@/lib/interaction';\nimport { cn } from '@/lib/cn';\nimport { useMaskedApiKeyField } from '@/lib/use-masked-api-key-field';\n\nexport type ImageProviderApiKeyFieldLabels = {\n apiKeyLabel: string;\n optionalPlaceholder: string;\n maskedHelp: string;\n copy: string;\n copied: string;\n show: string;\n hide: string;\n notInConfigFile: string;\n loadFailed: string;\n};\n\nexport function ImageProviderApiKeyField({\n providerId,\n value,\n onChange,\n labels,\n apiKeyLinks,\n apiKeyLinkLabels,\n}: {\n providerId: string;\n value: string;\n onChange: (next: string) => void;\n labels: ImageProviderApiKeyFieldLabels;\n apiKeyLinks: { href: string; kind: ApiKeyLinkKind }[];\n apiKeyLinkLabels: Pick<ProvidersSettingsMessages, 'getApiKey' | 'getApiKeyIntl' | 'getApiKeyCn'>;\n}) {\n const reveal = useCallback(\n () => revealImageProviderConfigApiKey(providerId).then((payload) => payload.apiKey ?? null),\n [providerId],\n );\n\n const {\n masked,\n showKey,\n revealed,\n revealLoading,\n revealErr,\n copied,\n inputValue,\n inputType,\n copyEnabled,\n copyKey,\n toggleEye,\n onInputChange,\n } = useMaskedApiKeyField({ value, reveal, loadFailedLabel: labels.loadFailed });\n\n return (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-key-${providerId}`}>\n {labels.apiKeyLabel}\n </label>\n {apiKeyLinks.length > 0 ? (\n <div className=\"flex flex-col gap-1\">\n {apiKeyLinks.map((link) => (\n <a\n key={`${link.kind}-${link.href}`}\n href={link.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex w-fit items-center gap-1 text-xs font-medium text-accent-fg hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n >\n {providerApiKeyLinkLabel(link.kind, apiKeyLinkLabels)}\n <ExternalLink className=\"size-3\" aria-hidden />\n </a>\n ))}\n </div>\n ) : null}\n {masked ? <p className=\"text-[11px] text-fg-subtle\">{labels.maskedHelp}</p> : null}\n <div className=\"relative min-w-0\">\n <input\n id={`img-cred-key-${providerId}`}\n type={inputType}\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(\n 'w-full rounded-lg border border-edge bg-surface-panel py-2 pl-3 pr-24 font-mono text-sm text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n )}\n value={inputValue}\n placeholder={masked ? '••••••••' : labels.optionalPlaceholder}\n onChange={(e) => onInputChange(e.target.value, onChange)}\n />\n <div className=\"absolute right-1 top-1/2 flex -translate-y-1/2 gap-0.5\">\n {copyEnabled ? (\n <button\n type=\"button\"\n className={cn(\n 'rounded p-1.5 text-fg-subtle hover:bg-surface-hover hover:text-fg',\n interaction.transition,\n interaction.press,\n interaction.focusRingPanel,\n )}\n title={copied ? labels.copied : labels.copy}\n aria-label={copied ? labels.copied : labels.copy}\n onClick={() => void copyKey()}\n >\n {copied ? <CheckCircle2 className=\"size-4\" /> : <Copy className=\"size-4\" />}\n </button>\n ) : null}\n <button\n type=\"button\"\n className={cn(\n 'rounded p-1.5 text-fg-subtle hover:bg-surface-hover hover:text-fg disabled:opacity-40',\n interaction.transition,\n interaction.press,\n interaction.focusRingPanel,\n )}\n title={showKey ? labels.hide : labels.show}\n aria-label={showKey ? labels.hide : labels.show}\n disabled={revealLoading}\n onClick={() => void toggleEye()}\n >\n {revealLoading ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n ) : showKey ? (\n <EyeOff className=\"size-4\" aria-hidden />\n ) : (\n <Eye className=\"size-4\" aria-hidden />\n )}\n </button>\n </div>\n </div>\n {masked && showKey && revealed === null && !revealErr ? (\n <p className=\"text-xs text-amber-700 dark:text-amber-400/90\">{labels.notInConfigFile}</p>\n ) : null}\n {revealErr ? <p className=\"text-xs text-red-600 dark:text-red-400\">{revealErr}</p> : null}\n </div>\n );\n}\n","import { ChevronDown, ExternalLink, Loader2, Save } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport { Link } from 'react-router-dom';\n\nimport { Button } from '@/components/ui/button';\nimport { ImageProviderApiKeyField } from '@/features/settings/image-provider-api-key-field';\nimport { emptyImageProviderCredRow, type ImageProviderCredRow } from '@/features/settings/image-providers-config-api';\nimport { getOrderedApiKeyLinks } from '@/features/settings/provider-enrichment';\nimport type {\n ImageGenProviderCredentialSummary,\n ImageProviderUiMetadata,\n} from '@/features/settings/use-image-provider-credentials';\nimport type { ProvidersSettingsMessages } from '@/i18n/messages';\nimport { settingsInputFocusClass } from '@/lib/form-field-width';\nimport type { StoredLanguage } from '@/lib/storage';\nimport { cn } from '@/lib/cn';\n\nfunction inputClass(): string {\n return cn(\n 'w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n );\n}\n\nfunction selectClass(): string {\n return cn(inputClass(), 'appearance-none bg-[length:1rem] bg-[right_0.5rem_center] bg-no-repeat pr-9');\n}\n\nconst CUSTOM_SENTINEL = '__custom__';\n\nfunction dashscopeSelectValue(\n row: ImageProviderCredRow,\n regions: NonNullable<ImageProviderUiMetadata['regions']>,\n): string {\n if (!row.region.trim() && !row.imageBaseUrl.trim()) return '';\n const r = row.region.trim().toLowerCase();\n if (regions.some((x) => x.value === r)) return r;\n return CUSTOM_SENTINEL;\n}\n\nfunction baseUrlSelectValue(\n row: ImageProviderCredRow,\n presets: NonNullable<ImageProviderUiMetadata['baseUrlPresets']>,\n): string {\n const b = row.baseUrl.trim().replace(/\\/+$/, '');\n if (!b) return '';\n const norm = presets.map((p) => p.value.replace(/\\/+$/, ''));\n const idx = norm.indexOf(b);\n if (idx >= 0) return presets[idx].value;\n return CUSTOM_SENTINEL;\n}\n\nexport type ImageProviderCredentialsPanelMessages = {\n credentialsIntro: string;\n regionHint: string;\n endpointPresetsHint: string;\n apiKeyLabel: string;\n optionalPlaceholder: string;\n regionLabel: string;\n baseUrlLabel: string;\n imageBaseUrlLabel: string;\n saveCredentials: string;\n savingCredentials: string;\n credentialsSaved: string;\n discardCredentials: string;\n credentialsNothingToSave: string;\n credentialsSaveError: string;\n regionPresetDefault: string;\n regionPresetCustom: string;\n baseUrlPresetDefault: string;\n baseUrlPresetCustom: string;\n openExtensionSettings: string;\n openImageModelsPage: string;\n extensionSettingsLinkTitle: string;\n imageModelsLinkTitle: string;\n configured: string;\n missingKey: string;\n unsavedChanges: string;\n expandProvider: string;\n collapseProvider: string;\n defaultModel: string;\n modelsLabel: string;\n modelCountOne: string;\n modelCountMany: string;\n imageBaseUrlPresetHint: string;\n dashscopeRegion_beijing: string;\n dashscopeRegion_singapore: string;\n dashscopeRegion_us: string;\n apiKeyMaskedHelp: string;\n apiKeyCopy: string;\n apiKeyCopied: string;\n apiKeyShow: string;\n apiKeyHide: string;\n apiKeyNotInConfigFile: string;\n apiKeyRevealFailed: string;\n minimaxClusterLabel: string;\n minimaxClusterHint: string;\n falQueueBaseLabel: string;\n falQueueBaseHint: string;\n};\n\nfunction translateDashscopeRegion(m: ImageProviderCredentialsPanelMessages, value: string, serverLabel: string) {\n if (value === 'beijing') return m.dashscopeRegion_beijing;\n if (value === 'singapore') return m.dashscopeRegion_singapore;\n if (value === 'us') return m.dashscopeRegion_us;\n return serverLabel;\n}\n\nfunction baseUrlPresetBlockTitle(\n t: ImageProviderCredentialsPanelMessages,\n kind: ImageProviderUiMetadata['baseUrlPresetKind'],\n): string {\n if (kind === 'minimax') return t.minimaxClusterLabel;\n if (kind === 'fal') return t.falQueueBaseLabel;\n return t.baseUrlLabel;\n}\n\nfunction baseUrlPresetBlockHint(\n t: ImageProviderCredentialsPanelMessages,\n kind: ImageProviderUiMetadata['baseUrlPresetKind'],\n): string | null {\n if (kind === 'minimax') return t.minimaxClusterHint;\n if (kind === 'fal') return t.falQueueBaseHint;\n return null;\n}\n\nfunction isProviderRowDirty(\n draft: ImageProviderCredRow,\n baseline: ImageProviderCredRow,\n): boolean {\n return JSON.stringify(draft) !== JSON.stringify(baseline);\n}\n\nfunction formatModelCount(t: ImageProviderCredentialsPanelMessages, count: number): string {\n if (count === 1) return t.modelCountOne;\n return t.modelCountMany.replace('{count}', String(count));\n}\n\nexport function ImageProviderCredentialsPanel({\n summaries,\n credDraft,\n credBaseline,\n credDirty,\n credSaving,\n credError,\n credSavedFlash,\n credNoopFlash,\n updateCredRow,\n onDiscardCredentials,\n onSaveCredentials,\n extensionIds,\n showExtensionLinks,\n showImageModelsLink,\n hideActions = false,\n language,\n apiKeyLinkLabels,\n messages: t,\n}: {\n summaries: ImageGenProviderCredentialSummary[];\n credDraft: Record<string, ImageProviderCredRow>;\n credBaseline: Record<string, ImageProviderCredRow>;\n credDirty: boolean;\n credSaving: boolean;\n credError: string | null;\n credSavedFlash: boolean;\n credNoopFlash: boolean;\n updateCredRow: (id: string, patch: Partial<ImageProviderCredRow>) => void;\n onDiscardCredentials: () => void;\n onSaveCredentials: () => void;\n /** Extension ids present in gateway discovery (for deep links). */\n extensionIds: Set<string>;\n showExtensionLinks: boolean;\n showImageModelsLink: boolean;\n /** When true, hides the inline Discard/Save buttons (caller uses a global Save bar instead). */\n hideActions?: boolean;\n language: StoredLanguage;\n apiKeyLinkLabels: Pick<ProvidersSettingsMessages, 'getApiKey' | 'getApiKeyIntl' | 'getApiKeyCn'>;\n messages: ImageProviderCredentialsPanelMessages;\n}) {\n const anyRegionUi = summaries.some((s) => (s.ui?.regions?.length ?? 0) > 0);\n const anyBaseUrlPresets = summaries.some((s) => (s.ui?.baseUrlPresets?.length ?? 0) > 0);\n const [manualExpandedIds, setManualExpandedIds] = useState<Set<string>>(() => new Set());\n const [manualCollapsedIds, setManualCollapsedIds] = useState<Set<string>>(() => new Set());\n\n const dirtyProviderIds = useMemo(() => {\n const ids = new Set<string>();\n for (const summary of summaries) {\n const draftRow = credDraft[summary.id] ?? emptyImageProviderCredRow();\n const baselineRow = credBaseline[summary.id] ?? emptyImageProviderCredRow();\n if (isProviderRowDirty(draftRow, baselineRow)) {\n ids.add(summary.id);\n }\n }\n return ids;\n }, [summaries, credDraft, credBaseline]);\n\n const isProviderExpanded = (id: string) => {\n if (manualCollapsedIds.has(id)) return false;\n if (manualExpandedIds.has(id)) return true;\n return dirtyProviderIds.has(id);\n };\n\n const toggleProviderExpanded = (id: string) => {\n const expanded = isProviderExpanded(id);\n if (expanded) {\n setManualCollapsedIds((current) => new Set(current).add(id));\n setManualExpandedIds((current) => {\n const next = new Set(current);\n next.delete(id);\n return next;\n });\n return;\n }\n setManualCollapsedIds((current) => {\n const next = new Set(current);\n next.delete(id);\n return next;\n });\n setManualExpandedIds((current) => new Set(current).add(id));\n };\n\n if (summaries.length === 0) {\n return null;\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1 text-xs leading-relaxed text-fg-muted\">\n <p>{t.credentialsIntro}</p>\n {anyRegionUi ? <p className=\"text-fg-subtle\">{t.regionHint}</p> : null}\n {anyBaseUrlPresets ? <p className=\"text-fg-subtle\">{t.endpointPresetsHint}</p> : null}\n {showImageModelsLink ? (\n <p>\n <Link\n to=\"/settings/image-models\"\n className=\"font-medium text-accent hover:underline\"\n title={t.imageModelsLinkTitle}\n >\n {t.openImageModelsPage}\n </Link>\n </p>\n ) : null}\n </div>\n {credError ? (\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-sm text-red-700 dark:text-red-300\">\n {credError}\n </div>\n ) : null}\n {hideActions ? null : (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {credSavedFlash ? (\n <span className=\"text-sm text-fg-muted\">{t.credentialsSaved}</span>\n ) : null}\n {credNoopFlash ? (\n <span className=\"text-sm text-fg-muted\">{t.credentialsNothingToSave}</span>\n ) : null}\n <Button type=\"button\" variant=\"secondary\" onClick={onDiscardCredentials} disabled={!credDirty || credSaving}>\n {t.discardCredentials}\n </Button>\n <Button type=\"button\" variant=\"primary\" onClick={onSaveCredentials} disabled={!credDirty || credSaving}>\n {credSaving ? (\n <>\n <Loader2 className=\"size-3.5 animate-spin\" />\n <span className=\"ml-1.5\">{t.savingCredentials}</span>\n </>\n ) : (\n <>\n <Save className=\"size-3.5\" />\n <span className=\"ml-1.5\">{t.saveCredentials}</span>\n </>\n )}\n </Button>\n </div>\n )}\n <div className=\"flex flex-col gap-4\">\n {summaries.map((p) => {\n const row = credDraft[p.id] ?? emptyImageProviderCredRow();\n const ui = p.ui;\n const extPath =\n showExtensionLinks && extensionIds.has(p.id)\n ? `/settings/ext/${encodeURIComponent(p.id)}`\n : null;\n const baselineRow = credBaseline[p.id] ?? emptyImageProviderCredRow();\n const isDirty = isProviderRowDirty(row, baselineRow);\n const isExpanded = isProviderExpanded(p.id);\n const providerName = p.label ?? p.id;\n const modelCountLabel = formatModelCount(t, p.models.length);\n return (\n <section\n key={p.id}\n className={cn(\n 'overflow-hidden rounded-xl border bg-surface-panel shadow-sm transition-colors dark:shadow-none',\n isDirty ? 'border-accent/50' : 'border-edge',\n )}\n >\n <button\n type=\"button\"\n className=\"flex w-full items-start justify-between gap-3 px-4 py-3 text-left hover:bg-surface-hover/70\"\n aria-expanded={isExpanded}\n aria-controls={`img-provider-credentials-${p.id}`}\n onClick={() => toggleProviderExpanded(p.id)}\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2\">\n <span className=\"truncate text-sm font-semibold text-fg\">{providerName}</span>\n <span className=\"rounded-full bg-surface-subtle px-2 py-0.5 text-[11px] font-medium text-fg-muted\">\n {p.id}\n </span>\n {isDirty ? (\n <span className=\"rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg\">\n {t.unsavedChanges}\n </span>\n ) : null}\n {p.configured ? (\n <span className=\"rounded-full bg-accent-soft px-2 py-0.5 text-[11px] font-medium text-accent-fg\">\n {t.configured}\n </span>\n ) : (\n <span className=\"rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-700 dark:text-amber-300\">\n {t.missingKey}\n </span>\n )}\n </div>\n <div className=\"flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs text-fg-subtle\">\n <span>{modelCountLabel}</span>\n {p.defaultModel ? (\n <span className=\"min-w-0 truncate\">\n <span className=\"text-fg-muted\">{t.defaultModel}:</span> {p.id}/{p.defaultModel}\n </span>\n ) : null}\n </div>\n </div>\n <ChevronDown\n className={cn(\n 'mt-0.5 size-4 shrink-0 text-fg-subtle transition-transform',\n isExpanded ? 'rotate-180' : 'rotate-0',\n )}\n aria-hidden=\"true\"\n />\n <span className=\"sr-only\">{isExpanded ? t.collapseProvider : t.expandProvider}</span>\n </button>\n\n {isExpanded ? (\n <div id={`img-provider-credentials-${p.id}`} className=\"border-t border-edge px-4 py-4\">\n {extPath ? (\n <Link\n to={extPath}\n className=\"mb-3 inline-flex items-center gap-1 text-xs font-medium text-accent hover:underline\"\n title={t.extensionSettingsLinkTitle}\n >\n <ExternalLink className=\"size-3\" />\n {t.openExtensionSettings}\n </Link>\n ) : null}\n {p.models.length > 0 ? (\n <p className=\"mb-3 text-xs leading-relaxed text-fg-subtle\">\n <span className=\"text-fg-muted\">{t.modelsLabel}:</span>{' '}\n {p.models.map((modelId) => `${p.id}/${modelId}`).join(', ')}\n </p>\n ) : null}\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <ImageProviderApiKeyField\n providerId={p.id}\n value={row.apiKey}\n onChange={(next) => updateCredRow(p.id, { apiKey: next })}\n apiKeyLinks={getOrderedApiKeyLinks(p.id, language)}\n apiKeyLinkLabels={apiKeyLinkLabels}\n labels={{\n apiKeyLabel: t.apiKeyLabel,\n optionalPlaceholder: t.optionalPlaceholder,\n maskedHelp: t.apiKeyMaskedHelp,\n copy: t.apiKeyCopy,\n copied: t.apiKeyCopied,\n show: t.apiKeyShow,\n hide: t.apiKeyHide,\n notInConfigFile: t.apiKeyNotInConfigFile,\n loadFailed: t.apiKeyRevealFailed,\n }}\n />\n\n {ui?.regions?.length ? (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-region-preset-${p.id}`}>\n {t.regionLabel}\n </label>\n <select\n id={`img-cred-region-preset-${p.id}`}\n className={selectClass()}\n value={dashscopeSelectValue(row, ui.regions)}\n onChange={(e) => {\n const v = e.target.value;\n if (v === '') {\n updateCredRow(p.id, { region: '', imageBaseUrl: '' });\n return;\n }\n if (v === CUSTOM_SENTINEL) {\n updateCredRow(p.id, { region: '', imageBaseUrl: '' });\n return;\n }\n const opt = ui.regions!.find((x) => x.value === v);\n if (opt) {\n updateCredRow(p.id, { region: opt.value, imageBaseUrl: opt.imageBaseUrl });\n }\n }}\n >\n <option value=\"\">{t.regionPresetDefault}</option>\n {ui.regions.map((r) => (\n <option key={r.value} value={r.value}>\n {translateDashscopeRegion(t, r.value, r.label)}\n </option>\n ))}\n <option value={CUSTOM_SENTINEL}>{t.regionPresetCustom}</option>\n </select>\n {dashscopeSelectValue(row, ui.regions) === CUSTOM_SENTINEL ? (\n <div className=\"mt-2 grid gap-2 sm:grid-cols-2\">\n <input\n type=\"text\"\n className={inputClass()}\n value={row.region}\n placeholder=\"region\"\n onChange={(e) => updateCredRow(p.id, { region: e.target.value })}\n />\n <input\n type=\"url\"\n className={inputClass()}\n value={row.imageBaseUrl}\n placeholder={t.imageBaseUrlLabel}\n onChange={(e) => updateCredRow(p.id, { imageBaseUrl: e.target.value })}\n />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {ui?.baseUrlPresets?.length ? (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-base-preset-${p.id}`}>\n {baseUrlPresetBlockTitle(t, ui.baseUrlPresetKind)}\n </label>\n {baseUrlPresetBlockHint(t, ui.baseUrlPresetKind) ? (\n <p className=\"text-[11px] text-fg-subtle\">{baseUrlPresetBlockHint(t, ui.baseUrlPresetKind)}</p>\n ) : null}\n <select\n id={`img-cred-base-preset-${p.id}`}\n className={selectClass()}\n value={baseUrlSelectValue(row, ui.baseUrlPresets)}\n onChange={(e) => {\n const v = e.target.value;\n if (v === '') {\n updateCredRow(p.id, { baseUrl: '' });\n return;\n }\n if (v === CUSTOM_SENTINEL) {\n updateCredRow(p.id, { baseUrl: '' });\n return;\n }\n updateCredRow(p.id, { baseUrl: v.replace(/\\/+$/, '') });\n }}\n >\n <option value=\"\">{t.baseUrlPresetDefault}</option>\n {ui.baseUrlPresets.map((b) => (\n <option key={b.value} value={b.value}>\n {b.label}\n </option>\n ))}\n <option value={CUSTOM_SENTINEL}>{t.baseUrlPresetCustom}</option>\n </select>\n {baseUrlSelectValue(row, ui.baseUrlPresets) === CUSTOM_SENTINEL ? (\n <input\n type=\"url\"\n className={cn(inputClass(), 'mt-2')}\n value={row.baseUrl}\n placeholder=\"https://…\"\n onChange={(e) => updateCredRow(p.id, { baseUrl: e.target.value })}\n />\n ) : null}\n </div>\n ) : null}\n\n {ui?.regions?.length && dashscopeSelectValue(row, ui.regions) !== CUSTOM_SENTINEL ? (\n <div className=\"flex min-w-0 flex-col gap-1 sm:col-span-2\">\n <label className=\"text-xs font-medium text-fg-muted\" htmlFor={`img-cred-imgbase-ro-${p.id}`}>\n {t.imageBaseUrlLabel}\n </label>\n <input\n id={`img-cred-imgbase-ro-${p.id}`}\n type=\"url\"\n readOnly\n className={cn(inputClass(), 'cursor-not-allowed opacity-90')}\n value={row.imageBaseUrl}\n title={t.imageBaseUrlPresetHint}\n />\n <p className=\"text-[11px] text-fg-subtle\">{t.imageBaseUrlPresetHint}</p>\n </div>\n ) : null}\n </div>\n </div>\n ) : null}\n </section>\n );\n })}\n </div>\n </div>\n );\n}\n","import { useCallback, useMemo, useRef, useState } from 'react';\nimport { mutate } from 'swr';\n\nimport { useGatewayConfigSwr } from '@/features/gateway/gateway-config-swr';\nimport {\n buildImageProvidersConfigPatch,\n emptyImageProviderCredRow,\n imageProviderCredRowsFromConfigRoot,\n patchImageProvidersConfig,\n type ImageProviderCredRow,\n} from '@/features/settings/image-providers-config-api';\nimport { IMAGE_PROVIDERS_SWR_KEY } from '@/features/settings/image-providers-swr-key';\nimport { apiUrl } from '@/lib/url';\nimport { useGatewayStore } from '@/stores/gateway-store';\n\nexport type ImageProviderUiRegionOption = {\n value: string;\n label: string;\n imageBaseUrl: string;\n};\n\nexport type ImageProviderUiBaseUrlPreset = {\n value: string;\n label: string;\n};\n\nexport type ImageProviderUiMetadata = {\n regions?: ImageProviderUiRegionOption[];\n baseUrlPresets?: ImageProviderUiBaseUrlPreset[];\n baseUrlPresetKind?: 'fal' | 'minimax' | 'google' | 'openai';\n};\n\nexport type ImageGenProviderCredentialSummary = {\n id: string;\n label?: string;\n defaultModel?: string;\n models: string[];\n configured?: boolean;\n ui?: ImageProviderUiMetadata;\n};\n\nexport function useImageProviderCredentials(summaries: ImageGenProviderCredentialSummary[]) {\n const hasToken = useGatewayStore((s) => Boolean(s.token));\n const gwSwr = useGatewayConfigSwr(hasToken);\n const gwCfg = gwSwr.data;\n\n const ids = useMemo(() => summaries.map((s) => s.id), [summaries]);\n\n const dirtyRef = useRef(false);\n const [localDraft, setLocalDraft] = useState<Record<string, ImageProviderCredRow> | null>(null);\n const [credSaving, setCredSaving] = useState(false);\n const [credError, setCredError] = useState<string | null>(null);\n const [credSavedFlash, setCredSavedFlash] = useState(false);\n const [credNoopFlash, setCredNoopFlash] = useState(false);\n\n const credRowsFromServer = useMemo(\n () => imageProviderCredRowsFromConfigRoot(gwCfg?.payload?.config, ids),\n [gwCfg?.payload?.config, ids],\n );\n\n const credDraft = localDraft ?? credRowsFromServer;\n const credBaseline = credRowsFromServer;\n\n const credDirty = useMemo(\n () => JSON.stringify(credDraft) !== JSON.stringify(credBaseline),\n [credDraft, credBaseline],\n );\n\n const updateCredRow = useCallback((id: string, patch: Partial<ImageProviderCredRow>) => {\n dirtyRef.current = true;\n setLocalDraft((prev) => {\n const base = prev ?? credRowsFromServer;\n const row = base[id] ?? emptyImageProviderCredRow();\n return { ...base, [id]: { ...row, ...patch } };\n });\n }, [credRowsFromServer]);\n\n const onDiscardCredentials = useCallback(() => {\n dirtyRef.current = false;\n setLocalDraft(null);\n setCredError(null);\n setCredSavedFlash(false);\n setCredNoopFlash(false);\n }, []);\n\n const saveCredentials = useCallback(\n async (errorFallback: string) => {\n const patch = buildImageProvidersConfigPatch(ids, credDraft, credBaseline);\n if (Object.keys(patch).length === 0) {\n setCredNoopFlash(true);\n window.setTimeout(() => setCredNoopFlash(false), 2200);\n return;\n }\n setCredSaving(true);\n setCredError(null);\n setCredSavedFlash(false);\n try {\n await patchImageProvidersConfig(patch);\n const updated = await gwSwr.mutate?.();\n void mutate(apiUrl(IMAGE_PROVIDERS_SWR_KEY));\n void updated;\n dirtyRef.current = false;\n setLocalDraft(null);\n setCredSavedFlash(true);\n window.setTimeout(() => setCredSavedFlash(false), 2000);\n } catch (e) {\n setCredError(e instanceof Error ? e.message : errorFallback);\n } finally {\n setCredSaving(false);\n }\n },\n [ids, credDraft, credBaseline, gwSwr],\n );\n\n return {\n gwSwr,\n credDraft,\n credBaseline,\n credDirty,\n credSaving,\n credError,\n credSavedFlash,\n credNoopFlash,\n updateCredRow,\n onDiscardCredentials,\n saveCredentials,\n };\n}\n","import { revalidateGatewayConfig } from '@/features/gateway/gateway-config-swr';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport type { SttSettings, SttProvidersPayload, TtsSettings, VoiceModelsPayload, VoiceSettingsState, VoiceProvidersPayload } from './voice-settings.types';\n\nexport type { SttSettings, TtsSettings, VoiceModelsPayload, VoiceSettingsState, VoiceProvidersPayload, SttProvidersPayload, TtsProviderListEntry, SttProviderListEntry } from './voice-settings.types';\n\nfunction defaultStt(): SttSettings {\n return {\n enabled: false,\n provider: 'alibaba',\n alibaba: { model: 'paraformer-v2' },\n openai: { model: 'whisper-1' },\n fallback: { enabled: true, order: ['alibaba', 'openai'] },\n };\n}\n\n// Defaults intentionally mirror src/config/schema.ts (TTSConfigSchema /\n// TTSEdgeConfigSchema) and extensions/tts-local-cli/xopc.extension.json so a\n// PATCH /api/config round-trip never silently overrides backend defaults.\nfunction defaultTts(): TtsSettings {\n return {\n enabled: false,\n provider: 'openai',\n trigger: 'always',\n maxTextLength: 512,\n timeoutMs: 60000,\n alibaba: { model: 'qwen-tts', voice: 'Cherry' },\n openai: { model: 'tts-1', voice: 'alloy' },\n edge: { voice: 'en-US-MichelleNeural' },\n minimax: { model: 'speech-2.8-hd', voice: 'male-qn-qingse' },\n 'tts-local-cli': {\n command: '',\n outputFormat: 'wav',\n },\n };\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction normalizeSttProvider(v: unknown): string {\n return typeof v === 'string' && v.trim().length > 0 ? v.trim() : 'alibaba';\n}\n\nfunction mergeStt(raw: unknown): SttSettings {\n const d = defaultStt();\n if (!isRecord(raw)) return d;\n const provider = normalizeSttProvider(raw.provider);\n const alibaba = isRecord(raw.alibaba) ? { ...d.alibaba, ...raw.alibaba } : d.alibaba;\n const openai = isRecord(raw.openai) ? { ...d.openai, ...raw.openai } : d.openai;\n const baseFallback = d.fallback ?? { enabled: true, order: ['alibaba', 'openai'] };\n let fallback = baseFallback;\n if (isRecord(raw.fallback)) {\n const order = Array.isArray(raw.fallback.order)\n ? raw.fallback.order.filter((x): x is string => typeof x === 'string' && x.trim().length > 0)\n : fallback.order;\n fallback = {\n enabled: typeof raw.fallback.enabled === 'boolean' ? raw.fallback.enabled : fallback.enabled,\n order: order.length ? order : fallback.order,\n };\n }\n\n const providers = isRecord(raw.providers)\n ? Object.fromEntries(\n Object.entries(raw.providers).map(([key, value]) => [\n key,\n isRecord(value) ? { ...value } : {},\n ]),\n )\n : undefined;\n\n return {\n enabled: Boolean(raw.enabled),\n provider,\n alibaba,\n openai,\n ...(providers ? { providers } : {}),\n fallback,\n };\n}\n\n/** Provider id is open string — extension SpeechProviderPlugins (e.g. tts-local-cli) are allowed. */\nfunction normalizeTtsProvider(v: unknown): string {\n return typeof v === 'string' && v.trim().length > 0 ? v.trim() : 'openai';\n}\n\nfunction mergeTts(raw: unknown): TtsSettings {\n const d = defaultTts();\n if (!isRecord(raw)) return d;\n const provider = normalizeTtsProvider(raw.provider);\n const trigger =\n raw.trigger === 'off' ||\n raw.trigger === 'always' ||\n raw.trigger === 'inbound' ||\n raw.trigger === 'tagged'\n ? raw.trigger\n : 'always';\n // Per-provider buckets: keep built-in defaults, plus passthrough for any\n // extension-provider key (e.g. `tts-local-cli`) so unknown plugins survive\n // a round-trip through the UI without losing their config.\n const localCliRaw = raw['tts-local-cli'];\n return {\n enabled: Boolean(raw.enabled),\n provider,\n trigger,\n maxTextLength:\n typeof raw.maxTextLength === 'number' && Number.isFinite(raw.maxTextLength)\n ? raw.maxTextLength\n : d.maxTextLength,\n timeoutMs:\n typeof raw.timeoutMs === 'number' && Number.isFinite(raw.timeoutMs) ? raw.timeoutMs : d.timeoutMs,\n alibaba: isRecord(raw.alibaba) ? { ...d.alibaba, ...raw.alibaba } : d.alibaba,\n openai: isRecord(raw.openai) ? { ...d.openai, ...raw.openai } : d.openai,\n edge: isRecord(raw.edge) ? { ...d.edge, ...raw.edge } : d.edge,\n minimax: isRecord(raw.minimax) ? { ...d.minimax, ...raw.minimax } : d.minimax,\n 'tts-local-cli': isRecord(localCliRaw)\n ? { ...d['tts-local-cli'], ...localCliRaw }\n : d['tts-local-cli'],\n };\n}\n\nexport function normalizeVoiceSettings(config: unknown): VoiceSettingsState {\n const c = isRecord(config) ? config : {};\n return {\n stt: mergeStt(c.stt),\n tts: mergeTts(c.tts),\n };\n}\n\nexport async function fetchVoiceSettings(): Promise<VoiceSettingsState> {\n const res = await fetchJson<{ ok?: boolean; payload?: { config?: unknown } }>(apiUrl('/api/config'));\n return normalizeVoiceSettings(res.payload?.config ?? {});\n}\n\nexport async function patchVoiceSettings(state: VoiceSettingsState): Promise<void> {\n await fetchJson(apiUrl('/api/config'), {\n method: 'PATCH',\n body: JSON.stringify({ stt: state.stt, tts: state.tts }),\n });\n void revalidateGatewayConfig();\n}\n\nexport async function fetchVoiceModels(): Promise<VoiceModelsPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: { models?: VoiceModelsPayload } }>(\n apiUrl('/api/voice/models'),\n );\n if (!res.payload?.models) {\n throw new Error('Missing voice models payload');\n }\n return res.payload.models;\n}\n\nexport async function fetchVoiceProviders(): Promise<VoiceProvidersPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: VoiceProvidersPayload }>(\n apiUrl('/api/voice/providers'),\n );\n if (!res.payload?.providers) {\n throw new Error('Missing voice providers payload');\n }\n return res.payload;\n}\n\nexport async function fetchVoiceSttProviders(): Promise<SttProvidersPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: SttProvidersPayload }>(\n apiUrl('/api/voice/stt-providers'),\n );\n if (!res.payload?.providers) {\n throw new Error('Missing STT providers payload');\n }\n return res.payload;\n}\n\nexport type RevealVoiceApiKeyPayload = {\n kind: 'stt' | 'tts';\n provider: string;\n apiKey: string | null;\n source: 'config' | 'none';\n};\n\n/** POST /api/voice/reveal-api-key — plaintext only when stored in config file. */\nexport async function revealVoiceConfigApiKey(args: {\n kind: 'stt' | 'tts';\n provider: string;\n}): Promise<RevealVoiceApiKeyPayload> {\n const res = await fetchJson<{ ok?: boolean; payload?: RevealVoiceApiKeyPayload }>(\n apiUrl('/api/voice/reveal-api-key'),\n {\n method: 'POST',\n body: JSON.stringify(args),\n },\n );\n if (!res.payload) {\n throw new Error('Missing reveal payload');\n }\n return res.payload;\n}\n","import { Check, Copy, Eye, EyeOff, Loader2 } from 'lucide-react';\nimport { useCallback } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { revealVoiceConfigApiKey } from '@/features/settings/voice-config-api';\nimport { settingsInputFocusClass } from '@/lib/form-field-width';\nimport { cn } from '@/lib/cn';\nimport { useMaskedApiKeyField } from '@/lib/use-masked-api-key-field';\n\nexport type VoiceApiKeyFieldLabels = {\n maskedHelp: string;\n copy: string;\n copied: string;\n show: string;\n hide: string;\n notInConfigFile: string;\n loadFailed: string;\n};\n\nexport function VoiceApiKeyField({\n kind,\n providerId,\n fieldId,\n value,\n onChange,\n labels,\n placeholder = 'sk-...',\n className,\n}: {\n kind: 'stt' | 'tts';\n providerId: string;\n fieldId: string;\n value: string;\n onChange: (next: string) => void;\n labels: VoiceApiKeyFieldLabels;\n placeholder?: string;\n className?: string;\n}) {\n const reveal = useCallback(\n () =>\n revealVoiceConfigApiKey({ kind, provider: providerId }).then((payload) => payload.apiKey ?? null),\n [kind, providerId],\n );\n\n const {\n masked,\n showKey,\n revealed,\n revealLoading,\n revealErr,\n copied,\n inputValue,\n inputType,\n copyEnabled,\n copyKey,\n toggleEye,\n onInputChange,\n } = useMaskedApiKeyField({ value, reveal, loadFailedLabel: labels.loadFailed });\n\n return (\n <div className={cn('flex min-w-0 flex-col gap-1.5', className)}>\n {masked ? <p className=\"text-xs text-fg-subtle\">{labels.maskedHelp}</p> : null}\n <div className=\"flex flex-wrap gap-2\">\n <input\n id={fieldId}\n type={inputType}\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(\n 'w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-fg',\n 'placeholder:text-fg-subtle',\n settingsInputFocusClass,\n 'dark:border-edge',\n 'min-w-0 flex-1 font-mono text-xs',\n )}\n value={inputValue}\n placeholder={masked ? '••••••••' : placeholder}\n onChange={(e) => onInputChange(e.target.value, onChange)}\n />\n {copyEnabled ? (\n <Button type=\"button\" variant=\"secondary\" className=\"px-2 py-1 text-xs\" onClick={() => void copyKey()}>\n {copied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {copied ? labels.copied : labels.copy}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"px-2 py-1 text-xs\"\n disabled={revealLoading}\n onClick={() => void toggleEye()}\n >\n {revealLoading ? (\n <Loader2 className=\"size-3.5 animate-spin\" aria-hidden />\n ) : showKey ? (\n <EyeOff className=\"size-3.5\" />\n ) : (\n <Eye className=\"size-3.5\" />\n )}\n {showKey ? labels.hide : labels.show}\n </Button>\n </div>\n {masked && showKey && revealed === null && !revealErr ? (\n <p className=\"text-xs text-amber-700 dark:text-amber-400/90\">{labels.notInConfigFile}</p>\n ) : null}\n {revealErr ? <p className=\"text-xs text-red-600 dark:text-red-400\">{revealErr}</p> : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -9,7 +9,7 @@
9
9
  <link rel="icon" type="image/svg+xml" href="/logo.svg" />
10
10
  <link rel="apple-touch-icon" href="/logo.svg" />
11
11
  <title>xopc</title>
12
- <script type="module" crossorigin src="/assets/index-S3bgG2JF.js"></script>
12
+ <script type="module" crossorigin src="/assets/index-ChiUhJAs.js"></script>
13
13
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-aKtaBQYM.js">
14
14
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-D0yxdRpg.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-BOUWij0V.js">
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.75";
2
+ var version = "0.0.77";
3
3
  //#endregion
4
4
  export { version };
5
5
 
@@ -66,7 +66,11 @@ async function prepareSessionManagerForRun(params) {
66
66
  return;
67
67
  }
68
68
  if (params.hadSessionFile && header && !hasAssistant) {
69
- await fs.writeFile(params.sessionFile, "", "utf-8");
69
+ try {
70
+ await fs.unlink(params.sessionFile);
71
+ } catch (err) {
72
+ if (err.code !== "ENOENT") throw err;
73
+ }
70
74
  sm.fileEntries = [header];
71
75
  sm.byId?.clear?.();
72
76
  sm.labelsById?.clear?.();
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager-init.js","names":[],"sources":["../../../../src/agent/embedded/session-manager-init.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\n\ntype SessionHeaderEntry = { type: \"session\"; id?: string; cwd?: string };\ntype SessionMessageEntry = {\n type: \"message\";\n message?: {\n role?: string;\n stopReason?: string;\n usage?: Record<string, unknown>;\n };\n};\n\n/** pi-coding-agent auto-compaction calls `calculateContextTokens(usage)` without a null check. */\nconst EMPTY_ASSISTANT_USAGE = {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\n/**\n * Legacy xopc transcripts may omit `usage` on assistant rows; pi AgentSession crashes on turn end.\n */\nexport function repairAssistantUsageInSessionManager(sessionManager: unknown): void {\n const sm = sessionManager as { fileEntries?: Array<SessionHeaderEntry | SessionMessageEntry | { type: string }> };\n if (!Array.isArray(sm.fileEntries)) {\n return;\n }\n for (const entry of sm.fileEntries) {\n if (entry.type !== \"message\") {\n continue;\n }\n const msg = (entry as SessionMessageEntry).message;\n if (msg?.role !== \"assistant\") {\n continue;\n }\n if (msg.stopReason === \"aborted\" || msg.stopReason === \"error\") {\n continue;\n }\n if (!msg.usage || typeof msg.usage !== \"object\") {\n msg.usage = { ...EMPTY_ASSISTANT_USAGE };\n } else if (msg.usage.totalTokens === undefined) {\n const u = msg.usage;\n const input = typeof u.input === \"number\" ? u.input : 0;\n const output = typeof u.output === \"number\" ? u.output : 0;\n const cacheRead = typeof u.cacheRead === \"number\" ? u.cacheRead : 0;\n const cacheWrite = typeof u.cacheWrite === \"number\" ? u.cacheWrite : 0;\n msg.usage = {\n ...EMPTY_ASSISTANT_USAGE,\n ...u,\n input,\n output,\n cacheRead,\n cacheWrite,\n totalTokens: input + output + cacheRead + cacheWrite,\n };\n }\n }\n}\n\n/**\n * pi-coding-agent SessionManager persistence quirk:\n * - If the file exists but has no assistant message, SessionManager marks itself `flushed=true`\n * and will never persist the initial user message.\n * - If the file doesn't exist yet, SessionManager builds a new session in memory and flushes\n * header+user+assistant once the first assistant arrives (good).\n *\n * This normalizes the file/session state so the first user prompt is persisted before the first\n * assistant entry, even for pre-created session files.\n */\nexport async function prepareSessionManagerForRun(params: {\n sessionManager: unknown;\n sessionFile: string;\n hadSessionFile: boolean;\n sessionId: string;\n cwd: string;\n}): Promise<void> {\n const sm = params.sessionManager as {\n sessionId: string;\n flushed: boolean;\n fileEntries: Array<SessionHeaderEntry | SessionMessageEntry | { type: string }>;\n byId?: Map<string, unknown>;\n labelsById?: Map<string, unknown>;\n leafId?: string | null;\n };\n\n const header = sm.fileEntries.find((e): e is SessionHeaderEntry => e.type === \"session\");\n const hasAssistant = sm.fileEntries.some(\n (e) => e.type === \"message\" && (e as SessionMessageEntry).message?.role === \"assistant\",\n );\n\n if (!params.hadSessionFile && header) {\n header.id = params.sessionId;\n header.cwd = params.cwd;\n sm.sessionId = params.sessionId;\n return;\n }\n\n if (params.hadSessionFile && header && !hasAssistant) {\n // Reset file so the first assistant flush includes header+user+assistant in order.\n await fs.writeFile(params.sessionFile, \"\", \"utf-8\");\n sm.fileEntries = [header];\n sm.byId?.clear?.();\n sm.labelsById?.clear?.();\n sm.leafId = null;\n sm.flushed = false;\n }\n\n repairAssistantUsageInSessionManager(sm);\n}\n"],"mappings":";;;AAaA,MAAM,wBAAwB;CAC5B,OAAO;CACP,QAAQ;CACR,WAAW;CACX,YAAY;CACZ,aAAa;CACb,MAAM;EAAE,OAAO;EAAG,QAAQ;EAAG,WAAW;EAAG,YAAY;EAAG,OAAO;EAAG;CACrE;;;;AAKD,SAAgB,qCAAqC,gBAA+B;CAClF,MAAM,KAAK;AACX,KAAI,CAAC,MAAM,QAAQ,GAAG,YAAY,CAChC;AAEF,MAAK,MAAM,SAAS,GAAG,aAAa;AAClC,MAAI,MAAM,SAAS,UACjB;EAEF,MAAM,MAAO,MAA8B;AAC3C,MAAI,KAAK,SAAS,YAChB;AAEF,MAAI,IAAI,eAAe,aAAa,IAAI,eAAe,QACrD;AAEF,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,SACrC,KAAI,QAAQ,EAAE,GAAG,uBAAuB;WAC/B,IAAI,MAAM,gBAAgB,KAAA,GAAW;GAC9C,MAAM,IAAI,IAAI;GACd,MAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;GACtD,MAAM,SAAS,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;GACzD,MAAM,YAAY,OAAO,EAAE,cAAc,WAAW,EAAE,YAAY;GAClE,MAAM,aAAa,OAAO,EAAE,eAAe,WAAW,EAAE,aAAa;AACrE,OAAI,QAAQ;IACV,GAAG;IACH,GAAG;IACH;IACA;IACA;IACA;IACA,aAAa,QAAQ,SAAS,YAAY;IAC3C;;;;;;;;;;;;;;AAeP,eAAsB,4BAA4B,QAMhC;CAChB,MAAM,KAAK,OAAO;CASlB,MAAM,SAAS,GAAG,YAAY,MAAM,MAA+B,EAAE,SAAS,UAAU;CACxF,MAAM,eAAe,GAAG,YAAY,MACjC,MAAM,EAAE,SAAS,aAAc,EAA0B,SAAS,SAAS,YAC7E;AAED,KAAI,CAAC,OAAO,kBAAkB,QAAQ;AACpC,SAAO,KAAK,OAAO;AACnB,SAAO,MAAM,OAAO;AACpB,KAAG,YAAY,OAAO;AACtB;;AAGF,KAAI,OAAO,kBAAkB,UAAU,CAAC,cAAc;AAEpD,QAAM,GAAG,UAAU,OAAO,aAAa,IAAI,QAAQ;AACnD,KAAG,cAAc,CAAC,OAAO;AACzB,KAAG,MAAM,SAAS;AAClB,KAAG,YAAY,SAAS;AACxB,KAAG,SAAS;AACZ,KAAG,UAAU;;AAGf,sCAAqC,GAAG"}
1
+ {"version":3,"file":"session-manager-init.js","names":[],"sources":["../../../../src/agent/embedded/session-manager-init.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\n\ntype SessionHeaderEntry = { type: \"session\"; id?: string; cwd?: string };\ntype SessionMessageEntry = {\n type: \"message\";\n message?: {\n role?: string;\n stopReason?: string;\n usage?: Record<string, unknown>;\n };\n};\n\n/** pi-coding-agent auto-compaction calls `calculateContextTokens(usage)` without a null check. */\nconst EMPTY_ASSISTANT_USAGE = {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\n/**\n * Legacy xopc transcripts may omit `usage` on assistant rows; pi AgentSession crashes on turn end.\n */\nexport function repairAssistantUsageInSessionManager(sessionManager: unknown): void {\n const sm = sessionManager as { fileEntries?: Array<SessionHeaderEntry | SessionMessageEntry | { type: string }> };\n if (!Array.isArray(sm.fileEntries)) {\n return;\n }\n for (const entry of sm.fileEntries) {\n if (entry.type !== \"message\") {\n continue;\n }\n const msg = (entry as SessionMessageEntry).message;\n if (msg?.role !== \"assistant\") {\n continue;\n }\n if (msg.stopReason === \"aborted\" || msg.stopReason === \"error\") {\n continue;\n }\n if (!msg.usage || typeof msg.usage !== \"object\") {\n msg.usage = { ...EMPTY_ASSISTANT_USAGE };\n } else if (msg.usage.totalTokens === undefined) {\n const u = msg.usage;\n const input = typeof u.input === \"number\" ? u.input : 0;\n const output = typeof u.output === \"number\" ? u.output : 0;\n const cacheRead = typeof u.cacheRead === \"number\" ? u.cacheRead : 0;\n const cacheWrite = typeof u.cacheWrite === \"number\" ? u.cacheWrite : 0;\n msg.usage = {\n ...EMPTY_ASSISTANT_USAGE,\n ...u,\n input,\n output,\n cacheRead,\n cacheWrite,\n totalTokens: input + output + cacheRead + cacheWrite,\n };\n }\n }\n}\n\n/**\n * pi-coding-agent SessionManager persistence quirk:\n * - If the file exists but has no assistant message, SessionManager marks itself `flushed=true`\n * and will never persist the initial user message.\n * - If the file doesn't exist yet, SessionManager builds a new session in memory and flushes\n * header+user+assistant once the first assistant arrives (good).\n *\n * This normalizes the file/session state so the first user prompt is persisted before the first\n * assistant entry, even for pre-created session files.\n */\nexport async function prepareSessionManagerForRun(params: {\n sessionManager: unknown;\n sessionFile: string;\n hadSessionFile: boolean;\n sessionId: string;\n cwd: string;\n}): Promise<void> {\n const sm = params.sessionManager as {\n sessionId: string;\n flushed: boolean;\n fileEntries: Array<SessionHeaderEntry | SessionMessageEntry | { type: string }>;\n byId?: Map<string, unknown>;\n labelsById?: Map<string, unknown>;\n leafId?: string | null;\n };\n\n const header = sm.fileEntries.find((e): e is SessionHeaderEntry => e.type === \"session\");\n const hasAssistant = sm.fileEntries.some(\n (e) => e.type === \"message\" && (e as SessionMessageEntry).message?.role === \"assistant\",\n );\n\n if (!params.hadSessionFile && header) {\n header.id = params.sessionId;\n header.cwd = params.cwd;\n sm.sessionId = params.sessionId;\n return;\n }\n\n if (params.hadSessionFile && header && !hasAssistant) {\n // Remove the pre-created transcript so pi SessionManager can create it with O_EXCL\n // on the first assistant flush (pi-coding-agent 0.77+ uses open(..., \"wx\") there).\n try {\n await fs.unlink(params.sessionFile);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n throw err;\n }\n }\n sm.fileEntries = [header];\n sm.byId?.clear?.();\n sm.labelsById?.clear?.();\n sm.leafId = null;\n sm.flushed = false;\n }\n\n repairAssistantUsageInSessionManager(sm);\n}\n"],"mappings":";;;AAaA,MAAM,wBAAwB;CAC5B,OAAO;CACP,QAAQ;CACR,WAAW;CACX,YAAY;CACZ,aAAa;CACb,MAAM;EAAE,OAAO;EAAG,QAAQ;EAAG,WAAW;EAAG,YAAY;EAAG,OAAO;EAAG;CACrE;;;;AAKD,SAAgB,qCAAqC,gBAA+B;CAClF,MAAM,KAAK;AACX,KAAI,CAAC,MAAM,QAAQ,GAAG,YAAY,CAChC;AAEF,MAAK,MAAM,SAAS,GAAG,aAAa;AAClC,MAAI,MAAM,SAAS,UACjB;EAEF,MAAM,MAAO,MAA8B;AAC3C,MAAI,KAAK,SAAS,YAChB;AAEF,MAAI,IAAI,eAAe,aAAa,IAAI,eAAe,QACrD;AAEF,MAAI,CAAC,IAAI,SAAS,OAAO,IAAI,UAAU,SACrC,KAAI,QAAQ,EAAE,GAAG,uBAAuB;WAC/B,IAAI,MAAM,gBAAgB,KAAA,GAAW;GAC9C,MAAM,IAAI,IAAI;GACd,MAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;GACtD,MAAM,SAAS,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;GACzD,MAAM,YAAY,OAAO,EAAE,cAAc,WAAW,EAAE,YAAY;GAClE,MAAM,aAAa,OAAO,EAAE,eAAe,WAAW,EAAE,aAAa;AACrE,OAAI,QAAQ;IACV,GAAG;IACH,GAAG;IACH;IACA;IACA;IACA;IACA,aAAa,QAAQ,SAAS,YAAY;IAC3C;;;;;;;;;;;;;;AAeP,eAAsB,4BAA4B,QAMhC;CAChB,MAAM,KAAK,OAAO;CASlB,MAAM,SAAS,GAAG,YAAY,MAAM,MAA+B,EAAE,SAAS,UAAU;CACxF,MAAM,eAAe,GAAG,YAAY,MACjC,MAAM,EAAE,SAAS,aAAc,EAA0B,SAAS,SAAS,YAC7E;AAED,KAAI,CAAC,OAAO,kBAAkB,QAAQ;AACpC,SAAO,KAAK,OAAO;AACnB,SAAO,MAAM,OAAO;AACpB,KAAG,YAAY,OAAO;AACtB;;AAGF,KAAI,OAAO,kBAAkB,UAAU,CAAC,cAAc;AAGpD,MAAI;AACF,SAAM,GAAG,OAAO,OAAO,YAAY;WAC5B,KAAK;AAEZ,OADc,IAA8B,SAC/B,SACX,OAAM;;AAGV,KAAG,cAAc,CAAC,OAAO;AACzB,KAAG,MAAM,SAAS;AAClB,KAAG,YAAY,SAAS;AACxB,KAAG,SAAS;AACZ,KAAG,UAAU;;AAGf,sCAAqC,GAAG"}
@@ -9,10 +9,10 @@ import { convertMarkdownTables } from "../markdown/tables.js";
9
9
  import { buildCodeSpanIndex, createInlineCodeState } from "../markdown/code-spans.js";
10
10
  import { bundledChannelPlugins } from "../generated/bundled-channel-plugins.js";
11
11
  import "./plugins/bundled.js";
12
- import { getChannelPlugin, getChannelRegistryVersion, listChannelPlugins, syncChannelPluginsFromManager } from "./plugins/registry.js";
13
12
  import { getChannelDock, getDockForBuiltinChannel } from "./dock.js";
14
13
  import "./format.js";
15
14
  import { MessagePipeline, createEnvelopeTimestampHandler, createFilterCommandsHandler, createFilterEmptyHandler, createFilterSelfHandler, createPipeline, standardPreflightHandlers, standardProcessHandlers } from "./pipeline.js";
15
+ import { getChannelPlugin, getChannelRegistryVersion, listChannelPlugins, syncChannelPluginsFromManager } from "./plugins/registry.js";
16
16
  import { ChannelManager, createChannelManager } from "./manager.js";
17
17
  import { collectSetupWizardChannels } from "./setup-wizard-discovery.js";
18
18
  export { CHAT_CHANNEL_ORDER, ChannelManager, MessagePipeline, buildCodeSpanIndex, bundledChannelPlugins, chunkMarkdownIR, chunkText, collectSetupWizardChannels, compileAllowlist, convertMarkdownTables, createChannelManager, createEnvelopeTimestampHandler, createFilterCommandsHandler, createFilterEmptyHandler, createFilterSelfHandler, createInlineCodeState, createPipeline, evaluateAccess, findFenceSpanAt, getChannelDock, getChannelPlugin, getChannelRegistryVersion, getChatChannelMeta, getDockForBuiltinChannel, hasBotMention, isChatChannelId, isSafeFenceBreak, listChannelPlugins, listChatChannelMeta, markdownToIR, markdownToIRWithMeta, parseFenceSpans, parseFrontmatterBlock, removeBotMention, renderMarkdownWithMarkers, resolveAllowlistMatch, resolveAllowlistMatchSimple, resolveDmPolicy, resolveGroupPolicy, standardPreflightHandlers, standardProcessHandlers, syncChannelPluginsFromManager };
@@ -3,10 +3,10 @@ import { init_logger } from "../utils/logger.js";
3
3
  import { mergeTtsConfigFromAppConfig } from "../voice/tts/merge-config.js";
4
4
  import { maybeApplyTtsToPayload } from "../voice/tts/payload.js";
5
5
  import "./internal-outbound.js";
6
- import { syncChannelPluginsFromManager } from "./plugins/registry.js";
7
6
  import { ChannelHealthMonitor } from "./health-monitor.js";
8
7
  import { deliverOutboundMessage } from "./outbound/deliver.js";
9
8
  import { OutboundPersistStore } from "./outbound/persist-store.js";
9
+ import { syncChannelPluginsFromManager } from "./plugins/registry.js";
10
10
  import { CHANNEL_RESTART_POLICY, computeBackoff } from "./restart-policy.js";
11
11
  //#region src/channels/manager.ts
12
12
  init_logger();
@@ -2,8 +2,8 @@ import { init_paths, resolveConfigPath } from "../../config/paths.js";
2
2
  import { init_loader, loadConfig } from "../../config/loader.js";
3
3
  import { approveChannelPairingFromCli } from "../../channels/pairing/approve-cli.js";
4
4
  import { bundledChannelPlugins } from "../../generated/bundled-channel-plugins.js";
5
- import { formatExamples, register } from "../registry.js";
6
5
  import { getChannelPlugin, listChannelPlugins, syncChannelPluginsFromManager } from "../../channels/plugins/registry.js";
6
+ import { formatExamples, register } from "../registry.js";
7
7
  import { colors } from "../utils/colors.js";
8
8
  import { SETUP_EXIT } from "./setup-shared/types.js";
9
9
  import { emitOutcome } from "./setup-shared/output.js";