yaicli 0.6.4__tar.gz → 0.7.1__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.
- {yaicli-0.6.4 → yaicli-0.7.1}/PKG-INFO +94 -4
- {yaicli-0.6.4 → yaicli-0.7.1}/README.md +90 -3
- {yaicli-0.6.4 → yaicli-0.7.1}/pyproject.toml +5 -1
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/const.py +17 -6
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/entry.py +24 -1
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/functions/__init__.py +13 -1
- yaicli-0.7.1/yaicli/llms/client.py +153 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/ai21_provider.py +33 -1
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/chatglm_provider.py +30 -7
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/doubao_provider.py +0 -14
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/gemini_provider.py +21 -22
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/huggingface_provider.py +1 -1
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/openai_provider.py +17 -8
- yaicli-0.7.1/yaicli/tools/__init__.py +127 -0
- yaicli-0.7.1/yaicli/tools/function.py +90 -0
- yaicli-0.7.1/yaicli/tools/mcp.py +459 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/utils.py +34 -0
- yaicli-0.6.4/yaicli/llms/client.py +0 -120
- yaicli-0.6.4/yaicli/tools.py +0 -159
- {yaicli-0.6.4 → yaicli-0.7.1}/.gitignore +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/LICENSE +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/__init__.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/chat.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/cli.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/config.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/console.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/exceptions.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/functions/buildin/execute_shell_command.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/history.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/__init__.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/chutes_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/cohere_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/deepseek_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/groq_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/infiniai_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/minimax_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/modelscope_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/ollama_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/openrouter_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/sambanova_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/siliconflow_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/targon_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/vertexai_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/xai_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/llms/providers/yi_provider.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/printer.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/render.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/role.py +0 -0
- {yaicli-0.6.4 → yaicli-0.7.1}/yaicli/schemas.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: yaicli
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.1
|
4
4
|
Summary: A simple CLI tool to interact with LLM
|
5
5
|
Project-URL: Homepage, https://github.com/belingud/yaicli
|
6
6
|
Project-URL: Repository, https://github.com/belingud/yaicli
|
@@ -215,6 +215,7 @@ Classifier: Programming Language :: Python :: 3
|
|
215
215
|
Requires-Python: >=3.10
|
216
216
|
Requires-Dist: click>=8.1.8
|
217
217
|
Requires-Dist: distro>=1.9.0
|
218
|
+
Requires-Dist: fastmcp>=2.9.2
|
218
219
|
Requires-Dist: httpx>=0.28.1
|
219
220
|
Requires-Dist: instructor>=1.7.9
|
220
221
|
Requires-Dist: json-repair>=0.44.1
|
@@ -237,6 +238,8 @@ Provides-Extra: gemini
|
|
237
238
|
Requires-Dist: google-genai>=1.20.0; extra == 'gemini'
|
238
239
|
Provides-Extra: huggingface
|
239
240
|
Requires-Dist: huggingface-hub>=0.33.0; extra == 'huggingface'
|
241
|
+
Provides-Extra: mistral
|
242
|
+
Requires-Dist: mistralai>=1.8.2; extra == 'mistral'
|
240
243
|
Provides-Extra: ollama
|
241
244
|
Requires-Dist: ollama>=0.5.1; extra == 'ollama'
|
242
245
|
Description-Content-Type: text/markdown
|
@@ -265,6 +268,7 @@ generate and execute shell commands, or get quick answers without leaving your w
|
|
265
268
|
> [!NOTE]
|
266
269
|
> YAICLI is actively developed. While core functionality is stable, some features may evolve in future releases.
|
267
270
|
|
271
|
+
> We support MCP since v0.7.0!
|
268
272
|
> We support Function Call since v0.5.0!
|
269
273
|
|
270
274
|
## ✨ Key Features
|
@@ -362,7 +366,6 @@ pip install .
|
|
362
366
|
- Deepseek
|
363
367
|
- Doubao
|
364
368
|
- Gemini
|
365
|
-
- Vertex AI
|
366
369
|
- Groq
|
367
370
|
- Huggingface
|
368
371
|
- Minimax
|
@@ -372,6 +375,7 @@ pip install .
|
|
372
375
|
- Sambanova
|
373
376
|
- Siliconflow
|
374
377
|
- Targon
|
378
|
+
- Vertex ai
|
375
379
|
- X AI
|
376
380
|
- Yi
|
377
381
|
- Unlimited OpenAI-compatible providers
|
@@ -438,6 +442,10 @@ ROLE_MODIFY_WARNING=true
|
|
438
442
|
ENABLE_FUNCTIONS=true
|
439
443
|
# Set to false to disable showing function output in the response
|
440
444
|
SHOW_FUNCTION_OUTPUT=true
|
445
|
+
|
446
|
+
# MCP settings
|
447
|
+
ENABLE_MCP=false
|
448
|
+
SHOW_MCP_OUTPUT=false
|
441
449
|
```
|
442
450
|
|
443
451
|
### Configuration Options Reference
|
@@ -468,7 +476,10 @@ SHOW_FUNCTION_OUTPUT=true
|
|
468
476
|
| `MAX_SAVED_CHATS` | Max saved chats | `20` | `YAI_MAX_SAVED_CHATS` |
|
469
477
|
| `ROLE_MODIFY_WARNING` | Warn user when modifying role | `true` | `YAI_ROLE_MODIFY_WARNING` |
|
470
478
|
| `ENABLE_FUNCTIONS` | Enable function calling | `true` | `YAI_ENABLE_FUNCTIONS` |
|
471
|
-
| `SHOW_FUNCTION_OUTPUT` | Show function output
|
479
|
+
| `SHOW_FUNCTION_OUTPUT` | Show function output when calling function | `true` | `YAI_SHOW_FUNCTION_OUTPUT` |
|
480
|
+
| `ENABLE_MCP` | Enable MCP tools | `false` | `YAI_ENABLE_MCP` |
|
481
|
+
| `SHOW_MCP_OUTPUT` | Show MCP output when calling mcp | `true` | `YAI_SHOW_MCP_OUTPUT` |
|
482
|
+
|
472
483
|
|
473
484
|
### LLM Provider Configuration
|
474
485
|
|
@@ -571,8 +582,10 @@ LOCATION=
|
|
571
582
|
|
572
583
|
#### Huggingface
|
573
584
|
|
585
|
+
Default `HF_PROVIDER` is `auto`.
|
586
|
+
|
574
587
|
```ini
|
575
|
-
HF_PROVIDER=
|
588
|
+
HF_PROVIDER=auto
|
576
589
|
PROVIDER=huggingface
|
577
590
|
API_KEY=
|
578
591
|
MODEL=deepseek-ai/DeepSeek-R1-0528
|
@@ -1252,6 +1265,83 @@ Thinking:
|
|
1252
1265
|
Current directory size: 156M (using du -sh .).
|
1253
1266
|
```
|
1254
1267
|
|
1268
|
+
### MCP
|
1269
|
+
|
1270
|
+
Add your MCP config in `~/.config/yaicli/mcp.json` (`C:\Users\<user>\.config\yaicli\mcp.json` on Windows.).
|
1271
|
+
|
1272
|
+
`--enable-mcp` option is corresponds to the configuration key `ENABLE_MCP`.
|
1273
|
+
|
1274
|
+
Example:
|
1275
|
+
|
1276
|
+
```shell
|
1277
|
+
ai 'What is the latest exchange rate between the BTC and the US dollar?' --enable-mcp --show-mcp-output
|
1278
|
+
|
1279
|
+
Assistant:
|
1280
|
+
|
1281
|
+
@Mcp call: bing_search({"query": "latest exchange rate between BTC and US dollar"})
|
1282
|
+
╭─ Mcp output ──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
1283
|
+
│ [ │
|
1284
|
+
│ { │
|
1285
|
+
│ "id": "result_1751024997243_0", │
|
1286
|
+
│ "title": "BTC to USD - Bitcoin to US Dollar Conversion - Exchange Rates", │
|
1287
|
+
│ "link": "https://www.exchange-rates.org/converter/btc-usd", │
|
1288
|
+
│ "snippet": "11 小时之前 · 1 Bitcoin = 107,304 US Dollars as of June 27, 2025 03:00 AM UTC. You can get live exchange │
|
1289
|
+
│ rates between Bitcoin and US Dollars using exchange-rates.org, which aggregates …" │
|
1290
|
+
│ }, │
|
1291
|
+
│ { │
|
1292
|
+
│ "id": "result_1751024997245_1", │
|
1293
|
+
│ "title": "Live Bitcoin to US Dollars Exchange Rate - ₿ 1 …", │
|
1294
|
+
│ "link": "https://btc.currencyrate.today/usd", │
|
1295
|
+
│ "snippet": ".b_imgcap_altitle p strong,.b_imgcap_altitle .b_factrow strong{color:#767676}#b_results │
|
1296
|
+
│ .b_imgcap_altitle{line-height:22px}.b_hList img{display:block}..." │
|
1297
|
+
│ }, │
|
1298
|
+
│ { │
|
1299
|
+
│ "id": "result_1751024997246_2", │
|
1300
|
+
│ "title": "1 BTC to USD - Bitcoins to US Dollars Exchange Rate - Xe", │
|
1301
|
+
│ "link": "https://www.xe.com/currencyconverter/convert/?From=BTC&To=USD", │
|
1302
|
+
│ "snippet": "2025年6月15日 · Get the latest 1 Bitcoin to US Dollar rate for FREE with the original Universal Currency │
|
1303
|
+
│ Converter. Set rate alerts for to and learn more about Bitcoins and US Dollars from …" │
|
1304
|
+
│ }, │
|
1305
|
+
│ { │
|
1306
|
+
│ "id": "result_1751024997246_3", │
|
1307
|
+
│ "title": "BTC to USD Exchange Rates | Best Exchange Rates", │
|
1308
|
+
│ "link": "https://bestexchangerates.com/rates/btc-to-usd", │
|
1309
|
+
│ "snippet": "Bitcoin (BTC) to US dollar (USD) market data - latest interbank exchange rate, trend, chart & historic │
|
1310
|
+
│ rates. Sell BTC → Buy USD" │
|
1311
|
+
│ }, │
|
1312
|
+
│ { │
|
1313
|
+
│ "id": "result_1751024997247_4", │
|
1314
|
+
│ "title": "BTC to USD | Bitcoin to US Dollar - Investing.com", │
|
1315
|
+
│ "link": "https://www.investing.com/crypto/bitcoin/btc-usd", │
|
1316
|
+
│ "snippet": "Bitcoin Eyes 120k as Fed Rate Cuts Hopes Rise, US Dollar Falls to Multi-Year Lows BTC hovers around │
|
1317
|
+
│ 107.5k after attempts at 108k Fed rate cut optimism rises USD falls to its lowest level …" │
|
1318
|
+
│ } │
|
1319
|
+
│ ] │
|
1320
|
+
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
1321
|
+
Here are some current exchange rates for Bitcoin (BTC) to US Dollar (USD):
|
1322
|
+
|
1323
|
+
1 Exchange-Rates.org:
|
1324
|
+
₿1 Bitcoin = 💵107,304 US Dollars (as of June 27, 2025, 03:00 AM UTC).
|
1325
|
+
Link
|
1326
|
+
2 BTC.CurrencyRate.Today:
|
1327
|
+
Live Bitcoin to US Dollars exchange rate.
|
1328
|
+
Link
|
1329
|
+
3 Xe.com:
|
1330
|
+
Latest conversion rate and information about Bitcoin to US Dollars.
|
1331
|
+
Link
|
1332
|
+
4 BestExchangeRates.com:
|
1333
|
+
Current BTC to USD market data, including charts and historic rates.
|
1334
|
+
Link
|
1335
|
+
5 Investing.com:
|
1336
|
+
Bitcoin price analysis and live BTC to USD updates.
|
1337
|
+
Link
|
1338
|
+
|
1339
|
+
For the most accurate and up-to-date rate, I recommend checking one of these sources directly.
|
1340
|
+
```
|
1341
|
+
|
1342
|
+

|
1343
|
+
|
1344
|
+
|
1255
1345
|
## 💻 Technical Details
|
1256
1346
|
|
1257
1347
|
### Architecture
|
@@ -22,6 +22,7 @@ generate and execute shell commands, or get quick answers without leaving your w
|
|
22
22
|
> [!NOTE]
|
23
23
|
> YAICLI is actively developed. While core functionality is stable, some features may evolve in future releases.
|
24
24
|
|
25
|
+
> We support MCP since v0.7.0!
|
25
26
|
> We support Function Call since v0.5.0!
|
26
27
|
|
27
28
|
## ✨ Key Features
|
@@ -119,7 +120,6 @@ pip install .
|
|
119
120
|
- Deepseek
|
120
121
|
- Doubao
|
121
122
|
- Gemini
|
122
|
-
- Vertex AI
|
123
123
|
- Groq
|
124
124
|
- Huggingface
|
125
125
|
- Minimax
|
@@ -129,6 +129,7 @@ pip install .
|
|
129
129
|
- Sambanova
|
130
130
|
- Siliconflow
|
131
131
|
- Targon
|
132
|
+
- Vertex ai
|
132
133
|
- X AI
|
133
134
|
- Yi
|
134
135
|
- Unlimited OpenAI-compatible providers
|
@@ -195,6 +196,10 @@ ROLE_MODIFY_WARNING=true
|
|
195
196
|
ENABLE_FUNCTIONS=true
|
196
197
|
# Set to false to disable showing function output in the response
|
197
198
|
SHOW_FUNCTION_OUTPUT=true
|
199
|
+
|
200
|
+
# MCP settings
|
201
|
+
ENABLE_MCP=false
|
202
|
+
SHOW_MCP_OUTPUT=false
|
198
203
|
```
|
199
204
|
|
200
205
|
### Configuration Options Reference
|
@@ -225,7 +230,10 @@ SHOW_FUNCTION_OUTPUT=true
|
|
225
230
|
| `MAX_SAVED_CHATS` | Max saved chats | `20` | `YAI_MAX_SAVED_CHATS` |
|
226
231
|
| `ROLE_MODIFY_WARNING` | Warn user when modifying role | `true` | `YAI_ROLE_MODIFY_WARNING` |
|
227
232
|
| `ENABLE_FUNCTIONS` | Enable function calling | `true` | `YAI_ENABLE_FUNCTIONS` |
|
228
|
-
| `SHOW_FUNCTION_OUTPUT` | Show function output
|
233
|
+
| `SHOW_FUNCTION_OUTPUT` | Show function output when calling function | `true` | `YAI_SHOW_FUNCTION_OUTPUT` |
|
234
|
+
| `ENABLE_MCP` | Enable MCP tools | `false` | `YAI_ENABLE_MCP` |
|
235
|
+
| `SHOW_MCP_OUTPUT` | Show MCP output when calling mcp | `true` | `YAI_SHOW_MCP_OUTPUT` |
|
236
|
+
|
229
237
|
|
230
238
|
### LLM Provider Configuration
|
231
239
|
|
@@ -328,8 +336,10 @@ LOCATION=
|
|
328
336
|
|
329
337
|
#### Huggingface
|
330
338
|
|
339
|
+
Default `HF_PROVIDER` is `auto`.
|
340
|
+
|
331
341
|
```ini
|
332
|
-
HF_PROVIDER=
|
342
|
+
HF_PROVIDER=auto
|
333
343
|
PROVIDER=huggingface
|
334
344
|
API_KEY=
|
335
345
|
MODEL=deepseek-ai/DeepSeek-R1-0528
|
@@ -1009,6 +1019,83 @@ Thinking:
|
|
1009
1019
|
Current directory size: 156M (using du -sh .).
|
1010
1020
|
```
|
1011
1021
|
|
1022
|
+
### MCP
|
1023
|
+
|
1024
|
+
Add your MCP config in `~/.config/yaicli/mcp.json` (`C:\Users\<user>\.config\yaicli\mcp.json` on Windows.).
|
1025
|
+
|
1026
|
+
`--enable-mcp` option is corresponds to the configuration key `ENABLE_MCP`.
|
1027
|
+
|
1028
|
+
Example:
|
1029
|
+
|
1030
|
+
```shell
|
1031
|
+
ai 'What is the latest exchange rate between the BTC and the US dollar?' --enable-mcp --show-mcp-output
|
1032
|
+
|
1033
|
+
Assistant:
|
1034
|
+
|
1035
|
+
@Mcp call: bing_search({"query": "latest exchange rate between BTC and US dollar"})
|
1036
|
+
╭─ Mcp output ──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
1037
|
+
│ [ │
|
1038
|
+
│ { │
|
1039
|
+
│ "id": "result_1751024997243_0", │
|
1040
|
+
│ "title": "BTC to USD - Bitcoin to US Dollar Conversion - Exchange Rates", │
|
1041
|
+
│ "link": "https://www.exchange-rates.org/converter/btc-usd", │
|
1042
|
+
│ "snippet": "11 小时之前 · 1 Bitcoin = 107,304 US Dollars as of June 27, 2025 03:00 AM UTC. You can get live exchange │
|
1043
|
+
│ rates between Bitcoin and US Dollars using exchange-rates.org, which aggregates …" │
|
1044
|
+
│ }, │
|
1045
|
+
│ { │
|
1046
|
+
│ "id": "result_1751024997245_1", │
|
1047
|
+
│ "title": "Live Bitcoin to US Dollars Exchange Rate - ₿ 1 …", │
|
1048
|
+
│ "link": "https://btc.currencyrate.today/usd", │
|
1049
|
+
│ "snippet": ".b_imgcap_altitle p strong,.b_imgcap_altitle .b_factrow strong{color:#767676}#b_results │
|
1050
|
+
│ .b_imgcap_altitle{line-height:22px}.b_hList img{display:block}..." │
|
1051
|
+
│ }, │
|
1052
|
+
│ { │
|
1053
|
+
│ "id": "result_1751024997246_2", │
|
1054
|
+
│ "title": "1 BTC to USD - Bitcoins to US Dollars Exchange Rate - Xe", │
|
1055
|
+
│ "link": "https://www.xe.com/currencyconverter/convert/?From=BTC&To=USD", │
|
1056
|
+
│ "snippet": "2025年6月15日 · Get the latest 1 Bitcoin to US Dollar rate for FREE with the original Universal Currency │
|
1057
|
+
│ Converter. Set rate alerts for to and learn more about Bitcoins and US Dollars from …" │
|
1058
|
+
│ }, │
|
1059
|
+
│ { │
|
1060
|
+
│ "id": "result_1751024997246_3", │
|
1061
|
+
│ "title": "BTC to USD Exchange Rates | Best Exchange Rates", │
|
1062
|
+
│ "link": "https://bestexchangerates.com/rates/btc-to-usd", │
|
1063
|
+
│ "snippet": "Bitcoin (BTC) to US dollar (USD) market data - latest interbank exchange rate, trend, chart & historic │
|
1064
|
+
│ rates. Sell BTC → Buy USD" │
|
1065
|
+
│ }, │
|
1066
|
+
│ { │
|
1067
|
+
│ "id": "result_1751024997247_4", │
|
1068
|
+
│ "title": "BTC to USD | Bitcoin to US Dollar - Investing.com", │
|
1069
|
+
│ "link": "https://www.investing.com/crypto/bitcoin/btc-usd", │
|
1070
|
+
│ "snippet": "Bitcoin Eyes 120k as Fed Rate Cuts Hopes Rise, US Dollar Falls to Multi-Year Lows BTC hovers around │
|
1071
|
+
│ 107.5k after attempts at 108k Fed rate cut optimism rises USD falls to its lowest level …" │
|
1072
|
+
│ } │
|
1073
|
+
│ ] │
|
1074
|
+
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
1075
|
+
Here are some current exchange rates for Bitcoin (BTC) to US Dollar (USD):
|
1076
|
+
|
1077
|
+
1 Exchange-Rates.org:
|
1078
|
+
₿1 Bitcoin = 💵107,304 US Dollars (as of June 27, 2025, 03:00 AM UTC).
|
1079
|
+
Link
|
1080
|
+
2 BTC.CurrencyRate.Today:
|
1081
|
+
Live Bitcoin to US Dollars exchange rate.
|
1082
|
+
Link
|
1083
|
+
3 Xe.com:
|
1084
|
+
Latest conversion rate and information about Bitcoin to US Dollars.
|
1085
|
+
Link
|
1086
|
+
4 BestExchangeRates.com:
|
1087
|
+
Current BTC to USD market data, including charts and historic rates.
|
1088
|
+
Link
|
1089
|
+
5 Investing.com:
|
1090
|
+
Bitcoin price analysis and live BTC to USD updates.
|
1091
|
+
Link
|
1092
|
+
|
1093
|
+
For the most accurate and up-to-date rate, I recommend checking one of these sources directly.
|
1094
|
+
```
|
1095
|
+
|
1096
|
+

