agent-cli 0.98.2__tar.gz → 0.98.4__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 (448) hide show
  1. {agent_cli-0.98.2 → agent_cli-0.98.4}/PKG-INFO +4 -3
  2. {agent_cli-0.98.2 → agent_cli-0.98.4}/README.md +3 -2
  3. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/transcribe.py +19 -3
  4. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/voice_edit.py +9 -1
  5. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/audio.py +75 -0
  6. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/opts.py +7 -0
  7. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/nemo.py +9 -1
  8. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/asr.py +73 -19
  9. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/transcribe.md +1 -1
  10. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +9 -1
  11. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +59 -0
  12. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +125 -42
  13. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +5 -1
  14. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +121 -109
  15. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +4 -0
  16. agent_cli-0.98.4/macos/AgentCLI/Tests/AgentCLITests/ConfigurableHotkeyControllerTests.swift +36 -0
  17. agent_cli-0.98.4/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +86 -0
  18. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/appcast.xml +30 -31
  19. agent_cli-0.98.4/tests/core/test_audio_levels.py +45 -0
  20. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_asr.py +53 -0
  21. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_nemo_backend.py +38 -0
  22. agent_cli-0.98.2/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +0 -56
  23. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
  24. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude/skills/agent-cli-dev/examples.md +0 -0
  25. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/README.md +0 -0
  26. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/marketplace.json +0 -0
  27. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/plugin.json +0 -0
  28. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
  29. {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
  30. {agent_cli-0.98.2 → agent_cli-0.98.4}/.cursorrules +0 -0
  31. {agent_cli-0.98.2 → agent_cli-0.98.4}/.dockerignore +0 -0
  32. {agent_cli-0.98.2 → agent_cli-0.98.4}/.env.example +0 -0
  33. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/logo.svg +0 -0
  34. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/release-drafter.yml +0 -0
  35. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/renovate.json +0 -0
  36. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/check_extras_sync.py +0 -0
  37. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/check_plugin_skill_sync.py +0 -0
  38. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/normalize_appcast.py +0 -0
  39. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/sync_extras.py +0 -0
  40. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/sync_requirements.py +0 -0
  41. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/automerge.yml +0 -0
  42. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/docker.yml +0 -0
  43. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/docs.yml +0 -0
  44. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/markdown-code-runner.yml +0 -0
  45. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/pytest.yml +0 -0
  46. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/release-drafter.yml +0 -0
  47. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/release.yml +0 -0
  48. {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/toc.yaml +0 -0
  49. {agent_cli-0.98.2 → agent_cli-0.98.4}/.gitignore +0 -0
  50. {agent_cli-0.98.2 → agent_cli-0.98.4}/.jscpd.json +0 -0
  51. {agent_cli-0.98.2 → agent_cli-0.98.4}/.pre-commit-config.yaml +0 -0
  52. {agent_cli-0.98.2 → agent_cli-0.98.4}/.prompts/docs-review.md +0 -0
  53. {agent_cli-0.98.2 → agent_cli-0.98.4}/.prompts/pr-review.md +0 -0
  54. {agent_cli-0.98.2 → agent_cli-0.98.4}/CLAUDE.md +0 -0
  55. {agent_cli-0.98.2 → agent_cli-0.98.4}/LICENSE +0 -0
  56. {agent_cli-0.98.2 → agent_cli-0.98.4}/LLAMA_SERVER_USAGE.md +0 -0
  57. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/__init__.py +0 -0
  58. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/__main__.py +0 -0
  59. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_extras.json +0 -0
  60. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_overrides/nemo-whisper.txt +0 -0
  61. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/.gitkeep +0 -0
  62. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/audio.txt +0 -0
  63. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/diarization.txt +0 -0
  64. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/faster-whisper.txt +0 -0
  65. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/kokoro.txt +0 -0
  66. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/llm.txt +0 -0
  67. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/memory.txt +0 -0
  68. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/mlx-whisper.txt +0 -0
  69. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/nemo-whisper.txt +0 -0
  70. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/piper.txt +0 -0
  71. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/rag.txt +0 -0
  72. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/server.txt +0 -0
  73. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/speed.txt +0 -0
  74. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/vad.txt +0 -0
  75. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/vectordb.txt +0 -0
  76. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/whisper-transformers.txt +0 -0
  77. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/wyoming.txt +0 -0
  78. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_tools.py +0 -0
  79. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/__init__.py +0 -0
  80. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/_voice_agent_common.py +0 -0
  81. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/assistant.py +0 -0
  82. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/autocorrect.py +0 -0
  83. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/chat.py +0 -0
  84. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/diarize_live_session.py +0 -0
  85. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/memory/__init__.py +0 -0
  86. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/memory/add.py +0 -0
  87. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/memory/proxy.py +0 -0
  88. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/rag_proxy.py +0 -0
  89. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/speak.py +0 -0
  90. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/speakers.py +0 -0
  91. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/transcribe_live.py +0 -0
  92. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/api.py +0 -0
  93. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/cli.py +0 -0
  94. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/config.py +0 -0
  95. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/config_cmd.py +0 -0
  96. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/constants.py +0 -0
  97. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/__init__.py +0 -0
  98. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/alignment.py +0 -0
  99. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/audio_format.py +0 -0
  100. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/chroma.py +0 -0
  101. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/deps.py +0 -0
  102. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/diarization.py +0 -0
  103. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/openai_proxy.py +0 -0
  104. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/process.py +0 -0
  105. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/reranker.py +0 -0
  106. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/speaker_identity.py +0 -0
  107. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/sse.py +0 -0
  108. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/transcription_logger.py +0 -0
  109. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/utils.py +0 -0
  110. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/vad.py +0 -0
  111. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/watch.py +0 -0
  112. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/daemon/__init__.py +0 -0
  113. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/daemon/cli.py +0 -0
  114. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/__init__.py +0 -0
  115. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/_branch_name.py +0 -0
  116. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/_config.py +0 -0
  117. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/_output.py +0 -0
  118. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/cleanup.py +0 -0
  119. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/cli.py +0 -0
  120. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/__init__.py +0 -0
  121. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/aider.py +0 -0
  122. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/base.py +0 -0
  123. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/claude.py +0 -0
  124. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/codex.py +0 -0
  125. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
  126. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/copilot.py +0 -0
  127. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
  128. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/gemini.py +0 -0
  129. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/opencode.py +0 -0
  130. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/registry.py +0 -0
  131. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/__init__.py +0 -0
  132. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/base.py +0 -0
  133. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/cursor.py +0 -0
  134. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/emacs.py +0 -0
  135. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/jetbrains.py +0 -0
  136. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/nano.py +0 -0
  137. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/neovim.py +0 -0
  138. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/registry.py +0 -0
  139. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/sublime.py +0 -0
  140. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/vim.py +0 -0
  141. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/vscode.py +0 -0
  142. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/zed.py +0 -0
  143. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/hooks.py +0 -0
  144. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/launch.py +0 -0
  145. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/project.py +0 -0
  146. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/registry.py +0 -0
  147. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/skill/SKILL.md +0 -0
  148. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/skill/examples.md +0 -0
  149. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/__init__.py +0 -0
  150. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/apple_terminal.py +0 -0
  151. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/base.py +0 -0
  152. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/gnome.py +0 -0
  153. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/iterm2.py +0 -0
  154. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/kitty.py +0 -0
  155. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/registry.py +0 -0
  156. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/tmux.py +0 -0
  157. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/warp.py +0 -0
  158. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/zellij.py +0 -0
  159. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/worktree.py +0 -0
  160. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/docs_gen.py +0 -0
  161. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/example-config.toml +0 -0
  162. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/__init__.py +0 -0
  163. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/common.py +0 -0
  164. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/extras.py +0 -0
  165. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/hotkeys.py +0 -0
  166. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/launchd.py +0 -0
  167. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/service_config.py +0 -0
  168. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/services.py +0 -0
  169. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/systemd.py +0 -0
  170. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/__init__.py +0 -0
  171. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_files.py +0 -0
  172. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_filters.py +0 -0
  173. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_git.py +0 -0
  174. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_indexer.py +0 -0
  175. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_ingest.py +0 -0
  176. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_persistence.py +0 -0
  177. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_prompt.py +0 -0
  178. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_retrieval.py +0 -0
  179. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_store.py +0 -0
  180. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_streaming.py +0 -0
  181. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_tasks.py +0 -0
  182. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/api.py +0 -0
  183. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/client.py +0 -0
  184. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/engine.py +0 -0
  185. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/entities.py +0 -0
  186. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/models.py +0 -0
  187. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/py.typed +0 -0
  188. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/__init__.py +0 -0
  189. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_indexer.py +0 -0
  190. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_indexing.py +0 -0
  191. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_prompt.py +0 -0
  192. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_retriever.py +0 -0
  193. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_store.py +0 -0
  194. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_utils.py +0 -0
  195. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/api.py +0 -0
  196. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/client.py +0 -0
  197. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/engine.py +0 -0
  198. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/models.py +0 -0
  199. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/.runtime/.gitkeep +0 -0
  200. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/__init__.py +0 -0
  201. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
  202. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
  203. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
  204. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
  205. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
  206. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
  207. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
  208. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
  209. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
  210. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
  211. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
  212. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
  213. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
  214. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
  215. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/run-openwakeword.sh +0 -0
  216. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
  217. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-linux.sh +0 -0
  218. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
  219. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-macos.sh +0 -0
  220. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-windows.ps1 +0 -0
  221. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
  222. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/start-all-services.sh +0 -0
  223. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/__init__.py +0 -0
  224. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/cli.py +0 -0
  225. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/common.py +0 -0
  226. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/model_manager.py +0 -0
  227. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/model_registry.py +0 -0
  228. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/proxy/__init__.py +0 -0
  229. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/proxy/api.py +0 -0
  230. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/streaming.py +0 -0
  231. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/__init__.py +0 -0
  232. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/api.py +0 -0
  233. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/__init__.py +0 -0
  234. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/base.py +0 -0
  235. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/kokoro.py +0 -0
  236. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/piper.py +0 -0
  237. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/model_manager.py +0 -0
  238. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/model_registry.py +0 -0
  239. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/wyoming_handler.py +0 -0
  240. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/__init__.py +0 -0
  241. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/api.py +0 -0
  242. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/__init__.py +0 -0
  243. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/base.py +0 -0
  244. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
  245. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/mlx.py +0 -0
  246. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/transformers.py +0 -0
  247. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/languages.py +0 -0
  248. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/model_manager.py +0 -0
  249. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/model_registry.py +0 -0
  250. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/wyoming_handler.py +0 -0
  251. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/__init__.py +0 -0
  252. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/_wyoming_utils.py +0 -0
  253. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/llm.py +0 -0
  254. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/tts.py +0 -0
  255. {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/wake_word.py +0 -0
  256. {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/docker-compose.yml +0 -0
  257. {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/memory-proxy.Dockerfile +0 -0
  258. {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/rag-proxy.Dockerfile +0 -0
  259. {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/transcribe-proxy.Dockerfile +0 -0
  260. {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/tts.Dockerfile +0 -0
  261. {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/whisper.Dockerfile +0 -0
  262. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/CNAME +0 -0
  263. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/architecture/index.md +0 -0
  264. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/architecture/memory.md +0 -0
  265. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/architecture/rag.md +0 -0
  266. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/assistant.md +0 -0
  267. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/autocorrect.md +0 -0
  268. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/chat.md +0 -0
  269. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/config.md +0 -0
  270. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/daemon.md +0 -0
  271. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/dev.md +0 -0
  272. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/diarize-live-session.md +0 -0
  273. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/index.md +0 -0
  274. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/install-extras.md +0 -0
  275. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/install-hotkeys.md +0 -0
  276. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/install-services.md +0 -0
  277. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/memory.md +0 -0
  278. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/rag-proxy.md +0 -0
  279. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/index.md +0 -0
  280. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/transcribe-proxy.md +0 -0
  281. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/tts.md +0 -0
  282. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/whisper.md +0 -0
  283. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/speak.md +0 -0
  284. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/speakers.md +0 -0
  285. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/start-services.md +0 -0
  286. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/transcribe-live.md +0 -0
  287. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/voice-edit.md +0 -0
  288. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/configuration.md +0 -0
  289. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/getting-started.md +0 -0
  290. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/iOS_Shortcut_Guide.md +0 -0
  291. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/index.md +0 -0
  292. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/docker.md +0 -0
  293. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/index.md +0 -0
  294. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/linux.md +0 -0
  295. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/macos-app.md +0 -0
  296. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/macos.md +0 -0
  297. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/nixos.md +0 -0
  298. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/windows.md +0 -0
  299. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/logo-avatar.svg +0 -0
  300. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/logo-clean.svg +0 -0
  301. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
  302. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/run_markdown_code_runner.py +0 -0
  303. {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/system-integration.md +0 -0
  304. {agent_cli-0.98.2 → agent_cli-0.98.4}/example.agent-cli-config.toml +0 -0
  305. {agent_cli-0.98.2 → agent_cli-0.98.4}/justfile +0 -0
  306. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Package.resolved +0 -0
  307. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Package.swift +0 -0
  308. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/README.md +0 -0
  309. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
  310. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Resources/Info.plist +0 -0
  311. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
  312. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +0 -0
  313. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +0 -0
  314. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
  315. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AppMetadata.swift +0 -0
  316. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AppUpdater.swift +0 -0
  317. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +0 -0
  318. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +0 -0
  319. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
  320. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
  321. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatus.swift +0 -0
  322. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatusRow.swift +0 -0
  323. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuActivityTracker.swift +0 -0
  324. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -0
  325. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
  326. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +0 -0
  327. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +0 -0
  328. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
  329. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/SettingsWindowController.swift +0 -0
  330. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/StatusMenuController.swift +0 -0
  331. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
  332. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
  333. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
  334. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
  335. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +0 -0
  336. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +0 -0
  337. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/build-macos-app.sh +0 -0
  338. {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/test-macos-app-e2e.sh +0 -0
  339. {agent_cli-0.98.2 → agent_cli-0.98.4}/pyproject.toml +0 -0
  340. {agent_cli-0.98.2 → agent_cli-0.98.4}/reddit.md +0 -0
  341. {agent_cli-0.98.2 → agent_cli-0.98.4}/shell.nix +0 -0
  342. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/__init__.py +0 -0
  343. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/__init__.py +0 -0
  344. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_fix_my_text.py +0 -0
  345. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_interactive.py +0 -0
  346. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_interactive_extra.py +0 -0
  347. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_memory_add.py +0 -0
  348. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_speak.py +0 -0
  349. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_speak_e2e.py +0 -0
  350. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_speakers.py +0 -0
  351. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe.py +0 -0
  352. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_agent.py +0 -0
  353. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_e2e.py +0 -0
  354. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_live.py +0 -0
  355. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_recovery.py +0 -0
  356. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_tts_common.py +0 -0
  357. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_tts_common_extra.py +0 -0
  358. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_voice_agent_common.py +0 -0
  359. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_voice_edit.py +0 -0
  360. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_voice_edit_e2e.py +0 -0
  361. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_wake_word_assistant.py +0 -0
  362. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/conftest.py +0 -0
  363. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/__init__.py +0 -0
  364. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_audio.py +0 -0
  365. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_audio_format.py +0 -0
  366. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_chroma.py +0 -0
  367. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_sse.py +0 -0
  368. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_vad.py +0 -0
  369. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_watch.py +0 -0
  370. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/__init__.py +0 -0
  371. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_cleanup.py +0 -0
  372. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_cli.py +0 -0
  373. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_coding_agents.py +0 -0
  374. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_editors.py +0 -0
  375. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_hooks.py +0 -0
  376. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_launch.py +0 -0
  377. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_project.py +0 -0
  378. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_terminals.py +0 -0
  379. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_verification.py +0 -0
  380. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_worktree.py +0 -0
  381. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/install/__init__.py +0 -0
  382. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/install/test_extras.py +0 -0
  383. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/install/test_launchd.py +0 -0
  384. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/__init__.py +0 -0
  385. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_api_health.py +0 -0
  386. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_api_integration_liveish.py +0 -0
  387. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_client.py +0 -0
  388. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_engine.py +0 -0
  389. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_files.py +0 -0
  390. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_filters.py +0 -0
  391. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_git_integration.py +0 -0
  392. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_indexer.py +0 -0
  393. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_memory_integration.py +0 -0
  394. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_proxy_passthrough.py +0 -0
  395. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_store.py +0 -0
  396. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_utils.py +0 -0
  397. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/__init__.py +0 -0
  398. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/audio.py +0 -0
  399. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/llm.py +0 -0
  400. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/wyoming.py +0 -0
  401. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/__init__.py +0 -0
  402. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_api.py +0 -0
  403. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_engine.py +0 -0
  404. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_history.py +0 -0
  405. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_indexer.py +0 -0
  406. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_indexing.py +0 -0
  407. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_rag_client.py +0 -0
  408. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_rag_integration_liveish.py +0 -0
  409. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_rag_proxy_passthrough.py +0 -0
  410. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_retriever.py +0 -0
  411. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_store.py +0 -0
  412. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_utils.py +0 -0
  413. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_alignment.py +0 -0
  414. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_api.py +0 -0
  415. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_api_integration.py +0 -0
  416. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_asr_recovery.py +0 -0
  417. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_audio_e2e.py +0 -0
  418. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_cli.py +0 -0
  419. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_config.py +0 -0
  420. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_config_cmd.py +0 -0
  421. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_daemon.py +0 -0
  422. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_diarization.py +0 -0
  423. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_diarize_live_session.py +0 -0
  424. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_docs_gen.py +0 -0
  425. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_env_vars.py +0 -0
  426. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_faster_whisper_backend.py +0 -0
  427. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_json_output.py +0 -0
  428. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_llm.py +0 -0
  429. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_llm_gemini.py +0 -0
  430. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_macos_app.py +0 -0
  431. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_memory_tools.py +0 -0
  432. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_mlx_backend.py +0 -0
  433. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_normalize_appcast.py +0 -0
  434. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_process_manager.py +0 -0
  435. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_requires_extras.py +0 -0
  436. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_server_streaming.py +0 -0
  437. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_server_tts.py +0 -0
  438. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_server_whisper.py +0 -0
  439. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_services.py +0 -0
  440. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_speaker_identity.py +0 -0
  441. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_tools.py +0 -0
  442. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_transformers_backend.py +0 -0
  443. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_tts.py +0 -0
  444. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_utils.py +0 -0
  445. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_wake_word.py +0 -0
  446. {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_wyoming_utils.py +0 -0
  447. {agent_cli-0.98.2 → agent_cli-0.98.4}/uv.lock +0 -0
  448. {agent_cli-0.98.2 → agent_cli-0.98.4}/zensical.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-cli
3
- Version: 0.98.2
3
+ Version: 0.98.4
4
4
  Summary: A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance.
5
5
  Project-URL: Homepage, https://github.com/basnijholt/agent-cli
6
6
  Author-email: Bas Nijholt <bas@nijho.lt>
@@ -899,8 +899,9 @@ the `[defaults]` section of your configuration file.
899
899
  │ --help -h Show this message and exit. │
900
900
  ╰────────────────────────────────────────────────────────────────────────────────────────╯
901
901
  ╭─ LLM Configuration ────────────────────────────────────────────────────────────────────╮
902
- │ --extra-instructions TEXT Extra instructions appended to the LLM
903
- │ cleanup prompt (requires --llm).
902
+ │ --extra-instructions TEXT Extra ASR context where supported, and LLM
903
+ │ cleanup instructions when --llm is enabled.
904
+ │ The NeMo backend ignores ASR text prompts. │
904
905
  │ --llm --no-llm Clean up transcript with LLM: fix errors, │
905
906
  │ add punctuation, remove filler words. Uses │
906
907
  │ --extra-instructions if set (via CLI or │
@@ -791,8 +791,9 @@ the `[defaults]` section of your configuration file.
791
791
  │ --help -h Show this message and exit. │
792
792
  ╰────────────────────────────────────────────────────────────────────────────────────────╯
793
793
  ╭─ LLM Configuration ────────────────────────────────────────────────────────────────────╮
794
- │ --extra-instructions TEXT Extra instructions appended to the LLM
795
- │ cleanup prompt (requires --llm).
794
+ │ --extra-instructions TEXT Extra ASR context where supported, and LLM
795
+ │ cleanup instructions when --llm is enabled.
796
+ │ The NeMo backend ignores ASR text prompts. │
796
797
  │ --llm --no-llm Clean up transcript with LLM: fix errors, │
797
798
  │ add punctuation, remove filler words. Uses │
798
799
  │ --extra-instructions if set (via CLI or │
@@ -10,14 +10,14 @@ import time
10
10
  from contextlib import suppress
11
11
  from datetime import UTC, datetime, timedelta
12
12
  from pathlib import Path # noqa: TC003
13
- from typing import Any, TypedDict
13
+ from typing import TYPE_CHECKING, Any, TypedDict
14
14
 
15
15
  import typer
16
16
 
17
17
  from agent_cli import config, opts
18
18
  from agent_cli.cli import app
19
19
  from agent_cli.core import process
20
- from agent_cli.core.audio import setup_devices
20
+ from agent_cli.core.audio import AudioLevelLogWriter, setup_devices
21
21
  from agent_cli.core.deps import requires_extras
22
22
  from agent_cli.core.diarization import (
23
23
  SpeakerDiarizer,
@@ -54,6 +54,9 @@ from agent_cli.services.llm import process_and_update_clipboard
54
54
 
55
55
  LOGGER = logging.getLogger()
56
56
 
57
+ if TYPE_CHECKING:
58
+ from collections.abc import Callable
59
+
57
60
 
58
61
  class TranscriptResult(TypedDict, total=False):
59
62
  """Result of transcription with optional LLM processing."""
@@ -361,6 +364,7 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
361
364
  diarization_cfg: config.Diarization | None = None,
362
365
  emit_output: bool = True,
363
366
  raise_diarization_errors: bool = False,
367
+ audio_level_callback: Callable[[bytes], None] | None = None,
364
368
  ) -> TranscriptResult:
365
369
  """Unified async entry point for both live and file-based transcription."""
366
370
  start_time = time.monotonic()
@@ -451,6 +455,7 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
451
455
  save_recording=save_recording,
452
456
  extra_instructions=extra_instructions,
453
457
  recording_path_callback=_set_saved_recording_path,
458
+ audio_level_callback=audio_level_callback,
454
459
  )
455
460
 
456
461
  elapsed = time.monotonic() - start_time
@@ -598,7 +603,10 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
598
603
  extra_instructions: str | None = typer.Option(
599
604
  None,
600
605
  "--extra-instructions",
601
- help="Extra instructions appended to the LLM cleanup prompt (requires `--llm`).",
606
+ help=(
607
+ "Extra ASR context where supported, and LLM cleanup instructions when "
608
+ "`--llm` is enabled. The NeMo backend ignores ASR text prompts."
609
+ ),
602
610
  rich_help_panel="LLM Configuration",
603
611
  ),
604
612
  from_file: Path | None = opts.FROM_FILE,
@@ -641,6 +649,7 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
641
649
  config_file: str | None = opts.CONFIG_FILE,
642
650
  print_args: bool = opts.PRINT_ARGS,
643
651
  transcription_log: Path | None = opts.TRANSCRIPTION_LOG,
652
+ voice_level_log: Path | None = opts.VOICE_LEVEL_LOG,
644
653
  # --- Diarization Options ---
645
654
  diarize: bool = opts.DIARIZE,
646
655
  diarize_format: opts.DiarizeFormat = opts.DIARIZE_FORMAT,
@@ -691,6 +700,9 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
691
700
  # Expand user path for transcription log
692
701
  if transcription_log:
693
702
  transcription_log = transcription_log.expanduser()
703
+ voice_level_log = _option_default(voice_level_log)
704
+ if voice_level_log:
705
+ voice_level_log = voice_level_log.expanduser()
694
706
 
695
707
  enroll_speakers = _option_default(enroll_speakers)
696
708
  identify_speakers = _option_default(identify_speakers)
@@ -895,6 +907,7 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
895
907
  # Use context manager before audio setup so --stop can target startup reliably.
896
908
  try:
897
909
  with process.pid_file_context(process_name), suppress(KeyboardInterrupt):
910
+ audio_level_writer = AudioLevelLogWriter(voice_level_log) if voice_level_log else None
898
911
  audio_in_cfg = config.AudioInput(
899
912
  input_device_index=input_device_index,
900
913
  input_device_name=input_device_name,
@@ -926,6 +939,9 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
926
939
  diarization_cfg=diarization_cfg,
927
940
  emit_output=not json_output,
928
941
  raise_diarization_errors=diarize,
942
+ audio_level_callback=audio_level_writer.write_chunk
943
+ if audio_level_writer
944
+ else None,
929
945
  ),
930
946
  )
931
947
  except ImportError as exc:
@@ -46,7 +46,7 @@ from agent_cli.agents._voice_agent_common import (
46
46
  )
47
47
  from agent_cli.cli import app
48
48
  from agent_cli.core import process
49
- from agent_cli.core.audio import setup_devices
49
+ from agent_cli.core.audio import AudioLevelLogWriter, setup_devices
50
50
  from agent_cli.core.deps import requires_extras
51
51
  from agent_cli.core.utils import (
52
52
  enable_json_mode,
@@ -106,6 +106,7 @@ async def _async_main(
106
106
  openai_tts_cfg: config.OpenAITTS,
107
107
  kokoro_tts_cfg: config.KokoroTTS,
108
108
  gemini_tts_cfg: config.GeminiTTS,
109
+ audio_level_log: Path | None = None,
109
110
  ) -> str | None:
110
111
  """Core asynchronous logic for the voice assistant."""
111
112
  device_info = setup_devices(general_cfg, audio_in_cfg, audio_out_cfg)
@@ -114,6 +115,7 @@ async def _async_main(
114
115
  input_device_index, _, tts_output_device_index = device_info
115
116
  audio_in_cfg.input_device_index = input_device_index
116
117
  audio_out_cfg.output_device_index = tts_output_device_index
118
+ audio_level_writer = AudioLevelLogWriter(audio_level_log) if audio_level_log else None
117
119
 
118
120
  original_text = get_clipboard_text()
119
121
  if original_text is None:
@@ -132,6 +134,7 @@ async def _async_main(
132
134
  LOGGER,
133
135
  live=live,
134
136
  quiet=general_cfg.quiet,
137
+ audio_level_callback=audio_level_writer.write_chunk if audio_level_writer else None,
135
138
  )
136
139
 
137
140
  if not audio_data:
@@ -226,6 +229,7 @@ def voice_edit(
226
229
  list_devices: bool = opts.LIST_DEVICES,
227
230
  quiet: bool = opts.QUIET,
228
231
  json_output: bool = opts.JSON_OUTPUT,
232
+ voice_level_log: Path | None = opts.VOICE_LEVEL_LOG,
229
233
  config_file: str | None = opts.CONFIG_FILE,
230
234
  print_args: bool = opts.PRINT_ARGS,
231
235
  ) -> None:
@@ -255,6 +259,9 @@ def voice_edit(
255
259
  enable_json_mode()
256
260
 
257
261
  setup_logging(log_level, log_file, quiet=effective_quiet)
262
+ voice_level_log = getattr(voice_level_log, "default", voice_level_log)
263
+ if voice_level_log:
264
+ voice_level_log = voice_level_log.expanduser()
258
265
  general_cfg = config.General(
259
266
  log_level=log_level,
260
267
  log_file=log_file,
@@ -293,6 +300,7 @@ def voice_edit(
293
300
  openai_tts_cfg=cfgs.openai_tts,
294
301
  kokoro_tts_cfg=cfgs.kokoro_tts,
295
302
  gemini_tts_cfg=cfgs.gemini_tts,
303
+ audio_level_log=voice_level_log,
296
304
  ),
297
305
  )
298
306
  if json_output:
@@ -4,10 +4,15 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import functools
7
+ import json
7
8
  import logging
9
+ import math
10
+ import struct
8
11
  import threading
12
+ import time
9
13
  from contextlib import asynccontextmanager, contextmanager
10
14
  from dataclasses import dataclass
15
+ from datetime import UTC, datetime
11
16
  from typing import TYPE_CHECKING, Literal
12
17
 
13
18
  from rich.text import Text
@@ -22,6 +27,7 @@ from agent_cli.core.utils import (
22
27
 
23
28
  if TYPE_CHECKING:
24
29
  from collections.abc import AsyncGenerator, Awaitable, Callable, Generator
30
+ from pathlib import Path
25
31
 
26
32
  import sounddevice as sd
27
33
  from rich.live import Live
@@ -30,6 +36,7 @@ if TYPE_CHECKING:
30
36
 
31
37
  LOGGER = logging.getLogger(__name__)
32
38
  _AUDIO_SHUTDOWN_TIMEOUT_SECONDS = 0.5
39
+ _MINIMUM_INPUT_DECIBELS = -55.0
33
40
 
34
41
 
35
42
  @dataclass
@@ -64,6 +71,74 @@ class StreamConfig:
64
71
  )
65
72
 
66
73
 
74
+ def normalized_audio_level(chunk: bytes) -> float:
75
+ """Return a 0...1 speech level from mono little-endian int16 PCM."""
76
+ sample_count = len(chunk) // constants.AUDIO_FORMAT_WIDTH
77
+ if sample_count <= 0:
78
+ return 0.0
79
+
80
+ pcm = chunk[: sample_count * constants.AUDIO_FORMAT_WIDTH]
81
+ samples = struct.unpack(f"<{sample_count}h", pcm)
82
+ mean_square = sum((sample / 32768.0) ** 2 for sample in samples) / sample_count
83
+ if mean_square <= 0:
84
+ return 0.0
85
+
86
+ root_mean_square = math.sqrt(mean_square)
87
+ decibels = 20 * math.log10(root_mean_square)
88
+ if decibels <= _MINIMUM_INPUT_DECIBELS:
89
+ return 0.0
90
+
91
+ linear_level = (decibels - _MINIMUM_INPUT_DECIBELS) / abs(_MINIMUM_INPUT_DECIBELS)
92
+ return min(1.0, math.sqrt(linear_level))
93
+
94
+
95
+ class AudioLevelLogWriter:
96
+ """Append normalized audio levels for UI consumers."""
97
+
98
+ def __init__(
99
+ self,
100
+ path: Path,
101
+ *,
102
+ interval_seconds: float = 0.05,
103
+ monotonic_clock: Callable[[], float] = time.monotonic,
104
+ timestamp_clock: Callable[[], datetime] = lambda: datetime.now(UTC),
105
+ ) -> None:
106
+ """Create a writer and clear stale samples at the destination."""
107
+ self.path = path.expanduser()
108
+ self.interval_seconds = interval_seconds
109
+ self.monotonic_clock = monotonic_clock
110
+ self.timestamp_clock = timestamp_clock
111
+ self._last_write = -math.inf
112
+ self._enabled = True
113
+ self._lock = threading.Lock()
114
+ try:
115
+ self.path.parent.mkdir(parents=True, exist_ok=True)
116
+ self.path.write_text("")
117
+ except OSError:
118
+ self._enabled = False
119
+
120
+ def write_chunk(self, chunk: bytes) -> None:
121
+ """Append one normalized level sample for a PCM chunk."""
122
+ with self._lock:
123
+ if not self._enabled:
124
+ return
125
+ now = self.monotonic_clock()
126
+ if now - self._last_write < self.interval_seconds:
127
+ return
128
+ self._last_write = now
129
+
130
+ entry = {
131
+ "timestamp": self.timestamp_clock().isoformat(),
132
+ "level": round(normalized_audio_level(chunk), 4),
133
+ }
134
+ try:
135
+ with self.path.open("a", encoding="utf-8") as file:
136
+ file.write(json.dumps(entry, separators=(",", ":")))
137
+ file.write("\n")
138
+ except OSError:
139
+ self._enabled = False
140
+
141
+
67
142
  class _AudioTee:
68
143
  """A thread-safe class to tee a continuous audio stream into multiple asyncio queues.
69
144
 
@@ -429,6 +429,13 @@ TRANSCRIPTION_LOG: Path | None = typer.Option(
429
429
  "Recent entries provide context for LLM cleanup.",
430
430
  rich_help_panel="General Options",
431
431
  )
432
+ VOICE_LEVEL_LOG: Path | None = typer.Option(
433
+ None,
434
+ "--voice-level-log",
435
+ help="Append normalized microphone levels to a JSONL file for UI indicators.",
436
+ hidden=True,
437
+ rich_help_panel="General Options",
438
+ )
432
439
 
433
440
  # --- Server Options ---
434
441
  SERVER_HOST: str = typer.Option(
@@ -344,6 +344,7 @@ class NemoWhisperBackend:
344
344
  self._resolved_model = _resolve_model_name(config.model_name)
345
345
  self._executor: ProcessPoolExecutor | None = None
346
346
  self._device: str | None = None
347
+ self._warned_initial_prompt_ignored = False
347
348
 
348
349
  @property
349
350
  def is_loaded(self) -> bool:
@@ -415,7 +416,7 @@ class NemoWhisperBackend:
415
416
  source_filename: str | None = None,
416
417
  language: str | None = None,
417
418
  task: Literal["transcribe", "translate"] = "transcribe", # noqa: ARG002
418
- initial_prompt: str | None = None, # noqa: ARG002
419
+ initial_prompt: str | None = None,
419
420
  temperature: float = 0.0, # noqa: ARG002
420
421
  vad_filter: bool = True, # noqa: ARG002
421
422
  word_timestamps: bool = False,
@@ -424,6 +425,13 @@ class NemoWhisperBackend:
424
425
  if self._executor is None:
425
426
  msg = "Model not loaded. Call load() first."
426
427
  raise RuntimeError(msg)
428
+ if initial_prompt and not self._warned_initial_prompt_ignored:
429
+ logger.warning(
430
+ "Whisper-style initial prompts are not supported by the agent-cli NeMo backend; "
431
+ "ignoring prompt for model %s",
432
+ self._config.model_name,
433
+ )
434
+ self._warned_initial_prompt_ignored = True
427
435
 
428
436
  audio = await asyncio.to_thread(_prepare_audio_for_nemo, audio, source_filename)
429
437
 
@@ -210,6 +210,31 @@ def create_recorded_audio_transcriber(
210
210
  raise ValueError(msg)
211
211
 
212
212
 
213
+ def _schedule_audio_level_callback(
214
+ pending_tasks: set[asyncio.Task[None]],
215
+ audio_level_callback: Callable[[bytes], None],
216
+ chunk: bytes,
217
+ logger: logging.Logger,
218
+ ) -> None:
219
+ """Run level callbacks off the event loop so UI metering cannot delay ASR sends."""
220
+
221
+ async def run_callback() -> None:
222
+ try:
223
+ await asyncio.to_thread(audio_level_callback, chunk)
224
+ except Exception:
225
+ logger.exception("Audio level callback failed")
226
+
227
+ task = asyncio.create_task(run_callback())
228
+ pending_tasks.add(task)
229
+ task.add_done_callback(pending_tasks.discard)
230
+
231
+
232
+ async def _finish_audio_level_callbacks(pending_tasks: set[asyncio.Task[None]]) -> None:
233
+ """Wait for scheduled level callbacks to finish before returning."""
234
+ if pending_tasks:
235
+ await asyncio.gather(*pending_tasks, return_exceptions=True)
236
+
237
+
213
238
  async def _send_audio(
214
239
  client: AsyncClient,
215
240
  stream: sd.InputStream,
@@ -221,6 +246,7 @@ async def _send_audio(
221
246
  save_recording: bool = True,
222
247
  initial_prompt: str | None = None,
223
248
  recording_path_callback: Callable[[Path], None] | None = None,
249
+ audio_level_callback: Callable[[bytes], None] | None = None,
224
250
  ) -> None:
225
251
  """Read from mic and send to Wyoming server."""
226
252
  from wyoming.asr import Transcribe # noqa: PLC0415
@@ -233,11 +259,19 @@ async def _send_audio(
233
259
 
234
260
  # Buffer to save audio if requested
235
261
  audio_buffer = io.BytesIO() if save_recording else None
262
+ pending_audio_level_tasks: set[asyncio.Task[None]] = set()
236
263
 
237
264
  async def send_chunk(chunk: bytes) -> None:
238
265
  """Send audio chunk to ASR server and optionally buffer it."""
239
266
  if audio_buffer is not None:
240
267
  audio_buffer.write(chunk)
268
+ if audio_level_callback:
269
+ _schedule_audio_level_callback(
270
+ pending_audio_level_tasks,
271
+ audio_level_callback,
272
+ chunk,
273
+ logger,
274
+ )
241
275
  await client.write_event(AudioChunk(audio=chunk, **constants.WYOMING_AUDIO_CONFIG).event())
242
276
 
243
277
  try:
@@ -252,16 +286,19 @@ async def _send_audio(
252
286
  progress_style="blue",
253
287
  )
254
288
  finally:
255
- await client.write_event(AudioStop().event())
256
- logger.debug("Sent AudioStop")
289
+ try:
290
+ await client.write_event(AudioStop().event())
291
+ logger.debug("Sent AudioStop")
257
292
 
258
- # Save the recording to disk if requested
259
- if save_recording and audio_buffer:
260
- audio_data = audio_buffer.getvalue()
261
- if audio_data:
262
- saved_path = _save_audio_to_file(audio_data, logger)
263
- if saved_path and recording_path_callback:
264
- recording_path_callback(saved_path)
293
+ # Save the recording to disk if requested
294
+ if save_recording and audio_buffer:
295
+ audio_data = audio_buffer.getvalue()
296
+ if audio_data:
297
+ saved_path = _save_audio_to_file(audio_data, logger)
298
+ if saved_path and recording_path_callback:
299
+ recording_path_callback(saved_path)
300
+ finally:
301
+ await _finish_audio_level_callbacks(pending_audio_level_tasks)
265
302
 
266
303
 
267
304
  async def record_audio_to_buffer(queue: asyncio.Queue, logger: logging.Logger) -> bytes:
@@ -328,6 +365,7 @@ async def record_audio_with_manual_stop(
328
365
  live: Live | None = None,
329
366
  save_recording: bool = True,
330
367
  recording_path_callback: Callable[[Path], None] | None = None,
368
+ audio_level_callback: Callable[[bytes], None] | None = None,
331
369
  ) -> bytes:
332
370
  """Record audio to a buffer using a manual stop signal.
333
371
 
@@ -339,29 +377,41 @@ async def record_audio_with_manual_stop(
339
377
  live: Rich Live display for progress
340
378
  save_recording: If True, save the recording to disk
341
379
  recording_path_callback: Optional callback invoked with the saved WAV path.
380
+ audio_level_callback: Optional callback invoked with each PCM chunk.
342
381
 
343
382
  Returns:
344
383
  The recorded audio data as bytes
345
384
 
346
385
  """
347
386
  audio_buffer = io.BytesIO()
387
+ pending_audio_level_tasks: set[asyncio.Task[None]] = set()
348
388
 
349
389
  def buffer_chunk(chunk: bytes) -> None:
350
390
  """Buffer audio chunk."""
351
391
  audio_buffer.write(chunk)
392
+ if audio_level_callback:
393
+ _schedule_audio_level_callback(
394
+ pending_audio_level_tasks,
395
+ audio_level_callback,
396
+ chunk,
397
+ logger,
398
+ )
352
399
 
353
400
  stream_config = setup_input_stream(input_device_index)
354
401
  with open_audio_stream(stream_config) as stream:
355
- await read_audio_stream(
356
- stream=stream,
357
- stop_event=stop_event,
358
- chunk_handler=buffer_chunk,
359
- logger=logger,
360
- live=live,
361
- quiet=quiet,
362
- progress_message="Recording",
363
- progress_style="green",
364
- )
402
+ try:
403
+ await read_audio_stream(
404
+ stream=stream,
405
+ stop_event=stop_event,
406
+ chunk_handler=buffer_chunk,
407
+ logger=logger,
408
+ live=live,
409
+ quiet=quiet,
410
+ progress_message="Recording",
411
+ progress_style="green",
412
+ )
413
+ finally:
414
+ await _finish_audio_level_callbacks(pending_audio_level_tasks)
365
415
 
366
416
  audio_data = audio_buffer.getvalue()
367
417
 
@@ -431,6 +481,7 @@ async def _transcribe_live_audio_wyoming(
431
481
  final_callback: Callable[[str], None] | None = None,
432
482
  extra_instructions: str | None = None,
433
483
  recording_path_callback: Callable[[Path], None] | None = None,
484
+ audio_level_callback: Callable[[bytes], None] | None = None,
434
485
  **_kwargs: object,
435
486
  ) -> str | None:
436
487
  """Unified ASR transcription function."""
@@ -460,6 +511,7 @@ async def _transcribe_live_audio_wyoming(
460
511
  save_recording=save_recording,
461
512
  initial_prompt=effective_prompt,
462
513
  recording_path_callback=recording_path_callback,
514
+ audio_level_callback=audio_level_callback,
463
515
  ),
464
516
  _receive_transcript(
465
517
  client,
@@ -488,6 +540,7 @@ async def _transcribe_live_audio_buffered(
488
540
  save_recording: bool = True,
489
541
  extra_instructions: str | None = None,
490
542
  recording_path_callback: Callable[[Path], None] | None = None,
543
+ audio_level_callback: Callable[[bytes], None] | None = None,
491
544
  **_kwargs: object,
492
545
  ) -> str | None:
493
546
  """Record audio to buffer, then transcribe.
@@ -502,6 +555,7 @@ async def _transcribe_live_audio_buffered(
502
555
  live=live,
503
556
  save_recording=save_recording,
504
557
  recording_path_callback=recording_path_callback,
558
+ audio_level_callback=audio_level_callback,
505
559
  )
506
560
  if not audio_data:
507
561
  return None
@@ -95,7 +95,7 @@ The `--from-file` option supports multiple audio formats:
95
95
 
96
96
  | Option | Default | Description |
97
97
  |--------|---------|-------------|
98
- | `--extra-instructions` | - | Extra instructions appended to the LLM cleanup prompt (requires `--llm`). |
98
+ | `--extra-instructions` | - | Extra ASR context where supported, and LLM cleanup instructions when `--llm` is enabled. The NeMo backend ignores ASR text prompts. |
99
99
  | `--llm/--no-llm` | `false` | Clean up transcript with LLM: fix errors, add punctuation, remove filler words. Uses `--extra-instructions` if set (via CLI or config file). Not compatible with --diarize. |
100
100
 
101
101
  ### Audio Recovery
@@ -76,6 +76,8 @@ struct AgentCommand {
76
76
  "transcribe",
77
77
  "--toggle",
78
78
  "--quiet",
79
+ "--voice-level-log",
80
+ VoiceLevelLog.defaultLogPath,
79
81
  "--transcription-log",
80
82
  RecentTranscriptionReader.defaultLogPath,
81
83
  ],
@@ -97,7 +99,13 @@ struct AgentCommand {
97
99
  static let voiceEdit = AgentCommand(
98
100
  identifier: "voice-edit",
99
101
  title: "Voice Edit Clipboard",
100
- arguments: ["voice-edit", "--toggle", "--quiet"],
102
+ arguments: [
103
+ "voice-edit",
104
+ "--toggle",
105
+ "--quiet",
106
+ "--voice-level-log",
107
+ VoiceLevelLog.defaultLogPath,
108
+ ],
101
109
  bootstrapRequirement: .transcription,
102
110
  showsRecordingIndicator: true,
103
111
  startNotificationTitle: "Voice Edit Started",
@@ -177,6 +177,17 @@ struct AgentRuntime {
177
177
  }
178
178
  }
179
179
 
180
+ if CommandLine.arguments.contains("--agentcli-voice-level-self-test") {
181
+ do {
182
+ try Self.runVoiceLevelSelfTest()
183
+ print("AgentCLI voice-level self-test ok")
184
+ exit(0)
185
+ } catch {
186
+ print("AgentCLI voice-level self-test failed: \(error.localizedDescription)")
187
+ exit(1)
188
+ }
189
+ }
190
+
180
191
  guard CommandLine.arguments.contains("--agentcli-bootstrap-self-test") else { return }
181
192
 
182
193
  let bootstrap = ensureReady(for: .transcription, force: true)
@@ -201,6 +212,54 @@ struct AgentRuntime {
201
212
  exit(0)
202
213
  }
203
214
 
215
+ private static func runVoiceLevelSelfTest() throws {
216
+ guard argumentValue(AgentCommand.toggleTranscription.arguments, for: "--voice-level-log") == VoiceLevelLog.defaultLogPath else {
217
+ throw SelfTestError("Toggle Transcription does not pass --voice-level-log")
218
+ }
219
+ guard argumentValue(AgentCommand.voiceEdit.arguments, for: "--voice-level-log") == VoiceLevelLog.defaultLogPath else {
220
+ throw SelfTestError("Voice Edit does not pass --voice-level-log")
221
+ }
222
+
223
+ let logURL = FileManager.default.temporaryDirectory
224
+ .appendingPathComponent(UUID().uuidString)
225
+ .appendingPathExtension("jsonl")
226
+ defer { try? FileManager.default.removeItem(at: logURL) }
227
+
228
+ try """
229
+ {"timestamp":"2026-06-04T12:00:00Z","level":0.25}
230
+ {"timestamp":"2026-06-04T12:00:01Z","level":0.75}
231
+ """.write(to: logURL, atomically: true, encoding: .utf8)
232
+
233
+ let formatter = ISO8601DateFormatter()
234
+ formatter.formatOptions = [.withInternetDateTime]
235
+ guard let now = formatter.date(from: "2026-06-04T12:00:01Z") else {
236
+ throw SelfTestError("Could not construct voice-level test timestamp")
237
+ }
238
+ guard VoiceLevelLog.latestLevel(from: logURL, now: now) == CGFloat(0.75) else {
239
+ throw SelfTestError("VoiceLevelLog did not read latest fresh level")
240
+ }
241
+ }
242
+
243
+ private static func argumentValue(_ arguments: [String], for option: String) -> String? {
244
+ guard let index = arguments.firstIndex(of: option),
245
+ arguments.indices.contains(index + 1) else {
246
+ return nil
247
+ }
248
+ return arguments[index + 1]
249
+ }
250
+
251
+ private struct SelfTestError: LocalizedError {
252
+ let message: String
253
+
254
+ init(_ message: String) {
255
+ self.message = message
256
+ }
257
+
258
+ var errorDescription: String? {
259
+ message
260
+ }
261
+ }
262
+
204
263
  func ensureInstalled(
205
264
  force: Bool = false,
206
265
  progress: AgentBootstrapProgress = { _ in }