yaicli 0.5.6__py3-none-any.whl → 0.5.7__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.
- pyproject.toml +1 -1
- yaicli/client.py +6 -0
- yaicli/config.py +17 -17
- yaicli/const.py +8 -0
- {yaicli-0.5.6.dist-info → yaicli-0.5.7.dist-info}/METADATA +28 -1
- {yaicli-0.5.6.dist-info → yaicli-0.5.7.dist-info}/RECORD +9 -9
- {yaicli-0.5.6.dist-info → yaicli-0.5.7.dist-info}/WHEEL +0 -0
- {yaicli-0.5.6.dist-info → yaicli-0.5.7.dist-info}/entry_points.txt +0 -0
- {yaicli-0.5.6.dist-info → yaicli-0.5.7.dist-info}/licenses/LICENSE +0 -0
pyproject.toml
CHANGED
yaicli/client.py
CHANGED
@@ -46,6 +46,8 @@ class LitellmClient:
|
|
46
46
|
def __post_init__(self) -> None:
|
47
47
|
"""Initialize OpenAI client"""
|
48
48
|
self.pre_tool_call_id = None
|
49
|
+
if cfg["PROVIDER"] == "openrouter":
|
50
|
+
cfg["EXTRA_HEADERS"].update({"X-Title": "Yaicli", "HTTP-Referer": "https://github.com/belingud/yaicli"})
|
49
51
|
|
50
52
|
def _convert_messages(self, messages: List[ChatMessage]) -> List[Dict[str, Any]]:
|
51
53
|
"""Convert message format to OpenAI API required format"""
|
@@ -135,6 +137,10 @@ class LitellmClient:
|
|
135
137
|
}
|
136
138
|
|
137
139
|
# Add optional parameters
|
140
|
+
if cfg["EXTRA_HEADERS"]:
|
141
|
+
params["extra_headers"] = cfg["EXTRA_HEADERS"]
|
142
|
+
if cfg["EXTRA_BODY"]:
|
143
|
+
params["extra_body"] = cfg["EXTRA_BODY"]
|
138
144
|
if cfg["ENABLE_FUNCTIONS"]:
|
139
145
|
params["tools"] = self._convert_functions(list_functions())
|
140
146
|
params["tool_choice"] = "auto"
|
yaicli/config.py
CHANGED
@@ -2,7 +2,8 @@ import configparser
|
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from functools import lru_cache
|
4
4
|
from os import getenv
|
5
|
-
|
5
|
+
import json
|
6
|
+
from typing import Optional
|
6
7
|
|
7
8
|
from rich import get_console
|
8
9
|
from rich.console import Console
|
@@ -70,17 +71,12 @@ class Config(dict):
|
|
70
71
|
self._load_from_env()
|
71
72
|
self._apply_type_conversion()
|
72
73
|
|
73
|
-
def _load_defaults(self) ->
|
74
|
-
"""Load default configuration values as strings.
|
75
|
-
|
76
|
-
Returns:
|
77
|
-
Dictionary with default configuration values
|
78
|
-
"""
|
74
|
+
def _load_defaults(self) -> None:
|
75
|
+
"""Load default configuration values as strings."""
|
79
76
|
defaults = {k: v["value"] for k, v in DEFAULT_CONFIG_MAP.items()}
|
80
77
|
self.update(defaults)
|
81
|
-
return defaults
|
82
78
|
|
83
|
-
def _ensure_version_updated_config_keys(self):
|
79
|
+
def _ensure_version_updated_config_keys(self) -> None:
|
84
80
|
"""Ensure configuration keys added in version updates exist in the config file.
|
85
81
|
Appends missing keys to the config file if they don't exist.
|
86
82
|
"""
|
@@ -133,7 +129,7 @@ class Config(dict):
|
|
133
129
|
Updates the configuration dictionary in-place with properly typed values.
|
134
130
|
Falls back to default values if conversion fails.
|
135
131
|
"""
|
136
|
-
|
132
|
+
default_values_map = {k: v["value"] for k, v in DEFAULT_CONFIG_MAP.items()}
|
137
133
|
|
138
134
|
for key, config_info in DEFAULT_CONFIG_MAP.items():
|
139
135
|
target_type = config_info["type"]
|
@@ -142,25 +138,29 @@ class Config(dict):
|
|
142
138
|
|
143
139
|
try:
|
144
140
|
if raw_value is None:
|
145
|
-
raw_value =
|
141
|
+
raw_value = default_values_map.get(key, "")
|
146
142
|
if target_type is bool:
|
147
143
|
converted_value = str2bool(raw_value)
|
148
144
|
elif target_type in (int, float, str):
|
149
145
|
converted_value = target_type(raw_value)
|
150
|
-
|
146
|
+
elif target_type is dict and raw_value:
|
147
|
+
converted_value = json.loads(raw_value)
|
148
|
+
except (ValueError, TypeError, json.JSONDecodeError) as e:
|
151
149
|
self.console.print(
|
152
150
|
f"[yellow]Warning:[/] Invalid value '{raw_value}' for '{key}'. "
|
153
|
-
f"Expected type '{target_type.__name__}'. Using default value '{
|
151
|
+
f"Expected type '{target_type.__name__}'. Using default value '{default_values_map[key]}'. Error: {e}",
|
154
152
|
style="dim",
|
155
153
|
justify=self["JUSTIFY"],
|
156
154
|
)
|
157
155
|
# Fallback to default string value if conversion fails
|
158
156
|
try:
|
159
157
|
if target_type is bool:
|
160
|
-
converted_value = str2bool(
|
161
|
-
|
162
|
-
converted_value = target_type(
|
163
|
-
|
158
|
+
converted_value = str2bool(default_values_map[key])
|
159
|
+
elif target_type in (int, float, str):
|
160
|
+
converted_value = target_type(default_values_map[key])
|
161
|
+
elif target_type is dict:
|
162
|
+
converted_value = json.loads(default_values_map[key])
|
163
|
+
except (ValueError, TypeError, json.JSONDecodeError):
|
164
164
|
# If default also fails (unlikely), keep the raw merged value or a sensible default
|
165
165
|
self.console.print(
|
166
166
|
f"[red]Error:[/red] Could not convert default value for '{key}'. Using raw value.",
|
yaicli/const.py
CHANGED
@@ -51,6 +51,8 @@ DEFAULT_MAX_HISTORY: int = 500
|
|
51
51
|
DEFAULT_AUTO_SUGGEST: BOOL_STR = "true"
|
52
52
|
DEFAULT_SHOW_REASONING: BOOL_STR = "true"
|
53
53
|
DEFAULT_TIMEOUT: int = 60
|
54
|
+
DEFAULT_EXTRA_HEADERS: str = "{}"
|
55
|
+
DEFAULT_EXTRA_BODY: str = "{}"
|
54
56
|
DEFAULT_INTERACTIVE_ROUND: int = 25
|
55
57
|
DEFAULT_CHAT_HISTORY_DIR: Path = Path(gettempdir()) / "yaicli/chats"
|
56
58
|
DEFAULT_MAX_SAVED_CHATS = 20
|
@@ -130,6 +132,8 @@ DEFAULT_CONFIG_MAP = {
|
|
130
132
|
"TOP_P": {"value": DEFAULT_TOP_P, "env_key": "YAI_TOP_P", "type": float},
|
131
133
|
"MAX_TOKENS": {"value": DEFAULT_MAX_TOKENS, "env_key": "YAI_MAX_TOKENS", "type": int},
|
132
134
|
"TIMEOUT": {"value": DEFAULT_TIMEOUT, "env_key": "YAI_TIMEOUT", "type": int},
|
135
|
+
"EXTRA_HEADERS": {"value": DEFAULT_EXTRA_HEADERS, "env_key": "YAI_EXTRA_HEADERS", "type": dict},
|
136
|
+
"EXTRA_BODY": {"value": DEFAULT_EXTRA_BODY, "env_key": "YAI_EXTRA_BODY", "type": dict},
|
133
137
|
"REASONING_EFFORT": {"value": DEFAULT_REASONING_EFFORT, "env_key": "YAI_REASONING_EFFORT", "type": str},
|
134
138
|
"INTERACTIVE_ROUND": {
|
135
139
|
"value": DEFAULT_INTERACTIVE_ROUND,
|
@@ -174,6 +178,10 @@ TEMPERATURE={DEFAULT_CONFIG_MAP["TEMPERATURE"]["value"]}
|
|
174
178
|
TOP_P={DEFAULT_CONFIG_MAP["TOP_P"]["value"]}
|
175
179
|
MAX_TOKENS={DEFAULT_CONFIG_MAP["MAX_TOKENS"]["value"]}
|
176
180
|
TIMEOUT={DEFAULT_CONFIG_MAP["TIMEOUT"]["value"]}
|
181
|
+
# json string
|
182
|
+
EXTRA_HEADERS=
|
183
|
+
# json string
|
184
|
+
EXTRA_BODY=
|
177
185
|
REASONING_EFFORT=
|
178
186
|
|
179
187
|
# Interactive mode parameters
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: yaicli
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.7
|
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
|
@@ -392,6 +392,9 @@ SHOW_FUNCTION_OUTPUT=true
|
|
392
392
|
| `OS_NAME` | Operating system | `auto` | `YAI_OS_NAME` |
|
393
393
|
| `STREAM` | Enable streaming | `true` | `YAI_STREAM` |
|
394
394
|
| `TIMEOUT` | API timeout (seconds) | `60` | `YAI_TIMEOUT` |
|
395
|
+
| `EXTRA_HEADERS` | Extra headers | - | `YAI_EXTRA_HEADERS` |
|
396
|
+
| `EXTRA_BODY` | Extra body | - | `YAI_EXTRA_BODY` |
|
397
|
+
| `REASONING_EFFORT` | Reasoning effort | - | `YAI_REASONING_EFFORT` |
|
395
398
|
| `INTERACTIVE_ROUND` | Interactive mode rounds | `25` | `YAI_INTERACTIVE_ROUND` |
|
396
399
|
| `CODE_THEME` | Syntax highlighting theme | `monokai` | `YAI_CODE_THEME` |
|
397
400
|
| `TEMPERATURE` | Response randomness | `0.7` | `YAI_TEMPERATURE` |
|
@@ -449,6 +452,28 @@ Browse available themes at: https://pygments.org/styles/
|
|
449
452
|
|
450
453
|

|
451
454
|
|
455
|
+
### Extra Headers and Body
|
456
|
+
|
457
|
+
You can add extra headers and body to the API request by setting `EXTRA_HEADERS` and `EXTRA_BODY` in the config file.
|
458
|
+
The value should be valid json string.
|
459
|
+
|
460
|
+
```ini
|
461
|
+
EXTRA_HEADERS={"X-Extra-Header": "value"}
|
462
|
+
EXTRA_BODY={"extra_key": "extra_value"}
|
463
|
+
```
|
464
|
+
|
465
|
+
Example: If you want to disable Qwen3's thinking behavior, you can add the following to the config file.
|
466
|
+
|
467
|
+
```ini
|
468
|
+
EXTRA_BODY={"enable_thinking": false}
|
469
|
+
```
|
470
|
+
|
471
|
+
Or just limit thinking tokens:
|
472
|
+
|
473
|
+
```ini
|
474
|
+
EXTRA_BODY={"thinking_budget": 4096}
|
475
|
+
```
|
476
|
+
|
452
477
|
## 🚀 Usage
|
453
478
|
|
454
479
|
### Quick Start
|
@@ -904,6 +929,8 @@ YAICLI is designed with a modular architecture that separates concerns and makes
|
|
904
929
|
| [Typer](https://typer.tiangolo.com/) | Command-line interface with type hints |
|
905
930
|
| [Rich](https://rich.readthedocs.io/) | Terminal formatting and beautiful display |
|
906
931
|
| [prompt_toolkit](https://python-prompt-toolkit.readthedocs.io/) | Interactive input with history and auto-completion |
|
932
|
+
| [litellm](https://litellm.ai/) | LLM provider compatibility |
|
933
|
+
| [json-repair](https://github.com/mangiucugna/json_repair) | Repair llm function call arguments |
|
907
934
|
|
908
935
|
## 👨💻 Contributing
|
909
936
|
|
@@ -1,11 +1,11 @@
|
|
1
|
-
pyproject.toml,sha256=
|
1
|
+
pyproject.toml,sha256=PCKvDYSn9V2qnxplRgsrbYZfcPjEzj1PvguJVwEtDo0,1963
|
2
2
|
yaicli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
yaicli/chat.py,sha256=DeTmOeBPU-oiOAIaDj2h-auJor0GyVVhrViLYF6zGIM,13638
|
4
4
|
yaicli/cli.py,sha256=1Flt0FgrKzbabjJpZJCcvnUjXaaLwyD2paRyMixEQV0,22985
|
5
|
-
yaicli/client.py,sha256=
|
6
|
-
yaicli/config.py,sha256=
|
5
|
+
yaicli/client.py,sha256=PzfoW0lZ2QHxt2IBLGl-l6CGpq98MsxPiag0QxwRKsw,16565
|
6
|
+
yaicli/config.py,sha256=65k7gERkOIJ5q4GN-CU7VYZgupShFgsMHT0eWPtCh_U,6535
|
7
7
|
yaicli/console.py,sha256=vARPJd-3lafutsQWrGntQVjLrYqaJD3qisN82pmuhjU,1973
|
8
|
-
yaicli/const.py,sha256=
|
8
|
+
yaicli/const.py,sha256=47I8I5hkJmLtPAhmesMvg7sydDSG_MB94BoRPtdBrUg,8442
|
9
9
|
yaicli/entry.py,sha256=gKzN8Yar3tpBd2Z2a80gD3k0W4Sf3lL7jdyws-2y-H0,8687
|
10
10
|
yaicli/exceptions.py,sha256=WBYg8OTJJzaj7lt6HE7ZyBoe5T6A3yZRNCRfWd4iN0c,372
|
11
11
|
yaicli/history.py,sha256=s-57X9FMsaQHF7XySq1gGH_jpd_cHHTYafYu2ECuG6M,2472
|
@@ -17,8 +17,8 @@ yaicli/tools.py,sha256=d-5LXbEB-1Uq5VKSgwlAiNDVOGrHkku2DpmZoorq1zw,3098
|
|
17
17
|
yaicli/utils.py,sha256=bpo3Xhozpxsaci3FtEIKZ32l4ZdyWMsrHjYGX0tB4J4,4541
|
18
18
|
yaicli/functions/__init__.py,sha256=_FJooQ9GkijG8xLwuU0cr5GBrGnC9Nc6bnCeUjrsT0k,1271
|
19
19
|
yaicli/functions/buildin/execute_shell_command.py,sha256=unl1-F8p6QZajeHdA0u5UpURMJM0WhdWMUWCCCHVRcI,1320
|
20
|
-
yaicli-0.5.
|
21
|
-
yaicli-0.5.
|
22
|
-
yaicli-0.5.
|
23
|
-
yaicli-0.5.
|
24
|
-
yaicli-0.5.
|
20
|
+
yaicli-0.5.7.dist-info/METADATA,sha256=VCCVoup7CdV0bKytlc9UtO2tLtAePXbm9faHoYZHRJo,50349
|
21
|
+
yaicli-0.5.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
22
|
+
yaicli-0.5.7.dist-info/entry_points.txt,sha256=iYVyQP0PJIm9tQnlQheqT435kK_xdGoi5j9aswGV9hA,66
|
23
|
+
yaicli-0.5.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
24
|
+
yaicli-0.5.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|