voice-mode 2.24.0__py3-none-any.whl → 2.25.0__py3-none-any.whl
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.
- voice_mode/__version__.py +1 -1
- voice_mode/cli.py +49 -25
- voice_mode/config.py +14 -5
- voice_mode/frontend/.next/BUILD_ID +1 -1
- voice_mode/frontend/.next/app-build-manifest.json +5 -5
- voice_mode/frontend/.next/build-manifest.json +3 -3
- voice_mode/frontend/.next/next-minimal-server.js.nft.json +1 -1
- voice_mode/frontend/.next/next-server.js.nft.json +1 -1
- voice_mode/frontend/.next/prerender-manifest.json +1 -1
- voice_mode/frontend/.next/required-server-files.json +1 -1
- voice_mode/frontend/.next/server/app/_not-found/page.js +1 -1
- voice_mode/frontend/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- voice_mode/frontend/.next/server/app/_not-found.html +1 -1
- voice_mode/frontend/.next/server/app/_not-found.rsc +1 -1
- voice_mode/frontend/.next/server/app/api/connection-details/route.js +2 -2
- voice_mode/frontend/.next/server/app/favicon.ico/route.js +2 -2
- voice_mode/frontend/.next/server/app/index.html +1 -1
- voice_mode/frontend/.next/server/app/index.rsc +2 -2
- voice_mode/frontend/.next/server/app/page.js +2 -2
- voice_mode/frontend/.next/server/app/page_client-reference-manifest.js +1 -1
- voice_mode/frontend/.next/server/chunks/994.js +2 -2
- voice_mode/frontend/.next/server/middleware-build-manifest.js +1 -1
- voice_mode/frontend/.next/server/next-font-manifest.js +1 -1
- voice_mode/frontend/.next/server/next-font-manifest.json +1 -1
- voice_mode/frontend/.next/server/pages/404.html +1 -1
- voice_mode/frontend/.next/server/pages/500.html +1 -1
- voice_mode/frontend/.next/server/server-reference-manifest.json +1 -1
- voice_mode/frontend/.next/standalone/.next/BUILD_ID +1 -1
- voice_mode/frontend/.next/standalone/.next/app-build-manifest.json +5 -5
- voice_mode/frontend/.next/standalone/.next/build-manifest.json +3 -3
- voice_mode/frontend/.next/standalone/.next/prerender-manifest.json +1 -1
- voice_mode/frontend/.next/standalone/.next/required-server-files.json +1 -1
- voice_mode/frontend/.next/standalone/.next/server/app/_not-found/page.js +1 -1
- voice_mode/frontend/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- voice_mode/frontend/.next/standalone/.next/server/app/_not-found.html +1 -1
- voice_mode/frontend/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- voice_mode/frontend/.next/standalone/.next/server/app/api/connection-details/route.js +2 -2
- voice_mode/frontend/.next/standalone/.next/server/app/favicon.ico/route.js +2 -2
- voice_mode/frontend/.next/standalone/.next/server/app/index.html +1 -1
- voice_mode/frontend/.next/standalone/.next/server/app/index.rsc +2 -2
- voice_mode/frontend/.next/standalone/.next/server/app/page.js +2 -2
- voice_mode/frontend/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- voice_mode/frontend/.next/standalone/.next/server/chunks/994.js +2 -2
- voice_mode/frontend/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
- voice_mode/frontend/.next/standalone/.next/server/next-font-manifest.js +1 -1
- voice_mode/frontend/.next/standalone/.next/server/next-font-manifest.json +1 -1
- voice_mode/frontend/.next/standalone/.next/server/pages/404.html +1 -1
- voice_mode/frontend/.next/standalone/.next/server/pages/500.html +1 -1
- voice_mode/frontend/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- voice_mode/frontend/.next/standalone/server.js +1 -1
- voice_mode/frontend/.next/static/chunks/app/layout-5675f418c42e0ae3.js +1 -0
- voice_mode/frontend/.next/static/chunks/app/{page-24f60cf4d3e53975.js → page-dbb3615cf25cdc16.js} +1 -1
- voice_mode/frontend/.next/static/chunks/{main-app-da1905c275f65c31.js → main-app-d25858d98b1d322b.js} +1 -1
- voice_mode/frontend/.next/trace +43 -43
- voice_mode/frontend/.next/types/app/api/connection-details/route.ts +1 -1
- voice_mode/frontend/.next/types/app/layout.ts +1 -1
- voice_mode/frontend/.next/types/app/page.ts +1 -1
- {voice_mode-2.24.0.dist-info → voice_mode-2.25.0.dist-info}/METADATA +1 -1
- {voice_mode-2.24.0.dist-info → voice_mode-2.25.0.dist-info}/RECORD +63 -63
- voice_mode/frontend/.next/static/chunks/app/layout-8ed5d7ac133f6c04.js +0 -1
- /voice_mode/frontend/.next/static/{YK51QIYKloFzSoCqqpa3Q → SsR9zBdw0hd2LN3Vo9tP_}/_buildManifest.js +0 -0
- /voice_mode/frontend/.next/static/{YK51QIYKloFzSoCqqpa3Q → SsR9zBdw0hd2LN3Vo9tP_}/_ssgManifest.js +0 -0
- {voice_mode-2.24.0.dist-info → voice_mode-2.25.0.dist-info}/WHEEL +0 -0
- {voice_mode-2.24.0.dist-info → voice_mode-2.25.0.dist-info}/entry_points.txt +0 -0
voice_mode/__version__.py
CHANGED
voice_mode/cli.py
CHANGED
@@ -6,7 +6,6 @@ import sys
|
|
6
6
|
import os
|
7
7
|
import warnings
|
8
8
|
import click
|
9
|
-
from .server import main as voice_mode_main
|
10
9
|
|
11
10
|
# Suppress known deprecation warnings for better user experience
|
12
11
|
# These apply to both CLI commands and MCP server operation
|
@@ -47,6 +46,7 @@ def voice_mode_main_cli(ctx, debug):
|
|
47
46
|
if ctx.invoked_subcommand is None:
|
48
47
|
# No subcommand - run MCP server
|
49
48
|
# Note: warnings are already suppressed at module level unless debug is enabled
|
49
|
+
from .server import main as voice_mode_main
|
50
50
|
voice_mode_main()
|
51
51
|
|
52
52
|
|
@@ -74,36 +74,14 @@ def livekit():
|
|
74
74
|
pass
|
75
75
|
|
76
76
|
|
77
|
-
#
|
78
|
-
from voice_mode.tools.service import (
|
79
|
-
status_service, start_service, stop_service, restart_service,
|
80
|
-
enable_service, disable_service, view_logs, update_service_files
|
81
|
-
)
|
82
|
-
|
83
|
-
# Import install/uninstall functions
|
84
|
-
from voice_mode.tools.services.kokoro.install import kokoro_install
|
85
|
-
from voice_mode.tools.services.kokoro.uninstall import kokoro_uninstall
|
86
|
-
from voice_mode.tools.services.whisper.install import whisper_install
|
87
|
-
from voice_mode.tools.services.whisper.uninstall import whisper_uninstall
|
88
|
-
from voice_mode.tools.services.whisper.download_model import download_model
|
89
|
-
from voice_mode.tools.services.livekit.install import livekit_install
|
90
|
-
from voice_mode.tools.services.livekit.uninstall import livekit_uninstall
|
91
|
-
from voice_mode.tools.services.livekit.frontend import livekit_frontend_start, livekit_frontend_stop, livekit_frontend_status, livekit_frontend_open, livekit_frontend_logs, livekit_frontend_install
|
92
|
-
|
93
|
-
# Import configuration management functions
|
94
|
-
from voice_mode.tools.configuration_management import update_config, list_config_keys
|
95
|
-
|
96
|
-
# Import diagnostic functions - extract the actual async functions from the tools
|
97
|
-
from voice_mode.tools.diagnostics import voice_mode_info
|
98
|
-
from voice_mode.tools.devices import check_audio_devices
|
99
|
-
from voice_mode.tools.voice_registry import voice_registry
|
100
|
-
from voice_mode.tools.dependencies import check_audio_dependencies
|
77
|
+
# Service functions are imported lazily in their respective command handlers to improve startup time
|
101
78
|
|
102
79
|
|
103
80
|
# Kokoro service commands
|
104
81
|
@kokoro.command()
|
105
82
|
def status():
|
106
83
|
"""Show Kokoro service status."""
|
84
|
+
from voice_mode.tools.service import status_service
|
107
85
|
result = asyncio.run(status_service("kokoro"))
|
108
86
|
click.echo(result)
|
109
87
|
|
@@ -111,6 +89,7 @@ def status():
|
|
111
89
|
@kokoro.command()
|
112
90
|
def start():
|
113
91
|
"""Start Kokoro service."""
|
92
|
+
from voice_mode.tools.service import start_service
|
114
93
|
result = asyncio.run(start_service("kokoro"))
|
115
94
|
click.echo(result)
|
116
95
|
|
@@ -118,6 +97,7 @@ def start():
|
|
118
97
|
@kokoro.command()
|
119
98
|
def stop():
|
120
99
|
"""Stop Kokoro service."""
|
100
|
+
from voice_mode.tools.service import stop_service
|
121
101
|
result = asyncio.run(stop_service("kokoro"))
|
122
102
|
click.echo(result)
|
123
103
|
|
@@ -125,6 +105,7 @@ def stop():
|
|
125
105
|
@kokoro.command()
|
126
106
|
def restart():
|
127
107
|
"""Restart Kokoro service."""
|
108
|
+
from voice_mode.tools.service import restart_service
|
128
109
|
result = asyncio.run(restart_service("kokoro"))
|
129
110
|
click.echo(result)
|
130
111
|
|
@@ -132,6 +113,7 @@ def restart():
|
|
132
113
|
@kokoro.command()
|
133
114
|
def enable():
|
134
115
|
"""Enable Kokoro service to start at boot/login."""
|
116
|
+
from voice_mode.tools.service import enable_service
|
135
117
|
result = asyncio.run(enable_service("kokoro"))
|
136
118
|
click.echo(result)
|
137
119
|
|
@@ -139,6 +121,7 @@ def enable():
|
|
139
121
|
@kokoro.command()
|
140
122
|
def disable():
|
141
123
|
"""Disable Kokoro service from starting at boot/login."""
|
124
|
+
from voice_mode.tools.service import disable_service
|
142
125
|
result = asyncio.run(disable_service("kokoro"))
|
143
126
|
click.echo(result)
|
144
127
|
|
@@ -147,6 +130,7 @@ def disable():
|
|
147
130
|
@click.option('--lines', '-n', default=50, help='Number of log lines to show')
|
148
131
|
def logs(lines):
|
149
132
|
"""View Kokoro service logs."""
|
133
|
+
from voice_mode.tools.service import view_logs
|
150
134
|
result = asyncio.run(view_logs("kokoro", lines))
|
151
135
|
click.echo(result)
|
152
136
|
|
@@ -154,6 +138,7 @@ def logs(lines):
|
|
154
138
|
@kokoro.command("update-service-files")
|
155
139
|
def kokoro_update_service_files():
|
156
140
|
"""Update Kokoro service files to latest version."""
|
141
|
+
from voice_mode.tools.service import update_service_files
|
157
142
|
result = asyncio.run(update_service_files("kokoro"))
|
158
143
|
click.echo(result)
|
159
144
|
|
@@ -193,6 +178,7 @@ def health():
|
|
193
178
|
@click.option('--auto-enable/--no-auto-enable', default=None, help='Enable service at boot/login')
|
194
179
|
def install(install_dir, port, force, version, auto_enable):
|
195
180
|
"""Install kokoro-fastapi TTS service."""
|
181
|
+
from voice_mode.tools.services.kokoro.install import kokoro_install
|
196
182
|
result = asyncio.run(kokoro_install.fn(
|
197
183
|
install_dir=install_dir,
|
198
184
|
port=port,
|
@@ -227,6 +213,7 @@ def install(install_dir, port, force, version, auto_enable):
|
|
227
213
|
@click.confirmation_option(prompt='Are you sure you want to uninstall Kokoro?')
|
228
214
|
def uninstall(remove_models, remove_all_data):
|
229
215
|
"""Uninstall kokoro-fastapi service and optionally remove data."""
|
216
|
+
from voice_mode.tools.services.kokoro.uninstall import kokoro_uninstall
|
230
217
|
result = asyncio.run(kokoro_uninstall.fn(
|
231
218
|
remove_models=remove_models,
|
232
219
|
remove_all_data=remove_all_data
|
@@ -260,6 +247,7 @@ def uninstall(remove_models, remove_all_data):
|
|
260
247
|
@whisper.command()
|
261
248
|
def status():
|
262
249
|
"""Show Whisper service status."""
|
250
|
+
from voice_mode.tools.service import status_service
|
263
251
|
result = asyncio.run(status_service("whisper"))
|
264
252
|
click.echo(result)
|
265
253
|
|
@@ -267,6 +255,7 @@ def status():
|
|
267
255
|
@whisper.command()
|
268
256
|
def start():
|
269
257
|
"""Start Whisper service."""
|
258
|
+
from voice_mode.tools.service import start_service
|
270
259
|
result = asyncio.run(start_service("whisper"))
|
271
260
|
click.echo(result)
|
272
261
|
|
@@ -274,6 +263,7 @@ def start():
|
|
274
263
|
@whisper.command()
|
275
264
|
def stop():
|
276
265
|
"""Stop Whisper service."""
|
266
|
+
from voice_mode.tools.service import stop_service
|
277
267
|
result = asyncio.run(stop_service("whisper"))
|
278
268
|
click.echo(result)
|
279
269
|
|
@@ -281,6 +271,7 @@ def stop():
|
|
281
271
|
@whisper.command()
|
282
272
|
def restart():
|
283
273
|
"""Restart Whisper service."""
|
274
|
+
from voice_mode.tools.service import restart_service
|
284
275
|
result = asyncio.run(restart_service("whisper"))
|
285
276
|
click.echo(result)
|
286
277
|
|
@@ -288,6 +279,7 @@ def restart():
|
|
288
279
|
@whisper.command()
|
289
280
|
def enable():
|
290
281
|
"""Enable Whisper service to start at boot/login."""
|
282
|
+
from voice_mode.tools.service import enable_service
|
291
283
|
result = asyncio.run(enable_service("whisper"))
|
292
284
|
click.echo(result)
|
293
285
|
|
@@ -295,6 +287,7 @@ def enable():
|
|
295
287
|
@whisper.command()
|
296
288
|
def disable():
|
297
289
|
"""Disable Whisper service from starting at boot/login."""
|
290
|
+
from voice_mode.tools.service import disable_service
|
298
291
|
result = asyncio.run(disable_service("whisper"))
|
299
292
|
click.echo(result)
|
300
293
|
|
@@ -303,6 +296,7 @@ def disable():
|
|
303
296
|
@click.option('--lines', '-n', default=50, help='Number of log lines to show')
|
304
297
|
def logs(lines):
|
305
298
|
"""View Whisper service logs."""
|
299
|
+
from voice_mode.tools.service import view_logs
|
306
300
|
result = asyncio.run(view_logs("whisper", lines))
|
307
301
|
click.echo(result)
|
308
302
|
|
@@ -310,6 +304,7 @@ def logs(lines):
|
|
310
304
|
@whisper.command("update-service-files")
|
311
305
|
def whisper_update_service_files():
|
312
306
|
"""Update Whisper service files to latest version."""
|
307
|
+
from voice_mode.tools.service import update_service_files
|
313
308
|
result = asyncio.run(update_service_files("whisper"))
|
314
309
|
click.echo(result)
|
315
310
|
|
@@ -350,6 +345,7 @@ def health():
|
|
350
345
|
@click.option('--auto-enable/--no-auto-enable', default=None, help='Enable service at boot/login')
|
351
346
|
def install(install_dir, model, use_gpu, force, version, auto_enable):
|
352
347
|
"""Install whisper.cpp STT service with automatic system detection."""
|
348
|
+
from voice_mode.tools.services.whisper.install import whisper_install
|
353
349
|
result = asyncio.run(whisper_install.fn(
|
354
350
|
install_dir=install_dir,
|
355
351
|
model=model,
|
@@ -394,6 +390,7 @@ def install(install_dir, model, use_gpu, force, version, auto_enable):
|
|
394
390
|
@click.confirmation_option(prompt='Are you sure you want to uninstall Whisper?')
|
395
391
|
def uninstall(remove_models, remove_all_data):
|
396
392
|
"""Uninstall whisper.cpp and optionally remove models and data."""
|
393
|
+
from voice_mode.tools.services.whisper.uninstall import whisper_uninstall
|
397
394
|
result = asyncio.run(whisper_uninstall.fn(
|
398
395
|
remove_models=remove_models,
|
399
396
|
remove_all_data=remove_all_data
|
@@ -437,6 +434,7 @@ def download_model_cmd(model, force, skip_core_ml):
|
|
437
434
|
medium, medium.en, large-v1, large-v2, large-v3, large-v3-turbo
|
438
435
|
"""
|
439
436
|
import json
|
437
|
+
from voice_mode.tools.services.whisper.download_model import download_model
|
440
438
|
result = asyncio.run(download_model.fn(
|
441
439
|
model=model,
|
442
440
|
force_download=force,
|
@@ -478,6 +476,7 @@ def download_model_cmd(model, force, skip_core_ml):
|
|
478
476
|
@livekit.command()
|
479
477
|
def status():
|
480
478
|
"""Show LiveKit service status."""
|
479
|
+
from voice_mode.tools.service import status_service
|
481
480
|
result = asyncio.run(status_service("livekit"))
|
482
481
|
click.echo(result)
|
483
482
|
|
@@ -485,6 +484,7 @@ def status():
|
|
485
484
|
@livekit.command()
|
486
485
|
def start():
|
487
486
|
"""Start LiveKit service."""
|
487
|
+
from voice_mode.tools.service import start_service
|
488
488
|
result = asyncio.run(start_service("livekit"))
|
489
489
|
click.echo(result)
|
490
490
|
|
@@ -492,6 +492,7 @@ def start():
|
|
492
492
|
@livekit.command()
|
493
493
|
def stop():
|
494
494
|
"""Stop LiveKit service."""
|
495
|
+
from voice_mode.tools.service import stop_service
|
495
496
|
result = asyncio.run(stop_service("livekit"))
|
496
497
|
click.echo(result)
|
497
498
|
|
@@ -499,6 +500,7 @@ def stop():
|
|
499
500
|
@livekit.command()
|
500
501
|
def restart():
|
501
502
|
"""Restart LiveKit service."""
|
503
|
+
from voice_mode.tools.service import restart_service
|
502
504
|
result = asyncio.run(restart_service("livekit"))
|
503
505
|
click.echo(result)
|
504
506
|
|
@@ -506,6 +508,7 @@ def restart():
|
|
506
508
|
@livekit.command()
|
507
509
|
def enable():
|
508
510
|
"""Enable LiveKit service to start at boot/login."""
|
511
|
+
from voice_mode.tools.service import enable_service
|
509
512
|
result = asyncio.run(enable_service("livekit"))
|
510
513
|
click.echo(result)
|
511
514
|
|
@@ -513,6 +516,7 @@ def enable():
|
|
513
516
|
@livekit.command()
|
514
517
|
def disable():
|
515
518
|
"""Disable LiveKit service from starting at boot/login."""
|
519
|
+
from voice_mode.tools.service import disable_service
|
516
520
|
result = asyncio.run(disable_service("livekit"))
|
517
521
|
click.echo(result)
|
518
522
|
|
@@ -521,6 +525,7 @@ def disable():
|
|
521
525
|
@click.option('--lines', '-n', default=50, help='Number of log lines to show')
|
522
526
|
def logs(lines):
|
523
527
|
"""View LiveKit service logs."""
|
528
|
+
from voice_mode.tools.service import view_logs
|
524
529
|
result = asyncio.run(view_logs("livekit", lines))
|
525
530
|
click.echo(result)
|
526
531
|
|
@@ -528,6 +533,7 @@ def logs(lines):
|
|
528
533
|
@livekit.command()
|
529
534
|
def update():
|
530
535
|
"""Update LiveKit service files to the latest version."""
|
536
|
+
from voice_mode.tools.service import update_service_files
|
531
537
|
result = asyncio.run(update_service_files("livekit"))
|
532
538
|
|
533
539
|
if result.get("success"):
|
@@ -546,6 +552,7 @@ def update():
|
|
546
552
|
@click.option('--auto-enable/--no-auto-enable', default=None, help='Enable service at boot/login')
|
547
553
|
def install(install_dir, port, force, version, auto_enable):
|
548
554
|
"""Install LiveKit server with development configuration."""
|
555
|
+
from voice_mode.tools.services.livekit.install import livekit_install
|
549
556
|
result = asyncio.run(livekit_install.fn(
|
550
557
|
install_dir=install_dir,
|
551
558
|
port=port,
|
@@ -583,6 +590,7 @@ def install(install_dir, port, force, version, auto_enable):
|
|
583
590
|
@click.confirmation_option(prompt='Are you sure you want to uninstall LiveKit?')
|
584
591
|
def uninstall(remove_config, remove_all_data):
|
585
592
|
"""Uninstall LiveKit server and optionally remove configuration and data."""
|
593
|
+
from voice_mode.tools.services.livekit.uninstall import livekit_uninstall
|
586
594
|
result = asyncio.run(livekit_uninstall.fn(
|
587
595
|
remove_config=remove_config,
|
588
596
|
remove_all_data=remove_all_data
|
@@ -615,6 +623,7 @@ def frontend():
|
|
615
623
|
@click.option('--auto-enable/--no-auto-enable', default=None, help='Enable service after installation (default: from config)')
|
616
624
|
def frontend_install(auto_enable):
|
617
625
|
"""Install and setup LiveKit Voice Assistant Frontend."""
|
626
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_install
|
618
627
|
result = asyncio.run(livekit_frontend_install.fn(auto_enable=auto_enable))
|
619
628
|
|
620
629
|
if result.get('success'):
|
@@ -642,6 +651,7 @@ def frontend_install(auto_enable):
|
|
642
651
|
@click.option('--host', default='127.0.0.1', help='Host to bind to (default: 127.0.0.1)')
|
643
652
|
def frontend_start(port, host):
|
644
653
|
"""Start the LiveKit Voice Assistant Frontend."""
|
654
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_start
|
645
655
|
result = asyncio.run(livekit_frontend_start.fn(port=port, host=host))
|
646
656
|
|
647
657
|
if result.get('success'):
|
@@ -663,6 +673,7 @@ def frontend_start(port, host):
|
|
663
673
|
@frontend.command("stop")
|
664
674
|
def frontend_stop():
|
665
675
|
"""Stop the LiveKit Voice Assistant Frontend."""
|
676
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_stop
|
666
677
|
result = asyncio.run(livekit_frontend_stop.fn())
|
667
678
|
|
668
679
|
if result.get('success'):
|
@@ -674,6 +685,7 @@ def frontend_stop():
|
|
674
685
|
@frontend.command("status")
|
675
686
|
def frontend_status():
|
676
687
|
"""Check status of the LiveKit Voice Assistant Frontend."""
|
688
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_status
|
677
689
|
result = asyncio.run(livekit_frontend_status.fn())
|
678
690
|
|
679
691
|
if 'error' in result:
|
@@ -701,6 +713,7 @@ def frontend_open():
|
|
701
713
|
|
702
714
|
Starts the frontend if not already running, then opens it in the default browser.
|
703
715
|
"""
|
716
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_open
|
704
717
|
result = asyncio.run(livekit_frontend_open.fn())
|
705
718
|
|
706
719
|
if result.get('success'):
|
@@ -723,11 +736,13 @@ def frontend_logs(lines, follow):
|
|
723
736
|
"""
|
724
737
|
if follow:
|
725
738
|
# For following, run tail -f directly
|
739
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_logs
|
726
740
|
result = asyncio.run(livekit_frontend_logs.fn(follow=True))
|
727
741
|
if result.get('success'):
|
728
742
|
click.echo(f"📂 Log file: {result['log_file']}")
|
729
743
|
click.echo("🔄 Following logs (press Ctrl+C to stop)...")
|
730
744
|
try:
|
745
|
+
import subprocess
|
731
746
|
subprocess.run(["tail", "-f", result['log_file']])
|
732
747
|
except KeyboardInterrupt:
|
733
748
|
click.echo("\n✅ Stopped following logs")
|
@@ -735,6 +750,7 @@ def frontend_logs(lines, follow):
|
|
735
750
|
click.echo(f"❌ Error: {result.get('error', 'Unknown error')}")
|
736
751
|
else:
|
737
752
|
# Show last N lines
|
753
|
+
from voice_mode.tools.services.livekit.frontend import livekit_frontend_logs
|
738
754
|
result = asyncio.run(livekit_frontend_logs.fn(lines=lines, follow=False))
|
739
755
|
if result.get('success'):
|
740
756
|
click.echo(f"📂 Log file: {result['log_file']}")
|
@@ -748,6 +764,7 @@ def frontend_logs(lines, follow):
|
|
748
764
|
@frontend.command("enable")
|
749
765
|
def frontend_enable():
|
750
766
|
"""Enable frontend service to start automatically at boot/login."""
|
767
|
+
from voice_mode.tools.service import enable_service
|
751
768
|
result = asyncio.run(enable_service("frontend"))
|
752
769
|
# enable_service returns a string, not a dict
|
753
770
|
click.echo(result)
|
@@ -756,6 +773,7 @@ def frontend_enable():
|
|
756
773
|
@frontend.command("disable")
|
757
774
|
def frontend_disable():
|
758
775
|
"""Disable frontend service from starting automatically."""
|
776
|
+
from voice_mode.tools.service import disable_service
|
759
777
|
result = asyncio.run(disable_service("frontend"))
|
760
778
|
# disable_service returns a string, not a dict
|
761
779
|
click.echo(result)
|
@@ -827,6 +845,7 @@ def config():
|
|
827
845
|
@config.command("list")
|
828
846
|
def config_list():
|
829
847
|
"""List all configuration keys with their descriptions."""
|
848
|
+
from voice_mode.tools.configuration_management import list_config_keys
|
830
849
|
result = asyncio.run(list_config_keys.fn())
|
831
850
|
click.echo(result)
|
832
851
|
|
@@ -873,6 +892,7 @@ def config_get(key):
|
|
873
892
|
@click.argument('value')
|
874
893
|
def config_set(key, value):
|
875
894
|
"""Set a configuration value."""
|
895
|
+
from voice_mode.tools.configuration_management import update_config
|
876
896
|
result = asyncio.run(update_config.fn(key, value))
|
877
897
|
click.echo(result)
|
878
898
|
|
@@ -887,6 +907,7 @@ def diag():
|
|
887
907
|
@diag.command()
|
888
908
|
def info():
|
889
909
|
"""Show voice-mode installation information."""
|
910
|
+
from voice_mode.tools.diagnostics import voice_mode_info
|
890
911
|
result = asyncio.run(voice_mode_info.fn())
|
891
912
|
click.echo(result)
|
892
913
|
|
@@ -894,6 +915,7 @@ def info():
|
|
894
915
|
@diag.command()
|
895
916
|
def devices():
|
896
917
|
"""List available audio input and output devices."""
|
918
|
+
from voice_mode.tools.devices import check_audio_devices
|
897
919
|
result = asyncio.run(check_audio_devices.fn())
|
898
920
|
click.echo(result)
|
899
921
|
|
@@ -901,6 +923,7 @@ def devices():
|
|
901
923
|
@diag.command()
|
902
924
|
def registry():
|
903
925
|
"""Show voice provider registry with all discovered endpoints."""
|
926
|
+
from voice_mode.tools.voice_registry import voice_registry
|
904
927
|
result = asyncio.run(voice_registry.fn())
|
905
928
|
click.echo(result)
|
906
929
|
|
@@ -909,6 +932,7 @@ def registry():
|
|
909
932
|
def dependencies():
|
910
933
|
"""Check system audio dependencies and provide installation guidance."""
|
911
934
|
import json
|
935
|
+
from voice_mode.tools.dependencies import check_audio_dependencies
|
912
936
|
result = asyncio.run(check_audio_dependencies.fn())
|
913
937
|
|
914
938
|
if isinstance(result, dict):
|
voice_mode/config.py
CHANGED
@@ -149,15 +149,24 @@ def env_bool(env_var: str, default: bool = False) -> bool:
|
|
149
149
|
value = os.getenv(env_var, "").lower()
|
150
150
|
return value in ("true", "1", "yes", "on") if value else default
|
151
151
|
|
152
|
+
# Helper function to expand paths with tilde
|
153
|
+
def expand_path(path_str: str) -> Path:
|
154
|
+
"""Expand tilde and environment variables in path strings."""
|
155
|
+
# First expand any environment variables
|
156
|
+
expanded = os.path.expandvars(path_str)
|
157
|
+
# Then expand tilde
|
158
|
+
expanded = os.path.expanduser(expanded)
|
159
|
+
return Path(expanded)
|
160
|
+
|
152
161
|
# Base directory for all voicemode data
|
153
|
-
BASE_DIR =
|
162
|
+
BASE_DIR = expand_path(os.getenv("VOICEMODE_BASE_DIR", str(Path.home() / ".voicemode")))
|
154
163
|
|
155
164
|
# Unified directory structure
|
156
165
|
AUDIO_DIR = BASE_DIR / "audio"
|
157
166
|
TRANSCRIPTIONS_DIR = BASE_DIR / "transcriptions"
|
158
167
|
LOGS_DIR = BASE_DIR / "logs"
|
159
168
|
# CONFIG_DIR = BASE_DIR / "config" # Removed - config stored in .voicemode.env file instead
|
160
|
-
MODELS_DIR =
|
169
|
+
MODELS_DIR = expand_path(os.getenv("VOICEMODE_MODELS_DIR", str(BASE_DIR / "models")))
|
161
170
|
|
162
171
|
# Debug configuration
|
163
172
|
DEBUG = os.getenv("VOICEMODE_DEBUG", "").lower() in ("true", "1", "yes", "on")
|
@@ -225,14 +234,14 @@ LIVEKIT_API_SECRET = os.getenv("LIVEKIT_API_SECRET", "secret")
|
|
225
234
|
WHISPER_MODEL = os.getenv("VOICEMODE_WHISPER_MODEL", "large-v2")
|
226
235
|
WHISPER_PORT = int(os.getenv("VOICEMODE_WHISPER_PORT", "2022"))
|
227
236
|
WHISPER_LANGUAGE = os.getenv("VOICEMODE_WHISPER_LANGUAGE", "auto")
|
228
|
-
WHISPER_MODEL_PATH = os.getenv("VOICEMODE_WHISPER_MODEL_PATH", str(BASE_DIR / "models" / "whisper"))
|
237
|
+
WHISPER_MODEL_PATH = expand_path(os.getenv("VOICEMODE_WHISPER_MODEL_PATH", str(BASE_DIR / "models" / "whisper")))
|
229
238
|
|
230
239
|
# ==================== KOKORO CONFIGURATION ====================
|
231
240
|
|
232
241
|
# Kokoro-specific configuration
|
233
242
|
KOKORO_PORT = int(os.getenv("VOICEMODE_KOKORO_PORT", "8880"))
|
234
|
-
KOKORO_MODELS_DIR = os.getenv("VOICEMODE_KOKORO_MODELS_DIR", str(BASE_DIR / "models" / "kokoro"))
|
235
|
-
KOKORO_CACHE_DIR = os.getenv("VOICEMODE_KOKORO_CACHE_DIR", str(BASE_DIR / "cache" / "kokoro"))
|
243
|
+
KOKORO_MODELS_DIR = expand_path(os.getenv("VOICEMODE_KOKORO_MODELS_DIR", str(BASE_DIR / "models" / "kokoro")))
|
244
|
+
KOKORO_CACHE_DIR = expand_path(os.getenv("VOICEMODE_KOKORO_CACHE_DIR", str(BASE_DIR / "cache" / "kokoro")))
|
236
245
|
KOKORO_DEFAULT_VOICE = os.getenv("VOICEMODE_KOKORO_DEFAULT_VOICE", "af_sky")
|
237
246
|
|
238
247
|
# ==================== LIVEKIT CONFIGURATION ====================
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
SsR9zBdw0hd2LN3Vo9tP_
|
@@ -4,25 +4,25 @@
|
|
4
4
|
"static/chunks/webpack-0ea9b80f19935b70.js",
|
5
5
|
"static/chunks/fd9d1056-af324d327b243cf1.js",
|
6
6
|
"static/chunks/117-40bc79a2b97edb21.js",
|
7
|
-
"static/chunks/main-app-
|
7
|
+
"static/chunks/main-app-d25858d98b1d322b.js",
|
8
8
|
"static/chunks/app/_not-found/page-5011050e402ab9c8.js"
|
9
9
|
],
|
10
10
|
"/layout": [
|
11
11
|
"static/chunks/webpack-0ea9b80f19935b70.js",
|
12
12
|
"static/chunks/fd9d1056-af324d327b243cf1.js",
|
13
13
|
"static/chunks/117-40bc79a2b97edb21.js",
|
14
|
-
"static/chunks/main-app-
|
14
|
+
"static/chunks/main-app-d25858d98b1d322b.js",
|
15
15
|
"static/css/a2f49a47752b5010.css",
|
16
|
-
"static/chunks/app/layout-
|
16
|
+
"static/chunks/app/layout-5675f418c42e0ae3.js"
|
17
17
|
],
|
18
18
|
"/page": [
|
19
19
|
"static/chunks/webpack-0ea9b80f19935b70.js",
|
20
20
|
"static/chunks/fd9d1056-af324d327b243cf1.js",
|
21
21
|
"static/chunks/117-40bc79a2b97edb21.js",
|
22
|
-
"static/chunks/main-app-
|
22
|
+
"static/chunks/main-app-d25858d98b1d322b.js",
|
23
23
|
"static/chunks/144d3bae-2d5f122b82426d88.js",
|
24
24
|
"static/chunks/471-bd4b96a33883dfa2.js",
|
25
|
-
"static/chunks/app/page-
|
25
|
+
"static/chunks/app/page-dbb3615cf25cdc16.js"
|
26
26
|
]
|
27
27
|
}
|
28
28
|
}
|
@@ -5,14 +5,14 @@
|
|
5
5
|
"devFiles": [],
|
6
6
|
"ampDevFiles": [],
|
7
7
|
"lowPriorityFiles": [
|
8
|
-
"static/
|
9
|
-
"static/
|
8
|
+
"static/SsR9zBdw0hd2LN3Vo9tP_/_buildManifest.js",
|
9
|
+
"static/SsR9zBdw0hd2LN3Vo9tP_/_ssgManifest.js"
|
10
10
|
],
|
11
11
|
"rootMainFiles": [
|
12
12
|
"static/chunks/webpack-0ea9b80f19935b70.js",
|
13
13
|
"static/chunks/fd9d1056-af324d327b243cf1.js",
|
14
14
|
"static/chunks/117-40bc79a2b97edb21.js",
|
15
|
-
"static/chunks/main-app-
|
15
|
+
"static/chunks/main-app-d25858d98b1d322b.js"
|
16
16
|
],
|
17
17
|
"pages": {
|
18
18
|
"/_app": [
|
@@ -1 +1 @@
|
|
1
|
-
{"version":1,"files":["../node_modules/styled-jsx/index.js","../node_modules/styled-jsx/package.json","../node_modules/styled-jsx/dist/index/index.js","../node_modules/react/package.json","../node_modules/react/index.js","../node_modules/client-only/package.json","../node_modules/react/cjs/react.production.min.js","../node_modules/client-only/index.js","../node_modules/styled-jsx/style.js","../node_modules/next/dist/compiled/next-server/server.runtime.prod.js","../node_modules/next/package.json","../node_modules/next/dist/lib/constants.js","../node_modules/next/dist/server/body-streams.js","../node_modules/next/dist/lib/picocolors.js","../node_modules/next/dist/shared/lib/constants.js","../node_modules/next/dist/server/web/utils.js","../node_modules/next/dist/client/components/app-router-headers.js","../node_modules/next/dist/server/lib/trace/
|
1
|
+
{"version":1,"files":["../node_modules/styled-jsx/index.js","../node_modules/styled-jsx/package.json","../node_modules/styled-jsx/dist/index/index.js","../node_modules/react/package.json","../node_modules/react/index.js","../node_modules/client-only/package.json","../node_modules/react/cjs/react.production.min.js","../node_modules/client-only/index.js","../node_modules/styled-jsx/style.js","../node_modules/next/dist/compiled/next-server/server.runtime.prod.js","../node_modules/next/package.json","../node_modules/next/dist/lib/constants.js","../node_modules/next/dist/server/body-streams.js","../node_modules/next/dist/lib/picocolors.js","../node_modules/next/dist/shared/lib/constants.js","../node_modules/next/dist/server/web/utils.js","../node_modules/next/dist/client/components/app-router-headers.js","../node_modules/next/dist/server/lib/trace/tracer.js","../node_modules/next/dist/server/lib/trace/constants.js","../node_modules/next/dist/client/components/static-generation-async-storage.external.js","../node_modules/next/dist/shared/lib/error-source.js","../node_modules/next/dist/shared/lib/modern-browserslist-target.js","../node_modules/next/dist/compiled/debug/package.json","../node_modules/next/dist/client/components/static-generation-async-storage-instance.js","../node_modules/next/dist/shared/lib/runtime-config.external.js","../node_modules/next/dist/compiled/debug/index.js","../node_modules/next/dist/compiled/ws/package.json","../node_modules/next/dist/compiled/lru-cache/package.json","../node_modules/next/dist/compiled/node-html-parser/package.json","../node_modules/@swc/helpers/_/_interop_require_default/package.json","../node_modules/next/dist/compiled/ws/index.js","../node_modules/next/dist/compiled/lru-cache/index.js","../node_modules/next/dist/compiled/node-html-parser/index.js","../node_modules/next/dist/client/components/async-local-storage.js","../node_modules/next/dist/compiled/@opentelemetry/api/package.json","../node_modules/@swc/helpers/package.json","../node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/parseStack.js","../node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/nodeStackFrames.js","../node_modules/next/dist/compiled/jsonwebtoken/package.json","../node_modules/next/dist/client/components/react-dev-overlay/server/middleware.js","../node_modules/@swc/helpers/cjs/_interop_require_default.cjs","../node_modules/next/dist/compiled/@opentelemetry/api/index.js","../node_modules/next/dist/compiled/jsonwebtoken/index.js","../node_modules/next/dist/compiled/browserslist/package.json","../node_modules/next/dist/compiled/browserslist/index.js","../node_modules/next/dist/client/components/react-dev-overlay/server/shared.js","../node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/getRawSourceMap.js","../node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/launchEditor.js","../node_modules/next/dist/compiled/babel/code-frame.js","../node_modules/next/dist/compiled/json5/package.json","../node_modules/next/dist/compiled/semver/package.json","../node_modules/next/dist/compiled/babel/package.json","../node_modules/next/dist/lib/semver-noop.js","../node_modules/next/dist/compiled/json5/index.js","../node_modules/next/dist/compiled/semver/index.js","../node_modules/next/dist/compiled/stacktrace-parser/package.json","../node_modules/next/dist/compiled/source-map08/package.json","../node_modules/caniuse-lite/dist/unpacker/agents.js","../node_modules/caniuse-lite/dist/unpacker/feature.js","../node_modules/caniuse-lite/dist/unpacker/region.js","../node_modules/next/dist/compiled/babel/bundle.js","../node_modules/next/dist/client/components/react-dev-overlay/internal/helpers/getSourceMapUrl.js","../node_modules/next/dist/compiled/stacktrace-parser/stack-trace-parser.cjs.js","../node_modules/next/dist/compiled/source-map08/source-map.js","../node_modules/caniuse-lite/package.json","../node_modules/next/dist/compiled/babel/core.js","../node_modules/caniuse-lite/data/agents.js","../node_modules/caniuse-lite/dist/lib/statuses.js","../node_modules/caniuse-lite/dist/lib/supported.js","../node_modules/caniuse-lite/dist/unpacker/browsers.js","../node_modules/caniuse-lite/dist/unpacker/browserVersions.js","../node_modules/next/dist/compiled/data-uri-to-buffer/package.json","../node_modules/next/dist/compiled/shell-quote/package.json","../node_modules/next/dist/compiled/data-uri-to-buffer/index.js","../node_modules/next/dist/compiled/shell-quote/index.js","../node_modules/caniuse-lite/data/browsers.js","../node_modules/caniuse-lite/data/browserVersions.js","../node_modules/next/dist/compiled/babel-packages/package.json","../node_modules/next/dist/compiled/babel-packages/packages-bundle.js","../node_modules/next/dist/compiled/babel/traverse.js","../node_modules/next/dist/compiled/babel/types.js","../node_modules/next/dist/compiled/babel/parser.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/amp-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/app-router-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/entrypoints.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/head-manager-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/hooks-client-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/html-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/image-config-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/loadable-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/loadable.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/router-context.js","../node_modules/next/dist/server/future/route-modules/app-page/vendored/contexts/server-inserted-html.js","../node_modules/next/dist/server/future/route-modules/app-page/module.compiled.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/amp-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/app-router-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/entrypoints.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/head-manager-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/hooks-client-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/html-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/image-config-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/loadable-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/loadable.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/router-context.js","../node_modules/next/dist/server/future/route-modules/pages/vendored/contexts/server-inserted-html.js","../node_modules/next/dist/server/future/route-modules/pages/module.compiled.js"]}
|