tunacode-cli 0.0.70__py3-none-any.whl → 0.0.71__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.
Potentially problematic release.
This version of tunacode-cli might be problematic. Click here for more details.
- tunacode/cli/main.py +2 -1
- tunacode/constants.py +1 -1
- tunacode/core/setup/config_setup.py +20 -4
- tunacode/utils/api_key_validation.py +93 -0
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.71.dist-info}/METADATA +2 -2
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.71.dist-info}/RECORD +9 -8
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.71.dist-info}/WHEEL +0 -0
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.71.dist-info}/entry_points.txt +0 -0
- {tunacode_cli-0.0.70.dist-info → tunacode_cli-0.0.71.dist-info}/licenses/LICENSE +0 -0
tunacode/cli/main.py
CHANGED
|
@@ -77,7 +77,8 @@ def main(
|
|
|
77
77
|
from tunacode.exceptions import ConfigurationError
|
|
78
78
|
|
|
79
79
|
if isinstance(e, ConfigurationError):
|
|
80
|
-
#
|
|
80
|
+
# Display the configuration error message
|
|
81
|
+
await ui.error(str(e))
|
|
81
82
|
update_task.cancel() # Cancel the update check
|
|
82
83
|
return
|
|
83
84
|
import traceback
|
tunacode/constants.py
CHANGED
|
@@ -16,6 +16,7 @@ from tunacode.exceptions import ConfigurationError
|
|
|
16
16
|
from tunacode.types import ConfigFile, ConfigPath, UserConfig
|
|
17
17
|
from tunacode.ui import console as ui
|
|
18
18
|
from tunacode.utils import system, user_configuration
|
|
19
|
+
from tunacode.utils.api_key_validation import validate_api_key_for_model
|
|
19
20
|
from tunacode.utils.text_utils import key_to_title
|
|
20
21
|
|
|
21
22
|
|
|
@@ -138,11 +139,15 @@ class ConfigSetup(BaseSetup):
|
|
|
138
139
|
)
|
|
139
140
|
)
|
|
140
141
|
|
|
141
|
-
#
|
|
142
|
+
# Validate API key exists for the selected model
|
|
143
|
+
model = self.state_manager.session.user_config["default_model"]
|
|
144
|
+
is_valid, error_msg = validate_api_key_for_model(
|
|
145
|
+
model, self.state_manager.session.user_config
|
|
146
|
+
)
|
|
147
|
+
if not is_valid:
|
|
148
|
+
raise ConfigurationError(error_msg)
|
|
142
149
|
|
|
143
|
-
self.state_manager.session.current_model =
|
|
144
|
-
"default_model"
|
|
145
|
-
]
|
|
150
|
+
self.state_manager.session.current_model = model
|
|
146
151
|
|
|
147
152
|
async def validate(self) -> bool:
|
|
148
153
|
"""Validate that configuration is properly set up."""
|
|
@@ -152,6 +157,17 @@ class ConfigSetup(BaseSetup):
|
|
|
152
157
|
valid = False
|
|
153
158
|
elif not self.state_manager.session.user_config.get("default_model"):
|
|
154
159
|
valid = False
|
|
160
|
+
else:
|
|
161
|
+
# Validate API key exists for the selected model
|
|
162
|
+
model = self.state_manager.session.user_config.get("default_model")
|
|
163
|
+
is_valid, error_msg = validate_api_key_for_model(
|
|
164
|
+
model, self.state_manager.session.user_config
|
|
165
|
+
)
|
|
166
|
+
if not is_valid:
|
|
167
|
+
valid = False
|
|
168
|
+
# Store error message for later use
|
|
169
|
+
setattr(self.state_manager, "_config_error", error_msg)
|
|
170
|
+
|
|
155
171
|
# Cache result for fastpath
|
|
156
172
|
if valid:
|
|
157
173
|
setattr(self.state_manager, "_config_valid", True)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module: tunacode.utils.api_key_validation
|
|
3
|
+
|
|
4
|
+
Utilities for validating API keys are configured for the selected model.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, Tuple
|
|
8
|
+
|
|
9
|
+
from tunacode.types import UserConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_required_api_key_for_model(model: str) -> Tuple[Optional[str], str]:
|
|
13
|
+
"""
|
|
14
|
+
Determine which API key is required for a given model.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
model: Model identifier in format "provider:model-name"
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Tuple of (api_key_name, provider_name) or (None, "unknown") if no specific key required
|
|
21
|
+
"""
|
|
22
|
+
if not model or ":" not in model:
|
|
23
|
+
return None, "unknown"
|
|
24
|
+
|
|
25
|
+
provider = model.split(":")[0].lower()
|
|
26
|
+
|
|
27
|
+
# Map providers to their required API keys
|
|
28
|
+
provider_key_map = {
|
|
29
|
+
"openrouter": ("OPENROUTER_API_KEY", "OpenRouter"),
|
|
30
|
+
"openai": ("OPENAI_API_KEY", "OpenAI"),
|
|
31
|
+
"anthropic": ("ANTHROPIC_API_KEY", "Anthropic"),
|
|
32
|
+
"google": ("GEMINI_API_KEY", "Google"),
|
|
33
|
+
"google-gla": ("GEMINI_API_KEY", "Google"),
|
|
34
|
+
"gemini": ("GEMINI_API_KEY", "Google"),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return provider_key_map.get(provider, (None, provider))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def validate_api_key_for_model(model: str, user_config: UserConfig) -> Tuple[bool, Optional[str]]:
|
|
41
|
+
"""
|
|
42
|
+
Check if the required API key exists for the given model.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
model: Model identifier in format "provider:model-name"
|
|
46
|
+
user_config: User configuration containing env variables
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Tuple of (is_valid, error_message)
|
|
50
|
+
"""
|
|
51
|
+
api_key_name, provider_name = get_required_api_key_for_model(model)
|
|
52
|
+
|
|
53
|
+
if not api_key_name:
|
|
54
|
+
# No specific API key required (might be custom endpoint)
|
|
55
|
+
return True, None
|
|
56
|
+
|
|
57
|
+
env_config = user_config.get("env", {})
|
|
58
|
+
api_key = env_config.get(api_key_name, "").strip()
|
|
59
|
+
|
|
60
|
+
if not api_key:
|
|
61
|
+
return False, (
|
|
62
|
+
f"No API key found for {provider_name}.\n"
|
|
63
|
+
f"Please run 'tunacode --setup' to configure your API key."
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return True, None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_configured_providers(user_config: UserConfig) -> list[str]:
|
|
70
|
+
"""
|
|
71
|
+
Get list of providers that have API keys configured.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
user_config: User configuration containing env variables
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
List of provider names that have API keys set
|
|
78
|
+
"""
|
|
79
|
+
env_config = user_config.get("env", {})
|
|
80
|
+
configured = []
|
|
81
|
+
|
|
82
|
+
provider_map = {
|
|
83
|
+
"OPENROUTER_API_KEY": "openrouter",
|
|
84
|
+
"OPENAI_API_KEY": "openai",
|
|
85
|
+
"ANTHROPIC_API_KEY": "anthropic",
|
|
86
|
+
"GEMINI_API_KEY": "google",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for key_name, provider in provider_map.items():
|
|
90
|
+
if env_config.get(key_name, "").strip():
|
|
91
|
+
configured.append(provider)
|
|
92
|
+
|
|
93
|
+
return configured
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tunacode-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.71
|
|
4
4
|
Summary: Your agentic CLI developer.
|
|
5
5
|
Project-URL: Homepage, https://tunacode.xyz/
|
|
6
6
|
Project-URL: Repository, https://github.com/alchemiststudiosDOTai/tunacode
|
|
@@ -100,7 +100,7 @@ See the [Hatch Build System Guide](documentation/development/hatch-build-system.
|
|
|
100
100
|
|
|
101
101
|
## Configuration
|
|
102
102
|
|
|
103
|
-
Choose your AI provider and set your API key. For more details, see the [Configuration Section](documentation/user/getting-started.md#2-configuration) in the Getting Started Guide.
|
|
103
|
+
Choose your AI provider and set your API key. For more details, see the [Configuration Section](documentation/user/getting-started.md#2-configuration) in the Getting Started Guide. For local models (LM Studio, Ollama, etc.), see the [Local Models Setup Guide](documentation/configuration/local-models.md).
|
|
104
104
|
|
|
105
105
|
### Recommended Models
|
|
106
106
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
tunacode/__init__.py,sha256=yUul8igNYMfUrHnYfioIGAqvrH8b5BKiO_pt1wVnmd0,119
|
|
2
|
-
tunacode/constants.py,sha256=
|
|
2
|
+
tunacode/constants.py,sha256=T9dFwi0O6ahSFKthCi5n_q1lWJGht7KAtH5fHIlwevI,6100
|
|
3
3
|
tunacode/context.py,sha256=YtfRjUiqsSkk2k9Nn_pjb_m-AXyh6XcOBOJWtFI0wVw,2405
|
|
4
4
|
tunacode/exceptions.py,sha256=m80njR-LqBXhFAEOPqCE7N2QPU4Fkjlf_f6CWKO0_Is,8479
|
|
5
5
|
tunacode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
tunacode/setup.py,sha256=F1E4zHVnbByu_Uo6AhCJ-W-lIGF_gV6kB84HLAGLmVY,2103
|
|
7
7
|
tunacode/types.py,sha256=Q3PeHB01qeaKteGDQf8Byx4q1XLSXVnNDG6D-WjWsBk,10157
|
|
8
8
|
tunacode/cli/__init__.py,sha256=zgs0UbAck8hfvhYsWhWOfBe5oK09ug2De1r4RuQZREA,55
|
|
9
|
-
tunacode/cli/main.py,sha256=
|
|
9
|
+
tunacode/cli/main.py,sha256=DEXS8ODPcsaT1MFBGALX5X7eoohMZDSg6sSW3kOgJxk,3136
|
|
10
10
|
tunacode/cli/repl.py,sha256=jhKMAff4kxt5f2ONacPao2wgcZvNr2BRBZdITh5yDro,22480
|
|
11
11
|
tunacode/cli/commands/__init__.py,sha256=J7MZofTaSgspAKP64OavPukj4l53qvkv_-sCfYEUi10,1794
|
|
12
12
|
tunacode/cli/commands/base.py,sha256=Ge_lNQA-GDfcb1Ap1oznCH3UrifBiHH3bA9DNL-tCDw,2519
|
|
@@ -68,7 +68,7 @@ tunacode/core/logging/logger.py,sha256=9RjRuX0GoUojRJ8WnJGQPFdXiluiJMCoFmvc8xEio
|
|
|
68
68
|
tunacode/core/setup/__init__.py,sha256=seoWYpRonptxNyApapS-yGz4o3jTj8vLsRPCTUO4siM,439
|
|
69
69
|
tunacode/core/setup/agent_setup.py,sha256=tpOIW85C6o1m8pwAZQBIMKxKIyBUOpHHn4JJmDBFH3Q,1403
|
|
70
70
|
tunacode/core/setup/base.py,sha256=FMjBQQS_q3KOxHqfg7NJGmKq-1nxC40htiPZprzTu7I,970
|
|
71
|
-
tunacode/core/setup/config_setup.py,sha256=
|
|
71
|
+
tunacode/core/setup/config_setup.py,sha256=sUD5Xof6onWdBa4FyxNhnFMd1K7Qrbs0dWdPMiHltw8,25166
|
|
72
72
|
tunacode/core/setup/coordinator.py,sha256=5ZhD4rHUrW0RIdGnjmoK4wCvqlNGcXal4Qwev4s039U,2393
|
|
73
73
|
tunacode/core/setup/environment_setup.py,sha256=n3IrObKEynHZSwtUJ1FddMg2C4sHz7ca42awemImV8s,2225
|
|
74
74
|
tunacode/core/setup/git_safety_setup.py,sha256=Htt8A4BAn7F4DbjhNu_SO01zjwaRQ3wMv-vZujE1-JA,7328
|
|
@@ -134,6 +134,7 @@ tunacode/ui/tool_ui.py,sha256=MVmBLXx6OTJVFLl58SpoW0KoStOrbAY9sc6XXMKgWtQ,7216
|
|
|
134
134
|
tunacode/ui/utils.py,sha256=yvoCTz8AOdRfV0XIqUX3sgg88g_wntV9yhnQP6WzAVs,114
|
|
135
135
|
tunacode/ui/validators.py,sha256=MMIMT1I2v0l2jIy-gxX_4GSApvUTi8XWIOACr_dmoBA,758
|
|
136
136
|
tunacode/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
137
|
+
tunacode/utils/api_key_validation.py,sha256=djfayP2g01d7YDVQXZUdW5ZhFtWAWw5oPhHCo_p74t0,2677
|
|
137
138
|
tunacode/utils/bm25.py,sha256=fd59YQXovC8rXwZrdoqIAfFrLn_WCVjzCh0pkU22APE,1966
|
|
138
139
|
tunacode/utils/diff_utils.py,sha256=V9QqQ0q4MfabVTnWptF3IXDp3estnfOKcJtDe_Sj14I,2372
|
|
139
140
|
tunacode/utils/file_utils.py,sha256=84g-MQRzmBI2aG_CuXsDl2OhvvWoSL7YdL5Kz_UKSwk,979
|
|
@@ -147,8 +148,8 @@ tunacode/utils/system.py,sha256=J8KqJ4ZqQrNSnM5rrJxPeMk9z2xQQp6dWtI1SKBY1-0,1112
|
|
|
147
148
|
tunacode/utils/text_utils.py,sha256=HAwlT4QMy41hr53cDbbNeNo05MI461TpI9b_xdIv8EY,7288
|
|
148
149
|
tunacode/utils/token_counter.py,sha256=dmFuqVz4ywGFdLfAi5Mg9bAGf8v87Ek-mHU-R3fsYjI,2711
|
|
149
150
|
tunacode/utils/user_configuration.py,sha256=OA-L0BgWNbf9sWpc8lyivgLscwJdpdI8TAYbe0wRs1s,4836
|
|
150
|
-
tunacode_cli-0.0.
|
|
151
|
-
tunacode_cli-0.0.
|
|
152
|
-
tunacode_cli-0.0.
|
|
153
|
-
tunacode_cli-0.0.
|
|
154
|
-
tunacode_cli-0.0.
|
|
151
|
+
tunacode_cli-0.0.71.dist-info/METADATA,sha256=wreKuVY4c3L6aTrSMHuOS-tiiq5ByGd1CaVUm1FCIgA,6898
|
|
152
|
+
tunacode_cli-0.0.71.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
153
|
+
tunacode_cli-0.0.71.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
|
|
154
|
+
tunacode_cli-0.0.71.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
|
|
155
|
+
tunacode_cli-0.0.71.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|