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 CHANGED
@@ -77,7 +77,8 @@ def main(
77
77
  from tunacode.exceptions import ConfigurationError
78
78
 
79
79
  if isinstance(e, ConfigurationError):
80
- # ConfigurationError already printed helpful message, just exit cleanly
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
@@ -9,7 +9,7 @@ from enum import Enum
9
9
 
10
10
  # Application info
11
11
  APP_NAME = "TunaCode"
12
- APP_VERSION = "0.0.70"
12
+ APP_VERSION = "0.0.71"
13
13
 
14
14
 
15
15
  # File patterns
@@ -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
- # No model validation - trust user's model choice
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 = self.state_manager.session.user_config[
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.70
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=fJ8A1kkzW2-5y4fi0kNz80jmJZflq0AGxW_Vdzn7wzE,6100
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=H4g9ilS2KmCP37lQuIOIcSG2NGGXXgj-lUU6MdfLrmI,3127
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=varmg7pLY9jw_5cnpbuL53_S6Koakb49mpObMU7UZsc,24418
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.70.dist-info/METADATA,sha256=oziDuVsyfx7OZ10yE9YaOw_lah-p7GVfant7HByB2mc,6773
151
- tunacode_cli-0.0.70.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
152
- tunacode_cli-0.0.70.dist-info/entry_points.txt,sha256=hbkytikj4dGu6rizPuAd_DGUPBGF191RTnhr9wdhORY,51
153
- tunacode_cli-0.0.70.dist-info/licenses/LICENSE,sha256=Btzdu2kIoMbdSp6OyCLupB1aRgpTCJ_szMimgEnpkkE,1056
154
- tunacode_cli-0.0.70.dist-info/RECORD,,
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,,