agent-cli 0.68.4__py3-none-any.whl → 0.69.0__py3-none-any.whl

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.
Files changed (46) hide show
  1. agent_cli/_requirements/audio.txt +10 -2
  2. agent_cli/_requirements/faster-whisper.txt +1 -0
  3. agent_cli/_requirements/kokoro.txt +1 -0
  4. agent_cli/_requirements/llm.txt +8 -1
  5. agent_cli/_requirements/memory.txt +1 -0
  6. agent_cli/_requirements/mlx-whisper.txt +2 -1
  7. agent_cli/_requirements/piper.txt +1 -0
  8. agent_cli/_requirements/rag.txt +1 -0
  9. agent_cli/_requirements/server.txt +1 -0
  10. agent_cli/_requirements/speed.txt +10 -2
  11. agent_cli/_requirements/vad.txt +10 -2
  12. agent_cli/agents/autocorrect.py +2 -1
  13. agent_cli/agents/memory/__init__.py +1 -0
  14. agent_cli/agents/memory/proxy.py +5 -12
  15. agent_cli/agents/rag_proxy.py +2 -9
  16. agent_cli/agents/transcribe.py +4 -1
  17. agent_cli/cli.py +18 -2
  18. agent_cli/config_cmd.py +1 -0
  19. agent_cli/core/chroma.py +4 -4
  20. agent_cli/core/deps.py +1 -1
  21. agent_cli/core/openai_proxy.py +9 -4
  22. agent_cli/core/process.py +2 -2
  23. agent_cli/core/reranker.py +5 -4
  24. agent_cli/core/utils.py +3 -1
  25. agent_cli/core/vad.py +2 -1
  26. agent_cli/core/watch.py +8 -6
  27. agent_cli/dev/cli.py +6 -5
  28. agent_cli/dev/coding_agents/base.py +1 -2
  29. agent_cli/dev/skill/SKILL.md +9 -4
  30. agent_cli/dev/skill/examples.md +65 -4
  31. agent_cli/install/extras.py +9 -7
  32. agent_cli/memory/_files.py +4 -1
  33. agent_cli/memory/_indexer.py +3 -2
  34. agent_cli/memory/_ingest.py +6 -5
  35. agent_cli/memory/_streaming.py +2 -2
  36. agent_cli/rag/_indexer.py +3 -2
  37. agent_cli/rag/api.py +1 -0
  38. agent_cli/server/cli.py +3 -5
  39. agent_cli/server/common.py +3 -4
  40. agent_cli/server/whisper/backends/faster_whisper.py +30 -23
  41. agent_cli/services/llm.py +2 -1
  42. {agent_cli-0.68.4.dist-info → agent_cli-0.69.0.dist-info}/METADATA +11 -6
  43. {agent_cli-0.68.4.dist-info → agent_cli-0.69.0.dist-info}/RECORD +46 -46
  44. {agent_cli-0.68.4.dist-info → agent_cli-0.69.0.dist-info}/WHEEL +0 -0
  45. {agent_cli-0.68.4.dist-info → agent_cli-0.69.0.dist-info}/entry_points.txt +0 -0
  46. {agent_cli-0.68.4.dist-info → agent_cli-0.69.0.dist-info}/licenses/LICENSE +0 -0
@@ -11,7 +11,9 @@ certifi==2026.1.4
11
11
  cffi==2.0.0
12
12
  # via sounddevice
13
13
  click==8.3.1
14
- # via typer-slim
14
+ # via
15
+ # typer
16
+ # typer-slim
15
17
  colorama==0.4.6 ; sys_platform == 'win32'
16
18
  # via click
17
19
  dotenv==0.9.9
@@ -49,13 +51,18 @@ python-dotenv==1.2.1
49
51
  rich==14.2.0
50
52
  # via
51
53
  # agent-cli
54
+ # typer
52
55
  # typer-slim
53
56
  setproctitle==1.3.7
54
57
  # via agent-cli
55
58
  shellingham==1.5.4
56
- # via typer-slim
59
+ # via
60
+ # typer
61
+ # typer-slim
57
62
  sounddevice==0.5.3
