agentex-sdk 0.4.19__py3-none-any.whl → 0.4.21__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/__init__.py +0 -1
- agentex/_utils/_typing.py +3 -1
- agentex/_version.py +1 -1
- agentex/lib/adk/__init__.py +3 -0
- agentex/lib/adk/_modules/acp.py +3 -1
- agentex/lib/adk/_modules/agent_task_tracker.py +3 -1
- agentex/lib/adk/_modules/agents.py +3 -1
- agentex/lib/adk/_modules/events.py +3 -1
- agentex/lib/adk/_modules/messages.py +3 -1
- agentex/lib/adk/_modules/state.py +3 -1
- agentex/lib/adk/_modules/streaming.py +3 -1
- agentex/lib/adk/_modules/tasks.py +4 -2
- agentex/lib/adk/_modules/tracing.py +3 -1
- agentex/lib/adk/providers/__init__.py +2 -2
- agentex/lib/adk/providers/_modules/litellm.py +10 -11
- agentex/lib/adk/providers/_modules/openai.py +27 -28
- agentex/lib/adk/providers/_modules/sgp.py +5 -6
- agentex/lib/adk/utils/_modules/client.py +4 -1
- agentex/lib/adk/utils/_modules/templating.py +5 -6
- agentex/lib/cli/commands/agents.py +21 -21
- agentex/lib/cli/commands/init.py +3 -3
- agentex/lib/cli/commands/main.py +3 -3
- agentex/lib/cli/commands/secrets.py +10 -10
- agentex/lib/cli/commands/tasks.py +26 -28
- agentex/lib/cli/commands/uv.py +1 -1
- agentex/lib/cli/debug/__init__.py +1 -1
- agentex/lib/cli/debug/debug_config.py +1 -2
- agentex/lib/cli/debug/debug_handlers.py +6 -4
- agentex/lib/cli/handlers/agent_handlers.py +15 -16
- agentex/lib/cli/handlers/cleanup_handlers.py +1 -1
- agentex/lib/cli/handlers/deploy_handlers.py +20 -39
- agentex/lib/cli/handlers/run_handlers.py +13 -16
- agentex/lib/cli/handlers/secret_handlers.py +25 -25
- agentex/lib/cli/templates/temporal/project/acp.py.j2 +11 -8
- agentex/lib/cli/utils/auth_utils.py +3 -2
- agentex/lib/cli/utils/credential_utils.py +1 -1
- agentex/lib/cli/utils/kubectl_utils.py +3 -3
- agentex/lib/cli/utils/kubernetes_secrets_utils.py +4 -4
- agentex/lib/cli/utils/path_utils.py +2 -2
- agentex/lib/core/adapters/llm/adapter_litellm.py +9 -4
- agentex/lib/core/adapters/llm/adapter_sgp.py +10 -7
- agentex/lib/core/adapters/llm/port.py +1 -1
- agentex/lib/core/adapters/streams/adapter_redis.py +7 -4
- agentex/lib/core/adapters/streams/port.py +1 -1
- agentex/lib/core/clients/temporal/temporal_client.py +34 -34
- agentex/lib/core/clients/temporal/types.py +1 -1
- agentex/lib/core/clients/temporal/utils.py +27 -25
- agentex/lib/core/services/adk/acp/acp.py +6 -6
- agentex/lib/core/services/adk/agent_task_tracker.py +1 -1
- agentex/lib/core/services/adk/agents.py +1 -1
- agentex/lib/core/services/adk/events.py +1 -1
- agentex/lib/core/services/adk/messages.py +5 -6
- agentex/lib/core/services/adk/providers/litellm.py +10 -10
- agentex/lib/core/services/adk/providers/openai.py +75 -43
- agentex/lib/core/services/adk/providers/sgp.py +3 -3
- agentex/lib/core/services/adk/state.py +5 -1
- agentex/lib/core/services/adk/streaming.py +19 -19
- agentex/lib/core/services/adk/tasks.py +8 -2
- agentex/lib/core/services/adk/tracing.py +3 -2
- agentex/lib/core/services/adk/utils/templating.py +4 -2
- agentex/lib/core/temporal/activities/__init__.py +27 -27
- agentex/lib/core/temporal/activities/activity_helpers.py +1 -1
- agentex/lib/core/temporal/activities/adk/acp/acp_activities.py +4 -4
- agentex/lib/core/temporal/activities/adk/agent_task_tracker_activities.py +1 -1
- agentex/lib/core/temporal/activities/adk/agents_activities.py +2 -2
- agentex/lib/core/temporal/activities/adk/events_activities.py +1 -1
- agentex/lib/core/temporal/activities/adk/messages_activities.py +3 -3
- agentex/lib/core/temporal/activities/adk/providers/litellm_activities.py +4 -4
- agentex/lib/core/temporal/activities/adk/providers/sgp_activities.py +1 -1
- agentex/lib/core/temporal/activities/adk/state_activities.py +1 -1
- agentex/lib/core/temporal/activities/adk/streaming_activities.py +3 -3
- agentex/lib/core/temporal/activities/adk/tasks_activities.py +2 -2
- agentex/lib/core/temporal/activities/adk/tracing_activities.py +1 -1
- agentex/lib/core/temporal/activities/adk/utils/templating_activities.py +1 -1
- agentex/lib/core/temporal/services/temporal_task_service.py +7 -7
- agentex/lib/core/temporal/workers/worker.py +31 -40
- agentex/lib/core/temporal/workflows/workflow.py +2 -2
- agentex/lib/core/tracing/__init__.py +2 -2
- agentex/lib/core/tracing/processors/agentex_tracing_processor.py +6 -6
- agentex/lib/core/tracing/processors/sgp_tracing_processor.py +16 -16
- agentex/lib/core/tracing/processors/tracing_processor_interface.py +1 -1
- agentex/lib/core/tracing/trace.py +7 -7
- agentex/lib/core/tracing/tracer.py +2 -2
- agentex/lib/core/tracing/tracing_processor_manager.py +43 -13
- agentex/lib/environment_variables.py +4 -4
- agentex/lib/sdk/config/agent_config.py +2 -2
- agentex/lib/sdk/config/agent_manifest.py +8 -8
- agentex/lib/sdk/config/project_config.py +6 -6
- agentex/lib/sdk/config/validation.py +2 -2
- agentex/lib/sdk/fastacp/base/base_acp_server.py +16 -16
- agentex/lib/sdk/fastacp/fastacp.py +14 -15
- agentex/lib/sdk/fastacp/impl/agentic_base_acp.py +4 -5
- agentex/lib/sdk/fastacp/impl/sync_acp.py +7 -7
- agentex/lib/sdk/fastacp/impl/temporal_acp.py +28 -19
- agentex/lib/sdk/fastacp/tests/conftest.py +18 -16
- agentex/lib/sdk/fastacp/tests/run_tests.py +1 -1
- agentex/lib/sdk/fastacp/tests/test_base_acp_server.py +4 -4
- agentex/lib/sdk/fastacp/tests/test_fastacp_factory.py +8 -8
- agentex/lib/sdk/fastacp/tests/test_integration.py +15 -14
- agentex/lib/sdk/state_machine/__init__.py +1 -1
- agentex/lib/sdk/state_machine/noop_workflow.py +5 -3
- agentex/lib/sdk/state_machine/state_machine.py +18 -12
- agentex/lib/sdk/utils/messages.py +5 -5
- agentex/lib/types/acp.py +2 -2
- agentex/lib/types/agent_configs.py +1 -1
- agentex/lib/types/converters.py +4 -2
- agentex/lib/types/credentials.py +1 -1
- agentex/lib/types/fastacp.py +4 -5
- agentex/lib/types/tracing.py +1 -1
- agentex/lib/utils/completions.py +5 -5
- agentex/lib/utils/console.py +1 -1
- agentex/lib/utils/debug.py +10 -5
- agentex/lib/utils/dev_tools/async_messages.py +11 -12
- agentex/lib/utils/iterables.py +1 -1
- agentex/lib/utils/json_schema.py +4 -4
- agentex/lib/utils/logging.py +7 -7
- agentex/lib/utils/mcp.py +1 -0
- agentex/lib/utils/model_utils.py +4 -5
- agentex/lib/utils/registration.py +5 -4
- agentex/resources/agents.py +11 -4
- agentex/types/agent_rpc_response.py +3 -3
- agentex/types/data_content.py +1 -1
- agentex/types/tool_request_content.py +1 -1
- agentex/types/tool_response_content.py +0 -1
- {agentex_sdk-0.4.19.dist-info → agentex_sdk-0.4.21.dist-info}/METADATA +1 -1
- {agentex_sdk-0.4.19.dist-info → agentex_sdk-0.4.21.dist-info}/RECORD +129 -129
- {agentex_sdk-0.4.19.dist-info → agentex_sdk-0.4.21.dist-info}/WHEEL +0 -0
- {agentex_sdk-0.4.19.dist-info → agentex_sdk-0.4.21.dist-info}/entry_points.txt +0 -0
- {agentex_sdk-0.4.19.dist-info → agentex_sdk-0.4.21.dist-info}/licenses/LICENSE +0 -0
@@ -4,7 +4,6 @@ Debug configuration models for AgentEx CLI debugging.
|
|
4
4
|
|
5
5
|
import socket
|
6
6
|
from enum import Enum
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from agentex.lib.utils.model_utils import BaseModel
|
10
9
|
|
@@ -62,7 +61,7 @@ class DebugConfig(BaseModel):
|
|
62
61
|
def create_both_debug(
|
63
62
|
cls,
|
64
63
|
worker_port: int = 5678,
|
65
|
-
|
64
|
+
_acp_port: int = 5679,
|
66
65
|
wait_for_attach: bool = False,
|
67
66
|
auto_port: bool = True
|
68
67
|
) -> "DebugConfig":
|
@@ -4,19 +4,21 @@ Debug process handlers for AgentEx CLI.
|
|
4
4
|
Provides debug-enabled versions of ACP server and temporal worker startup.
|
5
5
|
"""
|
6
6
|
|
7
|
-
import asyncio
|
8
7
|
import sys
|
8
|
+
import asyncio
|
9
|
+
import asyncio.subprocess
|
10
|
+
from typing import TYPE_CHECKING, Dict
|
9
11
|
from pathlib import Path
|
10
|
-
from typing import Dict, TYPE_CHECKING
|
11
12
|
|
12
13
|
from rich.console import Console
|
13
14
|
|
14
15
|
if TYPE_CHECKING:
|
15
|
-
|
16
|
+
pass
|
16
17
|
|
17
|
-
from .debug_config import DebugConfig, resolve_debug_port
|
18
18
|
from agentex.lib.utils.logging import make_logger
|
19
19
|
|
20
|
+
from .debug_config import DebugConfig, resolve_debug_port
|
21
|
+
|
20
22
|
logger = make_logger(__name__)
|
21
23
|
console = Console()
|
22
24
|
|
@@ -2,14 +2,13 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
|
-
from python_on_whales import DockerException, docker
|
6
5
|
from rich.console import Console
|
6
|
+
from python_on_whales import DockerException, docker
|
7
7
|
|
8
|
-
from agentex.lib.cli.handlers.run_handlers import RunError
|
9
|
-
from agentex.lib.cli.handlers.run_handlers import run_agent as _run_agent
|
10
8
|
from agentex.lib.cli.debug import DebugConfig
|
11
|
-
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
12
9
|
from agentex.lib.utils.logging import make_logger
|
10
|
+
from agentex.lib.cli.handlers.run_handlers import RunError, run_agent as _run_agent
|
11
|
+
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
13
12
|
|
14
13
|
logger = make_logger(__name__)
|
15
14
|
console = Console()
|
@@ -25,9 +24,9 @@ def build_agent(
|
|
25
24
|
repository_name: str | None,
|
26
25
|
platforms: list[str],
|
27
26
|
push: bool = False,
|
28
|
-
secret: str = None,
|
29
|
-
tag: str = None,
|
30
|
-
build_args: list[str] = None,
|
27
|
+
secret: str | None = None,
|
28
|
+
tag: str | None = None,
|
29
|
+
build_args: list[str] | None = None,
|
31
30
|
) -> str:
|
32
31
|
"""Build the agent locally and optionally push to registry
|
33
32
|
|
@@ -66,14 +65,14 @@ def build_agent(
|
|
66
65
|
# Log build context information for debugging
|
67
66
|
logger.info(f"Build context path: {build_context.path}")
|
68
67
|
logger.info(
|
69
|
-
f"Dockerfile path: {build_context.path / build_context.dockerfile_path}"
|
68
|
+
f"Dockerfile path: {build_context.path / build_context.dockerfile_path}" # type: ignore[operator]
|
70
69
|
)
|
71
70
|
|
72
71
|
try:
|
73
72
|
# Prepare build arguments
|
74
73
|
docker_build_kwargs = {
|
75
74
|
"context_path": str(build_context.path),
|
76
|
-
"file": str(build_context.path / build_context.dockerfile_path),
|
75
|
+
"file": str(build_context.path / build_context.dockerfile_path), # type: ignore[operator]
|
77
76
|
"tags": [image_name],
|
78
77
|
"platforms": platforms,
|
79
78
|
}
|
@@ -129,23 +128,23 @@ def build_agent(
|
|
129
128
|
|
130
129
|
def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = None):
|
131
130
|
"""Run an agent locally from the given manifest"""
|
132
|
-
import asyncio
|
133
|
-
import signal
|
134
131
|
import sys
|
132
|
+
import signal
|
133
|
+
import asyncio
|
135
134
|
|
136
135
|
# Flag to track if we're shutting down
|
137
136
|
shutting_down = False
|
138
137
|
|
139
|
-
def signal_handler(signum,
|
138
|
+
def signal_handler(signum, _frame):
|
140
139
|
"""Handle signals by raising KeyboardInterrupt"""
|
141
140
|
nonlocal shutting_down
|
142
141
|
if shutting_down:
|
143
142
|
# If we're already shutting down and get another signal, force exit
|
144
|
-
|
143
|
+
logger.info(f"Force exit on signal {signum}")
|
145
144
|
sys.exit(1)
|
146
|
-
|
145
|
+
|
147
146
|
shutting_down = True
|
148
|
-
|
147
|
+
logger.info(f"Received signal {signum}, shutting down...")
|
149
148
|
raise KeyboardInterrupt()
|
150
149
|
|
151
150
|
# Set up signal handling for the main thread
|
@@ -155,7 +154,7 @@ def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = None):
|
|
155
154
|
try:
|
156
155
|
asyncio.run(_run_agent(manifest_path, debug_config))
|
157
156
|
except KeyboardInterrupt:
|
158
|
-
|
157
|
+
logger.info("Shutdown completed.")
|
159
158
|
sys.exit(0)
|
160
159
|
except RunError as e:
|
161
160
|
raise RuntimeError(str(e)) from e
|
@@ -25,20 +25,14 @@ AGENTEX_AGENTS_HELM_CHART_VERSION = "0.1.7-v4-beta"
|
|
25
25
|
|
26
26
|
|
27
27
|
class InputDeployOverrides(BaseModel):
|
28
|
-
repository: str | None = Field(
|
29
|
-
|
30
|
-
)
|
31
|
-
image_tag: str | None = Field(
|
32
|
-
default=None, description="Override the image tag for deployment"
|
33
|
-
)
|
28
|
+
repository: str | None = Field(default=None, description="Override the repository for deployment")
|
29
|
+
image_tag: str | None = Field(default=None, description="Override the image tag for deployment")
|
34
30
|
|
35
31
|
|
36
32
|
def check_helm_installed() -> bool:
|
37
33
|
"""Check if helm is installed and available"""
|
38
34
|
try:
|
39
|
-
result = subprocess.run(
|
40
|
-
["helm", "version", "--short"], capture_output=True, text=True, check=True
|
41
|
-
)
|
35
|
+
result = subprocess.run(["helm", "version", "--short"], capture_output=True, text=True, check=True)
|
42
36
|
logger.info(f"Helm version: {result.stdout.strip()}")
|
43
37
|
return True
|
44
38
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
@@ -49,9 +43,7 @@ def add_helm_repo(helm_repository_name: str, helm_repository_url: str) -> None:
|
|
49
43
|
"""Add the agentex helm repository if not already added"""
|
50
44
|
try:
|
51
45
|
# Check if repo already exists
|
52
|
-
result = subprocess.run(
|
53
|
-
["helm", "repo", "list"], capture_output=True, text=True, check=True
|
54
|
-
)
|
46
|
+
result = subprocess.run(["helm", "repo", "list"], capture_output=True, text=True, check=True)
|
55
47
|
|
56
48
|
if helm_repository_name not in result.stdout:
|
57
49
|
console.print("Adding agentex helm repository...")
|
@@ -75,7 +67,6 @@ def add_helm_repo(helm_repository_name: str, helm_repository_url: str) -> None:
|
|
75
67
|
raise HelmError(f"Failed to add helm repository: {e}") from e
|
76
68
|
|
77
69
|
|
78
|
-
|
79
70
|
def convert_env_vars_dict_to_list(env_vars: dict[str, str]) -> list[dict[str, str]]:
|
80
71
|
"""Convert a dictionary of environment variables to a list of dictionaries"""
|
81
72
|
return [{"name": key, "value": value} for key, value in env_vars.items()]
|
@@ -169,11 +160,11 @@ def merge_deployment_configs(
|
|
169
160
|
# Priority: manifest -> environments.yaml -> secrets (highest)
|
170
161
|
all_env_vars: dict[str, str] = {}
|
171
162
|
secret_env_vars: list[dict[str, str]] = []
|
172
|
-
|
163
|
+
|
173
164
|
# Start with agent_config env vars from manifest
|
174
165
|
if agent_config.env:
|
175
166
|
all_env_vars.update(agent_config.env)
|
176
|
-
|
167
|
+
|
177
168
|
# Override with environment config env vars if they exist
|
178
169
|
if agent_env_config and agent_env_config.helm_overrides and "env" in agent_env_config.helm_overrides:
|
179
170
|
env_overrides = agent_env_config.helm_overrides["env"]
|
@@ -185,8 +176,6 @@ def merge_deployment_configs(
|
|
185
176
|
env_override_dict[str(env_var["name"])] = str(env_var["value"])
|
186
177
|
all_env_vars.update(env_override_dict)
|
187
178
|
|
188
|
-
|
189
|
-
|
190
179
|
# Handle credentials and check for conflicts
|
191
180
|
if agent_config.credentials:
|
192
181
|
for credential in agent_config.credentials:
|
@@ -199,7 +188,7 @@ def merge_deployment_configs(
|
|
199
188
|
env_var_name = credential.env_var_name
|
200
189
|
secret_name = credential.secret_name
|
201
190
|
secret_key = credential.secret_key
|
202
|
-
|
191
|
+
|
203
192
|
# Check if the environment variable name conflicts with existing env vars
|
204
193
|
if env_var_name in all_env_vars:
|
205
194
|
logger.warning(
|
@@ -208,7 +197,7 @@ def merge_deployment_configs(
|
|
208
197
|
)
|
209
198
|
# Remove from regular env vars since secret takes precedence
|
210
199
|
del all_env_vars[env_var_name]
|
211
|
-
|
200
|
+
|
212
201
|
secret_env_vars.append(
|
213
202
|
{
|
214
203
|
"name": env_var_name,
|
@@ -222,13 +211,14 @@ def merge_deployment_configs(
|
|
222
211
|
# Add auth principal env var if environment config is set
|
223
212
|
if agent_env_config.auth:
|
224
213
|
from agentex.lib.cli.utils.auth_utils import _encode_principal_context_from_env_config
|
214
|
+
|
225
215
|
encoded_principal = _encode_principal_context_from_env_config(agent_env_config.auth)
|
226
216
|
logger.info(f"Encoding auth principal from {agent_env_config.auth}")
|
227
217
|
if encoded_principal:
|
228
218
|
all_env_vars[EnvVarKeys.AUTH_PRINCIPAL_B64.value] = encoded_principal
|
229
219
|
else:
|
230
220
|
raise DeploymentError(f"Auth principal unable to be encoded for agent_env_config: {agent_env_config}")
|
231
|
-
|
221
|
+
|
232
222
|
logger.info(f"Defined agent helm overrides: {agent_env_config.helm_overrides}")
|
233
223
|
logger.info(f"Before-merge helm values: {helm_values}")
|
234
224
|
if agent_env_config.helm_overrides:
|
@@ -239,7 +229,7 @@ def merge_deployment_configs(
|
|
239
229
|
# Environment variable precedence: manifest -> environments.yaml -> secrets (highest)
|
240
230
|
if all_env_vars:
|
241
231
|
helm_values["env"] = convert_env_vars_dict_to_list(all_env_vars)
|
242
|
-
|
232
|
+
|
243
233
|
if secret_env_vars:
|
244
234
|
helm_values["secretEnvVars"] = secret_env_vars
|
245
235
|
|
@@ -252,30 +242,25 @@ def merge_deployment_configs(
|
|
252
242
|
|
253
243
|
# Handle image pull secrets
|
254
244
|
if manifest.deployment and manifest.deployment.imagePullSecrets:
|
255
|
-
pull_secrets = [
|
256
|
-
pull_secret.model_dump()
|
257
|
-
for pull_secret in manifest.deployment.imagePullSecrets
|
258
|
-
]
|
245
|
+
pull_secrets = [pull_secret.model_dump() for pull_secret in manifest.deployment.imagePullSecrets]
|
259
246
|
helm_values["global"]["imagePullSecrets"] = pull_secrets
|
260
247
|
helm_values["imagePullSecrets"] = pull_secrets
|
261
248
|
|
262
249
|
# Add dynamic ACP command based on manifest configuration if command is not set in helm overrides
|
263
|
-
helm_overrides_command =
|
250
|
+
helm_overrides_command = (
|
251
|
+
agent_env_config and agent_env_config.helm_overrides and "command" in agent_env_config.helm_overrides
|
252
|
+
)
|
264
253
|
if not helm_overrides_command:
|
265
254
|
add_acp_command_to_helm_values(helm_values, manifest, manifest_path)
|
266
|
-
|
267
|
-
|
255
|
+
|
256
|
+
logger.info("Deploying with the following helm values: %s", helm_values)
|
268
257
|
return helm_values
|
269
258
|
|
270
259
|
|
271
260
|
def _deep_merge(base_dict: dict[str, Any], override_dict: dict[str, Any]) -> None:
|
272
261
|
"""Deep merge override_dict into base_dict"""
|
273
262
|
for key, value in override_dict.items():
|
274
|
-
if (
|
275
|
-
key in base_dict
|
276
|
-
and isinstance(base_dict[key], dict)
|
277
|
-
and isinstance(value, dict)
|
278
|
-
):
|
263
|
+
if key in base_dict and isinstance(base_dict[key], dict) and isinstance(value, dict):
|
279
264
|
_deep_merge(base_dict[key], value)
|
280
265
|
else:
|
281
266
|
base_dict[key] = value
|
@@ -394,12 +379,8 @@ def deploy_agent(
|
|
394
379
|
|
395
380
|
# Show success message with helpful commands
|
396
381
|
console.print("\n[green]🎉 Deployment completed successfully![/green]")
|
397
|
-
console.print(
|
398
|
-
|
399
|
-
)
|
400
|
-
console.print(
|
401
|
-
f"[blue]View logs:[/blue] kubectl logs -l app.kubernetes.io/name=agentex-agent -n {namespace}"
|
402
|
-
)
|
382
|
+
console.print(f"[blue]Check deployment status:[/blue] helm status {release_name} -n {namespace}")
|
383
|
+
console.print(f"[blue]View logs:[/blue] kubectl logs -l app.kubernetes.io/name=agentex-agent -n {namespace}")
|
403
384
|
|
404
385
|
except subprocess.CalledProcessError as e:
|
405
386
|
raise HelmError(
|
@@ -1,26 +1,21 @@
|
|
1
|
-
import asyncio
|
2
1
|
import os
|
3
2
|
import sys
|
3
|
+
import asyncio
|
4
4
|
from pathlib import Path
|
5
5
|
|
6
|
-
from rich.console import Console
|
7
6
|
from rich.panel import Panel
|
7
|
+
from rich.console import Console
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
)
|
9
|
+
# Import debug functionality
|
10
|
+
from agentex.lib.cli.debug import DebugConfig, start_acp_server_debug, start_temporal_worker_debug
|
11
|
+
from agentex.lib.utils.logging import make_logger
|
13
12
|
from agentex.lib.cli.utils.path_utils import (
|
14
13
|
get_file_paths,
|
15
14
|
calculate_uvicorn_target_for_local,
|
16
15
|
)
|
17
|
-
|
18
16
|
from agentex.lib.environment_variables import EnvVarKeys
|
19
17
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
20
|
-
|
21
|
-
# Import debug functionality
|
22
|
-
from agentex.lib.cli.debug import DebugConfig, start_acp_server_debug, start_temporal_worker_debug
|
23
|
-
from agentex.lib.utils.logging import make_logger
|
18
|
+
from agentex.lib.cli.handlers.cleanup_handlers import cleanup_agent_workflows, should_cleanup_on_restart
|
24
19
|
|
25
20
|
logger = make_logger(__name__)
|
26
21
|
console = Console()
|
@@ -242,6 +237,8 @@ async def start_temporal_worker(
|
|
242
237
|
async def stream_process_output(process: asyncio.subprocess.Process, prefix: str):
|
243
238
|
"""Stream process output with prefix"""
|
244
239
|
try:
|
240
|
+
if process.stdout is None:
|
241
|
+
return
|
245
242
|
while True:
|
246
243
|
line = await process.stdout.readline()
|
247
244
|
if not line:
|
@@ -297,11 +294,11 @@ async def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = Non
|
|
297
294
|
manifest_dir = Path(manifest_path).parent
|
298
295
|
if debug_config and debug_config.should_debug_acp():
|
299
296
|
acp_process = await start_acp_server_debug(
|
300
|
-
file_paths["acp"], manifest.local_development.agent.port, agent_env, debug_config
|
297
|
+
file_paths["acp"], manifest.local_development.agent.port, agent_env, debug_config # type: ignore[union-attr]
|
301
298
|
)
|
302
299
|
else:
|
303
300
|
acp_process = await start_acp_server(
|
304
|
-
file_paths["acp"], manifest.local_development.agent.port, agent_env, manifest_dir
|
301
|
+
file_paths["acp"], manifest.local_development.agent.port, agent_env, manifest_dir # type: ignore[union-attr]
|
305
302
|
)
|
306
303
|
process_manager.add_process(acp_process)
|
307
304
|
|
@@ -325,7 +322,7 @@ async def run_agent(manifest_path: str, debug_config: "DebugConfig | None" = Non
|
|
325
322
|
tasks.append(worker_task)
|
326
323
|
|
327
324
|
console.print(
|
328
|
-
f"\n[green]✓ Agent running at: http://localhost:{manifest.local_development.agent.port}[/green]"
|
325
|
+
f"\n[green]✓ Agent running at: http://localhost:{manifest.local_development.agent.port}[/green]" # type: ignore[union-attr]
|
329
326
|
)
|
330
327
|
console.print("[dim]Press Ctrl+C to stop[/dim]\n")
|
331
328
|
|
@@ -369,8 +366,8 @@ def create_agent_environment(manifest: AgentManifest) -> dict[str, str]:
|
|
369
366
|
"REDIS_URL": "redis://localhost:6379",
|
370
367
|
"AGENT_NAME": manifest.agent.name,
|
371
368
|
"ACP_TYPE": manifest.agent.acp_type,
|
372
|
-
"ACP_URL": f"http://{manifest.local_development.agent.host_address}",
|
373
|
-
"ACP_PORT": str(manifest.local_development.agent.port),
|
369
|
+
"ACP_URL": f"http://{manifest.local_development.agent.host_address}", # type: ignore[union-attr]
|
370
|
+
"ACP_PORT": str(manifest.local_development.agent.port), # type: ignore[union-attr]
|
374
371
|
}
|
375
372
|
|
376
373
|
# Add authorization principal if set - for local development, auth is optional
|
@@ -1,28 +1,19 @@
|
|
1
|
-
import base64
|
2
1
|
import json
|
3
|
-
|
4
|
-
from pathlib import Path
|
2
|
+
import base64
|
5
3
|
from typing import Any
|
4
|
+
from pathlib import Path
|
5
|
+
from collections import defaultdict
|
6
6
|
|
7
|
-
import questionary
|
8
|
-
import typer
|
9
7
|
import yaml
|
10
|
-
|
8
|
+
import typer
|
9
|
+
import questionary
|
11
10
|
from rich.console import Console
|
11
|
+
from kubernetes.client.rest import ApiException
|
12
12
|
|
13
|
+
from agentex.lib.utils.logging import make_logger
|
14
|
+
from agentex.lib.types.credentials import CredentialMapping
|
13
15
|
from agentex.lib.cli.utils.cli_utils import handle_questionary_cancellation
|
14
16
|
from agentex.lib.cli.utils.kubectl_utils import get_k8s_client
|
15
|
-
from agentex.lib.cli.utils.kubernetes_secrets_utils import (
|
16
|
-
KUBERNETES_SECRET_TO_MANIFEST_KEY,
|
17
|
-
KUBERNETES_SECRET_TYPE_DOCKERCONFIGJSON,
|
18
|
-
KUBERNETES_SECRET_TYPE_OPAQUE,
|
19
|
-
VALID_SECRET_TYPES,
|
20
|
-
create_image_pull_secret_with_data,
|
21
|
-
create_secret_with_data,
|
22
|
-
get_secret_data,
|
23
|
-
update_image_pull_secret_with_data,
|
24
|
-
update_secret_with_data,
|
25
|
-
)
|
26
17
|
from agentex.lib.sdk.config.agent_config import AgentConfig
|
27
18
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
28
19
|
from agentex.lib.sdk.config.deployment_config import (
|
@@ -30,8 +21,17 @@ from agentex.lib.sdk.config.deployment_config import (
|
|
30
21
|
ImagePullSecretConfig,
|
31
22
|
InjectedSecretsValues,
|
32
23
|
)
|
33
|
-
from agentex.lib.
|
34
|
-
|
24
|
+
from agentex.lib.cli.utils.kubernetes_secrets_utils import (
|
25
|
+
VALID_SECRET_TYPES,
|
26
|
+
KUBERNETES_SECRET_TYPE_OPAQUE,
|
27
|
+
KUBERNETES_SECRET_TO_MANIFEST_KEY,
|
28
|
+
KUBERNETES_SECRET_TYPE_DOCKERCONFIGJSON,
|
29
|
+
get_secret_data,
|
30
|
+
create_secret_with_data,
|
31
|
+
update_secret_with_data,
|
32
|
+
create_image_pull_secret_with_data,
|
33
|
+
update_image_pull_secret_with_data,
|
34
|
+
)
|
35
35
|
|
36
36
|
logger = make_logger(__name__)
|
37
37
|
console = Console()
|
@@ -131,16 +131,16 @@ def interactive_secret_input(secret_name: str, secret_key: str) -> str:
|
|
131
131
|
return handle_questionary_cancellation(result, "text input")
|
132
132
|
|
133
133
|
|
134
|
-
def get_secret(name: str, namespace: str, context: str | None = None) -> dict:
|
134
|
+
def get_secret(name: str, namespace: str, context: str | None = None) -> dict[str, Any]:
|
135
135
|
"""Get details about a secret"""
|
136
136
|
v1 = get_k8s_client(context)
|
137
137
|
|
138
138
|
try:
|
139
139
|
secret = v1.read_namespaced_secret(name=name, namespace=namespace)
|
140
140
|
return {
|
141
|
-
"name": secret.metadata.name,
|
141
|
+
"name": secret.metadata.name, # type: ignore[union-attr]
|
142
142
|
"namespace": namespace,
|
143
|
-
"created": secret.metadata.creation_timestamp.isoformat(),
|
143
|
+
"created": secret.metadata.creation_timestamp.isoformat(), # type: ignore[union-attr]
|
144
144
|
"exists": True,
|
145
145
|
}
|
146
146
|
except ApiException as e:
|
@@ -173,7 +173,7 @@ def delete_secret(name: str, namespace: str, context: str | None = None) -> None
|
|
173
173
|
|
174
174
|
def get_kubernetes_secrets_by_type(
|
175
175
|
namespace: str, context: str | None = None
|
176
|
-
) -> dict[str, list[dict]]:
|
176
|
+
) -> dict[str, list[dict[str, Any]]]:
|
177
177
|
"""List metadata about secrets in the namespace"""
|
178
178
|
v1 = get_k8s_client(context)
|
179
179
|
|
@@ -218,7 +218,7 @@ def sync_user_defined_secrets(
|
|
218
218
|
cluster_secret_names = {secret["name"] for secret in found_secrets}
|
219
219
|
# Get the secrets from the manifest
|
220
220
|
agent_config: AgentConfig = manifest_obj.agent
|
221
|
-
manifest_credentials: list[CredentialMapping] = agent_config.credentials or []
|
221
|
+
manifest_credentials: list[CredentialMapping] = agent_config.credentials or [] # type: ignore[assignment]
|
222
222
|
|
223
223
|
if not manifest_credentials:
|
224
224
|
console.print("[yellow]No credentials found in manifest[/yellow]")
|
@@ -465,7 +465,7 @@ def sync_image_pull_secrets(
|
|
465
465
|
}
|
466
466
|
|
467
467
|
# Get the secrets from the manifest
|
468
|
-
deployment_config: DeploymentConfig = manifest_obj.deployment
|
468
|
+
deployment_config: DeploymentConfig = manifest_obj.deployment # type: ignore[assignment]
|
469
469
|
manifest_image_pull_secrets: list[ImagePullSecretConfig] = (
|
470
470
|
deployment_config.imagePullSecrets or []
|
471
471
|
)
|
@@ -5,23 +5,26 @@ import sys
|
|
5
5
|
if os.getenv("AGENTEX_DEBUG_ENABLED") == "true":
|
6
6
|
try:
|
7
7
|
import debugpy
|
8
|
+
from agentex.lib.utils.logging import make_logger
|
9
|
+
|
10
|
+
logger = make_logger(__name__)
|
8
11
|
debug_port = int(os.getenv("AGENTEX_DEBUG_PORT", "5679"))
|
9
12
|
debug_type = os.getenv("AGENTEX_DEBUG_TYPE", "acp")
|
10
13
|
wait_for_attach = os.getenv("AGENTEX_DEBUG_WAIT_FOR_ATTACH", "false").lower() == "true"
|
11
|
-
|
14
|
+
|
12
15
|
# Configure debugpy
|
13
16
|
debugpy.configure(subProcess=False)
|
14
17
|
debugpy.listen(debug_port)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
|
19
|
+
logger.info(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
|
20
|
+
|
18
21
|
if wait_for_attach:
|
19
|
-
|
22
|
+
logger.info(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
|
20
23
|
debugpy.wait_for_client()
|
21
|
-
|
24
|
+
logger.info(f"✅ [{debug_type.upper()}] Debugger attached!")
|
22
25
|
else:
|
23
|
-
|
24
|
-
|
26
|
+
logger.info(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
|
27
|
+
|
25
28
|
except ImportError:
|
26
29
|
print("❌ debugpy not available. Install with: pip install debugpy")
|
27
30
|
sys.exit(1)
|
@@ -1,13 +1,14 @@
|
|
1
|
-
import base64
|
2
1
|
import json
|
2
|
+
import base64
|
3
3
|
from typing import Any, Dict
|
4
4
|
|
5
5
|
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
6
6
|
from agentex.lib.sdk.config.environment_config import AgentAuthConfig
|
7
7
|
|
8
|
+
|
8
9
|
# DEPRECATED: Old function for backward compatibility
|
9
10
|
# Will be removed in future version
|
10
|
-
def _encode_principal_context(manifest: AgentManifest) -> str | None:
|
11
|
+
def _encode_principal_context(manifest: AgentManifest) -> str | None: # noqa: ARG001
|
11
12
|
"""
|
12
13
|
DEPRECATED: This function is deprecated as AgentManifest no longer contains auth.
|
13
14
|
Use _encode_principal_context_from_env_config instead.
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import subprocess
|
2
2
|
|
3
3
|
from kubernetes import client, config
|
4
|
-
from kubernetes.client.rest import ApiException
|
5
4
|
from rich.console import Console
|
5
|
+
from kubernetes.client.rest import ApiException
|
6
6
|
|
7
|
-
from agentex.lib.cli.utils.exceptions import DeploymentError
|
8
7
|
from agentex.lib.utils.logging import make_logger
|
8
|
+
from agentex.lib.cli.utils.exceptions import DeploymentError
|
9
9
|
|
10
10
|
logger = make_logger(__name__)
|
11
11
|
console = Console()
|
@@ -59,7 +59,7 @@ def list_available_contexts() -> list[str]:
|
|
59
59
|
"""List all available kubectl contexts"""
|
60
60
|
try:
|
61
61
|
contexts, _ = config.list_kube_config_contexts()
|
62
|
-
return [ctx["name"] for ctx in contexts]
|
62
|
+
return [ctx["name"] for ctx in contexts] # type: ignore[index]
|
63
63
|
except Exception as e:
|
64
64
|
raise DeploymentError(f"Failed to list kubectl contexts: {e}") from e
|
65
65
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import base64
|
2
2
|
|
3
3
|
from kubernetes import client
|
4
|
-
from kubernetes.client.rest import ApiException
|
5
4
|
from rich.console import Console
|
5
|
+
from kubernetes.client.rest import ApiException
|
6
6
|
|
7
|
-
from agentex.lib.cli.utils.kubectl_utils import get_k8s_client
|
8
7
|
from agentex.lib.utils.logging import make_logger
|
8
|
+
from agentex.lib.cli.utils.kubectl_utils import get_k8s_client
|
9
9
|
|
10
10
|
logger = make_logger(__name__)
|
11
11
|
console = Console()
|
@@ -172,11 +172,11 @@ def get_secret_data(
|
|
172
172
|
v1 = get_k8s_client(context)
|
173
173
|
try:
|
174
174
|
secret = v1.read_namespaced_secret(name=name, namespace=namespace)
|
175
|
-
if secret.data:
|
175
|
+
if secret.data: # type: ignore[union-attr]
|
176
176
|
# Decode base64 data
|
177
177
|
return {
|
178
178
|
key: base64.b64decode(value).decode("utf-8")
|
179
|
-
for key, value in secret.data.items()
|
179
|
+
for key, value in secret.data.items() # type: ignore[union-attr]
|
180
180
|
}
|
181
181
|
return {}
|
182
182
|
except ApiException as e:
|
@@ -1,8 +1,8 @@
|
|
1
|
-
from pathlib import Path
|
2
1
|
from typing import Dict
|
2
|
+
from pathlib import Path
|
3
3
|
|
4
|
-
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
5
4
|
from agentex.lib.utils.logging import make_logger
|
5
|
+
from agentex.lib.sdk.config.agent_manifest import AgentManifest
|
6
6
|
|
7
7
|
logger = make_logger(__name__)
|
8
8
|
|
@@ -1,15 +1,17 @@
|
|
1
|
-
from
|
1
|
+
from typing import override
|
2
|
+
from collections.abc import Generator, AsyncGenerator
|
2
3
|
|
3
4
|
import litellm as llm
|
4
5
|
|
5
|
-
from agentex.lib.core.adapters.llm.port import LLMGateway
|
6
|
-
from agentex.lib.types.llm_messages import Completion
|
7
6
|
from agentex.lib.utils.logging import make_logger
|
7
|
+
from agentex.lib.types.llm_messages import Completion
|
8
|
+
from agentex.lib.core.adapters.llm.port import LLMGateway
|
8
9
|
|
9
10
|
logger = make_logger(__name__)
|
10
11
|
|
11
12
|
|
12
13
|
class LiteLLMGateway(LLMGateway):
|
14
|
+
@override
|
13
15
|
def completion(self, *args, **kwargs) -> Completion:
|
14
16
|
if kwargs.get("stream", True):
|
15
17
|
raise ValueError(
|
@@ -19,6 +21,7 @@ class LiteLLMGateway(LLMGateway):
|
|
19
21
|
response = llm.completion(*args, **kwargs)
|
20
22
|
return Completion.model_validate(response)
|
21
23
|
|
24
|
+
@override
|
22
25
|
def completion_stream(self, *args, **kwargs) -> Generator[Completion, None, None]:
|
23
26
|
if not kwargs.get("stream"):
|
24
27
|
raise ValueError("To use streaming, please set stream=True in the kwargs")
|
@@ -26,6 +29,7 @@ class LiteLLMGateway(LLMGateway):
|
|
26
29
|
for chunk in llm.completion(*args, **kwargs):
|
27
30
|
yield Completion.model_validate(chunk)
|
28
31
|
|
32
|
+
@override
|
29
33
|
async def acompletion(self, *args, **kwargs) -> Completion:
|
30
34
|
if kwargs.get("stream", True):
|
31
35
|
raise ValueError(
|
@@ -36,11 +40,12 @@ class LiteLLMGateway(LLMGateway):
|
|
36
40
|
response = await llm.acompletion(*args, **kwargs)
|
37
41
|
return Completion.model_validate(response)
|
38
42
|
|
43
|
+
@override
|
39
44
|
async def acompletion_stream(
|
40
45
|
self, *args, **kwargs
|
41
46
|
) -> AsyncGenerator[Completion, None]:
|
42
47
|
if not kwargs.get("stream"):
|
43
48
|
raise ValueError("To use streaming, please set stream=True in the kwargs")
|
44
49
|
|
45
|
-
async for chunk in await llm.acompletion(*args, **kwargs):
|
50
|
+
async for chunk in await llm.acompletion(*args, **kwargs): # type: ignore[misc]
|
46
51
|
yield Completion.model_validate(chunk)
|