agent-cli 0.95.7__tar.gz → 0.95.9__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 (432) hide show
  1. agent_cli-0.95.9/.github/scripts/update_cask.py +87 -0
  2. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/release.yml +25 -0
  3. agent_cli-0.95.9/Casks/agent-cli.rb +29 -0
  4. {agent_cli-0.95.7 → agent_cli-0.95.9}/PKG-INFO +1 -1
  5. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +11 -1
  6. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +47 -1
  7. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +31 -0
  8. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +22 -1
  9. agent_cli-0.95.9/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +54 -0
  10. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +125 -11
  11. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +38 -0
  12. agent_cli-0.95.9/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +55 -0
  13. agent_cli-0.95.9/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +55 -0
  14. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_macos_app.py +64 -12
  15. agent_cli-0.95.9/tests/test_update_cask.py +51 -0
  16. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
  17. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude/skills/agent-cli-dev/examples.md +0 -0
  18. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude-plugin/README.md +0 -0
  19. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude-plugin/marketplace.json +0 -0
  20. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude-plugin/plugin.json +0 -0
  21. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
  22. {agent_cli-0.95.7 → agent_cli-0.95.9}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
  23. {agent_cli-0.95.7 → agent_cli-0.95.9}/.cursorrules +0 -0
  24. {agent_cli-0.95.7 → agent_cli-0.95.9}/.dockerignore +0 -0
  25. {agent_cli-0.95.7 → agent_cli-0.95.9}/.env.example +0 -0
  26. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/logo.svg +0 -0
  27. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/release-drafter.yml +0 -0
  28. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/renovate.json +0 -0
  29. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/scripts/check_extras_sync.py +0 -0
  30. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/scripts/check_plugin_skill_sync.py +0 -0
  31. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/scripts/sync_extras.py +0 -0
  32. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/scripts/sync_requirements.py +0 -0
  33. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/automerge.yml +0 -0
  34. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/docker.yml +0 -0
  35. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/docs.yml +0 -0
  36. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/markdown-code-runner.yml +0 -0
  37. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/pytest.yml +0 -0
  38. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/release-drafter.yml +0 -0
  39. {agent_cli-0.95.7 → agent_cli-0.95.9}/.github/workflows/toc.yaml +0 -0
  40. {agent_cli-0.95.7 → agent_cli-0.95.9}/.gitignore +0 -0
  41. {agent_cli-0.95.7 → agent_cli-0.95.9}/.jscpd.json +0 -0
  42. {agent_cli-0.95.7 → agent_cli-0.95.9}/.pre-commit-config.yaml +0 -0
  43. {agent_cli-0.95.7 → agent_cli-0.95.9}/.prompts/docs-review.md +0 -0
  44. {agent_cli-0.95.7 → agent_cli-0.95.9}/.prompts/pr-review.md +0 -0
  45. {agent_cli-0.95.7 → agent_cli-0.95.9}/CLAUDE.md +0 -0
  46. {agent_cli-0.95.7 → agent_cli-0.95.9}/LICENSE +0 -0
  47. {agent_cli-0.95.7 → agent_cli-0.95.9}/LLAMA_SERVER_USAGE.md +0 -0
  48. {agent_cli-0.95.7 → agent_cli-0.95.9}/README.md +0 -0
  49. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/__init__.py +0 -0
  50. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/__main__.py +0 -0
  51. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_extras.json +0 -0
  52. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/.gitkeep +0 -0
  53. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/audio.txt +0 -0
  54. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/diarization.txt +0 -0
  55. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/faster-whisper.txt +0 -0
  56. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/kokoro.txt +0 -0
  57. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/llm.txt +0 -0
  58. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/memory.txt +0 -0
  59. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/mlx-whisper.txt +0 -0
  60. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/piper.txt +0 -0
  61. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/rag.txt +0 -0
  62. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/server.txt +0 -0
  63. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/speed.txt +0 -0
  64. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/vad.txt +0 -0
  65. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/vectordb.txt +0 -0
  66. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/whisper-transformers.txt +0 -0
  67. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_requirements/wyoming.txt +0 -0
  68. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/_tools.py +0 -0
  69. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/__init__.py +0 -0
  70. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/_voice_agent_common.py +0 -0
  71. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/assistant.py +0 -0
  72. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/autocorrect.py +0 -0
  73. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/chat.py +0 -0
  74. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/diarize_live_session.py +0 -0
  75. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/memory/__init__.py +0 -0
  76. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/memory/add.py +0 -0
  77. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/memory/proxy.py +0 -0
  78. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/rag_proxy.py +0 -0
  79. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/speak.py +0 -0
  80. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/speakers.py +0 -0
  81. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/transcribe.py +0 -0
  82. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/transcribe_live.py +0 -0
  83. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/agents/voice_edit.py +0 -0
  84. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/api.py +0 -0
  85. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/cli.py +0 -0
  86. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/config.py +0 -0
  87. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/config_cmd.py +0 -0
  88. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/constants.py +0 -0
  89. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/__init__.py +0 -0
  90. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/alignment.py +0 -0
  91. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/audio.py +0 -0
  92. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/audio_format.py +0 -0
  93. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/chroma.py +0 -0
  94. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/deps.py +0 -0
  95. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/diarization.py +0 -0
  96. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/openai_proxy.py +0 -0
  97. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/process.py +0 -0
  98. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/reranker.py +0 -0
  99. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/speaker_identity.py +0 -0
  100. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/sse.py +0 -0
  101. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/transcription_logger.py +0 -0
  102. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/utils.py +0 -0
  103. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/vad.py +0 -0
  104. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/core/watch.py +0 -0
  105. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/daemon/__init__.py +0 -0
  106. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/daemon/cli.py +0 -0
  107. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/__init__.py +0 -0
  108. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/_branch_name.py +0 -0
  109. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/_config.py +0 -0
  110. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/_output.py +0 -0
  111. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/cleanup.py +0 -0
  112. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/cli.py +0 -0
  113. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/__init__.py +0 -0
  114. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/aider.py +0 -0
  115. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/base.py +0 -0
  116. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/claude.py +0 -0
  117. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/codex.py +0 -0
  118. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
  119. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/copilot.py +0 -0
  120. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
  121. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/gemini.py +0 -0
  122. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/opencode.py +0 -0
  123. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/coding_agents/registry.py +0 -0
  124. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/__init__.py +0 -0
  125. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/base.py +0 -0
  126. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/cursor.py +0 -0
  127. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/emacs.py +0 -0
  128. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/jetbrains.py +0 -0
  129. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/nano.py +0 -0
  130. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/neovim.py +0 -0
  131. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/registry.py +0 -0
  132. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/sublime.py +0 -0
  133. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/vim.py +0 -0
  134. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/vscode.py +0 -0
  135. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/editors/zed.py +0 -0
  136. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/hooks.py +0 -0
  137. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/launch.py +0 -0
  138. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/project.py +0 -0
  139. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/registry.py +0 -0
  140. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/skill/SKILL.md +0 -0
  141. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/skill/examples.md +0 -0
  142. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/__init__.py +0 -0
  143. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/apple_terminal.py +0 -0
  144. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/base.py +0 -0
  145. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/gnome.py +0 -0
  146. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/iterm2.py +0 -0
  147. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/kitty.py +0 -0
  148. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/registry.py +0 -0
  149. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/tmux.py +0 -0
  150. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/warp.py +0 -0
  151. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/terminals/zellij.py +0 -0
  152. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/dev/worktree.py +0 -0
  153. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/docs_gen.py +0 -0
  154. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/example-config.toml +0 -0
  155. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/__init__.py +0 -0
  156. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/common.py +0 -0
  157. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/extras.py +0 -0
  158. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/hotkeys.py +0 -0
  159. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/launchd.py +0 -0
  160. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/service_config.py +0 -0
  161. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/services.py +0 -0
  162. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/install/systemd.py +0 -0
  163. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/__init__.py +0 -0
  164. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_files.py +0 -0
  165. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_filters.py +0 -0
  166. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_git.py +0 -0
  167. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_indexer.py +0 -0
  168. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_ingest.py +0 -0
  169. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_persistence.py +0 -0
  170. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_prompt.py +0 -0
  171. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_retrieval.py +0 -0
  172. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_store.py +0 -0
  173. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_streaming.py +0 -0
  174. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/_tasks.py +0 -0
  175. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/api.py +0 -0
  176. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/client.py +0 -0
  177. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/engine.py +0 -0
  178. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/entities.py +0 -0
  179. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/memory/models.py +0 -0
  180. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/opts.py +0 -0
  181. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/py.typed +0 -0
  182. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/__init__.py +0 -0
  183. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/_indexer.py +0 -0
  184. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/_indexing.py +0 -0
  185. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/_prompt.py +0 -0
  186. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/_retriever.py +0 -0
  187. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/_store.py +0 -0
  188. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/_utils.py +0 -0
  189. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/api.py +0 -0
  190. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/client.py +0 -0
  191. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/engine.py +0 -0
  192. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/rag/models.py +0 -0
  193. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/.runtime/.gitkeep +0 -0
  194. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/__init__.py +0 -0
  195. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
  196. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
  197. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
  198. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
  199. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
  200. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
  201. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
  202. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
  203. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
  204. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
  205. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
  206. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
  207. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
  208. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
  209. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/run-openwakeword.sh +0 -0
  210. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
  211. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/setup-linux.sh +0 -0
  212. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
  213. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/setup-macos.sh +0 -0
  214. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/setup-windows.ps1 +0 -0
  215. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
  216. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/scripts/start-all-services.sh +0 -0
  217. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/__init__.py +0 -0
  218. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/cli.py +0 -0
  219. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/common.py +0 -0
  220. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/model_manager.py +0 -0
  221. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/model_registry.py +0 -0
  222. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/proxy/__init__.py +0 -0
  223. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/proxy/api.py +0 -0
  224. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/streaming.py +0 -0
  225. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/__init__.py +0 -0
  226. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/api.py +0 -0
  227. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/backends/__init__.py +0 -0
  228. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/backends/base.py +0 -0
  229. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/backends/kokoro.py +0 -0
  230. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/backends/piper.py +0 -0
  231. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/model_manager.py +0 -0
  232. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/model_registry.py +0 -0
  233. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/tts/wyoming_handler.py +0 -0
  234. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/__init__.py +0 -0
  235. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/api.py +0 -0
  236. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/backends/__init__.py +0 -0
  237. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/backends/base.py +0 -0
  238. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
  239. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/backends/mlx.py +0 -0
  240. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/backends/transformers.py +0 -0
  241. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/languages.py +0 -0
  242. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/model_manager.py +0 -0
  243. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/model_registry.py +0 -0
  244. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/server/whisper/wyoming_handler.py +0 -0
  245. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/services/__init__.py +0 -0
  246. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/services/_wyoming_utils.py +0 -0
  247. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/services/asr.py +0 -0
  248. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/services/llm.py +0 -0
  249. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/services/tts.py +0 -0
  250. {agent_cli-0.95.7 → agent_cli-0.95.9}/agent_cli/services/wake_word.py +0 -0
  251. {agent_cli-0.95.7 → agent_cli-0.95.9}/docker/docker-compose.yml +0 -0
  252. {agent_cli-0.95.7 → agent_cli-0.95.9}/docker/memory-proxy.Dockerfile +0 -0
  253. {agent_cli-0.95.7 → agent_cli-0.95.9}/docker/rag-proxy.Dockerfile +0 -0
  254. {agent_cli-0.95.7 → agent_cli-0.95.9}/docker/transcribe-proxy.Dockerfile +0 -0
  255. {agent_cli-0.95.7 → agent_cli-0.95.9}/docker/tts.Dockerfile +0 -0
  256. {agent_cli-0.95.7 → agent_cli-0.95.9}/docker/whisper.Dockerfile +0 -0
  257. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/CNAME +0 -0
  258. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/architecture/index.md +0 -0
  259. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/architecture/memory.md +0 -0
  260. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/architecture/rag.md +0 -0
  261. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/assistant.md +0 -0
  262. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/autocorrect.md +0 -0
  263. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/chat.md +0 -0
  264. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/config.md +0 -0
  265. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/daemon.md +0 -0
  266. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/dev.md +0 -0
  267. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/diarize-live-session.md +0 -0
  268. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/index.md +0 -0
  269. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/install-extras.md +0 -0
  270. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/install-hotkeys.md +0 -0
  271. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/install-services.md +0 -0
  272. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/memory.md +0 -0
  273. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/rag-proxy.md +0 -0
  274. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/server/index.md +0 -0
  275. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/server/transcribe-proxy.md +0 -0
  276. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/server/tts.md +0 -0
  277. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/server/whisper.md +0 -0
  278. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/speak.md +0 -0
  279. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/speakers.md +0 -0
  280. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/start-services.md +0 -0
  281. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/transcribe-live.md +0 -0
  282. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/transcribe.md +0 -0
  283. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/commands/voice-edit.md +0 -0
  284. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/configuration.md +0 -0
  285. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/getting-started.md +0 -0
  286. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/iOS_Shortcut_Guide.md +0 -0
  287. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/index.md +0 -0
  288. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/installation/docker.md +0 -0
  289. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/installation/index.md +0 -0
  290. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/installation/linux.md +0 -0
  291. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/installation/macos.md +0 -0
  292. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/installation/nixos.md +0 -0
  293. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/installation/windows.md +0 -0
  294. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/logo-avatar.svg +0 -0
  295. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/logo-clean.svg +0 -0
  296. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
  297. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/run_markdown_code_runner.py +0 -0
  298. {agent_cli-0.95.7 → agent_cli-0.95.9}/docs/system-integration.md +0 -0
  299. {agent_cli-0.95.7 → agent_cli-0.95.9}/example.agent-cli-config.toml +0 -0
  300. {agent_cli-0.95.7 → agent_cli-0.95.9}/justfile +0 -0
  301. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Package.resolved +0 -0
  302. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Package.swift +0 -0
  303. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/README.md +0 -0
  304. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
  305. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Resources/Info.plist +0 -0
  306. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
  307. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +0 -0
  308. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +0 -0
  309. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
  310. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +0 -0
  311. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +0 -0
  312. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
  313. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
  314. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -0
  315. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
  316. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
  317. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
  318. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
  319. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +0 -0
  320. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
  321. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
  322. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/build-macos-app.sh +0 -0
  323. {agent_cli-0.95.7 → agent_cli-0.95.9}/macos/test-macos-app-e2e.sh +0 -0
  324. {agent_cli-0.95.7 → agent_cli-0.95.9}/pyproject.toml +0 -0
  325. {agent_cli-0.95.7 → agent_cli-0.95.9}/reddit.md +0 -0
  326. {agent_cli-0.95.7 → agent_cli-0.95.9}/shell.nix +0 -0
  327. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/__init__.py +0 -0
  328. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/__init__.py +0 -0
  329. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_fix_my_text.py +0 -0
  330. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_interactive.py +0 -0
  331. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_interactive_extra.py +0 -0
  332. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_memory_add.py +0 -0
  333. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_speak.py +0 -0
  334. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_speak_e2e.py +0 -0
  335. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_speakers.py +0 -0
  336. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_transcribe.py +0 -0
  337. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_transcribe_agent.py +0 -0
  338. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_transcribe_e2e.py +0 -0
  339. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_transcribe_live.py +0 -0
  340. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_transcribe_recovery.py +0 -0
  341. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_tts_common.py +0 -0
  342. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_tts_common_extra.py +0 -0
  343. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_voice_agent_common.py +0 -0
  344. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_voice_edit.py +0 -0
  345. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_voice_edit_e2e.py +0 -0
  346. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/agents/test_wake_word_assistant.py +0 -0
  347. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/conftest.py +0 -0
  348. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/__init__.py +0 -0
  349. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/test_audio.py +0 -0
  350. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/test_audio_format.py +0 -0
  351. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/test_chroma.py +0 -0
  352. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/test_sse.py +0 -0
  353. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/test_vad.py +0 -0
  354. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/core/test_watch.py +0 -0
  355. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/__init__.py +0 -0
  356. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_cleanup.py +0 -0
  357. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_cli.py +0 -0
  358. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_coding_agents.py +0 -0
  359. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_editors.py +0 -0
  360. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_hooks.py +0 -0
  361. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_launch.py +0 -0
  362. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_project.py +0 -0
  363. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_terminals.py +0 -0
  364. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_verification.py +0 -0
  365. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/dev/test_worktree.py +0 -0
  366. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/install/__init__.py +0 -0
  367. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/install/test_extras.py +0 -0
  368. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/install/test_launchd.py +0 -0
  369. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/__init__.py +0 -0
  370. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_api_health.py +0 -0
  371. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_api_integration_liveish.py +0 -0
  372. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_client.py +0 -0
  373. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_engine.py +0 -0
  374. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_files.py +0 -0
  375. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_filters.py +0 -0
  376. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_git_integration.py +0 -0
  377. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_indexer.py +0 -0
  378. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_memory_integration.py +0 -0
  379. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_proxy_passthrough.py +0 -0
  380. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_store.py +0 -0
  381. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/memory/test_utils.py +0 -0
  382. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/mocks/__init__.py +0 -0
  383. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/mocks/audio.py +0 -0
  384. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/mocks/llm.py +0 -0
  385. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/mocks/wyoming.py +0 -0
  386. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/__init__.py +0 -0
  387. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_api.py +0 -0
  388. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_engine.py +0 -0
  389. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_history.py +0 -0
  390. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_indexer.py +0 -0
  391. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_indexing.py +0 -0
  392. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_rag_client.py +0 -0
  393. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_rag_integration_liveish.py +0 -0
  394. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_rag_proxy_passthrough.py +0 -0
  395. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_retriever.py +0 -0
  396. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_store.py +0 -0
  397. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/rag/test_utils.py +0 -0
  398. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_alignment.py +0 -0
  399. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_api.py +0 -0
  400. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_api_integration.py +0 -0
  401. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_asr.py +0 -0
  402. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_asr_recovery.py +0 -0
  403. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_audio_e2e.py +0 -0
  404. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_cli.py +0 -0
  405. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_config.py +0 -0
  406. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_config_cmd.py +0 -0
  407. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_daemon.py +0 -0
  408. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_diarization.py +0 -0
  409. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_diarize_live_session.py +0 -0
  410. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_docs_gen.py +0 -0
  411. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_env_vars.py +0 -0
  412. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_faster_whisper_backend.py +0 -0
  413. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_json_output.py +0 -0
  414. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_llm.py +0 -0
  415. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_llm_gemini.py +0 -0
  416. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_memory_tools.py +0 -0
  417. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_mlx_backend.py +0 -0
  418. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_process_manager.py +0 -0
  419. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_requires_extras.py +0 -0
  420. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_server_streaming.py +0 -0
  421. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_server_tts.py +0 -0
  422. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_server_whisper.py +0 -0
  423. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_services.py +0 -0
  424. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_speaker_identity.py +0 -0
  425. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_tools.py +0 -0
  426. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_transformers_backend.py +0 -0
  427. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_tts.py +0 -0
  428. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_utils.py +0 -0
  429. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_wake_word.py +0 -0
  430. {agent_cli-0.95.7 → agent_cli-0.95.9}/tests/test_wyoming_utils.py +0 -0
  431. {agent_cli-0.95.7 → agent_cli-0.95.9}/uv.lock +0 -0
  432. {agent_cli-0.95.7 → agent_cli-0.95.9}/zensical.toml +0 -0
