glaip-sdk 0.0.5b1__py3-none-any.whl → 0.0.6a0__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 +1 -1
- glaip_sdk/branding.py +3 -2
- glaip_sdk/cli/commands/__init__.py +1 -1
- glaip_sdk/cli/commands/agents.py +444 -268
- glaip_sdk/cli/commands/configure.py +12 -11
- glaip_sdk/cli/commands/mcps.py +28 -16
- glaip_sdk/cli/commands/models.py +5 -3
- glaip_sdk/cli/commands/tools.py +109 -102
- glaip_sdk/cli/display.py +38 -16
- glaip_sdk/cli/io.py +1 -1
- glaip_sdk/cli/main.py +26 -5
- glaip_sdk/cli/resolution.py +5 -4
- glaip_sdk/cli/utils.py +376 -157
- glaip_sdk/cli/validators.py +7 -2
- glaip_sdk/client/agents.py +184 -89
- glaip_sdk/client/base.py +24 -13
- glaip_sdk/client/validators.py +154 -94
- glaip_sdk/config/constants.py +0 -2
- glaip_sdk/models.py +4 -4
- glaip_sdk/utils/__init__.py +7 -7
- glaip_sdk/utils/client_utils.py +144 -78
- glaip_sdk/utils/display.py +4 -2
- glaip_sdk/utils/general.py +8 -6
- glaip_sdk/utils/import_export.py +55 -24
- glaip_sdk/utils/rendering/formatting.py +12 -6
- glaip_sdk/utils/rendering/models.py +1 -1
- glaip_sdk/utils/rendering/renderer/base.py +412 -248
- glaip_sdk/utils/rendering/renderer/console.py +6 -5
- glaip_sdk/utils/rendering/renderer/debug.py +94 -52
- glaip_sdk/utils/rendering/renderer/stream.py +93 -48
- glaip_sdk/utils/rendering/steps.py +103 -39
- glaip_sdk/utils/rich_utils.py +1 -1
- glaip_sdk/utils/run_renderer.py +1 -1
- glaip_sdk/utils/serialization.py +3 -1
- glaip_sdk/utils/validation.py +2 -2
- glaip_sdk-0.0.6a0.dist-info/METADATA +183 -0
- glaip_sdk-0.0.6a0.dist-info/RECORD +55 -0
- glaip_sdk-0.0.5b1.dist-info/METADATA +0 -645
- glaip_sdk-0.0.5b1.dist-info/RECORD +0 -55
- {glaip_sdk-0.0.5b1.dist-info → glaip_sdk-0.0.6a0.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.5b1.dist-info → glaip_sdk-0.0.6a0.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/commands/agents.py
CHANGED
|
@@ -7,6 +7,7 @@ Authors:
|
|
|
7
7
|
import json
|
|
8
8
|
import os
|
|
9
9
|
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
10
11
|
|
|
11
12
|
import click
|
|
12
13
|
from rich.console import Console
|
|
@@ -47,6 +48,7 @@ from glaip_sdk.cli.utils import (
|
|
|
47
48
|
build_renderer,
|
|
48
49
|
coerce_to_row,
|
|
49
50
|
get_client,
|
|
51
|
+
get_ctx_value,
|
|
50
52
|
output_flags,
|
|
51
53
|
output_list,
|
|
52
54
|
output_result,
|
|
@@ -73,7 +75,7 @@ console = Console()
|
|
|
73
75
|
AGENT_NOT_FOUND_ERROR = "Agent not found"
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
def _fetch_full_agent_details(client, agent):
|
|
78
|
+
def _fetch_full_agent_details(client: Any, agent: Any) -> Any | None:
|
|
77
79
|
"""Fetch full agent details by ID to ensure all fields are populated."""
|
|
78
80
|
try:
|
|
79
81
|
agent_id = str(getattr(agent, "id", "")).strip()
|
|
@@ -85,7 +87,7 @@ def _fetch_full_agent_details(client, agent):
|
|
|
85
87
|
return agent
|
|
86
88
|
|
|
87
89
|
|
|
88
|
-
def _get_agent_model_name(agent):
|
|
90
|
+
def _get_agent_model_name(agent: Any) -> str | None:
|
|
89
91
|
"""Extract model name from agent configuration."""
|
|
90
92
|
# Try different possible locations for model name
|
|
91
93
|
if hasattr(agent, "agent_config") and agent.agent_config:
|
|
@@ -100,7 +102,7 @@ def _get_agent_model_name(agent):
|
|
|
100
102
|
|
|
101
103
|
|
|
102
104
|
def _resolve_resources_by_name(
|
|
103
|
-
_client, items: tuple[str, ...], resource_type: str, find_func, label: str
|
|
105
|
+
_client: Any, items: tuple[str, ...], resource_type: str, find_func: Any, label: str
|
|
104
106
|
) -> list[str]:
|
|
105
107
|
"""Resolve resource names/IDs to IDs, handling ambiguity.
|
|
106
108
|
|
|
@@ -131,90 +133,112 @@ def _resolve_resources_by_name(
|
|
|
131
133
|
return out
|
|
132
134
|
|
|
133
135
|
|
|
134
|
-
def
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
# Try to fetch raw API data first to preserve ALL fields
|
|
141
|
-
raw_agent_data = fetch_raw_resource_details(client, agent, "agents")
|
|
136
|
+
def _fetch_and_format_raw_agent_data(client: Any, agent: Any) -> dict | None:
|
|
137
|
+
"""Fetch raw agent data and format it for display."""
|
|
138
|
+
try:
|
|
139
|
+
raw_agent_data = fetch_raw_resource_details(client, agent, "agents")
|
|
140
|
+
if not raw_agent_data:
|
|
141
|
+
return None
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
# Use raw API data - this preserves ALL fields including account_id
|
|
145
|
-
# Format dates for better display (minimal postprocessing)
|
|
143
|
+
# Format dates for better display
|
|
146
144
|
formatted_data = raw_agent_data.copy()
|
|
147
145
|
if "created_at" in formatted_data:
|
|
148
146
|
formatted_data["created_at"] = format_datetime(formatted_data["created_at"])
|
|
149
147
|
if "updated_at" in formatted_data:
|
|
150
148
|
formatted_data["updated_at"] = format_datetime(formatted_data["updated_at"])
|
|
151
149
|
|
|
152
|
-
|
|
150
|
+
return formatted_data
|
|
151
|
+
except Exception:
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _format_fallback_agent_data(client: Any, agent: Any) -> dict:
|
|
156
|
+
"""Format fallback agent data using Pydantic model."""
|
|
157
|
+
full_agent = _fetch_full_agent_details(client, agent)
|
|
158
|
+
|
|
159
|
+
# Define fields to extract
|
|
160
|
+
fields = [
|
|
161
|
+
"id",
|
|
162
|
+
"name",
|
|
163
|
+
"type",
|
|
164
|
+
"framework",
|
|
165
|
+
"version",
|
|
166
|
+
"description",
|
|
167
|
+
"instruction",
|
|
168
|
+
"created_at",
|
|
169
|
+
"updated_at",
|
|
170
|
+
"metadata",
|
|
171
|
+
"language_model_id",
|
|
172
|
+
"agent_config",
|
|
173
|
+
"tool_configs",
|
|
174
|
+
"tools",
|
|
175
|
+
"agents",
|
|
176
|
+
"mcps",
|
|
177
|
+
"a2a_profile",
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
result_data = build_resource_result_data(full_agent, fields)
|
|
181
|
+
|
|
182
|
+
# Handle missing instruction
|
|
183
|
+
if not result_data.get("instruction"):
|
|
184
|
+
result_data["instruction"] = "-"
|
|
185
|
+
|
|
186
|
+
# Format dates for better display
|
|
187
|
+
for date_field in ["created_at", "updated_at"]:
|
|
188
|
+
if result_data.get(date_field) and result_data[date_field] not in ["N/A", None]:
|
|
189
|
+
result_data[date_field] = format_datetime(result_data[date_field])
|
|
190
|
+
|
|
191
|
+
return result_data
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _display_agent_details(ctx: Any, client: Any, agent: Any) -> None:
|
|
195
|
+
"""Display full agent details using raw API data to preserve ALL fields."""
|
|
196
|
+
if agent is None:
|
|
197
|
+
handle_rich_output(ctx, Text("[red]❌ No agent provided[/red]"))
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
# Try to fetch and format raw agent data first
|
|
201
|
+
formatted_data = _fetch_and_format_raw_agent_data(client, agent)
|
|
202
|
+
|
|
203
|
+
if formatted_data:
|
|
204
|
+
# Use raw API data - this preserves ALL fields including account_id
|
|
205
|
+
panel_title = f"🤖 {formatted_data.get('name', 'Unknown')}"
|
|
153
206
|
output_result(
|
|
154
207
|
ctx,
|
|
155
208
|
formatted_data,
|
|
156
209
|
title="Agent Details",
|
|
157
|
-
panel_title=
|
|
210
|
+
panel_title=panel_title,
|
|
158
211
|
)
|
|
159
212
|
else:
|
|
160
|
-
# Fall back to
|
|
213
|
+
# Fall back to Pydantic model data if raw fetch fails
|
|
161
214
|
handle_rich_output(
|
|
162
215
|
ctx, Text("[yellow]Falling back to Pydantic model data[/yellow]")
|
|
163
216
|
)
|
|
164
|
-
full_agent = _fetch_full_agent_details(client, agent)
|
|
165
|
-
|
|
166
|
-
# Build result data using standardized helper
|
|
167
|
-
fields = [
|
|
168
|
-
"id",
|
|
169
|
-
"name",
|
|
170
|
-
"type",
|
|
171
|
-
"framework",
|
|
172
|
-
"version",
|
|
173
|
-
"description",
|
|
174
|
-
"instruction",
|
|
175
|
-
"created_at",
|
|
176
|
-
"updated_at",
|
|
177
|
-
"metadata",
|
|
178
|
-
"language_model_id",
|
|
179
|
-
"agent_config",
|
|
180
|
-
"tool_configs",
|
|
181
|
-
"tools",
|
|
182
|
-
"agents",
|
|
183
|
-
"mcps",
|
|
184
|
-
"a2a_profile",
|
|
185
|
-
]
|
|
186
|
-
result_data = build_resource_result_data(full_agent, fields)
|
|
187
|
-
if not result_data.get("instruction"):
|
|
188
|
-
result_data["instruction"] = "-" # pragma: no cover - cosmetic fallback
|
|
189
217
|
|
|
190
|
-
|
|
191
|
-
if "created_at" in result_data and result_data["created_at"] not in [
|
|
192
|
-
"N/A",
|
|
193
|
-
None,
|
|
194
|
-
]:
|
|
195
|
-
result_data["created_at"] = format_datetime(result_data["created_at"])
|
|
196
|
-
if "updated_at" in result_data and result_data["updated_at"] not in [
|
|
197
|
-
"N/A",
|
|
198
|
-
None,
|
|
199
|
-
]:
|
|
200
|
-
result_data["updated_at"] = format_datetime(result_data["updated_at"])
|
|
218
|
+
result_data = _format_fallback_agent_data(client, agent)
|
|
201
219
|
|
|
202
220
|
# Display using output_result
|
|
203
221
|
output_result(
|
|
204
222
|
ctx,
|
|
205
223
|
result_data,
|
|
206
224
|
title="Agent Details",
|
|
207
|
-
panel_title=f"🤖 {
|
|
225
|
+
panel_title=f"🤖 {result_data.get('name', 'Unknown')}",
|
|
208
226
|
)
|
|
209
227
|
|
|
210
228
|
|
|
211
229
|
@click.group(name="agents", no_args_is_help=True)
|
|
212
|
-
def agents_group():
|
|
230
|
+
def agents_group() -> None:
|
|
213
231
|
"""Agent management operations."""
|
|
214
232
|
pass
|
|
215
233
|
|
|
216
234
|
|
|
217
|
-
def _resolve_agent(
|
|
235
|
+
def _resolve_agent(
|
|
236
|
+
ctx: Any,
|
|
237
|
+
client: Any,
|
|
238
|
+
ref: str,
|
|
239
|
+
select: int | None = None,
|
|
240
|
+
interface_preference: str = "fuzzy",
|
|
241
|
+
) -> Any | None:
|
|
218
242
|
"""Resolve agent reference (ID or name) with ambiguity handling.
|
|
219
243
|
|
|
220
244
|
Args:
|
|
@@ -252,7 +276,15 @@ def _resolve_agent(ctx, client, ref, select=None, interface_preference="fuzzy"):
|
|
|
252
276
|
)
|
|
253
277
|
@output_flags()
|
|
254
278
|
@click.pass_context
|
|
255
|
-
def list_agents(
|
|
279
|
+
def list_agents(
|
|
280
|
+
ctx: Any,
|
|
281
|
+
simple: bool,
|
|
282
|
+
agent_type: str | None,
|
|
283
|
+
framework: str | None,
|
|
284
|
+
name: str | None,
|
|
285
|
+
version: str | None,
|
|
286
|
+
sync_langflow: bool,
|
|
287
|
+
) -> None:
|
|
256
288
|
"""List agents with optional filtering."""
|
|
257
289
|
try:
|
|
258
290
|
client = get_client(ctx)
|
|
@@ -274,7 +306,7 @@ def list_agents(ctx, simple, agent_type, framework, name, version, sync_langflow
|
|
|
274
306
|
]
|
|
275
307
|
|
|
276
308
|
# Transform function for safe attribute access
|
|
277
|
-
def transform_agent(agent):
|
|
309
|
+
def transform_agent(agent: Any) -> dict[str, Any]:
|
|
278
310
|
row = coerce_to_row(agent, ["id", "name", "type", "framework", "version"])
|
|
279
311
|
# Ensure id is always a string
|
|
280
312
|
row["id"] = str(row["id"])
|
|
@@ -307,7 +339,7 @@ def list_agents(ctx, simple, agent_type, framework, name, version, sync_langflow
|
|
|
307
339
|
)
|
|
308
340
|
@output_flags()
|
|
309
341
|
@click.pass_context
|
|
310
|
-
def get(ctx, agent_ref, select, export):
|
|
342
|
+
def get(ctx: Any, agent_ref: str, select: int | None, export: str | None) -> None:
|
|
311
343
|
"""Get agent details.
|
|
312
344
|
|
|
313
345
|
Examples:
|
|
@@ -364,7 +396,7 @@ def get(ctx, agent_ref, select, export):
|
|
|
364
396
|
raise click.ClickException(str(e))
|
|
365
397
|
|
|
366
398
|
|
|
367
|
-
def _validate_run_input(input_option, input_text):
|
|
399
|
+
def _validate_run_input(input_option: str | None, input_text: str | None) -> str:
|
|
368
400
|
"""Validate and determine the final input text for agent run."""
|
|
369
401
|
final_input_text = input_option if input_option else input_text
|
|
370
402
|
|
|
@@ -376,7 +408,7 @@ def _validate_run_input(input_option, input_text):
|
|
|
376
408
|
return final_input_text
|
|
377
409
|
|
|
378
410
|
|
|
379
|
-
def _parse_chat_history(chat_history):
|
|
411
|
+
def _parse_chat_history(chat_history: str | None) -> list[dict[str, Any]] | None:
|
|
380
412
|
"""Parse chat history JSON if provided."""
|
|
381
413
|
if not chat_history:
|
|
382
414
|
return None
|
|
@@ -387,9 +419,9 @@ def _parse_chat_history(chat_history):
|
|
|
387
419
|
raise click.ClickException("Invalid JSON in chat history")
|
|
388
420
|
|
|
389
421
|
|
|
390
|
-
def _setup_run_renderer(ctx, save, verbose):
|
|
422
|
+
def _setup_run_renderer(ctx: Any, save: str | None, verbose: bool) -> Any:
|
|
391
423
|
"""Set up renderer and working console for agent run."""
|
|
392
|
-
tty_enabled = bool((ctx
|
|
424
|
+
tty_enabled = bool(get_ctx_value(ctx, "tty", True))
|
|
393
425
|
return build_renderer(
|
|
394
426
|
ctx,
|
|
395
427
|
save_path=save,
|
|
@@ -399,8 +431,13 @@ def _setup_run_renderer(ctx, save, verbose):
|
|
|
399
431
|
|
|
400
432
|
|
|
401
433
|
def _prepare_run_kwargs(
|
|
402
|
-
agent
|
|
403
|
-
|
|
434
|
+
agent: Any,
|
|
435
|
+
final_input_text: str,
|
|
436
|
+
files: list[str] | None,
|
|
437
|
+
parsed_chat_history: list[dict[str, Any]] | None,
|
|
438
|
+
renderer: Any,
|
|
439
|
+
tty_enabled: bool,
|
|
440
|
+
) -> dict[str, Any]:
|
|
404
441
|
"""Prepare kwargs for agent run."""
|
|
405
442
|
run_kwargs = {
|
|
406
443
|
"agent_id": agent.id,
|
|
@@ -419,10 +456,10 @@ def _prepare_run_kwargs(
|
|
|
419
456
|
return run_kwargs
|
|
420
457
|
|
|
421
458
|
|
|
422
|
-
def _handle_run_output(ctx, result, renderer):
|
|
459
|
+
def _handle_run_output(ctx: Any, result: Any, renderer: Any) -> None:
|
|
423
460
|
"""Handle output formatting for agent run results."""
|
|
424
461
|
printed_by_renderer = bool(renderer)
|
|
425
|
-
selected_view = (ctx
|
|
462
|
+
selected_view = get_ctx_value(ctx, "view", "rich")
|
|
426
463
|
|
|
427
464
|
if not printed_by_renderer:
|
|
428
465
|
if selected_view == "json":
|
|
@@ -433,7 +470,7 @@ def _handle_run_output(ctx, result, renderer):
|
|
|
433
470
|
click.echo(result)
|
|
434
471
|
|
|
435
472
|
|
|
436
|
-
def _save_run_transcript(save, result, working_console):
|
|
473
|
+
def _save_run_transcript(save: str | None, result: Any, working_console: Any) -> None:
|
|
437
474
|
"""Save transcript to file if requested."""
|
|
438
475
|
if not save:
|
|
439
476
|
return
|
|
@@ -492,17 +529,17 @@ def _save_run_transcript(save, result, working_console):
|
|
|
492
529
|
@output_flags()
|
|
493
530
|
@click.pass_context
|
|
494
531
|
def run(
|
|
495
|
-
ctx,
|
|
496
|
-
agent_ref,
|
|
497
|
-
select,
|
|
498
|
-
input_text,
|
|
499
|
-
input_option,
|
|
500
|
-
chat_history,
|
|
501
|
-
timeout,
|
|
502
|
-
save,
|
|
503
|
-
files,
|
|
504
|
-
verbose,
|
|
505
|
-
):
|
|
532
|
+
ctx: Any,
|
|
533
|
+
agent_ref: str,
|
|
534
|
+
select: int | None,
|
|
535
|
+
input_text: str | None,
|
|
536
|
+
input_option: str | None,
|
|
537
|
+
chat_history: str | None,
|
|
538
|
+
timeout: float | None,
|
|
539
|
+
save: str | None,
|
|
540
|
+
files: tuple[str, ...] | None,
|
|
541
|
+
verbose: bool,
|
|
542
|
+
) -> None:
|
|
506
543
|
"""Run an agent with input text.
|
|
507
544
|
|
|
508
545
|
Usage: aip agents run <agent_ref> <input_text> [OPTIONS]
|
|
@@ -534,7 +571,7 @@ def run(
|
|
|
534
571
|
files,
|
|
535
572
|
parsed_chat_history,
|
|
536
573
|
renderer,
|
|
537
|
-
bool((ctx
|
|
574
|
+
bool(get_ctx_value(ctx, "tty", True)),
|
|
538
575
|
)
|
|
539
576
|
|
|
540
577
|
result = client.agents.run_agent(**run_kwargs, timeout=timeout)
|
|
@@ -551,6 +588,229 @@ def run(
|
|
|
551
588
|
raise click.ClickException(str(e))
|
|
552
589
|
|
|
553
590
|
|
|
591
|
+
def _handle_import_file_logic(
|
|
592
|
+
import_file: str,
|
|
593
|
+
model: str | None,
|
|
594
|
+
name: str,
|
|
595
|
+
instruction: str,
|
|
596
|
+
tools: tuple[str, ...],
|
|
597
|
+
agents: tuple[str, ...],
|
|
598
|
+
mcps: tuple[str, ...],
|
|
599
|
+
timeout: float | None,
|
|
600
|
+
) -> dict[str, Any]:
|
|
601
|
+
"""Handle import file logic and merge with CLI args."""
|
|
602
|
+
import_data = load_resource_from_file(Path(import_file), "agent")
|
|
603
|
+
import_data = convert_export_to_import_format(import_data)
|
|
604
|
+
import_data = normalize_agent_config_for_import(import_data, model)
|
|
605
|
+
|
|
606
|
+
cli_args = {
|
|
607
|
+
"name": name,
|
|
608
|
+
"instruction": instruction,
|
|
609
|
+
"model": model,
|
|
610
|
+
"tools": tools or (),
|
|
611
|
+
"agents": agents or (),
|
|
612
|
+
"mcps": mcps or (),
|
|
613
|
+
"timeout": timeout if timeout != DEFAULT_AGENT_RUN_TIMEOUT else None,
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
return merge_import_with_cli_args(import_data, cli_args)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def _build_cli_args_data(
|
|
620
|
+
name: str,
|
|
621
|
+
instruction: str,
|
|
622
|
+
model: str | None,
|
|
623
|
+
tools: tuple[str, ...],
|
|
624
|
+
agents: tuple[str, ...],
|
|
625
|
+
mcps: tuple[str, ...],
|
|
626
|
+
timeout: float | None,
|
|
627
|
+
) -> dict[str, Any]:
|
|
628
|
+
"""Build merged data from CLI arguments."""
|
|
629
|
+
return {
|
|
630
|
+
"name": name,
|
|
631
|
+
"instruction": instruction,
|
|
632
|
+
"model": model,
|
|
633
|
+
"tools": tools or (),
|
|
634
|
+
"agents": agents or (),
|
|
635
|
+
"mcps": mcps or (),
|
|
636
|
+
"timeout": timeout if timeout != DEFAULT_AGENT_RUN_TIMEOUT else None,
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def _extract_and_validate_fields(
|
|
641
|
+
merged_data: dict[str, Any],
|
|
642
|
+
) -> tuple[str, str, str | None, tuple, tuple, tuple, Any]:
|
|
643
|
+
"""Extract and validate required fields from merged data."""
|
|
644
|
+
name = merged_data.get("name")
|
|
645
|
+
instruction = merged_data.get("instruction")
|
|
646
|
+
model = merged_data.get("model")
|
|
647
|
+
tools = tuple(merged_data.get("tools", ()))
|
|
648
|
+
agents = tuple(merged_data.get("agents", ()))
|
|
649
|
+
mcps = tuple(merged_data.get("mcps", ()))
|
|
650
|
+
timeout = merged_data.get("timeout", DEFAULT_AGENT_RUN_TIMEOUT)
|
|
651
|
+
|
|
652
|
+
# Validate required fields
|
|
653
|
+
if not name:
|
|
654
|
+
raise click.ClickException("Agent name is required (--name or --import)")
|
|
655
|
+
if not instruction:
|
|
656
|
+
raise click.ClickException(
|
|
657
|
+
"Agent instruction is required (--instruction or --import)"
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
return name, instruction, model, tools, agents, mcps, timeout
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def _validate_and_coerce_fields(
|
|
664
|
+
name: str, instruction: str, timeout: Any
|
|
665
|
+
) -> tuple[str, str, Any]:
|
|
666
|
+
"""Validate and coerce field values."""
|
|
667
|
+
name = validate_agent_name(name)
|
|
668
|
+
instruction = validate_agent_instruction(instruction)
|
|
669
|
+
timeout = coerce_timeout(timeout)
|
|
670
|
+
if timeout is not None:
|
|
671
|
+
timeout = validate_timeout(timeout)
|
|
672
|
+
|
|
673
|
+
return name, instruction, timeout
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def _resolve_resources(
|
|
677
|
+
client: Any, tools: tuple, agents: tuple, mcps: tuple
|
|
678
|
+
) -> tuple[list, list, list]:
|
|
679
|
+
"""Resolve tool, agent, and MCP references."""
|
|
680
|
+
resolved_tools = _resolve_resources_by_name(
|
|
681
|
+
client, tools, "tool", client.find_tools, "Tool"
|
|
682
|
+
)
|
|
683
|
+
resolved_agents = _resolve_resources_by_name(
|
|
684
|
+
client, agents, "agent", client.find_agents, "Agent"
|
|
685
|
+
)
|
|
686
|
+
resolved_mcps = _resolve_resources_by_name(
|
|
687
|
+
client, mcps, "mcp", client.find_mcps, "MCP"
|
|
688
|
+
)
|
|
689
|
+
|
|
690
|
+
return resolved_tools, resolved_agents, resolved_mcps
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def _build_create_kwargs(
|
|
694
|
+
name: str,
|
|
695
|
+
instruction: str,
|
|
696
|
+
resolved_tools: list,
|
|
697
|
+
resolved_agents: list,
|
|
698
|
+
resolved_mcps: list,
|
|
699
|
+
timeout: Any,
|
|
700
|
+
merged_data: dict[str, Any],
|
|
701
|
+
model: str | None,
|
|
702
|
+
import_file: str | None,
|
|
703
|
+
) -> dict[str, Any]:
|
|
704
|
+
"""Build create_agent kwargs with all necessary parameters."""
|
|
705
|
+
create_kwargs = {
|
|
706
|
+
"name": name,
|
|
707
|
+
"instruction": instruction,
|
|
708
|
+
"tools": resolved_tools or None,
|
|
709
|
+
"agents": resolved_agents or None,
|
|
710
|
+
"mcps": resolved_mcps or None,
|
|
711
|
+
"timeout": timeout,
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
# Handle language model selection
|
|
715
|
+
lm_selection_dict, should_strip_lm_identity = resolve_language_model_selection(
|
|
716
|
+
merged_data, model
|
|
717
|
+
)
|
|
718
|
+
create_kwargs.update(lm_selection_dict)
|
|
719
|
+
|
|
720
|
+
# Handle import file specific logic
|
|
721
|
+
if import_file:
|
|
722
|
+
_add_import_file_attributes(
|
|
723
|
+
create_kwargs, merged_data, should_strip_lm_identity
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
return create_kwargs
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
def _add_import_file_attributes(
|
|
730
|
+
create_kwargs: dict[str, Any],
|
|
731
|
+
merged_data: dict[str, Any],
|
|
732
|
+
should_strip_lm_identity: bool,
|
|
733
|
+
) -> None:
|
|
734
|
+
"""Add import file specific attributes to create_kwargs."""
|
|
735
|
+
agent_config_raw = merged_data.get("agent_config")
|
|
736
|
+
if isinstance(agent_config_raw, dict):
|
|
737
|
+
create_kwargs["agent_config"] = sanitize_agent_config(
|
|
738
|
+
agent_config_raw, strip_lm_identity=should_strip_lm_identity
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
# Add other attributes from import data
|
|
742
|
+
excluded_fields = {
|
|
743
|
+
"name",
|
|
744
|
+
"instruction",
|
|
745
|
+
"model",
|
|
746
|
+
"language_model_id",
|
|
747
|
+
"tools",
|
|
748
|
+
"agents",
|
|
749
|
+
"timeout",
|
|
750
|
+
"agent_config",
|
|
751
|
+
"id",
|
|
752
|
+
"created_at",
|
|
753
|
+
"updated_at",
|
|
754
|
+
"type",
|
|
755
|
+
"framework",
|
|
756
|
+
"version",
|
|
757
|
+
"tool_configs",
|
|
758
|
+
"mcps",
|
|
759
|
+
"a2a_profile",
|
|
760
|
+
}
|
|
761
|
+
for key, value in merged_data.items():
|
|
762
|
+
if key not in excluded_fields and value is not None:
|
|
763
|
+
create_kwargs[key] = value
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
def _get_language_model_display_name(agent: Any, model: str | None) -> str:
|
|
767
|
+
"""Get display name for the language model."""
|
|
768
|
+
lm_display = getattr(agent, "model", None)
|
|
769
|
+
if not lm_display:
|
|
770
|
+
cfg = getattr(agent, "agent_config", {}) or {}
|
|
771
|
+
lm_display = (
|
|
772
|
+
cfg.get("lm_name")
|
|
773
|
+
or cfg.get("model")
|
|
774
|
+
or model
|
|
775
|
+
or f"{DEFAULT_MODEL} (backend default)"
|
|
776
|
+
)
|
|
777
|
+
return lm_display
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
def _handle_successful_creation(ctx: Any, agent: Any, model: str | None) -> None:
|
|
781
|
+
"""Handle successful agent creation output."""
|
|
782
|
+
handle_json_output(ctx, agent.model_dump())
|
|
783
|
+
|
|
784
|
+
lm_display = _get_language_model_display_name(agent, model)
|
|
785
|
+
|
|
786
|
+
handle_rich_output(
|
|
787
|
+
ctx,
|
|
788
|
+
display_creation_success(
|
|
789
|
+
"Agent",
|
|
790
|
+
agent.name,
|
|
791
|
+
agent.id,
|
|
792
|
+
Model=lm_display,
|
|
793
|
+
Type=getattr(agent, "type", "config"),
|
|
794
|
+
Framework=getattr(agent, "framework", "langchain"),
|
|
795
|
+
Version=getattr(agent, "version", "1.0"),
|
|
796
|
+
),
|
|
797
|
+
)
|
|
798
|
+
handle_rich_output(ctx, display_agent_run_suggestions(agent))
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
def _handle_creation_exception(ctx: Any, e: Exception) -> None:
|
|
802
|
+
"""Handle exceptions during agent creation."""
|
|
803
|
+
if isinstance(e, click.ClickException):
|
|
804
|
+
if get_ctx_value(ctx, "view") == "json":
|
|
805
|
+
handle_json_output(ctx, error=Exception(AGENT_NOT_FOUND_ERROR))
|
|
806
|
+
raise
|
|
807
|
+
|
|
808
|
+
handle_json_output(ctx, error=e)
|
|
809
|
+
if get_ctx_value(ctx, "view") != "json":
|
|
810
|
+
print_api_error(e)
|
|
811
|
+
raise click.ClickException(str(e))
|
|
812
|
+
|
|
813
|
+
|
|
554
814
|
@agents_group.command()
|
|
555
815
|
@click.option("--name", help="Agent name")
|
|
556
816
|
@click.option("--instruction", help="Agent instruction (prompt)")
|
|
@@ -576,16 +836,16 @@ def run(
|
|
|
576
836
|
@output_flags()
|
|
577
837
|
@click.pass_context
|
|
578
838
|
def create(
|
|
579
|
-
ctx,
|
|
580
|
-
name,
|
|
581
|
-
instruction,
|
|
582
|
-
model,
|
|
583
|
-
tools,
|
|
584
|
-
agents,
|
|
585
|
-
mcps,
|
|
586
|
-
timeout,
|
|
587
|
-
import_file,
|
|
588
|
-
):
|
|
839
|
+
ctx: Any,
|
|
840
|
+
name: str,
|
|
841
|
+
instruction: str,
|
|
842
|
+
model: str | None,
|
|
843
|
+
tools: tuple[str, ...] | None,
|
|
844
|
+
agents: tuple[str, ...] | None,
|
|
845
|
+
mcps: tuple[str, ...] | None,
|
|
846
|
+
timeout: float | None,
|
|
847
|
+
import_file: str | None,
|
|
848
|
+
) -> None:
|
|
589
849
|
"""Create a new agent.
|
|
590
850
|
|
|
591
851
|
Examples:
|
|
@@ -595,181 +855,59 @@ def create(
|
|
|
595
855
|
try:
|
|
596
856
|
client = get_client(ctx)
|
|
597
857
|
|
|
598
|
-
#
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
import_file
|
|
604
|
-
): # pragma: no cover - exercised in higher-level integration tests
|
|
605
|
-
import_data = load_resource_from_file(Path(import_file), "agent")
|
|
606
|
-
|
|
607
|
-
# Convert export format to import-compatible format
|
|
608
|
-
import_data = convert_export_to_import_format(import_data)
|
|
609
|
-
|
|
610
|
-
# Auto-normalize agent config (extract LM settings from agent_config)
|
|
611
|
-
import_data = normalize_agent_config_for_import(import_data, model)
|
|
612
|
-
|
|
613
|
-
# Merge CLI args with imported data
|
|
614
|
-
cli_args = {
|
|
615
|
-
"name": name,
|
|
616
|
-
"instruction": instruction,
|
|
617
|
-
"model": model,
|
|
618
|
-
"tools": tools or (),
|
|
619
|
-
"agents": agents or (),
|
|
620
|
-
"mcps": mcps or (),
|
|
621
|
-
"timeout": timeout if timeout != DEFAULT_AGENT_RUN_TIMEOUT else None,
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
merged_data = merge_import_with_cli_args(import_data, cli_args)
|
|
858
|
+
# Handle import file or CLI args
|
|
859
|
+
if import_file:
|
|
860
|
+
merged_data = _handle_import_file_logic(
|
|
861
|
+
import_file, model, name, instruction, tools, agents, mcps, timeout
|
|
862
|
+
)
|
|
625
863
|
else:
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
"name": name,
|
|
629
|
-
"instruction": instruction,
|
|
630
|
-
"model": model,
|
|
631
|
-
"tools": tools or (),
|
|
632
|
-
"agents": agents or (),
|
|
633
|
-
"mcps": mcps or (),
|
|
634
|
-
"timeout": timeout if timeout != DEFAULT_AGENT_RUN_TIMEOUT else None,
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
# Extract merged values
|
|
638
|
-
name = merged_data.get("name")
|
|
639
|
-
instruction = merged_data.get("instruction")
|
|
640
|
-
model = merged_data.get("model")
|
|
641
|
-
tools = tuple(merged_data.get("tools", ()))
|
|
642
|
-
agents = tuple(merged_data.get("agents", ()))
|
|
643
|
-
mcps = tuple(merged_data.get("mcps", ()))
|
|
644
|
-
timeout = merged_data.get("timeout", DEFAULT_AGENT_RUN_TIMEOUT)
|
|
645
|
-
# Coerce timeout to proper integer type
|
|
646
|
-
timeout = coerce_timeout(timeout)
|
|
647
|
-
|
|
648
|
-
# Validate required fields using centralized validators
|
|
649
|
-
if not name:
|
|
650
|
-
raise click.ClickException("Agent name is required (--name or --import)")
|
|
651
|
-
if not instruction:
|
|
652
|
-
raise click.ClickException(
|
|
653
|
-
"Agent instruction is required (--instruction or --import)"
|
|
864
|
+
merged_data = _build_cli_args_data(
|
|
865
|
+
name, instruction, model, tools, agents, mcps, timeout
|
|
654
866
|
)
|
|
655
867
|
|
|
656
|
-
#
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
)
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
)
|
|
669
|
-
resolved_mcps = _resolve_resources_by_name(
|
|
670
|
-
client, mcps, "mcp", client.find_mcps, "MCP"
|
|
868
|
+
# Extract and validate fields
|
|
869
|
+
(
|
|
870
|
+
name,
|
|
871
|
+
instruction,
|
|
872
|
+
model,
|
|
873
|
+
tools,
|
|
874
|
+
agents,
|
|
875
|
+
mcps,
|
|
876
|
+
timeout,
|
|
877
|
+
) = _extract_and_validate_fields(merged_data)
|
|
878
|
+
name, instruction, timeout = _validate_and_coerce_fields(
|
|
879
|
+
name, instruction, timeout
|
|
671
880
|
)
|
|
672
881
|
|
|
673
|
-
#
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
"instruction": instruction,
|
|
677
|
-
"tools": resolved_tools or None,
|
|
678
|
-
"agents": resolved_agents or None,
|
|
679
|
-
"mcps": resolved_mcps or None,
|
|
680
|
-
"timeout": timeout,
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
# Handle language model selection using helper function
|
|
684
|
-
lm_selection_dict, should_strip_lm_identity = resolve_language_model_selection(
|
|
685
|
-
merged_data, model
|
|
882
|
+
# Resolve resources
|
|
883
|
+
resolved_tools, resolved_agents, resolved_mcps = _resolve_resources(
|
|
884
|
+
client, tools, agents, mcps
|
|
686
885
|
)
|
|
687
|
-
create_kwargs.update(lm_selection_dict)
|
|
688
|
-
|
|
689
|
-
# If importing from file, include agent_config (pass-through minus credentials)
|
|
690
|
-
if import_file:
|
|
691
|
-
agent_config_raw = (
|
|
692
|
-
merged_data.get("agent_config")
|
|
693
|
-
if isinstance(merged_data, dict)
|
|
694
|
-
else None
|
|
695
|
-
)
|
|
696
|
-
if isinstance(agent_config_raw, dict):
|
|
697
|
-
# If language_model_id is used, strip LM identity keys from agent_config to avoid conflicts
|
|
698
|
-
create_kwargs["agent_config"] = sanitize_agent_config(
|
|
699
|
-
agent_config_raw, strip_lm_identity=should_strip_lm_identity
|
|
700
|
-
)
|
|
701
886
|
|
|
702
|
-
#
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
# System-only fields that shouldn't be passed to create_agent
|
|
715
|
-
"id",
|
|
716
|
-
"created_at",
|
|
717
|
-
"updated_at",
|
|
718
|
-
"type",
|
|
719
|
-
"framework",
|
|
720
|
-
"version",
|
|
721
|
-
"tool_configs",
|
|
722
|
-
"mcps",
|
|
723
|
-
"a2a_profile",
|
|
724
|
-
}
|
|
725
|
-
for key, value in merged_data.items():
|
|
726
|
-
if key not in excluded_fields and value is not None:
|
|
727
|
-
create_kwargs[key] = value
|
|
887
|
+
# Build create kwargs
|
|
888
|
+
create_kwargs = _build_create_kwargs(
|
|
889
|
+
name,
|
|
890
|
+
instruction,
|
|
891
|
+
resolved_tools,
|
|
892
|
+
resolved_agents,
|
|
893
|
+
resolved_mcps,
|
|
894
|
+
timeout,
|
|
895
|
+
merged_data,
|
|
896
|
+
model,
|
|
897
|
+
import_file,
|
|
898
|
+
)
|
|
728
899
|
|
|
900
|
+
# Create agent
|
|
729
901
|
agent = client.agents.create_agent(**create_kwargs)
|
|
730
902
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
lm_display = getattr(agent, "model", None)
|
|
734
|
-
if not lm_display:
|
|
735
|
-
cfg = getattr(agent, "agent_config", {}) or {}
|
|
736
|
-
lm_display = (
|
|
737
|
-
cfg.get("lm_name")
|
|
738
|
-
or cfg.get("model")
|
|
739
|
-
or model
|
|
740
|
-
or f"{DEFAULT_MODEL} (backend default)"
|
|
741
|
-
)
|
|
742
|
-
|
|
743
|
-
handle_rich_output(
|
|
744
|
-
ctx,
|
|
745
|
-
display_creation_success(
|
|
746
|
-
"Agent",
|
|
747
|
-
agent.name,
|
|
748
|
-
agent.id,
|
|
749
|
-
Model=lm_display,
|
|
750
|
-
Type=getattr(agent, "type", "config"),
|
|
751
|
-
Framework=getattr(agent, "framework", "langchain"),
|
|
752
|
-
Version=getattr(agent, "version", "1.0"),
|
|
753
|
-
),
|
|
754
|
-
)
|
|
755
|
-
handle_rich_output(ctx, display_agent_run_suggestions(agent))
|
|
903
|
+
# Handle successful creation
|
|
904
|
+
_handle_successful_creation(ctx, agent, model)
|
|
756
905
|
|
|
757
|
-
except
|
|
758
|
-
|
|
759
|
-
): # pragma: no cover - error formatting verified elsewhere
|
|
760
|
-
# Handle JSON output for ClickExceptions if view is JSON
|
|
761
|
-
if ctx.obj.get("view") == "json":
|
|
762
|
-
handle_json_output(ctx, error=Exception(AGENT_NOT_FOUND_ERROR))
|
|
763
|
-
# Re-raise ClickExceptions without additional processing
|
|
764
|
-
raise
|
|
765
|
-
except Exception as e: # pragma: no cover - defensive logging path
|
|
766
|
-
handle_json_output(ctx, error=e)
|
|
767
|
-
if ctx.obj.get("view") != "json":
|
|
768
|
-
print_api_error(e)
|
|
769
|
-
raise click.ClickException(str(e))
|
|
906
|
+
except Exception as e:
|
|
907
|
+
_handle_creation_exception(ctx, e)
|
|
770
908
|
|
|
771
909
|
|
|
772
|
-
def _get_agent_for_update(client, agent_id):
|
|
910
|
+
def _get_agent_for_update(client: Any, agent_id: str) -> Any:
|
|
773
911
|
"""Retrieve agent by ID for update operation."""
|
|
774
912
|
try:
|
|
775
913
|
return client.agents.get_agent_by_id(agent_id)
|
|
@@ -777,7 +915,21 @@ def _get_agent_for_update(client, agent_id):
|
|
|
777
915
|
raise click.ClickException(f"Agent with ID '{agent_id}' not found: {e}")
|
|
778
916
|
|
|
779
917
|
|
|
780
|
-
def _handle_update_import_file(
|
|
918
|
+
def _handle_update_import_file(
|
|
919
|
+
import_file: str | None,
|
|
920
|
+
name: str | None,
|
|
921
|
+
instruction: str | None,
|
|
922
|
+
tools: tuple[str, ...] | None,
|
|
923
|
+
agents: tuple[str, ...] | None,
|
|
924
|
+
timeout: float | None,
|
|
925
|
+
) -> tuple[
|
|
926
|
+
Any | None,
|
|
927
|
+
str | None,
|
|
928
|
+
str | None,
|
|
929
|
+
tuple[str, ...] | None,
|
|
930
|
+
tuple[str, ...] | None,
|
|
931
|
+
float | None,
|
|
932
|
+
]:
|
|
781
933
|
"""Handle import file processing for agent update."""
|
|
782
934
|
if not import_file:
|
|
783
935
|
return None, name, instruction, tools, agents, timeout
|
|
@@ -806,7 +958,13 @@ def _handle_update_import_file(import_file, name, instruction, tools, agents, ti
|
|
|
806
958
|
)
|
|
807
959
|
|
|
808
960
|
|
|
809
|
-
def _build_update_data(
|
|
961
|
+
def _build_update_data(
|
|
962
|
+
name: str | None,
|
|
963
|
+
instruction: str | None,
|
|
964
|
+
tools: tuple[str, ...] | None,
|
|
965
|
+
agents: tuple[str, ...] | None,
|
|
966
|
+
timeout: float | None,
|
|
967
|
+
) -> dict[str, Any]:
|
|
810
968
|
"""Build the update data dictionary from provided parameters."""
|
|
811
969
|
update_data = {}
|
|
812
970
|
if name is not None:
|
|
@@ -822,7 +980,9 @@ def _build_update_data(name, instruction, tools, agents, timeout):
|
|
|
822
980
|
return update_data
|
|
823
981
|
|
|
824
982
|
|
|
825
|
-
def _handle_update_import_config(
|
|
983
|
+
def _handle_update_import_config(
|
|
984
|
+
import_file: str | None, merged_data: dict[str, Any], update_data: dict[str, Any]
|
|
985
|
+
) -> None:
|
|
826
986
|
"""Handle agent config and additional attributes for import-based updates."""
|
|
827
987
|
if not import_file:
|
|
828
988
|
return
|
|
@@ -876,7 +1036,16 @@ def _handle_update_import_config(import_file, merged_data, update_data):
|
|
|
876
1036
|
)
|
|
877
1037
|
@output_flags()
|
|
878
1038
|
@click.pass_context
|
|
879
|
-
def update(
|
|
1039
|
+
def update(
|
|
1040
|
+
ctx: Any,
|
|
1041
|
+
agent_id: str,
|
|
1042
|
+
name: str | None,
|
|
1043
|
+
instruction: str | None,
|
|
1044
|
+
tools: tuple[str, ...] | None,
|
|
1045
|
+
agents: tuple[str, ...] | None,
|
|
1046
|
+
timeout: float | None,
|
|
1047
|
+
import_file: str | None,
|
|
1048
|
+
) -> None:
|
|
880
1049
|
"""Update an existing agent.
|
|
881
1050
|
|
|
882
1051
|
Examples:
|
|
@@ -888,10 +1057,15 @@ def update(ctx, agent_id, name, instruction, tools, agents, timeout, import_file
|
|
|
888
1057
|
agent = _get_agent_for_update(client, agent_id)
|
|
889
1058
|
|
|
890
1059
|
# Handle import file processing
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1060
|
+
(
|
|
1061
|
+
merged_data,
|
|
1062
|
+
name,
|
|
1063
|
+
instruction,
|
|
1064
|
+
tools,
|
|
1065
|
+
agents,
|
|
1066
|
+
timeout,
|
|
1067
|
+
) = _handle_update_import_file(
|
|
1068
|
+
import_file, name, instruction, tools, agents, timeout
|
|
895
1069
|
)
|
|
896
1070
|
|
|
897
1071
|
update_data = _build_update_data(name, instruction, tools, agents, timeout)
|
|
@@ -910,13 +1084,13 @@ def update(ctx, agent_id, name, instruction, tools, agents, timeout, import_file
|
|
|
910
1084
|
|
|
911
1085
|
except click.ClickException:
|
|
912
1086
|
# Handle JSON output for ClickExceptions if view is JSON
|
|
913
|
-
if ctx
|
|
1087
|
+
if get_ctx_value(ctx, "view") == "json":
|
|
914
1088
|
handle_json_output(ctx, error=Exception(AGENT_NOT_FOUND_ERROR))
|
|
915
1089
|
# Re-raise ClickExceptions without additional processing
|
|
916
1090
|
raise
|
|
917
1091
|
except Exception as e:
|
|
918
1092
|
handle_json_output(ctx, error=e)
|
|
919
|
-
if ctx
|
|
1093
|
+
if get_ctx_value(ctx, "view") != "json":
|
|
920
1094
|
print_api_error(e)
|
|
921
1095
|
raise click.ClickException(str(e))
|
|
922
1096
|
|
|
@@ -926,7 +1100,7 @@ def update(ctx, agent_id, name, instruction, tools, agents, timeout, import_file
|
|
|
926
1100
|
@click.option("-y", "--yes", is_flag=True, help="Skip confirmation")
|
|
927
1101
|
@output_flags()
|
|
928
1102
|
@click.pass_context
|
|
929
|
-
def delete(ctx, agent_id, yes):
|
|
1103
|
+
def delete(ctx: Any, agent_id: str, yes: bool) -> None:
|
|
930
1104
|
"""Delete an agent."""
|
|
931
1105
|
try:
|
|
932
1106
|
client = get_client(ctx)
|
|
@@ -954,13 +1128,13 @@ def delete(ctx, agent_id, yes):
|
|
|
954
1128
|
|
|
955
1129
|
except click.ClickException:
|
|
956
1130
|
# Handle JSON output for ClickExceptions if view is JSON
|
|
957
|
-
if ctx
|
|
1131
|
+
if get_ctx_value(ctx, "view") == "json":
|
|
958
1132
|
handle_json_output(ctx, error=Exception(AGENT_NOT_FOUND_ERROR))
|
|
959
1133
|
# Re-raise ClickExceptions without additional processing
|
|
960
1134
|
raise
|
|
961
1135
|
except Exception as e:
|
|
962
1136
|
handle_json_output(ctx, error=e)
|
|
963
|
-
if ctx
|
|
1137
|
+
if get_ctx_value(ctx, "view") != "json":
|
|
964
1138
|
print_api_error(e)
|
|
965
1139
|
raise click.ClickException(str(e))
|
|
966
1140
|
|
|
@@ -975,7 +1149,9 @@ def delete(ctx, agent_id, yes):
|
|
|
975
1149
|
)
|
|
976
1150
|
@output_flags()
|
|
977
1151
|
@click.pass_context
|
|
978
|
-
def sync_langflow(
|
|
1152
|
+
def sync_langflow(
|
|
1153
|
+
ctx: Any, base_url: str | None, api_key: str | None
|
|
1154
|
+
) -> None: # pragma: no cover - integration-only path
|
|
979
1155
|
"""Sync agents with LangFlow server flows.
|
|
980
1156
|
|
|
981
1157
|
This command fetches all flows from the configured LangFlow server and
|
|
@@ -999,7 +1175,7 @@ def sync_langflow(ctx, base_url, api_key): # pragma: no cover - integration-onl
|
|
|
999
1175
|
handle_json_output(ctx, result)
|
|
1000
1176
|
|
|
1001
1177
|
# Show success message for non-JSON output
|
|
1002
|
-
if ctx
|
|
1178
|
+
if get_ctx_value(ctx, "view") != "json":
|
|
1003
1179
|
from rich.text import Text
|
|
1004
1180
|
|
|
1005
1181
|
# Extract some useful info from the result
|
|
@@ -1017,6 +1193,6 @@ def sync_langflow(ctx, base_url, api_key): # pragma: no cover - integration-onl
|
|
|
1017
1193
|
|
|
1018
1194
|
except Exception as e:
|
|
1019
1195
|
handle_json_output(ctx, error=e)
|
|
1020
|
-
if ctx
|
|
1196
|
+
if get_ctx_value(ctx, "view") != "json":
|
|
1021
1197
|
print_api_error(e)
|
|
1022
1198
|
raise click.ClickException(str(e))
|