agent-cli 0.105.2__tar.gz → 0.107.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.107.0}/.github/workflows/docker.yml +4 -4
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/pytest.yml +1 -1
- {agent_cli-0.105.2 → agent_cli-0.107.0}/PKG-INFO +1 -1
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/transcribe.py +24 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +9 -2
- agent_cli-0.107.0/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +17 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +2 -1
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +187 -35
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +13 -0
- agent_cli-0.107.0/macos/AgentCLI/Tests/AgentCLITests/TranscriptionResultTests.swift +23 -0
- agent_cli-0.107.0/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +279 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/appcast.xml +46 -48
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_transcribe.py +2 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_transcribe_agent.py +61 -0
- {agent_cli-0.105.2 → agent_cli-0.107.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/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +0 -98
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude-plugin/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude-plugin/marketplace.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude-plugin/plugin.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.cursorrules +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.dockerignore +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.env.example +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/logo.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/release-drafter.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/renovate.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/scripts/check_extras_sync.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/scripts/check_plugin_skill_sync.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/scripts/normalize_appcast.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/scripts/sync_extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/scripts/sync_requirements.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/automerge.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/docs.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/markdown-code-runner.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/release-drafter.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/release.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.github/workflows/toc.yaml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.gitignore +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.jscpd.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.pre-commit-config.yaml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.prompts/docs-review.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/.prompts/pr-review.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/CLAUDE.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/LICENSE +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/LLAMA_SERVER_USAGE.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/__main__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_extras.json +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_overrides/nemo-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/.gitkeep +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/audio.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/diarization.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/faster-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/kokoro.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/llm.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/memory.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/mlx-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/nemo-whisper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/piper.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/rag.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/server.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/speed.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/vad.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/vectordb.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/whisper-transformers.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_requirements/wyoming.txt +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/_tools.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/_voice_agent_common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/assistant.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/autocorrect.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/chat.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/diarize_live_session.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/memory/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/memory/add.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/memory/proxy.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/rag_proxy.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/speak.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/speakers.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/transcribe_live.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/agents/voice_edit.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/config_cmd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/constants.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/alignment.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/audio_format.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/chroma.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/deps.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/openai_proxy.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/process.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/reranker.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/speaker_identity.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/sse.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/transcription_logger.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/vad.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/core/watch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/daemon/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/daemon/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/_branch_name.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/_config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/_output.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/cleanup.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/aider.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/claude.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/codex.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/copilot.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/gemini.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/opencode.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/coding_agents/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/cursor.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/emacs.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/jetbrains.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/nano.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/neovim.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/sublime.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/vim.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/vscode.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/editors/zed.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/hooks.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/launch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/project.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/skill/SKILL.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/skill/examples.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/apple_terminal.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/cmux.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/gnome.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/iterm2.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/kitty.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/tmux.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/warp.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/terminals/zellij.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/dev/worktree.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/docs_gen.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/example-config.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/hotkeys.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/launchd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/service_config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/services.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/install/systemd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_files.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_filters.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_git.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_ingest.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_persistence.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_prompt.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_retrieval.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_streaming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/_tasks.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/entities.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/memory/models.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/opts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/py.typed +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/_indexing.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/_prompt.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/_retriever.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/rag/models.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/.runtime/.gitkeep +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/run-openwakeword.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/setup-linux.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/setup-macos.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/setup-windows.ps1 +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/scripts/start-all-services.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/model_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/model_registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/proxy/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/proxy/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/proxy/diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/streaming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/backends/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/backends/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/backends/kokoro.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/backends/piper.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/model_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/model_registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/tts/wyoming_handler.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/base.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/mlx.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/nemo.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/backends/transformers.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/languages.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/model_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/model_registry.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/server/whisper/wyoming_handler.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/services/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/services/_wyoming_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/services/asr.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/services/llm.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/services/tts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/agent_cli/services/wake_word.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/diarization.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/docker-compose.yml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/memory-proxy.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/rag-proxy.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/transcribe-proxy.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/tts.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docker/whisper.Dockerfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/CNAME +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/architecture/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/architecture/memory.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/architecture/rag.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/assistant.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/autocorrect.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/chat.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/config.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/daemon.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/dev.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/diarize-live-session.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/install-extras.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/install-hotkeys.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/install-services.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/memory.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/rag-proxy.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/server/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/server/transcribe-proxy.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/server/tts.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/server/whisper.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/speak.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/speakers.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/start-services.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/transcribe-live.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/transcribe.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/commands/voice-edit.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/configuration.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/getting-started.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/iOS_Shortcut_Guide.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/docker.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/index.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/linux.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/macos-app.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/macos.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/nixos.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/installation/windows.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/logo-avatar.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/logo-clean.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/run_markdown_code_runner.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/docs/system-integration.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/example.agent-cli-config.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/justfile +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Package.resolved +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Package.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/README.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Resources/Info.plist +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AppMetadata.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/AppUpdater.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/LiveTranscriptionPreview.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatus.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatusRow.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityTracker.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/SettingsWindowController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/StatusMenuController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/ConfigurableHotkeyControllerTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/LivePreviewSwiftTestingTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/LiveTranscriptionPreviewTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/build-macos-app.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/macos/test-macos-app-e2e.sh +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/pyproject.toml +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/reddit.md +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/shell.nix +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_fix_my_text.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_interactive.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_interactive_extra.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_memory_add.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_speak.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_speak_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_speakers.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_transcribe_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_transcribe_live.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_tts_common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_tts_common_extra.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_voice_agent_common.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_voice_edit.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_voice_edit_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/agents/test_wake_word_assistant.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/conftest.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_audio_format.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_audio_levels.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_chroma.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_sse.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_vad.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/core/test_watch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_cleanup.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_coding_agents.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_editors.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_hooks.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_launch.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_project.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_terminals.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_verification.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/dev/test_worktree.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/install/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/install/test_extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/install/test_launchd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_api_health.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_api_integration_liveish.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_files.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_filters.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_git_integration.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_memory_integration.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_proxy_passthrough.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/memory/test_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/mocks/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/mocks/audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/mocks/llm.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/mocks/wyoming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/__init__.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_engine.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_history.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_indexer.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_indexing.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_rag_client.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_rag_integration_liveish.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_rag_proxy_passthrough.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_retriever.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_store.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/rag/test_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_alignment.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_api.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_api_integration.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_asr.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_asr_recovery.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_audio_e2e.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_cli.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_config.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_config_cmd.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_daemon.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_diarize_live_session.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_docs_gen.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_env_vars.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_faster_whisper_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_json_output.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_llm.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_llm_gemini.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_macos_app.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_memory_tools.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_mlx_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_nemo_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_normalize_appcast.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_process_manager.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_proxy_diarization.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_requires_extras.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_server_streaming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_server_tts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_server_tts_wyoming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_server_whisper.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_server_whisper_wyoming.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_services.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_speaker_identity.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_tools.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_transformers_backend.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_tts.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_wake_word.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_whisper_backend_audio.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/tests/test_wyoming_utils.py +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.0}/uv.lock +0 -0
- {agent_cli-0.105.2 → agent_cli-0.107.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.107.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.107.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift
RENAMED
|
@@ -161,13 +161,13 @@ final class AgentCommandRunner: ObservableObject {
|
|
|
161
161
|
holdTranscriptionState = .stopping
|
|
162
162
|
|
|
163
163
|
let wasRecording = recordingIndicator.isRecordingCommand(.toggleTranscription)
|
|
164
|
-
beginTranscribingActivity()
|
|
165
164
|
if wasRecording {
|
|
166
165
|
endRecordingIndicator(for: .toggleTranscription)
|
|
167
166
|
statusMessage = "Transcribing..."
|
|
168
167
|
} else {
|
|
169
168
|
statusMessage = "Stopping transcription as soon as it starts..."
|
|
170
169
|
}
|
|
170
|
+
beginTranscribingActivity()
|
|
171
171
|
stopHeldTranscriptionWhenReady()
|
|
172
172
|
}
|
|
173
173
|
|
|
@@ -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)
|
|
@@ -381,11 +386,13 @@ final class AgentCommandRunner: ObservableObject {
|
|
|
381
386
|
|
|
382
387
|
private func beginTranscribingActivity() {
|
|
383
388
|
activityTracker.beginTranscribing()
|
|
389
|
+
VoiceLevelOverlayController.shared.showTranscribing()
|
|
384
390
|
}
|
|
385
391
|
|
|
386
392
|
private func clearTranscribingActivityIfFinished() {
|
|
387
393
|
if pendingStopRecordingCommands.isEmpty && !holdTranscriptionState.isFinishing {
|
|
388
394
|
activityTracker.finishTranscribing()
|
|
395
|
+
VoiceLevelOverlayController.shared.finishTranscribing()
|
|
389
396
|
}
|
|
390
397
|
}
|
|
391
398
|
|
|
@@ -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
|
+
}
|
|
@@ -38,6 +38,7 @@ final class RecordingIndicatorController {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
func end(for command: AgentCommand) {
|
|
41
|
+
guard isRecordingCommand(command) else { return }
|
|
41
42
|
let wasRecording = isRecording
|
|
42
43
|
let activeCommandCount = max(0, activeRecordingCommands[command.identifier, default: 0] - 1)
|
|
43
44
|
if activeCommandCount > 0 {
|
|
@@ -48,7 +49,7 @@ final class RecordingIndicatorController {
|
|
|
48
49
|
recordingCommandCount = max(0, recordingCommandCount - 1)
|
|
49
50
|
if wasRecording && !isRecording {
|
|
50
51
|
play(.finishedRecording)
|
|
51
|
-
VoiceLevelOverlayController.shared.
|
|
52
|
+
VoiceLevelOverlayController.shared.endRecording()
|
|
52
53
|
}
|
|
53
54
|
if command.supportsLivePreviewOverlay {
|
|
54
55
|
LiveTranscriptionPreview.shared.stop()
|
{agent_cli-0.105.2 → agent_cli-0.107.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,69 @@ 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 == .transcribing
|
|
79
|
+
? "Transcribing \(meter.transcribingDuration)"
|
|
80
|
+
: meter.captureState.label))
|
|
81
|
+
.accessibilityValue(Text(showsPreviewSpace ? preview.text : ""))
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
private var levelMeter: some View {
|
|
79
|
-
HStack(
|
|
85
|
+
HStack(spacing: 8) {
|
|
86
|
+
if meter.captureState == .recording {
|
|
87
|
+
Text(meter.recordingDuration)
|
|
88
|
+
.font(.system(size: 12, weight: .semibold))
|
|
89
|
+
.monospacedDigit()
|
|
90
|
+
.fixedSize()
|
|
91
|
+
waveform
|
|
92
|
+
} else {
|
|
93
|
+
ProgressView()
|
|
94
|
+
.controlSize(.small)
|
|
95
|
+
Text(meter.captureState.label)
|
|
96
|
+
.font(.system(size: 12, weight: .semibold))
|
|
97
|
+
if meter.captureState == .transcribing {
|
|
98
|
+
Text(meter.transcribingDuration)
|
|
99
|
+
.font(.system(size: 12, weight: .semibold))
|
|
100
|
+
.monospacedDigit()
|
|
101
|
+
.fixedSize()
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
.foregroundStyle(statusColor)
|
|
106
|
+
.padding(.horizontal, 14)
|
|
107
|
+
.frame(width: VoiceLevelOverlayLayout.pillSize.width, height: VoiceLevelOverlayLayout.pillSize.height)
|
|
108
|
+
.background(Capsule().fill(statusColor.opacity(isLightMode ? 0.10 : 0.14)))
|
|
109
|
+
.background(Capsule().fill(backgroundColor))
|
|
110
|
+
.overlay(Capsule().stroke(statusColor.opacity(0.55), lineWidth: 1))
|
|
111
|
+
.shadow(
|
|
112
|
+
color: shadowColor,
|
|
113
|
+
radius: VoiceLevelOverlayLayout.shadowRadius,
|
|
114
|
+
y: VoiceLevelOverlayLayout.shadowYOffset
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private var waveform: some View {
|
|
119
|
+
HStack(alignment: .center, spacing: 2) {
|
|
80
120
|
ForEach(Array(meter.amplitudes.enumerated()), id: \.offset) { _, amplitude in
|
|
81
121
|
Capsule()
|
|
82
122
|
.fill(
|
|
83
123
|
LinearGradient(
|
|
84
124
|
colors: [
|
|
85
|
-
|
|
86
|
-
|
|
125
|
+
statusColor.opacity(0.65),
|
|
126
|
+
statusColor
|
|
87
127
|
],
|
|
88
128
|
startPoint: .bottom,
|
|
89
129
|
endPoint: .top
|
|
90
130
|
)
|
|
91
131
|
)
|
|
92
|
-
.frame(
|
|
132
|
+
.frame(maxWidth: .infinity)
|
|
133
|
+
.frame(height: max(6, 30 * amplitude))
|
|
93
134
|
.animation(.easeOut(duration: 0.11), value: amplitude)
|
|
94
135
|
}
|
|
95
136
|
}
|
|
96
|
-
.frame(
|
|
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
|
-
)
|
|
137
|
+
.frame(maxWidth: .infinity)
|
|
110
138
|
}
|
|
111
139
|
|
|
112
140
|
private var isLightMode: Bool {
|
|
@@ -133,12 +161,20 @@ struct VoiceLevelOverlayView: View {
|
|
|
133
161
|
Color.black.opacity(isLightMode ? 0.16 : 0.24)
|
|
134
162
|
}
|
|
135
163
|
|
|
136
|
-
private var
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
164
|
+
private var statusColor: Color {
|
|
165
|
+
if meter.captureState == .transcribing {
|
|
166
|
+
return isLightMode
|
|
167
|
+
? Color(red: 0.10, green: 0.32, blue: 0.70)
|
|
168
|
+
: Color(red: 0.45, green: 0.72, blue: 1.0)
|
|
169
|
+
}
|
|
170
|
+
if meter.captureState == .recording {
|
|
171
|
+
return isLightMode
|
|
172
|
+
? Color(red: 0.04, green: 0.40, blue: 0.18)
|
|
173
|
+
: Color(red: 0.42, green: 0.91, blue: 0.58)
|
|
174
|
+
}
|
|
175
|
+
return isLightMode
|
|
176
|
+
? Color(red: 0.62, green: 0.34, blue: 0.0)
|
|
177
|
+
: Color(red: 1.0, green: 0.74, blue: 0.25)
|
|
142
178
|
}
|
|
143
179
|
}
|
|
144
180
|
|
|
@@ -147,27 +183,63 @@ final class VoiceLevelOverlayController {
|
|
|
147
183
|
|
|
148
184
|
private var panel: NSPanel?
|
|
149
185
|
private var showsPreviewSpace = false
|
|
186
|
+
private var recordingShowsPreviewSpace = false
|
|
187
|
+
private var isRecording = false
|
|
188
|
+
private var isTranscribing = false
|
|
150
189
|
|
|
151
190
|
private init() {}
|
|
152
191
|
|
|
153
192
|
func show(showsPreviewSpace: Bool = false) {
|
|
193
|
+
isRecording = true
|
|
194
|
+
recordingShowsPreviewSpace = showsPreviewSpace
|
|
154
195
|
let panel = panel ?? makePanel()
|
|
155
196
|
self.panel = panel
|
|
156
|
-
|
|
157
|
-
self.showsPreviewSpace = showsPreviewSpace
|
|
158
|
-
updatePanelContent(panel)
|
|
159
|
-
}
|
|
160
|
-
panel.setContentSize(VoiceLevelOverlayLayout.panelSize(showsPreviewSpace: showsPreviewSpace))
|
|
161
|
-
position(panel)
|
|
197
|
+
setPreviewSpace(showsPreviewSpace, for: panel)
|
|
162
198
|
VoiceLevelMeter.shared.start()
|
|
163
199
|
panel.orderFrontRegardless()
|
|
164
200
|
}
|
|
165
201
|
|
|
166
202
|
func hide() {
|
|
203
|
+
isRecording = false
|
|
204
|
+
isTranscribing = false
|
|
167
205
|
VoiceLevelMeter.shared.stop()
|
|
168
206
|
panel?.orderOut(nil)
|
|
169
207
|
}
|
|
170
208
|
|
|
209
|
+
func showTranscribing() {
|
|
210
|
+
isTranscribing = true
|
|
211
|
+
let panel = panel ?? makePanel()
|
|
212
|
+
self.panel = panel
|
|
213
|
+
VoiceLevelMeter.shared.beginTranscribing()
|
|
214
|
+
setPreviewSpace(false, for: panel)
|
|
215
|
+
panel.orderFrontRegardless()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
func finishTranscribing() {
|
|
219
|
+
guard isTranscribing else { return }
|
|
220
|
+
isTranscribing = false
|
|
221
|
+
if isRecording {
|
|
222
|
+
if let panel {
|
|
223
|
+
setPreviewSpace(recordingShowsPreviewSpace, for: panel)
|
|
224
|
+
}
|
|
225
|
+
VoiceLevelMeter.shared.resumeRecording()
|
|
226
|
+
} else {
|
|
227
|
+
hide()
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
func endRecording() {
|
|
232
|
+
isRecording = false
|
|
233
|
+
if isTranscribing {
|
|
234
|
+
VoiceLevelMeter.shared.beginTranscribing()
|
|
235
|
+
if let panel {
|
|
236
|
+
setPreviewSpace(false, for: panel)
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
hide()
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
171
243
|
private func makePanel() -> NSPanel {
|
|
172
244
|
let panel = NSPanel(
|
|
173
245
|
contentRect: NSRect(
|
|
@@ -189,6 +261,15 @@ final class VoiceLevelOverlayController {
|
|
|
189
261
|
return panel
|
|
190
262
|
}
|
|
191
263
|
|
|
264
|
+
private func setPreviewSpace(_ showsPreviewSpace: Bool, for panel: NSPanel) {
|
|
265
|
+
if self.showsPreviewSpace != showsPreviewSpace {
|
|
266
|
+
self.showsPreviewSpace = showsPreviewSpace
|
|
267
|
+
updatePanelContent(panel)
|
|
268
|
+
}
|
|
269
|
+
panel.setContentSize(VoiceLevelOverlayLayout.panelSize(showsPreviewSpace: showsPreviewSpace))
|
|
270
|
+
position(panel)
|
|
271
|
+
}
|
|
272
|
+
|
|
192
273
|
private func updatePanelContent(_ panel: NSPanel) {
|
|
193
274
|
panel.contentView = NSHostingView(rootView: VoiceLevelOverlayView(
|
|
194
275
|
meter: VoiceLevelMeter.shared,
|
|
@@ -306,10 +387,31 @@ enum VoiceLevelLog {
|
|
|
306
387
|
}()
|
|
307
388
|
}
|
|
308
389
|
|
|
390
|
+
enum VoiceCaptureState {
|
|
391
|
+
case idle
|
|
392
|
+
case connecting
|
|
393
|
+
case recording
|
|
394
|
+
case waitingForAudio
|
|
395
|
+
case transcribing
|
|
396
|
+
|
|
397
|
+
var label: String {
|
|
398
|
+
switch self {
|
|
399
|
+
case .idle: return "Ready"
|
|
400
|
+
case .connecting: return "Connecting…"
|
|
401
|
+
case .recording: return "Recording"
|
|
402
|
+
case .waitingForAudio: return "Waiting for audio…"
|
|
403
|
+
case .transcribing: return "Transcribing…"
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
309
408
|
final class VoiceLevelMeter: ObservableObject {
|
|
310
409
|
static let shared = VoiceLevelMeter()
|
|
311
410
|
|
|
312
411
|
@Published private(set) var amplitudes = VoiceLevelMeter.idleAmplitudes
|
|
412
|
+
@Published private(set) var captureState = VoiceCaptureState.idle
|
|
413
|
+
@Published private(set) var recordingDuration = "00:00"
|
|
414
|
+
@Published private(set) var transcribingDuration = "00:00"
|
|
313
415
|
|
|
314
416
|
private static let barCount = 16
|
|
315
417
|
private static let idleAmplitudes = Array(repeating: CGFloat(0.16), count: barCount)
|
|
@@ -319,6 +421,8 @@ final class VoiceLevelMeter: ObservableObject {
|
|
|
319
421
|
private let levelLogURL: URL
|
|
320
422
|
private let now: () -> Date
|
|
321
423
|
private var timer: Timer?
|
|
424
|
+
private var recordingStartedAt: Date?
|
|
425
|
+
private var transcribingStartedAt: Date?
|
|
322
426
|
private var phase = 0.0
|
|
323
427
|
private var smoothedLevel = CGFloat(0.16)
|
|
324
428
|
|
|
@@ -328,12 +432,21 @@ final class VoiceLevelMeter: ObservableObject {
|
|
|
328
432
|
}
|
|
329
433
|
|
|
330
434
|
func start() {
|
|
331
|
-
guard timer == nil else { return }
|
|
435
|
+
guard timer == nil || captureState == .transcribing else { return }
|
|
332
436
|
VoiceLevelLog.reset(levelLogURL)
|
|
437
|
+
captureState = .connecting
|
|
438
|
+
recordingStartedAt = nil
|
|
439
|
+
recordingDuration = "00:00"
|
|
440
|
+
transcribingStartedAt = nil
|
|
441
|
+
transcribingDuration = "00:00"
|
|
333
442
|
phase = 0
|
|
334
443
|
smoothedLevel = Self.idleLevel
|
|
335
444
|
amplitudes = Self.idleAmplitudes
|
|
445
|
+
startPolling()
|
|
446
|
+
}
|
|
336
447
|
|
|
448
|
+
private func startPolling() {
|
|
449
|
+
timer?.invalidate()
|
|
337
450
|
let timer = Timer(timeInterval: Self.pollInterval, repeats: true) { [weak self] _ in
|
|
338
451
|
self?.pollLevel()
|
|
339
452
|
}
|
|
@@ -342,16 +455,55 @@ final class VoiceLevelMeter: ObservableObject {
|
|
|
342
455
|
pollLevel()
|
|
343
456
|
}
|
|
344
457
|
|
|
458
|
+
func resumeRecording() {
|
|
459
|
+
guard captureState == .transcribing else { return }
|
|
460
|
+
transcribingStartedAt = nil
|
|
461
|
+
captureState = recordingStartedAt == nil ? .connecting : .waitingForAudio
|
|
462
|
+
startPolling()
|
|
463
|
+
}
|
|
464
|
+
|
|
345
465
|
func stop() {
|
|
346
466
|
timer?.invalidate()
|
|
347
467
|
timer = nil
|
|
468
|
+
captureState = .idle
|
|
469
|
+
transcribingStartedAt = nil
|
|
470
|
+
transcribingDuration = "00:00"
|
|
471
|
+
recordingStartedAt = nil
|
|
472
|
+
recordingDuration = "00:00"
|
|
348
473
|
phase = 0
|
|
349
474
|
smoothedLevel = Self.idleLevel
|
|
350
475
|
amplitudes = Self.idleAmplitudes
|
|
351
476
|
}
|
|
352
477
|
|
|
353
|
-
|
|
354
|
-
|
|
478
|
+
func beginTranscribing() {
|
|
479
|
+
guard captureState != .transcribing else { return }
|
|
480
|
+
transcribingStartedAt = now()
|
|
481
|
+
transcribingDuration = "00:00"
|
|
482
|
+
captureState = .transcribing
|
|
483
|
+
amplitudes = Self.idleAmplitudes
|
|
484
|
+
startPolling()
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
func pollLevel() {
|
|
488
|
+
guard timer != nil else { return }
|
|
489
|
+
let now = now()
|
|
490
|
+
if captureState == .transcribing {
|
|
491
|
+
let elapsed = max(0, Int(now.timeIntervalSince(transcribingStartedAt ?? now)))
|
|
492
|
+
transcribingDuration = String(format: "%02d:%02d", elapsed / 60, elapsed % 60)
|
|
493
|
+
return
|
|
494
|
+
}
|
|
495
|
+
guard let level = VoiceLevelLog.latestLevel(from: levelLogURL, now: now) else {
|
|
496
|
+
if captureState == .recording {
|
|
497
|
+
captureState = .waitingForAudio
|
|
498
|
+
}
|
|
499
|
+
amplitudes = Self.idleAmplitudes
|
|
500
|
+
return
|
|
501
|
+
}
|
|
502
|
+
captureState = .recording
|
|
503
|
+
let startedAt = recordingStartedAt ?? now
|
|
504
|
+
recordingStartedAt = startedAt
|
|
505
|
+
let elapsedSeconds = max(0, Int(now.timeIntervalSince(startedAt)))
|
|
506
|
+
recordingDuration = String(format: "%02d:%02d", elapsedSeconds / 60, elapsedSeconds % 60)
|
|
355
507
|
updateDisplay(level: level)
|
|
356
508
|
}
|
|
357
509
|
|
|
@@ -4,6 +4,19 @@ import XCTest
|
|
|
4
4
|
@testable import AgentCLI
|
|
5
5
|
|
|
6
6
|
final class RecordingIndicatorControllerTests: XCTestCase {
|
|
7
|
+
func testRepeatedEndDoesNotStopAnotherRecording() {
|
|
8
|
+
let defaults = UserDefaults(suiteName: "AgentCLITests.recording-repeated-end")!
|
|
9
|
+
defaults.removePersistentDomain(forName: "AgentCLITests.recording-repeated-end")
|
|
10
|
+
let controller = RecordingIndicatorController(defaults: defaults, audioCuePlayer: RecordingCuePlayerSpy())
|
|
11
|
+
defer { controller.end(for: .voiceEdit) }
|
|
12
|
+
controller.begin(for: .toggleTranscription)
|
|
13
|
+
controller.begin(for: .voiceEdit)
|
|
14
|
+
controller.end(for: .toggleTranscription)
|
|
15
|
+
controller.end(for: .toggleTranscription)
|
|
16
|
+
XCTAssertTrue(controller.isRecording)
|
|
17
|
+
XCTAssertTrue(controller.isRecordingCommand(.voiceEdit))
|
|
18
|
+
}
|
|
19
|
+
|
|
7
20
|
func testRecordingSoundsAreDisabledByDefault() {
|
|
8
21
|
let defaults = UserDefaults(suiteName: "AgentCLITests.recording-sounds-default")!
|
|
9
22
|
defaults.removePersistentDomain(forName: "AgentCLITests.recording-sounds-default")
|
|
@@ -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
|