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