Skip to content

Conversation

@smirgol
Copy link

@smirgol smirgol commented Nov 29, 2025

Add support for Kokoro-FastAPI alongside the standard Kokoro implementation. Users can now toggle between standard and FastAPI (OpenAI-compatible) endpoints in settings.

Changes:

  • Add kokoro_api_type config key (default: 'standard')
  • Implement conditional API routing in kokoro.ts
  • Handle different voice list response formats for each API
  • Add API type selector to KokoroSettingsPage with help text
  • Integrate kokoroApiType state management in main settings

The implementation allows seamless switching between:

  • Standard Kokoro: POST /tts endpoint
  • Kokoro-FastAPI: POST /v1/audio/speech (OpenAI-compatible)

Summary by CodeRabbit

  • New Features

    • Added a settings option to choose between Standard Kokoro and Kokoro FastAPI for TTS.
    • Kokoro integration now supports multiple API types with unified voice listing and audio fetching.
    • Default Kokoro API type added to app configuration.
  • Bug Fixes

    • Persisted API type selection and ensured voice list refreshes when the API type changes.
    • Fixed a formatting typo in settings configuration.

✏️ Tip: You can customize this high-level summary in your review settings.

Add support for Kokoro-FastAPI alongside the standard Kokoro implementation.
Users can now toggle between standard and FastAPI endpoints in settings.

Changes:
- Add kokoro_api_type config key (default: 'standard')
- Implement conditional API routing in kokoro.ts
- Handle different voice list response formats for each API
- Add API type selector to KokoroSettingsPage with help text
- Integrate kokoroApiType state management in main settings

The implementation allows seamless switching between:
- Standard Kokoro: POST /tts endpoint
- Kokoro-FastAPI: POST /v1/audio/speech (OpenAI-compatible)
@vercel
Copy link

vercel bot commented Nov 29, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
amica Error Error Nov 29, 2025 6:08pm

@vercel
Copy link

vercel bot commented Nov 29, 2025

@smirgol is attempting to deploy a commit to the heyamica Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Nov 29, 2025

Walkthrough

Adds a Kokoro API type option to config and UI, threads a typed kokoroApiType state and setter through Settings into KokoroSettingsPage, and refactors Kokoro TTS/voice logic into typed apiConfigs with fetchAudio and fetchVoiceList supporting 'standard' and 'fastapi'.

Changes

