Skip to content

Celune 4.2.0#20

Open
celunah wants to merge 30 commits into
mainfrom
dev
Open

Celune 4.2.0#20
celunah wants to merge 30 commits into
mainfrom
dev

Conversation

@celunah

@celunah celunah commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Who said 3 months is too much? She needs to be good.

Summary by CodeRabbit

  • New Features

    • Added voice-conversion mode end-to-end: new VC tab/controls in the UI and WebUI, plus an audio conversion flow with pitch/f0 options.
    • Added REST support for POST /v1/convert, including proper sample-rate response headers.
    • Introduced extension event subscriptions via subscribe(...), enabling extensions to react to lifecycle/voice events.
    • Expanded Persona with emotion-aware state prompting and added broader app i18n.
  • Bug Fixes

    • Enforced VC-only conversion behavior and improved playback “idle” transitions and temp cleanup reliability.
  • Documentation / Chores

    • Updated README with an extensions guide, added i18n resources, and refreshed CI runtime/runtime messaging guidance.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

Celune 4.2.0 adds voice-conversion runtime support, typed extension events, Persona emotion prompting, Hugging Face cache configuration, and updated UI/API logging and command flows.

Changes

Unified runtime expansion

Layer / File(s) Summary
Docs, versioning, and runtime bootstrap
AGENTS.md, README.md, pyproject.toml, requirements.txt, launcher.c, scripts/build_nuitka.*, celune/__init__.py, celune/paths.py
CI guidance, extension docs, version pins, dependency lists, build guards, and Hugging Face runtime configuration are updated together.
Shared dataclasses and extension dispatch
celune/dataclasses/*, celune/typing/*, celune/extensions/*, celune/vc_backends/*, celune/cevoice.py
Typed event payloads, subscription dispatch, context overrides, voice-conversion backend interfaces, and protected CEVOICE temp-path handling are added and wired into exports.
Persona emotion and runtime flow
celune/persona/*, celune/constants.py, celune/analysis.py
Persona emotion analysis, prompt structure changes, pinned remote-code revisions, and related Persona runtime and identity handling changes are added together.
Core runtime, API, and audio conversion
celune/api.py, celune/celune.py, celune/pipeline.py, celune/backends/*, tests/support.py
Uploaded audio decoding, /v1/convert, voice-conversion routing, backend cleanup, stream timing metadata, and VC-mode runtime state are added across runtime and backend code.
UI, CLI, and runtime logging
celune/ui/*, celune/utils.py, celune/entrypoint.py, celune/chroma.py, celune/colors.py, celune/updater.py, celune/terminal.py
Terminal escapes, log capture, command hot-reload flows, and supporting utility and type adjustments are updated together.
Tests and examples
tests/*, extensions/test.py
Tests cover VC mode, hot reload, extension events, Persona emotion, API conversion, UI logging, and runtime path configuration.

Possibly related PRs

  • celunah/celune#7: Shares backend cleanup and backend-compatibility changes with this PR, including celune/backends/base.py and the BackendError to FileNotFoundError shift.
  • celunah/celune#15: Touches the same celune/api.py audio upload path that this PR extends with voice-conversion decoding and /v1/convert.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 I hop through logs and prompt-strings bright,
New voices dance through cache and light.
Events now whisper, typed and clear,
Reloads roll back with nary a tear.
I nibble a carrot and cheer, “Hooray!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 79.24% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s main change: a Celune 4.2.0 release/version bump.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Nitpick comments (3)
tests/test_backends_and_extensions.py (1)

972-977: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Assert override delegation arguments explicitly.

This test currently enters with_backend("mini") / with_cevoice("nova") but does not verify the override hooks received those exact values (Line 999-Line 1002). Add call assertions so future regressions in delegation are caught.

Suggested test tightening
     def setUp(self) -> None:
+        self.backend_override = mock.Mock(
+            side_effect=lambda backend_name: contextlib.nullcontext(
+                cast(Celune, SimpleNamespace())
+            )
+        )
+        self.cevoice_override = mock.Mock(
+            side_effect=lambda bundle: contextlib.nullcontext(
+                cast(Celune, SimpleNamespace())
+            )
+        )
         self.logs: list[tuple[str, str]] = []
         self.dev_logs: list[tuple[str, str]] = []
@@
-            backend_override=lambda backend_name: contextlib.nullcontext(
-                cast(Celune, SimpleNamespace())
-            ),
-            cevoice_override=lambda bundle: contextlib.nullcontext(
-                cast(Celune, SimpleNamespace())
-            ),
+            backend_override=self.backend_override,
+            cevoice_override=self.cevoice_override,
         )
@@
         with extension.with_backend("mini"):
             pass
         with extension.with_cevoice("nova"):
             pass
+        self.backend_override.assert_called_once_with("mini")
+        self.cevoice_override.assert_called_once_with("nova")

Also applies to: 999-1002

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_backends_and_extensions.py` around lines 972 - 977, The test is
not verifying that the override hooks receive the correct delegation arguments.
Replace the lambda functions for backend_override and cevoice_override with call
assertion objects (such as unittest.mock.Mock or similar) that will capture the
arguments passed to them, then add assertions after the with_backend("mini") and
with_cevoice("nova") calls to verify these mocks were called with the expected
argument values to catch future regressions in delegation.
extensions/test.py (1)

7-9: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add concrete event payload types to subscribed handlers.

Typing the event parameters here keeps the example aligned with the typed event contract the extension API is introducing.

Proposed patch
 import celune
 from celune import CeluneExtension
+from celune.dataclasses.events import ReadyEvent, VoiceChangedEvent
 from celune.utils import discard
@@
-    def on_ready(self, event) -> None:
+    def on_ready(self, event: ReadyEvent) -> None:
@@
-    def on_voice_changed(self, event) -> None:
+    def on_voice_changed(self, event: VoiceChangedEvent) -> None:

As per coding guidelines, avoid broad types and prefer concrete, meaningful types in Python signatures.

Also applies to: 18-18, 52-52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extensions/test.py` around lines 7 - 9, Replace the broad or untyped event
parameters in the subscribed event handlers with concrete event payload types.
Locate the handler functions at the indicated line numbers (likely decorated
with event subscription patterns) and replace any generic event parameter types
(such as Any or untyped event) with the specific, concrete event payload types
that match the typed event contract expected by the extension API. Ensure you
import any necessary concrete event types from the celune module if they are not
already imported.

Source: Coding guidelines

tests/test_pipeline.py (1)

1434-1447: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Assert the default identity is absent here.

This test can still pass if a custom pack named Celune inherits the default Celune identity fields, because it only checks the name label. Add negative assertions like the non-default pack test above.

Proposed test tightening
         self.assertIn("Celune:", prompt)
         self.assertIn("You are Celune", prompt)
+        self.assertNotIn("Gender: female", prompt)
+        self.assertNotIn("The speaker uses a more confident", prompt)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_pipeline.py` around lines 1434 - 1447, The test
test_named_celune_custom_pack_does_not_use_default_identity currently only
verifies positive assertions that the name labels are present, but does not
verify that default identity fields are actually absent from the custom pack.
Add negative assertions using assertNotIn to check that the default Celune
identity fields that should not be inherited are not present in the prompt
variable, similar to the pattern used in the non-default pack test mentioned in
the review.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@celune/api.py`:
- Around line 1909-1910: The `/v1/convert` route contains a blocking synchronous
call to celune.convert_audio() inside an async function which stalls the event
loop and delays other requests. Similarly, the `/v1/sfx` route at line 1849
calls the blocking celune.play_audio() method with the same issue. Move both of
these blocking operations off the event loop by wrapping them in an executor
call (such as loop.run_in_executor() or asyncio.to_thread()) so they run in a
thread pool instead of blocking the async event loop.

In `@celune/celune.py`:
- Around line 498-503: The _cleanup_residual_temp_data method calls
temp_dir.iterdir() without verifying that the directory exists first, causing a
FileNotFoundError on fresh installations. Add a guard clause at the beginning of
the method to check if temp_dir.exists() before attempting to iterate over its
contents, and return early if the directory does not exist.
- Around line 1788-1800: After loading the new model with
self.backend.load_model(new_model_name), the self.model_name attribute is not
updated to reflect the newly loaded model, causing it to remain stale. Add a
line after the model loading statement to update self.model_name to the
new_model_name value so that subsequent voice switches correctly identify the
current model and saved metadata reflects the correct model name.

In `@celune/entrypoint.py`:
- Around line 971-973: The ANSI title initialization block with the if
runtime.supports_ansi() check and subsequent sys.stdout.write/flush calls is
currently positioned outside the startup try block, which means any failures in
writing to stdout will bypass error handling and crash the startup sequence.
Move this entire block inside the startup try block (or alternatively guard it
with contextlib.suppress) to ensure that output stream failures are properly
caught and handled by the existing startup error handling mechanism.

In `@celune/extensions/manager.py`:
- Around line 388-392: The handler assignment to
self._event_registrations[owner_key] at line 388 does not clean up previously
registered handlers for the same owner_key before replacing them, causing old
callbacks to remain active and fire multiple times when autoload() or handler
registration runs again. Before assigning the new handlers list to
self._event_registrations[owner_key], check if handlers already exist for that
owner_key and properly unsubscribe or clean them up to prevent callback leaks
and duplicates.
- Around line 113-117: The unregister_all() method only unregisters extensions
but does not clean up module-level subscriptions that are registered under
module:* owner keys, leaving stale handlers active. After unregistering all
extensions in the loop, also clear or unregister any module-level handlers to
ensure complete cleanup of all auto-registered handlers and fully honor the
"unregister all" contract.

In `@celune/paths.py`:
- Around line 133-137: The portable-cache configuration is incomplete. In
addition to setting _HF_HOME_ENV and _HF_HUB_CACHE_ENV in the compiled/forced
branch shown in the diff, you need to also set TRANSFORMERS_CACHE to
default_transformers_cache. Add a similar conditional check after the
_HF_HUB_CACHE_ENV block that checks if TRANSFORMERS_CACHE is not in os.environ
and sets it to the default_transformers_cache variable that was computed
earlier, ensuring all three cache paths are properly configured.

In `@celune/persona/impl.py`:
- Line 250: The current check in the return statement at line 250 only validates
that voice_bundle_is_default is true, but this applies Celune defaults
(age/gender) to any character with a default voice bundle, not just Celune
itself. Add character gating to the condition by checking both that
voice_bundle_is_default is true AND that the engine's character/identity is
specifically Celune (likely by checking an additional engine attribute that
identifies the character as Celune) to ensure Celune defaults are only applied
when the character is actually Celune.

In `@celune/pipeline.py`:
- Around line 1471-1476: The exception handling in the loader.materialize() call
silently catches all exceptions and sets target_references to an empty tuple
without any logging or error reporting. Instead of silently dropping the
failure, add logging to record when loader.materialize() fails, including the
actual error details. Additionally, consider whether the voice conversion
feature requires these references to function properly with the current backend,
and if so, return None from the function to prevent silent behavioral changes
rather than continuing with empty target_references.

In `@celune/ui/app.py`:
- Around line 364-365: The refresh method in the _RefreshableWidget Protocol has
a return type annotation of object, which is too broad. Examine where the
refresh method is implemented or used throughout the codebase to determine what
specific type it should actually return, then replace the object return type
annotation with the more specific and narrower type that reflects the actual
usage. This will strengthen the type guarantees for this Protocol definition.

In `@celune/utils.py`:
- Line 843: The current implementation in the return statement that translates
special characters and removes double spaces using a single replace call is
incomplete because it only handles pairs of spaces. When the translated text
contains 3 or more consecutive spaces, the single replace pass will leave double
spaces behind. Fix this by using a regex-based approach with the re module to
replace one or more consecutive spaces with a single space in one pass, or
alternatively use a loop to repeatedly call replace until no double spaces
remain in the text.

In `@launcher.c`:
- Line 687: The printfe call at line 687 contains unescaped percent signs in the
format string "%PATH%" which are interpreted as format specifiers, causing
undefined behavior. To fix this, escape each percent sign by doubling it,
changing "%PATH%" to "%%PATH%%" in the format string argument to printfe. This
ensures the percent signs are printed literally rather than being parsed as
format specifiers.

In `@tests/test_celune_core.py`:
- Around line 911-923: The test needs to capture the value of
celune._reload_pending at the time each signal is recorded to properly verify
the ordering contract. Modify the record_signal function to append
celune._reload_pending to the tuple along with signal_type, celune.cur_state,
and celune.loaded, update the signal_states list type annotation from tuple[str,
str, bool] to tuple[str, str, bool, bool] to reflect the 4-element tuples, and
update the assertion that checks signal_states to include the expected
_reload_pending value for each recorded signal state.

In `@tests/test_runtime_paths.py`:
- Around line 181-201: The assertion checking
os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] in the
test_huggingface_runtime_disables_global_progress_and_logs method is located
after the with block exits, meaning it validates the restored environment rather
than the patched one. Move this assertion inside the with block, after the
configure_huggingface_runtime() call, so it checks the environment while the
mock.patch.dict context is still active.

---

Nitpick comments:
In `@extensions/test.py`:
- Around line 7-9: Replace the broad or untyped event parameters in the
subscribed event handlers with concrete event payload types. Locate the handler
functions at the indicated line numbers (likely decorated with event
subscription patterns) and replace any generic event parameter types (such as
Any or untyped event) with the specific, concrete event payload types that match
the typed event contract expected by the extension API. Ensure you import any
necessary concrete event types from the celune module if they are not already
imported.

In `@tests/test_backends_and_extensions.py`:
- Around line 972-977: The test is not verifying that the override hooks receive
the correct delegation arguments. Replace the lambda functions for
backend_override and cevoice_override with call assertion objects (such as
unittest.mock.Mock or similar) that will capture the arguments passed to them,
then add assertions after the with_backend("mini") and with_cevoice("nova")
calls to verify these mocks were called with the expected argument values to
catch future regressions in delegation.

In `@tests/test_pipeline.py`:
- Around line 1434-1447: The test
test_named_celune_custom_pack_does_not_use_default_identity currently only
verifies positive assertions that the name labels are present, but does not
verify that default identity fields are actually absent from the custom pack.
Add negative assertions using assertNotIn to check that the default Celune
identity fields that should not be inherited are not present in the prompt
variable, similar to the pattern used in the non-default pack test mentioned in
the review.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6a4bf112-5886-4e11-8af4-6b43caa7bd84

📥 Commits

Reviewing files that changed from the base of the PR and between fa13554 and 53bb99c.

📒 Files selected for processing (68)
  • AGENTS.md
  • README.md
  • celune/__init__.py
  • celune/api.py
  • celune/backends/__init__.py
  • celune/backends/base.py
  • celune/backends/dotstts.py
  • celune/backends/mini.py
  • celune/backends/qwen3.py
  • celune/backends/voxcpm2.py
  • celune/celune.py
  • celune/cevoice.py
  • celune/chroma.py
  • celune/colors.py
  • celune/constants.py
  • celune/dataclasses/__init__.py
  • celune/dataclasses/celune.py
  • celune/dataclasses/events.py
  • celune/dataclasses/extensions.py
  • celune/dataclasses/persona.py
  • celune/dataclasses/pipeline.py
  • celune/dataclasses/properties.py
  • celune/entrypoint.py
  • celune/extensions/base.py
  • celune/extensions/events.py
  • celune/extensions/manager.py
  • celune/paths.py
  • celune/persona/emotion.py
  • celune/persona/impl.py
  • celune/persona/memory.py
  • celune/persona/prompts.py
  • celune/persona/runtime.py
  • celune/pipeline.py
  • celune/terminal.py
  • celune/typing/__init__.py
  • celune/typing/analysis.py
  • celune/typing/backends.py
  • celune/typing/celune.py
  • celune/typing/cevoice.py
  • celune/typing/common.py
  • celune/typing/events.py
  • celune/typing/persona.py
  • celune/typing/pipeline.py
  • celune/ui/app.py
  • celune/ui/commands.py
  • celune/ui/terminal.py
  • celune/updater.py
  • celune/utils.py
  • celune/vc_backends/__init__.py
  • celune/vc_backends/base.py
  • celune/vc_backends/passthrough.py
  • celune/vram.py
  • extensions/test.py
  • launcher.c
  • requirements.txt
  • tests/support.py
  • tests/test_api_audio.py
  • tests/test_api_webui.py
  • tests/test_backends_and_extensions.py
  • tests/test_celune_core.py
  • tests/test_cevoice.py
  • tests/test_extension_events.py
  • tests/test_package_api.py
  • tests/test_persona_emotion.py
  • tests/test_persona_memory.py
  • tests/test_pipeline.py
  • tests/test_runtime_and_ui_commands.py
  • tests/test_runtime_paths.py

Comment thread celune/api.py Outdated
Comment thread celune/celune.py
Comment thread celune/celune.py
Comment thread celune/entrypoint.py Outdated
Comment thread celune/extensions/manager.py
Comment thread celune/ui/app.py
Comment on lines +364 to +365
class _RefreshableWidget(Protocol):
def refresh(self, *args, **kwargs) -> object:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Narrow the Protocol.refresh typing instead of returning object.

At Line 365, -> object is broader than needed and weakens local type guarantees.

Proposed fix
         class _RefreshableWidget(Protocol):
-            def refresh(self, *args, **kwargs) -> object:
+            def refresh(self, layout: bool = False) -> None:
                 """Refresh one widget in place.

As per coding guidelines, "Avoid using broad types like Any, object or T, unless the function explicitly requires a broad type."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class _RefreshableWidget(Protocol):
def refresh(self, *args, **kwargs) -> object:
class _RefreshableWidget(Protocol):
def refresh(self, layout: bool = False) -> None:
"""Refresh one widget in place.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/ui/app.py` around lines 364 - 365, The refresh method in the
_RefreshableWidget Protocol has a return type annotation of object, which is too
broad. Examine where the refresh method is implemented or used throughout the
codebase to determine what specific type it should actually return, then replace
the object return type annotation with the more specific and narrower type that
reflects the actual usage. This will strengthen the type guarantees for this
Protocol definition.

Source: Coding guidelines

Comment thread celune/utils.py Outdated
Comment thread launcher.c Outdated
Comment thread tests/test_celune_core.py Outdated
Comment thread tests/test_runtime_paths.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pyproject.toml`:
- Line 129: The pytest configuration in pyproject.toml is globally silencing all
DeprecationWarnings which masks both internal and external deprecation signals.
Remove or replace the filterwarnings setting that contains
"ignore::DeprecationWarning" with a more targeted approach that only suppresses
specific known third-party deprecations, allowing first-party deprecation
warnings to surface and help catch regressions during release validation.

In `@scripts/build_nuitka.ps1`:
- Around line 11-20: The process termination logic is brittle because
Stop-Process will fail with an error if the specified process does not exist,
since ErrorActionPreference defaults to Stop. Modify both Stop-Process calls
(for celune and celune-bin process names) to include the ErrorAction
SilentlyContinue parameter, so that the script continues gracefully even if
either process is not running. Additionally, consider checking for both celune
and celune-bin processes in the initial condition to ensure both are terminated
if either exists.

In `@scripts/build_nuitka.sh`:
- Around line 14-18: The pkill commands for celune and celune-bin will cause the
build script to fail under set -euo pipefail if the processes don't exist
(returning non-zero exit code), and the pattern-based matching with pgrep and
pkill is too broad and can match unintended process names. Guard both pkill
invocations with || true to prevent script failure when processes aren't
running, and use the -x flag with pkill to match exact process names only
instead of pattern matching, ensuring only the intended celune and celune-bin
processes are terminated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2254934e-f9a5-4228-906c-a99f0fffcbbd

📥 Commits

Reviewing files that changed from the base of the PR and between 53bb99c and 705e439.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (29)
  • celune/analysis.py
  • celune/api.py
  • celune/backends/dotstts.py
  • celune/backends/mini.py
  • celune/backends/qwen3.py
  • celune/backends/voxcpm2.py
  • celune/celune.py
  • celune/constants.py
  • celune/dataclasses/pipeline.py
  • celune/entrypoint.py
  • celune/extensions/manager.py
  • celune/paths.py
  • celune/persona/impl.py
  • celune/persona/runtime.py
  • celune/pipeline.py
  • celune/ui/app.py
  • celune/ui/terminal.py
  • celune/utils.py
  • extensions/test.py
  • launcher.c
  • pyproject.toml
  • scripts/build_nuitka.ps1
  • scripts/build_nuitka.sh
  • tests/test_backends_and_extensions.py
  • tests/test_celune_core.py
  • tests/test_persona_api.py
  • tests/test_pipeline.py
  • tests/test_runtime_and_ui_commands.py
  • tests/test_runtime_paths.py
✅ Files skipped from review due to trivial changes (1)
  • launcher.c
🚧 Files skipped from review as they are similar to previous changes (12)
  • celune/entrypoint.py
  • extensions/test.py
  • celune/utils.py
  • tests/test_runtime_paths.py
  • celune/api.py
  • tests/test_celune_core.py
  • tests/test_backends_and_extensions.py
  • tests/test_runtime_and_ui_commands.py
  • celune/extensions/manager.py
  • celune/pipeline.py
  • celune/celune.py
  • tests/test_pipeline.py

Comment thread pyproject.toml Outdated
Comment thread scripts/build_nuitka.ps1 Outdated
Comment thread scripts/build_nuitka.sh Outdated
@github-actions

Copy link
Copy Markdown

Detected potential slop in commit 09c7210e2098c6a245fb2d41406c98dc6afb3b53.

The following jobs have failed:

  • Windows Launcher Build failed

Please check the logs and unslop your code: https://github.com/celunah/celune/actions/runs/28101889312

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/build_nuitka.ps1`:
- Line 16: The conditional in build_nuitka.ps1 has a stray leading plus sign
before the if statement, which makes the PowerShell script invalid. Remove the
extra plus in the existingProcesses check and keep the condition as a normal if
block so the script can execute correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 552ce4a9-3e9f-49c9-80d1-24e5b0c1b781

📥 Commits

Reviewing files that changed from the base of the PR and between 705e439 and 3e89cbc.

📒 Files selected for processing (3)
  • pyproject.toml
  • scripts/build_nuitka.ps1
  • scripts/build_nuitka.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/build_nuitka.sh

Comment thread scripts/build_nuitka.ps1 Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
celune/entrypoint.py (1)

974-976: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Startup window-title text is still hardcoded English.

Every other user-facing string in this path was localized, but the OSC title "{APP_NAME} is starting up..." remains an inline literal. Consider routing it through string(...) for consistency with the rest of the i18n migration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/entrypoint.py` around lines 974 - 976, The startup window title in the
runtime.supports_ansi() block is still an inline English literal, so route the
`"{APP_NAME} is starting up..."` text through `string(...)` to match the rest of
the i18n migration. Update the logic around the `sys.stdout.write` call in
`entrypoint.py` so the OSC title uses the localized string helper while
preserving `APP_NAME` interpolation and the existing ANSI behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@celune/entrypoint.py`:
- Line 1182: The exception display fallback is unreachable because the current
print in entrypoint.py always treats exc as truthy. Update the handling around
the print(exc or string("cli.no_error_description")) call to use the exception’s
string form instead, so an empty exception message can fall back to the
localized no-error description. Keep the change localized to the
exception-printing path in the entrypoint logic.
- Around line 1259-1265: The start/run command path in entrypoint.py reads
args[1] without checking whether it exists, which causes an IndexError when the
command is invoked with no extra arguments. Update the args[0] in {"start",
"run"} branch to guard the args[1] access with a length check before comparing
against "--verbose" and "-v", following the same safe pattern used by the
verbose handling logic, so the existing invalid-argument flow can run when no
trailing flag is present.

---

Nitpick comments:
In `@celune/entrypoint.py`:
- Around line 974-976: The startup window title in the runtime.supports_ansi()
block is still an inline English literal, so route the `"{APP_NAME} is starting
up..."` text through `string(...)` to match the rest of the i18n migration.
Update the logic around the `sys.stdout.write` call in `entrypoint.py` so the
OSC title uses the localized string helper while preserving `APP_NAME`
interpolation and the existing ANSI behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f9bbf4b7-b2d3-4f5d-a124-92af064e3cf6

📥 Commits

Reviewing files that changed from the base of the PR and between 3e89cbc and fc5b536.

📒 Files selected for processing (12)
  • celune/api.py
  • celune/celune.py
  • celune/entrypoint.py
  • celune/extensions/manager.py
  • celune/i18n.py
  • celune/pipeline.py
  • celune/ui/app.py
  • celune/ui/commands.py
  • celune/ui/headless.py
  • scripts/build_nuitka.ps1
  • tests/test_namedays_i18n_updater.py
  • tests/test_pipeline.py
🚧 Files skipped from review as they are similar to previous changes (8)
  • scripts/build_nuitka.ps1
  • celune/extensions/manager.py
  • celune/ui/commands.py
  • celune/api.py
  • tests/test_pipeline.py
  • celune/pipeline.py
  • celune/ui/app.py
  • celune/celune.py

Comment thread celune/entrypoint.py Outdated
Comment thread celune/entrypoint.py
@celunah

celunah commented Jun 24, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

Copy link
Copy Markdown

Detected potential slop in commit 045db36f03459e4e78237e8ba83bd150f580ffe3.

The following jobs have failed:

  • Anti AI Slop & Vibe Coding Checks failed

Please check the logs and unslop your code: https://github.com/celunah/celune/actions/runs/28249201157

because all Celune backends being grouped into their own optional package groups, we have to explicitly tell CI to install the whole thing

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
celune/backends/tts/dotstts.py (1)

95-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the compatible-bundle failure message.

This backend availability error is likely surfaced to users when DotTTS cannot start, so the new English text should be moved into the localization database and read via string(...). As per coding guidelines, “Do not use raw string literals for user-facing text.”

Also applies to: 115-120

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/backends/tts/dotstts.py` around lines 95 - 100, The DotTTS backend
availability error in the loader check uses a raw English user-facing message
instead of the localization system. Move the compatible-bundle failure text used
in the `custom_assert` path inside the DotTTS initialization logic into the
localization database and retrieve it with `string(...)` so the message is no
longer hardcoded. Update the corresponding user-facing failure in `dotstts`
(including the related assertion block mentioned in the review) to use the
localized string instead of a literal.

Source: Coding guidelines

celune/backends/tts/voxcpm2.py (1)

87-92: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the compatible-bundle failure message.

This VoxCPM2 startup failure can be user-visible, so keep it in Celune’s localization database rather than hardcoding English in the backend. As per coding guidelines, “Make sure new user-facing strings ... are added to Celune's localization string database instead of being hardcoded in English.”

Also applies to: 107-112

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/backends/tts/voxcpm2.py` around lines 87 - 92, The VoxCPM2 startup
failure message is user-facing and should not be hardcoded in English. Update
the error handling in the VoxCPM2 backend around the loader assertion and the
matching path at the later startup check to pull the message from Celune’s
localization string database instead of embedding the literal text. Use the
existing VoxCPM2 backend symbols and the same localized message key consistently
wherever this compatible-bundle failure is raised.

Source: Coding guidelines

tests/test_api_webui.py (1)

590-593: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep new WebUI assertions locale-driven.

These tests still lock English UI copy into expected output ("voice conversion mode", "TTS", "VC", "CTRL+R toggle recording"). Prefer asserting the corresponding string(...) values, adding localization keys first if needed, so the tests enforce the i18n contract instead of bypassing it. As per coding guidelines, new user-facing strings must be added to the localization string database and called via string(...); based on learnings, do not hardcode strings when the repository already defines them.

Also applies to: 595-605, 635-640

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_api_webui.py` around lines 590 - 593, The WebUI tests are
hardcoding English UI text instead of validating the i18n contract. Update the
affected assertions in the test suite to use the corresponding string(...)
lookups rather than literals like voice conversion mode, TTS, VC, and CTRL+R
toggle recording, and add any missing localization keys to the string database
first if they do not already exist. Keep the checks anchored to the same test
helpers and assertions so the intent stays the same while making the tests
locale-driven.

Sources: Coding guidelines, Learnings

🧹 Nitpick comments (6)
AGENTS.md (1)

115-115: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hyphenate compound modifier: "user-facing strings"

"user facing" should be "user-facing" because it modifies "strings" as a compound adjective.

-Make sure to only modify user facing strings (both normal and dev mode strings), don't change anything internal.
+Make sure to only modify user-facing strings (both normal and dev mode strings), don't change anything internal.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` at line 115, The issue is a wording fix in the user-facing
guidance text: change “user facing strings” to “user-facing strings” while
keeping all internal behavior and non-string content unchanged. Update only the
affected string in AGENTS.md, and make sure both the normal and dev mode string
guidance still say that only user-facing strings should be modified.
celune/backends/vc/seedvc.py (1)

172-179: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the placeholder return documentation.

Result of this function. reads like generated placeholder text; please replace it with the actual sample-rate contract. Based on learnings, “After each task, run scripts/update_docstrings.py and then replace placeholder docstrings with proper documentation while preserving format.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/backends/vc/seedvc.py` around lines 172 - 179, The output_sample_rate
property in SeedVC still has placeholder return documentation. Update its
docstring so the Returns section clearly states the actual sample-rate contract
for the backend’s default Seed-VC mode, matching the 44100/22050 behavior based
on f0_condition. Preserve the existing docstring format while replacing the
generic placeholder text.

Source: Learnings

celune/celune.py (1)

727-733: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace placeholder docstring.

is_voice_conversion_mode still carries the generated placeholder (Result of this function.); document what it returns.

Based on learnings: "replace placeholder docstrings with proper documentation while preserving format."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/celune.py` around lines 727 - 733, The docstring on
is_voice_conversion_mode still uses the generated placeholder text, so replace
it with a real description of what the method returns. Keep the existing
docstring structure in Celune.is_voice_conversion_mode, but document that it
returns whether the instance is currently in voice conversion mode, and remove
the placeholder “Result of this function.” wording.

Source: Learnings

celune/dsp.py (1)

87-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the placeholder docstring with real documentation.

The pitch_shift_audio docstring still contains auto-generated placeholders (Value for \audio`., Result of this function.`) instead of describing the arguments and return value.

Based on learnings: "After each task, run scripts/update_docstrings.py and then replace placeholder docstrings with proper documentation while preserving format."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/dsp.py` around lines 87 - 96, The pitch_shift_audio docstring still
uses auto-generated placeholder text, so replace it with real documentation that
explains what audio, sample_rate, and n_steps represent and what the function
returns. Update the docstring in pitch_shift_audio to preserve the existing
format while removing the placeholder phrases like “Value for `audio`.” and
“Result of this function.”, then run scripts/update_docstrings.py as required
after making the change.

Source: Learnings

celune/ui/resources.py (1)

157-158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Localize the new footer hint.

"CTRL+R toggle recording" is a newly added user-facing string. As per coding guidelines, new user-facing strings should be added to Celune's localization database and rendered via string("key_name") rather than hardcoded in English. The neighboring footer hints are currently hardcoded too, but since this PR is centered on i18n, the new string ideally follows the same string(...) path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/ui/resources.py` around lines 157 - 158, The new footer hint in the
resources footer logic is hardcoded English text, so it should be moved through
Celune’s localization path. Update the branch in the footer-building code that
checks input_mode for voice_conversion to use the existing string(...) helper
with a new localization key instead of appending the literal text, and add that
key to the localization database so the hint is rendered in the same i18n flow
as other user-facing strings.

Source: Coding guidelines

scripts/run_ci.py (1)

22-35: 🎯 Functional Correctness | 🔵 Trivial

Replace the unordered set with a tuple to guarantee deterministic matching order.

The function _agent_permission_marker documents that it returns the "first matching marker", but _AGENT_ERROR_MARKERS is defined as a set. In Python, sets are unordered, so the iteration order is arbitrary and non-deterministic. This violates the function's contract when multiple error markers exist in the output.

Change the definition to a tuple or list to preserve the intended priority sequence.

Proposed fix
-_AGENT_ERROR_MARKERS = {
+_AGENT_ERROR_MARKERS = (
     "Access is denied",
     "Permission denied",
     "Operation not permitted",
-}
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/run_ci.py` around lines 22 - 35, The permission-marker matching in
_agent_permission_marker is using an unordered set, so “first match” is
non-deterministic when multiple markers appear. Change _AGENT_ERROR_MARKERS from
a set to an ordered sequence (tuple or list) and keep the existing iteration in
_agent_permission_marker so the marker priority is deterministic and matches the
documented behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@celune/backends/tts/__init__.py`:
- Around line 73-82: The backend resolution errors in the backend loader are
using hardcoded English user-facing strings instead of localized text. Update
the backend-selection path in the backend factory/initializer to add new
localization entries for the unknown-backend and invalid-backend-type messages,
then call them through string("key_name", **kwargs) in place of the literal
ValueError and TypeError text. Keep the existing logic in the backend
import/dispatch flow intact while switching the messages to Celune’s
localization database.

In `@celune/backends/vc/seedvc.py`:
- Around line 72-82: The Seed-VC backend is ignoring the configured pitch shift
because `SeedVCBackend.convert()` always passes a zero value instead of the
instance’s configured setting. Update the `convert` path (and any related call
sites around the `SeedVCBackend` pitch handling) so it either forwards the
effective `pitch_shift` from `self.pitch_shift` or removes the backend option
entirely if pitch shifting is intentionally handled elsewhere; do not leave the
configuration field unused.
- Around line 135-147: The Seed-VC install/load/validation messages are still
hardcoded in English and should be localized; update the user-facing strings in
SeedVCWrapper and related helper paths to use string(...) lookups instead of
literals. Add the new messages to lang/en.json, then replace the messages shown
during backend setup, wrapper loading, and conversion failure in the SeedVC
backend methods (including _load_wrapper_type and _get_wrapper) with their i18n
keys so they flow through Celune’s localization system.

In `@celune/ui/app.py`:
- Around line 1593-1601: `_stop_vc_recording_stream` is shutting down the
`sounddevice.InputStream` while `self._vc_recording_lock` is still held, which
can deadlock with the callback path that also acquires the same lock. Refactor
`_stop_vc_recording_stream` to only clear state and return the `stream`
reference, then move the `stream.stop()`/`stream.close()` work into the callers
(`toggle_vc_recording`, `_cancel_vc_recording`,
`_stop_vc_recording_for_feedback`) after the `with self._vc_recording_lock:`
block has exited, or via a dedicated `_shutdown_vc_stream` helper called outside
the lock.

---

Outside diff comments:
In `@celune/backends/tts/dotstts.py`:
- Around line 95-100: The DotTTS backend availability error in the loader check
uses a raw English user-facing message instead of the localization system. Move
the compatible-bundle failure text used in the `custom_assert` path inside the
DotTTS initialization logic into the localization database and retrieve it with
`string(...)` so the message is no longer hardcoded. Update the corresponding
user-facing failure in `dotstts` (including the related assertion block
mentioned in the review) to use the localized string instead of a literal.

In `@celune/backends/tts/voxcpm2.py`:
- Around line 87-92: The VoxCPM2 startup failure message is user-facing and
should not be hardcoded in English. Update the error handling in the VoxCPM2
backend around the loader assertion and the matching path at the later startup
check to pull the message from Celune’s localization string database instead of
embedding the literal text. Use the existing VoxCPM2 backend symbols and the
same localized message key consistently wherever this compatible-bundle failure
is raised.

In `@tests/test_api_webui.py`:
- Around line 590-593: The WebUI tests are hardcoding English UI text instead of
validating the i18n contract. Update the affected assertions in the test suite
to use the corresponding string(...) lookups rather than literals like voice
conversion mode, TTS, VC, and CTRL+R toggle recording, and add any missing
localization keys to the string database first if they do not already exist.
Keep the checks anchored to the same test helpers and assertions so the intent
stays the same while making the tests locale-driven.

---

Nitpick comments:
In `@AGENTS.md`:
- Line 115: The issue is a wording fix in the user-facing guidance text: change
“user facing strings” to “user-facing strings” while keeping all internal
behavior and non-string content unchanged. Update only the affected string in
AGENTS.md, and make sure both the normal and dev mode string guidance still say
that only user-facing strings should be modified.

In `@celune/backends/vc/seedvc.py`:
- Around line 172-179: The output_sample_rate property in SeedVC still has
placeholder return documentation. Update its docstring so the Returns section
clearly states the actual sample-rate contract for the backend’s default Seed-VC
mode, matching the 44100/22050 behavior based on f0_condition. Preserve the
existing docstring format while replacing the generic placeholder text.

In `@celune/celune.py`:
- Around line 727-733: The docstring on is_voice_conversion_mode still uses the
generated placeholder text, so replace it with a real description of what the
method returns. Keep the existing docstring structure in
Celune.is_voice_conversion_mode, but document that it returns whether the
instance is currently in voice conversion mode, and remove the placeholder
“Result of this function.” wording.

In `@celune/dsp.py`:
- Around line 87-96: The pitch_shift_audio docstring still uses auto-generated
placeholder text, so replace it with real documentation that explains what
audio, sample_rate, and n_steps represent and what the function returns. Update
the docstring in pitch_shift_audio to preserve the existing format while
removing the placeholder phrases like “Value for `audio`.” and “Result of this
function.”, then run scripts/update_docstrings.py as required after making the
change.

In `@celune/ui/resources.py`:
- Around line 157-158: The new footer hint in the resources footer logic is
hardcoded English text, so it should be moved through Celune’s localization
path. Update the branch in the footer-building code that checks input_mode for
voice_conversion to use the existing string(...) helper with a new localization
key instead of appending the literal text, and add that key to the localization
database so the hint is rendered in the same i18n flow as other user-facing
strings.

In `@scripts/run_ci.py`:
- Around line 22-35: The permission-marker matching in _agent_permission_marker
is using an unordered set, so “first match” is non-deterministic when multiple
markers appear. Change _AGENT_ERROR_MARKERS from a set to an ordered sequence
(tuple or list) and keep the existing iteration in _agent_permission_marker so
the marker priority is deterministic and matches the documented behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad2e8bca-c124-46ef-bb25-b39e924e3303

📥 Commits

Reviewing files that changed from the base of the PR and between fc5b536 and 2c475af.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (43)
  • .github/workflows/ci.yml
  • AGENTS.md
  • celune/api.py
  • celune/backends/__init__.py
  • celune/backends/tts/__init__.py
  • celune/backends/tts/base.py
  • celune/backends/tts/dotstts.py
  • celune/backends/tts/mini.py
  • celune/backends/tts/qwen3.py
  • celune/backends/tts/voxcpm2.py
  • celune/backends/vc/__init__.py
  • celune/backends/vc/base.py
  • celune/backends/vc/passthrough.py
  • celune/backends/vc/seedvc.py
  • celune/celune.py
  • celune/constants.py
  • celune/dataclasses/celune.py
  • celune/dataclasses/pipeline.py
  • celune/dsp.py
  • celune/entrypoint.py
  • celune/i18n.py
  • celune/lang/en.json
  • celune/modeling.py
  • celune/pipeline.py
  • celune/typing/celune.py
  • celune/ui/app.py
  • celune/ui/commands.py
  • celune/ui/resources.py
  • celune/ui/terminal.py
  • celune/ui/theme.py
  • celune/vram.py
  • default_config.yaml
  • pyproject.toml
  • scripts/run_ci.py
  • tests/support.py
  • tests/test_api_audio.py
  • tests/test_api_webui.py
  • tests/test_backends_and_extensions.py
  • tests/test_backends_mini.py
  • tests/test_celune_core.py
  • tests/test_modeling.py
  • tests/test_pipeline.py
  • tests/test_runtime_and_ui_commands.py
✅ Files skipped from review due to trivial changes (6)
  • default_config.yaml
  • celune/backends/init.py
  • celune/ui/theme.py
  • celune/lang/en.json
  • tests/test_backends_mini.py
  • .github/workflows/ci.yml
🚧 Files skipped from review as they are similar to previous changes (8)
  • celune/dataclasses/pipeline.py
  • celune/typing/celune.py
  • celune/entrypoint.py
  • tests/test_backends_and_extensions.py
  • celune/constants.py
  • tests/test_pipeline.py
  • celune/pipeline.py
  • celune/api.py

Comment thread celune/backends/tts/__init__.py Outdated
Comment thread celune/backends/vc/seedvc.py
Comment thread celune/backends/vc/seedvc.py Outdated
Comment thread celune/ui/app.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@celune/backends/vc/seedvc.py`:
- Line 236: The Seed-VC conversion path is applying pitch shift from the backend
state twice because the shared VC pipeline already handles the request/engine
pitch shift after conversion. Update the Seed-VC call site in the backend
conversion flow to use the request-level backend pitch value instead of
self.pitch_shift, and rely on the pipeline to pass 0 when post-processing owns
the shift; use the Seed-VC conversion method and its pitch_shift argument to
locate the change.

In `@celune/config.py`:
- Around line 16-17: AudioDeviceDirection is currently too broad and allows
invalid values to silently fall into the output branch. Update the typing in
celune/config.py to restrict AudioDeviceDirection to only the supported
direction values, and add validation in the code that branches on the direction
so unsupported inputs are rejected before the device lookup logic in the
relevant query function executes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a385d0f4-69b9-478a-8966-ef718f95e347

📥 Commits

Reviewing files that changed from the base of the PR and between 2c475af and 152b850.

📒 Files selected for processing (22)
  • AGENTS.md
  • celune/api.py
  • celune/backends/tts/__init__.py
  • celune/backends/tts/dotstts.py
  • celune/backends/tts/voxcpm2.py
  • celune/backends/vc/seedvc.py
  • celune/celune.py
  • celune/config.py
  • celune/dataclasses/pipeline.py
  • celune/dsp.py
  • celune/lang/en.json
  • celune/pipeline.py
  • celune/ui/app.py
  • celune/ui/resources.py
  • default_config.yaml
  • scripts/run_ci.py
  • tests/test_api_webui.py
  • tests/test_backends_and_extensions.py
  • tests/test_celune_core.py
  • tests/test_config_and_utils.py
  • tests/test_pipeline.py
  • tests/test_runtime_and_ui_commands.py
✅ Files skipped from review due to trivial changes (3)
  • celune/lang/en.json
  • default_config.yaml
  • tests/test_config_and_utils.py
🚧 Files skipped from review as they are similar to previous changes (15)
  • celune/dsp.py
  • scripts/run_ci.py
  • celune/dataclasses/pipeline.py
  • celune/backends/tts/init.py
  • celune/backends/tts/voxcpm2.py
  • celune/backends/tts/dotstts.py
  • AGENTS.md
  • tests/test_pipeline.py
  • tests/test_celune_core.py
  • celune/celune.py
  • tests/test_runtime_and_ui_commands.py
  • celune/api.py
  • celune/pipeline.py
  • celune/ui/app.py
  • tests/test_backends_and_extensions.py

Comment thread celune/backends/vc/seedvc.py Outdated
Comment thread celune/config.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
celune/entrypoint.py (1)

1274-1285: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate every trailing start/run flag, not just args[1].

celune start --test --bogus currently launches instead of returning EXIT_UNKNOWN_ARGS, because only the first extra token is checked while the rest of args[1:] is still consumed.

Suggested fix
     elif args[0] in {"start", "run"}:
-        if len(args) > 1:
-            if args[1] not in {"--verbose", "-v", "--test", "-t"}:
-                print(string("cli.invalid_argument"))
-                print()
-                print(
-                    string("cli.start_usage", program=resolved_argv[0], command=args[0])
-                )
-                print(string("cli.start_description", app_name=APP_NAME))
-                sys.exit(EXIT_CODES.EXIT_UNKNOWN_ARGS.value)
+        allowed_args = {"--verbose", "-v", "--test", "-t"}
+        if any(arg not in allowed_args for arg in args[1:]):
+            print(string("cli.invalid_argument"))
+            print()
+            print(
+                string("cli.start_usage", program=resolved_argv[0], command=args[0])
+            )
+            print(string("cli.start_description", app_name=APP_NAME))
+            sys.exit(EXIT_CODES.EXIT_UNKNOWN_ARGS.value)
         verbose = any(arg in {"--verbose", "-v"} for arg in args[1:])
         testing = any(arg in {"--test", "-t"} for arg in args[1:])
         start(verbose=verbose, testing=testing)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/entrypoint.py` around lines 1274 - 1285, The argument validation in
the CLI entrypoint only checks args[1], so extra trailing flags after start/run
can slip through. Update the validation logic in the entrypoint flow that calls
start(verbose=..., testing=...) to scan every token in args[1:] and reject any
unrecognized flag before computing verbose and testing, preserving the existing
valid flags set and EXIT_UNKNOWN_ARGS behavior.
♻️ Duplicate comments (1)
celune/entrypoint.py (1)

980-985: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep the UI test-mode startup inside the guarded startup path.

This branch now runs before the existing try, so failures from _load_ui_test_backend(), runtime.Celune(...), or ui.run() bypass the normal startup recovery and exit handling.

Suggested fix
 def start(verbose: bool = False, testing: bool = False) -> None:
@@
     runtime = _load_runtime()
-    if testing:
-        ui = runtime.CeluneUI()
-        celune = runtime.Celune(config={}, backend=_load_ui_test_backend())
-        ui.celune = celune
-        ui.run()
-        sys.exit(EXIT_CODES.EXIT_SUCCESS.value)
-
     try:
+        if testing:
+            ui = runtime.CeluneUI()
+            celune = runtime.Celune(config={}, backend=_load_ui_test_backend())
+            ui.celune = celune
+            ui.run()
+            sys.exit(EXIT_CODES.EXIT_SUCCESS.value)
         if runtime.supports_ansi():
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@celune/entrypoint.py` around lines 980 - 985, The UI test-mode startup in the
`testing` branch is now executing outside the guarded startup flow, so move it
back under the existing `try` path in `entrypoint.py` alongside the normal
startup logic. Keep the `_load_ui_test_backend()`, `runtime.Celune(...)`,
`ui.run()`, and `sys.exit(...)` calls within that guarded block so any failures
are handled by the same startup recovery and exit handling as the rest of the
`main` startup sequence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@celune/entrypoint.py`:
- Around line 1274-1285: The argument validation in the CLI entrypoint only
checks args[1], so extra trailing flags after start/run can slip through. Update
the validation logic in the entrypoint flow that calls start(verbose=...,
testing=...) to scan every token in args[1:] and reject any unrecognized flag
before computing verbose and testing, preserving the existing valid flags set
and EXIT_UNKNOWN_ARGS behavior.

---

Duplicate comments:
In `@celune/entrypoint.py`:
- Around line 980-985: The UI test-mode startup in the `testing` branch is now
executing outside the guarded startup flow, so move it back under the existing
`try` path in `entrypoint.py` alongside the normal startup logic. Keep the
`_load_ui_test_backend()`, `runtime.Celune(...)`, `ui.run()`, and
`sys.exit(...)` calls within that guarded block so any failures are handled by
the same startup recovery and exit handling as the rest of the `main` startup
sequence.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 144541a8-9880-4876-99b2-56b3b7b8d822

📥 Commits

Reviewing files that changed from the base of the PR and between 152b850 and 35e31fb.

📒 Files selected for processing (15)
  • celune/api.py
  • celune/backends/tts/base.py
  • celune/backends/vc/base.py
  • celune/backends/vc/seedvc.py
  • celune/celune.py
  • celune/config.py
  • celune/entrypoint.py
  • celune/lang/en.json
  • celune/pipeline.py
  • celune/runtime.py
  • celune/ui/app.py
  • tests/support.py
  • tests/test_backends_and_extensions.py
  • tests/test_main_doctor.py
  • tests/test_runtime_and_ui_commands.py
✅ Files skipped from review due to trivial changes (1)
  • celune/lang/en.json
🚧 Files skipped from review as they are similar to previous changes (11)
  • celune/backends/vc/base.py
  • tests/support.py
  • celune/config.py
  • celune/backends/tts/base.py
  • celune/backends/vc/seedvc.py
  • tests/test_backends_and_extensions.py
  • tests/test_runtime_and_ui_commands.py
  • celune/api.py
  • celune/pipeline.py
  • celune/celune.py
  • celune/ui/app.py

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