agent-cli 0.105.2__tar.gz → 0.106.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.105.2 → agent_cli-0.106.0}/.github/workflows/docker.yml +4 -4
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/pytest.yml +1 -1
- {agent_cli-0.105.2 → agent_cli-0.106.0}/PKG-INFO +1 -1
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/transcribe.py +24 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +6 -1
- agent_cli-0.106.0/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +17 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +85 -28
- agent_cli-0.106.0/macos/AgentCLI/Tests/AgentCLITests/TranscriptionResultTests.swift +23 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +89 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/appcast.xml +19 -15
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_transcribe.py +2 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_transcribe_agent.py +61 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_transcribe_recovery.py +5 -1
- agent_cli-0.105.2/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +0 -6
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude-plugin/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude-plugin/marketplace.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude-plugin/plugin.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.cursorrules +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.dockerignore +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.env.example +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/logo.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/release-drafter.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/renovate.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/scripts/check_extras_sync.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/scripts/check_plugin_skill_sync.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/scripts/normalize_appcast.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/scripts/sync_extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/scripts/sync_requirements.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/automerge.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/docs.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/markdown-code-runner.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/release-drafter.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/release.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.github/workflows/toc.yaml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.gitignore +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.jscpd.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.pre-commit-config.yaml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.prompts/docs-review.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/.prompts/pr-review.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/CLAUDE.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/LICENSE +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/LLAMA_SERVER_USAGE.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/__main__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_extras.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_overrides/nemo-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/.gitkeep +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/audio.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/diarization.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/faster-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/kokoro.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/llm.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/memory.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/mlx-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/nemo-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/piper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/rag.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/server.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/speed.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/vad.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/vectordb.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/whisper-transformers.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_requirements/wyoming.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/_tools.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/_voice_agent_common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/assistant.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/autocorrect.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/chat.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/diarize_live_session.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/memory/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/memory/add.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/memory/proxy.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/rag_proxy.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/speak.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/speakers.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/transcribe_live.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/agents/voice_edit.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/config_cmd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/constants.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/alignment.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/audio_format.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/chroma.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/deps.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/openai_proxy.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/process.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/reranker.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/speaker_identity.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/sse.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/transcription_logger.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/vad.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/core/watch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/daemon/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/daemon/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/_branch_name.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/_config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/_output.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/cleanup.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/aider.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/claude.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/codex.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/copilot.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/gemini.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/opencode.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/coding_agents/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/cursor.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/emacs.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/jetbrains.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/nano.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/neovim.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/sublime.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/vim.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/vscode.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/editors/zed.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/hooks.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/launch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/project.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/skill/SKILL.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/skill/examples.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/apple_terminal.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/cmux.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/gnome.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/iterm2.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/kitty.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/tmux.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/warp.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/terminals/zellij.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/dev/worktree.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/docs_gen.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/example-config.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/hotkeys.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/launchd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/service_config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/services.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/install/systemd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_files.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_filters.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_git.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_ingest.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_persistence.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_prompt.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_retrieval.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_streaming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/_tasks.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/entities.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/memory/models.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/opts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/py.typed +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/_indexing.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/_prompt.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/_retriever.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/rag/models.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/.runtime/.gitkeep +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/run-openwakeword.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/setup-linux.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/setup-macos.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/setup-windows.ps1 +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/scripts/start-all-services.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/model_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/model_registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/proxy/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/proxy/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/proxy/diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/streaming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/backends/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/backends/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/backends/kokoro.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/backends/piper.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/model_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/model_registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/tts/wyoming_handler.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/mlx.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/nemo.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/backends/transformers.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/languages.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/model_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/model_registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/server/whisper/wyoming_handler.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/services/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/services/_wyoming_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/services/asr.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/services/llm.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/services/tts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/agent_cli/services/wake_word.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/diarization.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/docker-compose.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/memory-proxy.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/rag-proxy.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/transcribe-proxy.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/tts.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docker/whisper.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/CNAME +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/architecture/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/architecture/memory.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/architecture/rag.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/assistant.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/autocorrect.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/chat.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/config.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/daemon.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/dev.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/diarize-live-session.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/install-extras.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/install-hotkeys.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/install-services.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/memory.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/rag-proxy.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/server/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/server/transcribe-proxy.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/server/tts.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/server/whisper.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/speak.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/speakers.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/start-services.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/transcribe-live.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/transcribe.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/commands/voice-edit.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/configuration.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/getting-started.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/iOS_Shortcut_Guide.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/docker.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/linux.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/macos-app.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/macos.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/nixos.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/installation/windows.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/logo-avatar.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/logo-clean.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/run_markdown_code_runner.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/docs/system-integration.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/example.agent-cli-config.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/justfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Package.resolved +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Package.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Resources/Info.plist +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AppMetadata.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AppUpdater.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/LiveTranscriptionPreview.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatus.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatusRow.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityTracker.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/SettingsWindowController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/StatusMenuController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/ConfigurableHotkeyControllerTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/LivePreviewSwiftTestingTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/LiveTranscriptionPreviewTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/build-macos-app.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/macos/test-macos-app-e2e.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/pyproject.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/reddit.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/shell.nix +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_fix_my_text.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_interactive.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_interactive_extra.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_memory_add.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_speak.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_speak_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_speakers.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_transcribe_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_transcribe_live.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_tts_common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_tts_common_extra.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_voice_agent_common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_voice_edit.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_voice_edit_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/agents/test_wake_word_assistant.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/conftest.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_audio_format.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_audio_levels.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_chroma.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_sse.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_vad.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/core/test_watch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_cleanup.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_coding_agents.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_editors.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_hooks.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_launch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_project.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_terminals.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_verification.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/dev/test_worktree.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/install/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/install/test_extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/install/test_launchd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_api_health.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_api_integration_liveish.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_files.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_filters.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_git_integration.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_memory_integration.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_proxy_passthrough.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/memory/test_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/mocks/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/mocks/audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/mocks/llm.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/mocks/wyoming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_history.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_indexing.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_rag_client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_rag_integration_liveish.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_rag_proxy_passthrough.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_retriever.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/rag/test_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_alignment.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_api_integration.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_asr.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_asr_recovery.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_audio_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_config_cmd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_daemon.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_diarize_live_session.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_docs_gen.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_env_vars.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_faster_whisper_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_json_output.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_llm.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_llm_gemini.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_macos_app.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_memory_tools.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_mlx_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_nemo_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_normalize_appcast.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_process_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_proxy_diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_requires_extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_server_streaming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_server_tts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_server_tts_wyoming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_server_whisper.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_server_whisper_wyoming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_services.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_speaker_identity.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_tools.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_transformers_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_tts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_wake_word.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_whisper_backend_audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/tests/test_wyoming_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/uv.lock +0 -0
- {agent_cli-0.105.2 → agent_cli-0.106.0}/zensical.toml +0 -0
|
@@ -49,7 +49,7 @@ jobs:
|
|
|
49
49
|
fetch-depth: 0 # Full history for version detection
|
|
50
50
|
|
|
51
51
|
- name: Set up Docker Buildx
|
|
52
|
-
uses: docker/setup-buildx-action@v4.
|
|
52
|
+
uses: docker/setup-buildx-action@v4.4.1
|
|
53
53
|
|
|
54
54
|
- name: Log in to Container Registry
|
|
55
55
|
uses: docker/login-action@v4.5.1
|
|
@@ -79,7 +79,7 @@ jobs:
|
|
|
79
79
|
type=sha,suffix=-${{ matrix.suffix }}
|
|
80
80
|
|
|
81
81
|
- name: Build and push
|
|
82
|
-
uses: docker/build-push-action@v7.
|
|
82
|
+
uses: docker/build-push-action@v7.4.0
|
|
83
83
|
with:
|
|
84
84
|
context: .
|
|
85
85
|
file: ${{ matrix.dockerfile }}
|
|
@@ -122,7 +122,7 @@ jobs:
|
|
|
122
122
|
fetch-depth: 0 # Full history for version detection
|
|
123
123
|
|
|
124
124
|
- name: Set up Docker Buildx
|
|
125
|
-
uses: docker/setup-buildx-action@v4.
|
|
125
|
+
uses: docker/setup-buildx-action@v4.4.1
|
|
126
126
|
|
|
127
127
|
- name: Log in to Container Registry
|
|
128
128
|
uses: docker/login-action@v4.5.1
|
|
@@ -152,7 +152,7 @@ jobs:
|
|
|
152
152
|
type=sha
|
|
153
153
|
|
|
154
154
|
- name: Build and push
|
|
155
|
-
uses: docker/build-push-action@v7.
|
|
155
|
+
uses: docker/build-push-action@v7.4.0
|
|
156
156
|
with:
|
|
157
157
|
context: .
|
|
158
158
|
file: ${{ matrix.dockerfile }}
|
|
@@ -43,6 +43,6 @@ jobs:
|
|
|
43
43
|
run: uv run --extra audio --extra diarization --extra llm --extra rag --extra memory --extra vad --extra faster-whisper --extra piper --extra kokoro --extra server --extra speed --extra test pytest -vvv
|
|
44
44
|
- name: Upload coverage reports to Codecov
|
|
45
45
|
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
|
|
46
|
-
uses: codecov/codecov-action@v7.1.
|
|
46
|
+
uses: codecov/codecov-action@v7.1.1
|
|
47
47
|
env:
|
|
48
48
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agent-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.106.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>
|
|
@@ -477,6 +477,9 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
|
|
|
477
477
|
live_preview_config=live_preview_config,
|
|
478
478
|
)
|
|
479
479
|
|
|
480
|
+
if transcript and not transcript.strip():
|
|
481
|
+
transcript = None
|
|
482
|
+
|
|
480
483
|
elapsed = time.monotonic() - start_time
|
|
481
484
|
|
|
482
485
|
# Apply diarization if enabled
|
|
@@ -554,6 +557,9 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
|
|
|
554
557
|
live=live,
|
|
555
558
|
context=combined_context,
|
|
556
559
|
)
|
|
560
|
+
if general_cfg.clipboard and not (processed_transcript or "").strip():
|
|
561
|
+
# Keep the raw speech recoverable if cleanup overwrote it with blank text.
|
|
562
|
+
pyperclip.copy(transcript)
|
|
557
563
|
|
|
558
564
|
# Log transcription if requested
|
|
559
565
|
if transcription_log:
|
|
@@ -615,6 +621,21 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
|
|
|
615
621
|
)
|
|
616
622
|
|
|
617
623
|
|
|
624
|
+
def _require_transcript(result: TranscriptResult, provider: str) -> None:
|
|
625
|
+
"""Do not report successful dictation when the backend produced no text."""
|
|
626
|
+
if not (result.get("transcript") or "").strip():
|
|
627
|
+
if result.get("raw_transcript"):
|
|
628
|
+
message = "LLM cleanup returned no text. Retry with --no-llm to use the raw transcript."
|
|
629
|
+
else:
|
|
630
|
+
message = f"No transcript returned by {provider}. Check the microphone and ASR server."
|
|
631
|
+
typer.echo(
|
|
632
|
+
f"{message} "
|
|
633
|
+
"If a recording was saved, retry with agent-cli transcribe --last-recording.",
|
|
634
|
+
err=True,
|
|
635
|
+
)
|
|
636
|
+
raise typer.Exit(1)
|
|
637
|
+
|
|
638
|
+
|
|
618
639
|
@app.command("transcribe", rich_help_panel="Voice Commands")
|
|
619
640
|
@requires_extras("audio", "llm", process_name="transcribe")
|
|
620
641
|
def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
@@ -896,6 +917,7 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
896
917
|
LOGGER.exception("Diarization failed")
|
|
897
918
|
_print_diarization_error(exc)
|
|
898
919
|
raise typer.Exit(1) from None
|
|
920
|
+
_require_transcript(result, asr_provider)
|
|
899
921
|
if json_output:
|
|
900
922
|
print(json.dumps(result))
|
|
901
923
|
return
|
|
@@ -937,6 +959,7 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
937
959
|
):
|
|
938
960
|
return
|
|
939
961
|
|
|
962
|
+
result = TranscriptResult(raw_transcript=None, transcript=None, llm_enabled=False)
|
|
940
963
|
# Use context manager before audio setup so --stop can target startup reliably.
|
|
941
964
|
try:
|
|
942
965
|
with process.pid_file_context(process_name), suppress(KeyboardInterrupt):
|
|
@@ -992,5 +1015,6 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
992
1015
|
LOGGER.exception("Diarization failed")
|
|
993
1016
|
_print_diarization_error(exc)
|
|
994
1017
|
raise typer.Exit(1) from None
|
|
1018
|
+
_require_transcript(result, asr_provider)
|
|
995
1019
|
if json_output:
|
|
996
1020
|
print(json.dumps(result))
|
{agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift
RENAMED
|
@@ -252,7 +252,12 @@ final class AgentCommandRunner: ObservableObject {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
let
|
|
255
|
+
let commandResult = AgentRuntime.shared.runAgentCLI(arguments: commandArguments)
|
|
256
|
+
// A stop acknowledgement may be empty; a completed recording must contain text.
|
|
257
|
+
// Validate here too because user-installed CLIs can predate the CLI-side check.
|
|
258
|
+
let result = shouldStartRecording && command.identifier == AgentCommand.toggleTranscription.identifier
|
|
259
|
+
? commandResult.requiringTranscript()
|
|
260
|
+
: commandResult
|
|
256
261
|
let message = Self.statusMessage(for: command, result: result)
|
|
257
262
|
let notificationTitle = Self.notificationTitle(for: command, result: result)
|
|
258
263
|
let notificationBody = Self.notificationBody(for: command, result: result, statusMessage: message)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
struct CommandResult {
|
|
4
|
+
let exitCode: Int32
|
|
5
|
+
let output: String
|
|
6
|
+
|
|
7
|
+
func requiringTranscript() -> CommandResult {
|
|
8
|
+
guard exitCode == 0, output.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
|
|
9
|
+
return self
|
|
10
|
+
}
|
|
11
|
+
return CommandResult(
|
|
12
|
+
exitCode: 1,
|
|
13
|
+
output: "No transcript returned. Check the microphone and ASR server, then try again. "
|
|
14
|
+
+ "If a recording was saved, recover it with agent-cli transcribe --last-recording."
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
}
|
{agent_cli-0.105.2 → agent_cli-0.106.0}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift
RENAMED
|
@@ -3,7 +3,7 @@ import Foundation
|
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
5
|
enum VoiceLevelOverlayLayout {
|
|
6
|
-
static let pillSize = CGSize(width:
|
|
6
|
+
static let pillSize = CGSize(width: 190, height: 38)
|
|
7
7
|
static let textWidth = CGFloat(420)
|
|
8
8
|
static let textHeight = CGFloat(86)
|
|
9
9
|
static let shadowRadius = CGFloat(13)
|
|
@@ -72,41 +72,57 @@ struct VoiceLevelOverlayView: View {
|
|
|
72
72
|
height: VoiceLevelOverlayLayout.panelSize(showsPreviewSpace: showsPreviewSpace).height,
|
|
73
73
|
alignment: .bottom
|
|
74
74
|
)
|
|
75
|
-
.
|
|
75
|
+
.accessibilityElement(children: .ignore)
|
|
76
|
+
.accessibilityLabel(Text(meter.captureState == .recording
|
|
77
|
+
? "Recording \(meter.recordingDuration)"
|
|
78
|
+
: meter.captureState.label))
|
|
79
|
+
.accessibilityValue(Text(showsPreviewSpace ? preview.text : ""))
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
private var levelMeter: some View {
|
|
79
|
-
HStack(
|
|
83
|
+
HStack(spacing: 8) {
|
|
84
|
+
if meter.captureState == .recording {
|
|
85
|
+
Text(meter.recordingDuration)
|
|
86
|
+
.font(.system(size: 12, weight: .semibold))
|
|
87
|
+
.monospacedDigit()
|
|
88
|
+
waveform
|
|
89
|
+
} else {
|
|
90
|
+
ProgressView()
|
|
91
|
+
.controlSize(.small)
|
|
92
|
+
Text(meter.captureState.label)
|
|
93
|
+
.font(.system(size: 12, weight: .semibold))
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
.foregroundStyle(statusColor)
|
|
97
|
+
.frame(width: VoiceLevelOverlayLayout.pillSize.width, height: VoiceLevelOverlayLayout.pillSize.height)
|
|
98
|
+
.background(Capsule().fill(statusColor.opacity(isLightMode ? 0.10 : 0.14)))
|
|
99
|
+
.background(Capsule().fill(backgroundColor))
|
|
100
|
+
.overlay(Capsule().stroke(statusColor.opacity(0.55), lineWidth: 1))
|
|
101
|
+
.shadow(
|
|
102
|
+
color: shadowColor,
|
|
103
|
+
radius: VoiceLevelOverlayLayout.shadowRadius,
|
|
104
|
+
y: VoiceLevelOverlayLayout.shadowYOffset
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private var waveform: some View {
|
|
109
|
+
HStack(alignment: .center, spacing: 2) {
|
|
80
110
|
ForEach(Array(meter.amplitudes.enumerated()), id: \.offset) { _, amplitude in
|
|
81
111
|
Capsule()
|
|
82
112
|
.fill(
|
|
83
113
|
LinearGradient(
|
|
84
114
|
colors: [
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
statusColor.opacity(0.65),
|
|
116
|
+
statusColor
|
|
87
117
|
],
|
|
88
118
|
startPoint: .bottom,
|
|
89
119
|
endPoint: .top
|
|
90
120
|
)
|
|
91
121
|
)
|
|
92
|
-
.frame(width:
|
|
122
|
+
.frame(width: 2, height: max(5, 25 * amplitude))
|
|
93
123
|
.animation(.easeOut(duration: 0.11), value: amplitude)
|
|
94
124
|
}
|
|
95
125
|
}
|
|
96
|
-
.frame(width: VoiceLevelOverlayLayout.pillSize.width, height: VoiceLevelOverlayLayout.pillSize.height)
|
|
97
|
-
.background(
|
|
98
|
-
Capsule()
|
|
99
|
-
.fill(backgroundColor)
|
|
100
|
-
)
|
|
101
|
-
.overlay(
|
|
102
|
-
Capsule()
|
|
103
|
-
.stroke(borderColor, lineWidth: 1)
|
|
104
|
-
)
|
|
105
|
-
.shadow(
|
|
106
|
-
color: shadowColor,
|
|
107
|
-
radius: VoiceLevelOverlayLayout.shadowRadius,
|
|
108
|
-
y: VoiceLevelOverlayLayout.shadowYOffset
|
|
109
|
-
)
|
|
110
126
|
}
|
|
111
127
|
|
|
112
128
|
private var isLightMode: Bool {
|
|
@@ -133,12 +149,15 @@ struct VoiceLevelOverlayView: View {
|
|
|
133
149
|
Color.black.opacity(isLightMode ? 0.16 : 0.24)
|
|
134
150
|
}
|
|
135
151
|
|
|
136
|
-
private var
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
152
|
+
private var statusColor: Color {
|
|
153
|
+
if meter.captureState == .recording {
|
|
154
|
+
return isLightMode
|
|
155
|
+
? Color(red: 0.04, green: 0.40, blue: 0.18)
|
|
156
|
+
: Color(red: 0.42, green: 0.91, blue: 0.58)
|
|
157
|
+
}
|
|
158
|
+
return isLightMode
|
|
159
|
+
? Color(red: 0.62, green: 0.34, blue: 0.0)
|
|
160
|
+
: Color(red: 1.0, green: 0.74, blue: 0.25)
|
|
142
161
|
}
|
|
143
162
|
}
|
|
144
163
|
|
|
@@ -306,10 +325,28 @@ enum VoiceLevelLog {
|
|
|
306
325
|
}()
|
|
307
326
|
}
|
|
308
327
|
|
|
328
|
+
enum VoiceCaptureState {
|
|
329
|
+
case idle
|
|
330
|
+
case connecting
|
|
331
|
+
case recording
|
|
332
|
+
case waitingForAudio
|
|
333
|
+
|
|
334
|
+
var label: String {
|
|
335
|
+
switch self {
|
|
336
|
+
case .idle: return "Ready"
|
|
337
|
+
case .connecting: return "Connecting…"
|
|
338
|
+
case .recording: return "Recording"
|
|
339
|
+
case .waitingForAudio: return "Waiting for audio…"
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
309
344
|
final class VoiceLevelMeter: ObservableObject {
|
|
310
345
|
static let shared = VoiceLevelMeter()
|
|
311
346
|
|
|
312
347
|
@Published private(set) var amplitudes = VoiceLevelMeter.idleAmplitudes
|
|
348
|
+
@Published private(set) var captureState = VoiceCaptureState.idle
|
|
349
|
+
@Published private(set) var recordingDuration = "00:00"
|
|
313
350
|
|
|
314
351
|
private static let barCount = 16
|
|
315
352
|
private static let idleAmplitudes = Array(repeating: CGFloat(0.16), count: barCount)
|
|
@@ -319,6 +356,7 @@ final class VoiceLevelMeter: ObservableObject {
|
|
|
319
356
|
private let levelLogURL: URL
|
|
320
357
|
private let now: () -> Date
|
|
321
358
|
private var timer: Timer?
|
|
359
|
+
private var recordingStartedAt: Date?
|
|
322
360
|
private var phase = 0.0
|
|
323
361
|
private var smoothedLevel = CGFloat(0.16)
|
|
324
362
|
|
|
@@ -330,6 +368,9 @@ final class VoiceLevelMeter: ObservableObject {
|
|
|
330
368
|
func start() {
|
|
331
369
|
guard timer == nil else { return }
|
|
332
370
|
VoiceLevelLog.reset(levelLogURL)
|
|
371
|
+
captureState = .connecting
|
|
372
|
+
recordingStartedAt = nil
|
|
373
|
+
recordingDuration = "00:00"
|
|
333
374
|
phase = 0
|
|
334
375
|
smoothedLevel = Self.idleLevel
|
|
335
376
|
amplitudes = Self.idleAmplitudes
|
|
@@ -345,13 +386,29 @@ final class VoiceLevelMeter: ObservableObject {
|
|
|
345
386
|
func stop() {
|
|
346
387
|
timer?.invalidate()
|
|
347
388
|
timer = nil
|
|
389
|
+
captureState = .idle
|
|
390
|
+
recordingStartedAt = nil
|
|
391
|
+
recordingDuration = "00:00"
|
|
348
392
|
phase = 0
|
|
349
393
|
smoothedLevel = Self.idleLevel
|
|
350
394
|
amplitudes = Self.idleAmplitudes
|
|
351
395
|
}
|
|
352
396
|
|
|
353
|
-
|
|
354
|
-
|
|
397
|
+
func pollLevel() {
|
|
398
|
+
guard timer != nil else { return }
|
|
399
|
+
let now = now()
|
|
400
|
+
guard let level = VoiceLevelLog.latestLevel(from: levelLogURL, now: now) else {
|
|
401
|
+
if captureState == .recording {
|
|
402
|
+
captureState = .waitingForAudio
|
|
403
|
+
}
|
|
404
|
+
amplitudes = Self.idleAmplitudes
|
|
405
|
+
return
|
|
406
|
+
}
|
|
407
|
+
captureState = .recording
|
|
408
|
+
let startedAt = recordingStartedAt ?? now
|
|
409
|
+
recordingStartedAt = startedAt
|
|
410
|
+
let elapsedSeconds = max(0, Int(now.timeIntervalSince(startedAt)))
|
|
411
|
+
recordingDuration = String(format: "%02d:%02d", elapsedSeconds / 60, elapsedSeconds % 60)
|
|
355
412
|
updateDisplay(level: level)
|
|
356
413
|
}
|
|
357
414
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#if canImport(XCTest)
|
|
2
|
+
import XCTest
|
|
3
|
+
@testable import AgentCLI
|
|
4
|
+
|
|
5
|
+
final class TranscriptionResultTests: XCTestCase {
|
|
6
|
+
func testEmptySuccessfulRecordingBecomesFailure() {
|
|
7
|
+
for output in ["", " \n\t"] {
|
|
8
|
+
let result = CommandResult(exitCode: 0, output: output).requiringTranscript()
|
|
9
|
+
XCTAssertNotEqual(result.exitCode, 0)
|
|
10
|
+
XCTAssertTrue(result.output.contains("No transcript"))
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func testTranscriptAndBackendFailureArePreserved() {
|
|
15
|
+
let success = CommandResult(exitCode: 0, output: "Hello world").requiringTranscript()
|
|
16
|
+
XCTAssertEqual(success.exitCode, 0)
|
|
17
|
+
XCTAssertEqual(success.output, "Hello world")
|
|
18
|
+
let failure = CommandResult(exitCode: 7, output: "Connection lost").requiringTranscript()
|
|
19
|
+
XCTAssertEqual(failure.exitCode, 7)
|
|
20
|
+
XCTAssertEqual(failure.output, "Connection lost")
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
#endif
|
|
@@ -4,6 +4,95 @@ import XCTest
|
|
|
4
4
|
@testable import AgentCLI
|
|
5
5
|
|
|
6
6
|
final class VoiceLevelMeterTests: XCTestCase {
|
|
7
|
+
func testRecordingTimerExcludesStartupAndResetsBetweenRecordings() throws {
|
|
8
|
+
let logURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
|
9
|
+
var now = try XCTUnwrap(Self.iso8601.date(from: "2026-06-04T12:00:00Z"))
|
|
10
|
+
let meter = VoiceLevelMeter(levelLogURL: logURL, now: { now })
|
|
11
|
+
defer {
|
|
12
|
+
meter.stop()
|
|
13
|
+
try? FileManager.default.removeItem(at: logURL)
|
|
14
|
+
}
|
|
15
|
+
meter.start()
|
|
16
|
+
now = now.addingTimeInterval(10)
|
|
17
|
+
meter.pollLevel()
|
|
18
|
+
XCTAssertEqual(meter.recordingDuration, "00:00")
|
|
19
|
+
|
|
20
|
+
func publishAudio() throws {
|
|
21
|
+
try "{\"timestamp\":\"\(Self.iso8601.string(from: now))\",\"level\":0}"
|
|
22
|
+
.write(to: logURL, atomically: true, encoding: .utf8)
|
|
23
|
+
meter.pollLevel()
|
|
24
|
+
}
|
|
25
|
+
try publishAudio()
|
|
26
|
+
XCTAssertEqual(meter.recordingDuration, "00:00")
|
|
27
|
+
now = now.addingTimeInterval(9)
|
|
28
|
+
try publishAudio()
|
|
29
|
+
XCTAssertEqual(meter.recordingDuration, "00:09")
|
|
30
|
+
now = now.addingTimeInterval(56)
|
|
31
|
+
try publishAudio()
|
|
32
|
+
XCTAssertEqual(meter.recordingDuration, "01:05")
|
|
33
|
+
now = now.addingTimeInterval(3600)
|
|
34
|
+
try publishAudio()
|
|
35
|
+
XCTAssertEqual(meter.recordingDuration, "61:05")
|
|
36
|
+
|
|
37
|
+
meter.stop()
|
|
38
|
+
XCTAssertEqual(meter.recordingDuration, "00:00")
|
|
39
|
+
meter.start()
|
|
40
|
+
try publishAudio()
|
|
41
|
+
XCTAssertEqual(meter.recordingDuration, "00:00")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func testRecordingReadinessFollowsFreshAudioIncludingSilence() throws {
|
|
45
|
+
let logURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
|
46
|
+
var now = try XCTUnwrap(Self.iso8601.date(from: "2026-06-04T12:00:00Z"))
|
|
47
|
+
let meter = VoiceLevelMeter(levelLogURL: logURL, now: { now })
|
|
48
|
+
defer {
|
|
49
|
+
meter.stop()
|
|
50
|
+
try? FileManager.default.removeItem(at: logURL)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// A previous recording must not make a new request look ready.
|
|
54
|
+
try #"{"timestamp":"2026-06-04T12:00:00Z","level":0.9}"#
|
|
55
|
+
.write(to: logURL, atomically: true, encoding: .utf8)
|
|
56
|
+
meter.start()
|
|
57
|
+
XCTAssertEqual(meter.captureState, .connecting)
|
|
58
|
+
|
|
59
|
+
try #"{"timestamp":"2026-06-04T12:00:00Z","level":0}"#
|
|
60
|
+
.write(to: logURL, atomically: true, encoding: .utf8)
|
|
61
|
+
meter.pollLevel()
|
|
62
|
+
XCTAssertEqual(meter.captureState, .recording, "Silent audio still proves capture is running.")
|
|
63
|
+
|
|
64
|
+
now = now.addingTimeInterval(2)
|
|
65
|
+
meter.pollLevel()
|
|
66
|
+
XCTAssertEqual(meter.captureState, .waitingForAudio)
|
|
67
|
+
|
|
68
|
+
try #"{"timestamp":"2026-06-04T12:00:02Z","level":0.6}"#
|
|
69
|
+
.write(to: logURL, atomically: true, encoding: .utf8)
|
|
70
|
+
meter.pollLevel()
|
|
71
|
+
XCTAssertEqual(meter.captureState, .recording)
|
|
72
|
+
|
|
73
|
+
meter.stop()
|
|
74
|
+
meter.pollLevel()
|
|
75
|
+
XCTAssertEqual(meter.captureState, .idle, "Late polling must not revive a released overlay.")
|
|
76
|
+
meter.start()
|
|
77
|
+
XCTAssertEqual(meter.captureState, .connecting)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
func testConnectingDoesNotAnimateFakeMicrophoneActivity() throws {
|
|
81
|
+
let logURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
|
82
|
+
let meter = VoiceLevelMeter(levelLogURL: logURL)
|
|
83
|
+
defer {
|
|
84
|
+
meter.stop()
|
|
85
|
+
try? FileManager.default.removeItem(at: logURL)
|
|
86
|
+
}
|
|
87
|
+
meter.start()
|
|
88
|
+
let initialAmplitudes = meter.amplitudes
|
|
89
|
+
meter.pollLevel()
|
|
90
|
+
XCTAssertEqual(meter.captureState, .connecting)
|
|
91
|
+
XCTAssertEqual(meter.amplitudes, initialAmplitudes)
|
|
92
|
+
meter.stop()
|
|
93
|
+
XCTAssertEqual(meter.captureState, .idle)
|
|
94
|
+
}
|
|
95
|
+
|
|
7
96
|
func testDisplayAmplitudesUseSineWaveShape() {
|
|
8
97
|
let amplitudes = VoiceLevelMeter.displayAmplitudes(level: 0.6, phase: 0.22)
|
|
9
98
|
|
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
<title>Agent CLI Updates</title>
|
|
5
5
|
<link>https://github.com/basnijholt/agent-cli</link>
|
|
6
6
|
<description>Signed Agent CLI macOS app updates.</description>
|
|
7
|
+
<item>
|
|
8
|
+
<title>0.105.2</title>
|
|
9
|
+
<pubDate>Tue, 15 Sep 2026 07:58:55 +0000</pubDate>
|
|
10
|
+
<link>https://github.com/basnijholt/agent-cli</link>
|
|
11
|
+
<sparkle:version>206</sparkle:version>
|
|
12
|
+
<sparkle:shortVersionString>0.105.2</sparkle:shortVersionString>
|
|
13
|
+
<sparkle:minimumSystemVersion>13.0</sparkle:minimumSystemVersion>
|
|
14
|
+
<sparkle:hardwareRequirements>arm64</sparkle:hardwareRequirements>
|
|
15
|
+
<description sparkle:format="markdown"><![CDATA[## Bug fixes
|
|
16
|
+
|
|
17
|
+
- Accept M4A, OGG, MP3, and other FFmpeg-supported uploads in the Transformers ASR backend. Transformers and NeMo now share audio preparation, with invalid input reported as HTTP 400. (#644)
|
|
18
|
+
- Normalize stereo, non-16-bit, and non-16 kHz WAV uploads before WAV-only ASR backends read them, preventing incorrect sample interpretation. Standard 16 kHz mono 16-bit WAV uploads pass through unchanged. (#644)
|
|
19
|
+
- Stop FFmpeg conversions when requests are cancelled or conversion times out, then clean up temporary files. Faster-whisper retains native compressed-audio decoding without a system FFmpeg dependency. (#644)
|
|
20
|
+
|
|
21
|
+
**Full changelog:** https://github.com/basnijholt/agent-cli/compare/v0.105.1...v0.105.2
|
|
22
|
+
|
|
23
|
+
]]></description>
|
|
24
|
+
<enclosure url="https://github.com/basnijholt/agent-cli/releases/download/v0.105.2/AgentCLI.zip" length="18490908" type="application/octet-stream" sparkle:edSignature="DQiGmgOiPGeI4S/4tQdoA7mgsAlgN3qHh2Z4SyLpN70Tv/qr7MjBNM1r+FPn6gYdRYhaaK/XcKfWaX01H8F0Bw=="/>
|
|
25
|
+
</item>
|
|
7
26
|
<item>
|
|
8
27
|
<title>0.105.1</title>
|
|
9
28
|
<pubDate>Tue, 08 Sep 2026 13:10:30 +0000</pubDate>
|
|
@@ -193,20 +212,5 @@
|
|
|
193
212
|
]]></description>
|
|
194
213
|
<enclosure url="https://github.com/basnijholt/agent-cli/releases/download/v0.102.0/AgentCLI.zip" length="24388215" type="application/octet-stream" sparkle:edSignature="1b3tpgDf/VolJ9MLr0R5N9gPmOkYG7Uf6ZyXQTNLPTfiMeo2malwMj5kzTFcCp7xQr/jijUB7/nRNoSzZiBnCg=="/>
|
|
195
214
|
</item>
|
|
196
|
-
<item>
|
|
197
|
-
<title>0.101.0</title>
|
|
198
|
-
<pubDate>Wed, 10 Jun 2026 18:21:45 +0000</pubDate>
|
|
199
|
-
<link>https://github.com/basnijholt/agent-cli</link>
|
|
200
|
-
<sparkle:version>196</sparkle:version>
|
|
201
|
-
<sparkle:shortVersionString>0.101.0</sparkle:shortVersionString>
|
|
202
|
-
<sparkle:minimumSystemVersion>13.0</sparkle:minimumSystemVersion>
|
|
203
|
-
<sparkle:hardwareRequirements>arm64</sparkle:hardwareRequirements>
|
|
204
|
-
<description sparkle:format="markdown"><![CDATA[## What’s Changed
|
|
205
|
-
|
|
206
|
-
* Add zellij multiplexer support to agent-cli dev (#590) @basnijholt
|
|
207
|
-
|
|
208
|
-
]]></description>
|
|
209
|
-
<enclosure url="https://github.com/basnijholt/agent-cli/releases/download/v0.101.0/AgentCLI.zip" length="22912290" type="application/octet-stream" sparkle:edSignature="9re7kqubAoQgSpsmDvAT/LCWy8/tI1RzR2uGkb+BCwGJbtfvuzDU2ETm/JD+lpQt3Ayik6ULAOv+/5S6JSmdBA=="/>
|
|
210
|
-
</item>
|
|
211
215
|
</channel>
|
|
212
216
|
</rss>
|
|
@@ -36,6 +36,7 @@ async def test_transcribe_main_llm_enabled(
|
|
|
36
36
|
caplog: pytest.LogCaptureFixture,
|
|
37
37
|
) -> None:
|
|
38
38
|
"""Test the main function of the transcribe agent with LLM enabled."""
|
|
39
|
+
mock_process_and_update_clipboard.return_value = "Hello world."
|
|
39
40
|
# Mock audio stream
|
|
40
41
|
mock_stream = MagicMock()
|
|
41
42
|
mock_stream.read.return_value = (MagicMock(tobytes=lambda: b"\0" * 1024), False)
|
|
@@ -515,6 +516,7 @@ async def test_transcribe_includes_clipboard_context(
|
|
|
515
516
|
mock_signal_handling_context: MagicMock,
|
|
516
517
|
) -> None:
|
|
517
518
|
"""Ensure clipboard content is forwarded to the LLM context."""
|
|
519
|
+
mock_process_and_update_clipboard.return_value = "Hello world."
|
|
518
520
|
# Mock audio stream
|
|
519
521
|
mock_stream = MagicMock()
|
|
520
522
|
mock_stream.read.return_value = (MagicMock(tobytes=lambda: b"\0" * 1024), False)
|
|
@@ -213,3 +213,64 @@ def test_transcribe_stop_json_cleans_stale_pid(
|
|
|
213
213
|
assert payload["was_running"] is False
|
|
214
214
|
assert payload["stale_cleaned"] is True
|
|
215
215
|
assert not pid_file.exists()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def test_quiet_empty_transcription_fails_without_touching_clipboard() -> None:
|
|
219
|
+
"""An empty ASR result must not look like successful dictation to the app."""
|
|
220
|
+
with (
|
|
221
|
+
patch("agent_cli.agents.transcribe.asr.create_transcriber") as create_transcriber,
|
|
222
|
+
patch("agent_cli.agents.transcribe.process.pid_file_context"),
|
|
223
|
+
patch("agent_cli.agents.transcribe.setup_devices", return_value=(0, "mic", None)),
|
|
224
|
+
patch("pyperclip.copy") as copy,
|
|
225
|
+
):
|
|
226
|
+
create_transcriber.return_value = AsyncMock(return_value=None)
|
|
227
|
+
result = runner.invoke(app, ["transcribe", "--quiet", "--no-llm", "--no-clipboard"])
|
|
228
|
+
assert result.exit_code != 0
|
|
229
|
+
assert "No transcript" in result.output
|
|
230
|
+
copy.assert_not_called()
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def test_quiet_whitespace_transcription_preserves_clipboard() -> None:
|
|
234
|
+
"""Whitespace from ASR is not dictation and must not erase clipboard text."""
|
|
235
|
+
with (
|
|
236
|
+
patch("agent_cli.agents.transcribe.asr.create_transcriber") as create_transcriber,
|
|
237
|
+
patch("agent_cli.agents.transcribe.process.pid_file_context"),
|
|
238
|
+
patch("agent_cli.agents.transcribe.setup_devices", return_value=(0, "mic", None)),
|
|
239
|
+
patch("pyperclip.copy") as copy,
|
|
240
|
+
):
|
|
241
|
+
create_transcriber.return_value = AsyncMock(return_value=" \n\t")
|
|
242
|
+
result = runner.invoke(app, ["transcribe", "--quiet", "--no-llm", "--clipboard"])
|
|
243
|
+
assert result.exit_code != 0
|
|
244
|
+
assert "No transcript" in result.output
|
|
245
|
+
copy.assert_not_called()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def test_empty_file_transcription_fails(tmp_path: Path) -> None:
|
|
249
|
+
"""Recovery must fail visibly too when a saved recording yields no text."""
|
|
250
|
+
recording = tmp_path / "recording.wav"
|
|
251
|
+
recording.touch()
|
|
252
|
+
with patch("agent_cli.agents.transcribe._async_main", new_callable=AsyncMock) as transcribe:
|
|
253
|
+
transcribe.return_value = {"raw_transcript": None, "transcript": None, "llm_enabled": False}
|
|
254
|
+
result = runner.invoke(app, ["transcribe", "--from-file", str(recording), "--quiet"])
|
|
255
|
+
assert result.exit_code != 0
|
|
256
|
+
assert "No transcript" in result.output
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def test_empty_llm_cleanup_retains_raw_transcript() -> None:
|
|
260
|
+
"""Failed cleanup must leave recoverable speech, not blank the clipboard."""
|
|
261
|
+
clipboard = ["previous clipboard"]
|
|
262
|
+
agent = MagicMock()
|
|
263
|
+
agent.run = AsyncMock(return_value=MagicMock(output=" \n"))
|
|
264
|
+
with (
|
|
265
|
+
patch("agent_cli.agents.transcribe.asr.create_transcriber") as create_transcriber,
|
|
266
|
+
patch("agent_cli.agents.transcribe.process.pid_file_context"),
|
|
267
|
+
patch("agent_cli.agents.transcribe.setup_devices", return_value=(0, "mic", None)),
|
|
268
|
+
patch("agent_cli.services.llm.create_llm_agent", return_value=agent),
|
|
269
|
+
patch("pyperclip.paste", side_effect=lambda: clipboard[0]),
|
|
270
|
+
patch("pyperclip.copy", side_effect=lambda text: clipboard.__setitem__(0, text)),
|
|
271
|
+
):
|
|
272
|
+
create_transcriber.return_value = AsyncMock(return_value="recognized speech")
|
|
273
|
+
result = runner.invoke(app, ["transcribe", "--quiet", "--llm", "--clipboard"])
|
|
274
|
+
assert result.exit_code != 0
|
|
275
|
+
assert "LLM" in result.output
|
|
276
|
+
assert clipboard[0] == "recognized speech"
|
|
@@ -751,7 +751,11 @@ def test_transcribe_command_last_recording_disabled(
|
|
|
751
751
|
patch("agent_cli.agents.transcribe._async_main", new_callable=AsyncMock) as mock_async_main,
|
|
752
752
|
patch("agent_cli.core.process.pid_file_context") as mock_pid_context,
|
|
753
753
|
):
|
|
754
|
-
mock_async_main.return_value = {
|
|
754
|
+
mock_async_main.return_value = {
|
|
755
|
+
"raw_transcript": "hello",
|
|
756
|
+
"transcript": "hello",
|
|
757
|
+
"llm_enabled": False,
|
|
758
|
+
}
|
|
755
759
|
|
|
756
760
|
# Call transcribe with --last-recording disabled (0)
|
|
757
761
|
transcribe.transcribe(
|
|
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
|