agent-cli 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Bas Nijholt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-cli
3
+ Version: 0.1.0
4
+ Summary: A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance.
5
+ Author-email: Bas Nijholt <bas@nijho.lt>
6
+ Project-URL: Homepage, https://github.com/basnijholt/agent-cli
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: wyoming
11
+ Requires-Dist: pyaudio
12
+ Requires-Dist: rich
13
+ Requires-Dist: pyperclip
14
+ Requires-Dist: pydantic-ai-slim[openai]
15
+ Requires-Dist: typer
16
+ Provides-Extra: test
17
+ Requires-Dist: pytest>=7.0.0; extra == "test"
18
+ Requires-Dist: pytest-asyncio>=0.20.0; extra == "test"
19
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
20
+ Requires-Dist: requests>=2.25.1; extra == "test"
21
+ Requires-Dist: pydantic-ai-slim[openai]; extra == "test"
22
+ Requires-Dist: pyperclip; extra == "test"
23
+ Requires-Dist: ollama; extra == "test"
24
+ Provides-Extra: dev
25
+ Requires-Dist: agent-cli[test]; extra == "dev"
26
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
27
+ Requires-Dist: versioningit; extra == "dev"
28
+ Requires-Dist: markdown-code-runner; extra == "dev"
29
+ Requires-Dist: ruff; extra == "dev"
30
+ Requires-Dist: notebook; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # Agent CLI
34
+
35
+ `agent-cli` is a Python command-line tool that provides a suite of AI-powered utilities.
36
+
37
+ > [!TIP]
38
+ > If using [`uv`](https://docs.astral.sh/uv/), you can easily run the tools from this package directly. For example, to see the help message for `autocorrect`:
39
+ >
40
+ > ```bash
41
+ > uvx agent-cli autocorrect --help
42
+ > ```
43
+
44
+ <details><summary><b><u>[ToC]</u></b> 📚</summary>
45
+
46
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
47
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
48
+
49
+ - [Features](#features)
50
+ - [Prerequisites](#prerequisites)
51
+ - [Installation](#installation)
52
+ - [Usage](#usage)
53
+ - [`autocorrect`](#autocorrect)
54
+ - [`transcribe`](#transcribe)
55
+ - [`voice-assistant`](#voice-assistant)
56
+ - [Development](#development)
57
+ - [Running Tests](#running-tests)
58
+ - [Pre-commit Hooks](#pre-commit-hooks)
59
+ - [Contributing](#contributing)
60
+ - [License](#license)
61
+
62
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
63
+
64
+ </details>
65
+
66
+ ## Features
67
+
68
+ - **`autocorrect`**: Correct grammar and spelling in your text using a local LLM with Ollama.
69
+ - **`transcribe`**: Transcribe audio files to text.
70
+ - **`voice-assistant`**: A voice-powered clipboard assistant.
71
+
72
+ ## Prerequisites
73
+
74
+ - **Python**: Version 3.11 or higher.
75
+ - **Ollama**: For `autocorrect` and `voice-assistant`, you need [Ollama](https://ollama.ai/) running with a model pulled (e.g., `ollama pull devstral:24b`).
76
+
77
+ ## Installation
78
+
79
+ Install `agent-cli` using pip:
80
+
81
+ ```bash
82
+ pip install agent-cli
83
+ ```
84
+
85
+ Or for development:
86
+
87
+ 1. **Clone the repository:**
88
+
89
+ ```bash
90
+ git clone git@github.com:basnijholt/agent-cli.git
91
+ cd agent-cli
92
+ ```
93
+
94
+ 2. **Install in development mode:**
95
+
96
+ ```bash
97
+ uv sync
98
+ source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
99
+ ```
100
+
101
+ ## Usage
102
+
103
+ This package provides multiple command-line tools.
104
+
105
+ ### `autocorrect`
106
+
107
+ Corrects text from your clipboard or direct input.
108
+
109
+ <details>
110
+ <summary>See the output of <code>agent-cli autocorrect --help</code></summary>
111
+
112
+ <!-- CODE:BASH:START -->
113
+ <!-- echo '```yaml' -->
114
+ <!-- export NO_COLOR=1 -->
115
+ <!-- export TERM=dumb -->
116
+ <!-- agent-cli autocorrect --help -->
117
+ <!-- echo '```' -->
118
+ <!-- CODE:END -->
119
+
120
+ <!-- OUTPUT:START -->
121
+ <!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
122
+ ```yaml
123
+ ```
124
+
125
+ <!-- OUTPUT:END -->
126
+
127
+ </details>
128
+
129
+ ### `transcribe`
130
+
131
+ Transcribes whatever you say into text using Wyoming ASR (Automatic Speech Recognition) which uses faster-whisper.
132
+
133
+ <details>
134
+ <summary>See the output of <code>agent-cli transcribe --help</code></summary>
135
+
136
+ <!-- CODE:BASH:START -->
137
+ <!-- echo '```yaml' -->
138
+ <!-- export NO_COLOR=1 -->
139
+ <!-- export TERM=dumb -->
140
+ <!-- agent-cli transcribe --help -->
141
+ <!-- echo '```' -->
142
+ <!-- CODE:END -->
143
+
144
+ <!-- OUTPUT:START -->
145
+ <!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
146
+ ```yaml
147
+ ```
148
+
149
+ <!-- OUTPUT:END -->
150
+
151
+ </details>
152
+
153
+ ### `voice-assistant`
154
+
155
+ Starts the voice assistant. Supports daemon mode with process management.
156
+
157
+ **Basic Usage:**
158
+ ```bash
159
+ # Run in foreground
160
+ agent-cli voice-assistant --device-index 1
161
+
162
+ # Run in background
163
+ agent-cli voice-assistant --device-index 1 &
164
+
165
+ # Check status
166
+ agent-cli voice-assistant --status
167
+
168
+ # Stop background process
169
+ agent-cli voice-assistant --stop
170
+ ```
171
+
172
+ **Keyboard Maestro Integration:**
173
+ The process management features make it perfect for hotkey toggles. Use `--status` to check if running, `--stop` to stop, and `&` to start in background.
174
+
175
+ <details>
176
+ <summary>See the output of <code>agent-cli voice-assistant --help</code></summary>
177
+
178
+ <!-- CODE:BASH:START -->
179
+ <!-- echo '```yaml' -->
180
+ <!-- export NO_COLOR=1 -->
181
+ <!-- export TERM=dumb -->
182
+ <!-- agent-cli voice-assistant --help -->
183
+ <!-- echo '```' -->
184
+ <!-- CODE:END -->
185
+
186
+ <!-- OUTPUT:START -->
187
+ <!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
188
+ ```yaml
189
+ ```
190
+
191
+ <!-- OUTPUT:END -->
192
+
193
+ </details>
194
+
195
+
196
+ ## Development
197
+
198
+ ### Running Tests
199
+
200
+ The project uses `pytest` for testing. To run tests using `uv`:
201
+
202
+ ```bash
203
+ uv run pytest
204
+ ```
205
+
206
+ ### Pre-commit Hooks
207
+
208
+ This project uses pre-commit hooks (ruff for linting and formatting, mypy for type checking) to maintain code quality. To set them up:
209
+
210
+ 1. Install pre-commit:
211
+
212
+ ```bash
213
+ pip install pre-commit
214
+ ```
215
+
216
+ 2. Install the hooks:
217
+
218
+ ```bash
219
+ pre-commit install
220
+ ```
221
+
222
+ Now, the hooks will run automatically before each commit.
223
+
224
+ ## Contributing
225
+
226
+ Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you'd like to contribute code, please fork the repository and submit a pull request.
227
+
228
+ ## License
229
+
230
+ This project is licensed under the MIT License - see the `LICENSE` file for details.
@@ -0,0 +1,198 @@
1
+ # Agent CLI
2
+
3
+ `agent-cli` is a Python command-line tool that provides a suite of AI-powered utilities.
4
+
5
+ > [!TIP]
6
+ > If using [`uv`](https://docs.astral.sh/uv/), you can easily run the tools from this package directly. For example, to see the help message for `autocorrect`:
7
+ >
8
+ > ```bash
9
+ > uvx agent-cli autocorrect --help
10
+ > ```
11
+
12
+ <details><summary><b><u>[ToC]</u></b> 📚</summary>
13
+
14
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
15
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
16
+
17
+ - [Features](#features)
18
+ - [Prerequisites](#prerequisites)
19
+ - [Installation](#installation)
20
+ - [Usage](#usage)
21
+ - [`autocorrect`](#autocorrect)
22
+ - [`transcribe`](#transcribe)
23
+ - [`voice-assistant`](#voice-assistant)
24
+ - [Development](#development)
25
+ - [Running Tests](#running-tests)
26
+ - [Pre-commit Hooks](#pre-commit-hooks)
27
+ - [Contributing](#contributing)
28
+ - [License](#license)
29
+
30
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
31
+
32
+ </details>
33
+
34
+ ## Features
35
+
36
+ - **`autocorrect`**: Correct grammar and spelling in your text using a local LLM with Ollama.
37
+ - **`transcribe`**: Transcribe audio files to text.
38
+ - **`voice-assistant`**: A voice-powered clipboard assistant.
39
+
40
+ ## Prerequisites
41
+
42
+ - **Python**: Version 3.11 or higher.
43
+ - **Ollama**: For `autocorrect` and `voice-assistant`, you need [Ollama](https://ollama.ai/) running with a model pulled (e.g., `ollama pull devstral:24b`).
44
+
45
+ ## Installation
46
+
47
+ Install `agent-cli` using pip:
48
+
49
+ ```bash
50
+ pip install agent-cli
51
+ ```
52
+
53
+ Or for development:
54
+
55
+ 1. **Clone the repository:**
56
+
57
+ ```bash
58
+ git clone git@github.com:basnijholt/agent-cli.git
59
+ cd agent-cli
60
+ ```
61
+
62
+ 2. **Install in development mode:**
63
+
64
+ ```bash
65
+ uv sync
66
+ source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
67
+ ```
68
+
69
+ ## Usage
70
+
71
+ This package provides multiple command-line tools.
72
+
73
+ ### `autocorrect`
74
+
75
+ Corrects text from your clipboard or direct input.
76
+
77
+ <details>
78
+ <summary>See the output of <code>agent-cli autocorrect --help</code></summary>
79
+
80
+ <!-- CODE:BASH:START -->
81
+ <!-- echo '```yaml' -->
82
+ <!-- export NO_COLOR=1 -->
83
+ <!-- export TERM=dumb -->
84
+ <!-- agent-cli autocorrect --help -->
85
+ <!-- echo '```' -->
86
+ <!-- CODE:END -->
87
+
88
+ <!-- OUTPUT:START -->
89
+ <!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
90
+ ```yaml
91
+ ```
92
+
93
+ <!-- OUTPUT:END -->
94
+
95
+ </details>
96
+
97
+ ### `transcribe`
98
+
99
+ Transcribes whatever you say into text using Wyoming ASR (Automatic Speech Recognition) which uses faster-whisper.
100
+
101
+ <details>
102
+ <summary>See the output of <code>agent-cli transcribe --help</code></summary>
103
+
104
+ <!-- CODE:BASH:START -->
105
+ <!-- echo '```yaml' -->
106
+ <!-- export NO_COLOR=1 -->
107
+ <!-- export TERM=dumb -->
108
+ <!-- agent-cli transcribe --help -->
109
+ <!-- echo '```' -->
110
+ <!-- CODE:END -->
111
+
112
+ <!-- OUTPUT:START -->
113
+ <!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
114
+ ```yaml
115
+ ```
116
+
117
+ <!-- OUTPUT:END -->
118
+
119
+ </details>
120
+
121
+ ### `voice-assistant`
122
+
123
+ Starts the voice assistant. Supports daemon mode with process management.
124
+
125
+ **Basic Usage:**
126
+ ```bash
127
+ # Run in foreground
128
+ agent-cli voice-assistant --device-index 1
129
+
130
+ # Run in background
131
+ agent-cli voice-assistant --device-index 1 &
132
+
133
+ # Check status
134
+ agent-cli voice-assistant --status
135
+
136
+ # Stop background process
137
+ agent-cli voice-assistant --stop
138
+ ```
139
+
140
+ **Keyboard Maestro Integration:**
141
+ The process management features make it perfect for hotkey toggles. Use `--status` to check if running, `--stop` to stop, and `&` to start in background.
142
+
143
+ <details>
144
+ <summary>See the output of <code>agent-cli voice-assistant --help</code></summary>
145
+
146
+ <!-- CODE:BASH:START -->
147
+ <!-- echo '```yaml' -->
148
+ <!-- export NO_COLOR=1 -->
149
+ <!-- export TERM=dumb -->
150
+ <!-- agent-cli voice-assistant --help -->
151
+ <!-- echo '```' -->
152
+ <!-- CODE:END -->
153
+
154
+ <!-- OUTPUT:START -->
155
+ <!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
156
+ ```yaml
157
+ ```
158
+
159
+ <!-- OUTPUT:END -->
160
+
161
+ </details>
162
+
163
+
164
+ ## Development
165
+
166
+ ### Running Tests
167
+
168
+ The project uses `pytest` for testing. To run tests using `uv`:
169
+
170
+ ```bash
171
+ uv run pytest
172
+ ```
173
+
174
+ ### Pre-commit Hooks
175
+
176
+ This project uses pre-commit hooks (ruff for linting and formatting, mypy for type checking) to maintain code quality. To set them up:
177
+
178
+ 1. Install pre-commit:
179
+
180
+ ```bash
181
+ pip install pre-commit
182
+ ```
183
+
184
+ 2. Install the hooks:
185
+
186
+ ```bash
187
+ pre-commit install
188
+ ```
189
+
190
+ Now, the hooks will run automatically before each commit.
191
+
192
+ ## Contributing
193
+
194
+ Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you'd like to contribute code, please fork the repository and submit a pull request.
195
+
196
+ ## License
197
+
198
+ This project is licensed under the MIT License - see the `LICENSE` file for details.
@@ -0,0 +1 @@
1
+ """A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance."""
@@ -0,0 +1 @@
1
+ """Agent implementations for the Agent CLI."""
@@ -0,0 +1,82 @@
1
+ """Shared Typer options for the Agent CLI agents."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import typer
6
+
7
+ from agent_cli import config
8
+
9
+ # --- LLM Options ---
10
+ MODEL: str = typer.Option(
11
+ config.DEFAULT_MODEL,
12
+ "--model",
13
+ "-m",
14
+ help=f"The Ollama model to use. Default is {config.DEFAULT_MODEL}.",
15
+ )
16
+ OLLAMA_HOST: str = typer.Option(
17
+ config.OLLAMA_HOST,
18
+ "--ollama-host",
19
+ help=f"The Ollama server host. Default is {config.OLLAMA_HOST}.",
20
+ )
21
+
22
+
23
+ # --- ASR (Audio) Options ---
24
+ DEVICE_INDEX: int | None = typer.Option(
25
+ None,
26
+ "--device-index",
27
+ help="Index of the PyAudio input device to use.",
28
+ )
29
+ LIST_DEVICES: bool = typer.Option(
30
+ False, # noqa: FBT003
31
+ "--list-devices",
32
+ help="List available audio input devices and exit.",
33
+ is_eager=True,
34
+ )
35
+ ASR_SERVER_IP: str = typer.Option(
36
+ config.ASR_SERVER_IP,
37
+ "--asr-server-ip",
38
+ help="Wyoming ASR server IP address.",
39
+ )
40
+ ASR_SERVER_PORT: int = typer.Option(
41
+ config.ASR_SERVER_PORT,
42
+ "--asr-server-port",
43
+ help="Wyoming ASR server port.",
44
+ )
45
+ CLIPBOARD: bool = typer.Option(
46
+ True, # noqa: FBT003
47
+ "--clipboard/--no-clipboard",
48
+ help="Copy transcript to clipboard.",
49
+ )
50
+
51
+
52
+ # --- Process Management Options ---
53
+ STOP: bool = typer.Option(
54
+ False, # noqa: FBT003
55
+ "--stop",
56
+ help="Stop any running background process.",
57
+ )
58
+ STATUS: bool = typer.Option(
59
+ False, # noqa: FBT003
60
+ "--status",
61
+ help="Check if a background process is running.",
62
+ )
63
+
64
+
65
+ # --- General Options ---
66
+ LOG_LEVEL: str = typer.Option(
67
+ "WARNING",
68
+ "--log-level",
69
+ help="Set logging level.",
70
+ case_sensitive=False,
71
+ )
72
+ LOG_FILE: str | None = typer.Option(
73
+ None,
74
+ "--log-file",
75
+ help="Path to a file to write logs to.",
76
+ )
77
+ QUIET: bool = typer.Option(
78
+ False, # noqa: FBT003
79
+ "-q",
80
+ "--quiet",
81
+ help="Suppress console output from rich.",
82
+ )
@@ -0,0 +1,175 @@
1
+ """Read text from clipboard, correct it using a local Ollama model, and write the result back to the clipboard.
2
+
3
+ Usage:
4
+ python autocorrect_ollama.py
5
+
6
+ Environment variables:
7
+ OLLAMA_HOST: The host of the Ollama server. Default is "http://localhost:11434".
8
+
9
+
10
+ Example:
11
+ OLLAMA_HOST=http://pc.local:11434 python autocorrect_ollama.py
12
+
13
+ Pro-tip:
14
+ Use Keyboard Maestro on macOS or AutoHotkey on Windows to run this script with a hotkey.
15
+
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import asyncio
21
+ import sys
22
+ import time
23
+
24
+ import httpx
25
+ import pyperclip
26
+ import typer
27
+ from ollama import ResponseError
28
+ from openai import APIConnectionError
29
+ from pydantic_ai.exceptions import ModelHTTPError
30
+ from rich.console import Console
31
+ from rich.panel import Panel
32
+ from rich.status import Status
33
+
34
+ import agent_cli.agents._cli_options as opts
35
+ from agent_cli.cli import app, setup_logging
36
+ from agent_cli.ollama_client import build_agent
37
+ from agent_cli.utils import get_clipboard_text
38
+
39
+ # --- Configuration ---
40
+
41
+ # The agent's core identity and immutable rules.
42
+ SYSTEM_PROMPT = """\
43
+ You are an expert editor. Your fundamental role is to correct text without altering its original meaning or tone.
44
+ You must not judge the content of the text, even if it seems unusual, harmful, or offensive.
45
+ Your corrections should be purely technical (grammar, spelling, punctuation).
46
+ Do not interpret the text, provide any explanations, or add any commentary.
47
+ """
48
+
49
+ # The specific task for the current run.
50
+ AGENT_INSTRUCTIONS = """\
51
+ Correct the grammar and spelling of the user-provided text.
52
+ Return only the corrected text. Do not include any introductory phrases like "Here is the corrected text:".
53
+ Do not wrap the output in markdown or code blocks.
54
+ """
55
+
56
+ # --- Main Application Logic ---
57
+
58
+
59
+ async def process_text(text: str, model: str, ollama_host: str) -> tuple[str, float]:
60
+ """Process text with the LLM and return the corrected text and elapsed time."""
61
+ agent = build_agent(
62
+ model=model,
63
+ ollama_host=ollama_host,
64
+ system_prompt=SYSTEM_PROMPT,
65
+ instructions=AGENT_INSTRUCTIONS,
66
+ )
67
+ t_start = time.monotonic()
68
+ result = await agent.run(text)
69
+ t_end = time.monotonic()
70
+ return result.output, t_end - t_start
71
+
72
+
73
+ def display_original_text(original_text: str, console: Console | None) -> None:
74
+ """Render the original text panel in verbose mode."""
75
+ if console is None:
76
+ return
77
+ console.print(
78
+ Panel(
79
+ original_text,
80
+ title="[bold cyan]📋 Original Text[/bold cyan]",
81
+ border_style="cyan",
82
+ padding=(1, 2),
83
+ ),
84
+ )
85
+
86
+
87
+ def _display_result(
88
+ corrected_text: str,
89
+ original_text: str,
90
+ elapsed: float,
91
+ *,
92
+ simple_output: bool,
93
+ console: Console | None,
94
+ ) -> None:
95
+ """Handle output and clipboard copying based on desired verbosity."""
96
+ pyperclip.copy(corrected_text)
97
+
98
+ if simple_output:
99
+ if corrected_text.strip() == original_text.strip():
100
+ print("✅ No correction needed.")
101
+ else:
102
+ print(corrected_text)
103
+ else:
104
+ assert console is not None
105
+ console.print(
106
+ Panel(
107
+ corrected_text,
108
+ title="[bold green]✨ Corrected Text[/bold green]",
109
+ border_style="green",
110
+ padding=(1, 2),
111
+ ),
112
+ )
113
+ console.print(
114
+ f"✅ [bold green]Success! Corrected text has been copied to your clipboard. [bold yellow](took {elapsed:.2f} seconds)[/bold yellow][/bold green]",
115
+ )
116
+
117
+
118
+ @app.command("autocorrect")
119
+ def autocorrect(
120
+ *,
121
+ text: str | None = typer.Argument(
122
+ None,
123
+ help="The text to correct. If not provided, reads from clipboard.",
124
+ ),
125
+ model: str = opts.MODEL,
126
+ ollama_host: str = opts.OLLAMA_HOST,
127
+ log_level: str = opts.LOG_LEVEL,
128
+ log_file: str | None = opts.LOG_FILE,
129
+ quiet: bool = opts.QUIET,
130
+ ) -> None:
131
+ """Correct text from clipboard using a local Ollama model."""
132
+ setup_logging(log_level, log_file, quiet=quiet)
133
+ console = Console() if not quiet else None
134
+ original_text = text if text is not None else get_clipboard_text(console)
135
+
136
+ if original_text is None:
137
+ sys.exit(0)
138
+
139
+ display_original_text(original_text, console)
140
+
141
+ try:
142
+ if quiet:
143
+ corrected_text, elapsed = asyncio.run(
144
+ process_text(original_text, model, ollama_host),
145
+ )
146
+ else:
147
+ with Status(
148
+ f"[bold yellow]🤖 Correcting with {model}...[/bold yellow]",
149
+ console=console,
150
+ ) as status:
151
+ maybe_log = f" (see [dim]log at {log_file}[/dim])" if log_file else ""
152
+ status.update(
153
+ f"[bold yellow]🤖 Correcting with {model}...{maybe_log}[/bold yellow]",
154
+ )
155
+ corrected_text, elapsed = asyncio.run(
156
+ process_text(original_text, model, ollama_host),
157
+ )
158
+
159
+ _display_result(
160
+ corrected_text,
161
+ original_text,
162
+ elapsed,
163
+ simple_output=quiet,
164
+ console=console,
165
+ )
166
+
167
+ except (ResponseError, httpx.ConnectError, ModelHTTPError, APIConnectionError) as e:
168
+ if quiet:
169
+ print(f"❌ {e}")
170
+ elif console:
171
+ console.print(f"❌ {e}", style="bold red")
172
+ console.print(
173
+ f" Please check that your Ollama server is running at [bold cyan]{ollama_host}[/bold cyan]",
174
+ )
175
+ sys.exit(1)