|
1097
|
+
|
1098
|
+
|
1012
1099
|
## 💻 Technical Details
|
1013
1100
|
|
1014
1101
|
### Architecture
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "yaicli"
|
3
|
-
version = "0.
|
3
|
+
version = "0.7.1"
|
4
4
|
description = "A simple CLI tool to interact with LLM"
|
5
5
|
authors = [{ name = "belingud", email = "im.victor@qq.com" }]
|
6
6
|
readme = "README.md"
|
@@ -55,6 +55,7 @@ keywords = [
|
|
55
55
|
dependencies = [
|
56
56
|
"click>=8.1.8",
|
57
57
|
"distro>=1.9.0",
|
58
|
+
"fastmcp>=2.9.2",
|
58
59
|
"httpx>=0.28.1",
|
59
60
|
"instructor>=1.7.9",
|
60
61
|
"json-repair>=0.44.1",
|
@@ -88,6 +89,9 @@ gemini = ["google-genai>=1.20.0"]
|
|
88
89
|
huggingface = [
|
89
90
|
"huggingface-hub>=0.33.0",
|
90
91
|
]
|
92
|
+
mistral = [
|
93
|
+
"mistralai>=1.8.2",
|
94
|
+
]
|
91
95
|
|
92
96
|
[tool.pytest.ini_options]
|
93
97
|
testpaths = ["tests"]
|
@@ -16,7 +16,7 @@ from rich.console import JustifyMethod
|
|
16
16
|
BOOL_STR = Literal["true", "false", "yes", "no", "y", "n", "1", "0", "on", "off"]
|
17
17
|
|
18
18
|
|
19
|
-
class JustifyEnum(StrEnum):
|
19
|
+
class JustifyEnum(StrEnum): # type: ignore
|
20
20
|
DEFAULT = "default"
|
21
21
|
LEFT = "left"
|
22
22
|
CENTER = "center"
|
@@ -43,6 +43,7 @@ HISTORY_FILE = Path("~/.yaicli_history").expanduser()
|
|
43
43
|
CONFIG_PATH = Path("~/.config/yaicli/config.ini").expanduser()
|
44
44
|
ROLES_DIR = CONFIG_PATH.parent / "roles"
|
45
45
|
FUNCTIONS_DIR = CONFIG_PATH.parent / "functions"
|
46
|
+
MCP_JSON_PATH = CONFIG_PATH.parent / "mcp.json"
|
46
47
|
|
47
48
|
# Default configuration values
|
48
49
|
DEFAULT_CODE_THEME = "monokai"
|
@@ -69,6 +70,8 @@ DEFAULT_ROLE_MODIFY_WARNING: BOOL_STR = "true"
|
|
69
70
|
DEFAULT_ENABLE_FUNCTIONS: BOOL_STR = "true"
|
70
71
|
DEFAULT_SHOW_FUNCTION_OUTPUT: BOOL_STR = "true"
|
71
72
|
DEFAULT_REASONING_EFFORT: Optional[Literal["low", "high", "medium"]] = None
|
73
|
+
DEFAULT_ENABLE_MCP: BOOL_STR = "false"
|
74
|
+
DEFAULT_SHOW_MCP_OUTPUT: BOOL_STR = "false"
|
72
75
|
|
73
76
|
|
74
77
|
SHELL_PROMPT = """You are YAICLI, a shell command generator.
|
@@ -93,16 +96,16 @@ CODER_PROMPT = (
|
|
93
96
|
)
|
94
97
|
|
95
98
|
|
96
|
-
class DefaultRoleNames(StrEnum):
|
99
|
+
class DefaultRoleNames(StrEnum): # type: ignore
|
97
100
|
SHELL = "Shell Command Generator"
|
98
101
|
DEFAULT = "DEFAULT"
|
99
102
|
CODER = "Code Assistant"
|
100
103
|
|
101
104
|
|
102
105
|
DEFAULT_ROLES: dict[str, dict[str, Any]] = {
|
103
|
-
DefaultRoleNames.SHELL.value: {"name": DefaultRoleNames.SHELL.value, "prompt": SHELL_PROMPT},
|
104
|
-
DefaultRoleNames.DEFAULT.value: {"name": DefaultRoleNames.DEFAULT.value, "prompt": DEFAULT_PROMPT},
|
105
|
-
DefaultRoleNames.CODER.value: {"name": DefaultRoleNames.CODER.value, "prompt": CODER_PROMPT},
|
106
|
+
DefaultRoleNames.SHELL.value: {"name": DefaultRoleNames.SHELL.value, "prompt": SHELL_PROMPT}, # type: ignore
|
107
|
+
DefaultRoleNames.DEFAULT.value: {"name": DefaultRoleNames.DEFAULT.value, "prompt": DEFAULT_PROMPT}, # type: ignore
|
108
|
+
DefaultRoleNames.CODER.value: {"name": DefaultRoleNames.CODER.value, "prompt": CODER_PROMPT}, # type: ignore
|
106
109
|
}
|
107
110
|
|
108
111
|
# DEFAULT_CONFIG_MAP is a dictionary of the configuration options.
|
@@ -151,6 +154,8 @@ DEFAULT_CONFIG_MAP = {
|
|
151
154
|
"env_key": "YAI_SHOW_FUNCTION_OUTPUT",
|
152
155
|
"type": bool,
|
153
156
|
},
|
157
|
+
"ENABLE_MCP": {"value": DEFAULT_ENABLE_MCP, "env_key": "YAI_ENABLE_MCP", "type": bool},
|
158
|
+
"SHOW_MCP_OUTPUT": {"value": DEFAULT_SHOW_MCP_OUTPUT, "env_key": "YAI_SHOW_MCP_OUTPUT", "type": bool},
|
154
159
|
}
|
155
160
|
|
156
161
|
DEFAULT_CONFIG_INI = f"""[core]
|
@@ -201,6 +206,12 @@ ROLE_MODIFY_WARNING={DEFAULT_CONFIG_MAP["ROLE_MODIFY_WARNING"]["value"]}
|
|
201
206
|
# Function settings
|
202
207
|
# Set to false to disable sending functions in API requests
|
203
208
|
ENABLE_FUNCTIONS={DEFAULT_CONFIG_MAP["ENABLE_FUNCTIONS"]["value"]}
|
204
|
-
# Set to false to disable showing function output
|
209
|
+
# Set to false to disable showing function output when calling functions
|
205
210
|
SHOW_FUNCTION_OUTPUT={DEFAULT_CONFIG_MAP["SHOW_FUNCTION_OUTPUT"]["value"]}
|
211
|
+
|
212
|
+
# MCP settings
|
213
|
+
# Set to false to disable MCP in API requests
|
214
|
+
ENABLE_MCP={DEFAULT_CONFIG_MAP["ENABLE_MCP"]["value"]}
|
215
|
+
# Set to false to disable showing MCP output when calling MCP tools
|
216
|
+
SHOW_MCP_OUTPUT={DEFAULT_CONFIG_MAP["SHOW_MCP_OUTPUT"]["value"]}
|
206
217
|
"""
|
@@ -6,7 +6,7 @@ import typer
|
|
6
6
|
from .chat import FileChatManager
|
7
7
|
from .config import cfg
|
8
8
|
from .const import DEFAULT_CONFIG_INI, DefaultRoleNames, JustifyEnum
|
9
|
-
from .functions import install_functions, print_functions
|
9
|
+
from .functions import install_functions, print_functions, print_mcp
|
10
10
|
from .role import RoleManager
|
11
11
|
|
12
12
|
app = typer.Typer(
|
@@ -209,6 +209,29 @@ def main(
|
|
209
209
|
show_default=False,
|
210
210
|
callback=override_config,
|
211
211
|
),
|
212
|
+
# ------------------- MCP Options -------------------
|
213
|
+
enable_mcp: bool = typer.Option( # noqa: F841
|
214
|
+
cfg["ENABLE_MCP"],
|
215
|
+
"--enable-mcp/--disable-mcp",
|
216
|
+
help=f"Enable/disable MCP in API requests [dim](default: {'enabled' if cfg['ENABLE_MCP'] else 'disabled'})[/dim]",
|
217
|
+
rich_help_panel="MCP Options",
|
218
|
+
callback=override_config,
|
219
|
+
),
|
220
|
+
show_mcp_output: bool = typer.Option( # noqa: F841
|
221
|
+
cfg["SHOW_MCP_OUTPUT"],
|
222
|
+
"--show-mcp-output/--hide-mcp-output",
|
223
|
+
help=f"Show the output of MCP [dim](default: {'show' if cfg['SHOW_MCP_OUTPUT'] else 'hide'})[/dim]",
|
224
|
+
rich_help_panel="MCP Options",
|
225
|
+
show_default=False,
|
226
|
+
callback=override_config,
|
227
|
+
),
|
228
|
+
list_mcp: bool = typer.Option( # noqa: F841
|
229
|
+
False,
|
230
|
+
"--list-mcp",
|
231
|
+
help="List all available mcp.",
|
232
|
+
rich_help_panel="MCP Options",
|
233
|
+
callback=print_mcp,
|
234
|
+
),
|
212
235
|
):
|
213
236
|
"""YAICLI: Your AI assistant in the command line.
|
214
237
|
|
@@ -1,9 +1,10 @@
|
|
1
|
+
import json
|
1
2
|
import shutil
|
2
3
|
from pathlib import Path
|
3
4
|
from typing import Any
|
4
5
|
|
5
6
|
from ..console import get_console
|
6
|
-
from ..const import FUNCTIONS_DIR
|
7
|
+
from ..const import FUNCTIONS_DIR, MCP_JSON_PATH
|
7
8
|
from ..utils import option_callback
|
8
9
|
|
9
10
|
console = get_console()
|
@@ -37,3 +38,14 @@ def print_functions(cls, _: Any) -> None:
|
|
37
38
|
if file.name.startswith("_"):
|
38
39
|
continue
|
39
40
|
console.print(file)
|
41
|
+
|
42
|
+
|
43
|
+
@option_callback
|
44
|
+
def print_mcp(cls, _: Any) -> None:
|
45
|
+
"""List all available mcp"""
|
46
|
+
if not MCP_JSON_PATH.exists():
|
47
|
+
console.print("No mcp config found, please add your mcp config in ~/.config/yaicli/mcp.json")
|
48
|
+
return
|
49
|
+
with open(MCP_JSON_PATH, "r") as f:
|
50
|
+
mcp_config = json.load(f)
|
51
|
+
console.print_json(data=mcp_config)
|
@@ -0,0 +1,153 @@
|
|
1
|
+
from typing import Generator, List, Optional, Union
|
2
|
+
|
3
|
+
from ..config import cfg
|
4
|
+
from ..console import get_console
|
5
|
+
from ..schemas import ChatMessage, LLMResponse, RefreshLive, ToolCall
|
6
|
+
from ..tools import execute_tool_call
|
7
|
+
from ..tools.mcp import MCP_TOOL_NAME_PREFIX
|
8
|
+
from .provider import Provider, ProviderFactory
|
9
|
+
|
10
|
+
|
11
|
+
class LLMClient:
|
12
|
+
"""
|
13
|
+
LLM Client that coordinates provider interactions and tool calling
|
14
|
+
|
15
|
+
This class handles the higher level logic of:
|
16
|
+
1. Getting responses from LLM providers
|
17
|
+
2. Managing tool calls and their execution
|
18
|
+
3. Handling conversation flow with tools
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
provider: Optional[Provider] = None,
|
24
|
+
provider_name: str = "",
|
25
|
+
config: dict = cfg,
|
26
|
+
verbose: bool = False,
|
27
|
+
**kwargs,
|
28
|
+
):
|
29
|
+
"""
|
30
|
+
Initialize LLM client
|
31
|
+
|
32
|
+
Args:
|
33
|
+
provider: Optional pre-initialized Provider instance
|
34
|
+
provider_name: Name of the provider to use if provider not provided
|
35
|
+
config: Configuration dictionary
|
36
|
+
verbose: Whether to enable verbose logging
|
37
|
+
"""
|
38
|
+
self.config = config
|
39
|
+
self.verbose = verbose
|
40
|
+
self.console = get_console()
|
41
|
+
self.enable_function = self.config["ENABLE_FUNCTIONS"]
|
42
|
+
self.enable_mcp = self.config["ENABLE_MCP"]
|
43
|
+
|
44
|
+
# Use provided provider or create one
|
45
|
+
if provider:
|
46
|
+
self.provider = provider
|
47
|
+
elif provider_name:
|
48
|
+
self.provider = ProviderFactory.create_provider(provider_name, config=config, verbose=verbose, **kwargs)
|
49
|
+
else:
|
50
|
+
provider_name = config.get("PROVIDER", "openai").lower()
|
51
|
+
self.provider = ProviderFactory.create_provider(provider_name, config=config, verbose=verbose, **kwargs)
|
52
|
+
|
53
|
+
self.max_recursion_depth = config.get("MAX_RECURSION_DEPTH", 5)
|
54
|
+
|
55
|
+
def completion_with_tools(
|
56
|
+
self,
|
57
|
+
messages: List[ChatMessage],
|
58
|
+
stream: bool = False,
|
59
|
+
recursion_depth: int = 0,
|
60
|
+
) -> Generator[Union[LLMResponse, RefreshLive], None, None]:
|
61
|
+
"""
|
62
|
+
Get completion from provider with tool calling support
|
63
|
+
|
64
|
+
Args:
|
65
|
+
messages: List of messages for the conversation
|
66
|
+
stream: Whether to stream the response
|
67
|
+
recursion_depth: Current recursion depth for tool calls
|
68
|
+
|
69
|
+
Yields:
|
70
|
+
LLMResponse objects and control signals
|
71
|
+
"""
|
72
|
+
if recursion_depth >= self.max_recursion_depth:
|
73
|
+
self.console.print(
|
74
|
+
f"Maximum recursion depth ({self.max_recursion_depth}) reached, stopping further tool calls",
|
75
|
+
style="yellow",
|
76
|
+
)
|
77
|
+
return
|
78
|
+
|
79
|
+
# Get completion from provider and collect response data
|
80
|
+
assistant_response_content = ""
|
81
|
+
# Providers may return identical tool calls with the same ID in a single response during streaming
|
82
|
+
tool_calls: dict[str, ToolCall] = {}
|
83
|
+
|
84
|
+
# Stream responses and collect data
|
85
|
+
for llm_response in self.provider.completion(messages, stream=stream):
|
86
|
+
yield llm_response # Forward response to caller
|
87
|
+
|
88
|
+
# Collect content and tool calls for potential tool execution
|
89
|
+
if llm_response.content:
|
90
|
+
assistant_response_content += llm_response.content
|
91
|
+
if llm_response.tool_call and llm_response.tool_call.id not in tool_calls:
|
92
|
+
tool_calls[llm_response.tool_call.id] = llm_response.tool_call
|
93
|
+
|
94
|
+
# Check if we need to execute tools
|
95
|
+
if not tool_calls or not (self.enable_function or self.enable_mcp):
|
96
|
+
return
|
97
|
+
|
98
|
+
# Filter valid tool calls based on enabled features
|
99
|
+
valid_tool_calls = self._get_valid_tool_calls(tool_calls)
|
100
|
+
if not valid_tool_calls:
|
101
|
+
return
|
102
|
+
|
103
|
+
# Execute tools and continue conversation
|
104
|
+
yield from self._execute_tools_and_continue(
|
105
|
+
messages, assistant_response_content, valid_tool_calls, stream, recursion_depth
|
106
|
+
)
|
107
|
+
|
108
|
+
def _get_valid_tool_calls(self, tool_calls: dict[str, ToolCall]) -> List[ToolCall]:
|
109
|
+
"""Filter tool calls based on enabled features"""
|
110
|
+
valid_tool_calls = []
|
111
|
+
|
112
|
+
for tool_call in tool_calls.values():
|
113
|
+
is_mcp = tool_call.name.startswith(MCP_TOOL_NAME_PREFIX)
|
114
|
+
|
115
|
+
if is_mcp and self.enable_mcp:
|
116
|
+
valid_tool_calls.append(tool_call)
|
117
|
+
elif not is_mcp and self.enable_function:
|
118
|
+
valid_tool_calls.append(tool_call)
|
119
|
+
|
120
|
+
return valid_tool_calls
|
121
|
+
|
122
|
+
def _execute_tools_and_continue(
|
123
|
+
self,
|
124
|
+
messages: List[ChatMessage],
|
125
|
+
assistant_response_content: str,
|
126
|
+
tool_calls: List[ToolCall],
|
127
|
+
stream: bool,
|
128
|
+
recursion_depth: int,
|
129
|
+
) -> Generator[Union[LLMResponse, RefreshLive], None, None]:
|
130
|
+
"""Execute tool calls and continue the conversation"""
|
131
|
+
# Signal that new content is coming
|
132
|
+
yield RefreshLive()
|
133
|
+
|
134
|
+
# Add assistant message with tool calls to history (only once)
|
135
|
+
messages.append(ChatMessage(role="assistant", content=assistant_response_content, tool_calls=tool_calls))
|
136
|
+
|
137
|
+
# Execute each tool call and add results to messages
|
138
|
+
tool_role = self.provider.detect_tool_role()
|
139
|
+
|
140
|
+
for tool_call in tool_calls:
|
141
|
+
function_result, _ = execute_tool_call(tool_call)
|
142
|
+
|
143
|
+
messages.append(
|
144
|
+
ChatMessage(
|
145
|
+
role=tool_role,
|
146
|
+
content=function_result,
|
147
|
+
name=tool_call.name,
|
148
|
+
tool_call_id=tool_call.id,
|
149
|
+
)
|
150
|
+
)
|
151
|
+
|
152
|
+
# Continue the conversation with updated history
|
153
|
+
yield from self.completion_with_tools(messages, stream=stream, recursion_depth=recursion_depth + 1)
|