agent-cli 0.95.6__tar.gz → 0.95.8__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 (431) hide show
  1. agent_cli-0.95.8/Casks/agent-cli.rb +29 -0
  2. {agent_cli-0.95.6 → agent_cli-0.95.8}/PKG-INFO +1 -1
  3. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +1 -1
  4. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +9 -5
  5. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +99 -16
  6. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +33 -9
  7. agent_cli-0.95.8/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +58 -0
  8. agent_cli-0.95.8/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +111 -0
  9. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +22 -1
  10. agent_cli-0.95.8/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +54 -0
  11. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +90 -12
  12. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +31 -1
  13. agent_cli-0.95.8/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +55 -0
  14. agent_cli-0.95.8/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +55 -0
  15. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_git_integration.py +1 -0
  16. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_macos_app.py +90 -16
  17. agent_cli-0.95.6/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -67
  18. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
  19. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude/skills/agent-cli-dev/examples.md +0 -0
  20. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude-plugin/README.md +0 -0
  21. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude-plugin/marketplace.json +0 -0
  22. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude-plugin/plugin.json +0 -0
  23. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
  24. {agent_cli-0.95.6 → agent_cli-0.95.8}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
  25. {agent_cli-0.95.6 → agent_cli-0.95.8}/.cursorrules +0 -0
  26. {agent_cli-0.95.6 → agent_cli-0.95.8}/.dockerignore +0 -0
  27. {agent_cli-0.95.6 → agent_cli-0.95.8}/.env.example +0 -0
  28. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/logo.svg +0 -0
  29. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/release-drafter.yml +0 -0
  30. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/renovate.json +0 -0
  31. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/scripts/check_extras_sync.py +0 -0
  32. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/scripts/check_plugin_skill_sync.py +0 -0
  33. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/scripts/sync_extras.py +0 -0
  34. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/scripts/sync_requirements.py +0 -0
  35. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/automerge.yml +0 -0
  36. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/docker.yml +0 -0
  37. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/docs.yml +0 -0
  38. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/markdown-code-runner.yml +0 -0
  39. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/pytest.yml +0 -0
  40. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/release-drafter.yml +0 -0
  41. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/release.yml +0 -0
  42. {agent_cli-0.95.6 → agent_cli-0.95.8}/.github/workflows/toc.yaml +0 -0
  43. {agent_cli-0.95.6 → agent_cli-0.95.8}/.gitignore +0 -0
  44. {agent_cli-0.95.6 → agent_cli-0.95.8}/.jscpd.json +0 -0
  45. {agent_cli-0.95.6 → agent_cli-0.95.8}/.pre-commit-config.yaml +0 -0
  46. {agent_cli-0.95.6 → agent_cli-0.95.8}/.prompts/docs-review.md +0 -0
  47. {agent_cli-0.95.6 → agent_cli-0.95.8}/.prompts/pr-review.md +0 -0
  48. {agent_cli-0.95.6 → agent_cli-0.95.8}/CLAUDE.md +0 -0
  49. {agent_cli-0.95.6 → agent_cli-0.95.8}/LICENSE +0 -0
  50. {agent_cli-0.95.6 → agent_cli-0.95.8}/LLAMA_SERVER_USAGE.md +0 -0
  51. {agent_cli-0.95.6 → agent_cli-0.95.8}/README.md +0 -0
  52. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/__init__.py +0 -0
  53. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/__main__.py +0 -0
  54. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_extras.json +0 -0
  55. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/.gitkeep +0 -0
  56. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/audio.txt +0 -0
  57. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/diarization.txt +0 -0
  58. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/faster-whisper.txt +0 -0
  59. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/kokoro.txt +0 -0
  60. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/llm.txt +0 -0
  61. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/memory.txt +0 -0
  62. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/mlx-whisper.txt +0 -0
  63. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/piper.txt +0 -0
  64. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/rag.txt +0 -0
  65. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/server.txt +0 -0
  66. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/speed.txt +0 -0
  67. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/vad.txt +0 -0
  68. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/vectordb.txt +0 -0
  69. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/whisper-transformers.txt +0 -0
  70. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_requirements/wyoming.txt +0 -0
  71. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/_tools.py +0 -0
  72. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/__init__.py +0 -0
  73. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/_voice_agent_common.py +0 -0
  74. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/assistant.py +0 -0
  75. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/autocorrect.py +0 -0
  76. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/chat.py +0 -0
  77. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/diarize_live_session.py +0 -0
  78. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/memory/__init__.py +0 -0
  79. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/memory/add.py +0 -0
  80. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/memory/proxy.py +0 -0
  81. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/rag_proxy.py +0 -0
  82. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/speak.py +0 -0
  83. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/speakers.py +0 -0
  84. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/transcribe.py +0 -0
  85. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/transcribe_live.py +0 -0
  86. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/agents/voice_edit.py +0 -0
  87. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/api.py +0 -0
  88. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/cli.py +0 -0
  89. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/config.py +0 -0
  90. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/config_cmd.py +0 -0
  91. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/constants.py +0 -0
  92. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/__init__.py +0 -0
  93. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/alignment.py +0 -0
  94. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/audio.py +0 -0
  95. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/audio_format.py +0 -0
  96. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/chroma.py +0 -0
  97. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/deps.py +0 -0
  98. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/diarization.py +0 -0
  99. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/openai_proxy.py +0 -0
  100. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/process.py +0 -0
  101. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/reranker.py +0 -0
  102. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/speaker_identity.py +0 -0
  103. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/sse.py +0 -0
  104. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/transcription_logger.py +0 -0
  105. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/utils.py +0 -0
  106. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/vad.py +0 -0
  107. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/core/watch.py +0 -0
  108. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/daemon/__init__.py +0 -0
  109. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/daemon/cli.py +0 -0
  110. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/__init__.py +0 -0
  111. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/_branch_name.py +0 -0
  112. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/_config.py +0 -0
  113. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/_output.py +0 -0
  114. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/cleanup.py +0 -0
  115. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/cli.py +0 -0
  116. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/__init__.py +0 -0
  117. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/aider.py +0 -0
  118. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/base.py +0 -0
  119. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/claude.py +0 -0
  120. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/codex.py +0 -0
  121. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
  122. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/copilot.py +0 -0
  123. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
  124. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/gemini.py +0 -0
  125. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/opencode.py +0 -0
  126. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/coding_agents/registry.py +0 -0
  127. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/__init__.py +0 -0
  128. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/base.py +0 -0
  129. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/cursor.py +0 -0
  130. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/emacs.py +0 -0
  131. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/jetbrains.py +0 -0
  132. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/nano.py +0 -0
  133. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/neovim.py +0 -0
  134. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/registry.py +0 -0
  135. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/sublime.py +0 -0
  136. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/vim.py +0 -0
  137. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/vscode.py +0 -0
  138. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/editors/zed.py +0 -0
  139. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/hooks.py +0 -0
  140. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/launch.py +0 -0
  141. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/project.py +0 -0
  142. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/registry.py +0 -0
  143. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/skill/SKILL.md +0 -0
  144. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/skill/examples.md +0 -0
  145. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/__init__.py +0 -0
  146. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/apple_terminal.py +0 -0
  147. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/base.py +0 -0
  148. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/gnome.py +0 -0
  149. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/iterm2.py +0 -0
  150. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/kitty.py +0 -0
  151. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/registry.py +0 -0
  152. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/tmux.py +0 -0
  153. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/warp.py +0 -0
  154. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/terminals/zellij.py +0 -0
  155. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/dev/worktree.py +0 -0
  156. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/docs_gen.py +0 -0
  157. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/example-config.toml +0 -0
  158. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/__init__.py +0 -0
  159. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/common.py +0 -0
  160. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/extras.py +0 -0
  161. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/hotkeys.py +0 -0
  162. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/launchd.py +0 -0
  163. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/service_config.py +0 -0
  164. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/services.py +0 -0
  165. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/install/systemd.py +0 -0
  166. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/__init__.py +0 -0
  167. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_files.py +0 -0
  168. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_filters.py +0 -0
  169. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_git.py +0 -0
  170. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_indexer.py +0 -0
  171. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_ingest.py +0 -0
  172. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_persistence.py +0 -0
  173. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_prompt.py +0 -0
  174. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_retrieval.py +0 -0
  175. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_store.py +0 -0
  176. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_streaming.py +0 -0
  177. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/_tasks.py +0 -0
  178. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/api.py +0 -0
  179. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/client.py +0 -0
  180. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/engine.py +0 -0
  181. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/entities.py +0 -0
  182. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/memory/models.py +0 -0
  183. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/opts.py +0 -0
  184. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/py.typed +0 -0
  185. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/__init__.py +0 -0
  186. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/_indexer.py +0 -0
  187. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/_indexing.py +0 -0
  188. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/_prompt.py +0 -0
  189. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/_retriever.py +0 -0
  190. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/_store.py +0 -0
  191. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/_utils.py +0 -0
  192. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/api.py +0 -0
  193. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/client.py +0 -0
  194. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/engine.py +0 -0
  195. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/rag/models.py +0 -0
  196. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/.runtime/.gitkeep +0 -0
  197. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/__init__.py +0 -0
  198. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
  199. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
  200. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
  201. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
  202. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
  203. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
  204. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
  205. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
  206. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
  207. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
  208. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
  209. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
  210. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
  211. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
  212. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/run-openwakeword.sh +0 -0
  213. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
  214. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/setup-linux.sh +0 -0
  215. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
  216. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/setup-macos.sh +0 -0
  217. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/setup-windows.ps1 +0 -0
  218. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
  219. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/scripts/start-all-services.sh +0 -0
  220. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/__init__.py +0 -0
  221. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/cli.py +0 -0
  222. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/common.py +0 -0
  223. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/model_manager.py +0 -0
  224. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/model_registry.py +0 -0
  225. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/proxy/__init__.py +0 -0
  226. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/proxy/api.py +0 -0
  227. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/streaming.py +0 -0
  228. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/__init__.py +0 -0
  229. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/api.py +0 -0
  230. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/backends/__init__.py +0 -0
  231. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/backends/base.py +0 -0
  232. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/backends/kokoro.py +0 -0
  233. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/backends/piper.py +0 -0
  234. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/model_manager.py +0 -0
  235. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/model_registry.py +0 -0
  236. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/tts/wyoming_handler.py +0 -0
  237. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/__init__.py +0 -0
  238. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/api.py +0 -0
  239. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/backends/__init__.py +0 -0
  240. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/backends/base.py +0 -0
  241. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
  242. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/backends/mlx.py +0 -0
  243. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/backends/transformers.py +0 -0
  244. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/languages.py +0 -0
  245. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/model_manager.py +0 -0
  246. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/model_registry.py +0 -0
  247. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/server/whisper/wyoming_handler.py +0 -0
  248. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/services/__init__.py +0 -0
  249. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/services/_wyoming_utils.py +0 -0
  250. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/services/asr.py +0 -0
  251. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/services/llm.py +0 -0
  252. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/services/tts.py +0 -0
  253. {agent_cli-0.95.6 → agent_cli-0.95.8}/agent_cli/services/wake_word.py +0 -0
  254. {agent_cli-0.95.6 → agent_cli-0.95.8}/docker/docker-compose.yml +0 -0
  255. {agent_cli-0.95.6 → agent_cli-0.95.8}/docker/memory-proxy.Dockerfile +0 -0
  256. {agent_cli-0.95.6 → agent_cli-0.95.8}/docker/rag-proxy.Dockerfile +0 -0
  257. {agent_cli-0.95.6 → agent_cli-0.95.8}/docker/transcribe-proxy.Dockerfile +0 -0
  258. {agent_cli-0.95.6 → agent_cli-0.95.8}/docker/tts.Dockerfile +0 -0
  259. {agent_cli-0.95.6 → agent_cli-0.95.8}/docker/whisper.Dockerfile +0 -0
  260. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/CNAME +0 -0
  261. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/architecture/index.md +0 -0
  262. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/architecture/memory.md +0 -0
  263. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/architecture/rag.md +0 -0
  264. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/assistant.md +0 -0
  265. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/autocorrect.md +0 -0
  266. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/chat.md +0 -0
  267. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/config.md +0 -0
  268. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/daemon.md +0 -0
  269. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/dev.md +0 -0
  270. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/diarize-live-session.md +0 -0
  271. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/index.md +0 -0
  272. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/install-extras.md +0 -0
  273. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/install-hotkeys.md +0 -0
  274. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/install-services.md +0 -0
  275. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/memory.md +0 -0
  276. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/rag-proxy.md +0 -0
  277. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/server/index.md +0 -0
  278. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/server/transcribe-proxy.md +0 -0
  279. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/server/tts.md +0 -0
  280. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/server/whisper.md +0 -0
  281. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/speak.md +0 -0
  282. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/speakers.md +0 -0
  283. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/start-services.md +0 -0
  284. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/transcribe-live.md +0 -0
  285. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/transcribe.md +0 -0
  286. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/commands/voice-edit.md +0 -0
  287. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/configuration.md +0 -0
  288. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/getting-started.md +0 -0
  289. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/iOS_Shortcut_Guide.md +0 -0
  290. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/index.md +0 -0
  291. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/installation/docker.md +0 -0
  292. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/installation/index.md +0 -0
  293. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/installation/linux.md +0 -0
  294. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/installation/macos.md +0 -0
  295. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/installation/nixos.md +0 -0
  296. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/installation/windows.md +0 -0
  297. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/logo-avatar.svg +0 -0
  298. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/logo-clean.svg +0 -0
  299. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
  300. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/run_markdown_code_runner.py +0 -0
  301. {agent_cli-0.95.6 → agent_cli-0.95.8}/docs/system-integration.md +0 -0
  302. {agent_cli-0.95.6 → agent_cli-0.95.8}/example.agent-cli-config.toml +0 -0
  303. {agent_cli-0.95.6 → agent_cli-0.95.8}/justfile +0 -0
  304. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Package.resolved +0 -0
  305. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Package.swift +0 -0
  306. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/README.md +0 -0
  307. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
  308. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Resources/Info.plist +0 -0
  309. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
  310. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
  311. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +0 -0
  312. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +0 -0
  313. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
  314. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
  315. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
  316. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
  317. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
  318. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
  319. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +0 -0
  320. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
  321. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
  322. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/build-macos-app.sh +0 -0
  323. {agent_cli-0.95.6 → agent_cli-0.95.8}/macos/test-macos-app-e2e.sh +0 -0
  324. {agent_cli-0.95.6 → agent_cli-0.95.8}/pyproject.toml +0 -0
  325. {agent_cli-0.95.6 → agent_cli-0.95.8}/reddit.md +0 -0
  326. {agent_cli-0.95.6 → agent_cli-0.95.8}/shell.nix +0 -0
  327. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/__init__.py +0 -0
  328. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/__init__.py +0 -0
  329. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_fix_my_text.py +0 -0
  330. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_interactive.py +0 -0
  331. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_interactive_extra.py +0 -0
  332. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_memory_add.py +0 -0
  333. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_speak.py +0 -0
  334. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_speak_e2e.py +0 -0
  335. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_speakers.py +0 -0
  336. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_transcribe.py +0 -0
  337. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_transcribe_agent.py +0 -0
  338. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_transcribe_e2e.py +0 -0
  339. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_transcribe_live.py +0 -0
  340. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_transcribe_recovery.py +0 -0
  341. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_tts_common.py +0 -0
  342. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_tts_common_extra.py +0 -0
  343. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_voice_agent_common.py +0 -0
  344. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_voice_edit.py +0 -0
  345. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_voice_edit_e2e.py +0 -0
  346. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/agents/test_wake_word_assistant.py +0 -0
  347. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/conftest.py +0 -0
  348. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/__init__.py +0 -0
  349. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/test_audio.py +0 -0
  350. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/test_audio_format.py +0 -0
  351. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/test_chroma.py +0 -0
  352. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/test_sse.py +0 -0
  353. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/test_vad.py +0 -0
  354. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/core/test_watch.py +0 -0
  355. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/__init__.py +0 -0
  356. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_cleanup.py +0 -0
  357. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_cli.py +0 -0
  358. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_coding_agents.py +0 -0
  359. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_editors.py +0 -0
  360. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_hooks.py +0 -0
  361. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_launch.py +0 -0
  362. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_project.py +0 -0
  363. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_terminals.py +0 -0
  364. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_verification.py +0 -0
  365. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/dev/test_worktree.py +0 -0
  366. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/install/__init__.py +0 -0
  367. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/install/test_extras.py +0 -0
  368. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/install/test_launchd.py +0 -0
  369. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/__init__.py +0 -0
  370. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_api_health.py +0 -0
  371. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_api_integration_liveish.py +0 -0
  372. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_client.py +0 -0
  373. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_engine.py +0 -0
  374. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_files.py +0 -0
  375. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_filters.py +0 -0
  376. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_indexer.py +0 -0
  377. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_memory_integration.py +0 -0
  378. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_proxy_passthrough.py +0 -0
  379. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_store.py +0 -0
  380. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/memory/test_utils.py +0 -0
  381. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/mocks/__init__.py +0 -0
  382. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/mocks/audio.py +0 -0
  383. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/mocks/llm.py +0 -0
  384. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/mocks/wyoming.py +0 -0
  385. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/__init__.py +0 -0
  386. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_api.py +0 -0
  387. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_engine.py +0 -0
  388. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_history.py +0 -0
  389. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_indexer.py +0 -0
  390. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_indexing.py +0 -0
  391. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_rag_client.py +0 -0
  392. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_rag_integration_liveish.py +0 -0
  393. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_rag_proxy_passthrough.py +0 -0
  394. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_retriever.py +0 -0
  395. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_store.py +0 -0
  396. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/rag/test_utils.py +0 -0
  397. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_alignment.py +0 -0
  398. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_api.py +0 -0
  399. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_api_integration.py +0 -0
  400. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_asr.py +0 -0
  401. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_asr_recovery.py +0 -0
  402. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_audio_e2e.py +0 -0
  403. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_cli.py +0 -0
  404. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_config.py +0 -0
  405. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_config_cmd.py +0 -0
  406. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_daemon.py +0 -0
  407. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_diarization.py +0 -0
  408. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_diarize_live_session.py +0 -0
  409. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_docs_gen.py +0 -0
  410. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_env_vars.py +0 -0
  411. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_faster_whisper_backend.py +0 -0
  412. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_json_output.py +0 -0
  413. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_llm.py +0 -0
  414. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_llm_gemini.py +0 -0
  415. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_memory_tools.py +0 -0
  416. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_mlx_backend.py +0 -0
  417. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_process_manager.py +0 -0
  418. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_requires_extras.py +0 -0
  419. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_server_streaming.py +0 -0
  420. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_server_tts.py +0 -0
  421. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_server_whisper.py +0 -0
  422. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_services.py +0 -0
  423. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_speaker_identity.py +0 -0
  424. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_tools.py +0 -0
  425. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_transformers_backend.py +0 -0
  426. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_tts.py +0 -0
  427. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_utils.py +0 -0
  428. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_wake_word.py +0 -0
  429. {agent_cli-0.95.6 → agent_cli-0.95.8}/tests/test_wyoming_utils.py +0 -0
  430. {agent_cli-0.95.6 → agent_cli-0.95.8}/uv.lock +0 -0
  431. {agent_cli-0.95.6 → agent_cli-0.95.8}/zensical.toml +0 -0
