glaip-sdk 0.0.2__py3-none-any.whl → 0.0.4__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.
- glaip_sdk/__init__.py +2 -2
- glaip_sdk/_version.py +51 -0
- glaip_sdk/branding.py +145 -0
- glaip_sdk/cli/commands/agents.py +876 -166
- glaip_sdk/cli/commands/configure.py +46 -104
- glaip_sdk/cli/commands/init.py +43 -118
- glaip_sdk/cli/commands/mcps.py +86 -161
- glaip_sdk/cli/commands/tools.py +196 -57
- glaip_sdk/cli/main.py +43 -29
- glaip_sdk/cli/utils.py +258 -27
- glaip_sdk/client/__init__.py +54 -2
- glaip_sdk/client/agents.py +196 -237
- glaip_sdk/client/base.py +62 -2
- glaip_sdk/client/mcps.py +63 -20
- glaip_sdk/client/tools.py +236 -81
- glaip_sdk/config/constants.py +10 -3
- glaip_sdk/exceptions.py +13 -0
- glaip_sdk/models.py +21 -5
- glaip_sdk/utils/__init__.py +116 -18
- glaip_sdk/utils/client_utils.py +284 -0
- glaip_sdk/utils/rendering/__init__.py +1 -0
- glaip_sdk/utils/rendering/formatting.py +211 -0
- glaip_sdk/utils/rendering/models.py +53 -0
- glaip_sdk/utils/rendering/renderer/__init__.py +38 -0
- glaip_sdk/utils/rendering/renderer/base.py +827 -0
- glaip_sdk/utils/rendering/renderer/config.py +33 -0
- glaip_sdk/utils/rendering/renderer/console.py +54 -0
- glaip_sdk/utils/rendering/renderer/debug.py +82 -0
- glaip_sdk/utils/rendering/renderer/panels.py +123 -0
- glaip_sdk/utils/rendering/renderer/progress.py +118 -0
- glaip_sdk/utils/rendering/renderer/stream.py +198 -0
- glaip_sdk/utils/rendering/steps.py +168 -0
- glaip_sdk/utils/run_renderer.py +22 -1086
- {glaip_sdk-0.0.2.dist-info → glaip_sdk-0.0.4.dist-info}/METADATA +8 -36
- glaip_sdk-0.0.4.dist-info/RECORD +41 -0
- glaip_sdk/cli/config.py +0 -592
- glaip_sdk/utils.py +0 -167
- glaip_sdk-0.0.2.dist-info/RECORD +0 -28
- {glaip_sdk-0.0.2.dist-info → glaip_sdk-0.0.4.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.2.dist-info → glaip_sdk-0.0.4.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/commands/tools.py
CHANGED
|
@@ -5,19 +5,20 @@ Authors:
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
+
import re
|
|
8
9
|
|
|
9
10
|
import click
|
|
10
11
|
from rich.console import Console
|
|
11
12
|
from rich.panel import Panel
|
|
12
|
-
|
|
13
|
-
from glaip_sdk.utils import is_uuid
|
|
13
|
+
from rich.text import Text
|
|
14
14
|
|
|
15
15
|
from ..utils import (
|
|
16
|
+
coerce_to_row,
|
|
16
17
|
get_client,
|
|
17
|
-
handle_ambiguous_resource,
|
|
18
18
|
output_flags,
|
|
19
19
|
output_list,
|
|
20
20
|
output_result,
|
|
21
|
+
resolve_resource,
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
console = Console()
|
|
@@ -31,25 +32,61 @@ def tools_group():
|
|
|
31
32
|
|
|
32
33
|
def _resolve_tool(ctx, client, ref, select=None):
|
|
33
34
|
"""Resolve tool reference (ID or name) with ambiguity handling."""
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
return resolve_resource(
|
|
36
|
+
ctx,
|
|
37
|
+
ref,
|
|
38
|
+
get_by_id=client.get_tool,
|
|
39
|
+
find_by_name=client.find_tools,
|
|
40
|
+
label="Tool",
|
|
41
|
+
select=select,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# ----------------------------- Helpers --------------------------------- #
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _extract_internal_name(code: str) -> str:
|
|
49
|
+
"""Extract plugin class name attribute from tool code."""
|
|
50
|
+
m = re.search(r'^\s*name\s*:\s*str\s*=\s*"([^"]+)"', code, re.M)
|
|
51
|
+
if not m:
|
|
52
|
+
m = re.search(r'^\s*name\s*=\s*"([^"]+)"', code, re.M)
|
|
53
|
+
if not m:
|
|
54
|
+
raise click.ClickException(
|
|
55
|
+
"Could not find plugin 'name' attribute in the tool file. "
|
|
56
|
+
'Ensure your plugin class defines e.g. name: str = "my_tool".'
|
|
57
|
+
)
|
|
58
|
+
return m.group(1)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _validate_name_match(provided: str | None, internal: str) -> str:
|
|
62
|
+
"""Validate provided --name against internal name; return effective name."""
|
|
63
|
+
if provided and provided != internal:
|
|
64
|
+
raise click.ClickException(
|
|
65
|
+
f"--name '{provided}' does not match plugin internal name '{internal}'. "
|
|
66
|
+
"Either update the code or pass a matching --name."
|
|
67
|
+
)
|
|
68
|
+
return provided or internal
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _check_duplicate_name(client, tool_name: str) -> None:
|
|
72
|
+
"""Raise if a tool with the same name already exists."""
|
|
73
|
+
try:
|
|
74
|
+
existing = client.find_tools(name=tool_name)
|
|
75
|
+
if existing:
|
|
76
|
+
raise click.ClickException(
|
|
77
|
+
f"A tool named '{tool_name}' already exists. "
|
|
78
|
+
"Please change your plugin's 'name' to a unique value, then re-run."
|
|
79
|
+
)
|
|
80
|
+
except click.ClickException:
|
|
81
|
+
# Re-raise ClickException (intended error)
|
|
82
|
+
raise
|
|
83
|
+
except Exception:
|
|
84
|
+
# Non-fatal: best-effort duplicate check for other errors
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _parse_tags(tags: str | None) -> list[str]:
|
|
89
|
+
return [t.strip() for t in (tags.split(",") if tags else []) if t.strip()]
|
|
53
90
|
|
|
54
91
|
|
|
55
92
|
@tools_group.command(name="list")
|
|
@@ -70,20 +107,10 @@ def list_tools(ctx):
|
|
|
70
107
|
|
|
71
108
|
# Transform function for safe dictionary access
|
|
72
109
|
def transform_tool(tool):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"name": tool.get("name", "N/A"),
|
|
78
|
-
"framework": tool.get("framework", "N/A"),
|
|
79
|
-
}
|
|
80
|
-
else:
|
|
81
|
-
# Fallback to attribute access
|
|
82
|
-
return {
|
|
83
|
-
"id": str(getattr(tool, "id", "N/A")),
|
|
84
|
-
"name": getattr(tool, "name", "N/A"),
|
|
85
|
-
"framework": getattr(tool, "framework", "N/A"),
|
|
86
|
-
}
|
|
110
|
+
row = coerce_to_row(tool, ["id", "name", "framework"])
|
|
111
|
+
# Ensure id is always a string
|
|
112
|
+
row["id"] = str(row["id"])
|
|
113
|
+
return row
|
|
87
114
|
|
|
88
115
|
output_list(ctx, tools, "🔧 Available Tools", columns, transform_tool)
|
|
89
116
|
|
|
@@ -92,6 +119,7 @@ def list_tools(ctx):
|
|
|
92
119
|
|
|
93
120
|
|
|
94
121
|
@tools_group.command()
|
|
122
|
+
@click.argument("file_arg", required=False, type=click.Path(exists=True))
|
|
95
123
|
@click.option(
|
|
96
124
|
"--file",
|
|
97
125
|
type=click.Path(exists=True),
|
|
@@ -111,11 +139,15 @@ def list_tools(ctx):
|
|
|
111
139
|
)
|
|
112
140
|
@output_flags()
|
|
113
141
|
@click.pass_context
|
|
114
|
-
def create(ctx, file, name, description, tags):
|
|
142
|
+
def create(ctx, file_arg, file, name, description, tags):
|
|
115
143
|
"""Create a new tool."""
|
|
116
144
|
try:
|
|
117
145
|
client = get_client(ctx)
|
|
118
146
|
|
|
147
|
+
# Allow positional file argument for better DX (matches examples)
|
|
148
|
+
if not file and file_arg:
|
|
149
|
+
file = file_arg
|
|
150
|
+
|
|
119
151
|
# Validate required parameters based on creation method
|
|
120
152
|
if not file:
|
|
121
153
|
# Metadata-only tool creation
|
|
@@ -126,27 +158,33 @@ def create(ctx, file, name, description, tags):
|
|
|
126
158
|
|
|
127
159
|
# Create tool based on whether file is provided
|
|
128
160
|
if file:
|
|
129
|
-
# File-based tool creation
|
|
161
|
+
# File-based tool creation — validate internal plugin name, no rewriting
|
|
130
162
|
with open(file, encoding="utf-8") as f:
|
|
131
163
|
code_content = f.read()
|
|
132
164
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
165
|
+
internal_name = _extract_internal_name(code_content)
|
|
166
|
+
tool_name = _validate_name_match(name, internal_name)
|
|
167
|
+
_check_duplicate_name(client, tool_name)
|
|
168
|
+
|
|
169
|
+
# Upload the plugin code as-is (no rewrite)
|
|
170
|
+
tool = client.create_tool_from_code(
|
|
171
|
+
tool_name,
|
|
172
|
+
code_content,
|
|
173
|
+
framework="langchain", # Always langchain
|
|
174
|
+
description=description,
|
|
175
|
+
tags=_parse_tags(tags),
|
|
176
|
+
)
|
|
141
177
|
else:
|
|
142
178
|
# Metadata-only tool creation
|
|
143
179
|
tool_kwargs = {}
|
|
144
180
|
if name:
|
|
145
181
|
tool_kwargs["name"] = name
|
|
182
|
+
tool_kwargs["tool_type"] = "custom" # Always custom
|
|
183
|
+
tool_kwargs["framework"] = "langchain" # Always langchain
|
|
146
184
|
if description:
|
|
147
185
|
tool_kwargs["description"] = description
|
|
148
186
|
if tags:
|
|
149
|
-
tool_kwargs["tags"] =
|
|
187
|
+
tool_kwargs["tags"] = _parse_tags(tags)
|
|
150
188
|
|
|
151
189
|
tool = client.create_tool(**tool_kwargs)
|
|
152
190
|
|
|
@@ -160,8 +198,8 @@ def create(ctx, file, name, description, tags):
|
|
|
160
198
|
panel = Panel(
|
|
161
199
|
f"[green]✅ Tool '{tool.name}' created successfully via {creation_method}![/green]\n\n"
|
|
162
200
|
f"ID: {tool.id}\n"
|
|
163
|
-
f"Framework:
|
|
164
|
-
f"Type: {'
|
|
201
|
+
f"Framework: {getattr(tool, 'framework', 'N/A')} (default)\n"
|
|
202
|
+
f"Type: {getattr(tool, 'tool_type', 'N/A')} (auto-detected)\n"
|
|
165
203
|
f"Description: {getattr(tool, 'description', 'No description')}",
|
|
166
204
|
title="🔧 Tool Created",
|
|
167
205
|
border_style="green",
|
|
@@ -172,7 +210,7 @@ def create(ctx, file, name, description, tags):
|
|
|
172
210
|
if ctx.obj.get("view") == "json":
|
|
173
211
|
click.echo(json.dumps({"error": str(e)}, indent=2))
|
|
174
212
|
else:
|
|
175
|
-
console.print(f"[red]Error creating tool: {e}[/red]")
|
|
213
|
+
console.print(Text(f"[red]Error creating tool: {e}[/red]"))
|
|
176
214
|
raise click.ClickException(str(e))
|
|
177
215
|
|
|
178
216
|
|
|
@@ -239,15 +277,15 @@ def update(ctx, tool_id, file, description, tags):
|
|
|
239
277
|
# Update code
|
|
240
278
|
updated_tool = tool.update(file_path=file)
|
|
241
279
|
if ctx.obj.get("view") != "json":
|
|
242
|
-
console.print(f"[green]✓[/green] Tool code updated from {file}")
|
|
280
|
+
console.print(Text(f"[green]✓[/green] Tool code updated from {file}"))
|
|
243
281
|
elif update_data:
|
|
244
282
|
# Update metadata
|
|
245
283
|
updated_tool = tool.update(**update_data)
|
|
246
284
|
if ctx.obj.get("view") != "json":
|
|
247
|
-
console.print("[green]✓[/green] Tool metadata updated")
|
|
285
|
+
console.print(Text("[green]✓[/green] Tool metadata updated"))
|
|
248
286
|
else:
|
|
249
287
|
if ctx.obj.get("view") != "json":
|
|
250
|
-
console.print("[yellow]No updates specified[/yellow]")
|
|
288
|
+
console.print(Text("[yellow]No updates specified[/yellow]"))
|
|
251
289
|
return
|
|
252
290
|
|
|
253
291
|
if ctx.obj.get("view") == "json":
|
|
@@ -261,7 +299,7 @@ def update(ctx, tool_id, file, description, tags):
|
|
|
261
299
|
if ctx.obj.get("view") == "json":
|
|
262
300
|
click.echo(json.dumps({"error": str(e)}, indent=2))
|
|
263
301
|
else:
|
|
264
|
-
console.print(f"[red]Error updating tool: {e}[/red]")
|
|
302
|
+
console.print(Text(f"[red]Error updating tool: {e}[/red]"))
|
|
265
303
|
raise click.ClickException(str(e))
|
|
266
304
|
|
|
267
305
|
|
|
@@ -286,7 +324,7 @@ def delete(ctx, tool_id, yes):
|
|
|
286
324
|
f"Are you sure you want to delete tool '{tool.name}'?"
|
|
287
325
|
):
|
|
288
326
|
if ctx.obj.get("view") != "json":
|
|
289
|
-
console.print("Deletion cancelled.")
|
|
327
|
+
console.print(Text("Deletion cancelled."))
|
|
290
328
|
return
|
|
291
329
|
|
|
292
330
|
tool.delete()
|
|
@@ -299,11 +337,112 @@ def delete(ctx, tool_id, yes):
|
|
|
299
337
|
)
|
|
300
338
|
)
|
|
301
339
|
else:
|
|
302
|
-
console.print(
|
|
340
|
+
console.print(
|
|
341
|
+
Text(f"[green]✅ Tool '{tool.name}' deleted successfully[/green]")
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
except Exception as e:
|
|
345
|
+
if ctx.obj.get("view") == "json":
|
|
346
|
+
click.echo(json.dumps({"error": str(e)}, indent=2))
|
|
347
|
+
else:
|
|
348
|
+
console.print(Text(f"[red]Error deleting tool: {e}[/red]"))
|
|
349
|
+
raise click.ClickException(str(e))
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@tools_group.command()
|
|
353
|
+
@click.argument("tool_id")
|
|
354
|
+
@output_flags()
|
|
355
|
+
@click.pass_context
|
|
356
|
+
def script(ctx, tool_id):
|
|
357
|
+
"""Get tool script content."""
|
|
358
|
+
try:
|
|
359
|
+
client = get_client(ctx)
|
|
360
|
+
|
|
361
|
+
# Get tool by ID (no ambiguity handling needed)
|
|
362
|
+
try:
|
|
363
|
+
tool = client.get_tool_by_id(tool_id)
|
|
364
|
+
except Exception as e:
|
|
365
|
+
raise click.ClickException(f"Tool with ID '{tool_id}' not found: {e}")
|
|
366
|
+
|
|
367
|
+
# Get tool script content
|
|
368
|
+
script_content = client.tools.get_tool_script(tool_id)
|
|
369
|
+
|
|
370
|
+
if ctx.obj.get("view") == "json":
|
|
371
|
+
click.echo(
|
|
372
|
+
json.dumps(
|
|
373
|
+
{
|
|
374
|
+
"tool_id": tool_id,
|
|
375
|
+
"tool_name": tool.name,
|
|
376
|
+
"script": script_content,
|
|
377
|
+
},
|
|
378
|
+
indent=2,
|
|
379
|
+
)
|
|
380
|
+
)
|
|
381
|
+
elif ctx.obj.get("output"):
|
|
382
|
+
# Save to file
|
|
383
|
+
output_file = ctx.obj.get("output")
|
|
384
|
+
with open(output_file, "w", encoding="utf-8") as f:
|
|
385
|
+
f.write(script_content)
|
|
386
|
+
console.print(f"[green]✅ Tool script saved to {output_file}[/green]")
|
|
387
|
+
else:
|
|
388
|
+
# Display in terminal
|
|
389
|
+
console.print(
|
|
390
|
+
Panel(
|
|
391
|
+
script_content,
|
|
392
|
+
title=f"🔧 Tool Script: {tool.name}",
|
|
393
|
+
border_style="cyan",
|
|
394
|
+
)
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
except Exception as e:
|
|
398
|
+
if ctx.obj.get("view") == "json":
|
|
399
|
+
click.echo(json.dumps({"error": str(e)}, indent=2))
|
|
400
|
+
else:
|
|
401
|
+
console.print(f"[red]Error getting tool script: {e}[/red]")
|
|
402
|
+
raise click.ClickException(str(e))
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@tools_group.command()
|
|
406
|
+
@click.argument("tool_id")
|
|
407
|
+
@click.option(
|
|
408
|
+
"--file",
|
|
409
|
+
type=click.Path(exists=True),
|
|
410
|
+
required=True,
|
|
411
|
+
help="New tool file for code update",
|
|
412
|
+
)
|
|
413
|
+
@click.option("--name", help="New tool name")
|
|
414
|
+
@click.option("--description", help="New description")
|
|
415
|
+
@click.option("--tags", help="Comma-separated tags")
|
|
416
|
+
@output_flags()
|
|
417
|
+
@click.pass_context
|
|
418
|
+
def upload_update(ctx, tool_id, file, name, description, tags):
|
|
419
|
+
"""Update a tool plugin via file upload."""
|
|
420
|
+
try:
|
|
421
|
+
client = get_client(ctx)
|
|
422
|
+
|
|
423
|
+
# Prepare update data
|
|
424
|
+
update_data = {}
|
|
425
|
+
if name:
|
|
426
|
+
update_data["name"] = name
|
|
427
|
+
if description:
|
|
428
|
+
update_data["description"] = description
|
|
429
|
+
if tags:
|
|
430
|
+
update_data["tags"] = [tag.strip() for tag in tags.split(",")]
|
|
431
|
+
|
|
432
|
+
# Update tool via file upload
|
|
433
|
+
updated_tool = client.tools.update_tool_via_file(tool_id, file, **update_data)
|
|
434
|
+
|
|
435
|
+
if ctx.obj.get("view") == "json":
|
|
436
|
+
click.echo(json.dumps(updated_tool.model_dump(), indent=2))
|
|
437
|
+
else:
|
|
438
|
+
console.print(
|
|
439
|
+
f"[green]✅ Tool '{updated_tool.name}' updated successfully via file upload[/green]"
|
|
440
|
+
)
|
|
441
|
+
console.print(f"[blue]📁 File: {file}[/blue]")
|
|
303
442
|
|
|
304
443
|
except Exception as e:
|
|
305
444
|
if ctx.obj.get("view") == "json":
|
|
306
445
|
click.echo(json.dumps({"error": str(e)}, indent=2))
|
|
307
446
|
else:
|
|
308
|
-
console.print(f"[red]Error
|
|
447
|
+
console.print(Text(f"[red]Error updating tool: {e}[/red]"))
|
|
309
448
|
raise click.ClickException(str(e))
|
glaip_sdk/cli/main.py
CHANGED
|
@@ -4,20 +4,33 @@ Authors:
|
|
|
4
4
|
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import os
|
|
8
|
+
import subprocess
|
|
7
9
|
import sys
|
|
8
10
|
|
|
9
11
|
import click
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
from rich.panel import Panel
|
|
14
|
+
from rich.table import Table
|
|
10
15
|
|
|
16
|
+
from glaip_sdk import Client
|
|
17
|
+
from glaip_sdk._version import __version__ as _SDK_VERSION
|
|
18
|
+
from glaip_sdk.branding import AIPBranding
|
|
11
19
|
from glaip_sdk.cli.commands.agents import agents_group
|
|
12
|
-
from glaip_sdk.cli.commands.configure import
|
|
20
|
+
from glaip_sdk.cli.commands.configure import (
|
|
21
|
+
config_group,
|
|
22
|
+
configure_command,
|
|
23
|
+
load_config,
|
|
24
|
+
)
|
|
13
25
|
from glaip_sdk.cli.commands.init import init_command
|
|
14
26
|
from glaip_sdk.cli.commands.mcps import mcps_group
|
|
15
27
|
from glaip_sdk.cli.commands.models import models_group
|
|
16
28
|
from glaip_sdk.cli.commands.tools import tools_group
|
|
29
|
+
from glaip_sdk.config.constants import DEFAULT_AGENT_RUN_TIMEOUT
|
|
17
30
|
|
|
18
31
|
|
|
19
32
|
@click.group()
|
|
20
|
-
@click.version_option(version=
|
|
33
|
+
@click.version_option(version=_SDK_VERSION, prog_name="aip")
|
|
21
34
|
@click.option("--api-url", envvar="AIP_API_URL", help="AIP API URL")
|
|
22
35
|
@click.option("--api-key", envvar="AIP_API_KEY", help="AIP API Key")
|
|
23
36
|
@click.option("--timeout", default=30.0, help="Request timeout in seconds")
|
|
@@ -37,11 +50,12 @@ def main(ctx, api_url, api_key, timeout, view, no_tty):
|
|
|
37
50
|
agents, tools, MCPs, and more.
|
|
38
51
|
|
|
39
52
|
Examples:
|
|
53
|
+
aip version # Show detailed version info
|
|
40
54
|
aip configure # Configure credentials
|
|
55
|
+
aip init # Initialize configuration
|
|
41
56
|
aip agents list # List all agents
|
|
42
57
|
aip tools create my_tool.py # Create a new tool
|
|
43
|
-
aip agents run my-agent "Hello" # Run an agent
|
|
44
|
-
aip init # Initialize configuration
|
|
58
|
+
aip agents run my-agent "Hello world" # Run an agent
|
|
45
59
|
"""
|
|
46
60
|
|
|
47
61
|
# Store configuration in context
|
|
@@ -75,21 +89,19 @@ def status(ctx):
|
|
|
75
89
|
"""Show connection status and basic info."""
|
|
76
90
|
config = {}
|
|
77
91
|
try:
|
|
78
|
-
from rich.console import Console
|
|
79
|
-
from rich.panel import Panel
|
|
80
|
-
from rich.table import Table
|
|
81
|
-
|
|
82
|
-
from glaip_sdk import Client
|
|
83
|
-
from glaip_sdk.cli.commands.configure import load_config
|
|
84
|
-
|
|
85
92
|
console = Console()
|
|
86
93
|
|
|
94
|
+
# Display AIP status banner
|
|
95
|
+
branding = AIPBranding.create_from_sdk(
|
|
96
|
+
sdk_version=_SDK_VERSION, package_name="glaip-sdk"
|
|
97
|
+
)
|
|
98
|
+
branding.display_status_banner("ready")
|
|
99
|
+
|
|
87
100
|
# Load config from file and merge with context
|
|
88
101
|
file_config = load_config()
|
|
89
102
|
context_config = ctx.obj or {}
|
|
90
103
|
|
|
91
104
|
# Load environment variables (middle priority)
|
|
92
|
-
import os
|
|
93
105
|
|
|
94
106
|
env_config = {}
|
|
95
107
|
if os.getenv("AIP_API_URL"):
|
|
@@ -146,7 +158,7 @@ def status(ctx):
|
|
|
146
158
|
Panel(
|
|
147
159
|
f"[bold green]✅ Connected to AIP Platform[/bold green]\n"
|
|
148
160
|
f"🔗 API URL: {client.api_url}\n"
|
|
149
|
-
f"
|
|
161
|
+
f"🤖 Agent Run Timeout: {DEFAULT_AGENT_RUN_TIMEOUT}s",
|
|
150
162
|
title="🚀 Connection Status",
|
|
151
163
|
border_style="green",
|
|
152
164
|
)
|
|
@@ -191,9 +203,10 @@ def status(ctx):
|
|
|
191
203
|
@main.command()
|
|
192
204
|
def version():
|
|
193
205
|
"""Show version information."""
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
206
|
+
branding = AIPBranding.create_from_sdk(
|
|
207
|
+
sdk_version=_SDK_VERSION, package_name="glaip-sdk"
|
|
208
|
+
)
|
|
209
|
+
branding.display_version_panel()
|
|
197
210
|
|
|
198
211
|
|
|
199
212
|
@main.command()
|
|
@@ -201,17 +214,13 @@ def version():
|
|
|
201
214
|
"--check-only", is_flag=True, help="Only check for updates without installing"
|
|
202
215
|
)
|
|
203
216
|
@click.option(
|
|
204
|
-
"--force",
|
|
217
|
+
"--force",
|
|
218
|
+
is_flag=True,
|
|
219
|
+
help="Force reinstall even if already up-to-date (adds --force-reinstall)",
|
|
205
220
|
)
|
|
206
221
|
def update(check_only: bool, force: bool):
|
|
207
222
|
"""Update AIP SDK to the latest version from PyPI."""
|
|
208
223
|
try:
|
|
209
|
-
import subprocess
|
|
210
|
-
import sys
|
|
211
|
-
|
|
212
|
-
from rich.console import Console
|
|
213
|
-
from rich.panel import Panel
|
|
214
|
-
|
|
215
224
|
console = Console()
|
|
216
225
|
|
|
217
226
|
if check_only:
|
|
@@ -238,12 +247,17 @@ def update(check_only: bool, force: bool):
|
|
|
238
247
|
|
|
239
248
|
# Update using pip
|
|
240
249
|
try:
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
250
|
+
cmd = [
|
|
251
|
+
sys.executable,
|
|
252
|
+
"-m",
|
|
253
|
+
"pip",
|
|
254
|
+
"install",
|
|
255
|
+
"--upgrade",
|
|
256
|
+
"glaip-sdk",
|
|
257
|
+
]
|
|
258
|
+
if force:
|
|
259
|
+
cmd.insert(5, "--force-reinstall")
|
|
260
|
+
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
247
261
|
|
|
248
262
|
console.print(
|
|
249
263
|
Panel(
|