agent-cli 0.70.5__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.
- agent_cli/__init__.py +5 -0
- agent_cli/__main__.py +6 -0
- agent_cli/_extras.json +14 -0
- agent_cli/_requirements/.gitkeep +0 -0
- agent_cli/_requirements/audio.txt +79 -0
- agent_cli/_requirements/faster-whisper.txt +215 -0
- agent_cli/_requirements/kokoro.txt +425 -0
- agent_cli/_requirements/llm.txt +183 -0
- agent_cli/_requirements/memory.txt +355 -0
- agent_cli/_requirements/mlx-whisper.txt +222 -0
- agent_cli/_requirements/piper.txt +176 -0
- agent_cli/_requirements/rag.txt +402 -0
- agent_cli/_requirements/server.txt +154 -0
- agent_cli/_requirements/speed.txt +77 -0
- agent_cli/_requirements/vad.txt +155 -0
- agent_cli/_requirements/wyoming.txt +71 -0
- agent_cli/_tools.py +368 -0
- agent_cli/agents/__init__.py +23 -0
- agent_cli/agents/_voice_agent_common.py +136 -0
- agent_cli/agents/assistant.py +383 -0
- agent_cli/agents/autocorrect.py +284 -0
- agent_cli/agents/chat.py +496 -0
- agent_cli/agents/memory/__init__.py +31 -0
- agent_cli/agents/memory/add.py +190 -0
- agent_cli/agents/memory/proxy.py +160 -0
- agent_cli/agents/rag_proxy.py +128 -0
- agent_cli/agents/speak.py +209 -0
- agent_cli/agents/transcribe.py +671 -0
- agent_cli/agents/transcribe_daemon.py +499 -0
- agent_cli/agents/voice_edit.py +291 -0
- agent_cli/api.py +22 -0
- agent_cli/cli.py +106 -0
- agent_cli/config.py +503 -0
- agent_cli/config_cmd.py +307 -0
- agent_cli/constants.py +27 -0
- agent_cli/core/__init__.py +1 -0
- agent_cli/core/audio.py +461 -0
- agent_cli/core/audio_format.py +299 -0
- agent_cli/core/chroma.py +88 -0
- agent_cli/core/deps.py +191 -0
- agent_cli/core/openai_proxy.py +139 -0
- agent_cli/core/process.py +195 -0
- agent_cli/core/reranker.py +120 -0
- agent_cli/core/sse.py +87 -0
- agent_cli/core/transcription_logger.py +70 -0
- agent_cli/core/utils.py +526 -0
- agent_cli/core/vad.py +175 -0
- agent_cli/core/watch.py +65 -0
- agent_cli/dev/__init__.py +14 -0
- agent_cli/dev/cli.py +1588 -0
- agent_cli/dev/coding_agents/__init__.py +19 -0
- agent_cli/dev/coding_agents/aider.py +24 -0
- agent_cli/dev/coding_agents/base.py +167 -0
- agent_cli/dev/coding_agents/claude.py +39 -0
- agent_cli/dev/coding_agents/codex.py +24 -0
- agent_cli/dev/coding_agents/continue_dev.py +15 -0
- agent_cli/dev/coding_agents/copilot.py +24 -0
- agent_cli/dev/coding_agents/cursor_agent.py +48 -0
- agent_cli/dev/coding_agents/gemini.py +28 -0
- agent_cli/dev/coding_agents/opencode.py +15 -0
- agent_cli/dev/coding_agents/registry.py +49 -0
- agent_cli/dev/editors/__init__.py +19 -0
- agent_cli/dev/editors/base.py +89 -0
- agent_cli/dev/editors/cursor.py +15 -0
- agent_cli/dev/editors/emacs.py +46 -0
- agent_cli/dev/editors/jetbrains.py +56 -0
- agent_cli/dev/editors/nano.py +31 -0
- agent_cli/dev/editors/neovim.py +33 -0
- agent_cli/dev/editors/registry.py +59 -0
- agent_cli/dev/editors/sublime.py +20 -0
- agent_cli/dev/editors/vim.py +42 -0
- agent_cli/dev/editors/vscode.py +15 -0
- agent_cli/dev/editors/zed.py +20 -0
- agent_cli/dev/project.py +568 -0
- agent_cli/dev/registry.py +52 -0
- agent_cli/dev/skill/SKILL.md +141 -0
- agent_cli/dev/skill/examples.md +571 -0
- agent_cli/dev/terminals/__init__.py +19 -0
- agent_cli/dev/terminals/apple_terminal.py +82 -0
- agent_cli/dev/terminals/base.py +56 -0
- agent_cli/dev/terminals/gnome.py +51 -0
- agent_cli/dev/terminals/iterm2.py +84 -0
- agent_cli/dev/terminals/kitty.py +77 -0
- agent_cli/dev/terminals/registry.py +48 -0
- agent_cli/dev/terminals/tmux.py +58 -0
- agent_cli/dev/terminals/warp.py +132 -0
- agent_cli/dev/terminals/zellij.py +78 -0
- agent_cli/dev/worktree.py +856 -0
- agent_cli/docs_gen.py +417 -0
- agent_cli/example-config.toml +185 -0
- agent_cli/install/__init__.py +5 -0
- agent_cli/install/common.py +89 -0
- agent_cli/install/extras.py +174 -0
- agent_cli/install/hotkeys.py +48 -0
- agent_cli/install/services.py +87 -0
- agent_cli/memory/__init__.py +7 -0
- agent_cli/memory/_files.py +250 -0
- agent_cli/memory/_filters.py +63 -0
- agent_cli/memory/_git.py +157 -0
- agent_cli/memory/_indexer.py +142 -0
- agent_cli/memory/_ingest.py +408 -0
- agent_cli/memory/_persistence.py +182 -0
- agent_cli/memory/_prompt.py +91 -0
- agent_cli/memory/_retrieval.py +294 -0
- agent_cli/memory/_store.py +169 -0
- agent_cli/memory/_streaming.py +44 -0
- agent_cli/memory/_tasks.py +48 -0
- agent_cli/memory/api.py +113 -0
- agent_cli/memory/client.py +272 -0
- agent_cli/memory/engine.py +361 -0
- agent_cli/memory/entities.py +43 -0
- agent_cli/memory/models.py +112 -0
- agent_cli/opts.py +433 -0
- agent_cli/py.typed +0 -0
- agent_cli/rag/__init__.py +3 -0
- agent_cli/rag/_indexer.py +67 -0
- agent_cli/rag/_indexing.py +226 -0
- agent_cli/rag/_prompt.py +30 -0
- agent_cli/rag/_retriever.py +156 -0
- agent_cli/rag/_store.py +48 -0
- agent_cli/rag/_utils.py +218 -0
- agent_cli/rag/api.py +175 -0
- agent_cli/rag/client.py +299 -0
- agent_cli/rag/engine.py +302 -0
- agent_cli/rag/models.py +55 -0
- agent_cli/scripts/.runtime/.gitkeep +0 -0
- agent_cli/scripts/__init__.py +1 -0
- agent_cli/scripts/check_plugin_skill_sync.py +50 -0
- agent_cli/scripts/linux-hotkeys/README.md +63 -0
- agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +45 -0
- agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +58 -0
- agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +58 -0
- agent_cli/scripts/macos-hotkeys/README.md +45 -0
- agent_cli/scripts/macos-hotkeys/skhd-config-example +5 -0
- agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +12 -0
- agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +37 -0
- agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +37 -0
- agent_cli/scripts/nvidia-asr-server/README.md +99 -0
- agent_cli/scripts/nvidia-asr-server/pyproject.toml +27 -0
- agent_cli/scripts/nvidia-asr-server/server.py +255 -0
- agent_cli/scripts/nvidia-asr-server/shell.nix +32 -0
- agent_cli/scripts/nvidia-asr-server/uv.lock +4654 -0
- agent_cli/scripts/run-openwakeword.sh +11 -0
- agent_cli/scripts/run-piper-windows.ps1 +30 -0
- agent_cli/scripts/run-piper.sh +24 -0
- agent_cli/scripts/run-whisper-linux.sh +40 -0
- agent_cli/scripts/run-whisper-macos.sh +6 -0
- agent_cli/scripts/run-whisper-windows.ps1 +51 -0
- agent_cli/scripts/run-whisper.sh +9 -0
- agent_cli/scripts/run_faster_whisper_server.py +136 -0
- agent_cli/scripts/setup-linux-hotkeys.sh +72 -0
- agent_cli/scripts/setup-linux.sh +108 -0
- agent_cli/scripts/setup-macos-hotkeys.sh +61 -0
- agent_cli/scripts/setup-macos.sh +76 -0
- agent_cli/scripts/setup-windows.ps1 +63 -0
- agent_cli/scripts/start-all-services-windows.ps1 +53 -0
- agent_cli/scripts/start-all-services.sh +178 -0
- agent_cli/scripts/sync_extras.py +138 -0
- agent_cli/server/__init__.py +3 -0
- agent_cli/server/cli.py +721 -0
- agent_cli/server/common.py +222 -0
- agent_cli/server/model_manager.py +288 -0
- agent_cli/server/model_registry.py +225 -0
- agent_cli/server/proxy/__init__.py +3 -0
- agent_cli/server/proxy/api.py +444 -0
- agent_cli/server/streaming.py +67 -0
- agent_cli/server/tts/__init__.py +3 -0
- agent_cli/server/tts/api.py +335 -0
- agent_cli/server/tts/backends/__init__.py +82 -0
- agent_cli/server/tts/backends/base.py +139 -0
- agent_cli/server/tts/backends/kokoro.py +403 -0
- agent_cli/server/tts/backends/piper.py +253 -0
- agent_cli/server/tts/model_manager.py +201 -0
- agent_cli/server/tts/model_registry.py +28 -0
- agent_cli/server/tts/wyoming_handler.py +249 -0
- agent_cli/server/whisper/__init__.py +3 -0
- agent_cli/server/whisper/api.py +413 -0
- agent_cli/server/whisper/backends/__init__.py +89 -0
- agent_cli/server/whisper/backends/base.py +97 -0
- agent_cli/server/whisper/backends/faster_whisper.py +225 -0
- agent_cli/server/whisper/backends/mlx.py +270 -0
- agent_cli/server/whisper/languages.py +116 -0
- agent_cli/server/whisper/model_manager.py +157 -0
- agent_cli/server/whisper/model_registry.py +28 -0
- agent_cli/server/whisper/wyoming_handler.py +203 -0
- agent_cli/services/__init__.py +343 -0
- agent_cli/services/_wyoming_utils.py +64 -0
- agent_cli/services/asr.py +506 -0
- agent_cli/services/llm.py +228 -0
- agent_cli/services/tts.py +450 -0
- agent_cli/services/wake_word.py +142 -0
- agent_cli-0.70.5.dist-info/METADATA +2118 -0
- agent_cli-0.70.5.dist-info/RECORD +196 -0
- agent_cli-0.70.5.dist-info/WHEEL +4 -0
- agent_cli-0.70.5.dist-info/entry_points.txt +4 -0
- agent_cli-0.70.5.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# This file was autogenerated by uv via the following command:
|
|
2
|
+
# uv export --extra speed --no-dev --no-emit-project --no-hashes
|
|
3
|
+
annotated-types==0.7.0
|
|
4
|
+
# via pydantic
|
|
5
|
+
anyio==4.12.1
|
|
6
|
+
# via httpx
|
|
7
|
+
audiostretchy==1.3.5
|
|
8
|
+
# via agent-cli
|
|
9
|
+
certifi==2026.1.4
|
|
10
|
+
# via
|
|
11
|
+
# httpcore
|
|
12
|
+
# httpx
|
|
13
|
+
click==8.3.1
|
|
14
|
+
# via
|
|
15
|
+
# typer
|
|
16
|
+
# typer-slim
|
|
17
|
+
colorama==0.4.6 ; sys_platform == 'win32'
|
|
18
|
+
# via click
|
|
19
|
+
dotenv==0.9.9
|
|
20
|
+
# via agent-cli
|
|
21
|
+
fire==0.7.1
|
|
22
|
+
# via audiostretchy
|
|
23
|
+
h11==0.16.0
|
|
24
|
+
# via httpcore
|
|
25
|
+
httpcore==1.0.9
|
|
26
|
+
# via httpx
|
|
27
|
+
httpx==0.28.1
|
|
28
|
+
# via agent-cli
|
|
29
|
+
idna==3.11
|
|
30
|
+
# via
|
|
31
|
+
# anyio
|
|
32
|
+
# httpx
|
|
33
|
+
markdown-it-py==4.0.0
|
|
34
|
+
# via rich
|
|
35
|
+
mdurl==0.1.2
|
|
36
|
+
# via markdown-it-py
|
|
37
|
+
numpy==2.3.5
|
|
38
|
+
# via audiostretchy
|
|
39
|
+
psutil==7.2.1 ; sys_platform == 'win32'
|
|
40
|
+
# via agent-cli
|
|
41
|
+
pydantic==2.12.5
|
|
42
|
+
# via agent-cli
|
|
43
|
+
pydantic-core==2.41.5
|
|
44
|
+
# via pydantic
|
|
45
|
+
pygments==2.19.2
|
|
46
|
+
# via rich
|
|
47
|
+
pyperclip==1.11.0
|
|
48
|
+
# via agent-cli
|
|
49
|
+
python-dotenv==1.2.1
|
|
50
|
+
# via dotenv
|
|
51
|
+
rich==14.2.0
|
|
52
|
+
# via
|
|
53
|
+
# agent-cli
|
|
54
|
+
# typer
|
|
55
|
+
# typer-slim
|
|
56
|
+
setproctitle==1.3.7
|
|
57
|
+
# via agent-cli
|
|
58
|
+
shellingham==1.5.4
|
|
59
|
+
# via
|
|
60
|
+
# typer
|
|
61
|
+
# typer-slim
|
|
62
|
+
termcolor==3.3.0
|
|
63
|
+
# via fire
|
|
64
|
+
typer==0.21.1
|
|
65
|
+
# via agent-cli
|
|
66
|
+
typer-slim==0.21.1
|
|
67
|
+
# via agent-cli
|
|
68
|
+
typing-extensions==4.15.0
|
|
69
|
+
# via
|
|
70
|
+
# anyio
|
|
71
|
+
# pydantic
|
|
72
|
+
# pydantic-core
|
|
73
|
+
# typer
|
|
74
|
+
# typer-slim
|
|
75
|
+
# typing-inspection
|
|
76
|
+
typing-inspection==0.4.2
|
|
77
|
+
# via pydantic
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# This file was autogenerated by uv via the following command:
|
|
2
|
+
# uv export --extra vad --no-dev --no-emit-project --no-hashes
|
|
3
|
+
annotated-types==0.7.0
|
|
4
|
+
# via pydantic
|
|
5
|
+
anyio==4.12.1
|
|
6
|
+
# via httpx
|
|
7
|
+
certifi==2026.1.4
|
|
8
|
+
# via
|
|
9
|
+
# httpcore
|
|
10
|
+
# httpx
|
|
11
|
+
click==8.3.1
|
|
12
|
+
# via
|
|
13
|
+
# typer
|
|
14
|
+
# typer-slim
|
|
15
|
+
colorama==0.4.6 ; sys_platform == 'win32'
|
|
16
|
+
# via click
|
|
17
|
+
coloredlogs==15.0.1
|
|
18
|
+
# via onnxruntime
|
|
19
|
+
dotenv==0.9.9
|
|
20
|
+
# via agent-cli
|
|
21
|
+
filelock==3.20.3
|
|
22
|
+
# via torch
|
|
23
|
+
flatbuffers==25.12.19
|
|
24
|
+
# via onnxruntime
|
|
25
|
+
fsspec==2026.1.0
|
|
26
|
+
# via torch
|
|
27
|
+
h11==0.16.0
|
|
28
|
+
# via httpcore
|
|
29
|
+
httpcore==1.0.9
|
|
30
|
+
# via httpx
|
|
31
|
+
httpx==0.28.1
|
|
32
|
+
# via agent-cli
|
|
33
|
+
humanfriendly==10.0
|
|
34
|
+
# via coloredlogs
|
|
35
|
+
idna==3.11
|
|
36
|
+
# via
|
|
37
|
+
# anyio
|
|
38
|
+
# httpx
|
|
39
|
+
jinja2==3.1.6
|
|
40
|
+
# via torch
|
|
41
|
+
markdown-it-py==4.0.0
|
|
42
|
+
# via rich
|
|
43
|
+
markupsafe==3.0.3
|
|
44
|
+
# via jinja2
|
|
45
|
+
mdurl==0.1.2
|
|
46
|
+
# via markdown-it-py
|
|
47
|
+
mpmath==1.3.0
|
|
48
|
+
# via sympy
|
|
49
|
+
networkx==3.6.1
|
|
50
|
+
# via torch
|
|
51
|
+
numpy==2.3.5
|
|
52
|
+
# via onnxruntime
|
|
53
|
+
nvidia-cublas-cu12==12.8.4.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
54
|
+
# via
|
|
55
|
+
# nvidia-cudnn-cu12
|
|
56
|
+
# nvidia-cusolver-cu12
|
|
57
|
+
# torch
|
|
58
|
+
nvidia-cuda-cupti-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
59
|
+
# via torch
|
|
60
|
+
nvidia-cuda-nvrtc-cu12==12.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
61
|
+
# via torch
|
|
62
|
+
nvidia-cuda-runtime-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
63
|
+
# via torch
|
|
64
|
+
nvidia-cudnn-cu12==9.10.2.21 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
65
|
+
# via torch
|
|
66
|
+
nvidia-cufft-cu12==11.3.3.83 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
67
|
+
# via torch
|
|
68
|
+
nvidia-cufile-cu12==1.13.1.3 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
69
|
+
# via torch
|
|
70
|
+
nvidia-curand-cu12==10.3.9.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
71
|
+
# via torch
|
|
72
|
+
nvidia-cusolver-cu12==11.7.3.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
73
|
+
# via torch
|
|
74
|
+
nvidia-cusparse-cu12==12.5.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
75
|
+
# via
|
|
76
|
+
# nvidia-cusolver-cu12
|
|
77
|
+
# torch
|
|
78
|
+
nvidia-cusparselt-cu12==0.7.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
79
|
+
# via torch
|
|
80
|
+
nvidia-nccl-cu12==2.27.5 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
81
|
+
# via torch
|
|
82
|
+
nvidia-nvjitlink-cu12==12.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
83
|
+
# via
|
|
84
|
+
# nvidia-cufft-cu12
|
|
85
|
+
# nvidia-cusolver-cu12
|
|
86
|
+
# nvidia-cusparse-cu12
|
|
87
|
+
# torch
|
|
88
|
+
nvidia-nvshmem-cu12==3.3.20 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
89
|
+
# via torch
|
|
90
|
+
nvidia-nvtx-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
91
|
+
# via torch
|
|
92
|
+
onnxruntime==1.20.1
|
|
93
|
+
# via silero-vad
|
|
94
|
+
packaging==25.0
|
|
95
|
+
# via
|
|
96
|
+
# onnxruntime
|
|
97
|
+
# silero-vad
|
|
98
|
+
protobuf==6.33.4
|
|
99
|
+
# via onnxruntime
|
|
100
|
+
psutil==7.2.1 ; sys_platform == 'win32'
|
|
101
|
+
# via agent-cli
|
|
102
|
+
pydantic==2.12.5
|
|
103
|
+
# via agent-cli
|
|
104
|
+
pydantic-core==2.41.5
|
|
105
|
+
# via pydantic
|
|
106
|
+
pygments==2.19.2
|
|
107
|
+
# via rich
|
|
108
|
+
pyperclip==1.11.0
|
|
109
|
+
# via agent-cli
|
|
110
|
+
pyreadline3==3.5.4 ; sys_platform == 'win32'
|
|
111
|
+
# via humanfriendly
|
|
112
|
+
python-dotenv==1.2.1
|
|
113
|
+
# via dotenv
|
|
114
|
+
rich==14.2.0
|
|
115
|
+
# via
|
|
116
|
+
# agent-cli
|
|
117
|
+
# typer
|
|
118
|
+
# typer-slim
|
|
119
|
+
setproctitle==1.3.7
|
|
120
|
+
# via agent-cli
|
|
121
|
+
setuptools==80.9.0 ; python_full_version >= '3.12'
|
|
122
|
+
# via torch
|
|
123
|
+
shellingham==1.5.4
|
|
124
|
+
# via
|
|
125
|
+
# typer
|
|
126
|
+
# typer-slim
|
|
127
|
+
silero-vad==6.2.0
|
|
128
|
+
# via agent-cli
|
|
129
|
+
sympy==1.14.0
|
|
130
|
+
# via
|
|
131
|
+
# onnxruntime
|
|
132
|
+
# torch
|
|
133
|
+
torch==2.9.1
|
|
134
|
+
# via
|
|
135
|
+
# silero-vad
|
|
136
|
+
# torchaudio
|
|
137
|
+
torchaudio==2.9.1
|
|
138
|
+
# via silero-vad
|
|
139
|
+
triton==3.5.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
140
|
+
# via torch
|
|
141
|
+
typer==0.21.1
|
|
142
|
+
# via agent-cli
|
|
143
|
+
typer-slim==0.21.1
|
|
144
|
+
# via agent-cli
|
|
145
|
+
typing-extensions==4.15.0
|
|
146
|
+
# via
|
|
147
|
+
# anyio
|
|
148
|
+
# pydantic
|
|
149
|
+
# pydantic-core
|
|
150
|
+
# torch
|
|
151
|
+
# typer
|
|
152
|
+
# typer-slim
|
|
153
|
+
# typing-inspection
|
|
154
|
+
typing-inspection==0.4.2
|
|
155
|
+
# via pydantic
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# This file was autogenerated by uv via the following command:
|
|
2
|
+
# uv export --extra wyoming --no-dev --no-emit-project --no-hashes
|
|
3
|
+
annotated-types==0.7.0
|
|
4
|
+
# via pydantic
|
|
5
|
+
anyio==4.12.1
|
|
6
|
+
# via httpx
|
|
7
|
+
certifi==2026.1.4
|
|
8
|
+
# via
|
|
9
|
+
# httpcore
|
|
10
|
+
# httpx
|
|
11
|
+
click==8.3.1
|
|
12
|
+
# via
|
|
13
|
+
# typer
|
|
14
|
+
# typer-slim
|
|
15
|
+
colorama==0.4.6 ; sys_platform == 'win32'
|
|
16
|
+
# via click
|
|
17
|
+
dotenv==0.9.9
|
|
18
|
+
# via agent-cli
|
|
19
|
+
h11==0.16.0
|
|
20
|
+
# via httpcore
|
|
21
|
+
httpcore==1.0.9
|
|
22
|
+
# via httpx
|
|
23
|
+
httpx==0.28.1
|
|
24
|
+
# via agent-cli
|
|
25
|
+
idna==3.11
|
|
26
|
+
# via
|
|
27
|
+
# anyio
|
|
28
|
+
# httpx
|
|
29
|
+
markdown-it-py==4.0.0
|
|
30
|
+
# via rich
|
|
31
|
+
mdurl==0.1.2
|
|
32
|
+
# via markdown-it-py
|
|
33
|
+
psutil==7.2.1 ; sys_platform == 'win32'
|
|
34
|
+
# via agent-cli
|
|
35
|
+
pydantic==2.12.5
|
|
36
|
+
# via agent-cli
|
|
37
|
+
pydantic-core==2.41.5
|
|
38
|
+
# via pydantic
|
|
39
|
+
pygments==2.19.2
|
|
40
|
+
# via rich
|
|
41
|
+
pyperclip==1.11.0
|
|
42
|
+
# via agent-cli
|
|
43
|
+
python-dotenv==1.2.1
|
|
44
|
+
# via dotenv
|
|
45
|
+
rich==14.2.0
|
|
46
|
+
# via
|
|
47
|
+
# agent-cli
|
|
48
|
+
# typer
|
|
49
|
+
# typer-slim
|
|
50
|
+
setproctitle==1.3.7
|
|
51
|
+
# via agent-cli
|
|
52
|
+
shellingham==1.5.4
|
|
53
|
+
# via
|
|
54
|
+
# typer
|
|
55
|
+
# typer-slim
|
|
56
|
+
typer==0.21.1
|
|
57
|
+
# via agent-cli
|
|
58
|
+
typer-slim==0.21.1
|
|
59
|
+
# via agent-cli
|
|
60
|
+
typing-extensions==4.15.0
|
|
61
|
+
# via
|
|
62
|
+
# anyio
|
|
63
|
+
# pydantic
|
|
64
|
+
# pydantic-core
|
|
65
|
+
# typer
|
|
66
|
+
# typer-slim
|
|
67
|
+
# typing-inspection
|
|
68
|
+
typing-inspection==0.4.2
|
|
69
|
+
# via pydantic
|
|
70
|
+
wyoming==1.8.0
|
|
71
|
+
# via agent-cli
|
agent_cli/_tools.py
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"""Tool definitions for the chat agent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
from datetime import UTC, datetime
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Memory system helpers
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _get_memory_file_path() -> Path:
|
|
20
|
+
"""Get the path to the memory file.
|
|
21
|
+
|
|
22
|
+
If the environment variable ``AGENT_CLI_HISTORY_DIR`` is set (by the
|
|
23
|
+
running agent), store the memory file in that directory.
|
|
24
|
+
Otherwise fall back to the user's config directory.
|
|
25
|
+
"""
|
|
26
|
+
history_dir = os.getenv("AGENT_CLI_HISTORY_DIR")
|
|
27
|
+
if history_dir:
|
|
28
|
+
return Path(history_dir).expanduser() / "long_term_memory.json"
|
|
29
|
+
|
|
30
|
+
return Path.home() / ".config" / "agent-cli" / "memory" / "long_term_memory.json"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _load_memories() -> list[dict[str, Any]]:
|
|
34
|
+
"""Load memories from file, returning empty list if file doesn't exist."""
|
|
35
|
+
memory_file = _get_memory_file_path()
|
|
36
|
+
if not memory_file.exists():
|
|
37
|
+
return []
|
|
38
|
+
|
|
39
|
+
with memory_file.open("r") as f:
|
|
40
|
+
return json.load(f)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _save_memories(memories: list[dict[str, Any]]) -> None:
|
|
44
|
+
"""Save memories to file, creating directories if needed."""
|
|
45
|
+
memory_file = _get_memory_file_path()
|
|
46
|
+
memory_file.parent.mkdir(parents=True, exist_ok=True)
|
|
47
|
+
|
|
48
|
+
with memory_file.open("w") as f:
|
|
49
|
+
json.dump(memories, f, indent=2)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _find_memory_by_id(memories: list[dict[str, Any]], memory_id: int) -> dict[str, Any] | None:
|
|
53
|
+
"""Find a memory by ID in the memories list."""
|
|
54
|
+
for memory in memories:
|
|
55
|
+
if memory["id"] == memory_id:
|
|
56
|
+
return memory
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _format_memory_summary(memory: dict[str, Any]) -> str:
|
|
61
|
+
"""Format a memory for display in search results."""
|
|
62
|
+
return (
|
|
63
|
+
f"ID: {memory['id']} | Category: {memory['category']} | "
|
|
64
|
+
f"Content: {memory['content']} | Tags: {', '.join(memory['tags'])}"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _format_memory_detailed(memory: dict[str, Any]) -> str:
|
|
69
|
+
"""Format a memory with full details for listing."""
|
|
70
|
+
created = datetime.fromisoformat(memory["timestamp"]).strftime("%Y-%m-%d %H:%M")
|
|
71
|
+
updated_info = ""
|
|
72
|
+
if "updated_at" in memory:
|
|
73
|
+
updated = datetime.fromisoformat(memory["updated_at"]).strftime("%Y-%m-%d %H:%M")
|
|
74
|
+
updated_info = f" (updated: {updated})"
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
f"ID: {memory['id']} | Category: {memory['category']}\n"
|
|
78
|
+
f"Content: {memory['content']}\n"
|
|
79
|
+
f"Tags: {', '.join(memory['tags']) if memory['tags'] else 'None'}\n"
|
|
80
|
+
f"Created: {created}{updated_info}\n"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _parse_tags(tags_string: str) -> list[str]:
|
|
85
|
+
"""Parse comma-separated tags string into a list of clean tags."""
|
|
86
|
+
return [tag.strip() for tag in tags_string.split(",") if tag.strip()]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
R = TypeVar("R")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _memory_operation(operation_name: str, operation_func: Callable[[], str]) -> str:
|
|
93
|
+
"""Wrapper for memory operations with consistent error handling."""
|
|
94
|
+
try:
|
|
95
|
+
return operation_func()
|
|
96
|
+
except Exception as e:
|
|
97
|
+
return f"Error {operation_name}: {e}"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def read_file(path: str) -> str:
|
|
101
|
+
"""Read the content of a file.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
path: The path to the file to read.
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
try:
|
|
108
|
+
return Path(path).read_text()
|
|
109
|
+
except FileNotFoundError:
|
|
110
|
+
return f"Error: File not found at {path}"
|
|
111
|
+
except OSError as e:
|
|
112
|
+
return f"Error reading file: {e}"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def execute_code(code: str) -> str:
|
|
116
|
+
"""Execute a shell command.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
code: The shell command to execute.
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
try:
|
|
123
|
+
result = subprocess.run(
|
|
124
|
+
code.split(),
|
|
125
|
+
capture_output=True,
|
|
126
|
+
text=True,
|
|
127
|
+
check=True,
|
|
128
|
+
)
|
|
129
|
+
return result.stdout
|
|
130
|
+
except subprocess.CalledProcessError as e:
|
|
131
|
+
return f"Error executing code: {e.stderr}"
|
|
132
|
+
except FileNotFoundError:
|
|
133
|
+
return f"Error: Command not found: {code.split()[0]}"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def add_memory(content: str, category: str = "general", tags: str = "") -> str:
|
|
137
|
+
"""Add important information to long-term memory for future conversations.
|
|
138
|
+
|
|
139
|
+
Use this when the user shares:
|
|
140
|
+
- Personal information (name, job, location, family, etc.)
|
|
141
|
+
- Preferences (favorite foods, work style, communication preferences, etc.)
|
|
142
|
+
- Important facts they want remembered (birthdays, project details, goals, etc.)
|
|
143
|
+
- Tasks or commitments they mention
|
|
144
|
+
|
|
145
|
+
Always ask for permission before storing personal or sensitive information.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
content: The specific information to remember (be descriptive and clear)
|
|
149
|
+
category: Type of memory - use "personal", "preferences", "facts", "tasks", "projects", or "general"
|
|
150
|
+
tags: Comma-separated keywords that would help find this memory later (e.g., "work, python, programming")
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Confirmation message with the memory ID
|
|
154
|
+
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
def _add_memory_operation() -> str:
|
|
158
|
+
memories = _load_memories()
|
|
159
|
+
|
|
160
|
+
memory = {
|
|
161
|
+
"id": len(memories) + 1,
|
|
162
|
+
"content": content,
|
|
163
|
+
"category": category,
|
|
164
|
+
"tags": _parse_tags(tags),
|
|
165
|
+
"timestamp": datetime.now(UTC).isoformat(),
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
memories.append(memory)
|
|
169
|
+
_save_memories(memories)
|
|
170
|
+
|
|
171
|
+
return f"Memory added successfully with ID {memory['id']}"
|
|
172
|
+
|
|
173
|
+
return _memory_operation("adding memory", _add_memory_operation)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def search_memory(query: str, category: str = "") -> str:
|
|
177
|
+
"""Search long-term memory for relevant information before answering questions.
|
|
178
|
+
|
|
179
|
+
Use this tool:
|
|
180
|
+
- Before answering questions about the user's preferences, personal info, or past conversations
|
|
181
|
+
- When the user asks "what do you remember about..." or similar questions
|
|
182
|
+
- When you need context about the user's work, projects, or goals
|
|
183
|
+
- To check if you've discussed a topic before
|
|
184
|
+
|
|
185
|
+
The search looks through memory content and tags for matches.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
query: Keywords to search for (e.g., "programming languages", "work schedule", "preferences")
|
|
189
|
+
category: Optional filter by category ("personal", "preferences", "facts", "tasks", "projects")
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Relevant memories found, or message if none found
|
|
193
|
+
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
def _search_memory_operation() -> str:
|
|
197
|
+
memories = _load_memories()
|
|
198
|
+
|
|
199
|
+
if not memories:
|
|
200
|
+
return "No memories found. Memory system not initialized."
|
|
201
|
+
|
|
202
|
+
# Simple text-based search
|
|
203
|
+
query_lower = query.lower()
|
|
204
|
+
relevant_memories = []
|
|
205
|
+
|
|
206
|
+
for memory in memories:
|
|
207
|
+
# Check if query matches content, tags, or category
|
|
208
|
+
content_match = query_lower in memory["content"].lower()
|
|
209
|
+
tag_match = any(query_lower in tag.lower() for tag in memory["tags"])
|
|
210
|
+
category_match = not category or memory["category"].lower() == category.lower()
|
|
211
|
+
|
|
212
|
+
if (content_match or tag_match) and category_match:
|
|
213
|
+
relevant_memories.append(memory)
|
|
214
|
+
|
|
215
|
+
if not relevant_memories:
|
|
216
|
+
return f"No memories found matching '{query}'"
|
|
217
|
+
|
|
218
|
+
# Format results
|
|
219
|
+
results = [_format_memory_summary(memory) for memory in relevant_memories[-5:]]
|
|
220
|
+
|
|
221
|
+
return "\n".join(results)
|
|
222
|
+
|
|
223
|
+
return _memory_operation("searching memory", _search_memory_operation)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def update_memory(memory_id: int, content: str = "", category: str = "", tags: str = "") -> str:
|
|
227
|
+
"""Update an existing memory by ID.
|
|
228
|
+
|
|
229
|
+
Use this tool:
|
|
230
|
+
- When the user wants to correct or modify previously stored information
|
|
231
|
+
- When information has changed (e.g., job change, preference updates)
|
|
232
|
+
- When the user says "update my memory about..." or "change the memory where..."
|
|
233
|
+
|
|
234
|
+
Only provide the fields that should be updated - empty fields will keep existing values.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
memory_id: The ID of the memory to update (use search_memory or list_all_memories to find IDs)
|
|
238
|
+
content: New content for the memory (leave empty to keep existing)
|
|
239
|
+
category: New category (leave empty to keep existing)
|
|
240
|
+
tags: New comma-separated tags (leave empty to keep existing)
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
Confirmation message or error if memory ID not found
|
|
244
|
+
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
def _update_memory_operation() -> str:
|
|
248
|
+
memories = _load_memories()
|
|
249
|
+
|
|
250
|
+
if not memories:
|
|
251
|
+
return "No memories found. Memory system not initialized."
|
|
252
|
+
|
|
253
|
+
# Find memory to update
|
|
254
|
+
memory_to_update = _find_memory_by_id(memories, memory_id)
|
|
255
|
+
if not memory_to_update:
|
|
256
|
+
return f"Memory with ID {memory_id} not found."
|
|
257
|
+
|
|
258
|
+
# Update fields if provided
|
|
259
|
+
if content:
|
|
260
|
+
memory_to_update["content"] = content
|
|
261
|
+
if category:
|
|
262
|
+
memory_to_update["category"] = category
|
|
263
|
+
if tags:
|
|
264
|
+
memory_to_update["tags"] = _parse_tags(tags)
|
|
265
|
+
|
|
266
|
+
# Add update timestamp
|
|
267
|
+
memory_to_update["updated_at"] = datetime.now(UTC).isoformat()
|
|
268
|
+
|
|
269
|
+
_save_memories(memories)
|
|
270
|
+
return f"Memory ID {memory_id} updated successfully."
|
|
271
|
+
|
|
272
|
+
return _memory_operation("updating memory", _update_memory_operation)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def list_all_memories(limit: int = 10) -> str:
|
|
276
|
+
"""List all memories with their details.
|
|
277
|
+
|
|
278
|
+
Use this tool:
|
|
279
|
+
- When the user asks "show me all my memories" or "list everything you remember"
|
|
280
|
+
- When they want to see specific memory IDs for updating or reference
|
|
281
|
+
- To provide a complete overview of stored information
|
|
282
|
+
|
|
283
|
+
Shows memories in reverse chronological order (newest first).
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
limit: Maximum number of memories to show (default 10, use higher numbers if user wants more)
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
Formatted list of all memories with IDs, content, categories, and tags
|
|
290
|
+
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
def _list_all_memories_operation() -> str:
|
|
294
|
+
memories = _load_memories()
|
|
295
|
+
|
|
296
|
+
if not memories:
|
|
297
|
+
return "No memories stored yet."
|
|
298
|
+
|
|
299
|
+
# Sort by ID (newest first) and limit results
|
|
300
|
+
memories_to_show = sorted(memories, key=lambda x: x["id"], reverse=True)[:limit]
|
|
301
|
+
|
|
302
|
+
results = [f"Showing {len(memories_to_show)} of {len(memories)} total memories:\n"]
|
|
303
|
+
results.extend(_format_memory_detailed(memory) for memory in memories_to_show)
|
|
304
|
+
|
|
305
|
+
if len(memories) > limit:
|
|
306
|
+
results.append(
|
|
307
|
+
f"... and {len(memories) - limit} more memories. Use a higher limit to see more.",
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return "\n".join(results)
|
|
311
|
+
|
|
312
|
+
return _memory_operation("listing memories", _list_all_memories_operation)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def list_memory_categories() -> str:
|
|
316
|
+
"""List all memory categories and their counts to see what has been remembered.
|
|
317
|
+
|
|
318
|
+
Use this tool:
|
|
319
|
+
- When the user asks "what categories do you have?"
|
|
320
|
+
- To get a quick overview of memory organization
|
|
321
|
+
- When the user wants to know what types of information are stored
|
|
322
|
+
|
|
323
|
+
This provides a summary view before using list_all_memories for details.
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
Summary of memory categories with counts (e.g., "personal: 5 memories")
|
|
327
|
+
|
|
328
|
+
"""
|
|
329
|
+
|
|
330
|
+
def _list_categories_operation() -> str:
|
|
331
|
+
memories = _load_memories()
|
|
332
|
+
|
|
333
|
+
if not memories:
|
|
334
|
+
return "No memories found. Memory system not initialized."
|
|
335
|
+
|
|
336
|
+
# Count categories
|
|
337
|
+
categories: dict[str, int] = {}
|
|
338
|
+
for memory in memories:
|
|
339
|
+
category = memory["category"]
|
|
340
|
+
categories[category] = categories.get(category, 0) + 1
|
|
341
|
+
|
|
342
|
+
if not categories:
|
|
343
|
+
return "No memory categories found."
|
|
344
|
+
|
|
345
|
+
results = ["Memory Categories:"]
|
|
346
|
+
for category, count in sorted(categories.items()):
|
|
347
|
+
results.append(f"- {category}: {count} memories")
|
|
348
|
+
|
|
349
|
+
return "\n".join(results)
|
|
350
|
+
|
|
351
|
+
return _memory_operation("listing categories", _list_categories_operation)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def tools() -> list:
|
|
355
|
+
"""Return a list of tools."""
|
|
356
|
+
from pydantic_ai.common_tools.duckduckgo import duckduckgo_search_tool # noqa: PLC0415
|
|
357
|
+
from pydantic_ai.tools import Tool # noqa: PLC0415
|
|
358
|
+
|
|
359
|
+
return [
|
|
360
|
+
Tool(read_file),
|
|
361
|
+
Tool(execute_code),
|
|
362
|
+
Tool(add_memory),
|
|
363
|
+
Tool(search_memory),
|
|
364
|
+
Tool(update_memory),
|
|
365
|
+
Tool(list_all_memories),
|
|
366
|
+
Tool(list_memory_categories),
|
|
367
|
+
duckduckgo_search_tool(),
|
|
368
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Agent implementations for the Agent CLI."""
|
|
2
|
+
|
|
3
|
+
from . import (
|
|
4
|
+
assistant,
|
|
5
|
+
autocorrect,
|
|
6
|
+
chat,
|
|
7
|
+
memory,
|
|
8
|
+
rag_proxy,
|
|
9
|
+
speak,
|
|
10
|
+
transcribe,
|
|
11
|
+
voice_edit,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"assistant",
|
|
16
|
+
"autocorrect",
|
|
17
|
+
"chat",
|
|
18
|
+
"memory",
|
|
19
|
+
"rag_proxy",
|
|
20
|
+
"speak",
|
|
21
|
+
"transcribe",
|
|
22
|
+
"voice_edit",
|
|
23
|
+
]
|