@@ -0,0 +1,87 @@
1
+ """Update the Agent CLI Homebrew cask version and checksum."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import re
7
+ from pathlib import Path
8
+
9
+ VERSION_RE = re.compile(r'^(?P<indent>\s*)version "[^"]+"$')
10
+ SHA256_RE = re.compile(r'^(?P<indent>\s*)sha256 "[0-9a-f]{64}"$')
11
+
12
+
13
+ def _validate_sha256(value: str) -> str:
14
+ if not re.fullmatch(r"[0-9a-f]{64}", value):
15
+ msg = "sha256 must be 64 lowercase hexadecimal characters"
16
+ raise ValueError(msg)
17
+ return value
18
+
19
+
20
+ def _validate_version(value: str) -> str:
21
+ value = value.removeprefix("v")
22
+ if not re.fullmatch(r"\d+(?:\.\d+)*(?:[-,._A-Za-z0-9]+)?", value):
23
+ msg = f"unsupported cask version: {value}"
24
+ raise ValueError(msg)
25
+ return value
26
+
27
+
28
+ def update_cask_text(text: str, *, version: str, sha256: str) -> str:
29
+ """Replace the single version and sha256 stanzas in a cask."""
30
+ version = _validate_version(version)
31
+ sha256 = _validate_sha256(sha256)
32
+
33
+ version_count = 0
34
+ sha256_count = 0
35
+ lines: list[str] = []
36
+ for source_line in text.splitlines(keepends=True):
37
+ newline = "\n" if source_line.endswith("\n") else ""
38
+ content = source_line.removesuffix("\n")
39
+
40
+ if match := VERSION_RE.match(content):
41
+ output_line = f'{match.group("indent")}version "{version}"{newline}'
42
+ version_count += 1
43
+ elif match := SHA256_RE.match(content):
44
+ output_line = f'{match.group("indent")}sha256 "{sha256}"{newline}'
45
+ sha256_count += 1
46
+ else:
47
+ output_line = source_line
48
+ lines.append(output_line)
49
+
50
+ if version_count != 1:
51
+ msg = f"expected exactly one version stanza, found {version_count}"
52
+ raise ValueError(msg)
53
+ if sha256_count != 1:
54
+ msg = f"expected exactly one sha256 stanza, found {sha256_count}"
55
+ raise ValueError(msg)
56
+
57
+ return "".join(lines)
58
+
59
+
60
+ def update_cask_file(path: Path, *, version: str, sha256: str) -> None:
61
+ """Update a cask file in place."""
62
+ path.write_text(
63
+ update_cask_text(path.read_text(), version=version, sha256=sha256),
64
+ encoding="utf-8",
65
+ )
66
+
67
+
68
+ def main() -> None:
69
+ """Run the command-line cask updater."""
70
+ parser = argparse.ArgumentParser(description=__doc__)
71
+ parser.add_argument(
72
+ "--cask",
73
+ type=Path,
74
+ default=Path("Casks/agent-cli.rb"),
75
+ help="Path to the cask file to update.",
76
+ )
77
+ parser.add_argument(
78
+ "--version", required=True, help="Release version, with or without v prefix."
79
+ )
80
+ parser.add_argument("--sha256", required=True, help="SHA-256 checksum for the release DMG.")
81
+ args = parser.parse_args()
82
+
83
+ update_cask_file(args.cask, version=args.version, sha256=args.sha256)
84
+
85
+
86
+ if __name__ == "__main__":
87
+ main()
@@ -64,3 +64,28 @@ jobs:
64
64
  GH_TOKEN: ${{ github.token }}
65
65
  TAG_NAME: ${{ github.event.release.tag_name }}
66
66
  run: gh release upload "$TAG_NAME" dist/macos/AgentCLI.dmg --clobber
67
+ - name: Update Homebrew cask
68
+ env:
69
+ TAG_NAME: ${{ github.event.release.tag_name }}
70
+ run: |
71
+ VERSION="${TAG_NAME#v}"
72
+ SHA256=$(shasum -a 256 dist/macos/AgentCLI.dmg | awk '{ print $1 }')
73
+
74
+ git fetch origin main
75
+ git switch --force-create cask-update origin/main
76
+
77
+ python3 .github/scripts/update_cask.py \
78
+ --version "$VERSION" \
79
+ --sha256 "$SHA256"
80
+
81
+ if git diff --quiet -- Casks/agent-cli.rb; then
82
+ echo "Casks/agent-cli.rb is already up to date."
83
+ exit 0
84
+ fi
85
+
86
+ git config user.name "github-actions[bot]"
87
+ git config user.email "github-actions[bot]@users.noreply.github.com"
88
+ git add Casks/agent-cli.rb
89
+ git commit -m "Update AgentCLI cask to ${TAG_NAME}"
90
+ git pull --rebase origin main
91
+ git push origin HEAD:main
@@ -0,0 +1,29 @@
1
+ cask "agent-cli" do
2
+ version "0.95.8"
3
+ sha256 "60273504f3c4bea181db64033790e0290bf1b53b86a1386afa3d41216a172029"
4
+
5
+ url "https://github.com/basnijholt/agent-cli/releases/download/v#{version}/AgentCLI.dmg"
6
+ name "Agent CLI"
7
+ desc "Local-first AI voice and text tools with menu bar integration"
8
+ homepage "https://github.com/basnijholt/agent-cli"
9
+
10
+ livecheck do
11
+ url :url
12
+ strategy :github_latest
13
+ end
14
+
15
+ depends_on arch: :arm64
16
+ depends_on macos: :ventura
17
+
18
+ app "AgentCLI.app"
19
+
20
+ uninstall launchctl: "com.agent_cli.whisper",
21
+ quit: "lt.nijho.agent-cli.menubar"
22
+
23
+ zap trash: [
24
+ "~/Library/Application Support/AgentCLI",
25
+ "~/Library/LaunchAgents/com.agent_cli.whisper.plist",
26
+ "~/Library/Logs/agent-cli-whisper",
27
+ "~/Library/Preferences/lt.nijho.agent-cli.menubar.plist",
28
+ ]
29
+ end
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-cli
3
- Version: 0.95.7
3
+ Version: 0.95.9
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>
@@ -1,5 +1,15 @@
1
1
  import Foundation
2
2
 
3
+ private extension String {
4
+ var isVisiblyBlank: Bool {
5
+ unicodeScalars.allSatisfy { scalar in
6
+ CharacterSet.whitespacesAndNewlines.contains(scalar)
7
+ || scalar.properties.generalCategory == .format
8
+ || scalar.properties.generalCategory == .control
9
+ }
10
+ }
11
+ }
12
+
3
13
  struct AgentCommand {
4
14
  let identifier: String
5
15
  let title: String
@@ -40,7 +50,7 @@ struct AgentCommand {
40
50
  guard appliesTranscriptionExtraInstructions else { return arguments }
41
51
 
42
52
  let trimmedInstructions = extraInstructions?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
43
- guard !trimmedInstructions.isEmpty else { return arguments }
53
+ guard !trimmedInstructions.isVisiblyBlank else { return arguments }
44
54
 
45
55
  return arguments + ["--extra-instructions", trimmedInstructions]
46
56
  }
@@ -29,9 +29,13 @@ final class AgentCommandRunner: ObservableObject {
29
29
  @Published private(set) var isRecording = false
30
30
  @Published private(set) var bootstrapPhase: BootstrapPhase = .idle
31
31
  @Published private var activeCommandCount = 0
32
+ @Published private var bootstrapAnimationTick = 0
33
+ @Published private var bootstrapElapsedSeconds = 0
32
34
  private var recordingIndicator = RecordingIndicatorController()
33
35
  private let pasteController: TranscriptPasteController
34
36
  private let bootstrap: AgentBootstrap
37
+ private var bootstrapAnimationTimer: Timer?
38
+ private var bootstrapPhaseStartedAt: Date?
35
39
  private var pendingStopRecordingCommands: Set<String> = []
36
40
  private var holdTranscriptionState: HoldTranscriptionState = .idle
37
41
  private var holdToTranscribePasteTarget: FocusedTextTarget?
@@ -47,7 +51,10 @@ final class AgentCommandRunner: ObservableObject {
47
51
  return "Recording"
48
52
  }
49
53
  if bootstrapPhase.isPreparing {
50
- return bootstrapPhase.statusMessage
54
+ return bootstrapPhase.statusMessage(
55
+ animationTick: bootstrapAnimationTick,
56
+ elapsedSeconds: bootstrapElapsedSeconds
57
+ )
51
58
  }
52
59
  if holdTranscriptionState.isFinishing {
53
60
  return "Transcribing..."
@@ -122,7 +129,19 @@ final class AgentCommandRunner: ObservableObject {
122
129
  }
123
130
 
124
131
  private func reportBootstrapPhase(_ phase: BootstrapPhase) {
132
+ let wasPreparing = bootstrapPhase.isPreparing
133
+ let phaseChanged = bootstrapPhase != phase
125
134
  bootstrapPhase = phase
135
+ if phase.isPreparing {
136
+ if !wasPreparing || phaseChanged {
137
+ bootstrapAnimationTick = 0
138
+ bootstrapElapsedSeconds = 0
139
+ bootstrapPhaseStartedAt = Date()
140
+ }
141
+ startBootstrapAnimationTimer()
142
+ } else {
143
+ stopBootstrapAnimationTimer()
144
+ }
126
145
  }
127
146
 
128
147
  private func makeBootstrapProgressReporter() -> AgentBootstrapProgress {
@@ -133,6 +152,33 @@ final class AgentCommandRunner: ObservableObject {
133
152
  }
134
153
  }
135
154
 
155
+ private func startBootstrapAnimationTimer() {
156
+ guard bootstrapAnimationTimer == nil else { return }
157
+ let timer = Timer(timeInterval: 0.8, repeats: true) { [weak self] _ in
158
+ Task { @MainActor in
159
+ guard let self else { return }
160
+ guard self.bootstrapPhase.isPreparing else {
161
+ self.stopBootstrapAnimationTimer()
162
+ return
163
+ }
164
+ self.bootstrapAnimationTick = (self.bootstrapAnimationTick + 1) % 4
165
+ if let startedAt = self.bootstrapPhaseStartedAt {
166
+ self.bootstrapElapsedSeconds = max(0, Int(Date().timeIntervalSince(startedAt)))
167
+ }
168
+ }
169
+ }
170
+ RunLoop.main.add(timer, forMode: .common)
171
+ bootstrapAnimationTimer = timer
172
+ }
173
+
174
+ private func stopBootstrapAnimationTimer() {
175
+ bootstrapAnimationTimer?.invalidate()
176
+ bootstrapAnimationTimer = nil
177
+ bootstrapAnimationTick = 0
178
+ bootstrapElapsedSeconds = 0
179
+ bootstrapPhaseStartedAt = nil
180
+ }
181
+
136
182
  @discardableResult
137
183
  func beginHoldToTranscribe() -> Bool {
138
184
  guard holdTranscriptionState == .idle else {
@@ -42,6 +42,37 @@ enum BootstrapPhase: Equatable {
42
42
  return "Voice service warm-up failed"
43
43
  }
44
44
  }
45
+
46
+ func statusMessage(animationTick: Int, elapsedSeconds: Int) -> String {
47
+ switch self {
48
+ case .checkingRuntime, .installingRuntime, .installingVoiceService, .waitingForVoiceService, .warmingWhisperModel:
49
+ let spinnerFrames = ["◐", "◓", "◑", "◒"]
50
+ let spinner = spinnerFrames[animationTick % spinnerFrames.count]
51
+ let minutes = elapsedSeconds / 60
52
+ let seconds = elapsedSeconds % 60
53
+ let elapsedTime = String(format: "%02d:%02d", minutes, seconds)
54
+ return "\(animatedStatusMessage) \(spinner) (\(elapsedTime))"
55
+ case .idle, .failed:
56
+ return statusMessage
57
+ }
58
+ }
59
+
60
+ private var animatedStatusMessage: String {
61
+ switch self {
62
+ case .checkingRuntime:
63
+ return "Checking CLI runtime"
64
+ case .installingRuntime:
65
+ return "Installing CLI runtime"
66
+ case .installingVoiceService:
67
+ return "Installing voice service"
68
+ case .waitingForVoiceService:
69
+ return "Waiting for voice service"
70
+ case .warmingWhisperModel:
71
+ return "Warming Whisper model"
72
+ case .idle, .failed:
73
+ return statusMessage
74
+ }
75
+ }
45
76
  }
46
77
 
47
78
  typealias AgentBootstrapProgress = (BootstrapPhase) -> Void
@@ -3,6 +3,16 @@ import Foundation
3
3
  final class RecordingIndicatorController {
4
4
  private var recordingCommandCount = 0
5
5
  private var activeRecordingCommands: [String: Int] = [:]
6
+ private let defaults: UserDefaults
7
+ private let audioCuePlayer: RecordingCuePlaying
8
+
9
+ init(
10
+ defaults: UserDefaults = .standard,
11
+ audioCuePlayer: RecordingCuePlaying = NativeRecordingCuePlayer.shared
12
+ ) {
13
+ self.defaults = defaults
14
+ self.audioCuePlayer = audioCuePlayer
15
+ }
6
16
 
7
17
  var isRecording: Bool {
8
18
  recordingCommandCount > 0
@@ -13,12 +23,17 @@ final class RecordingIndicatorController {
13
23
  }
14
24
 
15
25
  func begin(for command: AgentCommand) {
26
+ let wasRecording = isRecording
16
27
  activeRecordingCommands[command.identifier, default: 0] += 1
17
28
  recordingCommandCount += 1
29
+ if !wasRecording {
30
+ play(.startedRecording)
31
+ }
18
32
  VoiceLevelOverlayController.shared.show()
19
33
  }
20
34
 
21
35
  func end(for command: AgentCommand) {
36
+ let wasRecording = isRecording
22
37
  let activeCommandCount = max(0, activeRecordingCommands[command.identifier, default: 0] - 1)
23
38
  if activeCommandCount > 0 {
24
39
  activeRecordingCommands[command.identifier] = activeCommandCount
@@ -26,8 +41,14 @@ final class RecordingIndicatorController {
26
41
  activeRecordingCommands.removeValue(forKey: command.identifier)
27
42
  }
28
43
  recordingCommandCount = max(0, recordingCommandCount - 1)
29
- if !isRecording {
44
+ if wasRecording && !isRecording {
45
+ play(.finishedRecording)
30
46
  VoiceLevelOverlayController.shared.hide()
31
47
  }
32
48
  }
49
+
50
+ private func play(_ event: RecordingSoundEvent) {
51
+ guard RecordingSoundSettings.isEnabled(defaults: defaults) else { return }
52
+ audioCuePlayer.play(event)
53
+ }
33
54
  }
@@ -0,0 +1,54 @@
1
+ import AppKit
2
+ import Foundation
3
+
4
+ enum RecordingSoundSettings {
5
+ static let enabledKey = "recordingNotificationSoundsEnabled"
6
+
7
+ static func isEnabled(defaults: UserDefaults = .standard) -> Bool {
8
+ defaults.bool(forKey: enabledKey)
9
+ }
10
+ }
11
+
12
+ enum RecordingSoundEvent: Hashable {
13
+ case startedRecording
14
+ case finishedRecording
15
+
16
+ var cueName: NSSound.Name {
17
+ switch self {
18
+ case .startedRecording:
19
+ return NSSound.Name("Frog")
20
+ case .finishedRecording:
21
+ return NSSound.Name("Funk")
22
+ }
23
+ }
24
+ }
25
+
26
+ protocol RecordingCuePlaying: AnyObject {
27
+ func play(_ event: RecordingSoundEvent)
28
+ }
29
+
30
+ final class NativeRecordingCuePlayer: RecordingCuePlaying {
31
+ static let shared = NativeRecordingCuePlayer()
32
+
33
+ private var sounds: [RecordingSoundEvent: NSSound] = [:]
34
+
35
+ private init() {}
36
+
37
+ func play(_ event: RecordingSoundEvent) {
38
+ guard let sound = sound(for: event) else { return }
39
+ sound.stop()
40
+ sound.currentTime = 0
41
+ sound.play()
42
+ }
43
+
44
+ private func sound(for event: RecordingSoundEvent) -> NSSound? {
45
+ if let sound = sounds[event] {
46
+ return sound
47
+ }
48
+ guard let sound = NSSound(named: event.cueName) else {
49
+ return nil
50
+ }
51
+ sounds[event] = sound
52
+ return sound
53
+ }
54
+ }
@@ -5,10 +5,7 @@ import KeyboardShortcuts
5
5
  import SwiftUI
6
6
 
7
7
  extension KeyboardShortcuts.Name {
8
- static let toggleTranscription = Self(
9
- "toggleTranscription",
10
- default: KeyboardShortcuts.Shortcut(carbonKeyCode: kVK_Space, carbonModifiers: kEventKeyModifierFnMask)
11
- )
8
+ static let toggleTranscription = Self("toggleTranscription")
12
9
  static let holdToTranscribe = Self(
13
10
  "holdToTranscribe",
14
11
  default: KeyboardShortcuts.Shortcut(.function)
@@ -23,6 +20,68 @@ extension KeyboardShortcuts.Name {
23
20
  )
24
21
  }
25
22
 
23
+ enum ToggleTranscriptionDefault {
24
+ static let shortcut = FunctionShortcutPersistence.rawShortcut(
25
+ carbonKeyCode: kVK_Space,
26
+ carbonModifiers: kEventKeyModifierFnMask
27
+ )
28
+
29
+ static func set() {
30
+ FunctionShortcutPersistence.set(shortcut, for: .toggleTranscription)
31
+ }
32
+
33
+ static func seedIfNeeded() {
34
+ guard !userDefaultsContainsShortcut else {
35
+ return
36
+ }
37
+ set()
38
+ }
39
+
40
+ private static var userDefaultsContainsShortcut: Bool {
41
+ UserDefaults.standard.object(forKey: userDefaultsKey) != nil
42
+ }
43
+
44
+ private static var userDefaultsKey: String {
45
+ "KeyboardShortcuts_\(KeyboardShortcuts.Name.toggleTranscription.rawValue)"
46
+ }
47
+ }
48
+
49
+ enum FunctionShortcutPersistence {
50
+ static func rawShortcut(carbonKeyCode: Int, carbonModifiers: Int) -> KeyboardShortcuts.Shortcut {
51
+ // KeyboardShortcuts' public initializer normalizes away Fn, but Codable preserves raw Carbon modifiers.
52
+ let shortcutJSON = """
53
+ {"carbonKeyCode":\(carbonKeyCode),"carbonModifiers":\(carbonModifiers)}
54
+ """
55
+ guard let data = shortcutJSON.data(using: .utf8),
56
+ let shortcut = try? JSONDecoder().decode(KeyboardShortcuts.Shortcut.self, from: data) else {
57
+ return KeyboardShortcuts.Shortcut(
58
+ carbonKeyCode: carbonKeyCode,
59
+ carbonModifiers: carbonModifiers
60
+ )
61
+ }
62
+ return shortcut
63
+ }
64
+
65
+ static func set(_ shortcut: KeyboardShortcuts.Shortcut, for name: KeyboardShortcuts.Name) {
66
+ KeyboardShortcuts.setShortcut(nil, for: name)
67
+ guard let encoded = try? JSONEncoder().encode(shortcut),
68
+ let encodedString = String(data: encoded, encoding: .utf8) else {
69
+ return
70
+ }
71
+ UserDefaults.standard.set(encodedString, forKey: userDefaultsKey(for: name))
72
+ }
73
+
74
+ private static func userDefaultsKey(for name: KeyboardShortcuts.Name) -> String {
75
+ "KeyboardShortcuts_\(name.rawValue)"
76
+ }
77
+ }
78
+
79
+ private extension KeyboardShortcuts.Shortcut {
80
+ var usesFunctionModifier: Bool {
81
+ carbonModifiers & kEventKeyModifierFnMask != 0
82
+ }
83
+ }
84
+
26
85
  final class ShortcutRecordingState {
27
86
  static let shared = ShortcutRecordingState()
28
87
 
@@ -64,8 +123,8 @@ final class ShortcutSummaryState: ObservableObject {
64
123
  }
65
124
 
66
125
  func resetDefaults() {
126
+ ToggleTranscriptionDefault.set()
67
127
  KeyboardShortcuts.reset(
68
- .toggleTranscription,
69
128
  .holdToTranscribe,
70
129
  .autocorrect,
71
130
  .voiceEdit
@@ -115,15 +174,37 @@ private enum ShortcutDisplay {
115
174
  }
116
175
 
117
176
  var carbonModifiers = shortcut.carbonModifiers
118
- if event.modifierFlags.contains(.function) {
177
+ if event.modifierFlags.contains(.function),
178
+ shouldTreatFunctionFlagAsModifier(for: shortcut.carbonKeyCode) {
119
179
  carbonModifiers |= kEventKeyModifierFnMask
120
180
  }
121
- return KeyboardShortcuts.Shortcut(
181
+
182
+ guard carbonModifiers & kEventKeyModifierFnMask != 0 else {
183
+ return KeyboardShortcuts.Shortcut(
184
+ carbonKeyCode: shortcut.carbonKeyCode,
185
+ carbonModifiers: carbonModifiers
186
+ )
187
+ }
188
+
189
+ return FunctionShortcutPersistence.rawShortcut(
122
190
  carbonKeyCode: shortcut.carbonKeyCode,
123
191
  carbonModifiers: carbonModifiers
124
192
  )
125
193
  }
126
194
 
195
+ private static func shouldTreatFunctionFlagAsModifier(for carbonKeyCode: Int) -> Bool {
196
+ !isFunctionRowKey(carbonKeyCode)
197
+ }
198
+
199
+ private static func isFunctionRowKey(_ carbonKeyCode: Int) -> Bool {
200
+ switch carbonKeyCode {
201
+ case kVK_F1...kVK_F20:
202
+ return true
203
+ default:
204
+ return false
205
+ }
206
+ }
207
+
127
208
  private static func label(for shortcut: KeyboardShortcuts.Shortcut, fallback: String) -> String {
128
209
  if shortcut.carbonKeyCode == kVK_Function, shortcut.carbonModifiers == 0 {
129
210
  return "Fn"
@@ -154,13 +235,19 @@ enum ShortcutDefaultsMigrator {
154
235
  migrateDefault(
155
236
  name: .toggleTranscription,
156
237
  from: KeyboardShortcuts.Shortcut(.r, modifiers: [.command, .shift]),
157
- to: KeyboardShortcuts.Shortcut(carbonKeyCode: kVK_Space, carbonModifiers: kEventKeyModifierFnMask)
238
+ to: ToggleTranscriptionDefault.shortcut
239
+ )
240
+ migrateDefault(
241
+ name: .toggleTranscription,
242
+ from: KeyboardShortcuts.Shortcut(.space),
243
+ to: ToggleTranscriptionDefault.shortcut
158
244
  )
159
245
  migrateDefault(
160
246
  name: .holdToTranscribe,
161
247
  from: KeyboardShortcuts.Shortcut(.space, modifiers: [.control, .option]),
162
248
  to: KeyboardShortcuts.Shortcut(.function)
163
249
  )
250
+ ToggleTranscriptionDefault.seedIfNeeded()
164
251
  }
165
252
 
166
253
  private static func migrateDefault(
@@ -171,7 +258,19 @@ enum ShortcutDefaultsMigrator {
171
258
  guard KeyboardShortcuts.getShortcut(for: name) == oldShortcut else {
172
259
  return
173
260
  }
174
- KeyboardShortcuts.setShortcut(newShortcut, for: name)
261
+ setShortcut(newShortcut, for: name)
262
+ }
263
+
264
+ private static func setShortcut(
265
+ _ shortcut: KeyboardShortcuts.Shortcut,
266
+ for name: KeyboardShortcuts.Name
267
+ ) {
268
+ guard name == .toggleTranscription,
269
+ shortcut == ToggleTranscriptionDefault.shortcut else {
270
+ KeyboardShortcuts.setShortcut(shortcut, for: name)
271
+ return
272
+ }
273
+ ToggleTranscriptionDefault.set()
175
274
  }
176
275
  }
177
276
 
@@ -179,6 +278,8 @@ struct SettingsView: View {
179
278
  @ObservedObject private var loginItemController = LoginItemController.shared
180
279
  @AppStorage(RuntimeSettings.useUserInstalledAgentCLIKey)
181
280
  private var useUserInstalledAgentCLI = false
281
+ @AppStorage(RecordingSoundSettings.enabledKey)
282
+ private var recordingSoundsEnabled = false
182
283
  @AppStorage(TranscriptionSettings.transcriptionExtraInstructionsKey)
183
284
  private var transcriptionExtraInstructions = ""
184
285
  @State private var shortcutRevision = 0
@@ -202,10 +303,11 @@ struct SettingsView: View {
202
303
  }
203
304
 
204
305
  Toggle("Use User-Installed agent-cli", isOn: $useUserInstalledAgentCLI)
306
+ Toggle("Play Recording Sounds", isOn: $recordingSoundsEnabled)
205
307
  } header: {
206
308
  Text("General")
207
309
  } footer: {
208
- Text("Runs the agent-cli found on PATH with your normal config instead of the app's private bundled-uv runtime.")
310
+ Text("Runs the agent-cli found on PATH with your normal config instead of the app's private bundled-uv runtime. Recording sounds use Frog when recording starts and Funk when recording ends.")
209
311
  }
210
312
 
211
313
  Section {
@@ -368,7 +470,15 @@ final class ShortcutRecorderButton: NSButton {
368
470
  NSSound.beep()
369
471
  return
370
472
  }
371
- KeyboardShortcuts.setShortcut(shortcut, for: shortcutName)
473
+ if shortcut.usesFunctionModifier {
474
+ guard supportsFunctionChord(shortcutName) else {
475
+ NSSound.beep()
476
+ return
477
+ }
478
+ FunctionShortcutPersistence.set(shortcut, for: shortcutName)
479
+ } else {
480
+ KeyboardShortcuts.setShortcut(shortcut, for: shortcutName)
481
+ }
372
482
  stopRecording()
373
483
  }
374
484
  }
@@ -394,6 +504,10 @@ final class ShortcutRecorderButton: NSButton {
394
504
  stopRecording()
395
505
  }
396
506
 
507
+ private func supportsFunctionChord(_ name: KeyboardShortcuts.Name) -> Bool {
508
+ name == .toggleTranscription || name == .holdToTranscribe
509
+ }
510
+
397
511
  private func stopRecording() {
398
512
  if let eventMonitor {
399
513
  NSEvent.removeMonitor(eventMonitor)
@@ -41,6 +41,13 @@ final class AgentCommandTests: XCTestCase {
41
41
  )
42
42
  }
43
43
 
44
+ func testVisuallyBlankExtraInstructionsAreIgnored() {
45
+ XCTAssertEqual(
46
+ AgentCommand.toggleTranscription.resolvedArguments(extraInstructions: "\u{2060}\u{FEFF}"),
47
+ AgentCommand.toggleTranscription.arguments
48
+ )
49
+ }
50
+
44
51
  func testExtraInstructionsOnlyApplyToTranscription() {
45
52
  XCTAssertEqual(
46
53
  AgentCommand.autocorrect.resolvedArguments(extraInstructions: "Remember Bas."),
@@ -140,6 +147,37 @@ final class AgentCommandTests: XCTestCase {
140
147
 
141
148
  XCTAssertEqual(recorder.calls, [.init(requirement: .transcriptionModel, force: false)])
142
149
  }
150
+
151
+ func testPreparingStatusShowsFixedWidthSpinnerAndElapsedTime() {
152
+ XCTAssertEqual(
153
+ BootstrapPhase.checkingRuntime.statusMessage(animationTick: 0, elapsedSeconds: 0),
154
+ "Checking CLI runtime ◐ (00:00)"
155
+ )
156
+ XCTAssertEqual(
157
+ BootstrapPhase.installingRuntime.statusMessage(animationTick: 1, elapsedSeconds: 12),
158
+ "Installing CLI runtime ◓ (00:12)"
159
+ )
160
+ XCTAssertEqual(
161
+ BootstrapPhase.installingVoiceService.statusMessage(animationTick: 2, elapsedSeconds: 123),
162
+ "Installing voice service ◑ (02:03)"
163
+ )
164
+ XCTAssertEqual(
165
+ BootstrapPhase.waitingForVoiceService.statusMessage(animationTick: 0, elapsedSeconds: 0),
166
+ "Waiting for voice service ◐ (00:00)"
167
+ )
168
+ XCTAssertEqual(
169
+ BootstrapPhase.waitingForVoiceService.statusMessage(animationTick: 1, elapsedSeconds: 12),
170
+ "Waiting for voice service ◓ (00:12)"
171
+ )
172
+ XCTAssertEqual(
173
+ BootstrapPhase.waitingForVoiceService.statusMessage(animationTick: 2, elapsedSeconds: 123),
174
+ "Waiting for voice service ◑ (02:03)"
175
+ )
176
+ XCTAssertEqual(
177
+ BootstrapPhase.warmingWhisperModel.statusMessage(animationTick: 3, elapsedSeconds: 4),
178
+ "Warming Whisper model ◒ (00:04)"
179
+ )
180
+ }
143
181
  }
144
182
 
145
183
  private struct BootstrapCall: Equatable {