agentex-sdk 0.4.18__py3-none-any.whl → 0.4.20__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.
Files changed (130) hide show
  1. agentex/__init__.py +0 -1
  2. agentex/_utils/_typing.py +3 -1
  3. agentex/_version.py +1 -1
  4. agentex/lib/adk/__init__.py +3 -0
  5. agentex/lib/adk/_modules/acp.py +3 -1
  6. agentex/lib/adk/_modules/agent_task_tracker.py +3 -1
  7. agentex/lib/adk/_modules/agents.py +3 -1
  8. agentex/lib/adk/_modules/events.py +3 -1
  9. agentex/lib/adk/_modules/messages.py +3 -1
  10. agentex/lib/adk/_modules/state.py +3 -1
  11. agentex/lib/adk/_modules/streaming.py +3 -1
  12. agentex/lib/adk/_modules/tasks.py +4 -2
  13. agentex/lib/adk/_modules/tracing.py +3 -1
  14. agentex/lib/adk/providers/__init__.py +2 -2
  15. agentex/lib/adk/providers/_modules/litellm.py +10 -11
  16. agentex/lib/adk/providers/_modules/openai.py +27 -28
  17. agentex/lib/adk/providers/_modules/sgp.py +5 -6
  18. agentex/lib/adk/utils/_modules/client.py +4 -1
  19. agentex/lib/adk/utils/_modules/templating.py +5 -6
  20. agentex/lib/cli/commands/agents.py +21 -21
  21. agentex/lib/cli/commands/init.py +3 -3
  22. agentex/lib/cli/commands/main.py +3 -3
  23. agentex/lib/cli/commands/secrets.py +10 -10
  24. agentex/lib/cli/commands/tasks.py +26 -28
  25. agentex/lib/cli/commands/uv.py +1 -1
  26. agentex/lib/cli/debug/__init__.py +1 -1
  27. agentex/lib/cli/debug/debug_config.py +1 -2
  28. agentex/lib/cli/debug/debug_handlers.py +6 -4
  29. agentex/lib/cli/handlers/agent_handlers.py +15 -16
  30. agentex/lib/cli/handlers/cleanup_handlers.py +1 -1
  31. agentex/lib/cli/handlers/deploy_handlers.py +41 -55
  32. agentex/lib/cli/handlers/run_handlers.py +13 -16
  33. agentex/lib/cli/handlers/secret_handlers.py +25 -25
  34. agentex/lib/cli/templates/temporal/project/acp.py.j2 +11 -8
  35. agentex/lib/cli/utils/auth_utils.py +3 -2
  36. agentex/lib/cli/utils/credential_utils.py +1 -1
  37. agentex/lib/cli/utils/kubectl_utils.py +3 -3
  38. agentex/lib/cli/utils/kubernetes_secrets_utils.py +4 -4
  39. agentex/lib/cli/utils/path_utils.py +2 -2
  40. agentex/lib/core/adapters/llm/adapter_litellm.py +9 -4
  41. agentex/lib/core/adapters/llm/adapter_sgp.py +10 -7
  42. agentex/lib/core/adapters/llm/port.py +1 -1
  43. agentex/lib/core/adapters/streams/adapter_redis.py +7 -4
  44. agentex/lib/core/adapters/streams/port.py +1 -1
  45. agentex/lib/core/clients/temporal/temporal_client.py +34 -34
  46. agentex/lib/core/clients/temporal/types.py +1 -1
  47. agentex/lib/core/clients/temporal/utils.py +9 -12
  48. agentex/lib/core/services/adk/acp/acp.py +6 -6
  49. agentex/lib/core/services/adk/agent_task_tracker.py +1 -1
  50. agentex/lib/core/services/adk/agents.py +1 -1
  51. agentex/lib/core/services/adk/events.py +1 -1
  52. agentex/lib/core/services/adk/messages.py +5 -6
  53. agentex/lib/core/services/adk/providers/litellm.py +10 -10
  54. agentex/lib/core/services/adk/providers/openai.py +75 -43
  55. agentex/lib/core/services/adk/providers/sgp.py +3 -3
  56. agentex/lib/core/services/adk/state.py +5 -1
  57. agentex/lib/core/services/adk/streaming.py +19 -19
  58. agentex/lib/core/services/adk/tasks.py +8 -2
  59. agentex/lib/core/services/adk/tracing.py +3 -2
  60. agentex/lib/core/services/adk/utils/templating.py +4 -2
  61. agentex/lib/core/temporal/activities/__init__.py +27 -27
  62. agentex/lib/core/temporal/activities/activity_helpers.py +1 -1
  63. agentex/lib/core/temporal/activities/adk/acp/acp_activities.py +4 -4
  64. agentex/lib/core/temporal/activities/adk/agent_task_tracker_activities.py +1 -1
  65. agentex/lib/core/temporal/activities/adk/agents_activities.py +2 -2
  66. agentex/lib/core/temporal/activities/adk/events_activities.py +1 -1
  67. agentex/lib/core/temporal/activities/adk/messages_activities.py +3 -3
  68. agentex/lib/core/temporal/activities/adk/providers/litellm_activities.py +4 -4
  69. agentex/lib/core/temporal/activities/adk/providers/sgp_activities.py +1 -1
  70. agentex/lib/core/temporal/activities/adk/state_activities.py +1 -1
  71. agentex/lib/core/temporal/activities/adk/streaming_activities.py +3 -3
  72. agentex/lib/core/temporal/activities/adk/tasks_activities.py +2 -2
  73. agentex/lib/core/temporal/activities/adk/tracing_activities.py +1 -1
  74. agentex/lib/core/temporal/activities/adk/utils/templating_activities.py +1 -1
  75. agentex/lib/core/temporal/services/temporal_task_service.py +7 -7
  76. agentex/lib/core/temporal/workers/worker.py +31 -40
  77. agentex/lib/core/temporal/workflows/workflow.py +2 -2
  78. agentex/lib/core/tracing/__init__.py +2 -2
  79. agentex/lib/core/tracing/processors/agentex_tracing_processor.py +6 -6
  80. agentex/lib/core/tracing/processors/sgp_tracing_processor.py +16 -16
  81. agentex/lib/core/tracing/processors/tracing_processor_interface.py +1 -1
  82. agentex/lib/core/tracing/trace.py +7 -7
  83. agentex/lib/core/tracing/tracer.py +2 -2
  84. agentex/lib/core/tracing/tracing_processor_manager.py +43 -13
  85. agentex/lib/environment_variables.py +5 -4
  86. agentex/lib/sdk/config/agent_config.py +2 -2
  87. agentex/lib/sdk/config/agent_manifest.py +8 -8
  88. agentex/lib/sdk/config/environment_config.py +10 -2
  89. agentex/lib/sdk/config/project_config.py +6 -6
  90. agentex/lib/sdk/config/validation.py +2 -2
  91. agentex/lib/sdk/fastacp/base/base_acp_server.py +31 -13
  92. agentex/lib/sdk/fastacp/fastacp.py +14 -15
  93. agentex/lib/sdk/fastacp/impl/agentic_base_acp.py +4 -5
  94. agentex/lib/sdk/fastacp/impl/sync_acp.py +7 -7
  95. agentex/lib/sdk/fastacp/impl/temporal_acp.py +28 -19
  96. agentex/lib/sdk/fastacp/tests/conftest.py +18 -16
  97. agentex/lib/sdk/fastacp/tests/run_tests.py +1 -1
  98. agentex/lib/sdk/fastacp/tests/test_base_acp_server.py +4 -4
  99. agentex/lib/sdk/fastacp/tests/test_fastacp_factory.py +8 -8
  100. agentex/lib/sdk/fastacp/tests/test_integration.py +15 -14
  101. agentex/lib/sdk/state_machine/__init__.py +1 -1
  102. agentex/lib/sdk/state_machine/noop_workflow.py +5 -3
  103. agentex/lib/sdk/state_machine/state_machine.py +18 -12
  104. agentex/lib/sdk/utils/messages.py +5 -5
  105. agentex/lib/types/acp.py +2 -2
  106. agentex/lib/types/agent_configs.py +1 -1
  107. agentex/lib/types/converters.py +4 -2
  108. agentex/lib/types/credentials.py +1 -1
  109. agentex/lib/types/fastacp.py +4 -5
  110. agentex/lib/types/tracing.py +1 -1
  111. agentex/lib/utils/completions.py +5 -5
  112. agentex/lib/utils/console.py +1 -1
  113. agentex/lib/utils/debug.py +10 -5
  114. agentex/lib/utils/dev_tools/async_messages.py +11 -12
  115. agentex/lib/utils/iterables.py +1 -1
  116. agentex/lib/utils/json_schema.py +4 -4
  117. agentex/lib/utils/logging.py +62 -14
  118. agentex/lib/utils/mcp.py +1 -0
  119. agentex/lib/utils/model_utils.py +4 -5
  120. agentex/lib/utils/registration.py +5 -4
  121. agentex/resources/agents.py +11 -4
  122. agentex/types/agent_rpc_response.py +3 -3
  123. agentex/types/data_content.py +1 -1
  124. agentex/types/tool_request_content.py +1 -1
  125. agentex/types/tool_response_content.py +0 -1
  126. {agentex_sdk-0.4.18.dist-info → agentex_sdk-0.4.20.dist-info}/METADATA +4 -1
  127. {agentex_sdk-0.4.18.dist-info → agentex_sdk-0.4.20.dist-info}/RECORD +130 -130
  128. {agentex_sdk-0.4.18.dist-info → agentex_sdk-0.4.20.dist-info}/WHEEL +0 -0
  129. {agentex_sdk-0.4.18.dist-info → agentex_sdk-0.4.20.dist-info}/entry_points.txt +0 -0
  130. {agentex_sdk-0.4.18.dist-info → agentex_sdk-0.4.20.dist-info}/licenses/LICENSE +0 -0
