yaicli 0.6.4__py3-none-any.whl → 0.7.1__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.
yaicli/utils.py CHANGED
@@ -1,4 +1,6 @@
1
+ import asyncio
1
2
  import platform
3
+ from functools import wraps
2
4
  from os import getenv
3
5
  from os.path import basename, pathsep
4
6
  from typing import Any, Callable, Optional, TypeVar
@@ -132,3 +134,35 @@ def str2bool(value: Any) -> bool:
132
134
 
133
135
  # Handle empty strings and other invalid values
134
136
  raise ValueError(f"Invalid boolean value: {value}")
137
+
138
+
139
+ def get_or_create_event_loop() -> asyncio.AbstractEventLoop:
140
+ """
141
+ Get the current event loop or create a new one if it doesn't exist.
142
+ Compatible with Python 3.10+.
143
+
144
+ Returns:
145
+ asyncio.AbstractEventLoop: The current event loop or a new one if it doesn't exist.
146
+ """
147
+ try:
148
+ # Try to get the current running event loop
149
+ return asyncio.get_running_loop()
150
+ except RuntimeError:
151
+ # No running event loop, get or create event loop
152
+ try:
153
+ return asyncio.get_event_loop()
154
+ except RuntimeError:
155
+ # Create a new event loop and set it as the current thread's event loop
156
+ loop = asyncio.new_event_loop()
157
+ asyncio.set_event_loop(loop)
158
+ return loop
159
+
160
+
161
+ def wrap_function(func: Callable) -> Callable:
162
+ """Wrap a function to add a name and docstring"""
163
+
164
+ @wraps(func)
165
+ def wrapper(*args, **kwargs):
166
+ return func(*args, **kwargs)
167
+
168
+ return wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yaicli
3
- Version: 0.6.4
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 in response | `true` | `YAI_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=sambanova
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
+ ![mcp](artwork/mcp_example.png)
1343
+
1344
+
1255
1345
  ## 💻 Technical Details
1256
1346
 
1257
1347
  ### Architecture
@@ -1,38 +1,37 @@
1
- pyproject.toml,sha256=LQv7NHuPZjn7h03OWDzftK8V0G_OG0626EkpVEUh4IA,2756
1
+ pyproject.toml,sha256=nnGhGl-8nx5sHrGTF6TL9nHNZwUKFIAuBBTVSauePZ0,2816
2
2
  yaicli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  yaicli/chat.py,sha256=_emvZEdgMBth2nQGaNWPf0P45oW2k3bpuIwqsxFcM5A,13676
4
4
  yaicli/cli.py,sha256=s8Bj4MSQmLblh4fHBPKS-DvJoAdMmp64KC7e7BwzmOs,23322
5
5
  yaicli/config.py,sha256=_xLHgyW5dDg76bL1SyTcrQCnVs4dFpXafIS3sClshK0,6563
6
6
  yaicli/console.py,sha256=vARPJd-3lafutsQWrGntQVjLrYqaJD3qisN82pmuhjU,1973
7
- yaicli/const.py,sha256=G-EhMsSfOjKQLBhpOAc3pRtjvKmmWrwyyuyuGKHt7wk,8194
8
- yaicli/entry.py,sha256=Q1eqLE7tcHide7ooyPO7OCJpKE2YVuxR-NNFA2Pt2Hw,8693
7
+ yaicli/const.py,sha256=O4hNk3ztjJ1o26lMjM1GK5Jpy-oA9NF69Gy528_ccEM,8861
8
+ yaicli/entry.py,sha256=jz4sVVy2Nr7uFMqpBhodAjtV5zflxpNHhAROKFRAH58,9633
9
9
  yaicli/exceptions.py,sha256=WBYg8OTJJzaj7lt6HE7ZyBoe5T6A3yZRNCRfWd4iN0c,372
10
10
  yaicli/history.py,sha256=s-57X9FMsaQHF7XySq1gGH_jpd_cHHTYafYu2ECuG6M,2472
11
11
  yaicli/printer.py,sha256=g1TS7aDSQlWlSrQRhvNhNqoQKlsaf1lVOyUSK6LQLNQ,7945
12
12
  yaicli/render.py,sha256=k8o2P8fI44PJlyQbs7gmMiu2x2prwajdWn5JIt15BIA,505
13
13
  yaicli/role.py,sha256=PfwiVJIlzg7EzlvMM-kIy6vBK0d5d_J4M1I_fIZGnWk,7399
14
14
  yaicli/schemas.py,sha256=Ty2ybCvld-ritgBZoI3RR93vYfw9LUNqkR8xk8VRZ2A,762
15
- yaicli/tools.py,sha256=xw8KEs_xlSf79A2Aq1rAsUWahS6A_e5QMLt7QDXL5bs,5086
16
- yaicli/utils.py,sha256=bpo3Xhozpxsaci3FtEIKZ32l4ZdyWMsrHjYGX0tB4J4,4541
17
- yaicli/functions/__init__.py,sha256=_FJooQ9GkijG8xLwuU0cr5GBrGnC9Nc6bnCeUjrsT0k,1271
15
+ yaicli/utils.py,sha256=vCc_HoEKakA8HJ2m7_dIiIvMAIKEFlDpv1w1Yial-EE,5552
16
+ yaicli/functions/__init__.py,sha256=o2xwGvLKrvN8Wghhf_bU1klQfFRHW3g-f2BR968g31g,1652
18
17
  yaicli/functions/buildin/execute_shell_command.py,sha256=unl1-F8p6QZajeHdA0u5UpURMJM0WhdWMUWCCCHVRcI,1320
19
18
  yaicli/llms/__init__.py,sha256=x78cJujrJkelXPnzHS6pzHkITZdgLYZqJMnrMHbptoc,134
20
- yaicli/llms/client.py,sha256=mkE9KHSuPcJfpNQXbzF2YXGkel3jrOW8KfQ3YYpaK4M,4453
19
+ yaicli/llms/client.py,sha256=yjv8-DjVORdn1PKOC6t6Ei0uB3dz5GQ2bC3zAdKGALg,5759
21
20
  yaicli/llms/provider.py,sha256=jF15kmY_tZVOjlw0fbHQkEvlmOX57-HBhILzG0KvXyo,3412
22
- yaicli/llms/providers/ai21_provider.py,sha256=SvgGj9_87KEqmxCMLbtsSkT8J3rUD7Mb21UF7pMWsks,3035
23
- yaicli/llms/providers/chatglm_provider.py,sha256=QEzALvY5FBhuDCx6rHjLi7GSRTwTHNUwo8gg4FEdrxs,6466
21
+ yaicli/llms/providers/ai21_provider.py,sha256=1zHG1xYYL4zEA_hNa0YqmplC00evCKuZPU7r2v54Q8o,4551
22
+ yaicli/llms/providers/chatglm_provider.py,sha256=zno_AbFESsRG3E5-IVnqMc1uA-jTuE1u4u5gU0BkAkQ,7421
24
23
  yaicli/llms/providers/chutes_provider.py,sha256=mtvWvRRfHPH3JFfzym87wXtPNiMpLnur3805N9acx7E,882
25
24
  yaicli/llms/providers/cohere_provider.py,sha256=1UPzNqNOwM4_dsP4kvUaL9O6_bKjxm1lO6A0lM7hgS4,10959
26
25
  yaicli/llms/providers/deepseek_provider.py,sha256=iIV97x2ZCcwhGkshc8wpRi-YAnAnmo0n-YRegPlaOwQ,488
27
- yaicli/llms/providers/doubao_provider.py,sha256=4eOdE91ITUn3uo3mvYAzdrHsuFIIBwZWib21mtZn8OY,1938
28
- yaicli/llms/providers/gemini_provider.py,sha256=k_6JFmqiYPz5K8IioFic5tp8KAHgeeakjkPyqJVz8BI,8007
26
+ yaicli/llms/providers/doubao_provider.py,sha256=Tr0EP2fDh9txI-8dp_7BVAMswMkbw0cjBtZd6gI12v8,1453
27
+ yaicli/llms/providers/gemini_provider.py,sha256=78mOQEcf4uWzNduf8-tH0uMyka7xFbHNRnQQvHu_csU,8113
29
28
  yaicli/llms/providers/groq_provider.py,sha256=EiS1Yxw5jbAUBFCRYsJ57KYgZPk6oH-_gD72OfW8Oik,1358
30
- yaicli/llms/providers/huggingface_provider.py,sha256=vDJyyK_aOlvktNvs-cji6pDtmKEp61vuVJ783BZw4pc,1247
29
+ yaicli/llms/providers/huggingface_provider.py,sha256=XigSh4HDx00aYtBivMc2rwRwW6y6Nf0XgwEiFvcil2E,1239
31
30
  yaicli/llms/providers/infiniai_provider.py,sha256=8-nU6QE58PRoZL9b_HzbPp4yi6OGm7rXtfi9z7bJMOg,786
32
31
  yaicli/llms/providers/minimax_provider.py,sha256=W-j3dzrYMEv14bYt2pCPvPUxvxsUs-iMAcGB9yXakFs,744
33
32
  yaicli/llms/providers/modelscope_provider.py,sha256=qWM0T7r0Zf8k3pLzjj7_IFdnmnx7S3rJO0f9rRm8-_A,504
34
33
  yaicli/llms/providers/ollama_provider.py,sha256=pjpYjfnHWnExweZi1KGbT07JGkcxzKPhqICo8dD82D0,6967
35
- yaicli/llms/providers/openai_provider.py,sha256=ENn21QacP2iTcmbxuW7dgiw3_fUr8EGWhNSFR2yxjis,10079
34
+ yaicli/llms/providers/openai_provider.py,sha256=96vqKiVScULb9rfCuzrI7e9wCgXiqjc2Lx9XP8zCf9Q,10546
36
35
  yaicli/llms/providers/openrouter_provider.py,sha256=R-7FrUrCAKPZ3gbnuo0M6rPlVw1mvSBjbLGs_FtZWM0,732
37
36
  yaicli/llms/providers/sambanova_provider.py,sha256=FFLrsvARt1UPAFWWgiuB6zvGzGKdtehKL58HdE1fo_M,2254
38
37
  yaicli/llms/providers/siliconflow_provider.py,sha256=CW2VSt6evUyFy21vN84Nvmw1P0JpmHBLznsgiXMnHM0,496
@@ -40,8 +39,11 @@ yaicli/llms/providers/targon_provider.py,sha256=RQ808eS9lvsyvlzyKaQYcN0NimbpoNWg
40
39
  yaicli/llms/providers/vertexai_provider.py,sha256=_ddrse1LfXRChTgkvxUlexyfJlfr0sVJH-Rmno3djSI,636
41
40
  yaicli/llms/providers/xai_provider.py,sha256=Q6iOvJZOXIAwRiiHMKEBgq8-W6SGVZ9QD1_532bNYfo,199
42
41
  yaicli/llms/providers/yi_provider.py,sha256=EnTm9qTxHPnzERsKqgGnzRIVhXFcAEdYqtOra65pGmY,719
43
- yaicli-0.6.4.dist-info/METADATA,sha256=q1r4B-AADLIC9gAYEDd4BDHnAMnbjqDXrrOG3QNxbGc,55786
44
- yaicli-0.6.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
45
- yaicli-0.6.4.dist-info/entry_points.txt,sha256=iYVyQP0PJIm9tQnlQheqT435kK_xdGoi5j9aswGV9hA,66
46
- yaicli-0.6.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
47
- yaicli-0.6.4.dist-info/RECORD,,
42
+ yaicli/tools/__init__.py,sha256=62kSqvh232jog_pb85Tsx4Pe_rI9CAODGMTxAXdKzy0,4112
43
+ yaicli/tools/function.py,sha256=1yXnpOg7Y2sw_LwTOBH7042cHeBoBCVJJMQTVyQh_Hw,2802
44
+ yaicli/tools/mcp.py,sha256=-V17cDsQvmdb2eeVnuC_ypg5Rn6f10dUjEptNK1kTxU,15004
45
+ yaicli-0.7.1.dist-info/METADATA,sha256=8JNcElJu4dgwlbp7G11Ik0H20K6zrX7cHzdI7nZwbNA,64435
46
+ yaicli-0.7.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
+ yaicli-0.7.1.dist-info/entry_points.txt,sha256=iYVyQP0PJIm9tQnlQheqT435kK_xdGoi5j9aswGV9hA,66
48
+ yaicli-0.7.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
49
+ yaicli-0.7.1.dist-info/RECORD,,
yaicli/tools.py DELETED
@@ -1,159 +0,0 @@
1
- import importlib.util
2
- import sys
3
- from typing import Any, Dict, List, NewType, Optional, Tuple, cast
4
-
5
- from instructor import OpenAISchema
6
- from json_repair import repair_json
7
- from rich.panel import Panel
8
-
9
- from .config import cfg
10
- from .console import get_console
11
- from .const import FUNCTIONS_DIR
12
- from .schemas import ToolCall
13
-
14
- console = get_console()
15
-
16
- FunctionName = NewType("FunctionName", str)
17
-
18
-
19
- class Function:
20
- """Function description class"""
21
-
22
- def __init__(self, function: type[OpenAISchema]):
23
- self.name = function.openai_schema["name"]
24
- self.description = function.openai_schema.get("description", "")
25
- self.parameters = function.openai_schema.get("parameters", {})
26
- self.execute = function.execute # type: ignore
27
-
28
-
29
- _func_name_map: Optional[dict[FunctionName, Function]] = None
30
-
31
-
32
- def get_func_name_map() -> dict[FunctionName, Function]:
33
- """Get function name map"""
34
- global _func_name_map
35
- if _func_name_map:
36
- return _func_name_map
37
- if not FUNCTIONS_DIR.exists():
38
- FUNCTIONS_DIR.mkdir(parents=True, exist_ok=True)
39
- return {}
40
- functions = []
41
- for file in FUNCTIONS_DIR.glob("*.py"):
42
- if file.name.startswith("_"):
43
- continue
44
- module_name = str(file).replace("/", ".").rstrip(".py")
45
- spec = importlib.util.spec_from_file_location(module_name, str(file))
46
- module = importlib.util.module_from_spec(spec) # type: ignore
47
- sys.modules[module_name] = module
48
- spec.loader.exec_module(module) # type: ignore
49
-
50
- if not issubclass(module.Function, OpenAISchema):
51
- raise TypeError(f"Function {module_name} must be a subclass of instructor.OpenAISchema")
52
- if not hasattr(module.Function, "execute"):
53
- raise TypeError(f"Function {module_name} must have an 'execute' classmethod")
54
-
55
- # Add to function list
56
- functions.append(Function(function=module.Function))
57
-
58
- # Cache the function list
59
- _func_name_map = {FunctionName(func.name): func for func in functions}
60
- return _func_name_map
61
-
62
-
63
- def list_functions() -> list[Function]:
64
- """List all available buildin functions"""
65
- global _func_name_map
66
- if not _func_name_map:
67
- _func_name_map = get_func_name_map()
68
-
69
- return list(_func_name_map.values())
70
-
71
-
72
- def get_function(name: FunctionName) -> Function:
73
- """Get a function by name
74
-
75
- Args:
76
- name: Function name
77
-
78
- Returns:
79
- Function execute method
80
-
81
- Raises:
82
- ValueError: If function not found
83
- """
84
- func_map = get_func_name_map()
85
- if name in func_map:
86
- return func_map[FunctionName(name)]
87
- raise ValueError(f"Function {name!r} not found")
88
-
89
-
90
- def get_openai_schemas() -> List[Dict[str, Any]]:
91
- """Get OpenAI-compatible function schemas
92
-
93
- Returns:
94
- List of function schemas in OpenAI format
95
- """
96
- transformed_schemas = []
97
- for function in list_functions():
98
- schema = {
99
- "type": "function",
100
- "function": {
101
- "name": function.name,
102
- "description": function.description,
103
- "parameters": function.parameters,
104
- },
105
- }
106
- transformed_schemas.append(schema)
107
- return transformed_schemas
108
-
109
-
110
- def execute_tool_call(tool_call: ToolCall) -> Tuple[str, bool]:
111
- """Execute a tool call and return the result
112
-
113
- Args:
114
- tool_call: The tool call to execute
115
-
116
- Returns:
117
- Tuple[str, bool]: (result text, success flag)
118
- """
119
- console.print(f"@Function call: {tool_call.name}({tool_call.arguments})", style="blue")
120
-
121
- # 1. Get the function
122
- try:
123
- function = get_function(FunctionName(tool_call.name))
124
- except ValueError as e:
125
- error_msg = f"Function '{tool_call.name!r}' not exists: {e}"
126
- console.print(error_msg, style="red")
127
- return error_msg, False
128
-
129
- # 2. Parse function arguments
130
- try:
131
- arguments = repair_json(tool_call.arguments, return_objects=True)
132
- if not isinstance(arguments, dict):
133
- error_msg = f"Invalid arguments type: {arguments!r}, should be JSON object"
134
- console.print(error_msg, style="red")
135
- return error_msg, False
136
- arguments = cast(dict, arguments)
137
- except Exception as e:
138
- error_msg = f"Invalid arguments from llm: {e}\nRaw arguments: {tool_call.arguments!r}"
139
- console.print(error_msg, style="red")
140
- return error_msg, False
141
-
142
- # 3. Execute the function
143
- try:
144
- function_result = function.execute(**arguments)
145
- if cfg["SHOW_FUNCTION_OUTPUT"]:
146
- panel = Panel(
147
- function_result,
148
- title="Function output",
149
- title_align="left",
150
- expand=False,
151
- border_style="blue",
152
- style="dim",
153
- )
154
- console.print(panel)
155
- return function_result, True
156
- except Exception as e:
157
- error_msg = f"Call function error: {e}\nFunction name: {tool_call.name!r}\nArguments: {arguments!r}"
158
- console.print(error_msg, style="red")
159
- return error_msg, False
File without changes