tinet-agent-cli 0.1.0.dev37__py3-none-any.whl → 0.1.0.dev39__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.
- taco/__init__.py +1 -1
- taco/agent_openapi/service.py +6 -0
- taco/aikb/executors.py +50 -1
- taco/assets/__init__.py +1 -1
- taco/assets/agent_openapi/operations/trace/list-message-traces.json +2 -2
- taco/assets/manifest.json +1 -2
- taco/cli.py +29 -6
- taco/commands/agent.py +149 -95
- taco/commands/aikb.py +632 -90
- taco/commands/discovery.py +1 -199
- taco/core/assets.py +0 -18
- taco/core/developer_center_client.py +14 -1
- taco/core/errors.py +1 -0
- taco/core/output.py +2 -0
- taco/release.py +0 -12
- {tinet_agent_cli-0.1.0.dev37.dist-info → tinet_agent_cli-0.1.0.dev39.dist-info}/METADATA +16 -4
- {tinet_agent_cli-0.1.0.dev37.dist-info → tinet_agent_cli-0.1.0.dev39.dist-info}/RECORD +19 -22
- taco/assets/skills/README.md +0 -3
- taco/assets/skills/taco/SKILL.md +0 -68
- taco/assets/skills/taco/manifest.json +0 -10
- {tinet_agent_cli-0.1.0.dev37.dist-info → tinet_agent_cli-0.1.0.dev39.dist-info}/WHEEL +0 -0
- {tinet_agent_cli-0.1.0.dev37.dist-info → tinet_agent_cli-0.1.0.dev39.dist-info}/entry_points.txt +0 -0
taco/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.0.
|
|
1
|
+
__version__ = "0.1.0.dev39"
|
taco/agent_openapi/service.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
from typing import Any
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
@@ -67,6 +68,11 @@ def validate_response(operation: AgentOperation, payload: Any) -> dict[str, Any]
|
|
|
67
68
|
exit_code=4,
|
|
68
69
|
request_id=request_id,
|
|
69
70
|
path=operation.http["path"],
|
|
71
|
+
raw_response=json.dumps(
|
|
72
|
+
payload,
|
|
73
|
+
ensure_ascii=False,
|
|
74
|
+
separators=(",", ":"),
|
|
75
|
+
),
|
|
70
76
|
)
|
|
71
77
|
business = dict(payload)
|
|
72
78
|
business.pop("requestId", None)
|
taco/aikb/executors.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
import math
|
|
4
5
|
import os
|
|
6
|
+
import re
|
|
5
7
|
from typing import Any
|
|
6
8
|
from urllib.parse import urlsplit
|
|
7
9
|
|
|
@@ -17,6 +19,13 @@ from taco.core.http_headers import with_cli_user_agent
|
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
DEFAULT_UPLOAD_TIMEOUT_SECONDS = 600.0
|
|
22
|
+
RAW_HTML_CONTENT_IGNORED_MESSAGE = (
|
|
23
|
+
"服务端 rawHtmlContent 为非标准 JSON 内容,CLI 已忽略该属性。"
|
|
24
|
+
)
|
|
25
|
+
_RAW_HTML_CONTENT_PATTERN = re.compile(
|
|
26
|
+
r'"rawHtmlContent"\s*:\s*.*?(?=,\s*"escapedHtmlContent"\s*:)',
|
|
27
|
+
re.DOTALL,
|
|
28
|
+
)
|
|
20
29
|
|
|
21
30
|
|
|
22
31
|
def execute_http(
|
|
@@ -26,13 +35,53 @@ def execute_http(
|
|
|
26
35
|
query: dict[str, Any],
|
|
27
36
|
body: dict[str, Any],
|
|
28
37
|
) -> dict[str, Any]:
|
|
38
|
+
raw_html_content_ignored = False
|
|
39
|
+
|
|
40
|
+
def repair_signature_response(raw: str) -> Any:
|
|
41
|
+
nonlocal raw_html_content_ignored
|
|
42
|
+
payload = _parse_signature_response_without_raw_html(raw)
|
|
43
|
+
raw_html_content_ignored = True
|
|
44
|
+
return payload
|
|
45
|
+
|
|
29
46
|
payload = client.request_json(
|
|
30
47
|
operation.http["method"],
|
|
31
48
|
operation.http["path"],
|
|
32
49
|
query=query or None,
|
|
33
50
|
json_body=body or None,
|
|
51
|
+
preserve_invalid_response=operation.id == "signature-for-upload",
|
|
52
|
+
invalid_json_parser=(
|
|
53
|
+
repair_signature_response
|
|
54
|
+
if operation.id == "signature-for-upload"
|
|
55
|
+
else None
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
result = validate_response(operation, payload)
|
|
59
|
+
if raw_html_content_ignored:
|
|
60
|
+
result["message"] = RAW_HTML_CONTENT_IGNORED_MESSAGE
|
|
61
|
+
return result
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _parse_signature_response_without_raw_html(raw: str) -> dict[str, Any]:
|
|
65
|
+
matches = tuple(_RAW_HTML_CONTENT_PATTERN.finditer(raw))
|
|
66
|
+
if len(matches) != 1:
|
|
67
|
+
raise ValueError("响应中不存在唯一的非标准 rawHtmlContent 属性")
|
|
68
|
+
repaired = _RAW_HTML_CONTENT_PATTERN.sub(
|
|
69
|
+
'"rawHtmlContent":null',
|
|
70
|
+
raw,
|
|
71
|
+
count=1,
|
|
34
72
|
)
|
|
35
|
-
|
|
73
|
+
payload = json.loads(repaired)
|
|
74
|
+
if not isinstance(payload, dict):
|
|
75
|
+
raise ValueError("响应不是 JSON 对象")
|
|
76
|
+
result = payload.get("result")
|
|
77
|
+
if (
|
|
78
|
+
not isinstance(result, dict)
|
|
79
|
+
or "rawHtmlContent" not in result
|
|
80
|
+
or result["rawHtmlContent"] is not None
|
|
81
|
+
):
|
|
82
|
+
raise ValueError("非标准 rawHtmlContent 不在 result 中")
|
|
83
|
+
result.pop("rawHtmlContent")
|
|
84
|
+
return payload
|
|
36
85
|
|
|
37
86
|
|
|
38
87
|
def execute_presigned_put(
|
taco/assets/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"""Packaged schemas, scenarios, examples, and
|
|
1
|
+
"""Packaged schemas, scenarios, examples, and API catalogs."""
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
"inputs": {"description": "节点输入;JSON 内容返回对象,否则可能返回原始值。"},
|
|
48
48
|
"process_data": {"description": "节点处理过程数据。"},
|
|
49
49
|
"outputs": {"description": "节点输出;JSON 内容返回对象,否则可能返回原始值。"},
|
|
50
|
-
"status": {"type": "string", "description": "节点执行状态。"},
|
|
50
|
+
"status": {"type": ["string", "null"], "description": "节点执行状态。"},
|
|
51
51
|
"error": {"type": ["string", "null"], "description": "节点执行错误信息。"},
|
|
52
52
|
"elapsed_time": {"type": ["number", "null"], "description": "节点执行耗时,单位秒。"},
|
|
53
53
|
"execution_metadata": {"type": ["object", "null"], "description": "节点执行元数据。", "additionalProperties": true},
|
|
54
54
|
"extras": {"type": ["object", "null"], "description": "节点额外信息。", "additionalProperties": true},
|
|
55
|
-
"created_at": {"type": "integer", "description": "节点开始执行的 Unix 秒级时间戳。"},
|
|
55
|
+
"created_at": {"type": ["integer", "null"], "description": "节点开始执行的 Unix 秒级时间戳。"},
|
|
56
56
|
"finished_at": {"type": ["integer", "null"], "description": "节点完成执行的 Unix 秒级时间戳。"}
|
|
57
57
|
},
|
|
58
58
|
"additionalProperties": true
|
taco/assets/manifest.json
CHANGED
taco/cli.py
CHANGED
|
@@ -13,7 +13,10 @@ from taco.core.errors import TacoError
|
|
|
13
13
|
from taco.core.output import failure, to_json_line
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
app = typer.Typer(
|
|
16
|
+
app = typer.Typer(
|
|
17
|
+
help="Tinet Agent CLI Orchestrator",
|
|
18
|
+
add_completion=False,
|
|
19
|
+
)
|
|
17
20
|
app.add_typer(agent_app, name="agent")
|
|
18
21
|
app.add_typer(aikb_app, name="aikb")
|
|
19
22
|
app.add_typer(profile_app, name="profile")
|
|
@@ -63,7 +66,7 @@ def root(
|
|
|
63
66
|
def main() -> None:
|
|
64
67
|
try:
|
|
65
68
|
result = app(
|
|
66
|
-
args=
|
|
69
|
+
args=_normalize_cli_args(sys.argv[1:]),
|
|
67
70
|
standalone_mode=False,
|
|
68
71
|
prog_name="taco",
|
|
69
72
|
)
|
|
@@ -101,11 +104,15 @@ def main() -> None:
|
|
|
101
104
|
)
|
|
102
105
|
|
|
103
106
|
|
|
104
|
-
def
|
|
105
|
-
|
|
107
|
+
def _normalize_cli_args(args: list[str]) -> list[str]:
|
|
108
|
+
global_args: list[str] = []
|
|
109
|
+
command_args: list[str] = []
|
|
106
110
|
index = 0
|
|
107
111
|
while index < len(args):
|
|
108
112
|
argument = args[index]
|
|
113
|
+
if argument == "--":
|
|
114
|
+
command_args.extend(args[index:])
|
|
115
|
+
break
|
|
109
116
|
if argument == "--from-zenava":
|
|
110
117
|
index += 1
|
|
111
118
|
if index < len(args) and args[index].lower() in {"true", "false"}:
|
|
@@ -114,9 +121,25 @@ def _without_ignored_compat_args(args: list[str]) -> list[str]:
|
|
|
114
121
|
if argument.startswith("--from-zenava="):
|
|
115
122
|
index += 1
|
|
116
123
|
continue
|
|
117
|
-
|
|
124
|
+
if argument in {"--json", "--no-input"}:
|
|
125
|
+
global_args.append(argument)
|
|
126
|
+
index += 1
|
|
127
|
+
continue
|
|
128
|
+
if argument == "--profile":
|
|
129
|
+
index += 1
|
|
130
|
+
if index < len(args) and not args[index].startswith("-"):
|
|
131
|
+
global_args.extend((argument, args[index]))
|
|
132
|
+
index += 1
|
|
133
|
+
else:
|
|
134
|
+
command_args.append(argument)
|
|
135
|
+
continue
|
|
136
|
+
if argument.startswith("--profile="):
|
|
137
|
+
global_args.append(argument)
|
|
138
|
+
index += 1
|
|
139
|
+
continue
|
|
140
|
+
command_args.append(argument)
|
|
118
141
|
index += 1
|
|
119
|
-
return
|
|
142
|
+
return [*global_args, *command_args]
|
|
120
143
|
|
|
121
144
|
|
|
122
145
|
def _exit_main_with_error(error: TacoError) -> None:
|
taco/commands/agent.py
CHANGED
|
@@ -5,7 +5,7 @@ import os
|
|
|
5
5
|
import tempfile
|
|
6
6
|
from json import JSONDecodeError
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Any
|
|
8
|
+
from typing import Any, Literal
|
|
9
9
|
from uuid import UUID, uuid4
|
|
10
10
|
|
|
11
11
|
import typer
|
|
@@ -14,12 +14,11 @@ from taco.commands.app import app_app
|
|
|
14
14
|
from taco.commands.category import category_app
|
|
15
15
|
from taco.commands.chatflow import chatflow_app
|
|
16
16
|
from taco.commands.credential import credential_app
|
|
17
|
-
from taco.commands.discovery import example_app, scenario_app, schema_app
|
|
17
|
+
from taco.commands.discovery import example_app, scenario_app, schema_app
|
|
18
18
|
from taco.commands.model import model_app
|
|
19
19
|
from taco.commands.tool import tool_app
|
|
20
20
|
from taco.commands.workflow import workflow_app
|
|
21
|
-
from taco.agent_openapi.catalog import load_catalog
|
|
22
|
-
from taco.agent_openapi.models import thaw
|
|
21
|
+
from taco.agent_openapi.catalog import load_catalog
|
|
23
22
|
from taco.agent_openapi.parameters import parse_parameters
|
|
24
23
|
from taco.agent_openapi.service import AgentOpenApiService
|
|
25
24
|
from taco.core.context import get_cli_context
|
|
@@ -35,11 +34,15 @@ from taco.services.tool_service import ToolService
|
|
|
35
34
|
from taco.services.workflow_tool_service import WorkflowToolService
|
|
36
35
|
|
|
37
36
|
|
|
38
|
-
agent_app = typer.Typer(help="
|
|
37
|
+
agent_app = typer.Typer(help="智能体管理")
|
|
39
38
|
agent_tool_app = typer.Typer(help="本地 Agent DSL 工具挂载")
|
|
40
|
-
|
|
39
|
+
conversation_app = typer.Typer(help="智能体会话记录管理")
|
|
40
|
+
conversation_message_app = typer.Typer(help="会话消息管理")
|
|
41
|
+
conversation_trace_app = typer.Typer(help="消息追踪管理")
|
|
41
42
|
agent_app.add_typer(agent_tool_app, name="tool")
|
|
42
|
-
agent_app.add_typer(
|
|
43
|
+
agent_app.add_typer(conversation_app, name="conversation")
|
|
44
|
+
conversation_app.add_typer(conversation_message_app, name="message")
|
|
45
|
+
conversation_app.add_typer(conversation_trace_app, name="trace")
|
|
43
46
|
agent_app.add_typer(app_app, name="app")
|
|
44
47
|
agent_app.add_typer(category_app, name="category")
|
|
45
48
|
agent_app.add_typer(model_app, name="model")
|
|
@@ -47,112 +50,121 @@ agent_app.add_typer(workflow_app, name="workflow")
|
|
|
47
50
|
agent_app.add_typer(chatflow_app, name="chatflow")
|
|
48
51
|
agent_app.add_typer(example_app, name="example")
|
|
49
52
|
agent_app.add_typer(scenario_app, name="scenario")
|
|
50
|
-
agent_app.add_typer(skills_app, name="skills")
|
|
51
53
|
agent_app.add_typer(schema_app, name="schema")
|
|
52
54
|
agent_tool_app.add_typer(tool_app, name="catalog")
|
|
53
55
|
agent_tool_app.add_typer(credential_app, name="credential")
|
|
54
56
|
|
|
55
57
|
|
|
56
|
-
@
|
|
57
|
-
def
|
|
58
|
+
@conversation_app.command("list", help="查询智能体会话记录。")
|
|
59
|
+
def list_conversations(
|
|
58
60
|
ctx: typer.Context,
|
|
59
|
-
|
|
61
|
+
app_id: str = typer.Option(..., "--app-id", help="智能体应用 ID。"),
|
|
62
|
+
created_at_start: int = typer.Option(
|
|
63
|
+
...,
|
|
64
|
+
"--created-at-start",
|
|
65
|
+
min=1,
|
|
66
|
+
help="创建开始时间,Unix 秒级时间戳。",
|
|
67
|
+
),
|
|
68
|
+
created_at_end: int = typer.Option(
|
|
69
|
+
...,
|
|
70
|
+
"--created-at-end",
|
|
71
|
+
min=1,
|
|
72
|
+
help="创建结束时间,Unix 秒级时间戳,跨度不超过 90 天。",
|
|
73
|
+
),
|
|
74
|
+
conversation_id: str | None = typer.Option(
|
|
75
|
+
None,
|
|
76
|
+
"--conversation-id",
|
|
77
|
+
help="按指定会话 ID 查询。",
|
|
78
|
+
),
|
|
79
|
+
invoke_from: Literal["PROD", "DEBUG"] | None = typer.Option(
|
|
80
|
+
None,
|
|
81
|
+
"--invoke-from",
|
|
82
|
+
help="会话来源:PROD 或 DEBUG。",
|
|
83
|
+
),
|
|
84
|
+
is_transfer_human: bool | None = typer.Option(
|
|
85
|
+
None,
|
|
86
|
+
"--is-transfer-human/--no-transfer-human",
|
|
87
|
+
help="筛选是否发生过转人工。",
|
|
88
|
+
),
|
|
89
|
+
limit: int = typer.Option(10, "--limit", min=1, max=100, help="查询数量。"),
|
|
90
|
+
cursor: str | None = typer.Option(None, "--cursor", help="下一页游标。"),
|
|
60
91
|
) -> None:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if needle in haystack:
|
|
78
|
-
matches.append(_agent_operation_summary(operation))
|
|
79
|
-
emit_success(ctx, matches[:10], json_default=True)
|
|
92
|
+
_call_named_agent_operation(
|
|
93
|
+
ctx,
|
|
94
|
+
"list-conversations",
|
|
95
|
+
body=_without_none(
|
|
96
|
+
{
|
|
97
|
+
"app_id": app_id,
|
|
98
|
+
"created_at_start": created_at_start,
|
|
99
|
+
"created_at_end": created_at_end,
|
|
100
|
+
"conversation_id": conversation_id,
|
|
101
|
+
"invoke_from": invoke_from,
|
|
102
|
+
"is_transfer_human": is_transfer_human,
|
|
103
|
+
"limit": limit,
|
|
104
|
+
"cursor": cursor,
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
)
|
|
80
108
|
|
|
81
109
|
|
|
82
|
-
@
|
|
83
|
-
def
|
|
110
|
+
@conversation_message_app.command("list", help="查询指定会话的消息记录。")
|
|
111
|
+
def list_conversation_messages(
|
|
84
112
|
ctx: typer.Context,
|
|
85
|
-
|
|
113
|
+
app_id: str = typer.Option(..., "--app-id", help="智能体应用 ID。"),
|
|
114
|
+
conversation_id: str = typer.Option(..., "--conversation-id", help="会话 ID。"),
|
|
115
|
+
conversation_created_at: int = typer.Option(
|
|
116
|
+
...,
|
|
117
|
+
"--conversation-created-at",
|
|
118
|
+
min=1,
|
|
119
|
+
help="会话创建时间,Unix 秒级时间戳。",
|
|
120
|
+
),
|
|
121
|
+
limit: int = typer.Option(10, "--limit", min=1, max=100, help="查询数量。"),
|
|
122
|
+
cursor: str | None = typer.Option(None, "--cursor", help="下一页游标。"),
|
|
86
123
|
) -> None:
|
|
87
|
-
|
|
88
|
-
if operation is None:
|
|
89
|
-
exit_with_error(ctx, operation_not_found(operation_id), json_default=True)
|
|
90
|
-
emit_success(
|
|
124
|
+
_call_named_agent_operation(
|
|
91
125
|
ctx,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
json_default=True,
|
|
126
|
+
"list-conversation-messages",
|
|
127
|
+
body=_without_none(
|
|
128
|
+
{
|
|
129
|
+
"app_id": app_id,
|
|
130
|
+
"conversation_id": conversation_id,
|
|
131
|
+
"conversation_created_at": conversation_created_at,
|
|
132
|
+
"limit": limit,
|
|
133
|
+
"cursor": cursor,
|
|
134
|
+
}
|
|
135
|
+
),
|
|
103
136
|
)
|
|
104
137
|
|
|
105
138
|
|
|
106
|
-
@
|
|
107
|
-
def
|
|
139
|
+
@conversation_trace_app.command("list", help="查询指定消息的详细日志追踪。")
|
|
140
|
+
def list_message_traces(
|
|
108
141
|
ctx: typer.Context,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
None,
|
|
117
|
-
"--params-file",
|
|
118
|
-
help="语义参数 JSON 文件。",
|
|
119
|
-
),
|
|
120
|
-
body_file: Path | None = typer.Option(
|
|
121
|
-
None,
|
|
122
|
-
"--body-file",
|
|
123
|
-
help="JSON body 文件。",
|
|
142
|
+
app_id: str = typer.Option(..., "--app-id", help="智能体应用 ID。"),
|
|
143
|
+
conversation_id: str = typer.Option(..., "--conversation-id", help="会话 ID。"),
|
|
144
|
+
conversation_created_at: int = typer.Option(
|
|
145
|
+
...,
|
|
146
|
+
"--conversation-created-at",
|
|
147
|
+
min=1,
|
|
148
|
+
help="会话创建时间,Unix 秒级时间戳。",
|
|
124
149
|
),
|
|
150
|
+
message_id: str = typer.Option(..., "--message-id", help="消息 ID。"),
|
|
151
|
+
limit: int = typer.Option(10, "--limit", min=1, max=100, help="查询数量。"),
|
|
152
|
+
cursor: str | None = typer.Option(None, "--cursor", help="下一页游标。"),
|
|
125
153
|
) -> None:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
profile=get_cli_context(ctx).profile,
|
|
141
|
-
)
|
|
142
|
-
except TacoError as error:
|
|
143
|
-
exit_with_error(ctx, error, json_default=True)
|
|
144
|
-
emit_success(ctx, result, json_default=True)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def _agent_operation_summary(operation) -> dict[str, Any]:
|
|
148
|
-
return {
|
|
149
|
-
"id": operation.id,
|
|
150
|
-
"title": operation.title,
|
|
151
|
-
"group": operation.group,
|
|
152
|
-
"method": operation.http["method"],
|
|
153
|
-
"path": operation.http["path"],
|
|
154
|
-
"risk": operation.risk["level"],
|
|
155
|
-
}
|
|
154
|
+
_call_named_agent_operation(
|
|
155
|
+
ctx,
|
|
156
|
+
"list-message-traces",
|
|
157
|
+
body=_without_none(
|
|
158
|
+
{
|
|
159
|
+
"app_id": app_id,
|
|
160
|
+
"conversation_id": conversation_id,
|
|
161
|
+
"conversation_created_at": conversation_created_at,
|
|
162
|
+
"message_id": message_id,
|
|
163
|
+
"limit": limit,
|
|
164
|
+
"cursor": cursor,
|
|
165
|
+
}
|
|
166
|
+
),
|
|
167
|
+
)
|
|
156
168
|
|
|
157
169
|
|
|
158
170
|
@agent_app.command("create", help="创建 Agent 并把服务端默认配置写入本地 DSL。")
|
|
@@ -574,6 +586,48 @@ def publish_agent(
|
|
|
574
586
|
emit_success(ctx, data, json_default=True)
|
|
575
587
|
|
|
576
588
|
|
|
589
|
+
def _call_named_agent_operation(
|
|
590
|
+
ctx: typer.Context,
|
|
591
|
+
operation_id: str,
|
|
592
|
+
*,
|
|
593
|
+
query: dict[str, Any] | None = None,
|
|
594
|
+
body: dict[str, Any] | None = None,
|
|
595
|
+
) -> None:
|
|
596
|
+
operation = load_catalog().by_id[operation_id]
|
|
597
|
+
try:
|
|
598
|
+
validated_query, validated_body = _validated_agent_parameters(
|
|
599
|
+
operation,
|
|
600
|
+
query=query or {},
|
|
601
|
+
body=body or {},
|
|
602
|
+
)
|
|
603
|
+
result = AgentOpenApiService().call(
|
|
604
|
+
operation_id,
|
|
605
|
+
query=validated_query,
|
|
606
|
+
body=validated_body,
|
|
607
|
+
profile=get_cli_context(ctx).profile,
|
|
608
|
+
)
|
|
609
|
+
except TacoError as error:
|
|
610
|
+
exit_with_error(ctx, error, json_default=True)
|
|
611
|
+
emit_success(ctx, result, json_default=True)
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
def _validated_agent_parameters(
|
|
615
|
+
operation,
|
|
616
|
+
*,
|
|
617
|
+
query: dict[str, Any],
|
|
618
|
+
body: dict[str, Any],
|
|
619
|
+
) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
620
|
+
expressions = [
|
|
621
|
+
f"{key}={value if isinstance(value, str) else json.dumps(value)}"
|
|
622
|
+
for key, value in [*query.items(), *body.items()]
|
|
623
|
+
]
|
|
624
|
+
return parse_parameters(operation, params=expressions)
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def _without_none(values: dict[str, Any]) -> dict[str, Any]:
|
|
628
|
+
return {key: value for key, value in values.items() if value is not None}
|
|
629
|
+
|
|
630
|
+
|
|
577
631
|
def _read_json_object(path: Path | None) -> dict[str, Any]:
|
|
578
632
|
if path is None:
|
|
579
633
|
return {}
|