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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: glaip-sdk
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Python SDK for AI Agent Platform - Simplified CLI Design
|
|
5
5
|
Author-email: Raymond Christopher <raymond.christopher@gdplabs.id>
|
|
6
6
|
License: MIT
|
|
@@ -545,44 +545,16 @@ make test-integration
|
|
|
545
545
|
make pre-commit
|
|
546
546
|
```
|
|
547
547
|
|
|
548
|
-
###
|
|
548
|
+
### Versioning
|
|
549
549
|
|
|
550
|
-
|
|
550
|
+
Single source of truth: `pyproject.toml` under `[project].version`.
|
|
551
551
|
|
|
552
|
-
|
|
552
|
+
The SDK resolves its runtime version from installed package metadata
|
|
553
|
+
(`glaip_sdk/_version.py`), so you do not need to edit any code files when
|
|
554
|
+
changing the version. Update once in `pyproject.toml`, then build/reinstall.
|
|
553
555
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
python scripts/bump_version.py patch
|
|
557
|
-
|
|
558
|
-
# Bump minor version (0.1.0 → 0.2.0) - for new features
|
|
559
|
-
python scripts/bump_version.py minor
|
|
560
|
-
|
|
561
|
-
# Bump major version (0.1.0 → 1.0.0) - for breaking changes
|
|
562
|
-
python scripts/bump_version.py major
|
|
563
|
-
|
|
564
|
-
# Preview changes without making them
|
|
565
|
-
python scripts/bump_version.py --dry-run patch
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
#### What Gets Updated
|
|
569
|
-
|
|
570
|
-
The following files are automatically updated when bumping versions:
|
|
571
|
-
- `pyproject.toml` - Package version
|
|
572
|
-
- `glaip_sdk/__init__.py` - Module version
|
|
573
|
-
- `glaip_sdk/cli/main.py` - CLI version display
|
|
574
|
-
- `glaip_sdk/config/constants.py` - SDK version constant
|
|
575
|
-
- `examples/__init__.py` - Examples version
|
|
576
|
-
|
|
577
|
-
#### After Version Bump
|
|
578
|
-
|
|
579
|
-
```bash
|
|
580
|
-
# Push changes and tags
|
|
581
|
-
git push --follow-tags
|
|
582
|
-
|
|
583
|
-
# Create GitHub release for the new version
|
|
584
|
-
# (GitHub releases will automatically use the git tag)
|
|
585
|
-
```
|
|
556
|
+
Release by tagging (e.g., `v0.0.3`) and creating a GitHub Release that
|
|
557
|
+
matches the tag.
|
|
586
558
|
|
|
587
559
|
---
|
|
588
560
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
glaip_sdk/__init__.py,sha256=UGBsYHHSgSc1HGCTsA9bbz2ARJJ1g49cTieXEINHtAk,323
|
|
2
|
+
glaip_sdk/_version.py,sha256=Rb9YLDvK1DXCVFrjlLDbtucpwKh_PyCnmZ-ia9VX3Cc,1650
|
|
3
|
+
glaip_sdk/branding.py,sha256=Iwm9qsPoRNCiv7IS_pet_vno8ltdVR4UwyEHoYH7qp0,4891
|
|
4
|
+
glaip_sdk/exceptions.py,sha256=QTVtwxRHMN4e8gGn0icXphZvdugiRvcSrlMYylwGsDc,1993
|
|
5
|
+
glaip_sdk/models.py,sha256=kkuH66cj5Oyrma3bLldPpheeXR4H9xZa_z32bpLd3DU,7229
|
|
6
|
+
glaip_sdk/cli/__init__.py,sha256=cPI-uOOBww_ESiH6NQBdJiTg8CUVNigFOU3kl0tgTuI,143
|
|
7
|
+
glaip_sdk/cli/main.py,sha256=jiZmj9smpFYkdToJip_JMBNoBEIqOrt1cTaTQrNmN7w,10557
|
|
8
|
+
glaip_sdk/cli/utils.py,sha256=UBIrLIKLi4UZjwEa8J1AiOyGJe8o6eVhYBCwjx51CxQ,29182
|
|
9
|
+
glaip_sdk/cli/commands/__init__.py,sha256=WShiuYqHcbuexPboibDJ_Q2jOPIWp-TgsyUAO2-T20I,134
|
|
10
|
+
glaip_sdk/cli/commands/agents.py,sha256=yNrlOooe9vx_A_frycdJ9U4aibXAHV4aYwVYn54RbSY,38515
|
|
11
|
+
glaip_sdk/cli/commands/configure.py,sha256=SNaWPO0bgI6bztlKgoqGr0qh2KSSDztyubKhrw_HLEI,7285
|
|
12
|
+
glaip_sdk/cli/commands/init.py,sha256=W4z5TBlfSn9fmHpH1W92llgqfF0OvhgJSdny-P61Y_4,2934
|
|
13
|
+
glaip_sdk/cli/commands/mcps.py,sha256=4Ny54ApHYFCkJCXORD7zslVnrNdKs981adIbJNaYAMQ,12099
|
|
14
|
+
glaip_sdk/cli/commands/models.py,sha256=j8VqQ2edSEvD-sQXWm8ifUco9gX8J-OBib6OvzthpqU,1405
|
|
15
|
+
glaip_sdk/cli/commands/tools.py,sha256=-xPMOKD-shI2ly9Tl-IwhKQR2kEekEs63bw7EEXNoAU,14508
|
|
16
|
+
glaip_sdk/client/__init__.py,sha256=jnsD3HCiOGiuL_4aqJiVnBsF8HNFS-s_aNLfg26gJqs,7530
|
|
17
|
+
glaip_sdk/client/agents.py,sha256=k3QthlIu82KeXV_W29LuFTGZVzyGL11ZY5OA4P4a2Ug,15041
|
|
18
|
+
glaip_sdk/client/base.py,sha256=3Ri5GVYrZ4cZ5lex1pyG0nvEmGxeXwAY194MxSH1_cY,9463
|
|
19
|
+
glaip_sdk/client/mcps.py,sha256=UEwgFbl4ogeozfJGcUbQQ7JGfwYliN9i5V6fTvkbOZ0,4311
|
|
20
|
+
glaip_sdk/client/tools.py,sha256=v5jxHPgoGHwB2PXzlm0yywvqKaYLcrm6dJz9aT1SxuM,10954
|
|
21
|
+
glaip_sdk/client/validators.py,sha256=3MtOt11IivEwQAgzmdRGWUBzP223ytECOLU_a77x7IU,7101
|
|
22
|
+
glaip_sdk/config/constants.py,sha256=Pm0tGYiJ9VdW9XXz0CG36l8-sAhnlFPTKbHKKleUgik,705
|
|
23
|
+
glaip_sdk/utils/__init__.py,sha256=5pOPBTjJ4hzvMNYjLnTut_ovwU8QJ39kARKx9-qr5Qs,5101
|
|
24
|
+
glaip_sdk/utils/client_utils.py,sha256=O44OlbQD4X0cMo_3E_Ysb_XyfEG20v0wecl5SlM9kxo,9407
|
|
25
|
+
glaip_sdk/utils/run_renderer.py,sha256=JGQzXymsptgr927-F49H1AOT5bzqErDXZMF2pOxqbfw,1365
|
|
26
|
+
glaip_sdk/utils/rendering/__init__.py,sha256=vXjwk5rPhhfPyD8S0DnV4GFFEtPJp4HCCg1Um9SXfs0,70
|
|
27
|
+
glaip_sdk/utils/rendering/formatting.py,sha256=HPCBcpWP3EpSXsIgfm-uWm6Fjo6VWzqxrnhEc137wjA,6941
|
|
28
|
+
glaip_sdk/utils/rendering/models.py,sha256=ffPMv4XrKY4V2-THL69KONZf1NL7msIa-jVZAVuz2Js,1559
|
|
29
|
+
glaip_sdk/utils/rendering/steps.py,sha256=qx6aNhfYYAbcXaHws-zdHOc4Yw3me3Cd19SZkZluJvg,5837
|
|
30
|
+
glaip_sdk/utils/rendering/renderer/__init__.py,sha256=kZwCYRcQdK-9sfZPxAAqLB--A2icLbSKq7AW1_NIIGQ,987
|
|
31
|
+
glaip_sdk/utils/rendering/renderer/base.py,sha256=IRQMNW4WHPRpBFXfXuHSo8oOWi4-Tn1_hF9a9x0_q3c,32288
|
|
32
|
+
glaip_sdk/utils/rendering/renderer/config.py,sha256=E4ER8TJJbqr1hcWjkwG7XROqLuccQy4EL99CbuLvSXE,783
|
|
33
|
+
glaip_sdk/utils/rendering/renderer/console.py,sha256=ibQU07rmrWw-MMX6n3J2ewxuOEY-Z6RnKEfzMH2-IrA,1744
|
|
34
|
+
glaip_sdk/utils/rendering/renderer/debug.py,sha256=2XP6A4w3EIjVVY_M-BDPvHf05QQSz0TDTo-dRPf1fSc,2862
|
|
35
|
+
glaip_sdk/utils/rendering/renderer/panels.py,sha256=iTDJoRBaa73pX9z9nTcb6aKhfXe1Mds0RzCuhwtvkdc,2994
|
|
36
|
+
glaip_sdk/utils/rendering/renderer/progress.py,sha256=i4HG_iNwtK4c3Gf2sviLCiOJ-5ydX4t-YE5dgtLOxNI,3438
|
|
37
|
+
glaip_sdk/utils/rendering/renderer/stream.py,sha256=ZKitYkt_7OirNeERu3cc_NybQ8mWUMoEstg9UL1S090,7323
|
|
38
|
+
glaip_sdk-0.0.4.dist-info/METADATA,sha256=H5uB6CuucGboUl_Z9LhzJHOIc7PS_a0pgHcqNX7-ANE,19501
|
|
39
|
+
glaip_sdk-0.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
40
|
+
glaip_sdk-0.0.4.dist-info/entry_points.txt,sha256=65vNPUggyYnVGhuw7RhNJ8Fp2jygTcX0yxJBcBY3iLU,48
|
|
41
|
+
glaip_sdk-0.0.4.dist-info/RECORD,,
|
glaip_sdk/cli/config.py
DELETED
|
@@ -1,592 +0,0 @@
|
|
|
1
|
-
"""CLI commands for managing SDK configuration.
|
|
2
|
-
|
|
3
|
-
Authors:
|
|
4
|
-
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
import os
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
import click
|
|
12
|
-
|
|
13
|
-
from glaip_sdk import Client
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def get_client(ctx) -> Client:
|
|
17
|
-
"""Get configured client from context."""
|
|
18
|
-
config = ctx.obj or {}
|
|
19
|
-
return Client(
|
|
20
|
-
api_url=config.get("api_url"),
|
|
21
|
-
api_key=config.get("api_key"),
|
|
22
|
-
timeout=config.get("timeout", 30.0),
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@click.group()
|
|
27
|
-
def config_group():
|
|
28
|
-
"""Manage SDK configuration."""
|
|
29
|
-
pass
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@config_group.command()
|
|
33
|
-
@click.pass_context
|
|
34
|
-
def show(ctx):
|
|
35
|
-
"""Show current configuration."""
|
|
36
|
-
try:
|
|
37
|
-
# Get config from context
|
|
38
|
-
context_config = ctx.obj or {}
|
|
39
|
-
|
|
40
|
-
# Get config from environment
|
|
41
|
-
env_config = {
|
|
42
|
-
"api_url": os.getenv("AIP_API_URL"),
|
|
43
|
-
"api_key": os.getenv("AIP_API_KEY"),
|
|
44
|
-
"timeout": os.getenv("AIP_TIMEOUT", "30.0"),
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
# Get config from file
|
|
48
|
-
config_path = Path.home() / ".aip" / "config.yaml"
|
|
49
|
-
file_config = {}
|
|
50
|
-
if config_path.exists():
|
|
51
|
-
try:
|
|
52
|
-
import yaml
|
|
53
|
-
|
|
54
|
-
with open(config_path) as f:
|
|
55
|
-
file_config = yaml.safe_load(f) or {}
|
|
56
|
-
except Exception:
|
|
57
|
-
file_config = {}
|
|
58
|
-
|
|
59
|
-
click.echo("🔧 AIP SDK Configuration")
|
|
60
|
-
click.echo("=" * 50)
|
|
61
|
-
|
|
62
|
-
# Show configuration sources
|
|
63
|
-
click.echo("Configuration Sources (in order of precedence):")
|
|
64
|
-
click.echo(" 1. Command line arguments")
|
|
65
|
-
click.echo(" 2. Environment variables")
|
|
66
|
-
click.echo(" 3. Config file (~/.aip/config.yaml)")
|
|
67
|
-
click.echo(" 4. Default values")
|
|
68
|
-
click.echo()
|
|
69
|
-
|
|
70
|
-
# Show current values
|
|
71
|
-
click.echo("Current Configuration:")
|
|
72
|
-
click.echo(
|
|
73
|
-
f" API URL: {context_config.get('api_url') or env_config['api_url'] or file_config.get('api_url') or 'Not set'}"
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
api_key = (
|
|
77
|
-
context_config.get("api_key")
|
|
78
|
-
or env_config["api_key"]
|
|
79
|
-
or file_config.get("api_key")
|
|
80
|
-
)
|
|
81
|
-
if api_key:
|
|
82
|
-
# Mask API key for security
|
|
83
|
-
masked_key = (
|
|
84
|
-
api_key[:8] + "..." + api_key[-4:] if len(api_key) > 12 else "***"
|
|
85
|
-
)
|
|
86
|
-
click.echo(f" API Key: {masked_key}")
|
|
87
|
-
else:
|
|
88
|
-
click.echo(" API Key: Not set")
|
|
89
|
-
|
|
90
|
-
timeout = (
|
|
91
|
-
context_config.get("timeout")
|
|
92
|
-
or env_config["timeout"]
|
|
93
|
-
or file_config.get("timeout")
|
|
94
|
-
or "30.0"
|
|
95
|
-
)
|
|
96
|
-
click.echo(f" Timeout: {timeout} seconds")
|
|
97
|
-
|
|
98
|
-
# Show config file location
|
|
99
|
-
click.echo(f"\nConfig file: {config_path}")
|
|
100
|
-
if config_path.exists():
|
|
101
|
-
click.echo("✅ Config file exists")
|
|
102
|
-
else:
|
|
103
|
-
click.echo("❌ Config file does not exist")
|
|
104
|
-
|
|
105
|
-
except Exception as e:
|
|
106
|
-
click.echo(f"❌ Error showing configuration: {e}")
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
@config_group.command()
|
|
110
|
-
@click.option("--api-url", help="Set API URL")
|
|
111
|
-
@click.option("--api-key", help="Set API key")
|
|
112
|
-
@click.option("--timeout", type=float, help="Set timeout in seconds")
|
|
113
|
-
@click.option("--output", "-o", type=click.Path(), help="Output file for configuration")
|
|
114
|
-
@click.pass_context
|
|
115
|
-
def set(ctx, api_url, api_key, timeout, output):
|
|
116
|
-
"""Set configuration values."""
|
|
117
|
-
try:
|
|
118
|
-
# Get current config
|
|
119
|
-
config_path = Path.home() / ".aip" / "config.yaml"
|
|
120
|
-
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
121
|
-
|
|
122
|
-
# Load existing config
|
|
123
|
-
current_config = {}
|
|
124
|
-
if config_path.exists():
|
|
125
|
-
try:
|
|
126
|
-
import yaml
|
|
127
|
-
|
|
128
|
-
with open(config_path) as f:
|
|
129
|
-
current_config = yaml.safe_load(f) or {}
|
|
130
|
-
except Exception:
|
|
131
|
-
current_config = {}
|
|
132
|
-
|
|
133
|
-
# Update config with new values
|
|
134
|
-
updated = False
|
|
135
|
-
if api_url:
|
|
136
|
-
current_config["api_url"] = api_url
|
|
137
|
-
updated = True
|
|
138
|
-
click.echo(f"✅ API URL set to: {api_url}")
|
|
139
|
-
|
|
140
|
-
if api_key:
|
|
141
|
-
current_config["api_key"] = api_key
|
|
142
|
-
updated = True
|
|
143
|
-
# Mask API key for display
|
|
144
|
-
masked_key = (
|
|
145
|
-
api_key[:8] + "..." + api_key[-4:] if len(api_key) > 12 else "***"
|
|
146
|
-
)
|
|
147
|
-
click.echo(f"✅ API Key set to: {masked_key}")
|
|
148
|
-
|
|
149
|
-
if timeout:
|
|
150
|
-
current_config["timeout"] = timeout
|
|
151
|
-
updated = True
|
|
152
|
-
click.echo(f"✅ Timeout set to: {timeout} seconds")
|
|
153
|
-
|
|
154
|
-
if not updated:
|
|
155
|
-
click.echo(
|
|
156
|
-
"❌ No configuration values provided. Use --help for available options."
|
|
157
|
-
)
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
# Save updated config
|
|
161
|
-
try:
|
|
162
|
-
import yaml
|
|
163
|
-
|
|
164
|
-
with open(config_path, "w") as f:
|
|
165
|
-
yaml.dump(current_config, f, default_flow_style=False)
|
|
166
|
-
click.echo(f"📄 Configuration saved to: {config_path}")
|
|
167
|
-
except Exception as e:
|
|
168
|
-
click.echo(f"❌ Error saving configuration: {e}")
|
|
169
|
-
return
|
|
170
|
-
|
|
171
|
-
# Save to output file if specified
|
|
172
|
-
if output:
|
|
173
|
-
output_path = Path(output)
|
|
174
|
-
with open(output_path, "w") as f:
|
|
175
|
-
json.dump(current_config, f, indent=2, default=str)
|
|
176
|
-
click.echo(f"📄 Configuration also saved to: {output_path}")
|
|
177
|
-
|
|
178
|
-
except Exception as e:
|
|
179
|
-
click.echo(f"❌ Error setting configuration: {e}")
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
@config_group.command()
|
|
183
|
-
@click.option("--api-url", is_flag=True, help="Remove API URL setting")
|
|
184
|
-
@click.option("--api-key", is_flag=True, help="Remove API key setting")
|
|
185
|
-
@click.option("--timeout", is_flag=True, help="Remove timeout setting")
|
|
186
|
-
@click.option("--all", is_flag=True, help="Remove all configuration")
|
|
187
|
-
@click.option(
|
|
188
|
-
"--output", "-o", type=click.Path(), help="Output file for remaining configuration"
|
|
189
|
-
)
|
|
190
|
-
@click.pass_context
|
|
191
|
-
def unset(ctx, api_url, api_key, timeout, all, output):
|
|
192
|
-
"""Remove configuration values."""
|
|
193
|
-
try:
|
|
194
|
-
# Get current config
|
|
195
|
-
config_path = Path.home() / ".aip" / "config.yaml"
|
|
196
|
-
|
|
197
|
-
if not config_path.exists():
|
|
198
|
-
click.echo("❌ No configuration file found.")
|
|
199
|
-
return
|
|
200
|
-
|
|
201
|
-
# Load current config
|
|
202
|
-
try:
|
|
203
|
-
import yaml
|
|
204
|
-
|
|
205
|
-
with open(config_path) as f:
|
|
206
|
-
current_config = yaml.safe_load(f) or {}
|
|
207
|
-
except Exception as e:
|
|
208
|
-
click.echo(f"❌ Error loading configuration: {e}")
|
|
209
|
-
return
|
|
210
|
-
|
|
211
|
-
# Remove specified values
|
|
212
|
-
removed = False
|
|
213
|
-
if all:
|
|
214
|
-
# Remove all configuration
|
|
215
|
-
current_config = {}
|
|
216
|
-
removed = True
|
|
217
|
-
click.echo("✅ All configuration removed")
|
|
218
|
-
else:
|
|
219
|
-
if api_url and "api_url" in current_config:
|
|
220
|
-
del current_config["api_url"]
|
|
221
|
-
removed = True
|
|
222
|
-
click.echo("✅ API URL removed")
|
|
223
|
-
|
|
224
|
-
if api_key and "api_key" in current_config:
|
|
225
|
-
del current_config["api_key"]
|
|
226
|
-
removed = True
|
|
227
|
-
click.echo("✅ API Key removed")
|
|
228
|
-
|
|
229
|
-
if timeout and "timeout" in current_config:
|
|
230
|
-
del current_config["timeout"]
|
|
231
|
-
removed = True
|
|
232
|
-
click.echo("✅ Timeout removed")
|
|
233
|
-
|
|
234
|
-
if not removed:
|
|
235
|
-
click.echo(
|
|
236
|
-
"❌ No configuration values specified for removal. Use --help for available options."
|
|
237
|
-
)
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
# Save updated config
|
|
241
|
-
if current_config:
|
|
242
|
-
try:
|
|
243
|
-
with open(config_path, "w") as f:
|
|
244
|
-
yaml.dump(current_config, f, default_flow_style=False)
|
|
245
|
-
click.echo(f"📄 Updated configuration saved to: {config_path}")
|
|
246
|
-
except Exception as e:
|
|
247
|
-
click.echo(f"❌ Error saving configuration: {e}")
|
|
248
|
-
return
|
|
249
|
-
else:
|
|
250
|
-
# Remove config file if empty
|
|
251
|
-
try:
|
|
252
|
-
config_path.unlink()
|
|
253
|
-
click.echo(f"📄 Configuration file removed: {config_path}")
|
|
254
|
-
except Exception as e:
|
|
255
|
-
click.echo(f"❌ Error removing configuration file: {e}")
|
|
256
|
-
return
|
|
257
|
-
|
|
258
|
-
# Save to output file if specified
|
|
259
|
-
if output:
|
|
260
|
-
output_path = Path(output)
|
|
261
|
-
with open(output_path, "w") as f:
|
|
262
|
-
json.dump(current_config, f, indent=2, default=str)
|
|
263
|
-
click.echo(f"📄 Remaining configuration saved to: {output_path}")
|
|
264
|
-
|
|
265
|
-
except Exception as e:
|
|
266
|
-
click.echo(f"❌ Error removing configuration: {e}")
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
@config_group.command()
|
|
270
|
-
@click.option("--output", "-o", type=click.Path(), help="Output file for configuration")
|
|
271
|
-
@click.pass_context
|
|
272
|
-
def export(ctx, output):
|
|
273
|
-
"""Export current configuration."""
|
|
274
|
-
try:
|
|
275
|
-
# Get config from all sources
|
|
276
|
-
config_path = Path.home() / ".aip" / "config.yaml"
|
|
277
|
-
|
|
278
|
-
# Load file config
|
|
279
|
-
file_config = {}
|
|
280
|
-
if config_path.exists():
|
|
281
|
-
try:
|
|
282
|
-
import yaml
|
|
283
|
-
|
|
284
|
-
with open(config_path) as f:
|
|
285
|
-
file_config = yaml.safe_load(f) or {}
|
|
286
|
-
except Exception:
|
|
287
|
-
file_config = {}
|
|
288
|
-
|
|
289
|
-
# Get environment config
|
|
290
|
-
env_config = {
|
|
291
|
-
"api_url": os.getenv("AIP_API_URL"),
|
|
292
|
-
"api_key": os.getenv("AIP_API_KEY"),
|
|
293
|
-
"timeout": os.getenv("AIP_TIMEOUT"),
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
# Combine configs (environment overrides file)
|
|
297
|
-
combined_config = {**file_config, **env_config}
|
|
298
|
-
|
|
299
|
-
# Remove None values
|
|
300
|
-
combined_config = {k: v for k, v in combined_config.items() if v is not None}
|
|
301
|
-
|
|
302
|
-
if not combined_config:
|
|
303
|
-
click.echo("❌ No configuration found to export.")
|
|
304
|
-
return
|
|
305
|
-
|
|
306
|
-
# Display configuration
|
|
307
|
-
click.echo("📤 Exported Configuration:")
|
|
308
|
-
click.echo("=" * 30)
|
|
309
|
-
|
|
310
|
-
for key, value in combined_config.items():
|
|
311
|
-
if key == "api_key" and value:
|
|
312
|
-
# Mask API key for display
|
|
313
|
-
masked_value = (
|
|
314
|
-
value[:8] + "..." + value[-4:] if len(value) > 12 else "***"
|
|
315
|
-
)
|
|
316
|
-
click.echo(f"{key}: {masked_value}")
|
|
317
|
-
else:
|
|
318
|
-
click.echo(f"{key}: {value}")
|
|
319
|
-
|
|
320
|
-
# Save to output file if specified
|
|
321
|
-
if output:
|
|
322
|
-
output_path = Path(output)
|
|
323
|
-
with open(output_path, "w") as f:
|
|
324
|
-
json.dump(combined_config, f, indent=2, default=str)
|
|
325
|
-
click.echo(f"\n📄 Configuration exported to: {output_path}")
|
|
326
|
-
else:
|
|
327
|
-
# Save to default location
|
|
328
|
-
export_path = Path.home() / ".aip" / "config_export.json"
|
|
329
|
-
export_path.parent.mkdir(parents=True, exist_ok=True)
|
|
330
|
-
with open(export_path, "w") as f:
|
|
331
|
-
json.dump(combined_config, f, indent=2, default=str)
|
|
332
|
-
click.echo(f"\n📄 Configuration exported to: {export_path}")
|
|
333
|
-
|
|
334
|
-
except Exception as e:
|
|
335
|
-
click.echo(f"❌ Error exporting configuration: {e}")
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
@config_group.command()
|
|
339
|
-
@click.argument("config_file", type=click.Path(exists=True))
|
|
340
|
-
@click.option("--overwrite", is_flag=True, help="Overwrite existing configuration")
|
|
341
|
-
@click.option(
|
|
342
|
-
"--output", "-o", type=click.Path(), help="Output file for imported configuration"
|
|
343
|
-
)
|
|
344
|
-
@click.pass_context
|
|
345
|
-
def import_config(ctx, config_file, overwrite, output):
|
|
346
|
-
"""Import configuration from a file."""
|
|
347
|
-
try:
|
|
348
|
-
config_path = Path(config_file)
|
|
349
|
-
|
|
350
|
-
# Load configuration from file
|
|
351
|
-
try:
|
|
352
|
-
if config_path.suffix.lower() in [".json", ".js"]:
|
|
353
|
-
with open(config_path) as f:
|
|
354
|
-
imported_config = json.load(f)
|
|
355
|
-
elif config_path.suffix.lower() in [".yaml", ".yml"]:
|
|
356
|
-
import yaml
|
|
357
|
-
|
|
358
|
-
with open(config_path) as f:
|
|
359
|
-
imported_config = yaml.safe_load(f)
|
|
360
|
-
else:
|
|
361
|
-
click.echo(f"❌ Unsupported file format: {config_path.suffix}")
|
|
362
|
-
click.echo("Supported formats: .json, .yaml, .yml")
|
|
363
|
-
return
|
|
364
|
-
except Exception as e:
|
|
365
|
-
click.echo(f"❌ Error loading configuration file: {e}")
|
|
366
|
-
return
|
|
367
|
-
|
|
368
|
-
if not imported_config:
|
|
369
|
-
click.echo("❌ Configuration file is empty or invalid.")
|
|
370
|
-
return
|
|
371
|
-
|
|
372
|
-
# Get current config
|
|
373
|
-
current_config_path = Path.home() / ".aip" / "config.yaml"
|
|
374
|
-
current_config = {}
|
|
375
|
-
|
|
376
|
-
if current_config_path.exists() and not overwrite:
|
|
377
|
-
try:
|
|
378
|
-
import yaml
|
|
379
|
-
|
|
380
|
-
with open(current_config_path) as f:
|
|
381
|
-
current_config = yaml.safe_load(f) or {}
|
|
382
|
-
except Exception:
|
|
383
|
-
current_config = {}
|
|
384
|
-
|
|
385
|
-
# Merge configurations
|
|
386
|
-
merged_config = {**current_config, **imported_config}
|
|
387
|
-
|
|
388
|
-
# Save merged configuration
|
|
389
|
-
current_config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
390
|
-
try:
|
|
391
|
-
import yaml
|
|
392
|
-
|
|
393
|
-
with open(current_config_path, "w") as f:
|
|
394
|
-
yaml.dump(merged_config, f, default_flow_style=False)
|
|
395
|
-
click.echo(f"✅ Configuration imported and saved to: {current_config_path}")
|
|
396
|
-
except Exception as e:
|
|
397
|
-
click.echo(f"❌ Error saving merged configuration: {e}")
|
|
398
|
-
return
|
|
399
|
-
|
|
400
|
-
# Display imported configuration
|
|
401
|
-
click.echo("\n📥 Imported Configuration:")
|
|
402
|
-
click.echo("=" * 30)
|
|
403
|
-
|
|
404
|
-
for key, value in imported_config.items():
|
|
405
|
-
if key == "api_key" and value:
|
|
406
|
-
# Mask API key for display
|
|
407
|
-
masked_value = (
|
|
408
|
-
value[:8] + "..." + value[-4:] if len(value) > 12 else "***"
|
|
409
|
-
)
|
|
410
|
-
click.echo(f"{key}: {masked_value}")
|
|
411
|
-
else:
|
|
412
|
-
click.echo(f"{key}: {value}")
|
|
413
|
-
|
|
414
|
-
# Save to output file if specified
|
|
415
|
-
if output:
|
|
416
|
-
output_path = Path(output)
|
|
417
|
-
with open(output_path, "w") as f:
|
|
418
|
-
json.dump(merged_config, f, indent=2, default=str)
|
|
419
|
-
click.echo(f"\n📄 Merged configuration saved to: {output_path}")
|
|
420
|
-
|
|
421
|
-
except Exception as e:
|
|
422
|
-
click.echo(f"❌ Error importing configuration: {e}")
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
@config_group.command()
|
|
426
|
-
@click.pass_context
|
|
427
|
-
def validate(ctx):
|
|
428
|
-
"""Validate current configuration."""
|
|
429
|
-
try:
|
|
430
|
-
# Get config from all sources
|
|
431
|
-
config_path = Path.home() / ".aip" / "config.yaml"
|
|
432
|
-
|
|
433
|
-
# Load file config
|
|
434
|
-
file_config = {}
|
|
435
|
-
if config_path.exists():
|
|
436
|
-
try:
|
|
437
|
-
import yaml
|
|
438
|
-
|
|
439
|
-
with open(config_path) as f:
|
|
440
|
-
file_config = yaml.safe_load(f) or {}
|
|
441
|
-
except Exception as e:
|
|
442
|
-
click.echo(f"❌ Error loading config file: {e}")
|
|
443
|
-
file_config = {}
|
|
444
|
-
|
|
445
|
-
# Get environment config
|
|
446
|
-
env_config = {
|
|
447
|
-
"api_url": os.getenv("AIP_API_URL"),
|
|
448
|
-
"api_key": os.getenv("AIP_API_KEY"),
|
|
449
|
-
"timeout": os.getenv("AIP_TIMEOUT"),
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
# Combine configs (environment overrides file)
|
|
453
|
-
combined_config = {**file_config, **env_config}
|
|
454
|
-
|
|
455
|
-
# Remove None values
|
|
456
|
-
combined_config = {k: v for k, v in combined_config.items() if v is not None}
|
|
457
|
-
|
|
458
|
-
click.echo("🔍 Validating Configuration")
|
|
459
|
-
click.echo("=" * 40)
|
|
460
|
-
|
|
461
|
-
# Check required fields
|
|
462
|
-
required_fields = ["api_url", "api_key"]
|
|
463
|
-
missing_fields = []
|
|
464
|
-
|
|
465
|
-
for field in required_fields:
|
|
466
|
-
if field not in combined_config:
|
|
467
|
-
missing_fields.append(field)
|
|
468
|
-
else:
|
|
469
|
-
click.echo(f"✅ {field}: Set")
|
|
470
|
-
|
|
471
|
-
if missing_fields:
|
|
472
|
-
click.echo(f"❌ Missing required fields: {', '.join(missing_fields)}")
|
|
473
|
-
click.echo("\nTo set these values, use:")
|
|
474
|
-
for field in missing_fields:
|
|
475
|
-
if field == "api_url":
|
|
476
|
-
click.echo(f" aip config set --{field} <your-api-url>")
|
|
477
|
-
elif field == "api_key":
|
|
478
|
-
click.echo(f" aip config set --{field} <your-api-key>")
|
|
479
|
-
return
|
|
480
|
-
|
|
481
|
-
# Validate API URL format
|
|
482
|
-
api_url = combined_config["api_url"]
|
|
483
|
-
if not api_url.startswith(("http://", "https://")):
|
|
484
|
-
click.echo("⚠️ Warning: API URL should start with http:// or https://")
|
|
485
|
-
|
|
486
|
-
# Validate timeout if present
|
|
487
|
-
if "timeout" in combined_config:
|
|
488
|
-
try:
|
|
489
|
-
timeout = float(combined_config["timeout"])
|
|
490
|
-
if timeout <= 0:
|
|
491
|
-
click.echo(f"❌ Timeout must be positive, got: {timeout}")
|
|
492
|
-
return
|
|
493
|
-
click.echo(f"✅ timeout: {timeout} seconds")
|
|
494
|
-
except ValueError:
|
|
495
|
-
click.echo(f"❌ Invalid timeout value: {combined_config['timeout']}")
|
|
496
|
-
return
|
|
497
|
-
|
|
498
|
-
# Test connection if possible
|
|
499
|
-
click.echo("\n🔌 Testing Connection...")
|
|
500
|
-
try:
|
|
501
|
-
client = Client(
|
|
502
|
-
api_url=combined_config["api_url"],
|
|
503
|
-
api_key=combined_config["api_key"],
|
|
504
|
-
timeout=float(combined_config.get("timeout", 30.0)),
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
# Try to list resources to test connection
|
|
508
|
-
try:
|
|
509
|
-
agents = client.list_agents()
|
|
510
|
-
click.echo(f"✅ Connection successful! Found {len(agents)} agents")
|
|
511
|
-
except Exception as e:
|
|
512
|
-
click.echo(f"⚠️ Connection established but API call failed: {e}")
|
|
513
|
-
|
|
514
|
-
client.close()
|
|
515
|
-
|
|
516
|
-
except Exception as e:
|
|
517
|
-
click.echo(f"❌ Connection failed: {e}")
|
|
518
|
-
return
|
|
519
|
-
|
|
520
|
-
click.echo("\n🎉 Configuration is valid!")
|
|
521
|
-
|
|
522
|
-
except Exception as e:
|
|
523
|
-
click.echo(f"❌ Error validating configuration: {e}")
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
@config_group.command()
|
|
527
|
-
@click.pass_context
|
|
528
|
-
def init(ctx):
|
|
529
|
-
"""Initialize configuration interactively."""
|
|
530
|
-
try:
|
|
531
|
-
click.echo("🚀 AIP SDK Configuration Initialization")
|
|
532
|
-
click.echo("=" * 50)
|
|
533
|
-
click.echo("This will help you set up your AIP SDK configuration.")
|
|
534
|
-
click.echo()
|
|
535
|
-
|
|
536
|
-
# Get configuration values interactively
|
|
537
|
-
api_url = click.prompt(
|
|
538
|
-
"Enter your AIP API URL", default="https://api.aiagentplatform.com"
|
|
539
|
-
)
|
|
540
|
-
|
|
541
|
-
api_key = click.prompt("Enter your AIP API Key", hide_input=True)
|
|
542
|
-
|
|
543
|
-
timeout = click.prompt(
|
|
544
|
-
"Enter request timeout in seconds", default=30.0, type=float
|
|
545
|
-
)
|
|
546
|
-
|
|
547
|
-
# Confirm configuration
|
|
548
|
-
click.echo("\n📋 Configuration Summary:")
|
|
549
|
-
click.echo(f" API URL: {api_url}")
|
|
550
|
-
click.echo(
|
|
551
|
-
f" API Key: {api_key[:8]}...{api_key[-4:] if len(api_key) > 12 else '***'}"
|
|
552
|
-
)
|
|
553
|
-
click.echo(f" Timeout: {timeout} seconds")
|
|
554
|
-
|
|
555
|
-
if not click.confirm("\nIs this configuration correct?"):
|
|
556
|
-
click.echo("Configuration cancelled.")
|
|
557
|
-
return
|
|
558
|
-
|
|
559
|
-
# Save configuration
|
|
560
|
-
config_path = Path.home() / ".aip" / "config.yaml"
|
|
561
|
-
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
562
|
-
|
|
563
|
-
config_data = {"api_url": api_url, "api_key": api_key, "timeout": timeout}
|
|
564
|
-
|
|
565
|
-
try:
|
|
566
|
-
import yaml
|
|
567
|
-
|
|
568
|
-
with open(config_path, "w") as f:
|
|
569
|
-
yaml.dump(config_data, f, default_flow_style=False)
|
|
570
|
-
click.echo(f"\n✅ Configuration saved to: {config_path}")
|
|
571
|
-
except Exception as e:
|
|
572
|
-
click.echo(f"❌ Error saving configuration: {e}")
|
|
573
|
-
return
|
|
574
|
-
|
|
575
|
-
# Test connection
|
|
576
|
-
click.echo("\n🔌 Testing connection...")
|
|
577
|
-
try:
|
|
578
|
-
client = Client(api_url=api_url, api_key=api_key, timeout=timeout)
|
|
579
|
-
agents = client.list_agents()
|
|
580
|
-
click.echo(f"✅ Connection successful! Found {len(agents)} agents")
|
|
581
|
-
client.close()
|
|
582
|
-
except Exception as e:
|
|
583
|
-
click.echo(f"⚠️ Configuration saved but connection test failed: {e}")
|
|
584
|
-
click.echo(
|
|
585
|
-
"You may need to check your API credentials or network connection."
|
|
586
|
-
)
|
|
587
|
-
|
|
588
|
-
click.echo("\n🎉 Configuration initialization complete!")
|
|
589
|
-
click.echo("You can now use the AIP SDK CLI commands.")
|
|
590
|
-
|
|
591
|
-
except Exception as e:
|
|
592
|
-
click.echo(f"❌ Error during configuration initialization: {e}")
|