voice-mode 2.33.3__py3-none-any.whl → 2.34.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.
Files changed (64) hide show
  1. voice_mode/__version__.py +1 -1
  2. voice_mode/frontend/.next/BUILD_ID +1 -1
  3. voice_mode/frontend/.next/app-build-manifest.json +5 -5
  4. voice_mode/frontend/.next/build-manifest.json +3 -3
  5. voice_mode/frontend/.next/next-minimal-server.js.nft.json +1 -1
  6. voice_mode/frontend/.next/next-server.js.nft.json +1 -1
  7. voice_mode/frontend/.next/prerender-manifest.json +1 -1
  8. voice_mode/frontend/.next/required-server-files.json +1 -1
  9. voice_mode/frontend/.next/server/app/_not-found/page.js +1 -1
  10. voice_mode/frontend/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  11. voice_mode/frontend/.next/server/app/_not-found.html +1 -1
  12. voice_mode/frontend/.next/server/app/_not-found.rsc +1 -1
  13. voice_mode/frontend/.next/server/app/api/connection-details/route.js +2 -2
  14. voice_mode/frontend/.next/server/app/favicon.ico/route.js +2 -2
  15. voice_mode/frontend/.next/server/app/index.html +1 -1
  16. voice_mode/frontend/.next/server/app/index.rsc +2 -2
  17. voice_mode/frontend/.next/server/app/page.js +2 -2
  18. voice_mode/frontend/.next/server/app/page_client-reference-manifest.js +1 -1
  19. voice_mode/frontend/.next/server/chunks/994.js +2 -2
  20. voice_mode/frontend/.next/server/middleware-build-manifest.js +1 -1
  21. voice_mode/frontend/.next/server/next-font-manifest.js +1 -1
  22. voice_mode/frontend/.next/server/next-font-manifest.json +1 -1
  23. voice_mode/frontend/.next/server/pages/404.html +1 -1
  24. voice_mode/frontend/.next/server/pages/500.html +1 -1
  25. voice_mode/frontend/.next/server/server-reference-manifest.json +1 -1
  26. voice_mode/frontend/.next/standalone/.next/BUILD_ID +1 -1
  27. voice_mode/frontend/.next/standalone/.next/app-build-manifest.json +5 -5
  28. voice_mode/frontend/.next/standalone/.next/build-manifest.json +3 -3
  29. voice_mode/frontend/.next/standalone/.next/prerender-manifest.json +1 -1
  30. voice_mode/frontend/.next/standalone/.next/required-server-files.json +1 -1
  31. voice_mode/frontend/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  32. voice_mode/frontend/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  33. voice_mode/frontend/.next/standalone/.next/server/app/_not-found.html +1 -1
  34. voice_mode/frontend/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  35. voice_mode/frontend/.next/standalone/.next/server/app/api/connection-details/route.js +2 -2
  36. voice_mode/frontend/.next/standalone/.next/server/app/favicon.ico/route.js +2 -2
  37. voice_mode/frontend/.next/standalone/.next/server/app/index.html +1 -1
  38. voice_mode/frontend/.next/standalone/.next/server/app/index.rsc +2 -2
  39. voice_mode/frontend/.next/standalone/.next/server/app/page.js +2 -2
  40. voice_mode/frontend/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  41. voice_mode/frontend/.next/standalone/.next/server/chunks/994.js +2 -2
  42. voice_mode/frontend/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  43. voice_mode/frontend/.next/standalone/.next/server/next-font-manifest.js +1 -1
  44. voice_mode/frontend/.next/standalone/.next/server/next-font-manifest.json +1 -1
  45. voice_mode/frontend/.next/standalone/.next/server/pages/404.html +1 -1
  46. voice_mode/frontend/.next/standalone/.next/server/pages/500.html +1 -1
  47. voice_mode/frontend/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  48. voice_mode/frontend/.next/standalone/server.js +1 -1
  49. voice_mode/frontend/.next/static/chunks/app/{layout-0668b54a9a8a3d88.js → layout-8365e4b0b502e273.js} +1 -1
  50. voice_mode/frontend/.next/static/chunks/app/{page-b2295ed8502c5617.js → page-56c513d637021d6c.js} +1 -1
  51. voice_mode/frontend/.next/static/chunks/main-app-c2e7596a7588072c.js +1 -0
  52. voice_mode/frontend/.next/trace +43 -43
  53. voice_mode/frontend/.next/types/app/api/connection-details/route.ts +1 -1
  54. voice_mode/frontend/.next/types/app/layout.ts +1 -1
  55. voice_mode/frontend/.next/types/app/page.ts +1 -1
  56. voice_mode/tools/services/kokoro/install.py +207 -2
  57. voice_mode/tools/services/whisper/install.py +331 -187
  58. {voice_mode-2.33.3.dist-info → voice_mode-2.34.0.dist-info}/METADATA +1 -1
  59. {voice_mode-2.33.3.dist-info → voice_mode-2.34.0.dist-info}/RECORD +63 -63
  60. voice_mode/frontend/.next/static/chunks/main-app-78bb3214ad53942b.js +0 -1
  61. /voice_mode/frontend/.next/static/{G6vnbmBPF9PSjWGgrWUux → VjuJp4LAYPX7t1KdLNI3o}/_buildManifest.js +0 -0
  62. /voice_mode/frontend/.next/static/{G6vnbmBPF9PSjWGgrWUux → VjuJp4LAYPX7t1KdLNI3o}/_ssgManifest.js +0 -0
  63. {voice_mode-2.33.3.dist-info → voice_mode-2.34.0.dist-info}/WHEEL +0 -0
  64. {voice_mode-2.33.3.dist-info → voice_mode-2.34.0.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,4 @@
1
- // File: /tmp/build-via-sdist-i1skfj6s/voice_mode-2.33.3/voice_mode/frontend/app/api/connection-details/route.ts
1
+ // File: /tmp/build-via-sdist-s5x70n9b/voice_mode-2.34.0/voice_mode/frontend/app/api/connection-details/route.ts
2
2
  import * as entry from '../../../../../app/api/connection-details/route.js'
3
3
  import type { NextRequest } from 'next/server.js'
4
4
 
@@ -1,4 +1,4 @@
1
- // File: /tmp/build-via-sdist-i1skfj6s/voice_mode-2.33.3/voice_mode/frontend/app/layout.tsx
1
+ // File: /tmp/build-via-sdist-s5x70n9b/voice_mode-2.34.0/voice_mode/frontend/app/layout.tsx
2
2
  import * as entry from '../../../app/layout.js'
3
3
  import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
4
4
 
@@ -1,4 +1,4 @@
1
- // File: /tmp/build-via-sdist-i1skfj6s/voice_mode-2.33.3/voice_mode/frontend/app/page.tsx
1
+ // File: /tmp/build-via-sdist-s5x70n9b/voice_mode-2.34.0/voice_mode/frontend/app/page.tsx
2
2
  import * as entry from '../../../app/page.js'
3
3
  import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
4
4
 
@@ -22,6 +22,152 @@ from voice_mode.utils.migration_helpers import auto_migrate_if_needed
22
22
  logger = logging.getLogger("voice-mode")
23
23
 
24
24
 
25
+ async def update_kokoro_service_files(
26
+ install_dir: str,
27
+ voicemode_dir: str,
28
+ port: int,
29
+ start_script_path: str,
30
+ auto_enable: Optional[bool] = None
31
+ ) -> Dict[str, Any]:
32
+ """Update service files (plist/systemd) for kokoro service.
33
+
34
+ This function updates the service files without reinstalling kokoro itself.
35
+ It ensures paths are properly expanded and templates are up to date.
36
+
37
+ Returns:
38
+ Dict with success status and details about what was updated
39
+ """
40
+ system = platform.system()
41
+ result = {"success": False, "updated": False}
42
+
43
+ # Create log directory
44
+ log_dir = os.path.join(voicemode_dir, 'logs', 'kokoro')
45
+ os.makedirs(log_dir, exist_ok=True)
46
+
47
+ if system == "Darwin":
48
+ logger.info("Updating launchagent for kokoro...")
49
+ launchagents_dir = os.path.expanduser("~/Library/LaunchAgents")
50
+ os.makedirs(launchagents_dir, exist_ok=True)
51
+
52
+ plist_name = "com.voicemode.kokoro.plist"
53
+ plist_path = os.path.join(launchagents_dir, plist_name)
54
+
55
+ plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
56
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
57
+ <plist version="1.0">
58
+ <dict>
59
+ <key>Label</key>
60
+ <string>com.voicemode.kokoro</string>
61
+ <key>ProgramArguments</key>
62
+ <array>
63
+ <string>{start_script_path}</string>
64
+ </array>
65
+ <key>WorkingDirectory</key>
66
+ <string>{install_dir}</string>
67
+ <key>RunAtLoad</key>
68
+ <true/>
69
+ <key>KeepAlive</key>
70
+ <true/>
71
+ <key>StandardOutPath</key>
72
+ <string>{os.path.join(voicemode_dir, 'logs', 'kokoro', 'kokoro.log')}</string>
73
+ <key>StandardErrorPath</key>
74
+ <string>{os.path.join(voicemode_dir, 'logs', 'kokoro', 'kokoro.error.log')}</string>
75
+ <key>EnvironmentVariables</key>
76
+ <dict>
77
+ <key>PATH</key>
78
+ <string>{os.path.expanduser("~/.local/bin")}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin</string>
79
+ </dict>
80
+ </dict>
81
+ </plist>"""
82
+
83
+ # Unload if already loaded (ignore errors)
84
+ try:
85
+ subprocess.run(["launchctl", "unload", plist_path], capture_output=True)
86
+ except:
87
+ pass
88
+
89
+ # Write updated plist
90
+ with open(plist_path, 'w') as f:
91
+ f.write(plist_content)
92
+
93
+ result["success"] = True
94
+ result["updated"] = True
95
+ result["plist_path"] = plist_path
96
+
97
+ # Handle auto_enable if specified
98
+ if auto_enable is None:
99
+ auto_enable = SERVICE_AUTO_ENABLE
100
+
101
+ if auto_enable:
102
+ logger.info("Auto-enabling kokoro service...")
103
+ from voice_mode.tools.service import enable_service
104
+ enable_result = await enable_service("kokoro")
105
+ if "✅" in enable_result:
106
+ result["enabled"] = True
107
+ else:
108
+ logger.warning(f"Auto-enable failed: {enable_result}")
109
+ result["enabled"] = False
110
+
111
+ elif system == "Linux":
112
+ logger.info("Updating systemd user service for kokoro...")
113
+ systemd_user_dir = os.path.expanduser("~/.config/systemd/user")
114
+ os.makedirs(systemd_user_dir, exist_ok=True)
115
+
116
+ service_name = "voicemode-kokoro.service"
117
+ service_path = os.path.join(systemd_user_dir, service_name)
118
+
119
+ service_content = f"""[Unit]
120
+ Description=VoiceMode Kokoro TTS Service
121
+ After=network.target
122
+ [Service]
123
+ Type=simple
124
+ ExecStart={start_script_path}
125
+ Restart=on-failure
126
+ RestartSec=10
127
+ WorkingDirectory={install_dir}
128
+ StandardOutput=append:{os.path.join(voicemode_dir, 'logs', 'kokoro', 'kokoro.log')}
129
+ StandardError=append:{os.path.join(voicemode_dir, 'logs', 'kokoro', 'kokoro.error.log')}
130
+ Environment="PATH=/usr/local/bin:/usr/bin:/bin:/home/m/.local/bin"
131
+ [Install]
132
+ WantedBy=default.target
133
+ """
134
+
135
+ with open(service_path, 'w') as f:
136
+ f.write(service_content)
137
+
138
+ # Reload systemd
139
+ try:
140
+ subprocess.run(["systemctl", "--user", "daemon-reload"], check=True)
141
+ result["success"] = True
142
+ result["updated"] = True
143
+ result["service_path"] = service_path
144
+ except subprocess.CalledProcessError as e:
145
+ logger.warning(f"Failed to reload systemd: {e}")
146
+ result["success"] = True # Still consider it success if file was written
147
+ result["updated"] = True
148
+ result["service_path"] = service_path
149
+
150
+ # Handle auto_enable if specified
151
+ if auto_enable is None:
152
+ auto_enable = SERVICE_AUTO_ENABLE
153
+
154
+ if auto_enable:
155
+ logger.info("Auto-enabling kokoro service...")
156
+ from voice_mode.tools.service import enable_service
157
+ enable_result = await enable_service("kokoro")
158
+ if "✅" in enable_result:
159
+ result["enabled"] = True
160
+ else:
161
+ logger.warning(f"Auto-enable failed: {enable_result}")
162
+ result["enabled"] = False
163
+
164
+ else:
165
+ result["success"] = False
166
+ result["error"] = f"Unsupported platform: {system}"
167
+
168
+ return result
169
+
170
+
25
171
  @mcp.tool()
26
172
  async def kokoro_install(
27
173
  install_dir: Optional[str] = None,
@@ -101,13 +247,58 @@ async def kokoro_install(
101
247
  # Check if the requested version is already installed
102
248
  if is_version_installed(Path(install_dir), version):
103
249
  current_version = get_current_version(Path(install_dir))
250
+
251
+ # Determine which start script to use
252
+ system = platform.system()
253
+ if system == "Darwin":
254
+ start_script_name = "start-gpu_mac.sh"
255
+ else:
256
+ start_script_name = "start-gpu.sh" # Default to GPU version
257
+
258
+ start_script_path = os.path.join(install_dir, start_script_name)
259
+
260
+ # If a custom port is requested, create custom start script
261
+ if port != 8880 and os.path.exists(start_script_path):
262
+ logger.info(f"Creating custom start script for port {port}")
263
+ with open(start_script_path, 'r') as f:
264
+ script_content = f.read()
265
+ modified_script = script_content.replace("--port 8880", f"--port {port}")
266
+ custom_script_name = f"start-custom-{port}.sh"
267
+ custom_script_path = os.path.join(install_dir, custom_script_name)
268
+ with open(custom_script_path, 'w') as f:
269
+ f.write(modified_script)
270
+ os.chmod(custom_script_path, 0o755)
271
+ start_script_path = custom_script_path
272
+
273
+ # Always update service files even if kokoro is already installed
274
+ logger.info("Kokoro is already installed, updating service files...")
275
+ service_update_result = await update_kokoro_service_files(
276
+ install_dir=install_dir,
277
+ voicemode_dir=voicemode_dir,
278
+ port=port,
279
+ start_script_path=start_script_path,
280
+ auto_enable=auto_enable
281
+ )
282
+
283
+ # Build response message
284
+ message = f"kokoro-fastapi version {current_version} already installed."
285
+ if service_update_result.get("updated"):
286
+ message += " Service files updated."
287
+ if service_update_result.get("enabled"):
288
+ message += " Service auto-enabled."
289
+
104
290
  return {
105
291
  "success": True,
106
292
  "install_path": install_dir,
107
293
  "models_path": models_dir,
108
294
  "already_installed": True,
295
+ "service_files_updated": service_update_result.get("updated", False),
109
296
  "version": current_version,
110
- "message": f"kokoro-fastapi version {current_version} already installed. Use force_reinstall=True to reinstall."
297
+ "plist_path": service_update_result.get("plist_path"),
298
+ "service_path": service_update_result.get("service_path"),
299
+ "start_script": start_script_path,
300
+ "service_url": f"http://127.0.0.1:{port}",
301
+ "message": message
111
302
  }
112
303
 
113
304
  # Check Python version
@@ -215,7 +406,21 @@ async def kokoro_install(
215
406
  "message": f"Kokoro-fastapi {current_version} installed. Run: cd {install_dir} && ./{os.path.basename(start_script_path)}{' (' + migration_msg + ')' if migration_msg else ''}"
216
407
  }
217
408
 
218
- # Install launchagent on macOS
409
+ # Install/update service files
410
+ service_update_result = await update_kokoro_service_files(
411
+ install_dir=install_dir,
412
+ voicemode_dir=voicemode_dir,
413
+ port=port,
414
+ start_script_path=start_script_path,
415
+ auto_enable=auto_enable
416
+ )
417
+
418
+ if not service_update_result.get("success"):
419
+ logger.error(f"Failed to update service files: {service_update_result.get('error', 'Unknown error')}")
420
+ result["error"] = f"Service file update failed: {service_update_result.get('error', 'Unknown error')}"
421
+ return result
422
+
423
+ # Update result with service file information based on platform
219
424
  if system == "Darwin":
220
425
  logger.info("Installing launchagent for automatic startup...")
221
426
  launchagents_dir = os.path.expanduser("~/Library/LaunchAgents")