cade-cli 0.3.4__tar.gz → 0.4.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.
- {cade_cli-0.3.4 → cade_cli-0.4.0}/.gitignore +3 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/PKG-INFO +93 -7
- {cade_cli-0.3.4 → cade_cli-0.4.0}/README.md +91 -5
- {cade_cli-0.3.4 → cade_cli-0.4.0}/pyproject.toml +2 -2
- cade_cli-0.4.0/src/cadecoder/__init__.py +1 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/app.py +7 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/chat.py +99 -29
- cade_cli-0.4.0/src/cadecoder/cli/commands/context.py +323 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/model.py +5 -2
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/thread.py +46 -30
- cade_cli-0.4.0/src/cadecoder/cli/commands/tools.py +339 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/config.py +16 -17
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/constants.py +0 -2
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/errors.py +19 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/orchestrator.py +5 -2
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/__init__.py +35 -15
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/base.py +1 -0
- cade_cli-0.4.0/src/cadecoder/providers/ollama.py +308 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/openai.py +5 -2
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/__init__.py +9 -21
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/__init__.py +3 -10
- cade_cli-0.4.0/src/cadecoder/tools/manager/composite.py +267 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/config.py +21 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/mcp.py +207 -4
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ui/session.py +23 -7
- cade_cli-0.3.4/src/cadecoder/__init__.py +0 -1
- cade_cli-0.3.4/src/cadecoder/cli/commands/tools.py +0 -226
- cade_cli-0.3.4/src/cadecoder/tools/manager/arcade.py +0 -277
- cade_cli-0.3.4/src/cadecoder/tools/manager/cache.py +0 -129
- cade_cli-0.3.4/src/cadecoder/tools/manager/composite.py +0 -157
- cade_cli-0.3.4/src/cadecoder/tools/manager/local.py +0 -122
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ai/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ai/prompts.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/auth.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/auth.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/mcp.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/logging.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/names.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/types.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/context_window.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/parallel.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/anthropic.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/storage/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/storage/threads.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/templates/login_failed.html +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/templates/login_success.html +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/templates/styles.css +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/filesystem.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/git.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/search.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/shell.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/base.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ui/__init__.py +0 -0
- {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ui/display.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cade-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Cade - The CLI Agent from Arcade.dev
|
|
5
5
|
Project-URL: Homepage, https://arcade.dev
|
|
6
6
|
Project-URL: Documentation, https://docs.arcade.dev
|
|
@@ -24,8 +24,8 @@ Classifier: Typing :: Typed
|
|
|
24
24
|
Requires-Python: >=3.11
|
|
25
25
|
Requires-Dist: anthropic<1.0.0,>=0.34.0
|
|
26
26
|
Requires-Dist: arcade-core<5.0.0,>=4.1.0
|
|
27
|
+
Requires-Dist: arcade-mcp-server>=1.0.0
|
|
27
28
|
Requires-Dist: arcade-tdk>=2.0.0
|
|
28
|
-
Requires-Dist: arcadepy>=1.3.1
|
|
29
29
|
Requires-Dist: authlib<2.0.0,>=1.6.0
|
|
30
30
|
Requires-Dist: httpx<1.0.0,>=0.27.0
|
|
31
31
|
Requires-Dist: openai<2.0.0,>=1.0.0
|
|
@@ -75,7 +75,7 @@ brew install cade
|
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
77
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
78
|
-
uv
|
|
78
|
+
uv tool install cade-cli
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
### Install with pip
|
|
@@ -115,6 +115,27 @@ cade -r # Resume most recent
|
|
|
115
115
|
cade resume "my-project" # Resume by name
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
### Authentication
|
|
119
|
+
|
|
120
|
+
Cade uses Arcade Cloud for authentication and shares credentials with arcade-cli.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
cade login # Log in to Arcade Cloud
|
|
124
|
+
cade logout # Log out
|
|
125
|
+
cade whoami # Show current login status
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Context Management
|
|
129
|
+
|
|
130
|
+
Switch between organizations and projects for Arcade Cloud features.
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
cade context show # Show current org/project
|
|
134
|
+
cade context list # List available orgs and projects
|
|
135
|
+
cade context switch -i # Interactive selection
|
|
136
|
+
cade context switch --org my-org --project my-project
|
|
137
|
+
```
|
|
138
|
+
|
|
118
139
|
### Single Message Mode
|
|
119
140
|
|
|
120
141
|
```bash
|
|
@@ -128,6 +149,7 @@ cat error.log | cade -m "What went wrong?"
|
|
|
128
149
|
|--------|-------------|
|
|
129
150
|
| `-r`, `--resume` | Resume the most recent thread |
|
|
130
151
|
| `-m`, `--message` | Single message mode (non-interactive) |
|
|
152
|
+
| `-L`, `--local-only` | Disable remote tools (use only local tools) |
|
|
131
153
|
| `-v`, `--verbose` | Enable debug logging |
|
|
132
154
|
| `--version` | Show version |
|
|
133
155
|
|
|
@@ -205,9 +227,11 @@ Config is stored in `~/.cadecoder/`:
|
|
|
205
227
|
| Variable | Description |
|
|
206
228
|
|----------|-------------|
|
|
207
229
|
| `OPENAI_API_KEY` | OpenAI API key |
|
|
230
|
+
| `OPENAI_BASE_URL` | Custom OpenAI-compatible API endpoint |
|
|
208
231
|
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
209
232
|
| `ARCADE_API_KEY` | Arcade API key (alternative to OAuth) |
|
|
210
233
|
| `ARCADE_BASE_URL` | Custom Arcade API endpoint |
|
|
234
|
+
| `CADE_LOCAL_ONLY` | Set to `1` to disable remote tools |
|
|
211
235
|
| `CADECODER_HOME` | Override config directory |
|
|
212
236
|
|
|
213
237
|
### Example Config
|
|
@@ -228,9 +252,73 @@ provider = "openai"
|
|
|
228
252
|
model = "gpt-4.1"
|
|
229
253
|
|
|
230
254
|
[tool_settings]
|
|
231
|
-
|
|
255
|
+
# Tool filtering is managed via MCP server configuration
|
|
256
|
+
# See: cade mcp add --help
|
|
232
257
|
```
|
|
233
258
|
|
|
259
|
+
## Using Local or Custom LLMs
|
|
260
|
+
|
|
261
|
+
Cade works with any OpenAI-compatible API, including local servers (Ollama, vLLM, llama.cpp) and alternative cloud providers (Together AI, Groq, Fireworks).
|
|
262
|
+
|
|
263
|
+
### Local-Only Mode
|
|
264
|
+
|
|
265
|
+
When using local LLMs, you can skip Arcade Cloud authentication entirely with `--local-only`:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
# Local Ollama server without Arcade Cloud
|
|
269
|
+
cade chat --local-only --endpoint "http://localhost:11434/v1" --model "llama3"
|
|
270
|
+
|
|
271
|
+
# Or via environment variable
|
|
272
|
+
CADE_LOCAL_ONLY=1 cade chat --endpoint "http://localhost:11434/v1" --model "llama3"
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
This disables remote tools and uses only local tools. Cade will also gracefully fall back to local-only mode if Arcade Cloud authentication is not configured.
|
|
276
|
+
|
|
277
|
+
### Via CLI Flags
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
# Local Ollama server
|
|
281
|
+
cade chat --endpoint "http://localhost:11434/v1" --model "glm-4.7-flash:latest"
|
|
282
|
+
|
|
283
|
+
# vLLM server
|
|
284
|
+
cade chat -e http://localhost:8000/v1 -m mistral-7b
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Via Environment Variables
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
export OPENAI_BASE_URL="http://localhost:11434/v1"
|
|
291
|
+
export OPENAI_API_KEY="ollama" # Dummy key for local model
|
|
292
|
+
cade chat --model glm-4.7-flash:latest
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Via Config File
|
|
296
|
+
|
|
297
|
+
```toml
|
|
298
|
+
# ~/.cadecoder/cadecoder.toml
|
|
299
|
+
|
|
300
|
+
default_model = "glm-4.7-flash:latest"
|
|
301
|
+
|
|
302
|
+
[model_settings]
|
|
303
|
+
host = "http://localhost:11434/v1"
|
|
304
|
+
api_key = "ollama"
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
After configuring the TOML file:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
cade chat
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### `cade chat` Configuration Precedence
|
|
314
|
+
|
|
315
|
+
Settings are resolved in this order (first is used):
|
|
316
|
+
|
|
317
|
+
1. CLI flags (`--endpoint`, `--model`)
|
|
318
|
+
2. Environment variables (`OPENAI_BASE_URL`, `OPENAI_API_KEY`)
|
|
319
|
+
3. Config file (`model_settings.host`, `model_settings.api_key`)
|
|
320
|
+
4. Hardcoded defaults
|
|
321
|
+
|
|
234
322
|
## Contributing
|
|
235
323
|
|
|
236
324
|
### Development Setup
|
|
@@ -238,9 +326,7 @@ disabled_tools = []
|
|
|
238
326
|
```bash
|
|
239
327
|
git clone https://github.com/arcadeai-labs/cade.git
|
|
240
328
|
cd cade
|
|
241
|
-
uv
|
|
242
|
-
source .venv/bin/activate
|
|
243
|
-
uv pip install -e '.[dev]'
|
|
329
|
+
uv sync --extra dev
|
|
244
330
|
```
|
|
245
331
|
|
|
246
332
|
### Run Tests
|
|
@@ -21,7 +21,7 @@ brew install cade
|
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
24
|
-
uv
|
|
24
|
+
uv tool install cade-cli
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
### Install with pip
|
|
@@ -61,6 +61,27 @@ cade -r # Resume most recent
|
|
|
61
61
|
cade resume "my-project" # Resume by name
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
### Authentication
|
|
65
|
+
|
|
66
|
+
Cade uses Arcade Cloud for authentication and shares credentials with arcade-cli.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cade login # Log in to Arcade Cloud
|
|
70
|
+
cade logout # Log out
|
|
71
|
+
cade whoami # Show current login status
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Context Management
|
|
75
|
+
|
|
76
|
+
Switch between organizations and projects for Arcade Cloud features.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cade context show # Show current org/project
|
|
80
|
+
cade context list # List available orgs and projects
|
|
81
|
+
cade context switch -i # Interactive selection
|
|
82
|
+
cade context switch --org my-org --project my-project
|
|
83
|
+
```
|
|
84
|
+
|
|
64
85
|
### Single Message Mode
|
|
65
86
|
|
|
66
87
|
```bash
|
|
@@ -74,6 +95,7 @@ cat error.log | cade -m "What went wrong?"
|
|
|
74
95
|
|--------|-------------|
|
|
75
96
|
| `-r`, `--resume` | Resume the most recent thread |
|
|
76
97
|
| `-m`, `--message` | Single message mode (non-interactive) |
|
|
98
|
+
| `-L`, `--local-only` | Disable remote tools (use only local tools) |
|
|
77
99
|
| `-v`, `--verbose` | Enable debug logging |
|
|
78
100
|
| `--version` | Show version |
|
|
79
101
|
|
|
@@ -151,9 +173,11 @@ Config is stored in `~/.cadecoder/`:
|
|
|
151
173
|
| Variable | Description |
|
|
152
174
|
|----------|-------------|
|
|
153
175
|
| `OPENAI_API_KEY` | OpenAI API key |
|
|
176
|
+
| `OPENAI_BASE_URL` | Custom OpenAI-compatible API endpoint |
|
|
154
177
|
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
155
178
|
| `ARCADE_API_KEY` | Arcade API key (alternative to OAuth) |
|
|
156
179
|
| `ARCADE_BASE_URL` | Custom Arcade API endpoint |
|
|
180
|
+
| `CADE_LOCAL_ONLY` | Set to `1` to disable remote tools |
|
|
157
181
|
| `CADECODER_HOME` | Override config directory |
|
|
158
182
|
|
|
159
183
|
### Example Config
|
|
@@ -174,9 +198,73 @@ provider = "openai"
|
|
|
174
198
|
model = "gpt-4.1"
|
|
175
199
|
|
|
176
200
|
[tool_settings]
|
|
177
|
-
|
|
201
|
+
# Tool filtering is managed via MCP server configuration
|
|
202
|
+
# See: cade mcp add --help
|
|
178
203
|
```
|
|
179
204
|
|
|
205
|
+
## Using Local or Custom LLMs
|
|
206
|
+
|
|
207
|
+
Cade works with any OpenAI-compatible API, including local servers (Ollama, vLLM, llama.cpp) and alternative cloud providers (Together AI, Groq, Fireworks).
|
|
208
|
+
|
|
209
|
+
### Local-Only Mode
|
|
210
|
+
|
|
211
|
+
When using local LLMs, you can skip Arcade Cloud authentication entirely with `--local-only`:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Local Ollama server without Arcade Cloud
|
|
215
|
+
cade chat --local-only --endpoint "http://localhost:11434/v1" --model "llama3"
|
|
216
|
+
|
|
217
|
+
# Or via environment variable
|
|
218
|
+
CADE_LOCAL_ONLY=1 cade chat --endpoint "http://localhost:11434/v1" --model "llama3"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
This disables remote tools and uses only local tools. Cade will also gracefully fall back to local-only mode if Arcade Cloud authentication is not configured.
|
|
222
|
+
|
|
223
|
+
### Via CLI Flags
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Local Ollama server
|
|
227
|
+
cade chat --endpoint "http://localhost:11434/v1" --model "glm-4.7-flash:latest"
|
|
228
|
+
|
|
229
|
+
# vLLM server
|
|
230
|
+
cade chat -e http://localhost:8000/v1 -m mistral-7b
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Via Environment Variables
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
export OPENAI_BASE_URL="http://localhost:11434/v1"
|
|
237
|
+
export OPENAI_API_KEY="ollama" # Dummy key for local model
|
|
238
|
+
cade chat --model glm-4.7-flash:latest
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Via Config File
|
|
242
|
+
|
|
243
|
+
```toml
|
|
244
|
+
# ~/.cadecoder/cadecoder.toml
|
|
245
|
+
|
|
246
|
+
default_model = "glm-4.7-flash:latest"
|
|
247
|
+
|
|
248
|
+
[model_settings]
|
|
249
|
+
host = "http://localhost:11434/v1"
|
|
250
|
+
api_key = "ollama"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
After configuring the TOML file:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
cade chat
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### `cade chat` Configuration Precedence
|
|
260
|
+
|
|
261
|
+
Settings are resolved in this order (first is used):
|
|
262
|
+
|
|
263
|
+
1. CLI flags (`--endpoint`, `--model`)
|
|
264
|
+
2. Environment variables (`OPENAI_BASE_URL`, `OPENAI_API_KEY`)
|
|
265
|
+
3. Config file (`model_settings.host`, `model_settings.api_key`)
|
|
266
|
+
4. Hardcoded defaults
|
|
267
|
+
|
|
180
268
|
## Contributing
|
|
181
269
|
|
|
182
270
|
### Development Setup
|
|
@@ -184,9 +272,7 @@ disabled_tools = []
|
|
|
184
272
|
```bash
|
|
185
273
|
git clone https://github.com/arcadeai-labs/cade.git
|
|
186
274
|
cd cade
|
|
187
|
-
uv
|
|
188
|
-
source .venv/bin/activate
|
|
189
|
-
uv pip install -e '.[dev]'
|
|
275
|
+
uv sync --extra dev
|
|
190
276
|
```
|
|
191
277
|
|
|
192
278
|
### Run Tests
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cade-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
description = "Cade - The CLI Agent from Arcade.dev"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -28,11 +28,11 @@ dependencies = [
|
|
|
28
28
|
"pydantic[email]>=2.0.0,<3.0.0",
|
|
29
29
|
"toml>=0.10.0,<1.0.0",
|
|
30
30
|
"pyyaml>=6.0,<7.0.0",
|
|
31
|
-
"arcadepy>=1.3.1",
|
|
32
31
|
"openai>=1.0.0,<2.0.0",
|
|
33
32
|
"anthropic>=0.34.0,<1.0.0",
|
|
34
33
|
"ulid==1.1",
|
|
35
34
|
"arcade-tdk>=2.0.0",
|
|
35
|
+
"arcade-mcp-server>=1.0.0",
|
|
36
36
|
"arcade-core>=4.1.0,<5.0.0",
|
|
37
37
|
"authlib>=1.6.0,<2.0.0",
|
|
38
38
|
"pyperclip>=1.8.0,<2.0.0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.0"
|
|
@@ -13,6 +13,7 @@ from rich.console import Console
|
|
|
13
13
|
|
|
14
14
|
from cadecoder import __version__
|
|
15
15
|
from cadecoder.cli.commands import auth, chat
|
|
16
|
+
from cadecoder.cli.commands.context import context_app
|
|
16
17
|
from cadecoder.cli.commands.mcp import mcp_app
|
|
17
18
|
from cadecoder.cli.commands.model import model_app
|
|
18
19
|
from cadecoder.cli.commands.thread import thread_app
|
|
@@ -41,6 +42,12 @@ app.command(name="resume", help="Resume the most recent thread or a specific thr
|
|
|
41
42
|
)
|
|
42
43
|
|
|
43
44
|
# Register sub-command groups
|
|
45
|
+
app.add_typer(
|
|
46
|
+
context_app,
|
|
47
|
+
name="context",
|
|
48
|
+
help="Manage organization and project context",
|
|
49
|
+
rich_help_panel="User",
|
|
50
|
+
)
|
|
44
51
|
app.add_typer(mcp_app, name="mcp", help="Manage MCP servers", rich_help_panel="Tools")
|
|
45
52
|
app.add_typer(model_app, name="model", help="Manage AI models", rich_help_panel="Tools")
|
|
46
53
|
app.add_typer(tool_app, name="tools", help="View available tools", rich_help_panel="Tools")
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"""Interactive chat command for CadeCoder CLI."""
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
from typing import Annotated
|
|
4
5
|
|
|
5
6
|
import typer
|
|
6
7
|
from rich.console import Console
|
|
7
8
|
from rich.markup import escape
|
|
8
9
|
|
|
9
|
-
from cadecoder.core.config import get_config
|
|
10
|
-
from cadecoder.core.
|
|
11
|
-
from cadecoder.core.errors import CadeCoderError, StorageError
|
|
10
|
+
from cadecoder.core.config import get_config, is_local_only_mode
|
|
11
|
+
from cadecoder.core.errors import CadeCoderError, StorageError, get_provider_config_help
|
|
12
12
|
from cadecoder.core.logging import log
|
|
13
13
|
from cadecoder.execution.orchestrator import create_orchestrator
|
|
14
|
+
from cadecoder.providers import initialize_providers
|
|
15
|
+
from cadecoder.providers.base import provider_registry
|
|
14
16
|
from cadecoder.storage.threads import get_thread_history
|
|
15
17
|
from cadecoder.tools.local.git import get_current_branch_name
|
|
16
18
|
from cadecoder.ui.session import main as run_tui_main
|
|
@@ -18,19 +20,59 @@ from cadecoder.ui.session import main as run_tui_main
|
|
|
18
20
|
console = Console(stderr=True)
|
|
19
21
|
|
|
20
22
|
|
|
23
|
+
def _configure_custom_endpoint(endpoint: str) -> None:
|
|
24
|
+
"""Configure a custom API endpoint for local LLMs.
|
|
25
|
+
|
|
26
|
+
Automatically detects Ollama endpoints and uses the native OllamaProvider
|
|
27
|
+
for full tool calling support. Falls back to OpenAI-compatible mode for
|
|
28
|
+
other endpoints.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
endpoint: The custom API endpoint URL (e.g., http://localhost:11434/v1)
|
|
32
|
+
"""
|
|
33
|
+
# Detect Ollama endpoint (port 11434 or contains "ollama")
|
|
34
|
+
is_ollama = ":11434" in endpoint or "ollama" in endpoint.lower()
|
|
35
|
+
|
|
36
|
+
if is_ollama:
|
|
37
|
+
# Use native Ollama provider for full tool calling support
|
|
38
|
+
# Remove /v1 suffix if present (native API doesn't use it)
|
|
39
|
+
ollama_base = endpoint.rstrip("/").replace("/v1", "").replace("/api", "")
|
|
40
|
+
os.environ["OLLAMA_BASE_URL"] = ollama_base
|
|
41
|
+
log.info(f"Detected Ollama endpoint, using native OllamaProvider at {ollama_base}")
|
|
42
|
+
else:
|
|
43
|
+
# Use OpenAI-compatible provider for other endpoints
|
|
44
|
+
os.environ["OPENAI_BASE_URL"] = endpoint
|
|
45
|
+
if not os.environ.get("OPENAI_API_KEY"):
|
|
46
|
+
os.environ["OPENAI_API_KEY"] = "local"
|
|
47
|
+
log.info(f"Using OpenAI-compatible provider with endpoint {endpoint}")
|
|
48
|
+
|
|
49
|
+
# Re-initialize providers with the new endpoint
|
|
50
|
+
provider_registry._providers.clear()
|
|
51
|
+
provider_registry._default_provider = None
|
|
52
|
+
initialize_providers()
|
|
53
|
+
|
|
54
|
+
|
|
21
55
|
def chat(
|
|
22
56
|
thread_or_name: Annotated[
|
|
23
57
|
str | None,
|
|
24
58
|
typer.Argument(help="Thread ID or Thread Name to resume (optional)"),
|
|
25
59
|
] = None,
|
|
26
60
|
model: Annotated[
|
|
27
|
-
str,
|
|
61
|
+
str | None,
|
|
28
62
|
typer.Option(
|
|
29
63
|
"--model",
|
|
30
64
|
"-m",
|
|
31
65
|
help="AI model to use for the conversation.",
|
|
32
66
|
),
|
|
33
|
-
] =
|
|
67
|
+
] = None,
|
|
68
|
+
endpoint: Annotated[
|
|
69
|
+
str | None,
|
|
70
|
+
typer.Option(
|
|
71
|
+
"--endpoint",
|
|
72
|
+
"-e",
|
|
73
|
+
help="Custom API endpoint URL (for OpenAI-compatible APIs like Ollama, vLLM, etc.)",
|
|
74
|
+
),
|
|
75
|
+
] = None,
|
|
34
76
|
name: Annotated[
|
|
35
77
|
str | None,
|
|
36
78
|
typer.Option(
|
|
@@ -47,6 +89,14 @@ def chat(
|
|
|
47
89
|
help="System prompt to guide the AI assistant's behavior.",
|
|
48
90
|
),
|
|
49
91
|
] = None,
|
|
92
|
+
local_only: Annotated[
|
|
93
|
+
bool,
|
|
94
|
+
typer.Option(
|
|
95
|
+
"--local-only",
|
|
96
|
+
"-L",
|
|
97
|
+
help="Disable Arcade Cloud tools (use only local tools).",
|
|
98
|
+
),
|
|
99
|
+
] = False,
|
|
50
100
|
) -> None:
|
|
51
101
|
"""
|
|
52
102
|
Start an interactive chat session with AI.
|
|
@@ -56,17 +106,18 @@ def chat(
|
|
|
56
106
|
"""
|
|
57
107
|
command_name = "chat"
|
|
58
108
|
try:
|
|
109
|
+
# Figure out which model to use: CLI flag > config > constant
|
|
110
|
+
resolved_model = model or get_config().settings.default_model
|
|
111
|
+
if endpoint:
|
|
112
|
+
_configure_custom_endpoint(endpoint)
|
|
113
|
+
|
|
114
|
+
effective_local_only = local_only or is_local_only_mode()
|
|
115
|
+
|
|
59
116
|
# Preflight: ensure provider/API keys are configured before entering TUI
|
|
60
117
|
try:
|
|
61
|
-
_ = create_orchestrator()
|
|
62
|
-
except Exception
|
|
63
|
-
console.print(
|
|
64
|
-
"[bold red]Provider configuration error:[/bold red] "
|
|
65
|
-
"Failed to initialize the AI provider.\n"
|
|
66
|
-
"Set required API keys (e.g., OPENAI_API_KEY or ANTHROPIC_API_KEY) "
|
|
67
|
-
"or configure the provider, then try again.\n"
|
|
68
|
-
f"Details: {str(e)}"
|
|
69
|
-
)
|
|
118
|
+
_ = create_orchestrator(local_only=effective_local_only)
|
|
119
|
+
except Exception:
|
|
120
|
+
console.print(f"[bold red]Error:[/bold red] {get_provider_config_help()}")
|
|
70
121
|
raise typer.Exit(code=1)
|
|
71
122
|
|
|
72
123
|
# Get the thread history manager
|
|
@@ -110,7 +161,7 @@ def chat(
|
|
|
110
161
|
thread = history_manager.create_thread(
|
|
111
162
|
name=thread_or_name,
|
|
112
163
|
git_branch=current_branch,
|
|
113
|
-
model=
|
|
164
|
+
model=resolved_model,
|
|
114
165
|
user_id=user_id,
|
|
115
166
|
)
|
|
116
167
|
log.info(
|
|
@@ -136,7 +187,7 @@ def chat(
|
|
|
136
187
|
thread = history_manager.create_thread(
|
|
137
188
|
name=name,
|
|
138
189
|
git_branch=current_branch,
|
|
139
|
-
model=
|
|
190
|
+
model=resolved_model,
|
|
140
191
|
user_id=user_id,
|
|
141
192
|
)
|
|
142
193
|
selected_thread_id = thread.thread_id
|
|
@@ -157,9 +208,10 @@ def chat(
|
|
|
157
208
|
# Launch TUI
|
|
158
209
|
run_tui_main(
|
|
159
210
|
thread_id_to_run=str(selected_thread_id),
|
|
160
|
-
model=
|
|
211
|
+
model=resolved_model,
|
|
161
212
|
stream=True,
|
|
162
213
|
system_prompt=prompt,
|
|
214
|
+
local_only=effective_local_only,
|
|
163
215
|
)
|
|
164
216
|
except (StorageError, CadeCoderError) as e:
|
|
165
217
|
console.print(":x: [bold red]Error:[/bold red] " + escape(str(e)))
|
|
@@ -179,13 +231,21 @@ def resume(
|
|
|
179
231
|
typer.Argument(help="Thread name to resume (optional)"),
|
|
180
232
|
] = None,
|
|
181
233
|
model: Annotated[
|
|
182
|
-
str,
|
|
234
|
+
str | None,
|
|
183
235
|
typer.Option(
|
|
184
236
|
"--model",
|
|
185
237
|
"-m",
|
|
186
238
|
help="AI model to use for the conversation.",
|
|
187
239
|
),
|
|
188
|
-
] =
|
|
240
|
+
] = None,
|
|
241
|
+
endpoint: Annotated[
|
|
242
|
+
str | None,
|
|
243
|
+
typer.Option(
|
|
244
|
+
"--endpoint",
|
|
245
|
+
"-e",
|
|
246
|
+
help="Custom API endpoint URL (for OpenAI-compatible APIs like Ollama, vLLM).",
|
|
247
|
+
),
|
|
248
|
+
] = None,
|
|
189
249
|
prompt: Annotated[
|
|
190
250
|
str | None,
|
|
191
251
|
typer.Option(
|
|
@@ -194,6 +254,14 @@ def resume(
|
|
|
194
254
|
help="System prompt to guide the AI assistant's behavior.",
|
|
195
255
|
),
|
|
196
256
|
] = None,
|
|
257
|
+
local_only: Annotated[
|
|
258
|
+
bool,
|
|
259
|
+
typer.Option(
|
|
260
|
+
"--local-only",
|
|
261
|
+
"-L",
|
|
262
|
+
help="Only use local tools.",
|
|
263
|
+
),
|
|
264
|
+
] = False,
|
|
197
265
|
) -> None:
|
|
198
266
|
"""Resume a saved chat thread.
|
|
199
267
|
|
|
@@ -208,17 +276,18 @@ def resume(
|
|
|
208
276
|
"""
|
|
209
277
|
command_name = "resume"
|
|
210
278
|
try:
|
|
279
|
+
# Figure out which model to use: CLI flag > config > constant
|
|
280
|
+
resolved_model = model or get_config().settings.default_model
|
|
281
|
+
if endpoint:
|
|
282
|
+
_configure_custom_endpoint(endpoint)
|
|
283
|
+
|
|
284
|
+
effective_local_only = local_only or is_local_only_mode()
|
|
285
|
+
|
|
211
286
|
# Preflight provider before entering TUI
|
|
212
287
|
try:
|
|
213
|
-
_ = create_orchestrator()
|
|
214
|
-
except Exception
|
|
215
|
-
console.print(
|
|
216
|
-
"[bold red]Provider configuration error:[/bold red] "
|
|
217
|
-
"Failed to initialize the AI provider.\n"
|
|
218
|
-
"Set required API keys (e.g., OPENAI_API_KEY or ANTHROPIC_API_KEY) "
|
|
219
|
-
"or configure the provider, then try again.\n"
|
|
220
|
-
f"Details: {str(e)}"
|
|
221
|
-
)
|
|
288
|
+
_ = create_orchestrator(local_only=effective_local_only)
|
|
289
|
+
except Exception:
|
|
290
|
+
console.print(f"[bold red]Error:[/bold red] {get_provider_config_help()}")
|
|
222
291
|
raise typer.Exit(code=1)
|
|
223
292
|
|
|
224
293
|
history_manager = get_thread_history()
|
|
@@ -267,9 +336,10 @@ def resume(
|
|
|
267
336
|
|
|
268
337
|
run_tui_main(
|
|
269
338
|
thread_id_to_run=str(target_thread.thread_id),
|
|
270
|
-
model=
|
|
339
|
+
model=resolved_model,
|
|
271
340
|
stream=True,
|
|
272
341
|
system_prompt=prompt,
|
|
342
|
+
local_only=effective_local_only,
|
|
273
343
|
)
|
|
274
344
|
except (StorageError, CadeCoderError) as e:
|
|
275
345
|
console.print(":x: [bold red]Error:[/bold red] " + escape(str(e)))
|