@@ -2,9 +2,9 @@ from abc import ABC, abstractmethod
2
2
  from typing import Any, Generic, TypeVar
3
3
 
4
4
  from agentex.lib import adk
5
+ from agentex.lib.utils.model_utils import BaseModel
5
6
  from agentex.lib.sdk.state_machine.state import State
6
7
  from agentex.lib.sdk.state_machine.state_workflow import StateWorkflow
7
- from agentex.lib.utils.model_utils import BaseModel
8
8
 
9
9
  T = TypeVar("T", bound=BaseModel)
10
10
 
@@ -55,7 +55,13 @@ class StateMachine(ABC, Generic[T]):
55
55
  raise ValueError(f"State {target_state_name} not found")
56
56
  self._current_state = self._state_map[target_state_name]
57
57
 
58
- def get_state_machine_data(self) -> T:
58
+ def get_state_machine_data(self) -> T | None:
59
+ return self.state_machine_data
60
+
61
+ def require_state_machine_data(self) -> T:
62
+ """Get state machine data, raising an error if not set."""
63
+ if self.state_machine_data is None:
64
+ raise ValueError("State machine data not initialized - ensure data is provided")
59
65
  return self.state_machine_data
60
66
 
61
67
  @abstractmethod
@@ -70,7 +76,10 @@ class StateMachine(ABC, Generic[T]):
70
76
  async def step(self) -> str:
