glaip-sdk 0.0.7__py3-none-any.whl → 0.6.5b6__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 +6 -3
- glaip_sdk/_version.py +12 -5
- glaip_sdk/agents/__init__.py +27 -0
- glaip_sdk/agents/base.py +1126 -0
- glaip_sdk/branding.py +79 -15
- glaip_sdk/cli/account_store.py +540 -0
- glaip_sdk/cli/agent_config.py +2 -6
- glaip_sdk/cli/auth.py +699 -0
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents.py +503 -183
- glaip_sdk/cli/commands/common_config.py +101 -0
- glaip_sdk/cli/commands/configure.py +774 -137
- glaip_sdk/cli/commands/mcps.py +1124 -181
- glaip_sdk/cli/commands/models.py +25 -10
- glaip_sdk/cli/commands/tools.py +144 -92
- glaip_sdk/cli/commands/transcripts.py +755 -0
- glaip_sdk/cli/commands/update.py +61 -0
- glaip_sdk/cli/config.py +95 -0
- glaip_sdk/cli/constants.py +38 -0
- glaip_sdk/cli/context.py +150 -0
- glaip_sdk/cli/core/__init__.py +79 -0
- glaip_sdk/cli/core/context.py +124 -0
- glaip_sdk/cli/core/output.py +846 -0
- glaip_sdk/cli/core/prompting.py +649 -0
- glaip_sdk/cli/core/rendering.py +187 -0
- glaip_sdk/cli/display.py +143 -53
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +24 -18
- glaip_sdk/cli/main.py +420 -145
- glaip_sdk/cli/masking.py +136 -0
- glaip_sdk/cli/mcp_validators.py +287 -0
- glaip_sdk/cli/pager.py +266 -0
- glaip_sdk/cli/parsers/__init__.py +7 -0
- glaip_sdk/cli/parsers/json_input.py +177 -0
- glaip_sdk/cli/resolution.py +28 -21
- glaip_sdk/cli/rich_helpers.py +27 -0
- glaip_sdk/cli/slash/__init__.py +15 -0
- glaip_sdk/cli/slash/accounts_controller.py +500 -0
- glaip_sdk/cli/slash/accounts_shared.py +75 -0
- glaip_sdk/cli/slash/agent_session.py +282 -0
- glaip_sdk/cli/slash/prompt.py +245 -0
- glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
- glaip_sdk/cli/slash/session.py +1679 -0
- glaip_sdk/cli/slash/tui/__init__.py +9 -0
- glaip_sdk/cli/slash/tui/accounts.tcss +86 -0
- glaip_sdk/cli/slash/tui/accounts_app.py +872 -0
- glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
- glaip_sdk/cli/slash/tui/loading.py +58 -0
- glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
- glaip_sdk/cli/transcript/__init__.py +31 -0
- glaip_sdk/cli/transcript/cache.py +536 -0
- glaip_sdk/cli/transcript/capture.py +329 -0
- glaip_sdk/cli/transcript/export.py +38 -0
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/launcher.py +77 -0
- glaip_sdk/cli/transcript/viewer.py +372 -0
- glaip_sdk/cli/update_notifier.py +290 -0
- glaip_sdk/cli/utils.py +247 -1238
- glaip_sdk/cli/validators.py +16 -18
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_agent_payloads.py +520 -0
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +940 -574
- glaip_sdk/client/base.py +163 -48
- glaip_sdk/client/main.py +35 -12
- glaip_sdk/client/mcps.py +126 -18
- glaip_sdk/client/run_rendering.py +415 -0
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +195 -37
- glaip_sdk/client/validators.py +20 -48
- glaip_sdk/config/constants.py +15 -5
- glaip_sdk/exceptions.py +16 -9
- glaip_sdk/icons.py +25 -0
- glaip_sdk/mcps/__init__.py +21 -0
- glaip_sdk/mcps/base.py +345 -0
- glaip_sdk/models/__init__.py +90 -0
- glaip_sdk/models/agent.py +47 -0
- glaip_sdk/models/agent_runs.py +116 -0
- glaip_sdk/models/common.py +42 -0
- glaip_sdk/models/mcp.py +33 -0
- glaip_sdk/models/tool.py +33 -0
- glaip_sdk/payload_schemas/__init__.py +7 -0
- glaip_sdk/payload_schemas/agent.py +85 -0
- glaip_sdk/registry/__init__.py +55 -0
- glaip_sdk/registry/agent.py +164 -0
- glaip_sdk/registry/base.py +139 -0
- glaip_sdk/registry/mcp.py +253 -0
- glaip_sdk/registry/tool.py +231 -0
- glaip_sdk/rich_components.py +98 -2
- glaip_sdk/runner/__init__.py +59 -0
- glaip_sdk/runner/base.py +84 -0
- glaip_sdk/runner/deps.py +115 -0
- glaip_sdk/runner/langgraph.py +597 -0
- glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +158 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
- glaip_sdk/runner/tool_adapter/__init__.py +18 -0
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +177 -0
- glaip_sdk/tools/__init__.py +22 -0
- glaip_sdk/tools/base.py +435 -0
- glaip_sdk/utils/__init__.py +59 -13
- glaip_sdk/utils/a2a/__init__.py +34 -0
- glaip_sdk/utils/a2a/event_processor.py +188 -0
- glaip_sdk/utils/agent_config.py +53 -40
- glaip_sdk/utils/bundler.py +267 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +58 -26
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +65 -32
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +1 -36
- glaip_sdk/utils/import_export.py +20 -25
- glaip_sdk/utils/import_resolver.py +492 -0
- glaip_sdk/utils/instructions.py +101 -0
- glaip_sdk/utils/rendering/__init__.py +115 -1
- glaip_sdk/utils/rendering/formatting.py +85 -43
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/{renderer → layout}/panels.py +51 -19
- glaip_sdk/utils/rendering/layout/progress.py +202 -0
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +39 -7
- glaip_sdk/utils/rendering/renderer/__init__.py +9 -51
- glaip_sdk/utils/rendering/renderer/base.py +672 -759
- glaip_sdk/utils/rendering/renderer/config.py +4 -10
- glaip_sdk/utils/rendering/renderer/debug.py +75 -22
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +13 -54
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
- glaip_sdk/utils/rendering/renderer/toggle.py +182 -0
- glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
- glaip_sdk/utils/rendering/state.py +204 -0
- glaip_sdk/utils/rendering/step_tree_state.py +100 -0
- glaip_sdk/utils/rendering/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/steps/event_processor.py +778 -0
- glaip_sdk/utils/rendering/steps/format.py +176 -0
- glaip_sdk/utils/rendering/steps/manager.py +387 -0
- glaip_sdk/utils/rendering/timing.py +36 -0
- glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
- glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
- glaip_sdk/utils/resource_refs.py +29 -26
- glaip_sdk/utils/runtime_config.py +422 -0
- glaip_sdk/utils/serialization.py +184 -51
- glaip_sdk/utils/sync.py +142 -0
- glaip_sdk/utils/tool_detection.py +33 -0
- glaip_sdk/utils/validation.py +21 -30
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.6.5b6.dist-info}/METADATA +58 -12
- glaip_sdk-0.6.5b6.dist-info/RECORD +159 -0
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.6.5b6.dist-info}/WHEEL +1 -1
- glaip_sdk/models.py +0 -250
- glaip_sdk/utils/rendering/renderer/progress.py +0 -118
- glaip_sdk/utils/rendering/steps.py +0 -232
- glaip_sdk/utils/rich_utils.py +0 -29
- glaip_sdk-0.0.7.dist-info/RECORD +0 -55
- {glaip_sdk-0.0.7.dist-info → glaip_sdk-0.6.5b6.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/commands/models.py
CHANGED
|
@@ -9,7 +9,12 @@ from typing import Any
|
|
|
9
9
|
import click
|
|
10
10
|
from rich.console import Console
|
|
11
11
|
|
|
12
|
-
from glaip_sdk.
|
|
12
|
+
from glaip_sdk.branding import ACCENT_STYLE, INFO, SUCCESS
|
|
13
|
+
from glaip_sdk.cli.context import output_flags
|
|
14
|
+
from glaip_sdk.cli.utils import (
|
|
15
|
+
output_list,
|
|
16
|
+
with_client_and_spinner,
|
|
17
|
+
)
|
|
13
18
|
|
|
14
19
|
console = Console()
|
|
15
20
|
|
|
@@ -26,19 +31,31 @@ def models_group() -> None:
|
|
|
26
31
|
def list_models(ctx: Any) -> None:
|
|
27
32
|
"""List available language models."""
|
|
28
33
|
try:
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
with with_client_and_spinner(
|
|
35
|
+
ctx,
|
|
36
|
+
"[bold blue]Fetching language models…[/bold blue]",
|
|
37
|
+
console_override=console,
|
|
38
|
+
) as client:
|
|
39
|
+
models = client.list_language_models()
|
|
31
40
|
|
|
32
41
|
# Define table columns: (data_key, header, style, width)
|
|
33
42
|
columns = [
|
|
34
43
|
("id", "ID", "dim", 36),
|
|
35
|
-
("provider", "Provider",
|
|
36
|
-
("name", "Model",
|
|
37
|
-
("base_url", "Base URL",
|
|
44
|
+
("provider", "Provider", ACCENT_STYLE, None),
|
|
45
|
+
("name", "Model", SUCCESS, None),
|
|
46
|
+
("base_url", "Base URL", INFO, None),
|
|
38
47
|
]
|
|
39
48
|
|
|
40
49
|
# Transform function for safe dictionary access
|
|
41
50
|
def transform_model(model: dict[str, Any]) -> dict[str, Any]:
|
|
51
|
+
"""Transform a model dictionary to a display row dictionary.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
model: Model dictionary to transform.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Dictionary with id, provider, name, and base_url fields.
|
|
58
|
+
"""
|
|
42
59
|
return {
|
|
43
60
|
"id": str(model.get("id", "N/A")),
|
|
44
61
|
"provider": model.get("provider", "N/A"),
|
|
@@ -46,9 +63,7 @@ def list_models(ctx: Any) -> None:
|
|
|
46
63
|
"base_url": model.get("base_url", "Default") or "Default",
|
|
47
64
|
}
|
|
48
65
|
|
|
49
|
-
output_list(
|
|
50
|
-
ctx, models, "🧠 Available Language Models", columns, transform_model
|
|
51
|
-
)
|
|
66
|
+
output_list(ctx, models, "🧠 Available Language Models", columns, transform_model)
|
|
52
67
|
|
|
53
68
|
except Exception as e:
|
|
54
|
-
raise click.ClickException(str(e))
|
|
69
|
+
raise click.ClickException(str(e)) from e
|
glaip_sdk/cli/commands/tools.py
CHANGED
|
@@ -10,9 +10,14 @@ from pathlib import Path
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
import click
|
|
13
|
-
from
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
from glaip_sdk.branding import (
|
|
14
|
+
ACCENT_STYLE,
|
|
15
|
+
ERROR_STYLE,
|
|
16
|
+
INFO,
|
|
17
|
+
SUCCESS_STYLE,
|
|
18
|
+
WARNING_STYLE,
|
|
19
|
+
)
|
|
20
|
+
from glaip_sdk.cli.context import get_ctx_value, output_flags
|
|
16
21
|
from glaip_sdk.cli.display import (
|
|
17
22
|
display_api_error,
|
|
18
23
|
display_confirmation_prompt,
|
|
@@ -22,27 +27,25 @@ from glaip_sdk.cli.display import (
|
|
|
22
27
|
handle_json_output,
|
|
23
28
|
handle_rich_output,
|
|
24
29
|
)
|
|
25
|
-
from glaip_sdk.cli.io import
|
|
26
|
-
export_resource_to_file_with_validation as export_resource_to_file,
|
|
27
|
-
)
|
|
28
|
-
from glaip_sdk.cli.io import (
|
|
29
|
-
fetch_raw_resource_details,
|
|
30
|
-
)
|
|
30
|
+
from glaip_sdk.cli.io import fetch_raw_resource_details
|
|
31
31
|
from glaip_sdk.cli.io import (
|
|
32
32
|
load_resource_from_file_with_validation as load_resource_from_file,
|
|
33
33
|
)
|
|
34
34
|
from glaip_sdk.cli.resolution import resolve_resource_reference
|
|
35
|
+
from glaip_sdk.cli.rich_helpers import markup_text, print_markup
|
|
35
36
|
from glaip_sdk.cli.utils import (
|
|
36
37
|
coerce_to_row,
|
|
37
|
-
|
|
38
|
+
format_datetime_fields,
|
|
38
39
|
get_client,
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
handle_best_effort_check,
|
|
41
|
+
handle_resource_export,
|
|
41
42
|
output_list,
|
|
42
43
|
output_result,
|
|
44
|
+
spinner_context,
|
|
43
45
|
)
|
|
44
|
-
from glaip_sdk.
|
|
46
|
+
from glaip_sdk.icons import ICON_TOOL
|
|
45
47
|
from glaip_sdk.utils.import_export import merge_import_with_cli_args
|
|
48
|
+
from rich.console import Console
|
|
46
49
|
|
|
47
50
|
console = Console()
|
|
48
51
|
|
|
@@ -53,17 +56,32 @@ def tools_group() -> None:
|
|
|
53
56
|
pass
|
|
54
57
|
|
|
55
58
|
|
|
56
|
-
def _resolve_tool(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
def _resolve_tool(ctx: Any, client: Any, ref: str, select: int | None = None) -> Any | None:
|
|
60
|
+
"""Resolve a tool by ID or name, handling ambiguous matches interactively.
|
|
61
|
+
|
|
62
|
+
This function provides tool-specific resolution logic. It uses
|
|
63
|
+
resolve_resource_reference to find tools by UUID or name, with interactive
|
|
64
|
+
selection when multiple matches are found.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
ctx: Click context for CLI operations.
|
|
68
|
+
client: API client instance.
|
|
69
|
+
ref: Tool reference (UUID string or name).
|
|
70
|
+
select: Pre-selected index for non-interactive mode (1-based).
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Tool object if found, None otherwise.
|
|
74
|
+
"""
|
|
75
|
+
# Configure tool-specific resolution with standard fuzzy matching
|
|
76
|
+
get_by_id = client.get_tool
|
|
77
|
+
find_by_name = client.find_tools
|
|
60
78
|
return resolve_resource_reference(
|
|
61
79
|
ctx,
|
|
62
80
|
client,
|
|
63
81
|
ref,
|
|
64
82
|
"tool",
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
get_by_id,
|
|
84
|
+
find_by_name,
|
|
67
85
|
"Tool",
|
|
68
86
|
select=select,
|
|
69
87
|
)
|
|
@@ -97,22 +115,20 @@ def _validate_name_match(provided: str | None, internal: str) -> str:
|
|
|
97
115
|
|
|
98
116
|
def _check_duplicate_name(client: Any, tool_name: str) -> None:
|
|
99
117
|
"""Raise if a tool with the same name already exists."""
|
|
100
|
-
|
|
118
|
+
|
|
119
|
+
def _check_duplicate() -> None:
|
|
101
120
|
existing = client.find_tools(name=tool_name)
|
|
102
121
|
if existing:
|
|
103
122
|
raise click.ClickException(
|
|
104
123
|
f"A tool named '{tool_name}' already exists. "
|
|
105
124
|
"Please change your plugin's 'name' to a unique value, then re-run."
|
|
106
125
|
)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
raise
|
|
110
|
-
except Exception:
|
|
111
|
-
# Non-fatal: best-effort duplicate check for other errors
|
|
112
|
-
pass
|
|
126
|
+
|
|
127
|
+
handle_best_effort_check(_check_duplicate)
|
|
113
128
|
|
|
114
129
|
|
|
115
130
|
def _parse_tags(tags: str | None) -> list[str]:
|
|
131
|
+
"""Return a cleaned list of tag strings from a comma-separated input."""
|
|
116
132
|
return [t.strip() for t in (tags.split(",") if tags else []) if t.strip()]
|
|
117
133
|
|
|
118
134
|
|
|
@@ -174,9 +190,7 @@ def _validate_creation_parameters(
|
|
|
174
190
|
) -> None:
|
|
175
191
|
"""Validate required parameters for tool creation."""
|
|
176
192
|
if not file and not import_file:
|
|
177
|
-
raise click.ClickException(
|
|
178
|
-
"A tool file must be provided. Use --file to specify the tool file to upload."
|
|
179
|
-
)
|
|
193
|
+
raise click.ClickException("A tool file must be provided. Use --file to specify the tool file to upload.")
|
|
180
194
|
|
|
181
195
|
|
|
182
196
|
@tools_group.command(name="list")
|
|
@@ -193,26 +207,39 @@ def list_tools(ctx: Any, tool_type: str | None) -> None:
|
|
|
193
207
|
"""List all tools."""
|
|
194
208
|
try:
|
|
195
209
|
client = get_client(ctx)
|
|
196
|
-
|
|
210
|
+
with spinner_context(
|
|
211
|
+
ctx,
|
|
212
|
+
"[bold blue]Fetching tools…[/bold blue]",
|
|
213
|
+
console_override=console,
|
|
214
|
+
):
|
|
215
|
+
tools = client.list_tools(tool_type=tool_type)
|
|
197
216
|
|
|
198
217
|
# Define table columns: (data_key, header, style, width)
|
|
199
218
|
columns = [
|
|
200
219
|
("id", "ID", "dim", 36),
|
|
201
|
-
("name", "Name",
|
|
202
|
-
("framework", "Framework",
|
|
220
|
+
("name", "Name", ACCENT_STYLE, None),
|
|
221
|
+
("framework", "Framework", INFO, None),
|
|
203
222
|
]
|
|
204
223
|
|
|
205
224
|
# Transform function for safe dictionary access
|
|
206
225
|
def transform_tool(tool: Any) -> dict[str, Any]:
|
|
226
|
+
"""Transform a tool object to a display row dictionary.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
tool: Tool object to transform.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
Dictionary with id, name, and framework fields.
|
|
233
|
+
"""
|
|
207
234
|
row = coerce_to_row(tool, ["id", "name", "framework"])
|
|
208
235
|
# Ensure id is always a string
|
|
209
236
|
row["id"] = str(row["id"])
|
|
210
237
|
return row
|
|
211
238
|
|
|
212
|
-
output_list(ctx, tools, "
|
|
239
|
+
output_list(ctx, tools, f"{ICON_TOOL} Available Tools", columns, transform_tool)
|
|
213
240
|
|
|
214
241
|
except Exception as e:
|
|
215
|
-
raise click.ClickException(str(e))
|
|
242
|
+
raise click.ClickException(str(e)) from e
|
|
216
243
|
|
|
217
244
|
|
|
218
245
|
@tools_group.command()
|
|
@@ -251,8 +278,9 @@ def create(
|
|
|
251
278
|
tags: tuple[str, ...] | None,
|
|
252
279
|
import_file: str | None,
|
|
253
280
|
) -> None:
|
|
254
|
-
"""Create a new tool.
|
|
281
|
+
r"""Create a new tool.
|
|
255
282
|
|
|
283
|
+
\b
|
|
256
284
|
Examples:
|
|
257
285
|
aip tools create tool.py # Create from file
|
|
258
286
|
aip tools create --import tool.json # Create from exported configuration
|
|
@@ -276,7 +304,12 @@ def create(
|
|
|
276
304
|
_validate_creation_parameters(file, import_file)
|
|
277
305
|
|
|
278
306
|
# Create tool from file (either direct file or import file)
|
|
279
|
-
|
|
307
|
+
with spinner_context(
|
|
308
|
+
ctx,
|
|
309
|
+
"[bold blue]Creating tool…[/bold blue]",
|
|
310
|
+
console_override=console,
|
|
311
|
+
):
|
|
312
|
+
tool = _create_tool_from_file(client, file, name, description, tags)
|
|
280
313
|
|
|
281
314
|
# Handle JSON output
|
|
282
315
|
handle_json_output(ctx, tool.model_dump())
|
|
@@ -298,7 +331,7 @@ def create(
|
|
|
298
331
|
handle_json_output(ctx, error=e)
|
|
299
332
|
if get_ctx_value(ctx, "view") != "json":
|
|
300
333
|
display_api_error(e, "tool creation")
|
|
301
|
-
raise click.ClickException(str(e))
|
|
334
|
+
raise click.ClickException(str(e)) from e
|
|
302
335
|
|
|
303
336
|
|
|
304
337
|
@tools_group.command()
|
|
@@ -312,8 +345,9 @@ def create(
|
|
|
312
345
|
@output_flags()
|
|
313
346
|
@click.pass_context
|
|
314
347
|
def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None:
|
|
315
|
-
"""Get tool details.
|
|
348
|
+
r"""Get tool details.
|
|
316
349
|
|
|
350
|
+
\b
|
|
317
351
|
Examples:
|
|
318
352
|
aip tools get my-tool
|
|
319
353
|
aip tools get my-tool --export tool.json # Exports complete configuration as JSON
|
|
@@ -327,54 +361,38 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
|
|
|
327
361
|
|
|
328
362
|
# Handle export option
|
|
329
363
|
if export:
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
except Exception as e:
|
|
338
|
-
console.print(
|
|
339
|
-
Text(f"[yellow]⚠️ Could not fetch full tool details: {e}[/yellow]")
|
|
340
|
-
)
|
|
341
|
-
console.print(
|
|
342
|
-
Text("[yellow]⚠️ Proceeding with available data[/yellow]")
|
|
343
|
-
)
|
|
344
|
-
|
|
345
|
-
export_resource_to_file(tool, export_path, detected_format)
|
|
346
|
-
console.print(
|
|
347
|
-
Text(
|
|
348
|
-
f"[green]✅ Complete tool configuration exported to: {export_path} (format: {detected_format})[/green]"
|
|
349
|
-
)
|
|
364
|
+
handle_resource_export(
|
|
365
|
+
ctx,
|
|
366
|
+
tool,
|
|
367
|
+
Path(export),
|
|
368
|
+
resource_type="tool",
|
|
369
|
+
get_by_id_func=client.get_tool_by_id,
|
|
370
|
+
console_override=console,
|
|
350
371
|
)
|
|
351
372
|
|
|
352
373
|
# Try to fetch raw API data first to preserve ALL fields
|
|
353
|
-
|
|
374
|
+
with spinner_context(
|
|
375
|
+
ctx,
|
|
376
|
+
"[bold blue]Fetching detailed tool data…[/bold blue]",
|
|
377
|
+
console_override=console,
|
|
378
|
+
):
|
|
379
|
+
raw_tool_data = fetch_raw_resource_details(client, tool, "tools")
|
|
354
380
|
|
|
355
381
|
if raw_tool_data:
|
|
356
382
|
# Use raw API data - this preserves ALL fields
|
|
357
383
|
# Format dates for better display (minimal postprocessing)
|
|
358
|
-
formatted_data = raw_tool_data
|
|
359
|
-
if "created_at" in formatted_data:
|
|
360
|
-
formatted_data["created_at"] = format_datetime(
|
|
361
|
-
formatted_data["created_at"]
|
|
362
|
-
)
|
|
363
|
-
if "updated_at" in formatted_data:
|
|
364
|
-
formatted_data["updated_at"] = format_datetime(
|
|
365
|
-
formatted_data["updated_at"]
|
|
366
|
-
)
|
|
384
|
+
formatted_data = format_datetime_fields(raw_tool_data)
|
|
367
385
|
|
|
368
386
|
# Display using output_result with raw data
|
|
369
387
|
output_result(
|
|
370
388
|
ctx,
|
|
371
389
|
formatted_data,
|
|
372
390
|
title="Tool Details",
|
|
373
|
-
panel_title=f"
|
|
391
|
+
panel_title=f"{ICON_TOOL} {raw_tool_data.get('name', 'Unknown')}",
|
|
374
392
|
)
|
|
375
393
|
else:
|
|
376
394
|
# Fall back to original method if raw fetch fails
|
|
377
|
-
console.print("[
|
|
395
|
+
console.print(f"[{WARNING_STYLE}]Falling back to Pydantic model data[/]")
|
|
378
396
|
|
|
379
397
|
# Create result data with all available fields from backend
|
|
380
398
|
result_data = {
|
|
@@ -387,11 +405,14 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
|
|
|
387
405
|
}
|
|
388
406
|
|
|
389
407
|
output_result(
|
|
390
|
-
ctx,
|
|
408
|
+
ctx,
|
|
409
|
+
result_data,
|
|
410
|
+
title="Tool Details",
|
|
411
|
+
panel_title=f"{ICON_TOOL} {tool.name}",
|
|
391
412
|
)
|
|
392
413
|
|
|
393
414
|
except Exception as e:
|
|
394
|
-
raise click.ClickException(str(e))
|
|
415
|
+
raise click.ClickException(str(e)) from e
|
|
395
416
|
|
|
396
417
|
|
|
397
418
|
@tools_group.command()
|
|
@@ -418,9 +439,14 @@ def update(
|
|
|
418
439
|
|
|
419
440
|
# Get tool by ID (no ambiguity handling needed)
|
|
420
441
|
try:
|
|
421
|
-
|
|
442
|
+
with spinner_context(
|
|
443
|
+
ctx,
|
|
444
|
+
"[bold blue]Fetching tool…[/bold blue]",
|
|
445
|
+
console_override=console,
|
|
446
|
+
):
|
|
447
|
+
tool = client.get_tool_by_id(tool_id)
|
|
422
448
|
except Exception as e:
|
|
423
|
-
raise click.ClickException(f"Tool with ID '{tool_id}' not found: {e}")
|
|
449
|
+
raise click.ClickException(f"Tool with ID '{tool_id}' not found: {e}") from e
|
|
424
450
|
|
|
425
451
|
# Prepare update data
|
|
426
452
|
update_data = {}
|
|
@@ -433,24 +459,35 @@ def update(
|
|
|
433
459
|
# Update code via file upload (custom tools only)
|
|
434
460
|
if tool.tool_type != "custom":
|
|
435
461
|
raise click.ClickException(
|
|
436
|
-
|
|
462
|
+
"File updates are only supported for custom tools. "
|
|
463
|
+
f"Tool '{tool.name}' is of type '{tool.tool_type}'."
|
|
437
464
|
)
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
465
|
+
with spinner_context(
|
|
466
|
+
ctx,
|
|
467
|
+
"[bold blue]Uploading new tool code…[/bold blue]",
|
|
468
|
+
console_override=console,
|
|
469
|
+
):
|
|
470
|
+
updated_tool = client.tools.update_tool_via_file(tool.id, file, framework=tool.framework)
|
|
441
471
|
handle_rich_output(
|
|
442
|
-
ctx,
|
|
472
|
+
ctx,
|
|
473
|
+
markup_text(f"[{SUCCESS_STYLE}]✓[/] Tool code updated from {file}"),
|
|
443
474
|
)
|
|
444
475
|
elif update_data:
|
|
445
476
|
# Update metadata only (native tools only)
|
|
446
477
|
if tool.tool_type != "native":
|
|
447
478
|
raise click.ClickException(
|
|
448
|
-
|
|
479
|
+
"Metadata updates are only supported for native tools. "
|
|
480
|
+
f"Tool '{tool.name}' is of type '{tool.tool_type}'."
|
|
449
481
|
)
|
|
450
|
-
|
|
451
|
-
|
|
482
|
+
with spinner_context(
|
|
483
|
+
ctx,
|
|
484
|
+
"[bold blue]Updating tool metadata…[/bold blue]",
|
|
485
|
+
console_override=console,
|
|
486
|
+
):
|
|
487
|
+
updated_tool = tool.update(**update_data)
|
|
488
|
+
handle_rich_output(ctx, markup_text(f"[{SUCCESS_STYLE}]✓[/] Tool metadata updated"))
|
|
452
489
|
else:
|
|
453
|
-
handle_rich_output(ctx,
|
|
490
|
+
handle_rich_output(ctx, markup_text(f"[{WARNING_STYLE}]No updates specified[/]"))
|
|
454
491
|
return
|
|
455
492
|
|
|
456
493
|
handle_json_output(ctx, updated_tool.model_dump())
|
|
@@ -460,7 +497,7 @@ def update(
|
|
|
460
497
|
handle_json_output(ctx, error=e)
|
|
461
498
|
if get_ctx_value(ctx, "view") != "json":
|
|
462
499
|
display_api_error(e, "tool update")
|
|
463
|
-
raise click.ClickException(str(e))
|
|
500
|
+
raise click.ClickException(str(e)) from e
|
|
464
501
|
|
|
465
502
|
|
|
466
503
|
@tools_group.command()
|
|
@@ -475,15 +512,25 @@ def delete(ctx: Any, tool_id: str, yes: bool) -> None:
|
|
|
475
512
|
|
|
476
513
|
# Get tool by ID (no ambiguity handling needed)
|
|
477
514
|
try:
|
|
478
|
-
|
|
515
|
+
with spinner_context(
|
|
516
|
+
ctx,
|
|
517
|
+
"[bold blue]Fetching tool…[/bold blue]",
|
|
518
|
+
console_override=console,
|
|
519
|
+
):
|
|
520
|
+
tool = client.get_tool_by_id(tool_id)
|
|
479
521
|
except Exception as e:
|
|
480
|
-
raise click.ClickException(f"Tool with ID '{tool_id}' not found: {e}")
|
|
522
|
+
raise click.ClickException(f"Tool with ID '{tool_id}' not found: {e}") from e
|
|
481
523
|
|
|
482
524
|
# Confirm deletion via centralized display helper
|
|
483
525
|
if not yes and not display_confirmation_prompt("Tool", tool.name):
|
|
484
526
|
return
|
|
485
527
|
|
|
486
|
-
|
|
528
|
+
with spinner_context(
|
|
529
|
+
ctx,
|
|
530
|
+
"[bold blue]Deleting tool…[/bold blue]",
|
|
531
|
+
console_override=console,
|
|
532
|
+
):
|
|
533
|
+
tool.delete()
|
|
487
534
|
|
|
488
535
|
handle_json_output(
|
|
489
536
|
ctx,
|
|
@@ -498,7 +545,7 @@ def delete(ctx: Any, tool_id: str, yes: bool) -> None:
|
|
|
498
545
|
handle_json_output(ctx, error=e)
|
|
499
546
|
if get_ctx_value(ctx, "view") != "json":
|
|
500
547
|
display_api_error(e, "tool deletion")
|
|
501
|
-
raise click.ClickException(str(e))
|
|
548
|
+
raise click.ClickException(str(e)) from e
|
|
502
549
|
|
|
503
550
|
|
|
504
551
|
@tools_group.command("script")
|
|
@@ -509,16 +556,21 @@ def script(ctx: Any, tool_id: str) -> None:
|
|
|
509
556
|
"""Get tool script content."""
|
|
510
557
|
try:
|
|
511
558
|
client = get_client(ctx)
|
|
512
|
-
|
|
559
|
+
with spinner_context(
|
|
560
|
+
ctx,
|
|
561
|
+
"[bold blue]Fetching tool script…[/bold blue]",
|
|
562
|
+
console_override=console,
|
|
563
|
+
):
|
|
564
|
+
script_content = client.get_tool_script(tool_id)
|
|
513
565
|
|
|
514
566
|
if get_ctx_value(ctx, "view") == "json":
|
|
515
567
|
click.echo(json.dumps({"script": script_content}, indent=2))
|
|
516
568
|
else:
|
|
517
|
-
console.print(f"[
|
|
569
|
+
console.print(f"[{SUCCESS_STYLE}]📜 Tool Script for '{tool_id}':[/]")
|
|
518
570
|
console.print(script_content)
|
|
519
571
|
|
|
520
572
|
except Exception as e:
|
|
521
573
|
handle_json_output(ctx, error=e)
|
|
522
574
|
if get_ctx_value(ctx, "view") != "json":
|
|
523
|
-
|
|
524
|
-
raise click.ClickException(str(e))
|
|
575
|
+
print_markup(f"[{ERROR_STYLE}]Error getting tool script: {e}[/]", console=console)
|
|
576
|
+
raise click.ClickException(str(e)) from e
|