agent-cli 0.79.0__tar.gz → 0.80.0__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.
- {agent_cli-0.79.0 → agent_cli-0.80.0}/PKG-INFO +1 -1
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/cli.py +17 -4
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/setup-macos.sh +5 -15
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/backends/piper.py +76 -80
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/dev.md +1 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/installation/macos.md +15 -14
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude-plugin/README.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude-plugin/marketplace.json +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude-plugin/plugin.json +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.cursorrules +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.dockerignore +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.env.example +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/logo.svg +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/release-drafter.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/renovate.json +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/scripts/check_extras_sync.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/scripts/check_plugin_skill_sync.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/scripts/sync_extras.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/scripts/sync_requirements.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/automerge.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/docker.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/docs.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/markdown-code-runner.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/pytest.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/release-drafter.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/release.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.github/workflows/toc.yaml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.gitignore +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.jscpd.json +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.pre-commit-config.yaml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.prompts/docs-review.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/.prompts/pr-review.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/CLAUDE.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/LICENSE +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/README.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/__main__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_extras.json +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/.gitkeep +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/audio.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/faster-whisper.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/kokoro.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/llm.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/memory.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/mlx-whisper.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/piper.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/rag.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/server.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/speed.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/vad.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/whisper-transformers.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_requirements/wyoming.txt +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/_tools.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/_voice_agent_common.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/assistant.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/autocorrect.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/chat.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/memory/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/memory/add.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/memory/proxy.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/rag_proxy.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/speak.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/transcribe.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/transcribe_live.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/agents/voice_edit.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/cli.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/config.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/config_cmd.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/constants.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/audio.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/audio_format.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/chroma.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/deps.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/openai_proxy.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/process.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/reranker.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/sse.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/transcription_logger.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/vad.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/core/watch.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/daemon/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/daemon/cli.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/aider.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/base.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/claude.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/codex.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/copilot.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/gemini.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/opencode.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/coding_agents/registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/base.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/cursor.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/emacs.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/jetbrains.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/nano.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/neovim.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/sublime.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/vim.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/vscode.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/editors/zed.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/project.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/skill/SKILL.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/skill/examples.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/apple_terminal.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/base.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/gnome.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/iterm2.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/kitty.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/tmux.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/warp.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/terminals/zellij.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/dev/worktree.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/docs_gen.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/example-config.toml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/common.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/extras.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/hotkeys.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/launchd.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/service_config.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/services.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/install/systemd.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_files.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_filters.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_git.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_indexer.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_ingest.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_persistence.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_prompt.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_retrieval.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_store.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_streaming.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/_tasks.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/client.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/engine.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/entities.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/memory/models.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/opts.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/py.typed +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/_indexer.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/_indexing.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/_prompt.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/_retriever.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/_store.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/_utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/client.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/engine.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/rag/models.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/.runtime/.gitkeep +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/run-openwakeword.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/setup-linux.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/setup-windows.ps1 +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/scripts/start-all-services.sh +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/cli.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/common.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/model_manager.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/model_registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/proxy/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/proxy/api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/streaming.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/backends/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/backends/base.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/backends/kokoro.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/model_manager.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/model_registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/tts/wyoming_handler.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/backends/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/backends/base.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/backends/mlx.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/backends/transformers.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/languages.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/model_manager.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/model_registry.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/server/whisper/wyoming_handler.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/services/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/services/_wyoming_utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/services/asr.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/services/llm.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/services/tts.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/agent_cli/services/wake_word.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docker/docker-compose.yml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docker/memory-proxy.Dockerfile +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docker/rag-proxy.Dockerfile +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docker/transcribe-proxy.Dockerfile +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docker/tts.Dockerfile +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docker/whisper.Dockerfile +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/CNAME +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/architecture/index.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/architecture/memory.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/architecture/rag.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/assistant.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/autocorrect.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/chat.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/config.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/daemon.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/index.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/install-extras.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/install-hotkeys.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/install-services.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/memory.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/rag-proxy.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/server/index.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/server/transcribe-proxy.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/server/tts.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/server/whisper.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/speak.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/start-services.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/transcribe-live.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/transcribe.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/commands/voice-edit.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/configuration.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/getting-started.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/iOS_Shortcut_Guide.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/index.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/installation/docker.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/installation/index.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/installation/linux.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/installation/nixos.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/installation/windows.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/logo-clean.svg +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/run_markdown_code_runner.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/docs/system-integration.md +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/example.agent-cli-config.toml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/justfile +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/pyproject.toml +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/shell.nix +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_fix_my_text.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_interactive.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_interactive_extra.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_memory_add.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_speak.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_speak_e2e.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_transcribe.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_transcribe_agent.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_transcribe_e2e.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_transcribe_live.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_transcribe_recovery.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_tts_common.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_tts_common_extra.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_voice_agent_common.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_voice_edit.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_voice_edit_e2e.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/agents/test_wake_word_assistant.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/conftest.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/core/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/core/test_audio_format.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/core/test_chroma.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/core/test_sse.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/core/test_vad.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/core/test_watch.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_cli.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_coding_agents.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_editors.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_project.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_terminals.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_verification.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/dev/test_worktree.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/install/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/install/test_extras.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_api_health.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_api_integration_liveish.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_client.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_engine.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_files.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_filters.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_git_integration.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_indexer.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_memory_integration.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_proxy_passthrough.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_store.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/memory/test_utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/mocks/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/mocks/audio.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/mocks/llm.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/mocks/wyoming.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/__init__.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_engine.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_history.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_indexer.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_indexing.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_rag_client.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_rag_integration_liveish.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_rag_proxy_passthrough.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_retriever.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_store.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/rag/test_utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_api.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_api_integration.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_asr.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_asr_recovery.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_audio_e2e.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_cli.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_config.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_config_cmd.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_daemon.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_docs_gen.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_env_vars.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_json_output.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_llm.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_llm_gemini.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_memory_tools.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_mlx_backend.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_process_manager.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_requires_extras.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_server_streaming.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_server_tts.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_server_whisper.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_services.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_tools.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_transformers_backend.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_tts.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_wake_word.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/tests/test_wyoming_utils.py +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/uv.lock +0 -0
- {agent_cli-0.79.0 → agent_cli-0.80.0}/zensical.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.80.0
|
|
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>
|
|
@@ -1469,6 +1469,8 @@ def _clean_merged_worktrees(
|
|
|
1469
1469
|
repo_root: Path,
|
|
1470
1470
|
dry_run: bool,
|
|
1471
1471
|
yes: bool,
|
|
1472
|
+
*,
|
|
1473
|
+
force: bool = False,
|
|
1472
1474
|
) -> None:
|
|
1473
1475
|
"""Remove worktrees with merged PRs (requires gh CLI)."""
|
|
1474
1476
|
_info("Checking for worktrees with merged PRs...")
|
|
@@ -1509,7 +1511,7 @@ def _clean_merged_worktrees(
|
|
|
1509
1511
|
for wt, _pr_url in to_remove:
|
|
1510
1512
|
success, error = worktree.remove_worktree(
|
|
1511
1513
|
wt.path,
|
|
1512
|
-
force=
|
|
1514
|
+
force=force,
|
|
1513
1515
|
delete_branch=True,
|
|
1514
1516
|
repo_path=repo_root,
|
|
1515
1517
|
)
|
|
@@ -1523,6 +1525,8 @@ def _clean_no_commits_worktrees(
|
|
|
1523
1525
|
repo_root: Path,
|
|
1524
1526
|
dry_run: bool,
|
|
1525
1527
|
yes: bool,
|
|
1528
|
+
*,
|
|
1529
|
+
force: bool = False,
|
|
1526
1530
|
) -> None:
|
|
1527
1531
|
"""Remove worktrees with no commits ahead of the default branch."""
|
|
1528
1532
|
_info("Checking for worktrees with no commits...")
|
|
@@ -1546,7 +1550,7 @@ def _clean_no_commits_worktrees(
|
|
|
1546
1550
|
for wt in to_remove:
|
|
1547
1551
|
success, error = worktree.remove_worktree(
|
|
1548
1552
|
wt.path,
|
|
1549
|
-
force=
|
|
1553
|
+
force=force,
|
|
1550
1554
|
delete_branch=True,
|
|
1551
1555
|
repo_path=repo_root,
|
|
1552
1556
|
)
|
|
@@ -1584,6 +1588,14 @@ def clean(
|
|
|
1584
1588
|
bool,
|
|
1585
1589
|
typer.Option("--yes", "-y", help="Skip confirmation prompts"),
|
|
1586
1590
|
] = False,
|
|
1591
|
+
force: Annotated[
|
|
1592
|
+
bool,
|
|
1593
|
+
typer.Option(
|
|
1594
|
+
"--force",
|
|
1595
|
+
"-f",
|
|
1596
|
+
help="Force removal of worktrees with modified or untracked files",
|
|
1597
|
+
),
|
|
1598
|
+
] = False,
|
|
1587
1599
|
) -> None:
|
|
1588
1600
|
"""Clean up stale worktrees and empty directories.
|
|
1589
1601
|
|
|
@@ -1601,6 +1613,7 @@ def clean(
|
|
|
1601
1613
|
- `dev clean` — Basic cleanup
|
|
1602
1614
|
- `dev clean --merged` — Remove worktrees with merged PRs
|
|
1603
1615
|
- `dev clean --merged --dry-run` — Preview what would be removed
|
|
1616
|
+
- `dev clean --no-commits --force` — Force remove abandoned worktrees with local changes
|
|
1604
1617
|
"""
|
|
1605
1618
|
repo_root = _ensure_git_repo()
|
|
1606
1619
|
|
|
@@ -1635,11 +1648,11 @@ def clean(
|
|
|
1635
1648
|
|
|
1636
1649
|
# --merged mode: remove worktrees with merged PRs
|
|
1637
1650
|
if merged:
|
|
1638
|
-
_clean_merged_worktrees(repo_root, dry_run, yes)
|
|
1651
|
+
_clean_merged_worktrees(repo_root, dry_run, yes, force=force)
|
|
1639
1652
|
|
|
1640
1653
|
# --no-commits mode: remove worktrees with no commits ahead of default branch
|
|
1641
1654
|
if no_commits:
|
|
1642
|
-
_clean_no_commits_worktrees(repo_root, dry_run, yes)
|
|
1655
|
+
_clean_no_commits_worktrees(repo_root, dry_run, yes, force=force)
|
|
1643
1656
|
|
|
1644
1657
|
|
|
1645
1658
|
@app.command("doctor")
|
|
@@ -47,15 +47,9 @@ echo "⏳ This may take a few minutes depending on your internet connection..."
|
|
|
47
47
|
sleep 2 # Give Ollama service time to start
|
|
48
48
|
ollama pull gemma3:4b
|
|
49
49
|
|
|
50
|
-
# Install
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
echo " This will run speech-to-text on Apple Silicon using MLX"
|
|
54
|
-
curl -fsSL https://raw.githubusercontent.com/basnijholt/wyoming-mlx-whisper/main/scripts/install_service.sh | bash
|
|
55
|
-
echo "✅ wyoming-mlx-whisper installed as launchd service"
|
|
56
|
-
else
|
|
57
|
-
echo "ℹ️ Skipping wyoming-mlx-whisper service (Intel Mac - use Linux-style setup)"
|
|
58
|
-
fi
|
|
50
|
+
# Install whisper and tts as launchd daemons
|
|
51
|
+
echo "🎤 Installing whisper and tts-kokoro as background daemons..."
|
|
52
|
+
agent-cli daemon install whisper tts-kokoro -y
|
|
59
53
|
|
|
60
54
|
echo ""
|
|
61
55
|
echo "✅ Setup complete! You can now run the services:"
|
|
@@ -65,12 +59,8 @@ echo " ./start-all-services.sh"
|
|
|
65
59
|
echo ""
|
|
66
60
|
echo "Option 2 - Run services individually:"
|
|
67
61
|
echo " 1. Ollama: running as brew service (brew services start ollama)"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
else
|
|
71
|
-
echo " 2. Whisper: agent-cli server whisper"
|
|
72
|
-
fi
|
|
73
|
-
echo " 3. Piper: agent-cli server tts --backend piper"
|
|
62
|
+
echo " 2. Whisper: running as launchd daemon (agent-cli daemon status whisper)"
|
|
63
|
+
echo " 3. TTS: running as launchd daemon (agent-cli daemon status tts-kokoro)"
|
|
74
64
|
echo " 4. OpenWakeWord: ./run-openwakeword.sh"
|
|
75
65
|
echo ""
|
|
76
66
|
echo "🎉 agent-cli has been installed and is ready to use!"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Piper TTS backend using piper-tts library."""
|
|
1
|
+
"""Piper TTS backend using piper-tts library with subprocess isolation."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -7,10 +7,14 @@ import io
|
|
|
7
7
|
import logging
|
|
8
8
|
import time
|
|
9
9
|
import wave
|
|
10
|
+
from concurrent.futures import ProcessPoolExecutor
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from multiprocessing import get_context
|
|
10
13
|
from pathlib import Path
|
|
11
|
-
from typing import
|
|
14
|
+
from typing import Any, NoReturn
|
|
12
15
|
|
|
13
16
|
from agent_cli import constants
|
|
17
|
+
from agent_cli.core.process import set_process_title
|
|
14
18
|
from agent_cli.server.tts.backends.base import (
|
|
15
19
|
BackendConfig,
|
|
16
20
|
InvalidTextError,
|
|
@@ -18,29 +22,45 @@ from agent_cli.server.tts.backends.base import (
|
|
|
18
22
|
get_backend_cache_dir,
|
|
19
23
|
)
|
|
20
24
|
|
|
21
|
-
if TYPE_CHECKING:
|
|
22
|
-
from piper import PiperVoice
|
|
23
|
-
|
|
24
25
|
logger = logging.getLogger(__name__)
|
|
25
26
|
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
# --- Subprocess state (only used within subprocess worker) ---
|
|
29
|
+
# This state persists across function calls within the subprocess because:
|
|
30
|
+
# 1. Model loading is expensive and must be reused across synthesis calls
|
|
31
|
+
# 2. The subprocess is long-lived (ProcessPoolExecutor reuses workers)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class _SubprocessState:
|
|
36
|
+
"""Container for subprocess-local state. Not shared with main process."""
|
|
37
|
+
|
|
38
|
+
voice: Any = None
|
|
39
|
+
sample_rate: int = constants.PIPER_DEFAULT_SAMPLE_RATE
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
_state = _SubprocessState()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _load_model_in_subprocess(
|
|
28
46
|
model_name: str,
|
|
29
47
|
cache_dir: str | None,
|
|
30
|
-
) ->
|
|
31
|
-
"""Load Piper model
|
|
48
|
+
) -> int:
|
|
49
|
+
"""Load Piper model in subprocess. Returns sample rate.
|
|
32
50
|
|
|
33
51
|
Args:
|
|
34
52
|
model_name: Model name (e.g., 'en_US-lessac-medium') or path to .onnx file.
|
|
35
53
|
cache_dir: Optional cache directory for downloaded models.
|
|
36
54
|
|
|
37
55
|
Returns:
|
|
38
|
-
|
|
56
|
+
Sample rate of loaded model.
|
|
39
57
|
|
|
40
58
|
"""
|
|
41
59
|
from piper import PiperVoice # noqa: PLC0415
|
|
42
60
|
from piper.download_voices import download_voice # noqa: PLC0415
|
|
43
61
|
|
|
62
|
+
set_process_title("tts-piper")
|
|
63
|
+
|
|
44
64
|
# Use default cache dir if not specified
|
|
45
65
|
download_dir = Path(cache_dir) if cache_dir else get_backend_cache_dir("piper")
|
|
46
66
|
download_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -50,7 +70,9 @@ def _load_model_sync(
|
|
|
50
70
|
if model_path.exists() and model_path.suffix == ".onnx":
|
|
51
71
|
# Direct path to model file
|
|
52
72
|
voice = PiperVoice.load(str(model_path), use_cuda=False)
|
|
53
|
-
|
|
73
|
+
_state.voice = voice
|
|
74
|
+
_state.sample_rate = voice.config.sample_rate
|
|
75
|
+
return _state.sample_rate
|
|
54
76
|
|
|
55
77
|
# Otherwise, treat as a voice name and download if needed
|
|
56
78
|
voice_code = model_name.strip()
|
|
@@ -60,24 +82,22 @@ def _load_model_sync(
|
|
|
60
82
|
logger.info("Downloading Piper voice: %s", voice_code)
|
|
61
83
|
download_voice(voice_code, download_dir)
|
|
62
84
|
|
|
63
|
-
# Load the voice
|
|
85
|
+
# Load the voice and store in subprocess state
|
|
64
86
|
voice = PiperVoice.load(str(expected_model_path), use_cuda=False)
|
|
87
|
+
_state.voice = voice
|
|
88
|
+
_state.sample_rate = voice.config.sample_rate
|
|
65
89
|
|
|
66
|
-
return
|
|
90
|
+
return _state.sample_rate
|
|
67
91
|
|
|
68
92
|
|
|
69
|
-
def
|
|
70
|
-
voice: PiperVoice,
|
|
93
|
+
def _synthesize_in_subprocess(
|
|
71
94
|
text: str,
|
|
72
|
-
sample_rate: int,
|
|
73
95
|
length_scale: float,
|
|
74
96
|
) -> tuple[bytes, float]:
|
|
75
|
-
"""Synthesize text to audio
|
|
97
|
+
"""Synthesize text to audio in subprocess. Uses model from _state.
|
|
76
98
|
|
|
77
99
|
Args:
|
|
78
|
-
voice: Loaded PiperVoice instance.
|
|
79
100
|
text: Text to synthesize.
|
|
80
|
-
sample_rate: Sample rate from model config.
|
|
81
101
|
length_scale: Length scale (inverse of speed).
|
|
82
102
|
|
|
83
103
|
Returns:
|
|
@@ -86,6 +106,10 @@ def _synthesize_sync(
|
|
|
86
106
|
"""
|
|
87
107
|
from piper import SynthesisConfig # noqa: PLC0415
|
|
88
108
|
|
|
109
|
+
if _state.voice is None:
|
|
110
|
+
msg = "Model not loaded in subprocess. Call _load_model_in_subprocess first."
|
|
111
|
+
raise RuntimeError(msg)
|
|
112
|
+
|
|
89
113
|
# Create synthesis config with speed adjustment
|
|
90
114
|
syn_config = SynthesisConfig(length_scale=length_scale)
|
|
91
115
|
|
|
@@ -94,91 +118,83 @@ def _synthesize_sync(
|
|
|
94
118
|
with wave.open(buffer, "wb") as wav_file:
|
|
95
119
|
wav_file.setnchannels(1)
|
|
96
120
|
wav_file.setsampwidth(2) # 16-bit
|
|
97
|
-
wav_file.setframerate(sample_rate)
|
|
121
|
+
wav_file.setframerate(_state.sample_rate)
|
|
98
122
|
|
|
99
123
|
# Synthesize and write audio chunks
|
|
100
|
-
for audio_chunk in voice.synthesize(text, syn_config):
|
|
124
|
+
for audio_chunk in _state.voice.synthesize(text, syn_config):
|
|
101
125
|
wav_file.writeframes(audio_chunk.audio_int16_bytes)
|
|
102
126
|
|
|
103
127
|
audio_data = buffer.getvalue()
|
|
104
128
|
|
|
105
129
|
# Calculate duration: PCM data size / (sample_rate * channels * bytes_per_sample)
|
|
106
130
|
data_size = len(audio_data) - constants.WAV_HEADER_SIZE
|
|
107
|
-
duration = data_size / (sample_rate * 1 * 2)
|
|
131
|
+
duration = data_size / (_state.sample_rate * 1 * 2)
|
|
108
132
|
|
|
109
133
|
return audio_data, duration
|
|
110
134
|
|
|
111
135
|
|
|
112
136
|
class PiperBackend:
|
|
113
|
-
"""Piper TTS backend
|
|
137
|
+
"""Piper TTS backend with subprocess isolation.
|
|
114
138
|
|
|
115
|
-
|
|
116
|
-
|
|
139
|
+
Uses subprocess isolation: when unloaded, the subprocess terminates
|
|
140
|
+
and all memory is freed by the OS. This ensures clean memory management.
|
|
117
141
|
"""
|
|
118
142
|
|
|
119
143
|
def __init__(self, config: BackendConfig) -> None:
|
|
120
|
-
"""Initialize the Piper backend.
|
|
121
|
-
|
|
122
|
-
Args:
|
|
123
|
-
config: Backend configuration.
|
|
124
|
-
|
|
125
|
-
"""
|
|
144
|
+
"""Initialize the Piper backend."""
|
|
126
145
|
self._config = config
|
|
127
|
-
self.
|
|
146
|
+
self._executor: ProcessPoolExecutor | None = None
|
|
128
147
|
self._sample_rate: int = constants.PIPER_DEFAULT_SAMPLE_RATE # Updated on load
|
|
129
148
|
self._device: str | None = None
|
|
130
149
|
|
|
131
150
|
@property
|
|
132
151
|
def is_loaded(self) -> bool:
|
|
133
|
-
"""Check if the model is
|
|
134
|
-
return self.
|
|
152
|
+
"""Check if the model is loaded."""
|
|
153
|
+
return self._executor is not None
|
|
135
154
|
|
|
136
155
|
@property
|
|
137
156
|
def device(self) -> str | None:
|
|
138
|
-
"""Get the device the model is
|
|
157
|
+
"""Get the device the model is on."""
|
|
139
158
|
return self._device
|
|
140
159
|
|
|
141
160
|
async def load(self) -> float:
|
|
142
|
-
"""
|
|
143
|
-
|
|
144
|
-
Returns:
|
|
145
|
-
Load duration in seconds.
|
|
146
|
-
|
|
147
|
-
"""
|
|
148
|
-
if self._voice is not None:
|
|
161
|
+
"""Start subprocess and load model."""
|
|
162
|
+
if self._executor is not None:
|
|
149
163
|
return 0.0
|
|
150
164
|
|
|
151
165
|
start_time = time.time()
|
|
152
166
|
|
|
153
|
-
#
|
|
167
|
+
# Subprocess isolation: spawn context for clean state
|
|
168
|
+
ctx = get_context("spawn")
|
|
169
|
+
self._executor = ProcessPoolExecutor(max_workers=1, mp_context=ctx)
|
|
170
|
+
|
|
154
171
|
loop = asyncio.get_running_loop()
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
172
|
+
self._sample_rate = await loop.run_in_executor(
|
|
173
|
+
self._executor,
|
|
174
|
+
_load_model_in_subprocess,
|
|
158
175
|
self._config.model_name,
|
|
159
176
|
str(self._config.cache_dir) if self._config.cache_dir else None,
|
|
160
177
|
)
|
|
161
178
|
|
|
162
|
-
self._voice = voice
|
|
163
|
-
self._sample_rate = sample_rate
|
|
164
179
|
self._device = "cpu" # Piper is CPU-only
|
|
165
180
|
|
|
166
181
|
load_duration = time.time() - start_time
|
|
167
182
|
logger.info(
|
|
168
|
-
"Loaded Piper model %s in %.2fs
|
|
183
|
+
"Loaded Piper model %s on %s in %.2fs",
|
|
169
184
|
self._config.model_name,
|
|
185
|
+
self._device,
|
|
170
186
|
load_duration,
|
|
171
|
-
self._sample_rate,
|
|
172
187
|
)
|
|
173
|
-
|
|
174
188
|
return load_duration
|
|
175
189
|
|
|
176
190
|
async def unload(self) -> None:
|
|
177
|
-
"""
|
|
178
|
-
if self.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
191
|
+
"""Shutdown subprocess, releasing all memory."""
|
|
192
|
+
if self._executor is None:
|
|
193
|
+
return
|
|
194
|
+
self._executor.shutdown(wait=False, cancel_futures=True)
|
|
195
|
+
self._executor = None
|
|
196
|
+
self._device = None
|
|
197
|
+
logger.info("Piper model %s unloaded (subprocess terminated)", self._config.model_name)
|
|
182
198
|
|
|
183
199
|
async def synthesize(
|
|
184
200
|
self,
|
|
@@ -187,23 +203,9 @@ class PiperBackend:
|
|
|
187
203
|
voice: str | None = None, # noqa: ARG002
|
|
188
204
|
speed: float = 1.0,
|
|
189
205
|
) -> SynthesisResult:
|
|
190
|
-
"""Synthesize text to audio.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
text: Text to synthesize.
|
|
194
|
-
voice: Voice to use (not used for Piper - voice is the model).
|
|
195
|
-
speed: Speech speed multiplier (0.25 to 4.0).
|
|
196
|
-
|
|
197
|
-
Returns:
|
|
198
|
-
SynthesisResult with audio data and metadata.
|
|
199
|
-
|
|
200
|
-
Raises:
|
|
201
|
-
InvalidTextError: If the text is empty or invalid.
|
|
202
|
-
RuntimeError: If the model is not loaded.
|
|
203
|
-
|
|
204
|
-
"""
|
|
205
|
-
if self._voice is None:
|
|
206
|
-
msg = "Model not loaded"
|
|
206
|
+
"""Synthesize text to audio."""
|
|
207
|
+
if self._executor is None:
|
|
208
|
+
msg = "Model not loaded. Call load() first."
|
|
207
209
|
raise RuntimeError(msg)
|
|
208
210
|
|
|
209
211
|
if not text or not text.strip():
|
|
@@ -211,20 +213,14 @@ class PiperBackend:
|
|
|
211
213
|
raise InvalidTextError(msg)
|
|
212
214
|
|
|
213
215
|
# Convert speed to length_scale (inverse relationship)
|
|
214
|
-
# Speed is already validated/clamped by the API layer
|
|
215
216
|
# length_scale < 1.0 = faster, > 1.0 = slower
|
|
216
217
|
length_scale = 1.0 / speed
|
|
217
218
|
|
|
218
|
-
# Run synthesis in executor to avoid blocking.
|
|
219
|
-
# Thread-safe: ONNX Runtime InferenceSession.run() is thread-safe since v1.10+,
|
|
220
|
-
# so concurrent requests can share the same PiperVoice instance safely.
|
|
221
219
|
loop = asyncio.get_running_loop()
|
|
222
220
|
audio_data, duration = await loop.run_in_executor(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
self._voice,
|
|
221
|
+
self._executor,
|
|
222
|
+
_synthesize_in_subprocess,
|
|
226
223
|
text,
|
|
227
|
-
self._sample_rate,
|
|
228
224
|
length_scale,
|
|
229
225
|
)
|
|
230
226
|
|
|
@@ -333,6 +333,7 @@ agent-cli dev clean [OPTIONS]
|
|
|
333
333
|
| `--no-commits` | `false` | Also remove worktrees with 0 commits ahead of default branch (abandoned branches) |
|
|
334
334
|
| `--dry-run, -n` | `false` | Preview what would be removed without actually removing |
|
|
335
335
|
| `--yes, -y` | `false` | Skip confirmation prompts |
|
|
336
|
+
| `--force, -f` | `false` | Force removal of worktrees with modified or untracked files |
|
|
336
337
|
|
|
337
338
|
|
|
338
339
|
<!-- OUTPUT:END -->
|
|
@@ -52,19 +52,19 @@ The `setup-macos.sh` script:
|
|
|
52
52
|
- ✅ Installs `uv` if needed
|
|
53
53
|
- ✅ Installs/checks Ollama (native macOS app)
|
|
54
54
|
- ✅ Installs Zellij for session management
|
|
55
|
-
- ✅
|
|
55
|
+
- ✅ Installs Whisper and TTS as launchd daemons via `agent-cli daemon install`
|
|
56
56
|
|
|
57
57
|
## Services Overview
|
|
58
58
|
|
|
59
|
-
| Service | Implementation
|
|
60
|
-
| ---------------- |
|
|
61
|
-
| **Ollama** | Native macOS app
|
|
62
|
-
| **Whisper** |
|
|
63
|
-
| **
|
|
64
|
-
| **OpenWakeWord** | Wyoming OpenWakeWord
|
|
59
|
+
| Service | Implementation | Port | GPU Support |
|
|
60
|
+
| ---------------- | ----------------------- | ----- | -------------------- |
|
|
61
|
+
| **Ollama** | Native macOS app | 11434 | ✅ Metal GPU |
|
|
62
|
+
| **Whisper** | MLX Whisper (via daemon)| 10300 | ✅ Apple Silicon MLX |
|
|
63
|
+
| **TTS (Kokoro)** | Kokoro TTS (via daemon) | 10200 | ✅ Metal GPU (MPS) |
|
|
64
|
+
| **OpenWakeWord** | Wyoming OpenWakeWord | 10400 | N/A |
|
|
65
65
|
|
|
66
66
|
> [!NOTE]
|
|
67
|
-
> Whisper
|
|
67
|
+
> Whisper and TTS run as launchd daemons via `agent-cli daemon install`, using MLX and Metal for GPU acceleration on Apple Silicon.
|
|
68
68
|
|
|
69
69
|
## Session Management with Zellij
|
|
70
70
|
|
|
@@ -95,13 +95,14 @@ brew services start ollama
|
|
|
95
95
|
# Or run in foreground:
|
|
96
96
|
ollama serve
|
|
97
97
|
|
|
98
|
-
# Whisper
|
|
99
|
-
|
|
100
|
-
#
|
|
101
|
-
agent-cli
|
|
98
|
+
# Whisper and TTS are installed as launchd daemons
|
|
99
|
+
agent-cli daemon status # Check all daemon status
|
|
100
|
+
agent-cli daemon install whisper # Install whisper daemon
|
|
101
|
+
agent-cli daemon install tts-kokoro # Install TTS daemon
|
|
102
102
|
|
|
103
|
-
#
|
|
104
|
-
agent-cli server
|
|
103
|
+
# Or run in foreground (without daemon):
|
|
104
|
+
agent-cli server whisper
|
|
105
|
+
agent-cli server tts --backend kokoro
|
|
105
106
|
|
|
106
107
|
# OpenWakeWord
|
|
107
108
|
scripts/run-openwakeword.sh
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|