71
77
  current_state_name = self.get_current_state()
72
78
  current_state = self._state_map.get(current_state_name)
79
+ if current_state is None:
80
+ raise ValueError(f"Current state '{current_state_name}' not found in state map")
73
81
 
82
+ span = None
74
83
  if self._trace_transitions:
75
84
  if self._task_id is None:
76
85
  raise ValueError(
@@ -79,7 +88,7 @@ class StateMachine(ABC, Generic[T]):
79
88
  span = await adk.tracing.start_span(
80
89
  trace_id=self._task_id,
81
90
  name="state_transition",
82
- input=self.state_machine_data.model_dump(),
91
+ input=self.require_state_machine_data().model_dump(),
83
92
  data={"input_state": current_state_name},
84
93
  )
85
94
 
@@ -87,13 +96,10 @@ class StateMachine(ABC, Generic[T]):
87
96
  state_machine=self, state_machine_data=self.state_machine_data
88
97
  )
89
98
 
90
- if self._trace_transitions:
91
- if self._task_id is None:
92
- raise ValueError(
93
- "Task ID is must be set before tracing can be enabled"
94
- )
95
- span.output = self.state_machine_data.model_dump()
96
- span.data["output_state"] = next_state_name
99
+ if self._trace_transitions and span is not None:
100
+ span.output = self.require_state_machine_data().model_dump() # type: ignore[assignment]
101
+ if span.data is not None:
102
+ span.data["output_state"] = next_state_name # type: ignore[index]
97
103
  await adk.tracing.end_span(trace_id=self._task_id, span=span)