58
63
  # via agent-cli
64
+ typer==0.21.1
65
+ # via agent-cli
59
66
  typer-slim==0.21.1
60
67
  # via agent-cli
61
68
  typing-extensions==4.15.0
@@ -63,6 +70,7 @@ typing-extensions==4.15.0
63
70
  # anyio
64
71
  # pydantic
65
72
  # pydantic-core
73
+ # typer
66
74
  # typer-slim
67
75
  # typing-inspection
68
76
  typing-inspection==0.4.2
@@ -176,6 +176,7 @@ tqdm==4.67.1
176
176
  # huggingface-hub
177
177
  typer==0.21.1
178
178
  # via
179
+ # agent-cli
179
180
  # fastapi-cli
180
181
  # fastapi-cloud-cli
181
182
  typer-slim==0.21.1
@@ -367,6 +367,7 @@ triton==3.5.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
367
367
  # via torch
368
368
  typer==0.21.1
369
369
  # via
370
+ # agent-cli
370
371
  # fastapi-cli
371
372
  # fastapi-cloud-cli
372
373
  typer-slim==0.21.1
@@ -23,6 +23,7 @@ charset-normalizer==3.4.4
23
23
  click==8.3.1
24
24
  # via
25
25
  # ddgs
26
+ # typer
26
27
  # typer-slim
27
28
  colorama==0.4.6
28
29
  # via
@@ -132,13 +133,16 @@ requests==2.32.5
132
133
  rich==14.2.0
133
134
  # via
134
135
  # agent-cli
136
+ # typer
135
137
  # typer-slim
136
138
  rsa==4.9.1
137
139
  # via google-auth
138
140
  setproctitle==1.3.7
139
141
  # via agent-cli
140
142
  shellingham==1.5.4
141
- # via typer-slim
143
+ # via
144
+ # typer
145
+ # typer-slim
142
146
  sniffio==1.3.1
143
147
  # via
144
148
  # google-genai
@@ -151,6 +155,8 @@ tiktoken==0.12.0
151
155
  # via pydantic-ai-slim
152
156
  tqdm==4.67.1
153
157
  # via openai
158
+ typer==0.21.1
159
+ # via agent-cli
154
160
  typer-slim==0.21.1
155
161
  # via agent-cli
156
162
  typing-extensions==4.15.0
@@ -161,6 +167,7 @@ typing-extensions==4.15.0
161
167
  # opentelemetry-api
162
168
  # pydantic
163
169
  # pydantic-core
170
+ # typer
164
171
  # typer-slim
165
172
  # typing-inspection
166
173
  typing-inspection==0.4.2
@@ -300,6 +300,7 @@ transformers==4.57.5
300
300
  # via agent-cli
301
301
  typer==0.21.1
302
302
  # via
303
+ # agent-cli
303
304
  # chromadb
304
305
  # fastapi-cli
305
306
  # fastapi-cloud-cli
@@ -180,8 +180,9 @@ tqdm==4.67.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
180
180
  # via
181
181
  # huggingface-hub
182
182
  # mlx-whisper
183
- typer==0.21.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
183
+ typer==0.21.1
184
184
  # via
185
+ # agent-cli
185
186
  # fastapi-cli
186
187
  # fastapi-cloud-cli
187
188
  typer-slim==0.21.1
@@ -140,6 +140,7 @@ sympy==1.14.0
140
140
  # via onnxruntime
141
141
  typer==0.21.1
142
142
  # via
143
+ # agent-cli
143
144
  # fastapi-cli
144
145
  # fastapi-cloud-cli
145
146
  typer-slim==0.21.1
@@ -343,6 +343,7 @@ transformers==4.57.5
343
343
  # via agent-cli
344
344
  typer==0.21.1
345
345
  # via
346
+ # agent-cli
346
347
  # chromadb
347
348
  # fastapi-cli
348
349
  # fastapi-cloud-cli
@@ -118,6 +118,7 @@ starlette==0.50.0
118
118
  # via fastapi
119
119
  typer==0.21.1
