Skip to content

Commit afb24b4

Browse files
committed
feat: add enhanced API key validation functions
1 parent 76392b5 commit afb24b4

File tree

5 files changed

+1084
-0
lines changed

5 files changed

+1084
-0
lines changed

bin/gradient-cli

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Gradient CLI Tool
4+
5+
A command-line interface for common Gradient operations.
6+
"""
7+
8+
import argparse
9+
import json
10+
import sys
11+
from pathlib import Path
12+
from typing import Optional
13+
14+
try:
15+
from gradient import Gradient
16+
from gradient._utils import (
17+
validate_api_key,
18+
validate_client_credentials,
19+
validate_client_instance,
20+
get_available_models,
21+
is_model_available,
22+
get_model_info,
23+
)
24+
except ImportError as e:
25+
print(f"Error importing gradient: {e}")
26+
print("Make sure gradient is installed and PYTHONPATH is set correctly")
27+
sys.exit(1)
28+
29+
30+
def create_client(access_token: Optional[str] = None,
31+
model_key: Optional[str] = None,
32+
agent_key: Optional[str] = None,
33+
agent_endpoint: Optional[str] = None) -> Gradient:
34+
"""Create and validate a Gradient client."""
35+
try:
36+
client = Gradient(
37+
access_token=access_token,
38+
model_access_key=model_key,
39+
agent_access_key=agent_key,
40+
agent_endpoint=agent_endpoint,
41+
)
42+
validate_client_instance(client)
43+
return client
44+
except Exception as e:
45+
print(f"Error creating client: {e}")
46+
sys.exit(1)
47+
48+
49+
def cmd_validate(args):
50+
"""Validate API keys and client configuration."""
51+
print("🔍 Validating API keys and client configuration...")
52+
53+
# Validate individual keys
54+
if args.access_token:
55+
if validate_api_key(args.access_token):
56+
print("✅ Access token format is valid")
57+
else:
58+
print("❌ Access token format is invalid")
59+
return
60+
61+
if args.model_key:
62+
if validate_api_key(args.model_key):
63+
print("✅ Model access key format is valid")
64+
else:
65+
print("❌ Model access key format is invalid")
66+
return
67+
68+
if args.agent_key:
69+
if validate_api_key(args.agent_key):
70+
print("✅ Agent access key format is valid")
71+
else:
72+
print("❌ Agent access key format is invalid")
73+
return
74+
75+
# Validate client credentials
76+
try:
77+
validate_client_credentials(
78+
access_token=args.access_token,
79+
model_access_key=args.model_key,
80+
agent_access_key=args.agent_key,
81+
agent_endpoint=args.agent_endpoint
82+
)
83+
print("✅ Client credentials validation passed")
84+
except ValueError as e:
85+
print(f"❌ Client credentials validation failed: {e}")
86+
return
87+
88+
# Test client creation
89+
try:
90+
client = create_client(args.access_token, args.model_key, args.agent_key, args.agent_endpoint)
91+
print("✅ Client instance created and validated successfully")
92+
except Exception as e:
93+
print(f"❌ Client creation failed: {e}")
94+
95+
96+
def cmd_models(args):
97+
"""List and query available models."""
98+
print("🤖 Available Models:")
99+
100+
models = get_available_models()
101+
for model in models:
102+
status = "✅" if is_model_available(model) else "❌"
103+
print(f" {status} {model}")
104+
105+
if args.info:
106+
print(f"\n📋 Detailed info for '{args.info}':")
107+
info = get_model_info(args.info)
108+
if info:
109+
print(json.dumps(info, indent=2))
110+
else:
111+
print(f"❌ Model '{args.info}' not found")
112+
113+
114+
def cmd_test_connection(args):
115+
"""Test connection to Gradient services."""
116+
print("🔌 Testing connection to Gradient services...")
117+
118+
client = create_client(args.access_token, args.model_key, args.agent_key, args.agent_endpoint)
119+
120+
# Test basic connectivity by trying to get models
121+
try:
122+
# This would normally make an API call, but we'll use our cached models for now
123+
models = get_available_models()
124+
print(f"✅ Connection successful - {len(models)} models available")
125+
except Exception as e:
126+
print(f"❌ Connection test failed: {e}")
127+
128+
129+
def cmd_chat(args):
130+
"""Simple chat interface for testing."""
131+
print("💬 Gradient Chat Interface")
132+
print("Type 'quit' or 'exit' to end the conversation")
133+
print("-" * 50)
134+
135+
client = create_client(args.access_token, args.model_key, args.agent_key, args.agent_endpoint)
136+
137+
if not client.model_access_key:
138+
print("❌ Model access key required for chat functionality")
139+
return
140+
141+
messages = []
142+
143+
while True:
144+
try:
145+
user_input = input("\nYou: ").strip()
146+
if user_input.lower() in ['quit', 'exit', 'q']:
147+
print("👋 Goodbye!")
148+
break
149+
150+
if not user_input:
151+
continue
152+
153+
messages.append({"role": "user", "content": user_input})
154+
155+
print("🤖 Assistant: ", end="", flush=True)
156+
157+
# For streaming responses
158+
if args.stream:
159+
response = client.chat.completions.create(
160+
messages=messages,
161+
model=args.model or "llama3.3-70b-instruct",
162+
stream=True
163+
)
164+
165+
full_response = ""
166+
for chunk in response:
167+
if chunk.choices and chunk.choices[0].delta and chunk.choices[0].delta.content:
168+
content = chunk.choices[0].delta.content
169+
print(content, end="", flush=True)
170+
full_response += content
171+
172+
messages.append({"role": "assistant", "content": full_response})
173+
print() # New line after streaming
174+
175+
else:
176+
response = client.chat.completions.create(
177+
messages=messages,
178+
model=args.model or "llama3.3-70b-instruct",
179+
stream=False
180+
)
181+
182+
if response.choices and response.choices[0].message:
183+
content = response.choices[0].message.content
184+
print(content)
185+
messages.append({"role": "assistant", "content": content})
186+
187+
except KeyboardInterrupt:
188+
print("\n👋 Goodbye!")
189+
break
190+
except Exception as e:
191+
print(f"❌ Error: {e}")
192+
193+
194+
def main():
195+
"""Main CLI entry point."""
196+
parser = argparse.ArgumentParser(
197+
description="Gradient CLI - Command-line interface for Gradient AI operations",
198+
formatter_class=argparse.RawDescriptionHelpFormatter,
199+
epilog="""
200+
Examples:
201+
# Validate API keys
202+
gradient-cli validate --access-token sk-1234567890abcdef
203+
204+
# List available models
205+
gradient-cli models
206+
207+
# Get model info
208+
gradient-cli models --info llama3.3-70b-instruct
209+
210+
# Test connection
211+
gradient-cli test-connection --access-token sk-1234567890abcdef
212+
213+
# Start chat interface
214+
gradient-cli chat --model-key grad-1234567890abcdef --model llama3.3-70b-instruct
215+
"""
216+
)
217+
218+
parser.add_argument(
219+
"--access-token",
220+
help="DigitalOcean access token"
221+
)
222+
223+
parser.add_argument(
224+
"--model-key",
225+
help="Gradient model access key"
226+
)
227+
228+
parser.add_argument(
229+
"--agent-key",
230+
help="Gradient agent access key"
231+
)
232+
233+
parser.add_argument(
234+
"--agent-endpoint",
235+
help="Agent endpoint URL"
236+
)
237+
238+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
239+
240+
# Validate command
241+
validate_parser = subparsers.add_parser(
242+
"validate",
243+
help="Validate API keys and client configuration"
244+
)
245+
246+
# Models command
247+
models_parser = subparsers.add_parser(
248+
"models",
249+
help="List and query available models"
250+
)
251+
models_parser.add_argument(
252+
"--info",
253+
help="Get detailed information about a specific model"
254+
)
255+
256+
# Test connection command
257+
test_parser = subparsers.add_parser(
258+
"test-connection",
259+
help="Test connection to Gradient services"
260+
)
261+
262+
# Chat command
263+
chat_parser = subparsers.add_parser(
264+
"chat",
265+
help="Start an interactive chat session"
266+
)
267+
chat_parser.add_argument(
268+
"--model",
269+
default="llama3.3-70b-instruct",
270+
help="Model to use for chat (default: llama3.3-70b-instruct)"
271+
)
272+
chat_parser.add_argument(
273+
"--stream",
274+
action="store_true",
275+
help="Enable streaming responses"
276+
)
277+
278+
args = parser.parse_args()
279+
280+
if not args.command:
281+
parser.print_help()
282+
return
283+
284+
# Execute the appropriate command
285+
if args.command == "validate":
286+
cmd_validate(args)
287+
elif args.command == "models":
288+
cmd_models(args)
289+
elif args.command == "test-connection":
290+
cmd_test_connection(args)
291+
elif args.command == "chat":
292+
cmd_chat(args)
293+
294+
295+
if __name__ == "__main__":
296+
main()

src/gradient/_utils/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
get_required_header as get_required_header,
3030
maybe_coerce_boolean as maybe_coerce_boolean,
3131
maybe_coerce_integer as maybe_coerce_integer,
32+
validate_api_key as validate_api_key,
33+
validate_client_credentials as validate_client_credentials,
34+
validate_client_instance as validate_client_instance,
3235
)
3336
from ._compat import (
3437
get_args as get_args,

0 commit comments

Comments
 (0)