98
104
 
99
105
  await self.transition(next_state_name)
@@ -118,7 +124,7 @@ class StateMachine(ABC, Generic[T]):
118
124
  await self.transition(self._initial_state)
119
125
 
120
126
  if self._trace_transitions:
121
- span.output = {"output_state": self._initial_state}
127
+ span.output = {"output_state": self._initial_state} # type: ignore[assignment,union-attr]
122
128
  await adk.tracing.end_span(trace_id=self._task_id, span=span)
123
129
 
124
130
  def dump(self) -> dict[str, Any]:
@@ -168,7 +174,7 @@ class StateMachine(ABC, Generic[T]):
168
174
  state_machine_data = None
169
175
  if state_machine_data_dict is not None:
170
176
  # Get the actual model type from the class's type parameters
171
- model_type = cls.__orig_bases__[0].__args__[0]
177
+ model_type = cls.__orig_bases__[0].__args__[0] # type: ignore[attr-defined]
172
178
  state_machine_data = model_type.model_validate(state_machine_data_dict)
173
179
 
174
180
  # Create a new instance
@@ -2,17 +2,17 @@ import json
2
2
  from abc import ABC, abstractmethod
3
3
  from typing import Any, Literal, override
4
4
 
5
+ from agentex.types.data_content import DataContent
6
+ from agentex.types.task_message import TaskMessage
7
+ from agentex.types.text_content import TextContent
5
8
  from agentex.lib.types.llm_messages import (
6
- AssistantMessage,
7
9
  Message,
8
10
  ToolCall,
9
- ToolCallRequest,
10
11
  ToolMessage,
11
12
  UserMessage,
13
+ ToolCallRequest,
14
+ AssistantMessage,
12
15
  )
13
- from agentex.types.data_content import DataContent
14
- from agentex.types.task_message import TaskMessage
15
- from agentex.types.text_content import TextContent
16
16
  from agentex.types.tool_request_content import ToolRequestContent
17
17
  from agentex.types.tool_response_content import ToolResponseContent
18
18
 
agentex/lib/types/acp.py CHANGED
@@ -1,12 +1,12 @@
1
1
  from enum import Enum
2
2
  from typing import Any
3
3
 
4
- from pydantic import BaseModel, Field
4
+ from pydantic import Field, BaseModel
5
5
 
6
+ from agentex.types.task import Task
6
7
  from agentex.types.agent import Agent
7
8
  from agentex.types.event import Event
8
9
  from agentex.types.task_message_content import TaskMessageContent
9
- from agentex.types.task import Task
10
10
 
11
11
 
12
12
  class RPCMethod(str, Enum):
@@ -1,4 +1,4 @@
1
- from pydantic import BaseModel, Field, model_validator, validator
1
+ from pydantic import Field, BaseModel, validator, model_validator
2
2
 
3
3
 
4
4
  class TemporalWorkflowConfig(BaseModel):
@@ -1,9 +1,11 @@
1
+ import json
2
+
3
+ from agents import TResponseInputItem
4
+
1
5
  from agentex.types.task_message import TaskMessage
2
6
  from agentex.types.text_content import TextContent
3
7
  from agentex.types.tool_request_content import ToolRequestContent
4
8
  from agentex.types.tool_response_content import ToolResponseContent
5
- import json
6
- from agents import TResponseInputItem
7
9
 
8
10
 
