agent-cli 0.98.2__tar.gz → 0.98.4__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.98.2 → agent_cli-0.98.4}/PKG-INFO +4 -3
- {agent_cli-0.98.2 → agent_cli-0.98.4}/README.md +3 -2
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/transcribe.py +19 -3
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/voice_edit.py +9 -1
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/audio.py +75 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/opts.py +7 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/nemo.py +9 -1
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/asr.py +73 -19
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/transcribe.md +1 -1
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +9 -1
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +59 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +125 -42
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +5 -1
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +121 -109
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +4 -0
- agent_cli-0.98.4/macos/AgentCLI/Tests/AgentCLITests/ConfigurableHotkeyControllerTests.swift +36 -0
- agent_cli-0.98.4/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +86 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/appcast.xml +30 -31
- agent_cli-0.98.4/tests/core/test_audio_levels.py +45 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_asr.py +53 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_nemo_backend.py +38 -0
- agent_cli-0.98.2/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +0 -56
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/README.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/marketplace.json +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/plugin.json +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.cursorrules +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.dockerignore +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.env.example +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/logo.svg +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/release-drafter.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/renovate.json +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/check_extras_sync.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/check_plugin_skill_sync.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/normalize_appcast.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/sync_extras.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/scripts/sync_requirements.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/automerge.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/docker.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/docs.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/markdown-code-runner.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/pytest.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/release-drafter.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/release.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.github/workflows/toc.yaml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.gitignore +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.jscpd.json +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.pre-commit-config.yaml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.prompts/docs-review.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/.prompts/pr-review.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/CLAUDE.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/LICENSE +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/LLAMA_SERVER_USAGE.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/__main__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_extras.json +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_overrides/nemo-whisper.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/.gitkeep +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/audio.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/diarization.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/faster-whisper.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/kokoro.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/llm.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/memory.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/mlx-whisper.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/nemo-whisper.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/piper.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/rag.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/server.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/speed.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/vad.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/vectordb.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/whisper-transformers.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_requirements/wyoming.txt +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/_tools.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/_voice_agent_common.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/assistant.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/autocorrect.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/chat.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/diarize_live_session.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/memory/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/memory/add.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/memory/proxy.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/rag_proxy.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/speak.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/speakers.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/agents/transcribe_live.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/cli.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/config.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/config_cmd.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/constants.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/alignment.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/audio_format.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/chroma.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/deps.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/diarization.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/openai_proxy.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/process.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/reranker.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/speaker_identity.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/sse.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/transcription_logger.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/vad.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/core/watch.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/daemon/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/daemon/cli.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/_branch_name.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/_config.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/_output.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/cleanup.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/cli.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/aider.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/base.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/claude.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/codex.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/copilot.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/gemini.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/opencode.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/coding_agents/registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/base.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/cursor.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/emacs.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/jetbrains.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/nano.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/neovim.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/sublime.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/vim.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/vscode.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/editors/zed.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/hooks.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/launch.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/project.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/skill/SKILL.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/skill/examples.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/apple_terminal.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/base.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/gnome.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/iterm2.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/kitty.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/tmux.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/warp.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/terminals/zellij.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/dev/worktree.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/docs_gen.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/example-config.toml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/common.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/extras.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/hotkeys.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/launchd.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/service_config.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/services.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/install/systemd.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_files.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_filters.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_git.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_indexer.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_ingest.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_persistence.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_prompt.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_retrieval.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_store.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_streaming.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/_tasks.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/client.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/engine.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/entities.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/memory/models.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/py.typed +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_indexer.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_indexing.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_prompt.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_retriever.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_store.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/_utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/client.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/engine.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/rag/models.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/.runtime/.gitkeep +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/run-openwakeword.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-linux.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-macos.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/setup-windows.ps1 +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/scripts/start-all-services.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/cli.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/common.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/model_manager.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/model_registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/proxy/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/proxy/api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/streaming.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/base.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/kokoro.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/backends/piper.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/model_manager.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/model_registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/tts/wyoming_handler.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/base.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/mlx.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/backends/transformers.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/languages.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/model_manager.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/model_registry.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/server/whisper/wyoming_handler.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/_wyoming_utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/llm.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/tts.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/agent_cli/services/wake_word.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/docker-compose.yml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/memory-proxy.Dockerfile +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/rag-proxy.Dockerfile +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/transcribe-proxy.Dockerfile +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/tts.Dockerfile +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docker/whisper.Dockerfile +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/CNAME +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/architecture/index.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/architecture/memory.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/architecture/rag.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/assistant.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/autocorrect.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/chat.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/config.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/daemon.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/dev.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/diarize-live-session.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/index.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/install-extras.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/install-hotkeys.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/install-services.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/memory.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/rag-proxy.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/index.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/transcribe-proxy.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/tts.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/server/whisper.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/speak.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/speakers.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/start-services.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/transcribe-live.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/commands/voice-edit.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/configuration.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/getting-started.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/iOS_Shortcut_Guide.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/index.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/docker.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/index.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/linux.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/macos-app.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/macos.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/nixos.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/installation/windows.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/logo-avatar.svg +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/logo-clean.svg +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/run_markdown_code_runner.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/docs/system-integration.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/example.agent-cli-config.toml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/justfile +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Package.resolved +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Package.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/README.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Resources/Info.plist +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AppMetadata.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/AppUpdater.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatus.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatusRow.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuActivityTracker.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/SettingsWindowController.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/StatusMenuController.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/build-macos-app.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/macos/test-macos-app-e2e.sh +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/pyproject.toml +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/reddit.md +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/shell.nix +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_fix_my_text.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_interactive.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_interactive_extra.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_memory_add.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_speak.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_speak_e2e.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_speakers.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_agent.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_e2e.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_live.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_transcribe_recovery.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_tts_common.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_tts_common_extra.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_voice_agent_common.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_voice_edit.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_voice_edit_e2e.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/agents/test_wake_word_assistant.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/conftest.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_audio.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_audio_format.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_chroma.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_sse.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_vad.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/core/test_watch.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_cleanup.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_cli.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_coding_agents.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_editors.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_hooks.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_launch.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_project.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_terminals.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_verification.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/dev/test_worktree.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/install/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/install/test_extras.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/install/test_launchd.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_api_health.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_api_integration_liveish.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_client.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_engine.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_files.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_filters.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_git_integration.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_indexer.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_memory_integration.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_proxy_passthrough.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_store.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/memory/test_utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/audio.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/llm.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/mocks/wyoming.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/__init__.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_engine.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_history.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_indexer.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_indexing.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_rag_client.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_rag_integration_liveish.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_rag_proxy_passthrough.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_retriever.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_store.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/rag/test_utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_alignment.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_api.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_api_integration.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_asr_recovery.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_audio_e2e.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_cli.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_config.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_config_cmd.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_daemon.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_diarization.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_diarize_live_session.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_docs_gen.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_env_vars.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_faster_whisper_backend.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_json_output.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_llm.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_llm_gemini.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_macos_app.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_memory_tools.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_mlx_backend.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_normalize_appcast.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_process_manager.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_requires_extras.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_server_streaming.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_server_tts.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_server_whisper.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_services.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_speaker_identity.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_tools.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_transformers_backend.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_tts.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_wake_word.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/tests/test_wyoming_utils.py +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/uv.lock +0 -0
- {agent_cli-0.98.2 → agent_cli-0.98.4}/zensical.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-cli
|
|
3
|
-
Version: 0.98.
|
|
3
|
+
Version: 0.98.4
|
|
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>
|
|
@@ -899,8 +899,9 @@ the `[defaults]` section of your configuration file.
|
|
|
899
899
|
│ --help -h Show this message and exit. │
|
|
900
900
|
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
901
901
|
╭─ LLM Configuration ────────────────────────────────────────────────────────────────────╮
|
|
902
|
-
│ --extra-instructions TEXT Extra
|
|
903
|
-
│ cleanup
|
|
902
|
+
│ --extra-instructions TEXT Extra ASR context where supported, and LLM │
|
|
903
|
+
│ cleanup instructions when --llm is enabled. │
|
|
904
|
+
│ The NeMo backend ignores ASR text prompts. │
|
|
904
905
|
│ --llm --no-llm Clean up transcript with LLM: fix errors, │
|
|
905
906
|
│ add punctuation, remove filler words. Uses │
|
|
906
907
|
│ --extra-instructions if set (via CLI or │
|
|
@@ -791,8 +791,9 @@ the `[defaults]` section of your configuration file.
|
|
|
791
791
|
│ --help -h Show this message and exit. │
|
|
792
792
|
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
793
793
|
╭─ LLM Configuration ────────────────────────────────────────────────────────────────────╮
|
|
794
|
-
│ --extra-instructions TEXT Extra
|
|
795
|
-
│ cleanup
|
|
794
|
+
│ --extra-instructions TEXT Extra ASR context where supported, and LLM │
|
|
795
|
+
│ cleanup instructions when --llm is enabled. │
|
|
796
|
+
│ The NeMo backend ignores ASR text prompts. │
|
|
796
797
|
│ --llm --no-llm Clean up transcript with LLM: fix errors, │
|
|
797
798
|
│ add punctuation, remove filler words. Uses │
|
|
798
799
|
│ --extra-instructions if set (via CLI or │
|
|
@@ -10,14 +10,14 @@ import time
|
|
|
10
10
|
from contextlib import suppress
|
|
11
11
|
from datetime import UTC, datetime, timedelta
|
|
12
12
|
from pathlib import Path # noqa: TC003
|
|
13
|
-
from typing import Any, TypedDict
|
|
13
|
+
from typing import TYPE_CHECKING, Any, TypedDict
|
|
14
14
|
|
|
15
15
|
import typer
|
|
16
16
|
|
|
17
17
|
from agent_cli import config, opts
|
|
18
18
|
from agent_cli.cli import app
|
|
19
19
|
from agent_cli.core import process
|
|
20
|
-
from agent_cli.core.audio import setup_devices
|
|
20
|
+
from agent_cli.core.audio import AudioLevelLogWriter, setup_devices
|
|
21
21
|
from agent_cli.core.deps import requires_extras
|
|
22
22
|
from agent_cli.core.diarization import (
|
|
23
23
|
SpeakerDiarizer,
|
|
@@ -54,6 +54,9 @@ from agent_cli.services.llm import process_and_update_clipboard
|
|
|
54
54
|
|
|
55
55
|
LOGGER = logging.getLogger()
|
|
56
56
|
|
|
57
|
+
if TYPE_CHECKING:
|
|
58
|
+
from collections.abc import Callable
|
|
59
|
+
|
|
57
60
|
|
|
58
61
|
class TranscriptResult(TypedDict, total=False):
|
|
59
62
|
"""Result of transcription with optional LLM processing."""
|
|
@@ -361,6 +364,7 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
|
|
|
361
364
|
diarization_cfg: config.Diarization | None = None,
|
|
362
365
|
emit_output: bool = True,
|
|
363
366
|
raise_diarization_errors: bool = False,
|
|
367
|
+
audio_level_callback: Callable[[bytes], None] | None = None,
|
|
364
368
|
) -> TranscriptResult:
|
|
365
369
|
"""Unified async entry point for both live and file-based transcription."""
|
|
366
370
|
start_time = time.monotonic()
|
|
@@ -451,6 +455,7 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
|
|
|
451
455
|
save_recording=save_recording,
|
|
452
456
|
extra_instructions=extra_instructions,
|
|
453
457
|
recording_path_callback=_set_saved_recording_path,
|
|
458
|
+
audio_level_callback=audio_level_callback,
|
|
454
459
|
)
|
|
455
460
|
|
|
456
461
|
elapsed = time.monotonic() - start_time
|
|
@@ -598,7 +603,10 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
598
603
|
extra_instructions: str | None = typer.Option(
|
|
599
604
|
None,
|
|
600
605
|
"--extra-instructions",
|
|
601
|
-
help=
|
|
606
|
+
help=(
|
|
607
|
+
"Extra ASR context where supported, and LLM cleanup instructions when "
|
|
608
|
+
"`--llm` is enabled. The NeMo backend ignores ASR text prompts."
|
|
609
|
+
),
|
|
602
610
|
rich_help_panel="LLM Configuration",
|
|
603
611
|
),
|
|
604
612
|
from_file: Path | None = opts.FROM_FILE,
|
|
@@ -641,6 +649,7 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
641
649
|
config_file: str | None = opts.CONFIG_FILE,
|
|
642
650
|
print_args: bool = opts.PRINT_ARGS,
|
|
643
651
|
transcription_log: Path | None = opts.TRANSCRIPTION_LOG,
|
|
652
|
+
voice_level_log: Path | None = opts.VOICE_LEVEL_LOG,
|
|
644
653
|
# --- Diarization Options ---
|
|
645
654
|
diarize: bool = opts.DIARIZE,
|
|
646
655
|
diarize_format: opts.DiarizeFormat = opts.DIARIZE_FORMAT,
|
|
@@ -691,6 +700,9 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
691
700
|
# Expand user path for transcription log
|
|
692
701
|
if transcription_log:
|
|
693
702
|
transcription_log = transcription_log.expanduser()
|
|
703
|
+
voice_level_log = _option_default(voice_level_log)
|
|
704
|
+
if voice_level_log:
|
|
705
|
+
voice_level_log = voice_level_log.expanduser()
|
|
694
706
|
|
|
695
707
|
enroll_speakers = _option_default(enroll_speakers)
|
|
696
708
|
identify_speakers = _option_default(identify_speakers)
|
|
@@ -895,6 +907,7 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
895
907
|
# Use context manager before audio setup so --stop can target startup reliably.
|
|
896
908
|
try:
|
|
897
909
|
with process.pid_file_context(process_name), suppress(KeyboardInterrupt):
|
|
910
|
+
audio_level_writer = AudioLevelLogWriter(voice_level_log) if voice_level_log else None
|
|
898
911
|
audio_in_cfg = config.AudioInput(
|
|
899
912
|
input_device_index=input_device_index,
|
|
900
913
|
input_device_name=input_device_name,
|
|
@@ -926,6 +939,9 @@ def transcribe( # noqa: PLR0912, PLR0911, PLR0915, C901
|
|
|
926
939
|
diarization_cfg=diarization_cfg,
|
|
927
940
|
emit_output=not json_output,
|
|
928
941
|
raise_diarization_errors=diarize,
|
|
942
|
+
audio_level_callback=audio_level_writer.write_chunk
|
|
943
|
+
if audio_level_writer
|
|
944
|
+
else None,
|
|
929
945
|
),
|
|
930
946
|
)
|
|
931
947
|
except ImportError as exc:
|
|
@@ -46,7 +46,7 @@ from agent_cli.agents._voice_agent_common import (
|
|
|
46
46
|
)
|
|
47
47
|
from agent_cli.cli import app
|
|
48
48
|
from agent_cli.core import process
|
|
49
|
-
from agent_cli.core.audio import setup_devices
|
|
49
|
+
from agent_cli.core.audio import AudioLevelLogWriter, setup_devices
|
|
50
50
|
from agent_cli.core.deps import requires_extras
|
|
51
51
|
from agent_cli.core.utils import (
|
|
52
52
|
enable_json_mode,
|
|
@@ -106,6 +106,7 @@ async def _async_main(
|
|
|
106
106
|
openai_tts_cfg: config.OpenAITTS,
|
|
107
107
|
kokoro_tts_cfg: config.KokoroTTS,
|
|
108
108
|
gemini_tts_cfg: config.GeminiTTS,
|
|
109
|
+
audio_level_log: Path | None = None,
|
|
109
110
|
) -> str | None:
|
|
110
111
|
"""Core asynchronous logic for the voice assistant."""
|
|
111
112
|
device_info = setup_devices(general_cfg, audio_in_cfg, audio_out_cfg)
|
|
@@ -114,6 +115,7 @@ async def _async_main(
|
|
|
114
115
|
input_device_index, _, tts_output_device_index = device_info
|
|
115
116
|
audio_in_cfg.input_device_index = input_device_index
|
|
116
117
|
audio_out_cfg.output_device_index = tts_output_device_index
|
|
118
|
+
audio_level_writer = AudioLevelLogWriter(audio_level_log) if audio_level_log else None
|
|
117
119
|
|
|
118
120
|
original_text = get_clipboard_text()
|
|
119
121
|
if original_text is None:
|
|
@@ -132,6 +134,7 @@ async def _async_main(
|
|
|
132
134
|
LOGGER,
|
|
133
135
|
live=live,
|
|
134
136
|
quiet=general_cfg.quiet,
|
|
137
|
+
audio_level_callback=audio_level_writer.write_chunk if audio_level_writer else None,
|
|
135
138
|
)
|
|
136
139
|
|
|
137
140
|
if not audio_data:
|
|
@@ -226,6 +229,7 @@ def voice_edit(
|
|
|
226
229
|
list_devices: bool = opts.LIST_DEVICES,
|
|
227
230
|
quiet: bool = opts.QUIET,
|
|
228
231
|
json_output: bool = opts.JSON_OUTPUT,
|
|
232
|
+
voice_level_log: Path | None = opts.VOICE_LEVEL_LOG,
|
|
229
233
|
config_file: str | None = opts.CONFIG_FILE,
|
|
230
234
|
print_args: bool = opts.PRINT_ARGS,
|
|
231
235
|
) -> None:
|
|
@@ -255,6 +259,9 @@ def voice_edit(
|
|
|
255
259
|
enable_json_mode()
|
|
256
260
|
|
|
257
261
|
setup_logging(log_level, log_file, quiet=effective_quiet)
|
|
262
|
+
voice_level_log = getattr(voice_level_log, "default", voice_level_log)
|
|
263
|
+
if voice_level_log:
|
|
264
|
+
voice_level_log = voice_level_log.expanduser()
|
|
258
265
|
general_cfg = config.General(
|
|
259
266
|
log_level=log_level,
|
|
260
267
|
log_file=log_file,
|
|
@@ -293,6 +300,7 @@ def voice_edit(
|
|
|
293
300
|
openai_tts_cfg=cfgs.openai_tts,
|
|
294
301
|
kokoro_tts_cfg=cfgs.kokoro_tts,
|
|
295
302
|
gemini_tts_cfg=cfgs.gemini_tts,
|
|
303
|
+
audio_level_log=voice_level_log,
|
|
296
304
|
),
|
|
297
305
|
)
|
|
298
306
|
if json_output:
|
|
@@ -4,10 +4,15 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import functools
|
|
7
|
+
import json
|
|
7
8
|
import logging
|
|
9
|
+
import math
|
|
10
|
+
import struct
|
|
8
11
|
import threading
|
|
12
|
+
import time
|
|
9
13
|
from contextlib import asynccontextmanager, contextmanager
|
|
10
14
|
from dataclasses import dataclass
|
|
15
|
+
from datetime import UTC, datetime
|
|
11
16
|
from typing import TYPE_CHECKING, Literal
|
|
12
17
|
|
|
13
18
|
from rich.text import Text
|
|
@@ -22,6 +27,7 @@ from agent_cli.core.utils import (
|
|
|
22
27
|
|
|
23
28
|
if TYPE_CHECKING:
|
|
24
29
|
from collections.abc import AsyncGenerator, Awaitable, Callable, Generator
|
|
30
|
+
from pathlib import Path
|
|
25
31
|
|
|
26
32
|
import sounddevice as sd
|
|
27
33
|
from rich.live import Live
|
|
@@ -30,6 +36,7 @@ if TYPE_CHECKING:
|
|
|
30
36
|
|
|
31
37
|
LOGGER = logging.getLogger(__name__)
|
|
32
38
|
_AUDIO_SHUTDOWN_TIMEOUT_SECONDS = 0.5
|
|
39
|
+
_MINIMUM_INPUT_DECIBELS = -55.0
|
|
33
40
|
|
|
34
41
|
|
|
35
42
|
@dataclass
|
|
@@ -64,6 +71,74 @@ class StreamConfig:
|
|
|
64
71
|
)
|
|
65
72
|
|
|
66
73
|
|
|
74
|
+
def normalized_audio_level(chunk: bytes) -> float:
|
|
75
|
+
"""Return a 0...1 speech level from mono little-endian int16 PCM."""
|
|
76
|
+
sample_count = len(chunk) // constants.AUDIO_FORMAT_WIDTH
|
|
77
|
+
if sample_count <= 0:
|
|
78
|
+
return 0.0
|
|
79
|
+
|
|
80
|
+
pcm = chunk[: sample_count * constants.AUDIO_FORMAT_WIDTH]
|
|
81
|
+
samples = struct.unpack(f"<{sample_count}h", pcm)
|
|
82
|
+
mean_square = sum((sample / 32768.0) ** 2 for sample in samples) / sample_count
|
|
83
|
+
if mean_square <= 0:
|
|
84
|
+
return 0.0
|
|
85
|
+
|
|
86
|
+
root_mean_square = math.sqrt(mean_square)
|
|
87
|
+
decibels = 20 * math.log10(root_mean_square)
|
|
88
|
+
if decibels <= _MINIMUM_INPUT_DECIBELS:
|
|
89
|
+
return 0.0
|
|
90
|
+
|
|
91
|
+
linear_level = (decibels - _MINIMUM_INPUT_DECIBELS) / abs(_MINIMUM_INPUT_DECIBELS)
|
|
92
|
+
return min(1.0, math.sqrt(linear_level))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class AudioLevelLogWriter:
|
|
96
|
+
"""Append normalized audio levels for UI consumers."""
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
path: Path,
|
|
101
|
+
*,
|
|
102
|
+
interval_seconds: float = 0.05,
|
|
103
|
+
monotonic_clock: Callable[[], float] = time.monotonic,
|
|
104
|
+
timestamp_clock: Callable[[], datetime] = lambda: datetime.now(UTC),
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Create a writer and clear stale samples at the destination."""
|
|
107
|
+
self.path = path.expanduser()
|
|
108
|
+
self.interval_seconds = interval_seconds
|
|
109
|
+
self.monotonic_clock = monotonic_clock
|
|
110
|
+
self.timestamp_clock = timestamp_clock
|
|
111
|
+
self._last_write = -math.inf
|
|
112
|
+
self._enabled = True
|
|
113
|
+
self._lock = threading.Lock()
|
|
114
|
+
try:
|
|
115
|
+
self.path.parent.mkdir(parents=True, exist_ok=True)
|
|
116
|
+
self.path.write_text("")
|
|
117
|
+
except OSError:
|
|
118
|
+
self._enabled = False
|
|
119
|
+
|
|
120
|
+
def write_chunk(self, chunk: bytes) -> None:
|
|
121
|
+
"""Append one normalized level sample for a PCM chunk."""
|
|
122
|
+
with self._lock:
|
|
123
|
+
if not self._enabled:
|
|
124
|
+
return
|
|
125
|
+
now = self.monotonic_clock()
|
|
126
|
+
if now - self._last_write < self.interval_seconds:
|
|
127
|
+
return
|
|
128
|
+
self._last_write = now
|
|
129
|
+
|
|
130
|
+
entry = {
|
|
131
|
+
"timestamp": self.timestamp_clock().isoformat(),
|
|
132
|
+
"level": round(normalized_audio_level(chunk), 4),
|
|
133
|
+
}
|
|
134
|
+
try:
|
|
135
|
+
with self.path.open("a", encoding="utf-8") as file:
|
|
136
|
+
file.write(json.dumps(entry, separators=(",", ":")))
|
|
137
|
+
file.write("\n")
|
|
138
|
+
except OSError:
|
|
139
|
+
self._enabled = False
|
|
140
|
+
|
|
141
|
+
|
|
67
142
|
class _AudioTee:
|
|
68
143
|
"""A thread-safe class to tee a continuous audio stream into multiple asyncio queues.
|
|
69
144
|
|
|
@@ -429,6 +429,13 @@ TRANSCRIPTION_LOG: Path | None = typer.Option(
|
|
|
429
429
|
"Recent entries provide context for LLM cleanup.",
|
|
430
430
|
rich_help_panel="General Options",
|
|
431
431
|
)
|
|
432
|
+
VOICE_LEVEL_LOG: Path | None = typer.Option(
|
|
433
|
+
None,
|
|
434
|
+
"--voice-level-log",
|
|
435
|
+
help="Append normalized microphone levels to a JSONL file for UI indicators.",
|
|
436
|
+
hidden=True,
|
|
437
|
+
rich_help_panel="General Options",
|
|
438
|
+
)
|
|
432
439
|
|
|
433
440
|
# --- Server Options ---
|
|
434
441
|
SERVER_HOST: str = typer.Option(
|
|
@@ -344,6 +344,7 @@ class NemoWhisperBackend:
|
|
|
344
344
|
self._resolved_model = _resolve_model_name(config.model_name)
|
|
345
345
|
self._executor: ProcessPoolExecutor | None = None
|
|
346
346
|
self._device: str | None = None
|
|
347
|
+
self._warned_initial_prompt_ignored = False
|
|
347
348
|
|
|
348
349
|
@property
|
|
349
350
|
def is_loaded(self) -> bool:
|
|
@@ -415,7 +416,7 @@ class NemoWhisperBackend:
|
|
|
415
416
|
source_filename: str | None = None,
|
|
416
417
|
language: str | None = None,
|
|
417
418
|
task: Literal["transcribe", "translate"] = "transcribe", # noqa: ARG002
|
|
418
|
-
initial_prompt: str | None = None,
|
|
419
|
+
initial_prompt: str | None = None,
|
|
419
420
|
temperature: float = 0.0, # noqa: ARG002
|
|
420
421
|
vad_filter: bool = True, # noqa: ARG002
|
|
421
422
|
word_timestamps: bool = False,
|
|
@@ -424,6 +425,13 @@ class NemoWhisperBackend:
|
|
|
424
425
|
if self._executor is None:
|
|
425
426
|
msg = "Model not loaded. Call load() first."
|
|
426
427
|
raise RuntimeError(msg)
|
|
428
|
+
if initial_prompt and not self._warned_initial_prompt_ignored:
|
|
429
|
+
logger.warning(
|
|
430
|
+
"Whisper-style initial prompts are not supported by the agent-cli NeMo backend; "
|
|
431
|
+
"ignoring prompt for model %s",
|
|
432
|
+
self._config.model_name,
|
|
433
|
+
)
|
|
434
|
+
self._warned_initial_prompt_ignored = True
|
|
427
435
|
|
|
428
436
|
audio = await asyncio.to_thread(_prepare_audio_for_nemo, audio, source_filename)
|
|
429
437
|
|
|
@@ -210,6 +210,31 @@ def create_recorded_audio_transcriber(
|
|
|
210
210
|
raise ValueError(msg)
|
|
211
211
|
|
|
212
212
|
|
|
213
|
+
def _schedule_audio_level_callback(
|
|
214
|
+
pending_tasks: set[asyncio.Task[None]],
|
|
215
|
+
audio_level_callback: Callable[[bytes], None],
|
|
216
|
+
chunk: bytes,
|
|
217
|
+
logger: logging.Logger,
|
|
218
|
+
) -> None:
|
|
219
|
+
"""Run level callbacks off the event loop so UI metering cannot delay ASR sends."""
|
|
220
|
+
|
|
221
|
+
async def run_callback() -> None:
|
|
222
|
+
try:
|
|
223
|
+
await asyncio.to_thread(audio_level_callback, chunk)
|
|
224
|
+
except Exception:
|
|
225
|
+
logger.exception("Audio level callback failed")
|
|
226
|
+
|
|
227
|
+
task = asyncio.create_task(run_callback())
|
|
228
|
+
pending_tasks.add(task)
|
|
229
|
+
task.add_done_callback(pending_tasks.discard)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
async def _finish_audio_level_callbacks(pending_tasks: set[asyncio.Task[None]]) -> None:
|
|
233
|
+
"""Wait for scheduled level callbacks to finish before returning."""
|
|
234
|
+
if pending_tasks:
|
|
235
|
+
await asyncio.gather(*pending_tasks, return_exceptions=True)
|
|
236
|
+
|
|
237
|
+
|
|
213
238
|
async def _send_audio(
|
|
214
239
|
client: AsyncClient,
|
|
215
240
|
stream: sd.InputStream,
|
|
@@ -221,6 +246,7 @@ async def _send_audio(
|
|
|
221
246
|
save_recording: bool = True,
|
|
222
247
|
initial_prompt: str | None = None,
|
|
223
248
|
recording_path_callback: Callable[[Path], None] | None = None,
|
|
249
|
+
audio_level_callback: Callable[[bytes], None] | None = None,
|
|
224
250
|
) -> None:
|
|
225
251
|
"""Read from mic and send to Wyoming server."""
|
|
226
252
|
from wyoming.asr import Transcribe # noqa: PLC0415
|
|
@@ -233,11 +259,19 @@ async def _send_audio(
|
|
|
233
259
|
|
|
234
260
|
# Buffer to save audio if requested
|
|
235
261
|
audio_buffer = io.BytesIO() if save_recording else None
|
|
262
|
+
pending_audio_level_tasks: set[asyncio.Task[None]] = set()
|
|
236
263
|
|
|
237
264
|
async def send_chunk(chunk: bytes) -> None:
|
|
238
265
|
"""Send audio chunk to ASR server and optionally buffer it."""
|
|
239
266
|
if audio_buffer is not None:
|
|
240
267
|
audio_buffer.write(chunk)
|
|
268
|
+
if audio_level_callback:
|
|
269
|
+
_schedule_audio_level_callback(
|
|
270
|
+
pending_audio_level_tasks,
|
|
271
|
+
audio_level_callback,
|
|
272
|
+
chunk,
|
|
273
|
+
logger,
|
|
274
|
+
)
|
|
241
275
|
await client.write_event(AudioChunk(audio=chunk, **constants.WYOMING_AUDIO_CONFIG).event())
|
|
242
276
|
|
|
243
277
|
try:
|
|
@@ -252,16 +286,19 @@ async def _send_audio(
|
|
|
252
286
|
progress_style="blue",
|
|
253
287
|
)
|
|
254
288
|
finally:
|
|
255
|
-
|
|
256
|
-
|
|
289
|
+
try:
|
|
290
|
+
await client.write_event(AudioStop().event())
|
|
291
|
+
logger.debug("Sent AudioStop")
|
|
257
292
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
293
|
+
# Save the recording to disk if requested
|
|
294
|
+
if save_recording and audio_buffer:
|
|
295
|
+
audio_data = audio_buffer.getvalue()
|
|
296
|
+
if audio_data:
|
|
297
|
+
saved_path = _save_audio_to_file(audio_data, logger)
|
|
298
|
+
if saved_path and recording_path_callback:
|
|
299
|
+
recording_path_callback(saved_path)
|
|
300
|
+
finally:
|
|
301
|
+
await _finish_audio_level_callbacks(pending_audio_level_tasks)
|
|
265
302
|
|
|
266
303
|
|
|
267
304
|
async def record_audio_to_buffer(queue: asyncio.Queue, logger: logging.Logger) -> bytes:
|
|
@@ -328,6 +365,7 @@ async def record_audio_with_manual_stop(
|
|
|
328
365
|
live: Live | None = None,
|
|
329
366
|
save_recording: bool = True,
|
|
330
367
|
recording_path_callback: Callable[[Path], None] | None = None,
|
|
368
|
+
audio_level_callback: Callable[[bytes], None] | None = None,
|
|
331
369
|
) -> bytes:
|
|
332
370
|
"""Record audio to a buffer using a manual stop signal.
|
|
333
371
|
|
|
@@ -339,29 +377,41 @@ async def record_audio_with_manual_stop(
|
|
|
339
377
|
live: Rich Live display for progress
|
|
340
378
|
save_recording: If True, save the recording to disk
|
|
341
379
|
recording_path_callback: Optional callback invoked with the saved WAV path.
|
|
380
|
+
audio_level_callback: Optional callback invoked with each PCM chunk.
|
|
342
381
|
|
|
343
382
|
Returns:
|
|
344
383
|
The recorded audio data as bytes
|
|
345
384
|
|
|
346
385
|
"""
|
|
347
386
|
audio_buffer = io.BytesIO()
|
|
387
|
+
pending_audio_level_tasks: set[asyncio.Task[None]] = set()
|
|
348
388
|
|
|
349
389
|
def buffer_chunk(chunk: bytes) -> None:
|
|
350
390
|
"""Buffer audio chunk."""
|
|
351
391
|
audio_buffer.write(chunk)
|
|
392
|
+
if audio_level_callback:
|
|
393
|
+
_schedule_audio_level_callback(
|
|
394
|
+
pending_audio_level_tasks,
|
|
395
|
+
audio_level_callback,
|
|
396
|
+
chunk,
|
|
397
|
+
logger,
|
|
398
|
+
)
|
|
352
399
|
|
|
353
400
|
stream_config = setup_input_stream(input_device_index)
|
|
354
401
|
with open_audio_stream(stream_config) as stream:
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
402
|
+
try:
|
|
403
|
+
await read_audio_stream(
|
|
404
|
+
stream=stream,
|
|
405
|
+
stop_event=stop_event,
|
|
406
|
+
chunk_handler=buffer_chunk,
|
|
407
|
+
logger=logger,
|
|
408
|
+
live=live,
|
|
409
|
+
quiet=quiet,
|
|
410
|
+
progress_message="Recording",
|
|
411
|
+
progress_style="green",
|
|
412
|
+
)
|
|
413
|
+
finally:
|
|
414
|
+
await _finish_audio_level_callbacks(pending_audio_level_tasks)
|
|
365
415
|
|
|
366
416
|
audio_data = audio_buffer.getvalue()
|
|
367
417
|
|
|
@@ -431,6 +481,7 @@ async def _transcribe_live_audio_wyoming(
|
|
|
431
481
|
final_callback: Callable[[str], None] | None = None,
|
|
432
482
|
extra_instructions: str | None = None,
|
|
433
483
|
recording_path_callback: Callable[[Path], None] | None = None,
|
|
484
|
+
audio_level_callback: Callable[[bytes], None] | None = None,
|
|
434
485
|
**_kwargs: object,
|
|
435
486
|
) -> str | None:
|
|
436
487
|
"""Unified ASR transcription function."""
|
|
@@ -460,6 +511,7 @@ async def _transcribe_live_audio_wyoming(
|
|
|
460
511
|
save_recording=save_recording,
|
|
461
512
|
initial_prompt=effective_prompt,
|
|
462
513
|
recording_path_callback=recording_path_callback,
|
|
514
|
+
audio_level_callback=audio_level_callback,
|
|
463
515
|
),
|
|
464
516
|
_receive_transcript(
|
|
465
517
|
client,
|
|
@@ -488,6 +540,7 @@ async def _transcribe_live_audio_buffered(
|
|
|
488
540
|
save_recording: bool = True,
|
|
489
541
|
extra_instructions: str | None = None,
|
|
490
542
|
recording_path_callback: Callable[[Path], None] | None = None,
|
|
543
|
+
audio_level_callback: Callable[[bytes], None] | None = None,
|
|
491
544
|
**_kwargs: object,
|
|
492
545
|
) -> str | None:
|
|
493
546
|
"""Record audio to buffer, then transcribe.
|
|
@@ -502,6 +555,7 @@ async def _transcribe_live_audio_buffered(
|
|
|
502
555
|
live=live,
|
|
503
556
|
save_recording=save_recording,
|
|
504
557
|
recording_path_callback=recording_path_callback,
|
|
558
|
+
audio_level_callback=audio_level_callback,
|
|
505
559
|
)
|
|
506
560
|
if not audio_data:
|
|
507
561
|
return None
|
|
@@ -95,7 +95,7 @@ The `--from-file` option supports multiple audio formats:
|
|
|
95
95
|
|
|
96
96
|
| Option | Default | Description |
|
|
97
97
|
|--------|---------|-------------|
|
|
98
|
-
| `--extra-instructions` | - | Extra
|
|
98
|
+
| `--extra-instructions` | - | Extra ASR context where supported, and LLM cleanup instructions when `--llm` is enabled. The NeMo backend ignores ASR text prompts. |
|
|
99
99
|
| `--llm/--no-llm` | `false` | Clean up transcript with LLM: fix errors, add punctuation, remove filler words. Uses `--extra-instructions` if set (via CLI or config file). Not compatible with --diarize. |
|
|
100
100
|
|
|
101
101
|
### Audio Recovery
|
|
@@ -76,6 +76,8 @@ struct AgentCommand {
|
|
|
76
76
|
"transcribe",
|
|
77
77
|
"--toggle",
|
|
78
78
|
"--quiet",
|
|
79
|
+
"--voice-level-log",
|
|
80
|
+
VoiceLevelLog.defaultLogPath,
|
|
79
81
|
"--transcription-log",
|
|
80
82
|
RecentTranscriptionReader.defaultLogPath,
|
|
81
83
|
],
|
|
@@ -97,7 +99,13 @@ struct AgentCommand {
|
|
|
97
99
|
static let voiceEdit = AgentCommand(
|
|
98
100
|
identifier: "voice-edit",
|
|
99
101
|
title: "Voice Edit Clipboard",
|
|
100
|
-
arguments: [
|
|
102
|
+
arguments: [
|
|
103
|
+
"voice-edit",
|
|
104
|
+
"--toggle",
|
|
105
|
+
"--quiet",
|
|
106
|
+
"--voice-level-log",
|
|
107
|
+
VoiceLevelLog.defaultLogPath,
|
|
108
|
+
],
|
|
101
109
|
bootstrapRequirement: .transcription,
|
|
102
110
|
showsRecordingIndicator: true,
|
|
103
111
|
startNotificationTitle: "Voice Edit Started",
|
|
@@ -177,6 +177,17 @@ struct AgentRuntime {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
if CommandLine.arguments.contains("--agentcli-voice-level-self-test") {
|
|
181
|
+
do {
|
|
182
|
+
try Self.runVoiceLevelSelfTest()
|
|
183
|
+
print("AgentCLI voice-level self-test ok")
|
|
184
|
+
exit(0)
|
|
185
|
+
} catch {
|
|
186
|
+
print("AgentCLI voice-level self-test failed: \(error.localizedDescription)")
|
|
187
|
+
exit(1)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
180
191
|
guard CommandLine.arguments.contains("--agentcli-bootstrap-self-test") else { return }
|
|
181
192
|
|
|
182
193
|
let bootstrap = ensureReady(for: .transcription, force: true)
|
|
@@ -201,6 +212,54 @@ struct AgentRuntime {
|
|
|
201
212
|
exit(0)
|
|
202
213
|
}
|
|
203
214
|
|
|
215
|
+
private static func runVoiceLevelSelfTest() throws {
|
|
216
|
+
guard argumentValue(AgentCommand.toggleTranscription.arguments, for: "--voice-level-log") == VoiceLevelLog.defaultLogPath else {
|
|
217
|
+
throw SelfTestError("Toggle Transcription does not pass --voice-level-log")
|
|
218
|
+
}
|
|
219
|
+
guard argumentValue(AgentCommand.voiceEdit.arguments, for: "--voice-level-log") == VoiceLevelLog.defaultLogPath else {
|
|
220
|
+
throw SelfTestError("Voice Edit does not pass --voice-level-log")
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let logURL = FileManager.default.temporaryDirectory
|
|
224
|
+
.appendingPathComponent(UUID().uuidString)
|
|
225
|
+
.appendingPathExtension("jsonl")
|
|
226
|
+
defer { try? FileManager.default.removeItem(at: logURL) }
|
|
227
|
+
|
|
228
|
+
try """
|
|
229
|
+
{"timestamp":"2026-06-04T12:00:00Z","level":0.25}
|
|
230
|
+
{"timestamp":"2026-06-04T12:00:01Z","level":0.75}
|
|
231
|
+
""".write(to: logURL, atomically: true, encoding: .utf8)
|
|
232
|
+
|
|
233
|
+
let formatter = ISO8601DateFormatter()
|
|
234
|
+
formatter.formatOptions = [.withInternetDateTime]
|
|
235
|
+
guard let now = formatter.date(from: "2026-06-04T12:00:01Z") else {
|
|
236
|
+
throw SelfTestError("Could not construct voice-level test timestamp")
|
|
237
|
+
}
|
|
238
|
+
guard VoiceLevelLog.latestLevel(from: logURL, now: now) == CGFloat(0.75) else {
|
|
239
|
+
throw SelfTestError("VoiceLevelLog did not read latest fresh level")
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private static func argumentValue(_ arguments: [String], for option: String) -> String? {
|
|
244
|
+
guard let index = arguments.firstIndex(of: option),
|
|
245
|
+
arguments.indices.contains(index + 1) else {
|
|
246
|
+
return nil
|
|
247
|
+
}
|
|
248
|
+
return arguments[index + 1]
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private struct SelfTestError: LocalizedError {
|
|
252
|
+
let message: String
|
|
253
|
+
|
|
254
|
+
init(_ message: String) {
|
|
255
|
+
self.message = message
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
var errorDescription: String? {
|
|
259
|
+
message
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
204
263
|
func ensureInstalled(
|
|
205
264
|
force: Bool = false,
|
|
206
265
|
progress: AgentBootstrapProgress = { _ in }
|