@@ -0,0 +1,29 @@
1
+ cask "agent-cli" do
2
+ version "0.95.7"
3
+ sha256 "9db4a8d9f44765e1197d687a46e4cde041ada2d5284e6a22324c706d2a40848e"
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.6
3
+ Version: 0.95.8
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>
@@ -167,7 +167,7 @@ struct AgentCLIApp: App {
167
167
  Label("Quit", systemImage: "power")
168
168
  }
169
169
  } label: {
170
- AgentCLIMenuBarIcon(isRecording: runner.isRecording)
170
+ AgentCLIMenuBarIcon(state: runner.menuBarIconState)
171
171
  }
172
172
  .menuBarExtraStyle(.menu)
173
173
 
@@ -1,9 +1,13 @@
1
1
  import Foundation
2
2
 
3
- enum AgentBootstrapRequirement: Equatable {
4
- case cliRuntime
5
- case transcription
6
- case transcriptionModel
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
+ }
7
11
  }
8
12
 
9
13
  struct AgentCommand {
@@ -46,7 +50,7 @@ struct AgentCommand {
46
50
  guard appliesTranscriptionExtraInstructions else { return arguments }
47
51
 
48
52
  let trimmedInstructions = extraInstructions?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
49
- guard !trimmedInstructions.isEmpty else { return arguments }
53
+ guard !trimmedInstructions.isVisiblyBlank else { return arguments }
50
54
 
51
55
  return arguments + ["--extra-instructions", trimmedInstructions]
52
56
  }
@@ -19,8 +19,6 @@ private enum HoldTranscriptionState {
19
19
  }
20
20
  }