9
11
  def convert_task_messages_to_oai_agents_inputs(
@@ -1,4 +1,4 @@
1
- from pydantic import BaseModel, Field
1
+ from pydantic import Field, BaseModel
2
2
 
3
3
 
4
4
  class CredentialMapping(BaseModel):
@@ -1,6 +1,7 @@
1
1
  from typing import Any, Literal
2
2
 
3
- from pydantic import BaseModel, Field, field_validator
3
+ from pydantic import Field, BaseModel, field_validator
4
+
4
5
  from agentex.lib.core.clients.temporal.utils import validate_client_plugins
5
6
 
6
7
 
@@ -48,11 +49,9 @@ class TemporalACPConfig(AgenticACPConfig):
48
49
  """
49
50
 
50
51
  type: Literal["temporal"] = Field(default="temporal", frozen=True)
51
- temporal_address: str = Field(
52
- default="temporal-frontend.temporal.svc.cluster.local:7233", frozen=True
53
- )
52
+ temporal_address: str = Field(default="temporal-frontend.temporal.svc.cluster.local:7233", frozen=True)
54
53
  plugins: list[Any] = Field(default=[], frozen=True)
55
-
54
+
56
55
  @field_validator("plugins")
57
56
  @classmethod
58
57
  def validate_plugins(cls, v: list[Any]) -> list[Any]:
@@ -1,4 +1,4 @@
1
- from typing import Annotated, Literal
1
+ from typing import Literal, Annotated
2
2
 
3
3
  from pydantic import Field
4
4
 
@@ -1,18 +1,18 @@
1
1
  from copy import deepcopy
2
- from functools import reduce, singledispatch
3
2
  from typing import Any
3
+ from functools import reduce, singledispatch
4
4
 
5
5
  from agentex.lib.types.llm_messages import (
6
- Choice,
7
- Completion,
8
6
  Delta,
7
+ Choice,
9
8
  ToolCall,
9
+ Completion,
10
10
  ToolCallRequest,
11
11
  )
12
12
 
13
13
 
14
14
  @singledispatch
15
- def _concat_chunks(a: None, b: Any):
15
+ def _concat_chunks(_a: None, b: Any):
16
16
  return b
17
17
 
18
18
 
@@ -116,7 +116,7 @@ def concat_completion_chunks(chunks: list[Completion]) -> Completion:
116
116
  single `CompletionChunk`. Finally we convert the type to the appropriate non-streaming type `Completion` and return it.
117
117
  """
118
118
  if not chunks:
119
- return None
119
+ raise ValueError("Cannot concatenate empty chunks list")
120
120
 
121
121
  chunks_copy = chunks.copy()
122
122
  chunks_copy[0] = deepcopy(chunks_copy[0]) # _concat_chunks mutates first argument
@@ -1,6 +1,6 @@
1
1
  from rich import box
2
- from rich.console import Console
3
2
  from rich.table import Table
3
+ from rich.console import Console
4
4
 
5
5
  console = Console()
6
6
 
@@ -5,8 +5,13 @@ Provides debugging setup functionality that can be used across different compone
5
5
  """
6
6
 
7
7
  import os
8
+
8
9
  import debugpy # type: ignore
9
10
 
11
+ from agentex.lib.utils.logging import make_logger
12
+
13
+ logger = make_logger(__name__)
14
+
10
15
 
11
16
  def setup_debug_if_enabled() -> None:
12
17
  """
@@ -33,14 +38,14 @@ def setup_debug_if_enabled() -> None:
33
38
  debugpy.configure(subProcess=False)
34
39
  debugpy.listen(debug_port)
35
40
 
36
- print(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
37
-
41
+ logger.info(f"🐛 [{debug_type.upper()}] Debug server listening on port {debug_port}")
42
+
38
43
  if wait_for_attach:
39
- print(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
44
+ logger.info(f"⏳ [{debug_type.upper()}] Waiting for debugger to attach...")
40
45
  debugpy.wait_for_client()
41
- print(f"✅ [{debug_type.upper()}] Debugger attached!")
46
+ logger.info(f"✅ [{debug_type.upper()}] Debugger attached!")
42
47
  else:
43
- print(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
48
+ logger.info(f"📡 [{debug_type.upper()}] Ready for debugger attachment")
44
49
 
45
50
 
46
51
  def is_debug_enabled() -> bool:
@@ -6,26 +6,25 @@ to new streaming messages, handling mid-stream connections gracefully.
6
6
  """
7
7
 
8
8
  import json
9
- from datetime import datetime, timezone
10
9
  from typing import List, Optional
10
+ from datetime import datetime, timezone
11
11
 
12
- from yaspin.core import Yaspin
12
+ from yaspin import yaspin # type: ignore[import-untyped]
13
+ from rich.panel import Panel
14
+ from yaspin.core import Yaspin # type: ignore[import-untyped]
15
+ from rich.console import Console
16
+ from rich.markdown import Markdown
13
17
 
14
18
  from agentex import Agentex
15
- from agentex.types import Task, TaskMessage, TextContent, ToolRequestContent, ToolResponseContent, ReasoningContent
19
+ from agentex.types import Task, TaskMessage, TextContent, ReasoningContent, ToolRequestContent, ToolResponseContent
20
+ from agentex.types.text_delta import TextDelta
16
21
  from agentex.types.task_message_update import (
17
22
  TaskMessageUpdate,
18
- StreamTaskMessageStart,
19
- StreamTaskMessageDelta,
23
+ StreamTaskMessageDone,
20
24
  StreamTaskMessageFull,
21
- StreamTaskMessageDone
25
+ StreamTaskMessageDelta,
26
+ StreamTaskMessageStart,
22
27
  )
23
- from agentex.types.text_delta import TextDelta
24
-
25
- from rich.console import Console
26
- from rich.panel import Panel
27
- from rich.markdown import Markdown
28
- from yaspin import yaspin
29
28
 
30
29
 
31
30
  def print_task_message(
@@ -1,5 +1,5 @@
1
- from collections.abc import AsyncGenerator
2
1
  from typing import Any
2
+ from collections.abc import AsyncGenerator
3
3
 
4
4
 
5
5
  async def async_enumerate(
@@ -10,10 +10,10 @@ def resolve_refs(schema: dict) -> dict:
10
10
  """
11
11
  resolved = jsonref.replace_refs(schema, proxies=False, lazy_load=False)
12
12
  serializable = {
13
- "type": resolved.get("type"),
14
- "properties": resolved.get("properties"),
15
- "required": list(resolved.get("required", [])),
16
- "additionalProperties": resolved.get("additionalProperties", False),
13
+ "type": resolved.get("type"), # type: ignore[union-attr]
14
+ "properties": resolved.get("properties"), # type: ignore[union-attr]
15
+ "required": list(resolved.get("required", [])), # type: ignore[union-attr]
16
+ "additionalProperties": resolved.get("additionalProperties", False), # type: ignore[union-attr]
17
17
  }
18
18
  return serializable
19
19
 
@@ -1,31 +1,79 @@
1
+ import os
1
2
  import logging
3
+ import contextvars
2
4
 
5
+ import ddtrace
6
+ import json_log_formatter
3
7
  from rich.console import Console
4
8
  from rich.logging import RichHandler
5
9
 
10
+ _is_datadog_configured = bool(os.environ.get("DD_AGENT_HOST"))
6
11
 
7
- def make_logger(name: str):
12
+ ctx_var_request_id = contextvars.ContextVar[str]("request_id")
13
+
14
+
15
+ class CustomJSONFormatter(json_log_formatter.JSONFormatter):
16
+ def json_record(self, message: str, extra: dict, record: logging.LogRecord) -> dict: # type: ignore[override]
17
+ extra = super().json_record(message, extra, record)
18
+ extra["level"] = record.levelname
19
+ extra["name"] = record.name
20
+ extra["lineno"] = record.lineno
21
+ extra["pathname"] = record.pathname
22
+ extra["request_id"] = ctx_var_request_id.get(None)
23
+ if _is_datadog_configured:
24
+ extra["dd.trace_id"] = ddtrace.tracer.get_log_correlation_context().get("dd.trace_id", None) or getattr( # type: ignore[attr-defined]
25
+ record, "dd.trace_id", 0
26
+ )
27
+ extra["dd.span_id"] = ddtrace.tracer.get_log_correlation_context().get("dd.span_id", None) or getattr( # type: ignore[attr-defined]
28
+ record, "dd.span_id", 0
29
+ )
30
+ # add the env, service, and version configured for the tracer
31
+ # If tracing is not set up, then this should pull values from DD_ENV, DD_SERVICE, and DD_VERSION.
32
+ service_override = ddtrace.config.service or os.getenv("DD_SERVICE")
33
+ if service_override:
34
+ extra["dd.service"] = service_override
35
+
36
+ env_override = ddtrace.config.env or os.getenv("DD_ENV")
37
+ if env_override:
38
+ extra["dd.env"] = env_override
39
+
40
+ version_override = ddtrace.config.version or os.getenv("DD_VERSION")
41
+ if version_override:
42
+ extra["dd.version"] = version_override
43
+
44
+ return extra
45
+
46
+ def make_logger(name: str) -> logging.Logger:
8
47
  """
9
48
  Creates a logger object with a RichHandler to print colored text.
10
49
  :param name: The name of the module to create the logger for.
11
50
  :return: A logger object.
12
51
  """
13
52
  # Create a console object to print colored text
14
- console = Console()
15
-
16
- # Create a logger object with the name of the current module
17
53
  logger = logging.getLogger(name)
18
-
19
- # Set the global log level to INFO
20
54
  logger.setLevel(logging.INFO)
21
55
 
22
- # Add the RichHandler to the logger to print colored text
23
- handler = RichHandler(
24
- console=console,
25
- show_level=False,
26
- show_path=False,
27
- show_time=False,
28
- )
29
- logger.addHandler(handler)
56
+ environment = os.getenv("ENVIRONMENT")
57
+ if environment == "local":
58
+ console = Console()
59
+ # Add the RichHandler to the logger to print colored text
60
+ handler = RichHandler(
61
+ console=console,
62
+ show_level=False,
63
+ show_path=False,
64
+ show_time=False,
65
+ )
66
+ logger.addHandler(handler)
67
+ return logger
30
68
 
69
+ stream_handler = logging.StreamHandler()
70
+ if _is_datadog_configured:
71
+ stream_handler.setFormatter(CustomJSONFormatter())
72
+ else:
73
+ stream_handler.setFormatter(
74
+ logging.Formatter("%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] - %(message)s")
75
+ )
76
+
77
+ logger.addHandler(stream_handler)
78
+ # Create a logger object with the name of the current module
31
79
  return logger
agentex/lib/utils/mcp.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from typing import Any
2
+
2
3
  from mcp import StdioServerParameters
3
4
 
4
5
 
@@ -1,9 +1,8 @@
1
- from collections.abc import Iterable, Mapping
2
- from datetime import datetime
3
1
  from typing import Any, TypeVar
2
+ from datetime import datetime
3
+ from collections.abc import Mapping, Iterable
4
4
 
5
- from pydantic import BaseModel as PydanticBaseModel
6
- from pydantic import ConfigDict
5
+ from pydantic import BaseModel as PydanticBaseModel, ConfigDict
7
6
 
8
7
  from agentex.lib.utils.io import load_yaml_file
9
8
 
@@ -28,7 +27,7 @@ class BaseModel(PydanticBaseModel):
28
27
  def to_json(self, *args, **kwargs) -> str:
29
28
  return self.model_dump_json(*args, **kwargs)
30
29
 
31
- def to_dict(self, *args, **kwargs) -> dict[str, Any]:
30
+ def to_dict(self, *_args, **_kwargs) -> dict[str, Any]:
32
31
  return recursive_model_dump(self)
33
32
 
34
33
 
@@ -1,11 +1,12 @@
1
- import base64
2
- import json
3
1
  import os
4
- import httpx
2
+ import json
3
+ import base64
5
4
  import asyncio
6
5
 
7
- from agentex.lib.environment_variables import EnvironmentVariables, refreshed_environment_variables
6
+ import httpx
7
+
8
8
  from agentex.lib.utils.logging import make_logger
9
+ from agentex.lib.environment_variables import EnvironmentVariables
9
10
 
10
11
  logger = make_logger(__name__)
11
12
 
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import json
6
- from typing import AsyncGenerator, Generator, Union, Optional
6
+ from typing import Union, Optional, Generator, AsyncGenerator
7
7
  from typing_extensions import Literal
8
8
 
9
9
  import httpx
@@ -22,7 +22,14 @@ from .._response import (
22
22
  )
23
23
  from ..types.agent import Agent
24
24
  from .._base_client import make_request_options
25
- from ..types.agent_rpc_response import AgentRpcResponse, CancelTaskResponse, CreateTaskResponse, SendEventResponse, SendMessageResponse, SendMessageStreamResponse
25
+ from ..types.agent_rpc_response import (
26
+ AgentRpcResponse,
27
+ SendEventResponse,
28
+ CancelTaskResponse,
29
+ CreateTaskResponse,
30
+ SendMessageResponse,
31
+ SendMessageStreamResponse,
32
+ )
26
33
  from ..types.agent_list_response import AgentListResponse
27
34
  from ..types.shared.delete_response import DeleteResponse
28
35
 
@@ -1074,8 +1081,8 @@ class AsyncAgentsResource(AsyncAPIResource):
1074
1081
  except json.JSONDecodeError:
1075
1082
  # Skip invalid JSON lines
1076
1083
  continue
1077
- except ValidationError:
1078
- raise ValueError(f"Invalid SendMessageStreamResponse returned: {line}")
1084
+ except ValidationError as e:
1085
+ raise ValueError(f"Invalid SendMessageStreamResponse returned: {line}") from e
1079
1086
 
1080
1087
  async def send_event(
1081
1088
  self,
@@ -3,11 +3,11 @@
3
3
  from typing import Union, Optional
4
4
  from typing_extensions import Literal
5
5
 
6
- from .._models import BaseModel
7
- from .agent_rpc_result import AgentRpcResult
8
- from .event import Event
9
6
  from .task import Task
7
+ from .event import Event
8
+ from .._models import BaseModel
10
9
  from .task_message import TaskMessage
10
+ from .agent_rpc_result import AgentRpcResult
11
11
  from .task_message_update import TaskMessageUpdate
12
12
 
13
13
  __all__ = ["AgentRpcResponse"]
@@ -1,6 +1,6 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- from typing import Dict, Optional
3
+ from typing import Dict
4
4
  from typing_extensions import Literal
5
5
 
6
6
  from .._models import BaseModel
@@ -1,6 +1,6 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- from typing import Dict, Optional
3
+ from typing import Dict
4
4
  from typing_extensions import Literal
5
5
 
6
6
  from .._models import BaseModel
@@ -1,6 +1,5 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
- from typing import Optional
4
3
  from typing_extensions import Literal
5
4
 
6
5
  from .._models import BaseModel
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: agentex-sdk
3
- Version: 0.4.18
3
+ Version: 0.4.20
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
@@ -22,11 +22,14 @@ Requires-Python: <4,>=3.12
22
22
  Requires-Dist: aiohttp<4,>=3.10.10
23
23
  Requires-Dist: anyio<5,>=3.5.0
24
24
  Requires-Dist: cloudpickle>=3.1.1
25
+ Requires-Dist: datadog>=0.52.1
26
+ Requires-Dist: ddtrace>=3.13.0
25
27
  Requires-Dist: distro<2,>=1.7.0
26
28
  Requires-Dist: fastapi<0.116,>=0.115.0
27
29
  Requires-Dist: httpx<0.28,>=0.27.2
28
30
  Requires-Dist: ipykernel>=6.29.5
29
31
  Requires-Dist: jinja2<4,>=3.1.3
32
+ Requires-Dist: json-log-formatter>=1.1.1
30
33
  Requires-Dist: jsonref<2,>=1.1.0
31
34
  Requires-Dist: jsonschema<5,>=4.23.0
32
35
  Requires-Dist: kubernetes<29.0.0,>=25.0.0