agentic-fabriq-sdk 0.1.4__tar.gz → 0.1.6__tar.gz
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.
Potentially problematic release.
This version of agentic-fabriq-sdk might be problematic. Click here for more details.
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/PKG-INFO +40 -10
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/README.md +32 -5
- agentic_fabriq_sdk-0.1.6/af_cli/__init__.py +8 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/__init__.py +3 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/agents.py +238 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/auth.py +388 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/config.py +102 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/mcp_servers.py +83 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/secrets.py +109 -0
- agentic_fabriq_sdk-0.1.6/af_cli/commands/tools.py +83 -0
- agentic_fabriq_sdk-0.1.6/af_cli/core/__init__.py +3 -0
- agentic_fabriq_sdk-0.1.6/af_cli/core/client.py +123 -0
- agentic_fabriq_sdk-0.1.6/af_cli/core/config.py +200 -0
- agentic_fabriq_sdk-0.1.6/af_cli/core/oauth.py +506 -0
- agentic_fabriq_sdk-0.1.6/af_cli/core/output.py +180 -0
- agentic_fabriq_sdk-0.1.6/af_cli/core/token_storage.py +263 -0
- agentic_fabriq_sdk-0.1.6/af_cli/main.py +187 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/pyproject.toml +16 -5
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/__init__.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/auth/__init__.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/auth/dpop.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/auth/oauth.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/auth/token_cache.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/connectors/__init__.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/connectors/base.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/connectors/registry.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/dx/__init__.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/dx/decorators.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/dx/runtime.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/events.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/exceptions.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/fabriq_client.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/models/__init__.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/models/audit.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/models/types.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/py.typed +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/transport/__init__.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/transport/http.py +0 -0
- {agentic_fabriq_sdk-0.1.4 → agentic_fabriq_sdk-0.1.6}/af_sdk/vault.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-fabriq-sdk
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: Agentic Fabriq SDK: high-level client, CLI tool, DX helpers, and auth for AI agents
|
|
5
5
|
License: Apache-2.0
|
|
6
|
-
Keywords: fabriq,agentic-
|
|
7
|
-
Author: Agentic
|
|
8
|
-
Author-email: contributors@agentic-
|
|
6
|
+
Keywords: fabriq,agentic-fabriq,sdk,ai,agents,agentic,fabric,cli
|
|
7
|
+
Author: Agentic Fabriq Contributors
|
|
8
|
+
Author-email: contributors@agentic-fabriq.org
|
|
9
9
|
Requires-Python: >=3.11,<3.13
|
|
10
10
|
Classifier: Development Status :: 4 - Beta
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
@@ -17,23 +17,28 @@ Classifier: Typing :: Typed
|
|
|
17
17
|
Requires-Dist: PyJWT (>=2.8.0)
|
|
18
18
|
Requires-Dist: aiohttp (>=3.9.0)
|
|
19
19
|
Requires-Dist: httpx (>=0.25)
|
|
20
|
+
Requires-Dist: keyring (>=25.0.0)
|
|
20
21
|
Requires-Dist: nats-py (>=2.4.0)
|
|
21
22
|
Requires-Dist: opentelemetry-api (>=1.20.0)
|
|
22
23
|
Requires-Dist: opentelemetry-instrumentation-httpx (>=0.41b0)
|
|
23
24
|
Requires-Dist: pydantic (>=2.4)
|
|
25
|
+
Requires-Dist: rich (>=13.7.0)
|
|
24
26
|
Requires-Dist: stevedore (>=5.1.0)
|
|
27
|
+
Requires-Dist: typer (>=0.9.0)
|
|
25
28
|
Requires-Dist: typing-extensions
|
|
26
29
|
Project-URL: Documentation, https://docs.agentic-fabric.org
|
|
27
30
|
Project-URL: Homepage, https://github.com/agentic-fabric/agentic-fabric
|
|
28
31
|
Project-URL: Repository, https://github.com/agentic-fabric/agentic-fabric
|
|
29
32
|
Description-Content-Type: text/markdown
|
|
30
33
|
|
|
31
|
-
# Agentic
|
|
34
|
+
# Agentic Fabriq SDK
|
|
32
35
|
|
|
33
|
-
`agentic-fabriq-sdk` provides a Python SDK for interacting with
|
|
36
|
+
`agentic-fabriq-sdk` provides a Python SDK and CLI tool for interacting with Agentic Fabriq.
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
-
|
|
38
|
+
**What's included:**
|
|
39
|
+
- 🐍 **Python SDK**: High-level client (`af_sdk.FabriqClient`) and DX layer
|
|
40
|
+
- 🛠️ **CLI Tool**: `afctl` command for authentication and management
|
|
41
|
+
- 🔐 **OAuth2/PKCE**: Secure browser-based authentication with token storage
|
|
37
42
|
|
|
38
43
|
## Install
|
|
39
44
|
|
|
@@ -41,13 +46,38 @@ Description-Content-Type: text/markdown
|
|
|
41
46
|
pip install agentic-fabriq-sdk
|
|
42
47
|
```
|
|
43
48
|
|
|
49
|
+
This installs both the Python library and the `afctl` CLI tool.
|
|
50
|
+
|
|
44
51
|
## Quickstart
|
|
45
52
|
|
|
53
|
+
### CLI Tool
|
|
54
|
+
|
|
55
|
+
Authenticate and manage your Agentic Fabriq resources:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Login with OAuth2 (browser opens automatically)
|
|
59
|
+
afctl auth login
|
|
60
|
+
|
|
61
|
+
# Check authentication status
|
|
62
|
+
afctl auth status
|
|
63
|
+
|
|
64
|
+
# List available tools
|
|
65
|
+
afctl tools list
|
|
66
|
+
|
|
67
|
+
# List agents
|
|
68
|
+
afctl agents list
|
|
69
|
+
|
|
70
|
+
# Get help
|
|
71
|
+
afctl --help
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Python SDK
|
|
75
|
+
|
|
46
76
|
```python
|
|
47
77
|
from af_sdk.fabriq_client import FabriqClient
|
|
48
78
|
|
|
49
79
|
TOKEN = "..." # Bearer JWT for the Fabriq Gateway
|
|
50
|
-
BASE = "
|
|
80
|
+
BASE = "https://dashboard.agenticfabriq.com"
|
|
51
81
|
|
|
52
82
|
async def main():
|
|
53
83
|
async with FabriqClient(base_url=BASE, auth_token=TOKEN) as af:
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
# Agentic
|
|
1
|
+
# Agentic Fabriq SDK
|
|
2
2
|
|
|
3
|
-
`agentic-fabriq-sdk` provides a Python SDK for interacting with
|
|
3
|
+
`agentic-fabriq-sdk` provides a Python SDK and CLI tool for interacting with Agentic Fabriq.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
-
|
|
5
|
+
**What's included:**
|
|
6
|
+
- 🐍 **Python SDK**: High-level client (`af_sdk.FabriqClient`) and DX layer
|
|
7
|
+
- 🛠️ **CLI Tool**: `afctl` command for authentication and management
|
|
8
|
+
- 🔐 **OAuth2/PKCE**: Secure browser-based authentication with token storage
|
|
7
9
|
|
|
8
10
|
## Install
|
|
9
11
|
|
|
@@ -11,13 +13,38 @@
|
|
|
11
13
|
pip install agentic-fabriq-sdk
|
|
12
14
|
```
|
|
13
15
|
|
|
16
|
+
This installs both the Python library and the `afctl` CLI tool.
|
|
17
|
+
|
|
14
18
|
## Quickstart
|
|
15
19
|
|
|
20
|
+
### CLI Tool
|
|
21
|
+
|
|
22
|
+
Authenticate and manage your Agentic Fabriq resources:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Login with OAuth2 (browser opens automatically)
|
|
26
|
+
afctl auth login
|
|
27
|
+
|
|
28
|
+
# Check authentication status
|
|
29
|
+
afctl auth status
|
|
30
|
+
|
|
31
|
+
# List available tools
|
|
32
|
+
afctl tools list
|
|
33
|
+
|
|
34
|
+
# List agents
|
|
35
|
+
afctl agents list
|
|
36
|
+
|
|
37
|
+
# Get help
|
|
38
|
+
afctl --help
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Python SDK
|
|
42
|
+
|
|
16
43
|
```python
|
|
17
44
|
from af_sdk.fabriq_client import FabriqClient
|
|
18
45
|
|
|
19
46
|
TOKEN = "..." # Bearer JWT for the Fabriq Gateway
|
|
20
|
-
BASE = "
|
|
47
|
+
BASE = "https://dashboard.agenticfabriq.com"
|
|
21
48
|
|
|
22
49
|
async def main():
|
|
23
50
|
async with FabriqClient(base_url=BASE, auth_token=TOKEN) as af:
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent management commands for the Agentic Fabric CLI.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from af_cli.core.client import get_client
|
|
10
|
+
from af_cli.core.output import error, info, print_output, success, warning, prompt_confirm
|
|
11
|
+
|
|
12
|
+
app = typer.Typer(help="Agent management commands")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@app.command()
|
|
16
|
+
def list(
|
|
17
|
+
page: int = typer.Option(1, "--page", "-p", help="Page number"),
|
|
18
|
+
page_size: int = typer.Option(20, "--page-size", "-s", help="Page size"),
|
|
19
|
+
search: Optional[str] = typer.Option(None, "--search", "-q", help="Search query"),
|
|
20
|
+
format: str = typer.Option("table", "--format", "-f", help="Output format"),
|
|
21
|
+
):
|
|
22
|
+
"""List agents."""
|
|
23
|
+
try:
|
|
24
|
+
with get_client() as client:
|
|
25
|
+
params = {
|
|
26
|
+
"page": page,
|
|
27
|
+
"page_size": page_size,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if search:
|
|
31
|
+
params["search"] = search
|
|
32
|
+
|
|
33
|
+
response = client.get("/api/v1/agents", params=params)
|
|
34
|
+
|
|
35
|
+
# Support both new (items/total) and legacy (agents/total) shapes
|
|
36
|
+
if isinstance(response, dict):
|
|
37
|
+
if "items" in response:
|
|
38
|
+
agents = response.get("items", [])
|
|
39
|
+
total = response.get("total", len(agents))
|
|
40
|
+
elif "agents" in response:
|
|
41
|
+
agents = response.get("agents", [])
|
|
42
|
+
total = response.get("total", len(agents))
|
|
43
|
+
else:
|
|
44
|
+
agents = []
|
|
45
|
+
total = 0
|
|
46
|
+
elif isinstance(response, list):
|
|
47
|
+
agents = response
|
|
48
|
+
total = len(agents)
|
|
49
|
+
else:
|
|
50
|
+
agents = []
|
|
51
|
+
total = 0
|
|
52
|
+
|
|
53
|
+
if not agents:
|
|
54
|
+
warning("No agents found")
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
# Format agent data for display
|
|
58
|
+
display_data = []
|
|
59
|
+
for agent in agents:
|
|
60
|
+
display_data.append({
|
|
61
|
+
"id": agent.get("id"),
|
|
62
|
+
"name": agent.get("name"),
|
|
63
|
+
"version": agent.get("version"),
|
|
64
|
+
"protocol": agent.get("protocol"),
|
|
65
|
+
"endpoint_url": agent.get("endpoint_url"),
|
|
66
|
+
"auth_method": agent.get("auth_method"),
|
|
67
|
+
"created_at": (agent.get("created_at") or "")[:19], # Trim microseconds if present
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
print_output(
|
|
71
|
+
display_data,
|
|
72
|
+
format_type=format,
|
|
73
|
+
columns=["id", "name", "version", "protocol", "endpoint_url", "auth_method", "created_at"],
|
|
74
|
+
title=f"Agents ({len(agents)}/{total})"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
except Exception as e:
|
|
78
|
+
error(f"Failed to list agents: {e}")
|
|
79
|
+
raise typer.Exit(1)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@app.command()
|
|
83
|
+
def get(
|
|
84
|
+
agent_id: str = typer.Argument(..., help="Agent ID"),
|
|
85
|
+
format: str = typer.Option("table", "--format", "-f", help="Output format"),
|
|
86
|
+
):
|
|
87
|
+
"""Get agent details."""
|
|
88
|
+
try:
|
|
89
|
+
with get_client() as client:
|
|
90
|
+
agent = client.get(f"/api/v1/agents/{agent_id}")
|
|
91
|
+
|
|
92
|
+
print_output(
|
|
93
|
+
agent,
|
|
94
|
+
format_type=format,
|
|
95
|
+
title=f"Agent {agent_id}"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
except Exception as e:
|
|
99
|
+
error(f"Failed to get agent: {e}")
|
|
100
|
+
raise typer.Exit(1)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@app.command()
|
|
104
|
+
def create(
|
|
105
|
+
name: str = typer.Option(..., "--name", "-n", help="Agent name"),
|
|
106
|
+
description: Optional[str] = typer.Option(None, "--description", "-d", help="Agent description"),
|
|
107
|
+
version: str = typer.Option("1.0.0", "--version", "-v", help="Agent version"),
|
|
108
|
+
protocol: str = typer.Option("HTTP", "--protocol", help="Agent protocol"),
|
|
109
|
+
endpoint_url: str = typer.Option(..., "--endpoint-url", "-u", help="Agent endpoint URL"),
|
|
110
|
+
auth_method: str = typer.Option("OAUTH2", "--auth-method", "-a", help="Authentication method"),
|
|
111
|
+
):
|
|
112
|
+
"""Create a new agent."""
|
|
113
|
+
try:
|
|
114
|
+
with get_client() as client:
|
|
115
|
+
data = {
|
|
116
|
+
"name": name,
|
|
117
|
+
"description": description,
|
|
118
|
+
"version": version,
|
|
119
|
+
"protocol": protocol,
|
|
120
|
+
"endpoint_url": endpoint_url,
|
|
121
|
+
"auth_method": auth_method,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
agent = client.post("/api/v1/agents", data)
|
|
125
|
+
|
|
126
|
+
success(f"Agent created: {agent['id']}")
|
|
127
|
+
info(f"Name: {agent['name']}")
|
|
128
|
+
info(f"Endpoint: {agent['endpoint_url']}")
|
|
129
|
+
|
|
130
|
+
except Exception as e:
|
|
131
|
+
error(f"Failed to create agent: {e}")
|
|
132
|
+
raise typer.Exit(1)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@app.command()
|
|
136
|
+
def update(
|
|
137
|
+
agent_id: str = typer.Argument(..., help="Agent ID"),
|
|
138
|
+
name: Optional[str] = typer.Option(None, "--name", "-n", help="Agent name"),
|
|
139
|
+
description: Optional[str] = typer.Option(None, "--description", "-d", help="Agent description"),
|
|
140
|
+
version: Optional[str] = typer.Option(None, "--version", "-v", help="Agent version"),
|
|
141
|
+
protocol: Optional[str] = typer.Option(None, "--protocol", help="Agent protocol"),
|
|
142
|
+
endpoint_url: Optional[str] = typer.Option(None, "--endpoint-url", "-u", help="Agent endpoint URL"),
|
|
143
|
+
auth_method: Optional[str] = typer.Option(None, "--auth-method", "-a", help="Authentication method"),
|
|
144
|
+
):
|
|
145
|
+
"""Update an agent."""
|
|
146
|
+
try:
|
|
147
|
+
with get_client() as client:
|
|
148
|
+
data = {}
|
|
149
|
+
|
|
150
|
+
if name is not None:
|
|
151
|
+
data["name"] = name
|
|
152
|
+
if description is not None:
|
|
153
|
+
data["description"] = description
|
|
154
|
+
if version is not None:
|
|
155
|
+
data["version"] = version
|
|
156
|
+
if protocol is not None:
|
|
157
|
+
data["protocol"] = protocol
|
|
158
|
+
if endpoint_url is not None:
|
|
159
|
+
data["endpoint_url"] = endpoint_url
|
|
160
|
+
if auth_method is not None:
|
|
161
|
+
data["auth_method"] = auth_method
|
|
162
|
+
|
|
163
|
+
if not data:
|
|
164
|
+
error("No update data provided")
|
|
165
|
+
raise typer.Exit(1)
|
|
166
|
+
|
|
167
|
+
agent = client.put(f"/api/v1/agents/{agent_id}", data)
|
|
168
|
+
|
|
169
|
+
success(f"Agent updated: {agent['id']}")
|
|
170
|
+
info(f"Name: {agent['name']}")
|
|
171
|
+
info(f"Endpoint: {agent['endpoint_url']}")
|
|
172
|
+
|
|
173
|
+
except Exception as e:
|
|
174
|
+
error(f"Failed to update agent: {e}")
|
|
175
|
+
raise typer.Exit(1)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@app.command()
|
|
179
|
+
def delete(
|
|
180
|
+
agent_id: str = typer.Argument(..., help="Agent ID"),
|
|
181
|
+
force: bool = typer.Option(False, "--force", "-f", help="Force deletion without confirmation"),
|
|
182
|
+
):
|
|
183
|
+
"""Delete an agent."""
|
|
184
|
+
try:
|
|
185
|
+
if not force:
|
|
186
|
+
if not prompt_confirm(f"Are you sure you want to delete agent {agent_id}?"):
|
|
187
|
+
info("Deletion cancelled")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
with get_client() as client:
|
|
191
|
+
client.delete(f"/api/v1/agents/{agent_id}")
|
|
192
|
+
|
|
193
|
+
success(f"Agent deleted: {agent_id}")
|
|
194
|
+
|
|
195
|
+
except Exception as e:
|
|
196
|
+
error(f"Failed to delete agent: {e}")
|
|
197
|
+
raise typer.Exit(1)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@app.command()
|
|
201
|
+
def invoke(
|
|
202
|
+
agent_id: str = typer.Argument(..., help="Agent ID"),
|
|
203
|
+
input_text: str = typer.Option(..., "--input", "-i", help="Input message for the agent"),
|
|
204
|
+
format: str = typer.Option("table", "--format", "-f", help="Output format"),
|
|
205
|
+
):
|
|
206
|
+
"""Invoke an agent."""
|
|
207
|
+
try:
|
|
208
|
+
with get_client() as client:
|
|
209
|
+
data = {
|
|
210
|
+
"input": input_text,
|
|
211
|
+
"parameters": {},
|
|
212
|
+
"context": {},
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
info(f"Invoking agent {agent_id}...")
|
|
216
|
+
response = client.post(f"/api/v1/agents/{agent_id}/invoke", data)
|
|
217
|
+
|
|
218
|
+
success("Agent invoked successfully")
|
|
219
|
+
|
|
220
|
+
# Display response
|
|
221
|
+
if format == "table":
|
|
222
|
+
info("Response:")
|
|
223
|
+
print(response["output"])
|
|
224
|
+
|
|
225
|
+
if response.get("metadata"):
|
|
226
|
+
info("\nMetadata:")
|
|
227
|
+
print_output(response["metadata"], format_type="yaml")
|
|
228
|
+
|
|
229
|
+
if response.get("logs"):
|
|
230
|
+
info("\nLogs:")
|
|
231
|
+
for log in response["logs"]:
|
|
232
|
+
print(f" {log}")
|
|
233
|
+
else:
|
|
234
|
+
print_output(response, format_type=format)
|
|
235
|
+
|
|
236
|
+
except Exception as e:
|
|
237
|
+
error(f"Failed to invoke agent: {e}")
|
|
238
|
+
raise typer.Exit(1)
|