gemcode 0.3.101__tar.gz → 0.3.103__tar.gz
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.
- {gemcode-0.3.101/src/gemcode.egg-info → gemcode-0.3.103}/PKG-INFO +1 -1
- {gemcode-0.3.101 → gemcode-0.3.103}/pyproject.toml +1 -1
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/cli.py +52 -1
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/live_audio_engine.py +24 -1
- {gemcode-0.3.101 → gemcode-0.3.103/src/gemcode.egg-info}/PKG-INFO +1 -1
- {gemcode-0.3.101 → gemcode-0.3.103}/LICENSE +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/MANIFEST.in +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/README.md +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/setup.cfg +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/agent.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/autotune.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/checkpoints.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/config.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/curated_memory.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/dynamic_policy.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/evals/harness.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/ide_protocol.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/ide_stdio.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/invoke.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/kaira_daemon.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/learning.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/multimodal_input.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/output_styles.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/policy_profile.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query_sanitizer.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/repl_slash.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/rules.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/session_summariser.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/skills.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tool_result_store.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/compress_memory.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/curated_memory.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/notebook.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/repo_map.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/skills.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/subtask.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/tasks.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/veomem_tools.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/web_search.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/scrollback.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/welcome_banner.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/veomem_bridge.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/version.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/wal.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/sse_adapter.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/web_sse_compat.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/SOURCES.txt +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/requires.txt +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_add_dir.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_checkpoint_diff_command.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_compress_memory_tool.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_credentials.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_eval_harness_layout.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_ide_stdio_attachments.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_kaira_scheduler.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_multimodal_input.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_output_styles_and_rules.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_paths.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_permissions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_skills.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_slash_completion_registry.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_tools.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_web_sse_adapter.py +0 -0
- {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_workspace_hints.py +0 -0
|
@@ -710,6 +710,11 @@ def main() -> None:
|
|
|
710
710
|
action="store_true",
|
|
711
711
|
help="Do not play model audio to speakers (still prints text if any)",
|
|
712
712
|
)
|
|
713
|
+
audio_parser.add_argument(
|
|
714
|
+
"--list-devices",
|
|
715
|
+
action="store_true",
|
|
716
|
+
help="List available audio devices and exit (for mic troubleshooting)",
|
|
717
|
+
)
|
|
713
718
|
|
|
714
719
|
args = audio_parser.parse_args(sys.argv[2:])
|
|
715
720
|
load_cli_environment()
|
|
@@ -730,6 +735,36 @@ def main() -> None:
|
|
|
730
735
|
session_id = args.session or str(uuid.uuid4())
|
|
731
736
|
from gemcode.live_audio_engine import run_live_audio
|
|
732
737
|
|
|
738
|
+
if args.list_devices:
|
|
739
|
+
try:
|
|
740
|
+
import sounddevice as sd # type: ignore
|
|
741
|
+
except Exception:
|
|
742
|
+
print(
|
|
743
|
+
"\n[gemcode live-audio] Audio deps missing. Install:\n"
|
|
744
|
+
" python3 -m pip install -U \"gemcode[live]\"\n",
|
|
745
|
+
file=sys.stderr,
|
|
746
|
+
)
|
|
747
|
+
raise SystemExit(2)
|
|
748
|
+
try:
|
|
749
|
+
devs = sd.query_devices()
|
|
750
|
+
default_in, default_out = sd.default.device
|
|
751
|
+
print("Audio devices:")
|
|
752
|
+
for i, d in enumerate(devs):
|
|
753
|
+
name = str(d.get("name") or "")
|
|
754
|
+
mi = int(d.get("max_input_channels") or 0)
|
|
755
|
+
mo = int(d.get("max_output_channels") or 0)
|
|
756
|
+
mark = ""
|
|
757
|
+
if i == default_in:
|
|
758
|
+
mark += " [default-in]"
|
|
759
|
+
if i == default_out:
|
|
760
|
+
mark += " [default-out]"
|
|
761
|
+
print(f" {i:>2}: in={mi} out={mo} {name}{mark}")
|
|
762
|
+
print("\nTip: set GEMCODE_LIVE_AUDIO_INPUT_DEVICE to a device index or name.")
|
|
763
|
+
except Exception as e:
|
|
764
|
+
print(f"[gemcode live-audio] Could not list devices: {e}", file=sys.stderr)
|
|
765
|
+
raise SystemExit(2)
|
|
766
|
+
raise SystemExit(0)
|
|
767
|
+
|
|
733
768
|
# One-time explicit permission prompt (HITL) for mic/speaker use.
|
|
734
769
|
if hasattr(sys.stdin, "isatty") and sys.stdin.isatty():
|
|
735
770
|
try:
|
|
@@ -787,7 +822,13 @@ def main() -> None:
|
|
|
787
822
|
)
|
|
788
823
|
)
|
|
789
824
|
captured = buf.getvalue()
|
|
790
|
-
|
|
825
|
+
noisy = (
|
|
826
|
+
"An unexpected error occurred in live flow: 1000" in captured
|
|
827
|
+
or "APIError: 1000" in captured
|
|
828
|
+
or "APIError: 1011" in captured
|
|
829
|
+
or "An unexpected error occurred in live flow: 1011" in captured
|
|
830
|
+
)
|
|
831
|
+
if captured and not noisy:
|
|
791
832
|
# Re-emit unexpected stderr.
|
|
792
833
|
print(captured, file=sys.stderr, end="")
|
|
793
834
|
else:
|
|
@@ -808,6 +849,16 @@ def main() -> None:
|
|
|
808
849
|
if isinstance(e, APIError) and (getattr(e, "status_code", None) == 1000 or "1000" in str(e)):
|
|
809
850
|
print("\n[gemcode live-audio] Session ended.", file=sys.stderr)
|
|
810
851
|
raise SystemExit(0)
|
|
852
|
+
if isinstance(e, APIError) and getattr(e, "status_code", None) == 1011:
|
|
853
|
+
print(
|
|
854
|
+
"\n[gemcode live-audio] Gemini Live internal error (1011).\n"
|
|
855
|
+
"This is usually transient. Try again, or try:\n"
|
|
856
|
+
" - set a different live model: gemcode live-audio --model <id>\n"
|
|
857
|
+
" - disable playback: gemcode live-audio --no-playback\n"
|
|
858
|
+
" - shorten the session: gemcode live-audio --seconds 10\n",
|
|
859
|
+
file=sys.stderr,
|
|
860
|
+
)
|
|
861
|
+
raise SystemExit(2)
|
|
811
862
|
except Exception:
|
|
812
863
|
pass
|
|
813
864
|
# websockets can also surface a close directly.
|
|
@@ -8,6 +8,7 @@ This wires GemCode's existing outer session + callbacks into ADK's
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import asyncio
|
|
11
|
+
import os
|
|
11
12
|
import time
|
|
12
13
|
import sys
|
|
13
14
|
from dataclasses import dataclass
|
|
@@ -126,7 +127,8 @@ async def run_live_audio(
|
|
|
126
127
|
|
|
127
128
|
run_config = RunConfig(
|
|
128
129
|
# Prefer the enum value (avoids pydantic serializer warnings in some SDK versions).
|
|
129
|
-
|
|
130
|
+
# Request TEXT too so users see transcripts even when the model returns only audio.
|
|
131
|
+
response_modalities=[types.Modality.AUDIO, types.Modality.TEXT],
|
|
130
132
|
speech_config=speech_config,
|
|
131
133
|
# Keep SDK defaults for STT/TTS transcription configs.
|
|
132
134
|
)
|
|
@@ -188,16 +190,20 @@ async def run_live_audio(
|
|
|
188
190
|
# Mic capture → async queue (threaded producer).
|
|
189
191
|
pcm_q: asyncio.Queue[bytes] = asyncio.Queue(maxsize=50)
|
|
190
192
|
stop_at = time.time() + max(1, int(seconds))
|
|
193
|
+
chunks_sent = 0
|
|
194
|
+
non_silent_chunks = 0
|
|
191
195
|
|
|
192
196
|
def _mic_thread() -> None:
|
|
193
197
|
# ~20ms frames is a good latency/overhead balance.
|
|
194
198
|
blocksize = max(120, int(input_rate // 50))
|
|
199
|
+
device = os.environ.get("GEMCODE_LIVE_AUDIO_INPUT_DEVICE")
|
|
195
200
|
try:
|
|
196
201
|
stream = sd.RawInputStream( # type: ignore[attr-defined]
|
|
197
202
|
samplerate=int(input_rate),
|
|
198
203
|
channels=1,
|
|
199
204
|
dtype="int16",
|
|
200
205
|
blocksize=int(blocksize),
|
|
206
|
+
device=device if device else None,
|
|
201
207
|
)
|
|
202
208
|
except Exception:
|
|
203
209
|
# Let the consumer surface this as empty audio.
|
|
@@ -227,6 +233,14 @@ async def run_live_audio(
|
|
|
227
233
|
chunk = await asyncio.wait_for(pcm_q.get(), timeout=0.25)
|
|
228
234
|
except asyncio.TimeoutError:
|
|
229
235
|
continue
|
|
236
|
+
chunks_sent += 1
|
|
237
|
+
try:
|
|
238
|
+
arr = np.frombuffer(chunk, dtype="int16") # type: ignore[attr-defined]
|
|
239
|
+
# Consider it non-silent if mean abs amplitude crosses a tiny threshold.
|
|
240
|
+
if arr.size and float(np.mean(np.abs(arr))) > 25.0: # type: ignore[attr-defined]
|
|
241
|
+
non_silent_chunks += 1
|
|
242
|
+
except Exception:
|
|
243
|
+
pass
|
|
230
244
|
live_queue.send_realtime(
|
|
231
245
|
types.Blob(data=chunk, mime_type=_mime_type_for_rate(input_rate))
|
|
232
246
|
)
|
|
@@ -247,6 +261,15 @@ async def run_live_audio(
|
|
|
247
261
|
|
|
248
262
|
if not printed_any:
|
|
249
263
|
print("\n[gemcode live-audio] No model text received (audio may have been silent).")
|
|
264
|
+
if chunks_sent <= 2 or non_silent_chunks == 0:
|
|
265
|
+
print(
|
|
266
|
+
"\n[gemcode live-audio] Mic input looks silent or unavailable.\n"
|
|
267
|
+
"Check:\n"
|
|
268
|
+
"- System Settings → Privacy & Security → Microphone (allow your terminal)\n"
|
|
269
|
+
"- Your input device selection\n"
|
|
270
|
+
"Tip: set GEMCODE_LIVE_AUDIO_INPUT_DEVICE to a device index/name from sounddevice.query_devices().\n",
|
|
271
|
+
file=sys.stderr,
|
|
272
|
+
)
|
|
250
273
|
|
|
251
274
|
await runner.close()
|
|
252
275
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|