120
120
  # via
121
+ # agent-cli
121
122
  # fastapi-cli
122
123
  # fastapi-cloud-cli
123
124
  typer-slim==0.21.1
@@ -11,7 +11,9 @@ certifi==2026.1.4
11
11
  # httpcore
12
12
  # httpx
13
13
  click==8.3.1
14
- # via typer-slim
14
+ # via
15
+ # typer
16
+ # typer-slim
15
17
  colorama==0.4.6 ; sys_platform == 'win32'
16
18
  # via click
17
19
  dotenv==0.9.9
@@ -49,13 +51,18 @@ python-dotenv==1.2.1
49
51
  rich==14.2.0
50
52
  # via
51
53
  # agent-cli
54
+ # typer
52
55
  # typer-slim
53
56
  setproctitle==1.3.7
54
57
  # via agent-cli
55
58
  shellingham==1.5.4
56
- # via typer-slim
59
+ # via
60
+ # typer
61
+ # typer-slim
57
62
  termcolor==3.3.0
58
63
  # via fire
64
+ typer==0.21.1
65
+ # via agent-cli
59
66
  typer-slim==0.21.1
60
67
  # via agent-cli
61
68
  typing-extensions==4.15.0
@@ -63,6 +70,7 @@ typing-extensions==4.15.0
63
70
  # anyio
64
71
  # pydantic
65
72
  # pydantic-core
73
+ # typer
66
74
  # typer-slim
67
75
  # typing-inspection
68
76
  typing-inspection==0.4.2
@@ -9,7 +9,9 @@ certifi==2026.1.4
9
9
  # httpcore
10
10
  # httpx
11
11
  click==8.3.1
12
- # via typer-slim
12
+ # via
13
+ # typer
14
+ # typer-slim
13
15
  colorama==0.4.6 ; sys_platform == 'win32'
14
16
  # via click
15
17
  coloredlogs==15.0.1
@@ -112,13 +114,16 @@ python-dotenv==1.2.1
112
114
  rich==14.2.0
113
115
  # via
114
116
  # agent-cli
117
+ # typer
115
118
  # typer-slim
116
119
  setproctitle==1.3.7
117
120
  # via agent-cli
118
121
  setuptools==80.9.0 ; python_full_version >= '3.12'
119
122
  # via torch
120
123
  shellingham==1.5.4
121
- # via typer-slim
124
+ # via
125
+ # typer
126
+ # typer-slim
122
127
  silero-vad==6.2.0
123
128
  # via agent-cli
124
129
  sympy==1.14.0
@@ -133,6 +138,8 @@ torchaudio==2.9.1
133
138
  # via silero-vad
134
139
  triton==3.5.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
135
140
  # via torch
141
+ typer==0.21.1
142
+ # via agent-cli
136
143
  typer-slim==0.21.1
137
144
  # via agent-cli
138
145
  typing-extensions==4.15.0
@@ -141,6 +148,7 @@ typing-extensions==4.15.0
141
148
  # pydantic
142
149
  # pydantic-core
143
150
  # torch
151
+ # typer
144
152
  # typer-slim
145
153
  # typing-inspection
146
154
  typing-inspection==0.4.2
@@ -9,7 +9,6 @@ import sys
9
9
  import time
10
10
  from typing import TYPE_CHECKING
11
11
 
12
- import pyperclip
13
12
  import typer
14
13
 
15
14
  from agent_cli import config, opts
@@ -118,6 +117,8 @@ def _display_result(
118
117
  ) -> None:
119
118
  """Handle output and clipboard copying based on desired verbosity."""
120
119
  if clipboard:
120
+ import pyperclip # noqa: PLC0415
121
+
121
122
  pyperclip.copy(corrected_text)
122
123
 
123
124
  if simple_output:
@@ -10,6 +10,7 @@ from agent_cli.core.process import set_process_title
10
10
  memory_app = typer.Typer(
11
11
  name="memory",
12
12
  help="Memory system operations (add, proxy, etc.).",
13
+ add_completion=True,
13
14
  rich_markup_mode="markdown",
14
15
  no_args_is_help=True,
15
16
  )
