lyceum-cli 1.0.19__tar.gz → 1.0.21__tar.gz
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.
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/PKG-INFO +1 -1
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/auth/login.py +41 -25
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/inference/chat.py +19 -39
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cli.egg-info/PKG-INFO +1 -1
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/setup.py +1 -1
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/auth/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/execution/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/execution/python.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/inference/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/inference/batch.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/compute/inference/models.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/external/general/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/main.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/shared/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/shared/config.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/shared/display.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum/shared/streaming.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cli.egg-info/SOURCES.txt +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cli.egg-info/dependency_links.txt +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cli.egg-info/entry_points.txt +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cli.egg-info/requires.txt +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cli.egg-info/top_level.txt +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cloud_execution_api_client/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cloud_execution_api_client/api/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cloud_execution_api_client/models/__init__.py +0 -0
- {lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/setup.cfg +0 -0
|
@@ -86,13 +86,10 @@ class CallbackHandler(BaseHTTPRequestHandler):
|
|
|
86
86
|
<p class="text-sm text-gray-500">Your Lyceum CLI has been authenticated successfully and is ready to use.</p>
|
|
87
87
|
</div>
|
|
88
88
|
|
|
89
|
-
<!-- Close
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
>
|
|
94
|
-
Close Tab
|
|
95
|
-
</button>
|
|
89
|
+
<!-- Close Message -->
|
|
90
|
+
<div class="w-full py-3 px-4 bg-gray-50 text-gray-700 rounded-md border border-gray-200">
|
|
91
|
+
You can close this window now
|
|
92
|
+
</div>
|
|
96
93
|
|
|
97
94
|
<!-- Lyceum Branding -->
|
|
98
95
|
<div class="mt-8 pt-6 border-t border-gray-200">
|
|
@@ -160,13 +157,10 @@ class CallbackHandler(BaseHTTPRequestHandler):
|
|
|
160
157
|
<p class="text-gray-600">Please try again or contact support if the issue persists.</p>
|
|
161
158
|
</div>
|
|
162
159
|
|
|
163
|
-
<!-- Close
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
>
|
|
168
|
-
Close Tab
|
|
169
|
-
</button>
|
|
160
|
+
<!-- Close Message -->
|
|
161
|
+
<div class="w-full py-3 px-4 bg-gray-50 text-gray-700 rounded-md border border-gray-200">
|
|
162
|
+
You can close this window now
|
|
163
|
+
</div>
|
|
170
164
|
|
|
171
165
|
<!-- Lyceum Branding -->
|
|
172
166
|
<div class="mt-8 pt-6 border-t border-gray-200">
|
|
@@ -209,7 +203,9 @@ class CallbackHandler(BaseHTTPRequestHandler):
|
|
|
209
203
|
</div>
|
|
210
204
|
<h1 class="text-2xl font-bold text-gray-900 mb-2">Invalid Parameters</h1>
|
|
211
205
|
<p class="text-gray-600 mb-8">The authentication callback received invalid parameters.</p>
|
|
212
|
-
<
|
|
206
|
+
<div class="w-full py-3 px-4 bg-gray-50 text-gray-700 rounded-md border border-gray-200">
|
|
207
|
+
You can close this window now
|
|
208
|
+
</div>
|
|
213
209
|
</div>
|
|
214
210
|
</div>
|
|
215
211
|
</body>
|
|
@@ -244,7 +240,9 @@ class CallbackHandler(BaseHTTPRequestHandler):
|
|
|
244
240
|
</div>
|
|
245
241
|
<h1 class="text-2xl font-bold text-gray-900 mb-2">Page Not Found</h1>
|
|
246
242
|
<p class="text-gray-600 mb-8">The requested page could not be found.</p>
|
|
247
|
-
<
|
|
243
|
+
<div class="w-full py-3 px-4 bg-gray-50 text-gray-700 rounded-md border border-gray-200">
|
|
244
|
+
You can close this window now
|
|
245
|
+
</div>
|
|
248
246
|
</div>
|
|
249
247
|
</div>
|
|
250
248
|
</body>
|
|
@@ -285,7 +283,9 @@ class CallbackHandler(BaseHTTPRequestHandler):
|
|
|
285
283
|
<div class="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-md mb-8">
|
|
286
284
|
<p class="text-sm">{e}</p>
|
|
287
285
|
</div>
|
|
288
|
-
<
|
|
286
|
+
<div class="w-full py-3 px-4 bg-gray-50 text-gray-700 rounded-md border border-gray-200">
|
|
287
|
+
You can close this window now
|
|
288
|
+
</div>
|
|
289
289
|
</div>
|
|
290
290
|
</div>
|
|
291
291
|
</body>
|
|
@@ -400,16 +400,32 @@ def login(
|
|
|
400
400
|
try:
|
|
401
401
|
import httpx
|
|
402
402
|
headers = {"Authorization": f"Bearer {config.api_key}"}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
403
|
+
|
|
404
|
+
# Create client with explicit timeout and SSL verification
|
|
405
|
+
client = httpx.Client(timeout=30.0, verify=True)
|
|
406
|
+
try:
|
|
407
|
+
response = client.get(
|
|
408
|
+
f"{config.base_url}/api/v2/external/machine-types",
|
|
409
|
+
headers=headers
|
|
410
|
+
)
|
|
411
|
+
if response.status_code == 200:
|
|
412
|
+
console.print("[green]✅ Successfully authenticated![/green]")
|
|
413
|
+
if callback_result.get("user"):
|
|
414
|
+
console.print(f"[dim]Logged in as: {callback_result['user']}[/dim]")
|
|
415
|
+
else:
|
|
416
|
+
console.print(f"[red]❌ Token validation failed: HTTP {response.status_code}[/red]")
|
|
417
|
+
console.print(f"[dim]Response: {response.text}[/dim]")
|
|
418
|
+
raise typer.Exit(1)
|
|
419
|
+
finally:
|
|
420
|
+
client.close()
|
|
421
|
+
except httpx.TimeoutException as e:
|
|
422
|
+
console.print(f"[yellow]⚠️ Token validation timed out: {e}[/yellow]")
|
|
423
|
+
console.print(f"[yellow]Token saved but couldn't verify connectivity to {config.base_url}[/yellow]")
|
|
424
|
+
console.print("[dim]You can test the connection later with 'lyceum auth status'[/dim]")
|
|
425
|
+
# Don't exit with error - token was received successfully
|
|
411
426
|
except Exception as e:
|
|
412
427
|
console.print(f"[red]❌ Token validation failed: {e}[/red]")
|
|
428
|
+
console.print(f"[dim]Token saved but couldn't verify. Error type: {type(e).__name__}[/dim]")
|
|
413
429
|
raise typer.Exit(1)
|
|
414
430
|
|
|
415
431
|
elif callback_result["error"]:
|
|
@@ -167,58 +167,34 @@ def list_models():
|
|
|
167
167
|
|
|
168
168
|
@chat_app.command("image")
|
|
169
169
|
def analyze_image(
|
|
170
|
-
|
|
170
|
+
image_url: str = typer.Argument(..., help="URL of image to analyze"),
|
|
171
171
|
prompt: str = typer.Option("What do you see in this image?", "--prompt", "-p", help="Question about the image"),
|
|
172
|
-
model: str = typer.Option("
|
|
173
|
-
|
|
172
|
+
model: str = typer.Option("gpt-4-vision", "--model", "-m", help="Vision model to use"),
|
|
173
|
+
raw_output: bool = typer.Option(False, "--raw", help="Return full model response instead of just content"),
|
|
174
174
|
):
|
|
175
175
|
"""Analyze an image with AI vision models"""
|
|
176
176
|
try:
|
|
177
177
|
client = config.get_client()
|
|
178
178
|
|
|
179
|
-
# Prepare image data
|
|
180
|
-
image_url = None
|
|
181
|
-
image_data = None
|
|
182
|
-
|
|
183
|
-
if base64:
|
|
184
|
-
# Read base64 from file
|
|
185
|
-
from pathlib import Path
|
|
186
|
-
base64_path = Path(image_source)
|
|
187
|
-
if not base64_path.exists():
|
|
188
|
-
console.print(f"[red]❌ File not found: {image_source}[/red]")
|
|
189
|
-
raise typer.Exit(1)
|
|
190
|
-
|
|
191
|
-
with open(base64_path, 'r') as f:
|
|
192
|
-
image_data = f.read().strip()
|
|
193
|
-
|
|
194
|
-
console.print(f"[dim]📄 Read base64 image from {image_source} ({len(image_data)} chars)[/dim]")
|
|
195
|
-
else:
|
|
196
|
-
# Use as URL
|
|
197
|
-
image_url = image_source
|
|
198
|
-
|
|
199
179
|
# Create request payload for image analysis
|
|
200
180
|
sync_request = {
|
|
201
181
|
"model_id": model,
|
|
202
182
|
"input": {
|
|
203
183
|
"text": prompt,
|
|
184
|
+
"image_url": image_url
|
|
204
185
|
},
|
|
205
186
|
"max_tokens": 1000,
|
|
206
|
-
"temperature": 0.7
|
|
187
|
+
"temperature": 0.7,
|
|
188
|
+
"raw_output": raw_output
|
|
207
189
|
}
|
|
208
190
|
|
|
209
|
-
# Add image data
|
|
210
|
-
if image_data:
|
|
211
|
-
sync_request["input"]["image_data"] = image_data
|
|
212
|
-
else:
|
|
213
|
-
sync_request["input"]["image_url"] = image_url
|
|
214
|
-
|
|
215
191
|
console.print(f"[dim]👁️ Analyzing image with {model}...[/dim]")
|
|
216
|
-
|
|
192
|
+
|
|
217
193
|
import httpx
|
|
218
|
-
|
|
194
|
+
|
|
219
195
|
url = f"{config.base_url}/api/v2/external/sync/"
|
|
220
196
|
headers = {"Authorization": f"Bearer {config.api_key}", "Content-Type": "application/json"}
|
|
221
|
-
|
|
197
|
+
|
|
222
198
|
with httpx.Client() as http_client:
|
|
223
199
|
response = http_client.post(
|
|
224
200
|
url,
|
|
@@ -226,13 +202,17 @@ def analyze_image(
|
|
|
226
202
|
headers=headers,
|
|
227
203
|
timeout=60.0
|
|
228
204
|
)
|
|
229
|
-
|
|
205
|
+
|
|
230
206
|
if response.status_code == 200:
|
|
231
207
|
result = response.json()
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
208
|
+
|
|
209
|
+
if raw_output:
|
|
210
|
+
console.print(f"[green]✅ Raw Response:[/green]")
|
|
211
|
+
console.print(json.dumps(result.get('raw_response', result['output']), indent=2))
|
|
212
|
+
else:
|
|
213
|
+
console.print(f"[green]✅ Image Analysis:[/green]")
|
|
214
|
+
console.print(f"[cyan]{result['output']}[/cyan]")
|
|
215
|
+
|
|
236
216
|
elif response.status_code == 503:
|
|
237
217
|
console.print(f"[red]❌ Vision model {model} is not running.[/red]")
|
|
238
218
|
raise typer.Exit(1)
|
|
@@ -240,7 +220,7 @@ def analyze_image(
|
|
|
240
220
|
console.print(f"[red]❌ Error: HTTP {response.status_code}[/red]")
|
|
241
221
|
console.print(f"[red]{response.text}[/red]")
|
|
242
222
|
raise typer.Exit(1)
|
|
243
|
-
|
|
223
|
+
|
|
244
224
|
except Exception as e:
|
|
245
225
|
console.print(f"[red]❌ Error: {e}[/red]")
|
|
246
226
|
raise typer.Exit(1)
|
|
@@ -15,7 +15,7 @@ if readme_file.exists():
|
|
|
15
15
|
|
|
16
16
|
setup(
|
|
17
17
|
name="lyceum-cli",
|
|
18
|
-
version="1.0.
|
|
18
|
+
version="1.0.21",
|
|
19
19
|
description="Command-line interface for Lyceum Cloud Execution API",
|
|
20
20
|
long_description=long_description,
|
|
21
21
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lyceum_cli-1.0.19 → lyceum_cli-1.0.21}/lyceum_cloud_execution_api_client/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|