agentex-sdk 0.2.6__py3-none-any.whl → 0.2.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.
- agentex/_version.py +1 -1
- agentex/lib/adk/utils/_modules/client.py +6 -5
- agentex/lib/cli/commands/agents.py +36 -2
- agentex/lib/cli/debug/__init__.py +15 -0
- agentex/lib/cli/debug/debug_config.py +116 -0
- agentex/lib/cli/debug/debug_handlers.py +174 -0
- agentex/lib/cli/handlers/agent_handlers.py +3 -2
- agentex/lib/cli/handlers/deploy_handlers.py +1 -2
- agentex/lib/cli/handlers/run_handlers.py +24 -7
- agentex/lib/cli/templates/default/pyproject.toml.j2 +0 -1
- agentex/lib/cli/templates/sync/pyproject.toml.j2 +0 -1
- agentex/lib/cli/templates/temporal/project/acp.py.j2 +31 -0
- agentex/lib/cli/templates/temporal/project/run_worker.py.j2 +4 -1
- agentex/lib/cli/templates/temporal/pyproject.toml.j2 +1 -1
- agentex/lib/core/services/adk/acp/acp.py +5 -5
- agentex/lib/core/temporal/workers/worker.py +24 -0
- agentex/lib/environment_variables.py +2 -0
- agentex/lib/sdk/fastacp/base/base_acp_server.py +13 -90
- agentex/lib/utils/debug.py +63 -0
- agentex/lib/utils/registration.py +101 -0
- agentex/types/agent.py +7 -0
- {agentex_sdk-0.2.6.dist-info → agentex_sdk-0.2.7.dist-info}/METADATA +32 -1
- {agentex_sdk-0.2.6.dist-info → agentex_sdk-0.2.7.dist-info}/RECORD +26 -21
- {agentex_sdk-0.2.6.dist-info → agentex_sdk-0.2.7.dist-info}/WHEEL +0 -0
- {agentex_sdk-0.2.6.dist-info → agentex_sdk-0.2.7.dist-info}/entry_points.txt +0 -0
- {agentex_sdk-0.2.6.dist-info → agentex_sdk-0.2.7.dist-info}/licenses/LICENSE +0 -0
agentex/_version.py
CHANGED
@@ -8,17 +8,18 @@ logger = make_logger(__name__)
|
|
8
8
|
|
9
9
|
|
10
10
|
class EnvAuth(httpx.Auth):
|
11
|
-
def __init__(self, header_name="x-agent-
|
11
|
+
def __init__(self, header_name="x-agent-api-key"):
|
12
12
|
self.header_name = header_name
|
13
13
|
|
14
14
|
def auth_flow(self, request):
|
15
15
|
# This gets called for every request
|
16
16
|
env_vars = EnvironmentVariables.refresh()
|
17
17
|
if env_vars:
|
18
|
-
|
19
|
-
if
|
20
|
-
request.headers[self.header_name] =
|
21
|
-
|
18
|
+
agent_api_key = env_vars.AGENT_API_KEY
|
19
|
+
if agent_api_key:
|
20
|
+
request.headers[self.header_name] = agent_api_key
|
21
|
+
masked_key = agent_api_key[-4:] if agent_api_key and len(agent_api_key) > 4 else "****"
|
22
|
+
logger.info(f"Adding header {self.header_name}:{masked_key}")
|
22
23
|
yield request
|
23
24
|
|
24
25
|
|
@@ -11,6 +11,7 @@ from agentex.lib.cli.handlers.agent_handlers import (
|
|
11
11
|
build_agent,
|
12
12
|
run_agent,
|
13
13
|
)
|
14
|
+
from agentex.lib.cli.debug import DebugConfig, DebugMode
|
14
15
|
from agentex.lib.cli.handlers.cleanup_handlers import cleanup_agent_workflows
|
15
16
|
from agentex.lib.cli.handlers.deploy_handlers import (
|
16
17
|
DeploymentError,
|
@@ -171,7 +172,13 @@ def run(
|
|
171
172
|
False,
|
172
173
|
help="Clean up existing workflows for this agent before starting"
|
173
174
|
),
|
174
|
-
|
175
|
+
# Debug options
|
176
|
+
debug: bool = typer.Option(False, help="Enable debug mode for both worker and ACP (disables auto-reload)"),
|
177
|
+
debug_worker: bool = typer.Option(False, help="Enable debug mode for temporal worker only"),
|
178
|
+
debug_acp: bool = typer.Option(False, help="Enable debug mode for ACP server only"),
|
179
|
+
debug_port: int = typer.Option(5678, help="Port for remote debugging (worker uses this, ACP uses port+1)"),
|
180
|
+
wait_for_debugger: bool = typer.Option(False, help="Wait for debugger to attach before starting"),
|
181
|
+
) -> None:
|
175
182
|
"""
|
176
183
|
Run an agent locally from the given manifest.
|
177
184
|
"""
|
@@ -196,8 +203,35 @@ def run(
|
|
196
203
|
console.print(f"[yellow]⚠ Pre-run cleanup failed: {str(e)}[/yellow]")
|
197
204
|
logger.warning(f"Pre-run cleanup failed: {e}")
|
198
205
|
|
206
|
+
# Create debug configuration based on CLI flags
|
207
|
+
debug_config = None
|
208
|
+
if debug or debug_worker or debug_acp:
|
209
|
+
# Determine debug mode
|
210
|
+
if debug:
|
211
|
+
mode = DebugMode.BOTH
|
212
|
+
elif debug_worker and debug_acp:
|
213
|
+
mode = DebugMode.BOTH
|
214
|
+
elif debug_worker:
|
215
|
+
mode = DebugMode.WORKER
|
216
|
+
elif debug_acp:
|
217
|
+
mode = DebugMode.ACP
|
218
|
+
else:
|
219
|
+
mode = DebugMode.NONE
|
220
|
+
|
221
|
+
debug_config = DebugConfig(
|
222
|
+
enabled=True,
|
223
|
+
mode=mode,
|
224
|
+
port=debug_port,
|
225
|
+
wait_for_attach=wait_for_debugger,
|
226
|
+
auto_port=False # Use fixed port to match VS Code launch.json
|
227
|
+
)
|
228
|
+
|
229
|
+
console.print(f"[blue]🐛 Debug mode enabled: {mode.value}[/blue]")
|
230
|
+
if wait_for_debugger:
|
231
|
+
console.print("[yellow]⏳ Processes will wait for debugger attachment[/yellow]")
|
232
|
+
|
199
233
|
try:
|
200
|
-
run_agent(manifest_path=manifest)
|
234
|
+
run_agent(manifest_path=manifest, debug_config=debug_config)
|
201
235
|
except Exception as e:
|
202
236
|
typer.echo(f"Error running agent: {str(e)}", err=True)
|
203
237
|
logger.exception("Error running agent")
|
@@ -0,0 +1,15 @@
|
|
1
|
+
"""
|
2
|
+
Debug functionality for AgentEx CLI
|
3
|
+
|
4
|
+
Provides debug support for temporal workers and ACP servers during local development.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from .debug_config import DebugConfig, DebugMode
|
8
|
+
from .debug_handlers import start_acp_server_debug, start_temporal_worker_debug
|
9
|
+
|
10
|
+
__all__ = [
|
11
|
+
"DebugConfig",
|
12
|
+
"DebugMode",
|
13
|
+
"start_acp_server_debug",
|
14
|
+
"start_temporal_worker_debug",
|
15
|
+
]
|
@@ -0,0 +1,116 @@
|
|
1
|
+
"""
|
2
|
+
Debug configuration models for AgentEx CLI debugging.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import socket
|
6
|
+
from enum import Enum
|
7
|
+
from typing import Optional
|
8
|
+
|
9
|
+
from agentex.lib.utils.model_utils import BaseModel
|
10
|
+
|
11
|
+
|
12
|
+
class DebugMode(str, Enum):
|
13
|
+
"""Debug mode options"""
|
14
|
+
WORKER = "worker"
|
15
|
+
ACP = "acp"
|
16
|
+
BOTH = "both"
|
17
|
+
NONE = "none"
|
18
|
+
|
19
|
+
|
20
|
+
class DebugConfig(BaseModel):
|
21
|
+
"""Configuration for debug mode"""
|
22
|
+
|
23
|
+
enabled: bool = False
|
24
|
+
mode: DebugMode = DebugMode.NONE
|
25
|
+
port: int = 5678
|
26
|
+
wait_for_attach: bool = False
|
27
|
+
auto_port: bool = True # Automatically find available port if specified port is busy
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def create_worker_debug(
|
31
|
+
cls,
|
32
|
+
port: int = 5678,
|
33
|
+
wait_for_attach: bool = False,
|
34
|
+
auto_port: bool = True
|
35
|
+
) -> "DebugConfig":
|
36
|
+
"""Create debug config for worker debugging"""
|
37
|
+
return cls(
|
38
|
+
enabled=True,
|
39
|
+
mode=DebugMode.WORKER,
|
40
|
+
port=port,
|
41
|
+
wait_for_attach=wait_for_attach,
|
42
|
+
auto_port=auto_port
|
43
|
+
)
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def create_acp_debug(
|
47
|
+
cls,
|
48
|
+
port: int = 5679,
|
49
|
+
wait_for_attach: bool = False,
|
50
|
+
auto_port: bool = True
|
51
|
+
) -> "DebugConfig":
|
52
|
+
"""Create debug config for ACP debugging"""
|
53
|
+
return cls(
|
54
|
+
enabled=True,
|
55
|
+
mode=DebugMode.ACP,
|
56
|
+
port=port,
|
57
|
+
wait_for_attach=wait_for_attach,
|
58
|
+
auto_port=auto_port
|
59
|
+
)
|
60
|
+
|
61
|
+
@classmethod
|
62
|
+
def create_both_debug(
|
63
|
+
cls,
|
64
|
+
worker_port: int = 5678,
|
65
|
+
acp_port: int = 5679,
|
66
|
+
wait_for_attach: bool = False,
|
67
|
+
auto_port: bool = True
|
68
|
+
) -> "DebugConfig":
|
69
|
+
"""Create debug config for both worker and ACP debugging"""
|
70
|
+
return cls(
|
71
|
+
enabled=True,
|
72
|
+
mode=DebugMode.BOTH,
|
73
|
+
port=worker_port, # Primary port for worker
|
74
|
+
wait_for_attach=wait_for_attach,
|
75
|
+
auto_port=auto_port
|
76
|
+
)
|
77
|
+
|
78
|
+
def should_debug_worker(self) -> bool:
|
79
|
+
"""Check if worker should be debugged"""
|
80
|
+
return self.enabled and self.mode in (DebugMode.WORKER, DebugMode.BOTH)
|
81
|
+
|
82
|
+
def should_debug_acp(self) -> bool:
|
83
|
+
"""Check if ACP should be debugged"""
|
84
|
+
return self.enabled and self.mode in (DebugMode.ACP, DebugMode.BOTH)
|
85
|
+
|
86
|
+
def get_worker_port(self) -> int:
|
87
|
+
"""Get port for worker debugging"""
|
88
|
+
return self.port
|
89
|
+
|
90
|
+
def get_acp_port(self) -> int:
|
91
|
+
"""Get port for ACP debugging"""
|
92
|
+
if self.mode == DebugMode.BOTH:
|
93
|
+
return self.port + 1 # Use port + 1 for ACP when debugging both
|
94
|
+
return self.port
|
95
|
+
|
96
|
+
|
97
|
+
def find_available_port(start_port: int = 5678, max_attempts: int = 10) -> int:
|
98
|
+
"""Find an available port starting from start_port"""
|
99
|
+
for port in range(start_port, start_port + max_attempts):
|
100
|
+
try:
|
101
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
102
|
+
s.bind(('localhost', port))
|
103
|
+
return port
|
104
|
+
except OSError:
|
105
|
+
continue
|
106
|
+
|
107
|
+
# If we can't find an available port, just return the start port
|
108
|
+
# and let the debug server handle the error
|
109
|
+
return start_port
|
110
|
+
|
111
|
+
|
112
|
+
def resolve_debug_port(config: DebugConfig, target_port: int) -> int:
|
113
|
+
"""Resolve the actual port to use for debugging"""
|
114
|
+
if config.auto_port:
|
115
|
+
return find_available_port(target_port)
|
116
|
+
return target_port
|
@@ -0,0 +1,174 @@
|
|
1
|
+
"""
|
2
|
+
Debug process handlers for AgentEx CLI.
|
3
|
+
|
4
|
+
Provides debug-enabled versions of ACP server and temporal worker startup.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import asyncio
|
8
|
+
import sys
|
9
|
+
from pathlib import Path
|
10
|
+
from typing import Dict, TYPE_CHECKING
|
11
|
+
|
12
|
+
from rich.console import Console
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
import asyncio.subprocess
|
16
|
+
|
17
|
+
from .debug_config import DebugConfig, resolve_debug_port
|
18
|
+
from agentex.lib.utils.logging import make_logger
|
19
|
+
|
20
|
+
logger = make_logger(__name__)
|
21
|
+
console = Console()
|
22
|
+
|
23
|
+
|
24
|
+
async def start_temporal_worker_debug(
|
25
|
+
worker_path: Path,
|
26
|
+
env: Dict[str, str],
|
27
|
+
debug_config: DebugConfig
|
28
|
+
):
|
29
|
+
"""Start temporal worker with debug support"""
|
30
|
+
|
31
|
+
if not debug_config.should_debug_worker():
|
32
|
+
raise ValueError("Debug config is not configured for worker debugging")
|
33
|
+
|
34
|
+
# Resolve the actual debug port
|
35
|
+
debug_port = resolve_debug_port(debug_config, debug_config.get_worker_port())
|
36
|
+
|
37
|
+
# Add debug environment variables
|
38
|
+
debug_env = env.copy()
|
39
|
+
debug_env.update({
|
40
|
+
"AGENTEX_DEBUG_ENABLED": "true",
|
41
|
+
"AGENTEX_DEBUG_PORT": str(debug_port),
|
42
|
+
"AGENTEX_DEBUG_WAIT_FOR_ATTACH": str(debug_config.wait_for_attach).lower(),
|
43
|
+
"AGENTEX_DEBUG_TYPE": "worker"
|
44
|
+
})
|
45
|
+
|
46
|
+
# Start the worker process
|
47
|
+
# For debugging, use absolute path to run_worker.py to run from workspace root
|
48
|
+
worker_script = worker_path.parent / "run_worker.py"
|
49
|
+
cmd = [sys.executable, str(worker_script)]
|
50
|
+
|
51
|
+
console.print(f"[blue]🐛 Starting Temporal worker in debug mode[/blue]")
|
52
|
+
console.print(f"[yellow]📡 Debug server will listen on port {debug_port}[/yellow]")
|
53
|
+
console.print(f"[green]✓ VS Code should connect to: localhost:{debug_port}[/green]")
|
54
|
+
|
55
|
+
if debug_config.wait_for_attach:
|
56
|
+
console.print(f"[yellow]⏳ Worker will wait for debugger to attach[/yellow]")
|
57
|
+
|
58
|
+
console.print(f"[dim]💡 In your IDE: Attach to localhost:{debug_port}[/dim]")
|
59
|
+
console.print(f"[dim]🔧 If connection fails, check that VS Code launch.json uses port {debug_port}[/dim]")
|
60
|
+
|
61
|
+
return await asyncio.create_subprocess_exec(
|
62
|
+
*cmd,
|
63
|
+
cwd=Path.cwd(), # Run from current working directory (workspace root)
|
64
|
+
env=debug_env,
|
65
|
+
stdout=asyncio.subprocess.PIPE,
|
66
|
+
stderr=asyncio.subprocess.STDOUT,
|
67
|
+
)
|
68
|
+
|
69
|
+
|
70
|
+
async def start_acp_server_debug(
|
71
|
+
acp_path: Path,
|
72
|
+
port: int,
|
73
|
+
env: Dict[str, str],
|
74
|
+
debug_config: DebugConfig
|
75
|
+
):
|
76
|
+
"""Start ACP server with debug support"""
|
77
|
+
|
78
|
+
if not debug_config.should_debug_acp():
|
79
|
+
raise ValueError("Debug config is not configured for ACP debugging")
|
80
|
+
|
81
|
+
# Resolve the actual debug port
|
82
|
+
debug_port = resolve_debug_port(debug_config, debug_config.get_acp_port())
|
83
|
+
|
84
|
+
# Add debug environment variables
|
85
|
+
debug_env = env.copy()
|
86
|
+
debug_env.update({
|
87
|
+
"AGENTEX_DEBUG_ENABLED": "true",
|
88
|
+
"AGENTEX_DEBUG_PORT": str(debug_port),
|
89
|
+
"AGENTEX_DEBUG_WAIT_FOR_ATTACH": str(debug_config.wait_for_attach).lower(),
|
90
|
+
"AGENTEX_DEBUG_TYPE": "acp"
|
91
|
+
})
|
92
|
+
|
93
|
+
# Disable uvicorn auto-reload in debug mode to prevent conflicts
|
94
|
+
cmd = [
|
95
|
+
sys.executable,
|
96
|
+
"-m",
|
97
|
+
"uvicorn",
|
98
|
+
f"{acp_path.parent.name}.acp:acp",
|
99
|
+
"--port",
|
100
|
+
str(port),
|
101
|
+
"--host",
|
102
|
+
"0.0.0.0",
|
103
|
+
# Note: No --reload flag when debugging
|
104
|
+
]
|
105
|
+
|
106
|
+
console.print(f"[blue]🐛 Starting ACP server in debug mode[/blue]")
|
107
|
+
console.print(f"[yellow]📡 Debug server will listen on port {debug_port}[/yellow]")
|
108
|
+
|
109
|
+
if debug_config.wait_for_attach:
|
110
|
+
console.print(f"[yellow]⏳ ACP server will wait for debugger to attach[/yellow]")
|
111
|
+
|
112
|
+
console.print(f"[dim]💡 In your IDE: Attach to localhost:{debug_port}[/dim]")
|
113
|
+
|
114
|
+
return await asyncio.create_subprocess_exec(
|
115
|
+
*cmd,
|
116
|
+
cwd=acp_path.parent.parent,
|
117
|
+
env=debug_env,
|
118
|
+
stdout=asyncio.subprocess.PIPE,
|
119
|
+
stderr=asyncio.subprocess.STDOUT,
|
120
|
+
)
|
121
|
+
|
122
|
+
|
123
|
+
def create_debug_startup_script() -> str:
|
124
|
+
"""Create a Python script snippet for debug initialization"""
|
125
|
+
return '''
|
126
|
+
import os
|
127
|
+
import sys
|
128
|
+
|
129
|
+
# Debug initialization for AgentEx
|
130
|
+
if os.getenv("AGENTEX_DEBUG_ENABLED") == "true":
|
131
|
+
try:
|
132
|
+
import debugpy
|
133
|
+
debug_port = int(os.getenv("AGENTEX_DEBUG_PORT", "5678"))
|
134
|
+
debug_type = os.getenv("AGENTEX_DEBUG_TYPE", "unknown")
|
135
|
+
wait_for_attach = os.getenv("AGENTEX_DEBUG_WAIT_FOR_ATTACH", "false").lower() == "true"
|
136
|
+
|
137
|
+
# Configure debugpy
|
138
|
+
debugpy.configure(subProcess=False)
|
139
|
+
debugpy.listen(debug_port)
|
140
|
+
|
141
|
+
print(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
|
142
|
+
|
143
|
+
if wait_for_attach:
|
144
|
+
print(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
|
145
|
+
debugpy.wait_for_client()
|
146
|
+
print(f"✅ [{debug_type.upper()}] Debugger attached!")
|
147
|
+
else:
|
148
|
+
print(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
|
149
|
+
|
150
|
+
except ImportError:
|
151
|
+
print("❌ debugpy not available. Install with: pip install debugpy")
|
152
|
+
sys.exit(1)
|
153
|
+
except Exception as e:
|
154
|
+
print(f"❌ Debug setup failed: {e}")
|
155
|
+
sys.exit(1)
|
156
|
+
'''
|
157
|
+
|
158
|
+
|
159
|
+
def inject_debug_code_to_worker_template() -> str:
|
160
|
+
"""Generate debug code to inject into worker template"""
|
161
|
+
return """
|
162
|
+
# === DEBUG SETUP (Auto-generated by AgentEx CLI) ===
|
163
|
+
""" + create_debug_startup_script() + """
|
164
|
+
# === END DEBUG SETUP ===
|
165
|
+
"""
|
166
|
+
|
167
|
+
|
168
|
+
def inject_debug_code_to_acp_template() -> str:
|
169
|
+
"""Generate debug code to inject into ACP template"""
|
170
|
+
return """
|
171
|
+
# === DEBUG SETUP (Auto-generated by AgentEx CLI) ===
|
172
|
+
""" + create_debug_startup_script() + """
|
173
|
+
# === END DEBUG SETUP ===
|
174
|
+
"""
|
@@ -7,6 +7,7 @@ from rich.console import Console
|
|
7
7
|
|
8
8
|
from agentex.lib.cli.handlers.run_handlers import RunError
|
9
9
|
from agentex.lib.cli.handlers.run_handlers import run_agent as _run_agent
|
10
|
+
from agentex.lib.cli.debug import DebugConfig
|
10
11
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
11
12
|
from agentex.lib.utils.logging import make_logger
|
12
13
|
|
@@ -126,7 +127,7 @@ def build_agent(
|
|
126
127
|
return image_name
|
127
128
|
|
128
129
|
|
129
|
-
def run_agent(manifest_path: str):
|
130
|
+
def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = None):
|
130
131
|
"""Run an agent locally from the given manifest"""
|
131
132
|
import asyncio
|
132
133
|
import signal
|
@@ -152,7 +153,7 @@ def run_agent(manifest_path: str):
|
|
152
153
|
signal.signal(signal.SIGTERM, signal_handler)
|
153
154
|
|
154
155
|
try:
|
155
|
-
asyncio.run(_run_agent(manifest_path))
|
156
|
+
asyncio.run(_run_agent(manifest_path, debug_config))
|
156
157
|
except KeyboardInterrupt:
|
157
158
|
print("Shutdown completed.")
|
158
159
|
sys.exit(0)
|
@@ -22,7 +22,7 @@ logger = make_logger(__name__)
|
|
22
22
|
console = Console()
|
23
23
|
|
24
24
|
TEMPORAL_WORKER_KEY = "temporal-worker"
|
25
|
-
AGENTEX_AGENTS_HELM_CHART_VERSION = "0.1.
|
25
|
+
AGENTEX_AGENTS_HELM_CHART_VERSION = "0.1.6-v1-beta"
|
26
26
|
|
27
27
|
|
28
28
|
class InputDeployOverrides(BaseModel):
|
@@ -204,7 +204,6 @@ def merge_deployment_configs(
|
|
204
204
|
for pull_secret in manifest.deployment.imagePullSecrets
|
205
205
|
]
|
206
206
|
helm_values["global"]["imagePullSecrets"] = pull_secrets
|
207
|
-
# TODO: Remove this once i bump the chart version again
|
208
207
|
helm_values["imagePullSecrets"] = pull_secrets
|
209
208
|
|
210
209
|
# Apply cluster-specific overrides
|
@@ -18,6 +18,9 @@ from agentex.lib.cli.utils.path_utils import (
|
|
18
18
|
|
19
19
|
from agentex.lib.environment_variables import EnvVarKeys
|
20
20
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
21
|
+
|
22
|
+
# Import debug functionality
|
23
|
+
from agentex.lib.cli.debug import DebugConfig, start_acp_server_debug, start_temporal_worker_debug
|
21
24
|
from agentex.lib.utils.logging import make_logger
|
22
25
|
|
23
26
|
logger = make_logger(__name__)
|
@@ -249,7 +252,7 @@ async def stream_process_output(process: asyncio.subprocess.Process, prefix: str
|
|
249
252
|
logger.debug(f"Output streaming ended for {prefix}: {e}")
|
250
253
|
|
251
254
|
|
252
|
-
async def run_agent(manifest_path: str):
|
255
|
+
async def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = None):
|
253
256
|
"""Run an agent locally from the given manifest"""
|
254
257
|
|
255
258
|
# Validate manifest exists
|
@@ -289,11 +292,16 @@ async def run_agent(manifest_path: str):
|
|
289
292
|
)
|
290
293
|
)
|
291
294
|
|
292
|
-
# Start ACP server
|
295
|
+
# Start ACP server (with debug support if enabled)
|
293
296
|
manifest_dir = Path(manifest_path).parent
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
+
if debug_config and debug_config.should_debug_acp():
|
298
|
+
acp_process = await start_acp_server_debug(
|
299
|
+
file_paths["acp"], manifest.local_development.agent.port, agent_env, debug_config
|
300
|
+
)
|
301
|
+
else:
|
302
|
+
acp_process = await start_acp_server(
|
303
|
+
file_paths["acp"], manifest.local_development.agent.port, agent_env, manifest_dir
|
304
|
+
)
|
297
305
|
process_manager.add_process(acp_process)
|
298
306
|
|
299
307
|
# Start output streaming for ACP
|
@@ -301,9 +309,18 @@ async def run_agent(manifest_path: str):
|
|
301
309
|
|
302
310
|
tasks = [acp_output_task]
|
303
311
|
|
304
|
-
# Start temporal worker if needed
|
312
|
+
# Start temporal worker if needed (with debug support if enabled)
|
305
313
|
if is_temporal_agent(manifest) and file_paths["worker"]:
|
306
|
-
|
314
|
+
if debug_config and debug_config.should_debug_worker():
|
315
|
+
# In debug mode, start worker without auto-reload to prevent conflicts
|
316
|
+
worker_process = await start_temporal_worker_debug(
|
317
|
+
file_paths["worker"], agent_env, debug_config
|
318
|
+
)
|
319
|
+
process_manager.add_process(worker_process)
|
320
|
+
worker_task = asyncio.create_task(stream_process_output(worker_process, "WORKER"))
|
321
|
+
else:
|
322
|
+
# Normal mode with auto-reload
|
323
|
+
worker_task = await start_temporal_worker_with_reload(file_paths["worker"], agent_env, process_manager)
|
307
324
|
tasks.append(worker_task)
|
308
325
|
|
309
326
|
console.print(
|
@@ -1,4 +1,35 @@
|
|
1
1
|
import os
|
2
|
+
import sys
|
3
|
+
|
4
|
+
# === DEBUG SETUP (AgentEx CLI Debug Support) ===
|
5
|
+
if os.getenv("AGENTEX_DEBUG_ENABLED") == "true":
|
6
|
+
try:
|
7
|
+
import debugpy
|
8
|
+
debug_port = int(os.getenv("AGENTEX_DEBUG_PORT", "5679"))
|
9
|
+
debug_type = os.getenv("AGENTEX_DEBUG_TYPE", "acp")
|
10
|
+
wait_for_attach = os.getenv("AGENTEX_DEBUG_WAIT_FOR_ATTACH", "false").lower() == "true"
|
11
|
+
|
12
|
+
# Configure debugpy
|
13
|
+
debugpy.configure(subProcess=False)
|
14
|
+
debugpy.listen(debug_port)
|
15
|
+
|
16
|
+
print(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
|
17
|
+
|
18
|
+
if wait_for_attach:
|
19
|
+
print(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
|
20
|
+
debugpy.wait_for_client()
|
21
|
+
print(f"✅ [{debug_type.upper()}] Debugger attached!")
|
22
|
+
else:
|
23
|
+
print(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
|
24
|
+
|
25
|
+
except ImportError:
|
26
|
+
print("❌ debugpy not available. Install with: pip install debugpy")
|
27
|
+
sys.exit(1)
|
28
|
+
except Exception as e:
|
29
|
+
print(f"❌ Debug setup failed: {e}")
|
30
|
+
sys.exit(1)
|
31
|
+
# === END DEBUG SETUP ===
|
32
|
+
|
2
33
|
from agentex.lib.sdk.fastacp.fastacp import FastACP
|
3
34
|
from agentex.lib.types.fastacp import TemporalACPConfig
|
4
35
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import asyncio
|
2
|
-
import os
|
3
2
|
|
4
3
|
from agentex.lib.core.temporal.activities import get_all_activities
|
5
4
|
from agentex.lib.core.temporal.workers.worker import AgentexWorker
|
6
5
|
from agentex.lib.utils.logging import make_logger
|
6
|
+
from agentex.lib.utils.debug import setup_debug_if_enabled
|
7
7
|
from agentex.lib.environment_variables import EnvironmentVariables
|
8
8
|
|
9
9
|
from workflow import {{ workflow_class }}
|
@@ -15,6 +15,9 @@ logger = make_logger(__name__)
|
|
15
15
|
|
16
16
|
|
17
17
|
async def main():
|
18
|
+
# Setup debug mode if enabled
|
19
|
+
setup_debug_if_enabled()
|
20
|
+
|
18
21
|
task_queue_name = environment_variables.WORKFLOW_TASK_QUEUE
|
19
22
|
if task_queue_name is None:
|
20
23
|
raise ValueError("WORKFLOW_TASK_QUEUE is not set")
|
@@ -6,7 +6,6 @@ build-backend = "hatchling.build"
|
|
6
6
|
name = "{{ project_name }}"
|
7
7
|
version = "0.1.0"
|
8
8
|
description = "{{ description }}"
|
9
|
-
readme = "README.md"
|
10
9
|
requires-python = ">=3.12"
|
11
10
|
dependencies = [
|
12
11
|
"agentex-sdk",
|
@@ -20,6 +19,7 @@ dev = [
|
|
20
19
|
"black",
|
21
20
|
"isort",
|
22
21
|
"flake8",
|
22
|
+
"debugpy>=1.8.15",
|
23
23
|
]
|
24
24
|
|
25
25
|
[tool.hatch.build.targets.wheel]
|
@@ -64,7 +64,7 @@ class ACPService:
|
|
64
64
|
else:
|
65
65
|
raise ValueError("Either agent_name or agent_id must be provided")
|
66
66
|
|
67
|
-
task_entry = Task.model_validate(json_rpc_response
|
67
|
+
task_entry = Task.model_validate(json_rpc_response.result)
|
68
68
|
if span:
|
69
69
|
span.output = task_entry.model_dump()
|
70
70
|
return task_entry
|
@@ -115,7 +115,7 @@ class ACPService:
|
|
115
115
|
else:
|
116
116
|
raise ValueError("Either agent_name or agent_id must be provided")
|
117
117
|
|
118
|
-
task_message = TaskMessage.model_validate(json_rpc_response
|
118
|
+
task_message = TaskMessage.model_validate(json_rpc_response.result)
|
119
119
|
if span:
|
120
120
|
span.output = task_message.model_dump()
|
121
121
|
return task_message
|
@@ -147,7 +147,7 @@ class ACPService:
|
|
147
147
|
agent_name=agent_name,
|
148
148
|
method="event/send",
|
149
149
|
params={
|
150
|
-
"
|
150
|
+
"task_id": task_id,
|
151
151
|
"content": cast(TaskMessageContentParam, content.model_dump()),
|
152
152
|
},
|
153
153
|
)
|
@@ -163,7 +163,7 @@ class ACPService:
|
|
163
163
|
else:
|
164
164
|
raise ValueError("Either agent_name or agent_id must be provided")
|
165
165
|
|
166
|
-
event_entry = Event.model_validate(json_rpc_response
|
166
|
+
event_entry = Event.model_validate(json_rpc_response.result)
|
167
167
|
if span:
|
168
168
|
span.output = event_entry.model_dump()
|
169
169
|
return event_entry
|
@@ -204,7 +204,7 @@ class ACPService:
|
|
204
204
|
else:
|
205
205
|
raise ValueError("Either task_name or task_id must be provided")
|
206
206
|
|
207
|
-
task_entry = Task.model_validate(json_rpc_response
|
207
|
+
task_entry = Task.model_validate(json_rpc_response.result)
|
208
208
|
if span:
|
209
209
|
span.output = task_entry.model_dump()
|
210
210
|
return task_entry
|
@@ -24,6 +24,8 @@ from temporalio.worker import (
|
|
24
24
|
)
|
25
25
|
|
26
26
|
from agentex.lib.utils.logging import make_logger
|
27
|
+
from agentex.lib.utils.registration import register_agent
|
28
|
+
from agentex.lib.environment_variables import EnvironmentVariables
|
27
29
|
|
28
30
|
logger = make_logger(__name__)
|
29
31
|
|
@@ -103,9 +105,16 @@ class AgentexWorker:
|
|
103
105
|
workflow: type,
|
104
106
|
):
|
105
107
|
await self.start_health_check_server()
|
108
|
+
await self._register_agent()
|
106
109
|
temporal_client = await get_temporal_client(
|
107
110
|
temporal_address=os.environ.get("TEMPORAL_ADDRESS", "localhost:7233"),
|
108
111
|
)
|
112
|
+
|
113
|
+
# Enable debug mode if AgentEx debug is enabled (disables deadlock detection)
|
114
|
+
debug_enabled = os.environ.get("AGENTEX_DEBUG_ENABLED", "false").lower() == "true"
|
115
|
+
if debug_enabled:
|
116
|
+
logger.info("🐛 [WORKER] Temporal debug mode enabled - deadlock detection disabled")
|
117
|
+
|
109
118
|
worker = Worker(
|
110
119
|
client=temporal_client,
|
111
120
|
task_queue=self.task_queue,
|
@@ -115,6 +124,7 @@ class AgentexWorker:
|
|
115
124
|
workflow_runner=UnsandboxedWorkflowRunner(),
|
116
125
|
max_concurrent_activities=self.max_concurrent_activities,
|
117
126
|
build_id=str(uuid.uuid4()),
|
127
|
+
debug_mode=debug_enabled, # Disable deadlock detection in debug mode
|
118
128
|
)
|
119
129
|
|
120
130
|
logger.info(f"Starting workers for task queue: {self.task_queue}")
|
@@ -160,3 +170,17 @@ class AgentexWorker:
|
|
160
170
|
f"Failed to start health check server on alternative port {alt_port}: {e}"
|
161
171
|
)
|
162
172
|
raise
|
173
|
+
|
174
|
+
"""
|
175
|
+
Register the worker with the Agentex server.
|
176
|
+
|
177
|
+
Even though the Temporal server will also register the agent with the server,
|
178
|
+
doing this on the worker side is required to make sure that both share the API key
|
179
|
+
which is returned on registration and used to authenticate the worker with the Agentex server.
|
180
|
+
"""
|
181
|
+
async def _register_agent(self):
|
182
|
+
env_vars = EnvironmentVariables.refresh()
|
183
|
+
if env_vars and env_vars.AGENTEX_BASE_URL:
|
184
|
+
await register_agent(env_vars)
|
185
|
+
else:
|
186
|
+
logger.warning("AGENTEX_BASE_URL not set, skipping worker registration")
|
@@ -23,6 +23,7 @@ class EnvVarKeys(str, Enum):
|
|
23
23
|
AGENT_NAME = "AGENT_NAME"
|
24
24
|
AGENT_DESCRIPTION = "AGENT_DESCRIPTION"
|
25
25
|
AGENT_ID = "AGENT_ID"
|
26
|
+
AGENT_API_KEY = "AGENT_API_KEY"
|
26
27
|
# ACP Configuration
|
27
28
|
ACP_URL = "ACP_URL"
|
28
29
|
ACP_PORT = "ACP_PORT"
|
@@ -52,6 +53,7 @@ class EnvironmentVariables(BaseModel):
|
|
52
53
|
AGENT_NAME: str
|
53
54
|
AGENT_DESCRIPTION: str | None = None
|
54
55
|
AGENT_ID: str | None = None
|
56
|
+
AGENT_API_KEY: str | None = None
|
55
57
|
ACP_TYPE: str | None = "agentic"
|
56
58
|
# ACP Configuration
|
57
59
|
ACP_URL: str
|
@@ -1,15 +1,10 @@
|
|
1
1
|
import asyncio
|
2
|
-
import base64
|
3
2
|
import inspect
|
4
|
-
import json
|
5
|
-
import os
|
6
3
|
from collections.abc import AsyncGenerator, Awaitable, Callable
|
7
4
|
from contextlib import asynccontextmanager
|
8
5
|
from typing import Any
|
9
6
|
|
10
|
-
import httpx
|
11
7
|
import uvicorn
|
12
|
-
from agentex.lib.adk.utils._modules.client import create_async_agentex_client
|
13
8
|
from fastapi import FastAPI, Request
|
14
9
|
from fastapi.responses import StreamingResponse
|
15
10
|
from pydantic import TypeAdapter, ValidationError
|
@@ -30,6 +25,7 @@ from agentex.lib.types.task_message_updates import StreamTaskMessageFull, TaskMe
|
|
30
25
|
from agentex.types.task_message_content import TaskMessageContent
|
31
26
|
from agentex.lib.utils.logging import make_logger
|
32
27
|
from agentex.lib.utils.model_utils import BaseModel
|
28
|
+
from agentex.lib.utils.registration import register_agent
|
33
29
|
|
34
30
|
logger = make_logger(__name__)
|
35
31
|
|
@@ -74,7 +70,7 @@ class BaseACPServer(FastAPI):
|
|
74
70
|
async def lifespan_context(app: FastAPI):
|
75
71
|
env_vars = EnvironmentVariables.refresh()
|
76
72
|
if env_vars.AGENTEX_BASE_URL:
|
77
|
-
await
|
73
|
+
await register_agent(env_vars)
|
78
74
|
else:
|
79
75
|
logger.warning("AGENTEX_BASE_URL not set, skipping agent registration")
|
80
76
|
|
@@ -101,6 +97,16 @@ class BaseACPServer(FastAPI):
|
|
101
97
|
data = await request.json()
|
102
98
|
rpc_request = JSONRPCRequest(**data)
|
103
99
|
|
100
|
+
# Check if the request is authenticated
|
101
|
+
if refreshed_environment_variables and getattr(refreshed_environment_variables, "AGENT_API_KEY", None):
|
102
|
+
authorization_header = request.headers.get("x-agent-api-key")
|
103
|
+
if authorization_header != refreshed_environment_variables.AGENT_API_KEY:
|
104
|
+
return JSONRPCResponse(
|
105
|
+
id=rpc_request.id,
|
106
|
+
error=JSONRPCError(code=-32601, message="Unauthorized"),
|
107
|
+
)
|
108
|
+
|
109
|
+
|
104
110
|
# Check if method is valid first
|
105
111
|
try:
|
106
112
|
method = RPCMethod(rpc_request.method)
|
@@ -345,87 +351,4 @@ class BaseACPServer(FastAPI):
|
|
345
351
|
"""Start the Uvicorn server for async handlers."""
|
346
352
|
uvicorn.run(self, host=host, port=port, **kwargs)
|
347
353
|
|
348
|
-
|
349
|
-
if not env_vars.AUTH_PRINCIPAL_B64:
|
350
|
-
return None
|
351
|
-
|
352
|
-
try:
|
353
|
-
decoded_str = base64.b64decode(env_vars.AUTH_PRINCIPAL_B64).decode('utf-8')
|
354
|
-
return json.loads(decoded_str)
|
355
|
-
except Exception:
|
356
|
-
return None
|
357
|
-
|
358
|
-
async def _register_agent(self, env_vars: EnvironmentVariables):
|
359
|
-
"""Register this agent with the Agentex server"""
|
360
|
-
# Build the agent's own URL
|
361
|
-
full_acp_url = f"{env_vars.ACP_URL.rstrip('/')}:{env_vars.ACP_PORT}"
|
362
|
-
|
363
|
-
description = (
|
364
|
-
env_vars.AGENT_DESCRIPTION
|
365
|
-
or f"Generic description for agent: {env_vars.AGENT_NAME}"
|
366
|
-
)
|
367
|
-
|
368
|
-
# Prepare registration data
|
369
|
-
registration_data = {
|
370
|
-
"name": env_vars.AGENT_NAME,
|
371
|
-
"description": description,
|
372
|
-
"acp_url": full_acp_url,
|
373
|
-
"acp_type": env_vars.ACP_TYPE,
|
374
|
-
"principal_context": self._get_auth_principal(env_vars)
|
375
|
-
}
|
376
|
-
|
377
|
-
if env_vars.AGENT_ID:
|
378
|
-
registration_data["agent_id"] = env_vars.AGENT_ID
|
379
|
-
|
380
|
-
# Make the registration request
|
381
|
-
registration_url = f"{env_vars.AGENTEX_BASE_URL.rstrip('/')}/agents/register"
|
382
|
-
# Retry logic with configurable attempts and delay
|
383
|
-
max_retries = 3
|
384
|
-
base_delay = 5 # seconds
|
385
|
-
last_exception = None
|
386
|
-
|
387
|
-
attempt = 0
|
388
|
-
while attempt < max_retries:
|
389
|
-
try:
|
390
|
-
async with httpx.AsyncClient() as client:
|
391
|
-
response = await client.post(
|
392
|
-
registration_url, json=registration_data, timeout=30.0
|
393
|
-
)
|
394
|
-
if response.status_code == 200:
|
395
|
-
agent = response.json()
|
396
|
-
agent_id, agent_name = agent["id"], agent["name"]
|
397
|
-
|
398
|
-
os.environ["AGENT_ID"] = agent_id
|
399
|
-
os.environ["AGENT_NAME"] = agent_name
|
400
|
-
env_vars.AGENT_ID = agent_id
|
401
|
-
env_vars.AGENT_NAME = agent_name
|
402
|
-
global refreshed_environment_variables
|
403
|
-
refreshed_environment_variables = env_vars
|
404
|
-
logger.info(
|
405
|
-
f"Successfully registered agent '{env_vars.AGENT_NAME}' with Agentex server with acp_url: {full_acp_url}. Registration data: {registration_data}"
|
406
|
-
)
|
407
|
-
return # Success, exit the retry loop
|
408
|
-
else:
|
409
|
-
error_msg = f"Failed to register agent. Status: {response.status_code}, Response: {response.text}"
|
410
|
-
logger.error(error_msg)
|
411
|
-
last_exception = Exception(
|
412
|
-
f"Failed to startup agent: {response.text}"
|
413
|
-
)
|
414
|
-
|
415
|
-
except Exception as e:
|
416
|
-
logger.error(
|
417
|
-
f"Exception during agent registration attempt {attempt + 1}: {e}"
|
418
|
-
)
|
419
|
-
last_exception = e
|
420
|
-
attempt += 1
|
421
|
-
if attempt < max_retries:
|
422
|
-
delay = (attempt) * base_delay # 5, 10, 15 seconds
|
423
|
-
logger.info(
|
424
|
-
f"Retrying in {delay} seconds... (attempt {attempt}/{max_retries})"
|
425
|
-
)
|
426
|
-
await asyncio.sleep(delay)
|
427
|
-
|
428
|
-
# If we get here, all retries failed
|
429
|
-
raise last_exception or Exception(
|
430
|
-
f"Failed to register agent after {max_retries} attempts"
|
431
|
-
)
|
354
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
"""
|
2
|
+
Debug utilities for AgentEx development.
|
3
|
+
|
4
|
+
Provides debugging setup functionality that can be used across different components.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import os
|
8
|
+
import debugpy # type: ignore
|
9
|
+
|
10
|
+
|
11
|
+
def setup_debug_if_enabled() -> None:
|
12
|
+
"""
|
13
|
+
Setup debugpy if debug mode is enabled via environment variables.
|
14
|
+
|
15
|
+
This function checks for AgentEx debug environment variables and configures
|
16
|
+
debugpy accordingly. It's designed to be called early in worker startup.
|
17
|
+
|
18
|
+
Environment Variables:
|
19
|
+
AGENTEX_DEBUG_ENABLED: Set to "true" to enable debug mode
|
20
|
+
AGENTEX_DEBUG_PORT: Port for debug server (default: 5678)
|
21
|
+
AGENTEX_DEBUG_TYPE: Type identifier for logging (default: "worker")
|
22
|
+
AGENTEX_DEBUG_WAIT_FOR_ATTACH: Set to "true" to wait for debugger attachment
|
23
|
+
|
24
|
+
Raises:
|
25
|
+
Any exception from debugpy setup (will bubble up naturally)
|
26
|
+
"""
|
27
|
+
if os.getenv("AGENTEX_DEBUG_ENABLED") == "true":
|
28
|
+
debug_port = int(os.getenv("AGENTEX_DEBUG_PORT", "5678"))
|
29
|
+
debug_type = os.getenv("AGENTEX_DEBUG_TYPE", "worker")
|
30
|
+
wait_for_attach = os.getenv("AGENTEX_DEBUG_WAIT_FOR_ATTACH", "false").lower() == "true"
|
31
|
+
|
32
|
+
# Configure debugpy
|
33
|
+
debugpy.configure(subProcess=False)
|
34
|
+
debugpy.listen(debug_port)
|
35
|
+
|
36
|
+
print(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
|
37
|
+
|
38
|
+
if wait_for_attach:
|
39
|
+
print(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
|
40
|
+
debugpy.wait_for_client()
|
41
|
+
print(f"✅ [{debug_type.upper()}] Debugger attached!")
|
42
|
+
else:
|
43
|
+
print(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
|
44
|
+
|
45
|
+
|
46
|
+
def is_debug_enabled() -> bool:
|
47
|
+
"""
|
48
|
+
Check if debug mode is currently enabled.
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
bool: True if AGENTEX_DEBUG_ENABLED is set to "true"
|
52
|
+
"""
|
53
|
+
return os.getenv("AGENTEX_DEBUG_ENABLED", "false").lower() == "true"
|
54
|
+
|
55
|
+
|
56
|
+
def get_debug_port() -> int:
|
57
|
+
"""
|
58
|
+
Get the debug port from environment variables.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
int: Debug port (default: 5678)
|
62
|
+
"""
|
63
|
+
return int(os.getenv("AGENTEX_DEBUG_PORT", "5678"))
|
@@ -0,0 +1,101 @@
|
|
1
|
+
import base64
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
import httpx
|
5
|
+
import asyncio
|
6
|
+
|
7
|
+
from agentex.lib.environment_variables import EnvironmentVariables, refreshed_environment_variables
|
8
|
+
from agentex.lib.utils.logging import make_logger
|
9
|
+
|
10
|
+
logger = make_logger(__name__)
|
11
|
+
|
12
|
+
def get_auth_principal(env_vars: EnvironmentVariables):
|
13
|
+
if not env_vars.AUTH_PRINCIPAL_B64:
|
14
|
+
return None
|
15
|
+
|
16
|
+
try:
|
17
|
+
decoded_str = base64.b64decode(env_vars.AUTH_PRINCIPAL_B64).decode('utf-8')
|
18
|
+
return json.loads(decoded_str)
|
19
|
+
except Exception:
|
20
|
+
return None
|
21
|
+
|
22
|
+
async def register_agent(env_vars: EnvironmentVariables):
|
23
|
+
"""Register this agent with the Agentex server"""
|
24
|
+
if not env_vars.AGENTEX_BASE_URL:
|
25
|
+
logger.warning("AGENTEX_BASE_URL is not set, skipping registration")
|
26
|
+
return
|
27
|
+
# Build the agent's own URL
|
28
|
+
full_acp_url = f"{env_vars.ACP_URL.rstrip('/')}:{env_vars.ACP_PORT}"
|
29
|
+
|
30
|
+
description = (
|
31
|
+
env_vars.AGENT_DESCRIPTION
|
32
|
+
or f"Generic description for agent: {env_vars.AGENT_NAME}"
|
33
|
+
)
|
34
|
+
|
35
|
+
# Prepare registration data
|
36
|
+
registration_data = {
|
37
|
+
"name": env_vars.AGENT_NAME,
|
38
|
+
"description": description,
|
39
|
+
"acp_url": full_acp_url,
|
40
|
+
"acp_type": env_vars.ACP_TYPE,
|
41
|
+
"principal_context": get_auth_principal(env_vars)
|
42
|
+
}
|
43
|
+
|
44
|
+
if env_vars.AGENT_ID:
|
45
|
+
registration_data["agent_id"] = env_vars.AGENT_ID
|
46
|
+
|
47
|
+
# Make the registration request
|
48
|
+
registration_url = f"{env_vars.AGENTEX_BASE_URL.rstrip('/')}/agents/register"
|
49
|
+
# Retry logic with configurable attempts and delay
|
50
|
+
max_retries = 3
|
51
|
+
base_delay = 5 # seconds
|
52
|
+
last_exception = None
|
53
|
+
|
54
|
+
attempt = 0
|
55
|
+
while attempt < max_retries:
|
56
|
+
try:
|
57
|
+
async with httpx.AsyncClient() as client:
|
58
|
+
response = await client.post(
|
59
|
+
registration_url, json=registration_data, timeout=30.0
|
60
|
+
)
|
61
|
+
if response.status_code == 200:
|
62
|
+
agent = response.json()
|
63
|
+
agent_id, agent_name = agent["id"], agent["name"]
|
64
|
+
agent_api_key = agent["agent_api_key"]
|
65
|
+
|
66
|
+
os.environ["AGENT_ID"] = agent_id
|
67
|
+
os.environ["AGENT_NAME"] = agent_name
|
68
|
+
os.environ["AGENT_API_KEY"] = agent_api_key
|
69
|
+
env_vars.AGENT_ID = agent_id
|
70
|
+
env_vars.AGENT_NAME = agent_name
|
71
|
+
env_vars.AGENT_API_KEY = agent_api_key
|
72
|
+
global refreshed_environment_variables
|
73
|
+
refreshed_environment_variables = env_vars
|
74
|
+
logger.info(
|
75
|
+
f"Successfully registered agent '{env_vars.AGENT_NAME}' with Agentex server with acp_url: {full_acp_url}. Registration data: {registration_data}"
|
76
|
+
)
|
77
|
+
return # Success, exit the retry loop
|
78
|
+
else:
|
79
|
+
error_msg = f"Failed to register agent. Status: {response.status_code}, Response: {response.text}"
|
80
|
+
logger.error(error_msg)
|
81
|
+
last_exception = Exception(
|
82
|
+
f"Failed to startup agent: {response.text}"
|
83
|
+
)
|
84
|
+
|
85
|
+
except Exception as e:
|
86
|
+
logger.error(
|
87
|
+
f"Exception during agent registration attempt {attempt + 1}: {e}"
|
88
|
+
)
|
89
|
+
last_exception = e
|
90
|
+
attempt += 1
|
91
|
+
if attempt < max_retries:
|
92
|
+
delay = (attempt) * base_delay # 5, 10, 15 seconds
|
93
|
+
logger.info(
|
94
|
+
f"Retrying in {delay} seconds... (attempt {attempt}/{max_retries})"
|
95
|
+
)
|
96
|
+
await asyncio.sleep(delay)
|
97
|
+
|
98
|
+
# If we get here, all retries failed
|
99
|
+
raise last_exception or Exception(
|
100
|
+
f"Failed to register agent after {max_retries} attempts"
|
101
|
+
)
|
agentex/types/agent.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
2
2
|
|
3
3
|
from typing import Optional
|
4
|
+
from datetime import datetime
|
4
5
|
from typing_extensions import Literal
|
5
6
|
|
6
7
|
from .._models import BaseModel
|
@@ -16,12 +17,18 @@ class Agent(BaseModel):
|
|
16
17
|
acp_type: AcpType
|
17
18
|
"""The type of the ACP Server (Either sync or agentic)"""
|
18
19
|
|
20
|
+
created_at: datetime
|
21
|
+
"""The timestamp when the agent was created"""
|
22
|
+
|
19
23
|
description: str
|
20
24
|
"""The description of the action."""
|
21
25
|
|
22
26
|
name: str
|
23
27
|
"""The unique name of the agent."""
|
24
28
|
|
29
|
+
updated_at: datetime
|
30
|
+
"""The timestamp when the agent was last updated"""
|
31
|
+
|
25
32
|
status: Optional[Literal["Pending", "Building", "Ready", "Failed", "Unknown"]] = None
|
26
33
|
"""The status of the action, indicating if it's building, ready, failed, etc."""
|
27
34
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: agentex-sdk
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.7
|
4
4
|
Summary: The official Python library for the agentex API
|
5
5
|
Project-URL: Homepage, https://github.com/scaleapi/agentex-python
|
6
6
|
Project-URL: Repository, https://github.com/scaleapi/agentex-python
|
@@ -126,6 +126,37 @@ asyncio.run(main())
|
|
126
126
|
|
127
127
|
Functionality between the synchronous and asynchronous clients is otherwise identical.
|
128
128
|
|
129
|
+
## Debugging
|
130
|
+
|
131
|
+
AgentEx provides built-in debugging support for **temporal projects** during local development.
|
132
|
+
|
133
|
+
```bash
|
134
|
+
# Basic debugging
|
135
|
+
uv run agentex agents run --manifest manifest.yaml --debug-worker
|
136
|
+
|
137
|
+
# Wait for debugger to attach before starting
|
138
|
+
uv run agentex agents run --manifest manifest.yaml --debug-worker --wait-for-debugger
|
139
|
+
|
140
|
+
# Custom debug port
|
141
|
+
uv run agentex agents run --manifest manifest.yaml --debug-worker --debug-port 5679
|
142
|
+
```
|
143
|
+
|
144
|
+
For **VS Code**, add this configuration to `.vscode/launch.json`:
|
145
|
+
|
146
|
+
```json
|
147
|
+
{
|
148
|
+
"name": "Attach to AgentEx Worker",
|
149
|
+
"type": "debugpy",
|
150
|
+
"request": "attach",
|
151
|
+
"connect": { "host": "localhost", "port": 5678 },
|
152
|
+
"pathMappings": [{ "localRoot": "${workspaceFolder}", "remoteRoot": "." }],
|
153
|
+
"justMyCode": false,
|
154
|
+
"console": "integratedTerminal"
|
155
|
+
}
|
156
|
+
```
|
157
|
+
|
158
|
+
The debug server automatically finds an available port starting from 5678 and prints connection details when starting.
|
159
|
+
|
129
160
|
### With aiohttp
|
130
161
|
|
131
162
|
By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
|
@@ -11,7 +11,7 @@ agentex/_resource.py,sha256=S1t7wmR5WUvoDIhZjo_x-E7uoTJBynJ3d8tPJMQYdjw,1106
|
|
11
11
|
agentex/_response.py,sha256=Tb9zazsnemO2rTxWtBjAD5WBqlhli5ZaXGbiKgdu5DE,28794
|
12
12
|
agentex/_streaming.py,sha256=FNGJExRCF-vTRUZHFKUfoAWFhDGOB3XbioVCF37Jr7E,10104
|
13
13
|
agentex/_types.py,sha256=KyKYySGIfHPod2hho1fPxssk5NuVn8C4MeMTtA-lg80,6198
|
14
|
-
agentex/_version.py,sha256=
|
14
|
+
agentex/_version.py,sha256=juL3-lsGG8DrsKnzc0QzewhZCTZuJXw8vQoNFh7Of6g,159
|
15
15
|
agentex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
agentex/_utils/__init__.py,sha256=PNZ_QJuzZEgyYXqkO1HVhGkj5IU9bglVUcw7H-Knjzw,2062
|
17
17
|
agentex/_utils/_logs.py,sha256=LUjFPc3fweSChBUmjhQD8uYmwQAmFMNDuVFKfjYBQfM,777
|
@@ -25,7 +25,7 @@ agentex/_utils/_typing.py,sha256=D0DbbNu8GnYQTSICnTSHDGsYXj8TcAKyhejb0XcnjtY,460
|
|
25
25
|
agentex/_utils/_utils.py,sha256=ts4CiiuNpFiGB6YMdkQRh2SZvYvsl7mAF-JWHCcLDf4,12312
|
26
26
|
agentex/lib/.keep,sha256=wuNrz-5SXo3jJaJOJgz4vFHM41YH_g20F5cRQo0vLes,224
|
27
27
|
agentex/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
-
agentex/lib/environment_variables.py,sha256=
|
28
|
+
agentex/lib/environment_variables.py,sha256=cCL7_cKDNuPyUTmuNLZVTDdFnJPmCsDZ5uN23MtZP-k,3248
|
29
29
|
agentex/lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
agentex/lib/adk/__init__.py,sha256=-PpVfEvYr_HD7TnxUWU8RCW2OnxfwpPxTW97dKTnqvI,1082
|
31
31
|
agentex/lib/adk/_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -45,21 +45,24 @@ agentex/lib/adk/providers/_modules/openai.py,sha256=QyjujK4JHiATB4xI9CiR67agcRhA
|
|
45
45
|
agentex/lib/adk/providers/_modules/sgp.py,sha256=QszUPyeGBODfI5maYvlzErD87PsMsX6vrfC7n65WNjE,3224
|
46
46
|
agentex/lib/adk/utils/__init__.py,sha256=7f6ayV0_fqyw5cwzVANNcZWGJZ-vrrYtZ0qi7KKBRFs,130
|
47
47
|
agentex/lib/adk/utils/_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
48
|
-
agentex/lib/adk/utils/_modules/client.py,sha256=
|
48
|
+
agentex/lib/adk/utils/_modules/client.py,sha256=zMBYsPr2zXpSynF2W_5SKOpALtXvS0cTNdcJX93ce1I,974
|
49
49
|
agentex/lib/adk/utils/_modules/templating.py,sha256=wgjkE4uC1gsArK-exyxOOZwp5Yu7ePqviZuyTDlP9m0,3595
|
50
50
|
agentex/lib/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
51
51
|
agentex/lib/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
52
|
-
agentex/lib/cli/commands/agents.py,sha256=
|
52
|
+
agentex/lib/cli/commands/agents.py,sha256=ThpiifTcORxe2kHCfw0Cxm7_i--gHHtO8ZsqCSi2UaY,12957
|
53
53
|
agentex/lib/cli/commands/init.py,sha256=JsfusiLTgPu5IAI0MVDR15qA6wx5R2ZowjUJ728GJyQ,8146
|
54
54
|
agentex/lib/cli/commands/main.py,sha256=aDn9xJIIQQD33v3caET_NX-8eBxoWC3QfZGMUgjeGN8,1093
|
55
55
|
agentex/lib/cli/commands/secrets.py,sha256=cVtsqyGGieBVM4dKkbJROmzR_NJRODFngcEbi1Nc92A,5604
|
56
56
|
agentex/lib/cli/commands/tasks.py,sha256=9ARR0VgM2ZZXSFDlMiA_E9RDL2V7Piipp8Fna_OBrKQ,3652
|
57
57
|
agentex/lib/cli/commands/uv.py,sha256=n6nk2F2gPUXrvWOljSN06Y5bOEnhaZH4rulproAJktA,3553
|
58
|
+
agentex/lib/cli/debug/__init__.py,sha256=dt_NjaWesD2M5BqtTKswWc23PGA_dC0uR2m61JP_xIc,378
|
59
|
+
agentex/lib/cli/debug/debug_config.py,sha256=Gl0rI1WUPwhehyDC0EdLo7S8q9hlBy41ZIu3NBUm6QQ,3415
|
60
|
+
agentex/lib/cli/debug/debug_handlers.py,sha256=i2Og0v5MPKIxG0uMZIp4NpmCpAro23t7PLCU4d7EKag,5684
|
58
61
|
agentex/lib/cli/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
|
-
agentex/lib/cli/handlers/agent_handlers.py,sha256=
|
62
|
+
agentex/lib/cli/handlers/agent_handlers.py,sha256=iVZ-4TSQJuq7XpPBYjYIN76M33XwxDjQTuNwTzzynec,5573
|
60
63
|
agentex/lib/cli/handlers/cleanup_handlers.py,sha256=V1V0zeErOUGTgCQqjyUl6CWtzGjFW878uzFaLOQJEyQ,7073
|
61
|
-
agentex/lib/cli/handlers/deploy_handlers.py,sha256=
|
62
|
-
agentex/lib/cli/handlers/run_handlers.py,sha256=
|
64
|
+
agentex/lib/cli/handlers/deploy_handlers.py,sha256=pwdc-m5-auXzlDA-0-TzAPpIGxsYecPKXryrAIpELTM,14832
|
65
|
+
agentex/lib/cli/handlers/run_handlers.py,sha256=b02-ng64fMHdd7u2hB_tmwHrm2_0DL-pcA565JDpyPc,14949
|
63
66
|
agentex/lib/cli/handlers/secret_handlers.py,sha256=VfAdAQovW9tG36Xgk_gGIGwTyFMxR3P6xc7fmAviNA8,24719
|
64
67
|
agentex/lib/cli/templates/default/.dockerignore.j2,sha256=hweGFxw5eDZYsb5EnRHpv27o9M1HF2PEWOxqsfBBcAE,320
|
65
68
|
agentex/lib/cli/templates/default/Dockerfile-uv.j2,sha256=tGJo_C4vwHYikV4QhGFtSiG6K7Nt4UDdJ71Gob_uTho,1109
|
@@ -67,7 +70,7 @@ agentex/lib/cli/templates/default/Dockerfile.j2,sha256=T7ouO3glVBo7U2I1TPQvgARyx
|
|
67
70
|
agentex/lib/cli/templates/default/README.md.j2,sha256=4Sn_cY_TMfN_c5h-I_L3TgTrNKUvhzQvKGDZjS3n2Gw,6361
|
68
71
|
agentex/lib/cli/templates/default/dev.ipynb.j2,sha256=8xY82gVfQ0mhzlEZzI4kLqIXCF19YgimLnpEirDMX8I,3395
|
69
72
|
agentex/lib/cli/templates/default/manifest.yaml.j2,sha256=n-XK6LqSyBVY6a7KOfIlOQx4LbMNEVzzHIh6yEiqAhs,3752
|
70
|
-
agentex/lib/cli/templates/default/pyproject.toml.j2,sha256=
|
73
|
+
agentex/lib/cli/templates/default/pyproject.toml.j2,sha256=eyN6dYqJTFzb5WztJMxboy9Wc0XPXVnKYaF5JBxJE7o,507
|
71
74
|
agentex/lib/cli/templates/default/requirements.txt.j2,sha256=iTmO-z8qFkUa1jTctFCs0WYuq7Sqi6VNQAwATakh2fQ,94
|
72
75
|
agentex/lib/cli/templates/default/deploy/example.yaml.j2,sha256=sHIEuhtruyCfGPgeLQ1ilCCnRH0HpsqhDdQT44UWUaU,1554
|
73
76
|
agentex/lib/cli/templates/default/project/acp.py.j2,sha256=XZsHNQaQDNvooarFt_NvM8rLQ-rpc_knKkNTPnRxtM4,1136
|
@@ -79,7 +82,7 @@ agentex/lib/cli/templates/sync/Dockerfile.j2,sha256=T7ouO3glVBo7U2I1TPQvgARyxXGL
|
|
79
82
|
agentex/lib/cli/templates/sync/README.md.j2,sha256=_S7Ngl4qOUQHPFldLXDBvuIWPFU2-WcuxGmr5EXLX6k,8816
|
80
83
|
agentex/lib/cli/templates/sync/dev.ipynb.j2,sha256=Z42iRveuI_k5LcJqWX-3H1glPtNTkxg_MKVe1lwuJos,6055
|
81
84
|
agentex/lib/cli/templates/sync/manifest.yaml.j2,sha256=V497KXzvA76sHrgIJ5zRJptpIH8sGbSXZaIsEyp5NZ4,3747
|
82
|
-
agentex/lib/cli/templates/sync/pyproject.toml.j2,sha256=
|
85
|
+
agentex/lib/cli/templates/sync/pyproject.toml.j2,sha256=eyN6dYqJTFzb5WztJMxboy9Wc0XPXVnKYaF5JBxJE7o,507
|
83
86
|
agentex/lib/cli/templates/sync/requirements.txt.j2,sha256=iTmO-z8qFkUa1jTctFCs0WYuq7Sqi6VNQAwATakh2fQ,94
|
84
87
|
agentex/lib/cli/templates/sync/deploy/example.yaml.j2,sha256=sHIEuhtruyCfGPgeLQ1ilCCnRH0HpsqhDdQT44UWUaU,1554
|
85
88
|
agentex/lib/cli/templates/sync/project/acp.py.j2,sha256=X5RaE9iR4Dp-kPJL0r1QAe6ohfiOTcYizwtwGW2GzHg,1003
|
@@ -89,11 +92,11 @@ agentex/lib/cli/templates/temporal/Dockerfile.j2,sha256=pcszlprNTqKMpYEtA4XYlc3v
|
|
89
92
|
agentex/lib/cli/templates/temporal/README.md.j2,sha256=d6BQAZBf7lCKROXnpDu-Ml1Rq0OM8cCFEOpmStoPWfc,10132
|
90
93
|
agentex/lib/cli/templates/temporal/dev.ipynb.j2,sha256=8xY82gVfQ0mhzlEZzI4kLqIXCF19YgimLnpEirDMX8I,3395
|
91
94
|
agentex/lib/cli/templates/temporal/manifest.yaml.j2,sha256=S-hJlpVCnT62r66otqHa3iROOn1w_yYvehOOxvLQotY,4483
|
92
|
-
agentex/lib/cli/templates/temporal/pyproject.toml.j2,sha256=
|
95
|
+
agentex/lib/cli/templates/temporal/pyproject.toml.j2,sha256=MoR1g6KnGOQrXWOXhFKMw561kgpxy0tdom0KLtQe8A8,548
|
93
96
|
agentex/lib/cli/templates/temporal/requirements.txt.j2,sha256=iTmO-z8qFkUa1jTctFCs0WYuq7Sqi6VNQAwATakh2fQ,94
|
94
97
|
agentex/lib/cli/templates/temporal/deploy/example.yaml.j2,sha256=sHIEuhtruyCfGPgeLQ1ilCCnRH0HpsqhDdQT44UWUaU,1554
|
95
|
-
agentex/lib/cli/templates/temporal/project/acp.py.j2,sha256=
|
96
|
-
agentex/lib/cli/templates/temporal/project/run_worker.py.j2,sha256=
|
98
|
+
agentex/lib/cli/templates/temporal/project/acp.py.j2,sha256=Ha5oBaGT1WC93TEBfWMM7OtbmAYOF2t3PjY6uOL6mJE,2386
|
99
|
+
agentex/lib/cli/templates/temporal/project/run_worker.py.j2,sha256=kgEbi-NNKDEOcW7lWP1rfQhFHpqjLtUi0Bc7AjO9jQo,979
|
97
100
|
agentex/lib/cli/templates/temporal/project/workflow.py.j2,sha256=VPnHnzr09i5y68vCOIJ8wTrc8KVHoDp5WooQew0GiWg,3210
|
98
101
|
agentex/lib/cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
99
102
|
agentex/lib/cli/utils/auth_utils.py,sha256=Y8pCqvQxhYtyQOzbpFZ_PUIp6vo8XGDOPdyoRI1_KG8,489
|
@@ -127,7 +130,7 @@ agentex/lib/core/services/adk/streaming.py,sha256=zIXxMaoL5iTTC8CvmNoG4lRQO5JHyW
|
|
127
130
|
agentex/lib/core/services/adk/tasks.py,sha256=XEX0u4skq81Fn-gjTzSE_-Iv_mKySZHchpotxAsnJwg,2618
|
128
131
|
agentex/lib/core/services/adk/tracing.py,sha256=w4mnIoq5m5iwlkDN_NOUjhi6hUpD958cYn1QR6hFgB8,1156
|
129
132
|
agentex/lib/core/services/adk/acp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
130
|
-
agentex/lib/core/services/adk/acp/acp.py,sha256=
|
133
|
+
agentex/lib/core/services/adk/acp/acp.py,sha256=Ei6r5CcM1RA7DqfTRpAWCmP7Buw97b3ajQuE4DsdSaQ,7559
|
131
134
|
agentex/lib/core/services/adk/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
132
135
|
agentex/lib/core/services/adk/providers/litellm.py,sha256=7RIVqQ5XaCP2cEL1pr4nl5jfG_0FDMvDTZVKu1iaN3M,9864
|
133
136
|
agentex/lib/core/services/adk/providers/openai.py,sha256=Qply4Q7BJqRyukAuNPnFcLXf0eQWACaa5LamGc6xpTY,31559
|
@@ -159,7 +162,7 @@ agentex/lib/core/temporal/services/temporal_task_service.py,sha256=kXUOwcg1Suc0k
|
|
159
162
|
agentex/lib/core/temporal/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
160
163
|
agentex/lib/core/temporal/types/workflow.py,sha256=o8lBUloI44NTYFfbA1BLgzUneyN7aLbt042Eq_9OKo8,89
|
161
164
|
agentex/lib/core/temporal/workers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
162
|
-
agentex/lib/core/temporal/workers/worker.py,sha256=
|
165
|
+
agentex/lib/core/temporal/workers/worker.py,sha256=kmdfs67UWjzxU9ZOE7vq_q4S4jj7jB5ZMyJkZYptrAY,6670
|
163
166
|
agentex/lib/core/temporal/workflows/workflow.py,sha256=VTS4nqwdJqqjIy6nTyvFLdAoBHnunO8-8rVY0Gx5_zo,723
|
164
167
|
agentex/lib/core/tracing/__init__.py,sha256=3dLjXGTwAJxi_xxwdh8Mt04pdLyzN9VxAl8XHmV70Ak,229
|
165
168
|
agentex/lib/core/tracing/trace.py,sha256=45Nn0Z97kC_9XNyb9N8IWUFo0OIdb7dDZShhgOTGJB0,8952
|
@@ -178,7 +181,7 @@ agentex/lib/sdk/config/local_development_config.py,sha256=b1AZsOVo1RoHKbk8Nm5nC8
|
|
178
181
|
agentex/lib/sdk/config/project_config.py,sha256=CGH_r9KbnSFMj2CnBkZnfg41L2o0TeVNz6MwBDKPT_U,3642
|
179
182
|
agentex/lib/sdk/fastacp/__init__.py,sha256=UvAdexdnfb4z0F4a2sfXROFyh9EjH89kf3AxHPybzCM,75
|
180
183
|
agentex/lib/sdk/fastacp/fastacp.py,sha256=K4D7a9EiJfCgWp2hrE_TbpZBaF4Uc46MfndZK3F9mA0,3061
|
181
|
-
agentex/lib/sdk/fastacp/base/base_acp_server.py,sha256=
|
184
|
+
agentex/lib/sdk/fastacp/base/base_acp_server.py,sha256=fkEVg5M4Ni2uPt_oiCP7_jfTmRvcC0o2VTg0Oka7mXA,14590
|
182
185
|
agentex/lib/sdk/fastacp/impl/agentic_base_acp.py,sha256=LWLAlHrs-2Lc2UICBAEFL8c3JwTA6oxPnzUzW0qQWSA,2694
|
183
186
|
agentex/lib/sdk/fastacp/impl/sync_acp.py,sha256=8FEDfBxI31NoVLX9nyckQ8QwA0UV4svC3fhGKgXBIwk,3862
|
184
187
|
agentex/lib/sdk/fastacp/impl/temporal_acp.py,sha256=ZLqjzBBVrXJCXD2bFlrcDkFvpsXZp3thC2rTwZ6xNaY,3737
|
@@ -211,6 +214,7 @@ agentex/lib/types/tracing.py,sha256=0YBdy3aKvxIcpOW0podEAqsFl3yEKW4PswNf-QnMNqo,
|
|
211
214
|
agentex/lib/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
212
215
|
agentex/lib/utils/completions.py,sha256=m9TMwl9-nYK4DOQ8bNyj5YCFrxK3yN3zKvXmdINcIbo,4158
|
213
216
|
agentex/lib/utils/console.py,sha256=HVP1NSF4idx40hlGB3ifuofy3rsc83WF_1yNpHYM99M,417
|
217
|
+
agentex/lib/utils/debug.py,sha256=1o2NjG8bZXTi63KTGjL3EmU_zMGapco7v5xoDuZRjU8,2148
|
214
218
|
agentex/lib/utils/io.py,sha256=17p7dfUZ1YxTAc-n_g7eFOjzInoKi7Uedyad967EKYQ,754
|
215
219
|
agentex/lib/utils/iterables.py,sha256=cD49hj98mtY0QPaS0ZA2kguNeGzRU4UfbZfwyASWdzY,319
|
216
220
|
agentex/lib/utils/json_schema.py,sha256=nSHbi6LC-oWXHP6sMLCBychA7B0R2DItRIJNCCEzRsY,741
|
@@ -219,6 +223,7 @@ agentex/lib/utils/mcp.py,sha256=lYQPwKAOH6Gf2I_TeovhEG9YUijUPcN0rENNdT0Vk6c,505
|
|
219
223
|
agentex/lib/utils/model_utils.py,sha256=_zPUIoSl-A7LsIuH-8I6aJBmbgjARbl7puMPh9lx5QU,1562
|
220
224
|
agentex/lib/utils/parsing.py,sha256=2T-B4nJSupo2RLf9AkpV6VQHqDnF97ZBgO6zvGCauCo,369
|
221
225
|
agentex/lib/utils/regex.py,sha256=Y3VcehCznAqa59D4WTwK_ki722oudHBlFqBk0I930zo,212
|
226
|
+
agentex/lib/utils/registration.py,sha256=FAL40KSMRCltHZcDtioGeRNgfB19Twqu6Srp4x7UMSU,3781
|
222
227
|
agentex/lib/utils/temporal.py,sha256=sXo8OPMMXiyrF7OSBCJBuN_ufyQOD2bLOXgDbVZoyds,292
|
223
228
|
agentex/lib/utils/dev_tools/__init__.py,sha256=oaHxw6ymfhNql-kzXHv3NWVHuqD4fHumasNXJG7kHTU,261
|
224
229
|
agentex/lib/utils/dev_tools/async_messages.py,sha256=-alUK1KFltcRb6xtRtIJIRJW9Sf1FwDRgaNPhOn-luw,18105
|
@@ -234,7 +239,7 @@ agentex/resources/messages/batch.py,sha256=pegCmnjK_J0jek5ChX1pKpq5RmCucTYLbK69H
|
|
234
239
|
agentex/resources/messages/messages.py,sha256=fuFmmGNOjRJVzmYHcfP2trg0yii0n9MPPCpt7F8fDs4,17930
|
235
240
|
agentex/types/__init__.py,sha256=v-2hxFsIvOZ_2mZy-5RqILX0VJWG4sN9MRvXAbThqYI,3514
|
236
241
|
agentex/types/acp_type.py,sha256=Fj-4SzmM6m95ck_ZXtNbcWggHiD9F49bxBLPbl1fxe4,208
|
237
|
-
agentex/types/agent.py,sha256=
|
242
|
+
agentex/types/agent.py,sha256=t6CUsKSaK6Gs_X9g0YxSi5G3Hh21FrGVGnAD6MytVBk,981
|
238
243
|
agentex/types/agent_list_params.py,sha256=81IWnRZ2rLfHH7GB6VkXShYjb44DO0guG1znJcV3tuI,316
|
239
244
|
agentex/types/agent_list_response.py,sha256=g0b9Cw7j2yk14veyJORpF3me8iW7g7pr2USpXGokoFI,254
|
240
245
|
agentex/types/agent_rpc_by_name_params.py,sha256=G6xkjrZKPmJvhwqgc68tAnzmb4wYh9k0zlcm9CsLQR0,2024
|
@@ -291,8 +296,8 @@ agentex/types/messages/batch_update_params.py,sha256=Ug5CThbD49a8j4qucg04OdmVrp_
|
|
291
296
|
agentex/types/messages/batch_update_response.py,sha256=TbSBe6SuPzjXXWSj-nRjT1JHGBooTshHQQDa1AixQA8,278
|
292
297
|
agentex/types/shared/__init__.py,sha256=IKs-Qn5Yja0kFh1G1kDqYZo43qrOu1hSoxlPdN-85dI,149
|
293
298
|
agentex/types/shared/delete_response.py,sha256=8qH3zvQXaOHYQSHyXi7UQxdR4miTzR7V9K4zXVsiUyk,215
|
294
|
-
agentex_sdk-0.2.
|
295
|
-
agentex_sdk-0.2.
|
296
|
-
agentex_sdk-0.2.
|
297
|
-
agentex_sdk-0.2.
|
298
|
-
agentex_sdk-0.2.
|
299
|
+
agentex_sdk-0.2.7.dist-info/METADATA,sha256=jDeAOkWMQtFYbgfRbFGwSITJDei-oGZIBYeDksRdq4o,15037
|
300
|
+
agentex_sdk-0.2.7.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
301
|
+
agentex_sdk-0.2.7.dist-info/entry_points.txt,sha256=V7vJuMZdF0UlvgX6KiBN7XUvq_cxF5kplcYvc1QlFaQ,62
|
302
|
+
agentex_sdk-0.2.7.dist-info/licenses/LICENSE,sha256=Q1AOx2FtRcMlyMgQJ9eVN2WKPq2mQ33lnB4tvWxabLA,11337
|
303
|
+
agentex_sdk-0.2.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|