@@ -11,7 +11,7 @@ from rich.logging import RichHandler
11
11
  from agent_cli import constants, opts
12
12
  from agent_cli.agents.memory import memory_app
13
13
  from agent_cli.core.deps import requires_extras
14
- from agent_cli.core.utils import console, print_command_line_args, print_error_message
14
+ from agent_cli.core.utils import console, print_command_line_args
15
15
 
16
16
 
17
17
  @memory_app.command("proxy")
@@ -105,17 +105,10 @@ def proxy(
105
105
  if print_args:
106
106
  print_command_line_args(locals())
107
107
 
108
- try:
109
- import uvicorn # noqa: PLC0415
110
-
111
- from agent_cli.memory._files import ensure_store_dirs # noqa: PLC0415
112
- from agent_cli.memory.api import create_app # noqa: PLC0415
113
- except ImportError as exc:
114
- print_error_message(
115
- "Memory dependencies are not installed. Please install with "
116
- "`pip install agent-cli[memory]` or `uv sync --extra memory`.",
117
- )
118
- raise typer.Exit(1) from exc
108
+ import uvicorn # noqa: PLC0415
109
+
110
+ from agent_cli.memory._files import ensure_store_dirs # noqa: PLC0415
111
+ from agent_cli.memory.api import create_app # noqa: PLC0415
119
112
 
120
113
  logging.basicConfig(
121
114
  level=log_level.upper(),
@@ -77,16 +77,9 @@ def rag_proxy(
77
77
  logging.getLogger("chromadb").setLevel(logging.WARNING)
78
78
  logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
79
79
 
80
- try:
81
- import uvicorn # noqa: PLC0415
80
+ import uvicorn # noqa: PLC0415
82
81
 
83
- from agent_cli.rag.api import create_app # noqa: PLC0415
84
- except ImportError as exc:
85
- print_error_message(
86
- "RAG dependencies are not installed. Please install with "
87
- "`pip install agent-cli[rag]` or `uv sync --extra rag`.",
88
- )
89
- raise typer.Exit(1) from exc
82
+ from agent_cli.rag.api import create_app # noqa: PLC0415
90
83
 
91
84
  docs_folder = docs_folder.resolve()
92
85
  chroma_path = chroma_path.resolve()
@@ -12,7 +12,6 @@ from datetime import UTC, datetime, timedelta
12
12
  from pathlib import Path # noqa: TC003
13
13
  from typing import Any, TypedDict
14
14
 
15
- import pyperclip
16
15
  import typer
17
16
 
18
17
  from agent_cli import config, opts
@@ -364,6 +363,8 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
364
363
  )
365
364
  clipboard_snapshot: str | None = None
366
365
  if general_cfg.clipboard:
366
+ import pyperclip # noqa: PLC0415
367
+
367
368
  clipboard_snapshot = pyperclip.paste()
368
369
  pyperclip.copy(transcript)
369
370
  LOGGER.info("Copied raw transcript to clipboard before LLM processing.")
@@ -445,6 +446,8 @@ async def _async_main( # noqa: PLR0912, PLR0915, C901
445
446
  )
446
447
 
447
448
  if general_cfg.clipboard:
449
+ import pyperclip # noqa: PLC0415
450
+
448
451
  pyperclip.copy(transcript)
449
452
  LOGGER.info("Copied transcript to clipboard.")
450
453
  else:
agent_cli/cli.py CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import sys
6
+ from pathlib import Path
5
7
  from typing import Annotated
6
8
 
7
9
  import typer
10
+ from rich.table import Table
8
11
 
9
12
  from . import __version__
10
13
  from .config import load_config, normalize_provider_defaults
@@ -14,15 +17,28 @@ from .core.utils import console
14
17
  app = typer.Typer(
15
18
  name="agent-cli",
16
19
  help="A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance.",
17
- add_completion=True,
18
20
  context_settings={"help_option_names": ["-h", "--help"]},
21
+ add_completion=True,
19
22
  rich_markup_mode="markdown",
23
+ no_args_is_help=True,
20
24
  )
21
25
 
22
26
 
23
27
  def _version_callback(value: bool) -> None:
24
28
  if value:
25
- console.print(f"agent-cli {__version__}")
29
+ path = Path(__file__).parent
30
+ data = [
31
+ ("agent-cli version", __version__),
32
+ ("agent-cli location", str(path)),
33
+ ("Python version", sys.version),
34
+ ("Python executable", sys.executable),
35
+ ]
36
+ table = Table(show_header=False)
37
+ table.add_column("Property", style="cyan")
38
+ table.add_column("Value", style="magenta")
39
+ for prop, val in data:
40
+ table.add_row(prop, val)
41
+ console.print(table)
26
42
  raise typer.Exit
27
43
 
28
44
 
agent_cli/config_cmd.py CHANGED
@@ -21,6 +21,7 @@ from agent_cli.core.utils import console
21
21
  config_app = typer.Typer(
22
22
  name="config",
23
23
  help="Manage agent-cli configuration files.",
24
+ add_completion=True,
24
25
  rich_markup_mode="markdown",
25
26
  no_args_is_help=True,
26
27
  )
agent_cli/core/chroma.py CHANGED
@@ -4,10 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING, Any
6
6
 
7
- import chromadb
8
- from chromadb.config import Settings
9
- from chromadb.utils import embedding_functions
10
-
11
7
  from agent_cli.constants import DEFAULT_OPENAI_EMBEDDING_MODEL
12
8
 
13
9
  if TYPE_CHECKING:
@@ -28,6 +24,10 @@ def init_collection(
28
24
  subdir: str | None = None,
29
25
  ) -> Collection:
30
26
  """Initialize a Chroma collection with OpenAI-compatible embeddings."""
27
+ import chromadb # noqa: PLC0415
28
+ from chromadb.config import Settings # noqa: PLC0415
29
+ from chromadb.utils import embedding_functions # noqa: PLC0415
30
+
31
31
  target_path = persistence_path / subdir if subdir else persistence_path
32
32
  target_path.mkdir(parents=True, exist_ok=True)
33
33
  client = chromadb.PersistentClient(
agent_cli/core/deps.py CHANGED
@@ -142,7 +142,7 @@ def _try_auto_install(missing: list[str]) -> bool:
142
142
  console.print(
143
143
  f"[yellow]Auto-installing missing extras: {', '.join(extras_to_install)}[/]",
144
144
  )
145
- return install_extras_programmatic(extras_to_install)
145
+ return install_extras_programmatic(extras_to_install, quiet=True)
146
146
 
147
147
 
148
148
  def _check_and_install_extras(extras: tuple[str, ...]) -> list[str]:
@@ -6,13 +6,11 @@ import json
6
6
  import logging
7
7
  from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
8
8
 
9
- import httpx
10
- from fastapi import HTTPException, Request, Response
11
- from fastapi.responses import StreamingResponse
12
-
13
9
  if TYPE_CHECKING:
14
10
  from collections.abc import AsyncGenerator, Iterable
15
11
 
12
+ from fastapi import Request, Response
13
+
16
14
  LOGGER = logging.getLogger(__name__)
17
15
 
18
16
 
@@ -33,6 +31,9 @@ async def proxy_request_to_upstream(
33
31
  api_key: str | None = None,
34
32
  ) -> Response:
35
33
  """Forward a raw HTTP request to an upstream OpenAI-compatible provider."""
34
+ import httpx # noqa: PLC0415
35
+ from fastapi import Response # noqa: PLC0415
36
+
36
37
  auth_header = request.headers.get("Authorization")
37
38
  headers = {}
38
39
  if auth_header:
@@ -82,6 +83,10 @@ async def forward_chat_request(
82
83
  exclude_fields: Iterable[str] = (),
83
84
  ) -> Any:
84
85
  """Forward a chat request to a backend LLM."""
86
+ import httpx # noqa: PLC0415
87
+ from fastapi import HTTPException # noqa: PLC0415
88
+ from fastapi.responses import StreamingResponse # noqa: PLC0415
89
+
85
90
  forward_payload = request.model_dump(exclude=set(exclude_fields))
86
91
  headers = {"Authorization": f"Bearer {api_key}"} if api_key else None
87
92
 
agent_cli/core/process.py CHANGED
@@ -10,8 +10,6 @@ from contextlib import contextmanager
10
10
  from pathlib import Path
11
11
  from typing import TYPE_CHECKING
12
12
 
13
- import setproctitle
14
-
15
13
  if TYPE_CHECKING:
16
14
  from collections.abc import Generator
17
15
 
@@ -36,6 +34,8 @@ def set_process_title(process_name: str) -> None:
36
34
  process_name: The name of the process (e.g., 'transcribe', 'chat').
37
35
 
38
36
  """
37
+ import setproctitle # noqa: PLC0415
38
+
39
39
  global _original_proctitle
40
40
 
41
41
  # Capture the original command line only once, before any modification
@@ -4,15 +4,13 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
 
7
- from huggingface_hub import hf_hub_download
8
- from onnxruntime import InferenceSession
9
- from transformers import AutoTokenizer
10
-
11
7
  LOGGER = logging.getLogger(__name__)
12
8
 
13
9
 
14
10
  def _download_onnx_model(model_name: str, onnx_filename: str) -> str:
15
11
  """Download the ONNX model, favoring the common `onnx/` folder layout."""
12
+ from huggingface_hub import hf_hub_download # noqa: PLC0415
13
+
16
14
  if "/" in onnx_filename:
17
15
  return hf_hub_download(repo_id=model_name, filename=onnx_filename)
18
16
 
@@ -45,6 +43,9 @@ class OnnxCrossEncoder:
45
43
  onnx_filename: str = "model.onnx",
46
44
  ) -> None:
47
45
  """Initialize the ONNX CrossEncoder."""
46
+ from onnxruntime import InferenceSession # noqa: PLC0415
47
+ from transformers import AutoTokenizer # noqa: PLC0415
48
+
48
49
  self.model_name = model_name
49
50
 
50
51
  # Download model if needed
agent_cli/core/utils.py CHANGED
@@ -18,7 +18,6 @@ from contextlib import (
18
18
  )
19
19
  from typing import TYPE_CHECKING, Any
20
20
 
21
- import pyperclip
22
21
  from rich.console import Console
23
22
  from rich.live import Live
24
23
  from rich.panel import Panel
@@ -40,6 +39,7 @@ if TYPE_CHECKING:
40
39
  from pathlib import Path
41
40
 
42
41
  console = Console()
42
+ err_console = Console(stderr=True)
43
43
 
44
44
 
45
45
  def enable_json_mode() -> None:
@@ -233,6 +233,8 @@ def print_device_index(input_device_index: int | None, input_device_name: str |
233
233
 
234
234
  def get_clipboard_text(*, quiet: bool = False) -> str | None:
235
235
  """Get text from clipboard, with an optional status message."""
236
+ import pyperclip # noqa: PLC0415
237
+
236
238
  text = pyperclip.paste()
237
239
  if not text:
238
240
  if not quiet:
agent_cli/core/vad.py CHANGED
@@ -12,7 +12,6 @@ from agent_cli import constants
12
12
  try:
13
13
  import numpy as np
14
14
  import torch
15
- from silero_vad.utils_vad import OnnxWrapper
16
15
  except ImportError as e:
17
16
  msg = (
18
17
  "silero-vad is required for the transcribe-daemon command. "
@@ -57,6 +56,8 @@ class VoiceActivityDetector:
57
56
  msg = f"Sample rate must be 8000 or 16000, got {sample_rate}"
58
57
  raise ValueError(msg)
59
58
 
59
+ from silero_vad.utils_vad import OnnxWrapper # noqa: PLC0415
60
+
60
61
  self.sample_rate = sample_rate
61
62
  self.threshold = threshold
62
63
  self.silence_threshold_ms = silence_threshold_ms
agent_cli/core/watch.py CHANGED
@@ -3,13 +3,13 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
- from collections.abc import Callable
7
6
  from pathlib import Path
7
+ from typing import TYPE_CHECKING
8
8
 
9
- from watchfiles import Change, awatch
9
+ if TYPE_CHECKING:
10
+ from collections.abc import Callable
10
11
 
11
- ChangeHandler = Callable[[Change, Path], None]
12
- PathFilter = Callable[[Path, Path], bool]
12
+ from watchfiles import Change
13
13
 
14
14
 
15
15
  def _default_skip_hidden(path: Path, root: Path) -> bool:
@@ -20,10 +20,10 @@ def _default_skip_hidden(path: Path, root: Path) -> bool:
20
20
 
21
21
  async def watch_directory(
22
22
  root: Path,
23
- handler: ChangeHandler,
23
+ handler: Callable[[Change, Path], None],
24
24
  *,
25
25
  skip_hidden: bool = True,
26
- ignore_filter: PathFilter | None = None,
26
+ ignore_filter: Callable[[Path, Path], bool] | None = None,
27
27
  use_executor: bool = True,
28
28
  ) -> None:
29
29
  """Watch a directory for file changes and invoke handler(change, path).
@@ -38,6 +38,8 @@ async def watch_directory(
38
38
  use_executor: If True, run handler in a thread pool executor.
39
39
 
40
40
  """
41
+ from watchfiles import awatch # noqa: PLC0415
42
+
41
43
  loop = asyncio.get_running_loop()
42
44
 
43
45
  # Determine which filter to use
agent_cli/dev/cli.py CHANGED
@@ -13,7 +13,6 @@ from pathlib import Path
13
13
  from typing import TYPE_CHECKING, Annotated, NoReturn
14
14
 
15
15
  import typer
16
- from rich.console import Console
17
16
  from rich.panel import Panel
18
17
  from rich.table import Table
19
18
 
@@ -21,6 +20,7 @@ from agent_cli.cli import app as main_app
21
20
  from agent_cli.cli import set_config_defaults
22
21
  from agent_cli.config import load_config
23
22
  from agent_cli.core.process import set_process_title
23
+ from agent_cli.core.utils import console, err_console
24
24
 
25
25
  # Word lists for generating random branch names (like Docker container names)
26
26
  _ADJECTIVES = [
@@ -112,9 +112,6 @@ if TYPE_CHECKING:
112
112
  from .coding_agents.base import CodingAgent
113
113
  from .editors.base import Editor
114
114
 
115
- console = Console()
116
- err_console = Console(stderr=True)
117
-
118
115
  app = typer.Typer(
119
116
  name="dev",
120
117
  help="Parallel development environment manager using git worktrees.",
@@ -478,7 +475,7 @@ def _launch_agent(
478
475
 
479
476
 
480
477
  @app.command("new")
481
- def new( # noqa: PLR0912, PLR0915
478
+ def new( # noqa: C901, PLR0912, PLR0915
482
479
  branch: Annotated[
483
480
  str | None,
484
481
  typer.Argument(help="Branch name (auto-generated if not provided)"),
@@ -565,6 +562,10 @@ def new( # noqa: PLR0912, PLR0915
565
562
  if prompt_file is not None:
566
563
  prompt = prompt_file.read_text().strip()
567
564
 
565
+ # If a prompt is provided, automatically enable agent mode
566
+ if prompt:
567
+ agent = True
568
+
568
569
  repo_root = _ensure_git_repo()
569
570
 
570
571
  # Generate branch name if not provided
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import os
6
6
  import shutil
7
7
  from abc import ABC
8
+ from pathlib import PurePath
8
9
  from typing import TYPE_CHECKING
9
10
 
10
11
  if TYPE_CHECKING:
@@ -131,8 +132,6 @@ def _get_parent_process_names() -> list[str]:
131
132
  - CLI tools that set process.title (like Claude) show their name directly
132
133
  """
133
134
  try:
134
- from pathlib import PurePath # noqa: PLC0415
135
-
136
135
  import psutil # noqa: PLC0415
137
136
 
138
137
  process = psutil.Process(os.getpid())