21
21
 
22
- typealias AgentBootstrap = @Sendable (AgentBootstrapRequirement, Bool) -> CommandResult
23
-
24
22
  @MainActor
25
23
  final class AgentCommandRunner: ObservableObject {
26
24
  static let shared = AgentCommandRunner()
@@ -29,10 +27,15 @@ final class AgentCommandRunner: ObservableObject {
29
27
  @Published var lastOutput = ""
30
28
  @Published private(set) var hasLastError = false
31
29
  @Published private(set) var isRecording = false
30
+ @Published private(set) var bootstrapPhase: BootstrapPhase = .idle
32
31
  @Published private var activeCommandCount = 0
32
+ @Published private var bootstrapAnimationTick = 0
33
+ @Published private var bootstrapElapsedSeconds = 0
33
34
  private var recordingIndicator = RecordingIndicatorController()
34
35
  private let pasteController: TranscriptPasteController
35
36
  private let bootstrap: AgentBootstrap
37
+ private var bootstrapAnimationTimer: Timer?
38
+ private var bootstrapPhaseStartedAt: Date?
36
39
  private var pendingStopRecordingCommands: Set<String> = []
37
40
  private var holdTranscriptionState: HoldTranscriptionState = .idle
38
41
  private var holdToTranscribePasteTarget: FocusedTextTarget?
@@ -47,6 +50,12 @@ final class AgentCommandRunner: ObservableObject {
47
50
  if isRecording {
48
51
  return "Recording"
49
52
  }
53
+ if bootstrapPhase.isPreparing {
54
+ return bootstrapPhase.statusMessage(
55
+ animationTick: bootstrapAnimationTick,
56
+ elapsedSeconds: bootstrapElapsedSeconds
57
+ )
58
+ }
50
59
  if holdTranscriptionState.isFinishing {
51
60
  return "Transcribing..."
52
61
  }
@@ -56,10 +65,20 @@ final class AgentCommandRunner: ObservableObject {
56
65
  return Self.compactMenuStatus(statusMessage)
57
66
  }
58
67
 
68
+ var menuBarIconState: MenuBarIconState {
69
+ if isRecording {
70
+ return .recording
71
+ }
72
+ if bootstrapPhase.isPreparing {
73
+ return .preparing
74
+ }
75
+ return .idle
76
+ }
77
+
59
78
  init(
60
79
  pasteController: TranscriptPasteController = TranscriptPasteController(),
61
- bootstrap: @escaping AgentBootstrap = { requirement, force in
62
- AgentRuntime.shared.ensureReady(for: requirement, force: force)
80
+ bootstrap: @escaping AgentBootstrap = { requirement, force, progress in
81
+ AgentRuntime.shared.ensureReady(for: requirement, force: force, progress: progress)
63
82
  }
64
83
  ) {
65
84
  self.pasteController = pasteController
@@ -82,13 +101,12 @@ final class AgentCommandRunner: ObservableObject {
82
101
  hasStartedTranscriptionWarmUp = true
83
102
 
84
103
  activeCommandCount += 1
85
- if statusMessage == "Ready" {
86
- statusMessage = "Preparing voice service..."
87
- }
104
+ reportBootstrapPhase(.checkingRuntime)
88
105
 
89
106
  let bootstrap = self.bootstrap
107
+ let reportBootstrapPhase = makeBootstrapProgressReporter()
90
108
  DispatchQueue.global(qos: .utility).async {
91
- let result = bootstrap(.transcriptionModel, false)
109
+ let result = bootstrap(.transcriptionModel, false, reportBootstrapPhase)
92
110
 
93
111
  Task { @MainActor in
94
112
  self.activeCommandCount = max(0, self.activeCommandCount - 1)
@@ -97,12 +115,11 @@ final class AgentCommandRunner: ObservableObject {
97
115
  }
98
116
 
99
117
  if result.exitCode == 0 {
100
- if self.statusMessage == "Preparing voice service..." {
101
- self.statusMessage = "Ready"
102
- }
118
+ self.reportBootstrapPhase(.idle)
103
119
  return
104
120
  }
105
121
 
122
+ self.reportBootstrapPhase(.failed)
106
123
  self.recordFailure(title: "Startup Voice Service Warm-Up", result: result)
107
124
  self.statusMessage = result.output.isEmpty
108
125
  ? "Voice service warm-up failed with exit code \(result.exitCode)"
@@ -111,6 +128,57 @@ final class AgentCommandRunner: ObservableObject {
111
128
  }
112
129
  }
113
130
 
131
+ private func reportBootstrapPhase(_ phase: BootstrapPhase) {
132
+ let wasPreparing = bootstrapPhase.isPreparing
133
+ let phaseChanged = bootstrapPhase != phase
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
+ }
145
+ }
146
+
147
+ private func makeBootstrapProgressReporter() -> AgentBootstrapProgress {
148
+ { [weak self] phase in
149
+ Task { @MainActor in
150
+ self?.reportBootstrapPhase(phase)
151
+ }
152
+ }
153
+ }
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) % 3
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
+
114
182
  @discardableResult
115
183
  func beginHoldToTranscribe() -> Bool {
116
184
  guard holdTranscriptionState == .idle else {
@@ -171,19 +239,23 @@ final class AgentCommandRunner: ObservableObject {
171
239
  }
172
240
 
173
241
  activeCommandCount += 1
174
- statusMessage = isStopRequest
175
- ? "Stopping \(command.title)..."
176
- : "Running \(command.title)..."
242
+ if !self.bootstrapPhase.isPreparing {
243
+ statusMessage = isStopRequest
244
+ ? "Stopping \(command.title)..."
245
+ : "Running \(command.title)..."
246
+ }
177
247
 
178
248
  let bootstrap = self.bootstrap
249
+ let reportBootstrapPhase = makeBootstrapProgressReporter()
179
250
  let commandArguments = command.resolvedArguments(extraInstructions: TranscriptionSettings.extraInstructions)
180
251
  DispatchQueue.global(qos: .userInitiated).async {
181
- let bootstrapResult = bootstrap(command.bootstrapRequirement, command.forceBootstrap)
252
+ let bootstrapResult = bootstrap(command.bootstrapRequirement, command.forceBootstrap, reportBootstrapPhase)
182
253
  guard bootstrapResult.exitCode == 0 else {
183
254
  let message = Self.statusMessage(for: command, result: bootstrapResult)
184
255
  let notificationTitle = Self.notificationTitle(for: command, result: bootstrapResult)
185
256
  let notificationBody = Self.notificationBody(for: command, result: bootstrapResult, statusMessage: message)
186
257
  Task { @MainActor in
258
+ self.reportBootstrapPhase(.failed)
187
259
  if isStopRequest {
188
260
  self.clearStopRequested(for: command)
189
261
  }
@@ -200,6 +272,10 @@ final class AgentCommandRunner: ObservableObject {
200
272
  return
201
273
  }
202
274
 
275
+ Task { @MainActor in
276
+ self.reportBootstrapPhase(.idle)
277
+ }
278
+
203
279
  if shouldStartRecording {
204
280
  Task { @MainActor in
205
281
  if self.beginRecordingIndicator(for: command) {
@@ -261,14 +337,17 @@ final class AgentCommandRunner: ObservableObject {
261
337
  statusMessage = "Stopping Toggle Transcription..."
262
338
 
263
339
  let bootstrap = self.bootstrap
340
+ let reportBootstrapPhase = makeBootstrapProgressReporter()
264
341
  DispatchQueue.global(qos: .userInitiated).async {
265
342
  let bootstrapResult = bootstrap(
266
343
  AgentCommand.stopTranscription.bootstrapRequirement,
267
- AgentCommand.stopTranscription.forceBootstrap
344
+ AgentCommand.stopTranscription.forceBootstrap,
345
+ reportBootstrapPhase
268
346
  )
269
347
  guard bootstrapResult.exitCode == 0 else {
270
348
  let message = Self.statusMessage(for: AgentCommand.stopTranscription, result: bootstrapResult)
271
349
  Task { @MainActor in
350
+ self.reportBootstrapPhase(.failed)
272
351
  self.holdTranscriptionState = .idle
273
352
  self.lastOutput = bootstrapResult.output
274
353
  self.recordFailure(command: AgentCommand.stopTranscription, result: bootstrapResult)
@@ -281,6 +360,10 @@ final class AgentCommandRunner: ObservableObject {
281
360
  return
282
361
  }
283
362
 
363
+ Task { @MainActor in
364
+ self.reportBootstrapPhase(.idle)
365
+ }
366
+
284
367
  let result = AgentRuntime.shared.runAgentCLI(arguments: AgentCommand.stopTranscription.arguments)
285
368
 
286
369
  Task { @MainActor in
@@ -170,7 +170,10 @@ struct AgentRuntime {
170
170
  exit(0)
171
171
  }
172
172
 
173
- func ensureInstalled(force: Bool = false) -> CommandResult {
173
+ func ensureInstalled(
174
+ force: Bool = false,
175
+ progress: AgentBootstrapProgress = { _ in }
176
+ ) -> CommandResult {
174
177
  let mode = runtimeMode
175
178
  do {
176
179
  try prepareDirectories(for: mode)
@@ -179,6 +182,7 @@ struct AgentRuntime {
179
182
  }
180
183
 
181
184
  if mode == .userInstalled {
185
+ progress(.checkingRuntime)
182
186
  return ensureUserInstalledCLIAvailable()
183
187
  }
184
188
 
@@ -188,6 +192,7 @@ struct AgentRuntime {
188
192
  return CommandResult(exitCode: 0, output: "")
189
193
  }
190
194
 
195
+ progress(.installingRuntime)
191
196
  guard fileManager.isExecutableFile(atPath: bundledUVURL.path) else {
192
197
  return CommandResult(
193
198
  exitCode: 127,
@@ -243,36 +248,54 @@ struct AgentRuntime {
243
248
  "packageSource=\(agentCLIPackageSource)\ninstallRequirement=\(agentCLIInstallRequirement)\n"
244
249
  }
245
250
 
246
- func ensureReady(for requirement: AgentBootstrapRequirement, force: Bool = false) -> CommandResult {
251
+ func ensureReady(
252
+ for requirement: AgentBootstrapRequirement,
253
+ force: Bool = false,
254
+ progress: AgentBootstrapProgress = { _ in }
255
+ ) -> CommandResult {
247
256
  Self.bootstrapQueue.sync {
248
- ensureReadyUnsynchronized(for: requirement, force: force)
257
+ ensureReadyUnsynchronized(for: requirement, force: force, progress: progress)
249
258
  }
250
259
  }
251
260
 
252
- private func ensureReadyUnsynchronized(for requirement: AgentBootstrapRequirement, force: Bool = false) -> CommandResult {
261
+ private func ensureReadyUnsynchronized(
262
+ for requirement: AgentBootstrapRequirement,
263
+ force: Bool = false,
264
+ progress: AgentBootstrapProgress
265
+ ) -> CommandResult {
253
266
  switch requirement {
254
267
  case .cliRuntime:
255
- return ensureInstalled(force: force)
268
+ return ensureInstalled(force: force, progress: progress)
256
269
  case .transcription:
257
- let installResult = ensureInstalled(force: force)
270
+ let installResult = ensureInstalled(force: force, progress: progress)
258
271
  guard installResult.exitCode == 0 else {
259
272
  return installResult
260
273
  }
261
- return ensureWhisperDaemon(force: force)
274
+ return ensureWhisperDaemon(force: force, progress: progress)
262
275
  case .transcriptionModel:
263
- let daemonResult = ensureReadyUnsynchronized(for: .transcription, force: force)
276
+ let daemonResult = ensureReadyUnsynchronized(
277
+ for: .transcription,
278
+ force: force,
279
+ progress: progress
280
+ )
264
281
  guard daemonResult.exitCode == 0 else {
265
282
  return daemonResult
266
283
  }
284
+ progress(.warmingWhisperModel)
267
285
  return warmUpWhisperModel()
268
286
  }
269
287
  }
270
288
 
271
- private func ensureWhisperDaemon(force: Bool = false) -> CommandResult {
289
+ private func ensureWhisperDaemon(
290
+ force: Bool = false,
291
+ progress: AgentBootstrapProgress
292
+ ) -> CommandResult {
272
293
  if !force, (try? String(contentsOf: whisperDaemonMarkerURL)) == whisperDaemonMarkerContents {
294
+ progress(.waitingForVoiceService)
273
295
  return waitForWhisperDaemonReady()
274
296
  }
275
297
 
298
+ progress(.installingVoiceService)
276
299
  let result = runAgentCLI(arguments: ["daemon", "install", "whisper", "-y"])
277
300
  guard result.exitCode == 0 else {
278
301
  return result
@@ -283,6 +306,7 @@ struct AgentRuntime {
283
306
  atomically: true,
284
307
  encoding: .utf8
285
308
  )
309
+ progress(.waitingForVoiceService)
286
310
  return waitForWhisperDaemonReady()
287
311
  }
288
312
 
@@ -0,0 +1,58 @@
1
+ import Foundation
2
+
3
+ enum AgentBootstrapRequirement: Equatable {
4
+ case cliRuntime
5
+ case transcription
6
+ case transcriptionModel
7
+ }
8
+
9
+ enum BootstrapPhase: Equatable {
10
+ case idle
11
+ case checkingRuntime
12
+ case installingRuntime
13
+ case installingVoiceService
14
+ case waitingForVoiceService
15
+ case warmingWhisperModel
16
+ case failed
17
+
18
+ var isPreparing: Bool {
19
+ switch self {
20
+ case .idle, .failed:
21
+ return false
22
+ case .checkingRuntime, .installingRuntime, .installingVoiceService, .waitingForVoiceService, .warmingWhisperModel:
23
+ return true
24
+ }
25
+ }
26
+
27
+ var statusMessage: String {
28
+ switch self {
29
+ case .idle:
30
+ return "Ready"
31
+ case .checkingRuntime:
32
+ return "Checking CLI runtime..."
33
+ case .installingRuntime:
34
+ return "Installing CLI runtime..."
35
+ case .installingVoiceService:
36
+ return "Installing voice service..."
37
+ case .waitingForVoiceService:
38
+ return "Waiting for voice service..."
39
+ case .warmingWhisperModel:
40
+ return "Warming Whisper model..."
41
+ case .failed:
42
+ return "Voice service warm-up failed"
43
+ }
44
+ }
45
+
46
+ func statusMessage(animationTick: Int, elapsedSeconds: Int) -> String {
47
+ switch self {
48
+ case .waitingForVoiceService:
49
+ let periodCount = (animationTick % 3) + 1
50
+ return "Waiting for voice service\(String(repeating: ".", count: periodCount)) (\(elapsedSeconds)s)"
51
+ case .idle, .checkingRuntime, .installingRuntime, .installingVoiceService, .warmingWhisperModel, .failed:
52
+ return statusMessage
53
+ }
54
+ }
55
+ }
56
+
57
+ typealias AgentBootstrapProgress = (BootstrapPhase) -> Void
58
+ typealias AgentBootstrap = (AgentBootstrapRequirement, Bool, @escaping AgentBootstrapProgress) -> CommandResult
@@ -0,0 +1,111 @@
1
+ import AppKit
2
+ import Foundation
3
+ import SwiftUI
4
+
5
+ enum MenuBarIconState: Equatable {
6
+ case idle
7
+ case preparing
8
+ case recording
9
+ }
10
+
11
+ struct AgentCLIMenuBarIcon: View {
12
+ let state: MenuBarIconState
13
+
14
+ var body: some View {
15
+ if let image = Self.logoImage(state: state) {
16
+ Image(nsImage: image)
17
+ .resizable()
18
+ .aspectRatio(contentMode: .fit)
19
+ .frame(width: 22, height: 18)
20
+ .id(state)
21
+ .accessibilityLabel(accessibilityLabel)
22
+ } else {
23
+ Image(systemName: fallbackSystemImage)
24
+ .id(state)
25
+ .accessibilityLabel(accessibilityLabel)
26
+ }
27
+ }
28
+
29
+ private var accessibilityLabel: Text {
30
+ switch state {
31
+ case .idle:
32
+ return Text("Agent CLI")
33
+ case .preparing:
34
+ return Text("Agent CLI preparing")
35
+ case .recording:
36
+ return Text("Agent CLI recording")
37
+ }
38
+ }
39
+
40
+ private var fallbackSystemImage: String {
41
+ switch state {
42
+ case .idle:
43
+ return "person.crop.circle"
44
+ case .preparing:
45
+ return "arrow.triangle.2.circlepath.circle.fill"
46
+ case .recording:
47
+ return "record.circle.fill"
48
+ }
49
+ }
50
+
51
+ private static func logoImage(state: MenuBarIconState) -> NSImage? {
52
+ switch state {
53
+ case .idle:
54
+ return idleLogoImage
55
+ case .preparing:
56
+ return preparingLogoImage
57
+ case .recording:
58
+ return recordingLogoImage
59
+ }
60
+ }
61
+
62
+ private static let idleLogoImage: NSImage? = {
63
+ guard let url = Bundle.main.url(forResource: "logo-avatar", withExtension: "svg"),
64
+ let image = NSImage(contentsOf: url)
65
+ else {
66
+ return nil
67
+ }
68
+ image.isTemplate = true
69
+ image.size = NSSize(width: 18, height: 18)
70
+ return image
71
+ }()
72
+
73
+ private static let recordingLogoImage: NSImage? = makeRecordingLogoImage()
74
+ private static let preparingLogoImage: NSImage? = makePreparingLogoImage()
75
+
76
+ private static func makeRecordingLogoImage() -> NSImage? {
77
+ makeBadgedLogoImage(badgeColor: .systemRed, badgeDiameter: 7)
78
+ }
79
+
80
+ private static func makePreparingLogoImage() -> NSImage? {
81
+ makeBadgedLogoImage(badgeColor: .controlAccentColor, badgeDiameter: 7)
82
+ }
83
+
84
+ private static func makeBadgedLogoImage(badgeColor: NSColor, badgeDiameter: CGFloat) -> NSImage? {
85
+ guard let url = Bundle.main.url(forResource: "logo-avatar", withExtension: "svg"),
86
+ let avatar = NSImage(contentsOf: url)
87
+ else {
88
+ return nil
89
+ }
90
+
91
+ avatar.size = NSSize(width: 18, height: 18)
92
+
93
+ let image = NSImage(size: NSSize(width: 22, height: 18))
94
+ image.lockFocus()
95
+ avatar.draw(
96
+ in: NSRect(x: 0, y: 0, width: 18, height: 18),
97
+ from: .zero,
98
+ operation: .sourceOver,
99
+ fraction: 1
100
+ )
101
+
102
+ NSColor.white.setFill()
103
+ NSBezierPath(ovalIn: NSRect(x: 12.5, y: 0.5, width: 10, height: 10)).fill()
104
+ badgeColor.setFill()
105
+ NSBezierPath(ovalIn: NSRect(x: 14, y: 2, width: badgeDiameter, height: badgeDiameter)).fill()
106
+ image.unlockFocus()
107
+
108
+ image.isTemplate = false
109
+ return image
110
+ }
111
+ }
@@ -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
+ }