Cohort / File(s) Summary
Config Default
src/utils/config.ts
Added kokoro_api_type default sourced from process.env.NEXT_PUBLIC_KOKORO_API_TYPE with fallback 'standard'.
Settings Shell
src/components/settings.tsx
Introduced kokoroApiType state initialized from config, passed kokoroApiType and setKokoroApiType into KokoroSettingsPage, and added kokoroApiType to a useEffect dependency list.
Kokoro Settings UI
src/components/settings/KokoroSettingsPage.tsx
Expanded props to accept kokoroApiType: KokoroApiType and setKokoroApiType; added an API Type select row; on change calls setKokoroApiType, persists via updateConfig("kokoro_api_type", value), marks settings updated, and updated useEffect deps to include kokoroApiType and kokoroUrl.
Kokoro API Abstraction
src/features/kokoro/kokoro.ts
Added exported `KokoroApiType = 'standard'

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SettingsUI as Settings Page
  participant KokoroModule as kokoro.ts
  participant KokoroAPI as External Kokoro API

  User->>SettingsUI: select Kokoro API Type
  SettingsUI->>SettingsUI: setKokoroApiType(value)
  SettingsUI->>SettingsUI: updateConfig("kokoro_api_type", value)
  SettingsUI->>KokoroModule: kokoroVoiceList()
  KokoroModule->>KokoroModule: choose apiConfigs[kokoroApiType]
  KokoroModule->>KokoroAPI: HTTP request (voices endpoint per config)
  KokoroAPI-->>KokoroModule: voices response
  KokoroModule->>SettingsUI: normalized voice list
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Inspect apiConfigs endpoints, request shapes, headers, and voice parsing in src/features/kokoro/kokoro.ts.
  • Verify KokoroApiType typing and prop threading in src/components/settings.tsx and src/components/settings/KokoroSettingsPage.tsx.
  • Check updateConfig("kokoro_api_type", ...), useEffect dependencies, ArrayBuffer handling in fetchAudio, and error messages.

Poem

🐇 I nibbled through the config trail,
Two Kokoro paths now set to sail,
I flipped the switch, the voices sang,
A tiny hop — the soundboards rang,
Code carrots crunch: hop, hop, hooray! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feature: Add FastAPI support with conditional endpoint routing' accurately reflects the main changes: introducing FastAPI support for Kokoro with conditional routing between standard and FastAPI endpoints.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca2415c and 9964dcc.

📒 Files selected for processing (4)
  • src/components/settings.tsx (2 hunks)
  • src/components/settings/KokoroSettingsPage.tsx (2 hunks)
  • src/features/kokoro/kokoro.ts (1 hunks)
  • src/utils/config.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/components/settings/KokoroSettingsPage.tsx (3)
src/components/settings/common.tsx (1)
  • FormRow (74-88)
src/i18n/index.ts (1)
  • t (26-26)
src/utils/config.ts (1)
  • updateConfig (157-172)
src/components/settings.tsx (1)
src/utils/config.ts (1)
  • config (140-155)
src/features/kokoro/kokoro.ts (1)
src/utils/config.ts (1)
  • config (140-155)
🔇 Additional comments (1)
src/utils/config.ts (1)

80-83: New kokoro_api_type default is consistent and safe

The new default key cleanly follows the existing config pattern and matches downstream usage in settings.tsx and kokoro.ts. No issues from a config perspective.

Add error checking for failed API responses in fetchVoiceList(). Add defensive fallback for unexpected kokoro_api_type config values. Fix type safety and voice list reactivity in KokoroSettingsPage.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/features/kokoro/kokoro.ts (1)

3-77: Kokoro API abstraction looks solid; consider tightening voice list typing (optional)

The ApiType + apiConfigs setup with a defensive default for kokoro_api_type and consistent response.ok checks in both fetchAudio and fetchVoiceList looks good and should make adding more variants straightforward.

If you want to push type-safety a bit further, you could narrow parseVoiceList away from any and model the FastAPI JSON shape explicitly (e.g. interface FastApiVoices { data: { id: string }[] }) so the parser returns a guaranteed { voices: string[] } rather than falling back to return data. That would line up with how you’re already using a discriminated ApiType union. Based on learnings, this matches your preference for stronger typing on external API boundaries.

src/components/settings/KokoroSettingsPage.tsx (1)

59-67: Narrow the select’s change event to preserve the ApiType union (optional)

Runtime behavior is fine, but React.ChangeEvent<any> plus an untyped value weakens the benefit of the ApiType union on the setter. You can keep things type-safe with:

-            <select
+            <select
               className="mt-2 block w-full rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6"
               value={kokoroApiType}
-              onChange={(event: React.ChangeEvent<any>) => {
-                const value = event.target.value;
-                setKokoroApiType(value);
+              onChange={(event: React.ChangeEvent<HTMLSelectElement>) => {
+                const value = event.target.value as ApiType;
+                setKokoroApiType(value);
                 updateConfig("kokoro_api_type", value);
                 setSettingsUpdated(true);
               }}

This keeps kokoroApiType strictly aligned with the union while still matching the actual option values. Based on learnings, this leans into the stronger typing you prefer.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9964dcc and 4916611.

📒 Files selected for processing (3)
  • src/components/settings.tsx (4 hunks)
  • src/components/settings/KokoroSettingsPage.tsx (3 hunks)
  • src/features/kokoro/kokoro.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-13T07:01:57.942Z
Learnt from: AlphaEcho11
Repo: semperai/amica PR: 213
File: src/features/chat/koboldAiChat.ts:0-0
Timestamp: 2025-08-13T07:01:57.942Z
Learning: AlphaEcho11 prefers strong typing and comprehensive error handling for Tauri invoke calls in frontend TypeScript code. They implemented an OpenAIResponse interface and wrapped invoke calls in try/catch blocks in openAiChat.ts, and expect similar patterns to be applied consistently across similar proxy call implementations.

Applied to files:

  • src/features/kokoro/kokoro.ts
🧬 Code graph analysis (3)
src/features/kokoro/kokoro.ts (2)
src/features/chat/chat.ts (1)
  • fetchAudio (638-707)
src/utils/config.ts (1)
  • config (140-155)
src/components/settings/KokoroSettingsPage.tsx (4)
src/features/kokoro/kokoro.ts (1)
  • ApiType (3-3)
src/components/settings/common.tsx (1)
  • FormRow (74-88)
src/i18n/index.ts (1)
  • t (26-26)
src/utils/config.ts (1)
  • updateConfig (157-172)
src/components/settings.tsx (1)
src/utils/config.ts (1)
  • config (140-155)
🔇 Additional comments (1)
src/components/settings.tsx (1)

265-311: Notification effect dependencies now correctly include Kokoro settings

Including kokoroUrl, kokoroVoice, kokoroApiType, and settingsUpdated in the dependencies (and fixing the double comma) ensures the “Successfully saved!” toast also fires when only Kokoro settings—especially the API type—change. This resolves the previous edge case without altering the effect’s semantics.

Comment on lines 139 to 141
const [kokoroUrl, setKokoroUrl] = useState(config("kokoro_url"));
const [kokoroApiType, setKokoroApiType] = useState(config("kokoro_api_type"));
const [kokoroVoice, setKokoroVoice] = useState(config("kokoro_voice"));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Type kokoroApiType state as ApiType and add a defensive default

Right now kokoroApiType is inferred as string:

const [kokoroApiType, setKokoroApiType] = useState(config("kokoro_api_type"));

but KokoroSettingsPage expects kokoroApiType: ApiType and setKokoroApiType: (key: ApiType) => void. This both undermines the union’s safety and is likely to trip the type checker.

You can align state with the ApiType union and mirror the defensive fallback you already use in kokoro.ts:

-import { KokoroSettingsPage } from "./settings/KokoroSettingsPage";
+import { KokoroSettingsPage } from "./settings/KokoroSettingsPage";
+import type { ApiType } from "@/features/kokoro/kokoro";
@@
-  const [kokoroUrl, setKokoroUrl] = useState(config("kokoro_url"));
-  const [kokoroApiType, setKokoroApiType] = useState(config("kokoro_api_type"));
+  const [kokoroUrl, setKokoroUrl] = useState(config("kokoro_url"));
+  const [kokoroApiType, setKokoroApiType] = useState<ApiType>(
+    config("kokoro_api_type") === "fastapi" ? "fastapi" : "standard"
+  );
   const [kokoroVoice, setKokoroVoice] = useState(config("kokoro_voice"));
@@
     case 'kokoro_settings':
       return <KokoroSettingsPage
         kokoroUrl={kokoroUrl}
         kokoroApiType={kokoroApiType}
         kokoroVoice={kokoroVoice}
         setKokoroVoice={setKokoroVoice}
         setKokoroUrl={setKokoroUrl}
         setKokoroApiType={setKokoroApiType}
         setSettingsUpdated={setSettingsUpdated}
         />

This keeps Settings’ local state consistent with the rest of the Kokoro code and prevents accidental invalid values from leaking into the UI. Based on learnings, this restores the strong typing boundary for this config.

Also applies to: 593-602

Make type name Kokoro-specific to avoid naming ambiguity with other backend APIs.
Return empty voices array instead of raw data when response shape is unexpected. Apply defensive validation to both standard and FastAPI parsers, ensuring consistent return type.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/features/kokoro/kokoro.ts (3)

3-41: Nice API‑type abstraction; consider tightening parseVoiceList typing

The KokoroApiType union plus apiConfigs map is a clean way to support multiple Kokoro backends and makes it easy to add more in the future. The only small gap is that parseVoiceList takes data: any; you could improve type‑safety by defining explicit response types for the standard and FastAPI shapes (or using unknown with runtime narrowing) so that the contract { voices: string[] } is enforced at the type level as well as at runtime. Not urgent, but it would further reduce “escape hatches” from your otherwise strongly typed surface.

Based on learnings, this aligns well with your preference for strong typing; parseVoiceList is just the one remaining any hotspot.


43-82: Defensive kokoro_api_type handling and aligned error checks look solid

Using rawType with a fallback to 'standard' avoids crashes from bad config and keeps behavior predictable, and checking res.ok in both fetchAudio and fetchVoiceList gives consistent, Kokoro‑specific failure semantics. One tiny nit: res.arrayBuffer() is already typed as Promise<ArrayBuffer> in modern lib.dom.d.ts, so if your TS lib target allows it you can likely drop the as any cast on Line 61 and keep the return type purely ArrayBuffer. If the cast is needed for your target, feel free to ignore this.


84-101: Optionally preserve original error when wrapping Kokoro failures

kokoro and kokoroVoiceList currently log and then throw a new Error("Kokoro TTS API Error"), which hides the original error object from callers (even though it’s in the console). If upstream code ever needs more diagnostic detail, you could either rethrow the original (throw e;) or wrap it with a cause where supported (e.g., new Error("Kokoro TTS API Error", { cause: e })). Not required for this PR, but worth considering if you later add richer error handling/UI.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4916611 and db42913.

📒 Files selected for processing (2)
  • src/components/settings/KokoroSettingsPage.tsx (3 hunks)
  • src/features/kokoro/kokoro.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-13T07:01:57.942Z
Learnt from: AlphaEcho11
Repo: semperai/amica PR: 213
File: src/features/chat/koboldAiChat.ts:0-0
Timestamp: 2025-08-13T07:01:57.942Z
Learning: AlphaEcho11 prefers strong typing and comprehensive error handling for Tauri invoke calls in frontend TypeScript code. They implemented an OpenAIResponse interface and wrapped invoke calls in try/catch blocks in openAiChat.ts, and expect similar patterns to be applied consistently across similar proxy call implementations.

Applied to files:

  • src/features/kokoro/kokoro.ts
🧬 Code graph analysis (2)
src/features/kokoro/kokoro.ts (1)
src/utils/config.ts (1)
  • config (140-155)
src/components/settings/KokoroSettingsPage.tsx (4)
src/features/kokoro/kokoro.ts (1)
  • KokoroApiType (3-3)
src/components/settings/common.tsx (1)
  • FormRow (74-88)
src/i18n/index.ts (1)
  • t (26-26)
src/utils/config.ts (1)
  • updateConfig (157-172)
🔇 Additional comments (2)
src/components/settings/KokoroSettingsPage.tsx (2)

6-24: Props and effect wiring now match Kokoro API type semantics

Importing KokoroApiType here and using it for both kokoroApiType and setKokoroApiType keeps the settings UI in lock‑step with the backend’s supported modes, and updating the useEffect dependency array to [kokoroApiType, kokoroUrl] ensures the voice list tracks the active API/URL instead of being fixed at mount time. This is a good, type‑safe clean‑up of the earlier behavior.

Also applies to: 28-45


57-77: Based on my analysis, I can confirm the technical validity of the review's suggestions through web search, but I cannot verify the actual implementation details in the codebase due to repository access issues. Here's what I can confirm:

Verified Information:

  • ✅ The typing suggestion (React.ChangeEvent<HTMLSelectElement>) is correct per React/TypeScript best practices
  • ✅ The voice selection concern (stale voice ID after API type switch) is a valid state management pattern that could cause failures
  • ⚠️ Cannot verify: Whether the current code actually has this issue or if voice reset logic is already implemented

Since I cannot directly inspect the codebase to confirm the current implementation or verify if these issues actually exist, I must mark this for manual verification:


Reset kokoroVoice when switching API types if the voice is unavailable in the new backend, and tighten onChange typing

When the user switches between Standard and FastAPI, the selected kokoroVoice may no longer exist in the new backend's voice list, causing TTS calls to fail even though the selector appears in-sync. After fetching the new voice list, verify that the current kokoroVoice is valid; if not, automatically reset it to a safe default (e.g., the first voice in the list) and persist via setKokoroVoice/updateConfig.

Additionally, narrow the select element's event typing:

onChange={(event: React.ChangeEvent<HTMLSelectElement>) => {
  const value = event.target.value as KokoroApiType;
  setKokoroApiType(value);
  updateConfig("kokoro_api_type", value);
  setSettingsUpdated(true);
}}

This maintains proper type safety and ensures only valid KokoroApiType values flow through the handler.

Add explicit type annotation to kokoroApiType useState and apply defensive fallback to ensure invalid config values default to 'standard', maintaining type safety across the component boundary.
Standard parser now handles {"voices":[...]} objects and bare [...] arrays. FastAPI parser handles both data.data (objects with id) and data.voices (string array) formats. Both default to empty array on unexpected format.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/features/kokoro/kokoro.ts (2)

49-68: Remove unnecessary type assertion.

Line 67 casts the ArrayBuffer result to any, but res.arrayBuffer() already returns Promise<ArrayBuffer>. The cast is redundant and weakens type safety.

Based on learnings, strong typing is preferred in this codebase.

Apply this diff:

-  return (await res.arrayBuffer()) as any;
+  return await res.arrayBuffer();

90-98: Consider preserving error context in exception handling (optional).

The catch block throws a generic error message, which discards the original error details. While the error is logged to console, including the original error message or cause in the thrown error would aid debugging.

One option:

   } catch (e) {
     console.error('ERROR', e);
-    throw new Error("Kokoro TTS API Error");
+    throw new Error(`Kokoro TTS API Error: ${e instanceof Error ? e.message : String(e)}`);
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 801eb7f and 3fbd01e.

📒 Files selected for processing (1)
  • src/features/kokoro/kokoro.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-13T07:01:57.942Z
Learnt from: AlphaEcho11
Repo: semperai/amica PR: 213
File: src/features/chat/koboldAiChat.ts:0-0
Timestamp: 2025-08-13T07:01:57.942Z
Learning: AlphaEcho11 prefers strong typing and comprehensive error handling for Tauri invoke calls in frontend TypeScript code. They implemented an OpenAIResponse interface and wrapped invoke calls in try/catch blocks in openAiChat.ts, and expect similar patterns to be applied consistently across similar proxy call implementations.

Applied to files:

  • src/features/kokoro/kokoro.ts
🧬 Code graph analysis (1)
src/features/kokoro/kokoro.ts (2)
src/features/chat/chat.ts (1)
  • fetchAudio (638-707)
src/utils/config.ts (1)
  • config (140-155)
🔇 Additional comments (3)
src/features/kokoro/kokoro.ts (3)

5-26: Clean API abstraction with good extensibility.

The apiConfigs pattern effectively decouples the two API variants and makes it straightforward to add additional implementations in the future. The defensive parsing in parseVoiceList for the standard API handles multiple response formats gracefully.


70-88: Good defensive programming and error handling.

The defensive defaulting for apiType and the response.ok check ensure robust behavior even with unexpected config values or API failures. The implementation is consistent with fetchAudio.


100-107: LGTM! Good error handling pattern.

The function correctly delegates to fetchVoiceList() and preserves the original error when re-throwing, which aids debugging.

@smirgol
Copy link
Author

smirgol commented Nov 29, 2025

Boy, that CodeRabbit thing surely is picky. :D

Validate voice entries in parseVoiceList before mapping, filtering out undefined/invalid entries. Remove unnecessary type assertion from arrayBuffer() call. Preserve original error context in exception messages for better debugging.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/features/kokoro/kokoro.ts (1)

58-60: Consider extracting the API type validation logic (optional).

The API type validation with defensive default appears in both fetchAudio and fetchVoiceList. Extracting it into a small helper function would reduce duplication and make future changes easier.

For example:

function getValidatedApiType(): KokoroApiType {
  const rawType = config("kokoro_api_type");
  return rawType === "fastapi" ? "fastapi" : "standard";
}

Then use it in both functions:

 async function fetchAudio(message: string): Promise<ArrayBuffer> {
-  const rawType = config("kokoro_api_type");
-  const apiType: KokoroApiType = rawType === "fastapi" ? "fastapi" : "standard";
+  const apiType = getValidatedApiType();
   const apiConfig = apiConfigs[apiType];
   // ...
 }

 async function fetchVoiceList(): Promise<{ voices: string[] }> {
-  const rawType = config("kokoro_api_type");
-  const apiType: KokoroApiType = rawType === "fastapi" ? "fastapi" : "standard";
+  const apiType = getValidatedApiType();
   const apiConfig = apiConfigs[apiType];
   // ...
 }

Also applies to: 79-80

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3fbd01e and 48bbfa1.

📒 Files selected for processing (1)
  • src/features/kokoro/kokoro.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-13T07:01:57.942Z
Learnt from: AlphaEcho11
Repo: semperai/amica PR: 213
File: src/features/chat/koboldAiChat.ts:0-0
Timestamp: 2025-08-13T07:01:57.942Z
Learning: AlphaEcho11 prefers strong typing and comprehensive error handling for Tauri invoke calls in frontend TypeScript code. They implemented an OpenAIResponse interface and wrapped invoke calls in try/catch blocks in openAiChat.ts, and expect similar patterns to be applied consistently across similar proxy call implementations.

Applied to files:

  • src/features/kokoro/kokoro.ts
🧬 Code graph analysis (1)
src/features/kokoro/kokoro.ts (2)
src/features/chat/chat.ts (1)
  • fetchAudio (638-707)
src/utils/config.ts (1)
  • config (140-155)
🔇 Additional comments (6)
src/features/kokoro/kokoro.ts (6)

3-4: Clean type definition.

The KokoroApiType union type is well-defined and provides clear type safety for API mode selection.


5-55: Excellent configuration abstraction with robust validation.

The apiConfigs map provides a clean, extensible structure for supporting multiple API variants. The parseVoiceList implementations include comprehensive validation that filters out invalid entries, successfully addressing previous review concerns about voice ID safety.


57-76: Well-structured with proper error handling.

The fetchAudio function correctly implements the defensive API type default and response validation, addressing previous review concerns. Error handling is consistent and informative.


78-96: Consistent implementation with proper error handling.

The fetchVoiceList function correctly implements response validation and defensive API type defaults, addressing previous review concerns. The structure mirrors fetchAudio for consistency.


98-106: LGTM!

Clean implementation with informative error handling. The enhanced error message includes the original error details, which aids debugging.


108-115: LGTM!

Clean delegation to fetchVoiceList with appropriate error handling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant