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.
Files changed (157) hide show
  1. {gemcode-0.3.101/src/gemcode.egg-info → gemcode-0.3.103}/PKG-INFO +1 -1
  2. {gemcode-0.3.101 → gemcode-0.3.103}/pyproject.toml +1 -1
  3. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/cli.py +52 -1
  4. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/live_audio_engine.py +24 -1
  5. {gemcode-0.3.101 → gemcode-0.3.103/src/gemcode.egg-info}/PKG-INFO +1 -1
  6. {gemcode-0.3.101 → gemcode-0.3.103}/LICENSE +0 -0
  7. {gemcode-0.3.101 → gemcode-0.3.103}/MANIFEST.in +0 -0
  8. {gemcode-0.3.101 → gemcode-0.3.103}/README.md +0 -0
  9. {gemcode-0.3.101 → gemcode-0.3.103}/setup.cfg +0 -0
  10. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/__init__.py +0 -0
  11. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/__main__.py +0 -0
  12. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/agent.py +0 -0
  13. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/audit.py +0 -0
  14. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/autocompact.py +0 -0
  15. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/autotune.py +0 -0
  16. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/callbacks.py +0 -0
  17. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/capability_routing.py +0 -0
  18. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/checkpoints.py +0 -0
  19. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/compaction.py +0 -0
  20. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/computer_use/__init__.py +0 -0
  21. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/computer_use/browser_computer.py +0 -0
  22. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/config.py +0 -0
  23. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/context_budget.py +0 -0
  24. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/context_warning.py +0 -0
  25. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/credentials.py +0 -0
  26. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/curated_memory.py +0 -0
  27. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/dynamic_policy.py +0 -0
  28. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/evals/harness.py +0 -0
  29. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/hitl_session.py +0 -0
  30. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/hooks.py +0 -0
  31. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/ide_protocol.py +0 -0
  32. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/ide_stdio.py +0 -0
  33. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/intent_classifier.py +0 -0
  34. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/interactions.py +0 -0
  35. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/invoke.py +0 -0
  36. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/kaira_daemon.py +0 -0
  37. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/learning.py +0 -0
  38. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/limits.py +0 -0
  39. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/logging_config.py +0 -0
  40. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/mcp_loader.py +0 -0
  41. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/memory/__init__.py +0 -0
  42. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/memory/embedding_memory_service.py +0 -0
  43. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/memory/file_memory_service.py +0 -0
  44. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/modality_tools.py +0 -0
  45. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/model_errors.py +0 -0
  46. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/model_routing.py +0 -0
  47. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/multimodal_input.py +0 -0
  48. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/openapi_loader.py +0 -0
  49. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/output_styles.py +0 -0
  50. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/paths.py +0 -0
  51. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/permissions.py +0 -0
  52. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/plugins/__init__.py +0 -0
  53. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
  54. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
  55. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/policy_profile.py +0 -0
  56. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/pricing.py +0 -0
  57. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/prompt_suggestions.py +0 -0
  58. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/__init__.py +0 -0
  59. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/config.py +0 -0
  60. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/deps.py +0 -0
  61. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/engine.py +0 -0
  62. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/stop_hooks.py +0 -0
  63. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/token_budget.py +0 -0
  64. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query/transitions.py +0 -0
  65. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/query_sanitizer.py +0 -0
  66. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/refine.py +0 -0
  67. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/repl_commands.py +0 -0
  68. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/repl_slash.py +0 -0
  69. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/review_agent.py +0 -0
  70. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/rules.py +0 -0
  71. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/session_runtime.py +0 -0
  72. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/session_store.py +0 -0
  73. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/session_summariser.py +0 -0
  74. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/skills.py +0 -0
  75. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/slash_commands.py +0 -0
  76. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/thinking.py +0 -0
  77. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tool_prompt_manifest.py +0 -0
  78. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tool_registry.py +0 -0
  79. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tool_result_store.py +0 -0
  80. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/__init__.py +0 -0
  81. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/bash.py +0 -0
  82. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/browser.py +0 -0
  83. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/compress_memory.py +0 -0
  84. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/curated_memory.py +0 -0
  85. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/edit.py +0 -0
  86. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/filesystem.py +0 -0
  87. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/notebook.py +0 -0
  88. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/notes.py +0 -0
  89. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/repo_map.py +0 -0
  90. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/search.py +0 -0
  91. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/shell.py +0 -0
  92. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/shell_gate.py +0 -0
  93. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/skills.py +0 -0
  94. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/subtask.py +0 -0
  95. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/tasks.py +0 -0
  96. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/think.py +0 -0
  97. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/todo.py +0 -0
  98. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/veomem_tools.py +0 -0
  99. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/web.py +0 -0
  100. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools/web_search.py +0 -0
  101. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tools_inspector.py +0 -0
  102. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/trust.py +0 -0
  103. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/input_handler.py +0 -0
  104. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/scrollback.py +0 -0
  105. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/spinner.py +0 -0
  106. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/welcome_banner.py +0 -0
  107. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/tui/welcome_rich.py +0 -0
  108. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/veomem_bridge.py +0 -0
  109. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/version.py +0 -0
  110. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/vertex.py +0 -0
  111. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/wal.py +0 -0
  112. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/__init__.py +0 -0
  113. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/sse_adapter.py +0 -0
  114. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/terminal_repl.py +0 -0
  115. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/web/web_sse_compat.py +0 -0
  116. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode/workspace_hints.py +0 -0
  117. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/SOURCES.txt +0 -0
  118. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/dependency_links.txt +0 -0
  119. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/entry_points.txt +0 -0
  120. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/requires.txt +0 -0
  121. {gemcode-0.3.101 → gemcode-0.3.103}/src/gemcode.egg-info/top_level.txt +0 -0
  122. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_add_dir.py +0 -0
  123. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_agent_instruction.py +0 -0
  124. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_autocompact.py +0 -0
  125. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_capability_routing.py +0 -0
  126. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_checkpoint_diff_command.py +0 -0
  127. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_cli_init.py +0 -0
  128. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_compress_memory_tool.py +0 -0
  129. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_computer_use_permissions.py +0 -0
  130. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_context_budget.py +0 -0
  131. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_context_warning.py +0 -0
  132. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_credentials.py +0 -0
  133. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_eval_harness_layout.py +0 -0
  134. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_ide_stdio_attachments.py +0 -0
  135. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_interactive_permission_ask.py +0 -0
  136. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_kaira_scheduler.py +0 -0
  137. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_modality_tools.py +0 -0
  138. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_model_error_retry.py +0 -0
  139. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_model_errors.py +0 -0
  140. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_model_routing.py +0 -0
  141. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_multimodal_input.py +0 -0
  142. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_output_styles_and_rules.py +0 -0
  143. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_paths.py +0 -0
  144. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_permissions.py +0 -0
  145. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_prompt_suggestions.py +0 -0
  146. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_repl_commands.py +0 -0
  147. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_repl_slash.py +0 -0
  148. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_skills.py +0 -0
  149. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_slash_commands.py +0 -0
  150. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_slash_completion_registry.py +0 -0
  151. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_thinking_config.py +0 -0
  152. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_token_budget.py +0 -0
  153. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_tool_context_circulation.py +0 -0
  154. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_tools.py +0 -0
  155. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_tools_inspector.py +0 -0
  156. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_web_sse_adapter.py +0 -0
  157. {gemcode-0.3.101 → gemcode-0.3.103}/tests/test_workspace_hints.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.101
3
+ Version: 0.3.103
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gemcode"
7
- version = "0.3.101"
7
+ version = "0.3.103"
8
8
  description = "Local-first coding agent on Google Gemini + ADK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -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
- if captured and "An unexpected error occurred in live flow: 1000" not in captured:
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
- response_modalities=[types.Modality.AUDIO],
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.3.101
3
+ Version: 0.3.103
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes