agentex-sdk 0.4.6__py3-none-any.whl → 0.4.8__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/cli/templates/sync/project/acp.py.j2 +1 -1
- agentex/lib/core/services/adk/acp/acp.py +12 -5
- agentex/lib/core/services/adk/messages.py +1 -1
- agentex/lib/core/services/adk/providers/litellm.py +6 -3
- agentex/lib/core/services/adk/providers/openai.py +146 -43
- agentex/lib/core/services/adk/streaming.py +72 -15
- agentex/lib/core/temporal/activities/adk/streaming_activities.py +1 -1
- agentex/lib/sdk/fastacp/base/base_acp_server.py +2 -2
- agentex/lib/sdk/fastacp/impl/sync_acp.py +2 -2
- agentex/lib/utils/dev_tools/async_messages.py +32 -1
- {agentex_sdk-0.4.6.dist-info → agentex_sdk-0.4.8.dist-info}/METADATA +1 -1
- {agentex_sdk-0.4.6.dist-info → agentex_sdk-0.4.8.dist-info}/RECORD +16 -17
- agentex/lib/types/task_message_updates.py +0 -171
- {agentex_sdk-0.4.6.dist-info → agentex_sdk-0.4.8.dist-info}/WHEEL +0 -0
- {agentex_sdk-0.4.6.dist-info → agentex_sdk-0.4.8.dist-info}/entry_points.txt +0 -0
- {agentex_sdk-0.4.6.dist-info → agentex_sdk-0.4.8.dist-info}/licenses/LICENSE +0 -0
agentex/_version.py
CHANGED
@@ -2,7 +2,7 @@ from typing import AsyncGenerator, Union
|
|
2
2
|
from agentex.lib.sdk.fastacp.fastacp import FastACP
|
3
3
|
from agentex.lib.types.acp import SendMessageParams
|
4
4
|
|
5
|
-
from agentex.
|
5
|
+
from agentex.types.task_message_update import TaskMessageUpdate
|
6
6
|
from agentex.types.task_message_content import TaskMessageContent
|
7
7
|
from agentex.types.text_content import TextContent
|
8
8
|
from agentex.lib.utils.logging import make_logger
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Any, cast
|
1
|
+
from typing import Any, List, cast
|
2
2
|
|
3
3
|
from agentex import AsyncAgentex
|
4
4
|
from agentex.lib.core.tracing.tracer import AsyncTracer
|
@@ -78,7 +78,7 @@ class ACPService:
|
|
78
78
|
task_name: str | None = None,
|
79
79
|
trace_id: str | None = None,
|
80
80
|
parent_span_id: str | None = None,
|
81
|
-
) -> TaskMessage:
|
81
|
+
) -> List[TaskMessage]:
|
82
82
|
trace = self._tracer.trace(trace_id=trace_id)
|
83
83
|
async with trace.span(
|
84
84
|
parent_id=parent_span_id,
|
@@ -115,10 +115,17 @@ class ACPService:
|
|
115
115
|
else:
|
116
116
|
raise ValueError("Either agent_name or agent_id must be provided")
|
117
117
|
|
118
|
-
|
118
|
+
task_messages: List[TaskMessage] = []
|
119
|
+
if isinstance(json_rpc_response.result, list):
|
120
|
+
for message in json_rpc_response.result:
|
121
|
+
task_message = TaskMessage.model_validate(message)
|
122
|
+
task_messages.append(task_message)
|
123
|
+
else:
|
124
|
+
task_messages = [TaskMessage.model_validate(json_rpc_response.result)]
|
125
|
+
|
119
126
|
if span:
|
120
|
-
span.output = task_message.model_dump()
|
121
|
-
return
|
127
|
+
span.output = [task_message.model_dump() for task_message in task_messages]
|
128
|
+
return task_messages
|
122
129
|
|
123
130
|
async def event_send(
|
124
131
|
self,
|
@@ -4,7 +4,7 @@ from typing import Any, Coroutine, cast
|
|
4
4
|
from agentex import AsyncAgentex
|
5
5
|
from agentex.lib.core.services.adk.streaming import StreamingService
|
6
6
|
from agentex.lib.core.tracing.tracer import AsyncTracer
|
7
|
-
from agentex.
|
7
|
+
from agentex.types.task_message_update import StreamTaskMessageFull, TaskMessageUpdate
|
8
8
|
from agentex.types.task_message import TaskMessage, TaskMessageContent
|
9
9
|
from agentex.lib.utils.logging import make_logger
|
10
10
|
from agentex.lib.utils.temporal import heartbeat_if_in_workflow
|
@@ -8,11 +8,11 @@ from agentex.lib.types.llm_messages import (
|
|
8
8
|
Completion,
|
9
9
|
LLMConfig,
|
10
10
|
)
|
11
|
-
from agentex.
|
11
|
+
from agentex.types.task_message_update import (
|
12
12
|
StreamTaskMessageDelta,
|
13
13
|
StreamTaskMessageFull,
|
14
|
-
TextDelta,
|
15
14
|
)
|
15
|
+
from agentex.types.task_message_delta import TextDelta
|
16
16
|
from agentex.types.task_message import TaskMessage
|
17
17
|
from agentex.types.task_message_content import TextContent
|
18
18
|
from agentex.lib.utils import logging
|
@@ -112,6 +112,7 @@ class LiteLLMService:
|
|
112
112
|
update=StreamTaskMessageFull(
|
113
113
|
parent_task_message=streaming_context.task_message,
|
114
114
|
content=final_content,
|
115
|
+
type="full",
|
115
116
|
),
|
116
117
|
)
|
117
118
|
else:
|
@@ -221,7 +222,8 @@ class LiteLLMService:
|
|
221
222
|
await streaming_context.stream_update(
|
222
223
|
update=StreamTaskMessageDelta(
|
223
224
|
parent_task_message=streaming_context.task_message,
|
224
|
-
delta=TextDelta(text_delta=delta),
|
225
|
+
delta=TextDelta(text_delta=delta, type="text"),
|
226
|
+
type="delta",
|
225
227
|
),
|
226
228
|
)
|
227
229
|
heartbeat_if_in_workflow("content chunk streamed")
|
@@ -244,6 +246,7 @@ class LiteLLMService:
|
|
244
246
|
update=StreamTaskMessageFull(
|
245
247
|
parent_task_message=streaming_context.task_message,
|
246
248
|
content=final_content,
|
249
|
+
type="full",
|
247
250
|
),
|
248
251
|
)
|
249
252
|
|
@@ -11,7 +11,12 @@ from openai.types.responses import (
|
|
11
11
|
ResponseCompletedEvent,
|
12
12
|
ResponseFunctionToolCall,
|
13
13
|
ResponseOutputItemDoneEvent,
|
14
|
+
ResponseReasoningSummaryPartDoneEvent,
|
14
15
|
ResponseTextDeltaEvent,
|
16
|
+
ResponseReasoningSummaryTextDeltaEvent,
|
17
|
+
ResponseReasoningSummaryTextDoneEvent,
|
18
|
+
ResponseReasoningTextDeltaEvent,
|
19
|
+
ResponseReasoningTextDoneEvent,
|
15
20
|
)
|
16
21
|
from pydantic import BaseModel
|
17
22
|
|
@@ -22,14 +27,18 @@ from agentex.lib.core.services.adk.streaming import (
|
|
22
27
|
StreamingTaskMessageContext,
|
23
28
|
)
|
24
29
|
from agentex.lib.core.tracing.tracer import AsyncTracer
|
25
|
-
from agentex.
|
30
|
+
from agentex.types.task_message_update import (
|
26
31
|
StreamTaskMessageDelta,
|
27
32
|
StreamTaskMessageFull,
|
33
|
+
)
|
34
|
+
from agentex.types.task_message_delta import (
|
28
35
|
TextDelta,
|
36
|
+
ReasoningSummaryDelta,
|
37
|
+
ReasoningContentDelta,
|
29
38
|
)
|
30
39
|
from agentex.types.task_message_content import (
|
31
|
-
TextContent,
|
32
40
|
ReasoningContent,
|
41
|
+
TextContent,
|
33
42
|
ToolRequestContent,
|
34
43
|
ToolResponseContent,
|
35
44
|
)
|
@@ -317,6 +326,7 @@ class OpenAIService:
|
|
317
326
|
update=StreamTaskMessageFull(
|
318
327
|
parent_task_message=streaming_context.task_message,
|
319
328
|
content=text_content,
|
329
|
+
type="full",
|
320
330
|
),
|
321
331
|
)
|
322
332
|
|
@@ -341,6 +351,7 @@ class OpenAIService:
|
|
341
351
|
update=StreamTaskMessageFull(
|
342
352
|
parent_task_message=streaming_context.task_message,
|
343
353
|
content=tool_request_content,
|
354
|
+
type="full",
|
344
355
|
),
|
345
356
|
)
|
346
357
|
|
@@ -357,13 +368,14 @@ class OpenAIService:
|
|
357
368
|
async with (
|
358
369
|
self.streaming_service.streaming_task_message_context(
|
359
370
|
task_id=task_id,
|
360
|
-
initial_content=tool_response_content
|
371
|
+
initial_content=tool_response_content
|
361
372
|
) as streaming_context
|
362
373
|
):
|
363
374
|
await streaming_context.stream_update(
|
364
375
|
update=StreamTaskMessageFull(
|
365
376
|
parent_task_message=streaming_context.task_message,
|
366
377
|
content=tool_response_content,
|
378
|
+
type="full",
|
367
379
|
),
|
368
380
|
)
|
369
381
|
|
@@ -619,6 +631,7 @@ class OpenAIService:
|
|
619
631
|
update=StreamTaskMessageFull(
|
620
632
|
parent_task_message=streaming_context.task_message,
|
621
633
|
content=tool_request_content,
|
634
|
+
type="full",
|
622
635
|
),
|
623
636
|
)
|
624
637
|
|
@@ -638,7 +651,7 @@ class OpenAIService:
|
|
638
651
|
async with (
|
639
652
|
self.streaming_service.streaming_task_message_context(
|
640
653
|
task_id=task_id,
|
641
|
-
initial_content=tool_response_content
|
654
|
+
initial_content=tool_response_content
|
642
655
|
) as streaming_context
|
643
656
|
):
|
644
657
|
# The message has already been persisted, but we still need to send an update
|
@@ -646,33 +659,7 @@ class OpenAIService:
|
|
646
659
|
update=StreamTaskMessageFull(
|
647
660
|
parent_task_message=streaming_context.task_message,
|
648
661
|
content=tool_response_content,
|
649
|
-
|
650
|
-
)
|
651
|
-
|
652
|
-
elif event.item.type == "reasoning_item":
|
653
|
-
# Handle reasoning items
|
654
|
-
reasoning_item = event.item.raw_item
|
655
|
-
|
656
|
-
reasoning_content = ReasoningContent(
|
657
|
-
author="agent",
|
658
|
-
style="static",
|
659
|
-
summary=[summary.text for summary in reasoning_item.summary],
|
660
|
-
content=[content.text for content in reasoning_item.content] if hasattr(reasoning_item, "content") and reasoning_item.content else None,
|
661
|
-
type="reasoning",
|
662
|
-
)
|
663
|
-
|
664
|
-
# Create reasoning content using streaming context (immediate completion)
|
665
|
-
async with (
|
666
|
-
self.streaming_service.streaming_task_message_context(
|
667
|
-
task_id=task_id,
|
668
|
-
initial_content=reasoning_content,
|
669
|
-
) as streaming_context
|
670
|
-
):
|
671
|
-
# The message has already been persisted, but we still need to send an update
|
672
|
-
await streaming_context.stream_update(
|
673
|
-
update=StreamTaskMessageFull(
|
674
|
-
parent_task_message=streaming_context.task_message,
|
675
|
-
content=reasoning_content,
|
662
|
+
type="full",
|
676
663
|
),
|
677
664
|
)
|
678
665
|
|
@@ -705,10 +692,117 @@ class OpenAIService:
|
|
705
692
|
await streaming_context.stream_update(
|
706
693
|
update=StreamTaskMessageDelta(
|
707
694
|
parent_task_message=streaming_context.task_message,
|
708
|
-
delta=TextDelta(text_delta=event.data.delta),
|
695
|
+
delta=TextDelta(text_delta=event.data.delta, type="text"),
|
696
|
+
type="delta",
|
697
|
+
),
|
698
|
+
)
|
699
|
+
|
700
|
+
elif isinstance(event.data, ResponseReasoningSummaryTextDeltaEvent):
|
701
|
+
# Handle reasoning summary text delta
|
702
|
+
item_id = event.data.item_id
|
703
|
+
summary_index = event.data.summary_index
|
704
|
+
|
705
|
+
# Check if we already have a streaming context for this reasoning item
|
706
|
+
if item_id not in item_id_to_streaming_context:
|
707
|
+
# Create a new streaming context for this reasoning item
|
708
|
+
streaming_context = self.streaming_service.streaming_task_message_context(
|
709
|
+
task_id=task_id,
|
710
|
+
initial_content=ReasoningContent(
|
711
|
+
author="agent",
|
712
|
+
summary=[],
|
713
|
+
content=[],
|
714
|
+
type="reasoning",
|
715
|
+
style="active",
|
716
|
+
),
|
717
|
+
)
|
718
|
+
# Open the streaming context
|
719
|
+
item_id_to_streaming_context[
|
720
|
+
item_id
|
721
|
+
] = await streaming_context.open()
|
722
|
+
unclosed_item_ids.add(item_id)
|
723
|
+
else:
|
724
|
+
streaming_context = item_id_to_streaming_context[
|
725
|
+
item_id
|
726
|
+
]
|
727
|
+
|
728
|
+
# Stream the summary delta through the streaming service
|
729
|
+
await streaming_context.stream_update(
|
730
|
+
update=StreamTaskMessageDelta(
|
731
|
+
parent_task_message=streaming_context.task_message,
|
732
|
+
delta=ReasoningSummaryDelta(
|
733
|
+
summary_index=summary_index,
|
734
|
+
summary_delta=event.data.delta,
|
735
|
+
type="reasoning_summary",
|
736
|
+
),
|
737
|
+
type="delta",
|
738
|
+
),
|
739
|
+
)
|
740
|
+
|
741
|
+
elif isinstance(event.data, ResponseReasoningTextDeltaEvent):
|
742
|
+
# Handle reasoning content text delta
|
743
|
+
item_id = event.data.item_id
|
744
|
+
content_index = event.data.content_index
|
745
|
+
|
746
|
+
# Check if we already have a streaming context for this reasoning item
|
747
|
+
if item_id not in item_id_to_streaming_context:
|
748
|
+
# Create a new streaming context for this reasoning item
|
749
|
+
streaming_context = self.streaming_service.streaming_task_message_context(
|
750
|
+
task_id=task_id,
|
751
|
+
initial_content=ReasoningContent(
|
752
|
+
author="agent",
|
753
|
+
summary=[],
|
754
|
+
content=[],
|
755
|
+
type="reasoning",
|
756
|
+
style="active",
|
757
|
+
),
|
758
|
+
)
|
759
|
+
# Open the streaming context
|
760
|
+
item_id_to_streaming_context[
|
761
|
+
item_id
|
762
|
+
] = await streaming_context.open()
|
763
|
+
unclosed_item_ids.add(item_id)
|
764
|
+
else:
|
765
|
+
streaming_context = item_id_to_streaming_context[
|
766
|
+
item_id
|
767
|
+
]
|
768
|
+
|
769
|
+
# Stream the content delta through the streaming service
|
770
|
+
await streaming_context.stream_update(
|
771
|
+
update=StreamTaskMessageDelta(
|
772
|
+
parent_task_message=streaming_context.task_message,
|
773
|
+
delta=ReasoningContentDelta(
|
774
|
+
content_index=content_index,
|
775
|
+
content_delta=event.data.delta,
|
776
|
+
type="reasoning_content",
|
777
|
+
),
|
778
|
+
type="delta",
|
709
779
|
),
|
710
780
|
)
|
711
781
|
|
782
|
+
elif isinstance(event.data, ResponseReasoningSummaryTextDoneEvent):
|
783
|
+
# Handle reasoning summary text completion
|
784
|
+
item_id = event.data.item_id
|
785
|
+
summary_index = event.data.summary_index
|
786
|
+
|
787
|
+
# We do NOT close the streaming context here as there can be multiple
|
788
|
+
# reasoning summaries. The context will be closed when the entire
|
789
|
+
# output item is done (ResponseOutputItemDoneEvent)
|
790
|
+
|
791
|
+
# You would think they would use the event ResponseReasoningSummaryPartDoneEvent
|
792
|
+
# to close the streaming context, but they do!!!
|
793
|
+
# They output both a ResponseReasoningSummaryTextDoneEvent and a ResponseReasoningSummaryPartDoneEvent
|
794
|
+
# I have no idea why they do this.
|
795
|
+
|
796
|
+
elif isinstance(event.data, ResponseReasoningTextDoneEvent):
|
797
|
+
# Handle reasoning content text completion
|
798
|
+
item_id = event.data.item_id
|
799
|
+
content_index = event.data.content_index
|
800
|
+
|
801
|
+
# We do NOT close the streaming context here as there can be multiple
|
802
|
+
# reasoning content texts. The context will be closed when the entire
|
803
|
+
# output item is done (ResponseOutputItemDoneEvent)
|
804
|
+
|
805
|
+
|
712
806
|
elif isinstance(event.data, ResponseOutputItemDoneEvent):
|
713
807
|
# Handle item completion
|
714
808
|
item_id = event.data.item.id
|
@@ -719,23 +813,32 @@ class OpenAIService:
|
|
719
813
|
item_id
|
720
814
|
]
|
721
815
|
await streaming_context.close()
|
722
|
-
unclosed_item_ids
|
816
|
+
if item_id in unclosed_item_ids:
|
817
|
+
unclosed_item_ids.remove(item_id)
|
723
818
|
|
724
819
|
elif isinstance(event.data, ResponseCompletedEvent):
|
725
820
|
# All items complete, finish all remaining streaming contexts for this session
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
821
|
+
# Create a copy to avoid modifying set during iteration
|
822
|
+
remaining_items = list(unclosed_item_ids)
|
823
|
+
for item_id in remaining_items:
|
824
|
+
if (item_id in unclosed_item_ids and
|
825
|
+
item_id in item_id_to_streaming_context): # Check if still unclosed
|
826
|
+
streaming_context = item_id_to_streaming_context[
|
827
|
+
item_id
|
828
|
+
]
|
829
|
+
await streaming_context.close()
|
830
|
+
unclosed_item_ids.discard(item_id)
|
732
831
|
|
733
832
|
finally:
|
734
833
|
# Cleanup: ensure all streaming contexts for this session are properly finished
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
834
|
+
# Create a copy to avoid modifying set during iteration
|
835
|
+
remaining_items = list(unclosed_item_ids)
|
836
|
+
for item_id in remaining_items:
|
837
|
+
if (item_id in unclosed_item_ids and
|
838
|
+
item_id in item_id_to_streaming_context): # Check if still unclosed
|
839
|
+
streaming_context = item_id_to_streaming_context[item_id]
|
840
|
+
await streaming_context.close()
|
841
|
+
unclosed_item_ids.discard(item_id)
|
739
842
|
|
740
843
|
if span:
|
741
844
|
span.output = {
|
@@ -1,21 +1,24 @@
|
|
1
1
|
import json
|
2
|
-
from typing import Literal
|
2
|
+
from typing import Literal
|
3
3
|
|
4
4
|
from agentex import AsyncAgentex
|
5
5
|
from agentex.lib.core.adapters.streams.port import StreamRepository
|
6
|
-
from agentex.
|
6
|
+
from agentex.types.task_message_update import (
|
7
7
|
TaskMessageDelta,
|
8
8
|
TaskMessageUpdate,
|
9
|
-
TextDelta,
|
10
|
-
DataDelta,
|
11
|
-
ToolRequestDelta,
|
12
|
-
ToolResponseDelta,
|
13
|
-
StreamTaskMessage,
|
14
9
|
StreamTaskMessageStart,
|
15
10
|
StreamTaskMessageDelta,
|
16
11
|
StreamTaskMessageFull,
|
17
12
|
StreamTaskMessageDone,
|
18
13
|
)
|
14
|
+
from agentex.types.task_message_delta import (
|
15
|
+
TextDelta,
|
16
|
+
DataDelta,
|
17
|
+
ToolRequestDelta,
|
18
|
+
ToolResponseDelta,
|
19
|
+
ReasoningSummaryDelta,
|
20
|
+
ReasoningContentDelta,
|
21
|
+
)
|
19
22
|
from agentex.lib.utils.logging import make_logger
|
20
23
|
from agentex.types.data_content import DataContent
|
21
24
|
from agentex.types.task_message import (
|
@@ -25,6 +28,7 @@ from agentex.types.task_message import (
|
|
25
28
|
from agentex.types.text_content import TextContent
|
26
29
|
from agentex.types.tool_request_content import ToolRequestContent
|
27
30
|
from agentex.types.tool_response_content import ToolResponseContent
|
31
|
+
from agentex.types.reasoning_content import ReasoningContent
|
28
32
|
|
29
33
|
logger = make_logger(__name__)
|
30
34
|
|
@@ -36,7 +40,10 @@ def _get_stream_topic(task_id: str) -> str:
|
|
36
40
|
class DeltaAccumulator:
|
37
41
|
def __init__(self):
|
38
42
|
self._accumulated_deltas: list[TaskMessageDelta] = []
|
39
|
-
self._delta_type: Literal["text", "data", "tool_request", "tool_response"] | None = None
|
43
|
+
self._delta_type: Literal["text", "data", "tool_request", "tool_response", "reasoning"] | None = None
|
44
|
+
# For reasoning, we need to track both summary and content deltas
|
45
|
+
self._reasoning_summaries: dict[int, str] = {}
|
46
|
+
self._reasoning_contents: dict[int, str] = {}
|
40
47
|
|
41
48
|
def add_delta(self, delta: TaskMessageDelta):
|
42
49
|
if self._delta_type is None:
|
@@ -48,15 +55,35 @@ class DeltaAccumulator:
|
|
48
55
|
self._delta_type = "tool_request"
|
49
56
|
elif delta.type == "tool_response":
|
50
57
|
self._delta_type = "tool_response"
|
58
|
+
elif delta.type in ["reasoning_summary", "reasoning_content"]:
|
59
|
+
self._delta_type = "reasoning"
|
51
60
|
else:
|
52
61
|
raise ValueError(f"Unknown delta type: {delta.type}")
|
53
62
|
else:
|
54
|
-
|
63
|
+
# For reasoning, we allow both summary and content deltas
|
64
|
+
if self._delta_type == "reasoning":
|
65
|
+
if delta.type not in ["reasoning_summary", "reasoning_content"]:
|
66
|
+
raise ValueError(
|
67
|
+
f"Expected reasoning delta but got: {delta.type}"
|
68
|
+
)
|
69
|
+
elif self._delta_type != delta.type:
|
55
70
|
raise ValueError(
|
56
71
|
f"Delta type mismatch: {self._delta_type} != {delta.type}"
|
57
72
|
)
|
58
73
|
|
59
|
-
|
74
|
+
# Handle reasoning deltas specially
|
75
|
+
if delta.type == "reasoning_summary":
|
76
|
+
if isinstance(delta, ReasoningSummaryDelta):
|
77
|
+
if delta.summary_index not in self._reasoning_summaries:
|
78
|
+
self._reasoning_summaries[delta.summary_index] = ""
|
79
|
+
self._reasoning_summaries[delta.summary_index] += delta.summary_delta or ""
|
80
|
+
elif delta.type == "reasoning_content":
|
81
|
+
if isinstance(delta, ReasoningContentDelta):
|
82
|
+
if delta.content_index not in self._reasoning_contents:
|
83
|
+
self._reasoning_contents[delta.content_index] = ""
|
84
|
+
self._reasoning_contents[delta.content_index] += delta.content_delta or ""
|
85
|
+
else:
|
86
|
+
self._accumulated_deltas.append(delta)
|
60
87
|
|
61
88
|
def convert_to_content(self) -> TaskMessageContent:
|
62
89
|
if self._delta_type == "text":
|
@@ -107,7 +134,7 @@ class DeltaAccumulator:
|
|
107
134
|
# Type assertion: we know all deltas are ToolResponseDelta when _delta_type is TOOL_RESPONSE
|
108
135
|
tool_response_deltas = [delta for delta in self._accumulated_deltas if isinstance(delta, ToolResponseDelta)]
|
109
136
|
tool_response_content_str = "".join(
|
110
|
-
[delta.
|
137
|
+
[delta.content_delta or "" for delta in tool_response_deltas]
|
111
138
|
)
|
112
139
|
return ToolResponseContent(
|
113
140
|
author="agent",
|
@@ -115,6 +142,27 @@ class DeltaAccumulator:
|
|
115
142
|
name=tool_response_deltas[0].name,
|
116
143
|
content=tool_response_content_str,
|
117
144
|
)
|
145
|
+
elif self._delta_type == "reasoning":
|
146
|
+
# Convert accumulated reasoning deltas to ReasoningContent
|
147
|
+
# Sort by index to maintain order
|
148
|
+
summary_list = [self._reasoning_summaries[i] for i in sorted(self._reasoning_summaries.keys()) if self._reasoning_summaries[i]]
|
149
|
+
content_list = [self._reasoning_contents[i] for i in sorted(self._reasoning_contents.keys()) if self._reasoning_contents[i]]
|
150
|
+
|
151
|
+
# Only return reasoning content if we have non-empty summaries or content
|
152
|
+
if summary_list or content_list:
|
153
|
+
return ReasoningContent(
|
154
|
+
author="agent",
|
155
|
+
summary=summary_list,
|
156
|
+
content=content_list if content_list else None,
|
157
|
+
type="reasoning",
|
158
|
+
style="static",
|
159
|
+
)
|
160
|
+
else:
|
161
|
+
# Return empty text content instead of empty reasoning
|
162
|
+
return TextContent(
|
163
|
+
author="agent",
|
164
|
+
content="",
|
165
|
+
)
|
118
166
|
else:
|
119
167
|
raise ValueError(f"Unknown delta type: {self._delta_type}")
|
120
168
|
|
@@ -154,6 +202,7 @@ class StreamingTaskMessageContext:
|
|
154
202
|
start_event = StreamTaskMessageStart(
|
155
203
|
parent_task_message=self.task_message,
|
156
204
|
content=self.initial_content,
|
205
|
+
type="start",
|
157
206
|
)
|
158
207
|
await self._streaming_service.stream_update(start_event)
|
159
208
|
|
@@ -168,11 +217,19 @@ class StreamingTaskMessageContext:
|
|
168
217
|
return self.task_message # Already done
|
169
218
|
|
170
219
|
# Send the DONE event
|
171
|
-
done_event = StreamTaskMessageDone(
|
220
|
+
done_event = StreamTaskMessageDone(
|
221
|
+
parent_task_message=self.task_message,
|
222
|
+
type="done",
|
223
|
+
)
|
172
224
|
await self._streaming_service.stream_update(done_event)
|
173
225
|
|
174
226
|
# Update the task message with the final content
|
175
|
-
|
227
|
+
has_deltas = (
|
228
|
+
self._delta_accumulator._accumulated_deltas or
|
229
|
+
self._delta_accumulator._reasoning_summaries or
|
230
|
+
self._delta_accumulator._reasoning_contents
|
231
|
+
)
|
232
|
+
if has_deltas:
|
176
233
|
self.task_message.content = self._delta_accumulator.convert_to_content()
|
177
234
|
|
178
235
|
await self._agentex_client.messages.update(
|
@@ -187,8 +244,8 @@ class StreamingTaskMessageContext:
|
|
187
244
|
return self.task_message
|
188
245
|
|
189
246
|
async def stream_update(
|
190
|
-
self, update:
|
191
|
-
) ->
|
247
|
+
self, update: TaskMessageUpdate
|
248
|
+
) -> TaskMessageUpdate | None:
|
192
249
|
"""Stream an update to the repository."""
|
193
250
|
if self._is_closed:
|
194
251
|
raise ValueError("Context is already done")
|
@@ -3,7 +3,7 @@ from enum import Enum
|
|
3
3
|
from temporalio import activity
|
4
4
|
|
5
5
|
from agentex.lib.core.services.adk.streaming import StreamingService
|
6
|
-
from agentex.
|
6
|
+
from agentex.types.task_message_update import TaskMessageUpdate
|
7
7
|
from agentex.lib.utils.logging import make_logger
|
8
8
|
from agentex.lib.utils.model_utils import BaseModel
|
9
9
|
from agentex.lib.utils.temporal import heartbeat_if_in_workflow
|
@@ -21,7 +21,7 @@ from agentex.lib.types.acp import (
|
|
21
21
|
SendMessageParams,
|
22
22
|
)
|
23
23
|
from agentex.lib.types.json_rpc import JSONRPCError, JSONRPCRequest, JSONRPCResponse
|
24
|
-
from agentex.
|
24
|
+
from agentex.types.task_message_update import StreamTaskMessageFull, TaskMessageUpdate
|
25
25
|
from agentex.types.task_message_content import TaskMessageContent
|
26
26
|
from agentex.lib.utils.logging import make_logger
|
27
27
|
from agentex.lib.utils.model_utils import BaseModel
|
@@ -332,7 +332,7 @@ class BaseACPServer(FastAPI):
|
|
332
332
|
|
333
333
|
async def async_generator(task_message_content_list: list[TaskMessageContent]):
|
334
334
|
for i, task_message_content in enumerate(task_message_content_list):
|
335
|
-
yield StreamTaskMessageFull(index=i, content=task_message_content)
|
335
|
+
yield StreamTaskMessageFull(type="full", index=i, content=task_message_content)
|
336
336
|
|
337
337
|
return async_generator(task_message_content_list)
|
338
338
|
|
@@ -3,12 +3,12 @@ from typing import Any, override
|
|
3
3
|
|
4
4
|
from agentex.lib.sdk.fastacp.base.base_acp_server import BaseACPServer
|
5
5
|
from agentex.lib.types.acp import SendMessageParams
|
6
|
-
from agentex.
|
6
|
+
from agentex.types.task_message_update import (
|
7
7
|
StreamTaskMessageDelta,
|
8
8
|
StreamTaskMessageFull,
|
9
9
|
TaskMessageUpdate,
|
10
|
-
TextDelta,
|
11
10
|
)
|
11
|
+
from agentex.types.task_message_delta import TextDelta
|
12
12
|
from agentex.types.task_message_content import TaskMessageContent, TextContent
|
13
13
|
from agentex.lib.utils.logging import make_logger
|
14
14
|
|
@@ -12,7 +12,7 @@ from typing import List, Optional
|
|
12
12
|
from yaspin.core import Yaspin
|
13
13
|
|
14
14
|
from agentex import Agentex
|
15
|
-
from agentex.types import Task, TaskMessage, TextContent, ToolRequestContent, ToolResponseContent
|
15
|
+
from agentex.types import Task, TaskMessage, TextContent, ToolRequestContent, ToolResponseContent, ReasoningContent
|
16
16
|
from agentex.types.task_message_update import (
|
17
17
|
TaskMessageUpdate,
|
18
18
|
StreamTaskMessageStart,
|
@@ -48,6 +48,13 @@ def print_task_message(
|
|
48
48
|
if isinstance(message.content, TextContent) and not message.content.content.strip():
|
49
49
|
return
|
50
50
|
|
51
|
+
# Skip empty reasoning messages
|
52
|
+
if isinstance(message.content, ReasoningContent):
|
53
|
+
has_summary = message.content.summary and any(s for s in message.content.summary if s)
|
54
|
+
has_content = message.content.content and any(c for c in message.content.content if c)
|
55
|
+
if not has_summary and not has_content:
|
56
|
+
return
|
57
|
+
|
51
58
|
timestamp = message.created_at.strftime("%m/%d/%Y %H:%M:%S") if message.created_at else "N/A"
|
52
59
|
|
53
60
|
console = None
|
@@ -103,6 +110,26 @@ def print_task_message(
|
|
103
110
|
content = f"✅ **Tool Response: {tool_name}**\n\n{tool_response}"
|
104
111
|
|
105
112
|
content_type = "tool_response"
|
113
|
+
elif isinstance(message.content, ReasoningContent):
|
114
|
+
# Format reasoning content
|
115
|
+
reasoning_parts = []
|
116
|
+
|
117
|
+
# Add summary if available
|
118
|
+
if message.content.summary:
|
119
|
+
# Join summaries with double newline for better formatting
|
120
|
+
summary_text = "\n\n".join(s for s in message.content.summary if s)
|
121
|
+
if summary_text:
|
122
|
+
reasoning_parts.append(summary_text)
|
123
|
+
|
124
|
+
# Add full reasoning content if available
|
125
|
+
if message.content.content:
|
126
|
+
content_text = "\n\n".join(c for c in message.content.content if c)
|
127
|
+
if content_text:
|
128
|
+
reasoning_parts.append(content_text)
|
129
|
+
|
130
|
+
# Format reasoning content (we already checked it's not empty at the top)
|
131
|
+
content = "🧠 **Reasoning**\n\n" + "\n\n".join(reasoning_parts)
|
132
|
+
content_type = "reasoning"
|
106
133
|
else:
|
107
134
|
content = f"{type(message.content).__name__}: {message.content}"
|
108
135
|
content_type = "other"
|
@@ -116,6 +143,8 @@ def print_task_message(
|
|
116
143
|
border_style = "yellow"
|
117
144
|
elif content_type == "tool_response":
|
118
145
|
border_style = "bright_green"
|
146
|
+
elif content_type == "reasoning":
|
147
|
+
border_style = "bright_magenta"
|
119
148
|
else:
|
120
149
|
border_style = author_color
|
121
150
|
|
@@ -123,6 +152,8 @@ def print_task_message(
|
|
123
152
|
console.print(panel)
|
124
153
|
else:
|
125
154
|
title = f"{message.content.author.upper()} [{timestamp}]"
|
155
|
+
if content_type == "reasoning":
|
156
|
+
title = f"🧠 REASONING [{timestamp}]"
|
126
157
|
print(f"{title}\n{content}\n")
|
127
158
|
|
128
159
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: agentex-sdk
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.8
|
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
|
@@ -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=B50Ua8_D0D-KO2Gx_YEx60xydpxFLCIU8BwZh9UZhbY,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
|
@@ -83,7 +83,7 @@ agentex/lib/cli/templates/sync/environments.yaml.j2,sha256=BGprRPca_Y2sPA7kOiSK8
|
|
83
83
|
agentex/lib/cli/templates/sync/manifest.yaml.j2,sha256=V497KXzvA76sHrgIJ5zRJptpIH8sGbSXZaIsEyp5NZ4,3747
|
84
84
|
agentex/lib/cli/templates/sync/pyproject.toml.j2,sha256=eyN6dYqJTFzb5WztJMxboy9Wc0XPXVnKYaF5JBxJE7o,507
|
85
85
|
agentex/lib/cli/templates/sync/requirements.txt.j2,sha256=iTmO-z8qFkUa1jTctFCs0WYuq7Sqi6VNQAwATakh2fQ,94
|
86
|
-
agentex/lib/cli/templates/sync/project/acp.py.j2,sha256=
|
86
|
+
agentex/lib/cli/templates/sync/project/acp.py.j2,sha256=PUVXnN7IikBWYnfqLMgual-iXdl_benAjEfNcRADHBk,998
|
87
87
|
agentex/lib/cli/templates/temporal/.dockerignore.j2,sha256=hweGFxw5eDZYsb5EnRHpv27o9M1HF2PEWOxqsfBBcAE,320
|
88
88
|
agentex/lib/cli/templates/temporal/Dockerfile-uv.j2,sha256=_FNRUdE8m1jfcmYR3rZAAkm2mqyTCwUXbLs4dm4lZs8,1401
|
89
89
|
agentex/lib/cli/templates/temporal/Dockerfile.j2,sha256=N1Z73jb8pnxsjP9zbs-tSyNHO6usVzyOdtWorbR5gVY,1434
|
@@ -122,16 +122,16 @@ agentex/lib/core/services/adk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
122
122
|
agentex/lib/core/services/adk/agent_task_tracker.py,sha256=7HHxzTezx0FEmUlIcWusoXT0D91QVeggOKowIA919gI,2897
|
123
123
|
agentex/lib/core/services/adk/agents.py,sha256=MVklI4Ht8j8EAO18-0reLFRr6S5OIdEIymB1mU8FnKE,1446
|
124
124
|
agentex/lib/core/services/adk/events.py,sha256=gzhEfodEKk2bW5e1RJdrk2MW316U5VWdxMynhtFWgTA,1949
|
125
|
-
agentex/lib/core/services/adk/messages.py,sha256=
|
125
|
+
agentex/lib/core/services/adk/messages.py,sha256=pqIYaY11tmGOD8OnU3qoy5lk82AI1FgW5ShmfxidG_I,6042
|
126
126
|
agentex/lib/core/services/adk/state.py,sha256=O4hF7dj-uQP5VVeHmx37m36rmIlOwfQ2pL2ROndq7Zg,3830
|
127
|
-
agentex/lib/core/services/adk/streaming.py,sha256=
|
127
|
+
agentex/lib/core/services/adk/streaming.py,sha256=keZyy7CixM2_3tf2THv-X4gGOOSAk0mEKBk-WReBqJE,12406
|
128
128
|
agentex/lib/core/services/adk/tasks.py,sha256=XEX0u4skq81Fn-gjTzSE_-Iv_mKySZHchpotxAsnJwg,2618
|
129
129
|
agentex/lib/core/services/adk/tracing.py,sha256=w4mnIoq5m5iwlkDN_NOUjhi6hUpD958cYn1QR6hFgB8,1156
|
130
130
|
agentex/lib/core/services/adk/acp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
131
|
-
agentex/lib/core/services/adk/acp/acp.py,sha256=
|
131
|
+
agentex/lib/core/services/adk/acp/acp.py,sha256=4KeRPaka8GqnF2PQiNigcijgvQ_rf8Si0EoOdQNqjN4,7926
|
132
132
|
agentex/lib/core/services/adk/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
133
|
-
agentex/lib/core/services/adk/providers/litellm.py,sha256=
|
134
|
-
agentex/lib/core/services/adk/providers/openai.py,sha256=
|
133
|
+
agentex/lib/core/services/adk/providers/litellm.py,sha256=EKzus_xohNW-85V5hwvd1WqUd3ebv2wc9vDIWO2t1Mw,10044
|
134
|
+
agentex/lib/core/services/adk/providers/openai.py,sha256=Ad7iFQDg1iz8KjswO16lzjpzEJCz5FtyXV-fB6qMPLk,39535
|
135
135
|
agentex/lib/core/services/adk/providers/sgp.py,sha256=9gm-sPNQ_OSTaBzL0onerKhokPk_ZHndaKNO-z16wyQ,3676
|
136
136
|
agentex/lib/core/services/adk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
137
|
agentex/lib/core/services/adk/utils/templating.py,sha256=eaXSFq31Y9p5pRD6J6SL4QdTFtxy81dilbF2XXc2JYQ,1889
|
@@ -144,7 +144,7 @@ agentex/lib/core/temporal/activities/adk/agents_activities.py,sha256=q3PGgOLXvcE
|
|
144
144
|
agentex/lib/core/temporal/activities/adk/events_activities.py,sha256=60ygWk1aNG8Qf2IcnatXK1h86ZT32WCYkUAyRiM_p4c,1532
|
145
145
|
agentex/lib/core/temporal/activities/adk/messages_activities.py,sha256=fmiNOAt6Ov4nYzGGbkvDcSCMXPPTrsL66xSNud3_3RQ,3053
|
146
146
|
agentex/lib/core/temporal/activities/adk/state_activities.py,sha256=2YtAz7C2GMfyZGdp8wje1TvYjFGttdbLNAm9xSIbESA,2590
|
147
|
-
agentex/lib/core/temporal/activities/adk/streaming_activities.py,sha256=
|
147
|
+
agentex/lib/core/temporal/activities/adk/streaming_activities.py,sha256=PEXeFU9mNHbGoF3-kk4HNS53NX_MfdwI7LKWBl3--4c,1048
|
148
148
|
agentex/lib/core/temporal/activities/adk/tasks_activities.py,sha256=hQjdD-TfSzxsiW9eiJ5ZTvY0Ieu0tE950_Zk2PUVc9g,1442
|
149
149
|
agentex/lib/core/temporal/activities/adk/tracing_activities.py,sha256=RF8nSBA9x6Ui7_MD9He5ljlH_xZduIhx_JUTEyKdCxA,1523
|
150
150
|
agentex/lib/core/temporal/activities/adk/acp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -181,9 +181,9 @@ agentex/lib/sdk/config/project_config.py,sha256=CGH_r9KbnSFMj2CnBkZnfg41L2o0TeVN
|
|
181
181
|
agentex/lib/sdk/config/validation.py,sha256=QGAlAzlVJiWRlIksqxNS-JSwkk8Z4gXMSFUJc4qPrIQ,8989
|
182
182
|
agentex/lib/sdk/fastacp/__init__.py,sha256=UvAdexdnfb4z0F4a2sfXROFyh9EjH89kf3AxHPybzCM,75
|
183
183
|
agentex/lib/sdk/fastacp/fastacp.py,sha256=K4D7a9EiJfCgWp2hrE_TbpZBaF4Uc46MfndZK3F9mA0,3061
|
184
|
-
agentex/lib/sdk/fastacp/base/base_acp_server.py,sha256=
|
184
|
+
agentex/lib/sdk/fastacp/base/base_acp_server.py,sha256=vj7jPg8a8z07dTl3P-ZVTdhcuW3ulm4QrptWyYVnTAs,14598
|
185
185
|
agentex/lib/sdk/fastacp/impl/agentic_base_acp.py,sha256=LWLAlHrs-2Lc2UICBAEFL8c3JwTA6oxPnzUzW0qQWSA,2694
|
186
|
-
agentex/lib/sdk/fastacp/impl/sync_acp.py,sha256=
|
186
|
+
agentex/lib/sdk/fastacp/impl/sync_acp.py,sha256=0y_cYD-0UJOiVJv-BBMOt6PvElDf5zmc1uvbr81VcSI,3897
|
187
187
|
agentex/lib/sdk/fastacp/impl/temporal_acp.py,sha256=hQa_zGG6l_jIHNC75H_KXlPUuVqNBc-zIm-pmCDSZ6w,3759
|
188
188
|
agentex/lib/sdk/fastacp/tests/README.md,sha256=HejScemERLCs-wCgU3l1Xo4tcQ4gQy15GgoF-CkNh-0,8270
|
189
189
|
agentex/lib/sdk/fastacp/tests/conftest.py,sha256=wU3DCGZNBqY-HcJ4tz_tlphhS_5xGbZ6gSd72fGY2E0,9490
|
@@ -209,7 +209,6 @@ agentex/lib/types/fastacp.py,sha256=nU4rT823Ckix7bFwvVXtPsk6el3U1E4TH-OEvMqIBr4,
|
|
209
209
|
agentex/lib/types/files.py,sha256=sNxiuR_oEo7Z0YMqjQShErvS3txWyobrZzc4QMMM61U,320
|
210
210
|
agentex/lib/types/json_rpc.py,sha256=9sPADVEduOnyTm1yCS8vhZDfjMQVEdzqIWpycY_NrV8,1068
|
211
211
|
agentex/lib/types/llm_messages.py,sha256=eXsVJt_aQf3eGg_tPrDOPjFOhkbolb9IN1tU1c-IHYM,10668
|
212
|
-
agentex/lib/types/task_message_updates.py,sha256=jt9RUftr13sw0WbvdHOeK0Tidzdq-xfewx1AYqV8gtg,4298
|
213
212
|
agentex/lib/types/tracing.py,sha256=0YBdy3aKvxIcpOW0podEAqsFl3yEKW4PswNf-QnMNqo,731
|
214
213
|
agentex/lib/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
215
214
|
agentex/lib/utils/completions.py,sha256=m9TMwl9-nYK4DOQ8bNyj5YCFrxK3yN3zKvXmdINcIbo,4158
|
@@ -226,7 +225,7 @@ agentex/lib/utils/regex.py,sha256=Y3VcehCznAqa59D4WTwK_ki722oudHBlFqBk0I930zo,21
|
|
226
225
|
agentex/lib/utils/registration.py,sha256=FAL40KSMRCltHZcDtioGeRNgfB19Twqu6Srp4x7UMSU,3781
|
227
226
|
agentex/lib/utils/temporal.py,sha256=sXo8OPMMXiyrF7OSBCJBuN_ufyQOD2bLOXgDbVZoyds,292
|
228
227
|
agentex/lib/utils/dev_tools/__init__.py,sha256=oaHxw6ymfhNql-kzXHv3NWVHuqD4fHumasNXJG7kHTU,261
|
229
|
-
agentex/lib/utils/dev_tools/async_messages.py,sha256
|
228
|
+
agentex/lib/utils/dev_tools/async_messages.py,sha256=dM01spww2Fy6ej_WDnPXs2eG-9yCU7Xc1IMKwJzq6cM,19543
|
230
229
|
agentex/resources/__init__.py,sha256=74rMqWBzQ2dSrKQqsrd7-jskPws0O_ogkFltvZO3HoU,3265
|
231
230
|
agentex/resources/agents.py,sha256=WLG7wTQcCZCtqvNiyi2wjuDA2u85nEA5o9kUr5pBQXE,46977
|
232
231
|
agentex/resources/events.py,sha256=Zc9JhUm3bq2VFnBAolC0M7KZernzj1AjZ_vj0ibP4GY,10412
|
@@ -301,8 +300,8 @@ agentex/types/messages/batch_update_params.py,sha256=Ug5CThbD49a8j4qucg04OdmVrp_
|
|
301
300
|
agentex/types/messages/batch_update_response.py,sha256=TbSBe6SuPzjXXWSj-nRjT1JHGBooTshHQQDa1AixQA8,278
|
302
301
|
agentex/types/shared/__init__.py,sha256=IKs-Qn5Yja0kFh1G1kDqYZo43qrOu1hSoxlPdN-85dI,149
|
303
302
|
agentex/types/shared/delete_response.py,sha256=8qH3zvQXaOHYQSHyXi7UQxdR4miTzR7V9K4zXVsiUyk,215
|
304
|
-
agentex_sdk-0.4.
|
305
|
-
agentex_sdk-0.4.
|
306
|
-
agentex_sdk-0.4.
|
307
|
-
agentex_sdk-0.4.
|
308
|
-
agentex_sdk-0.4.
|
303
|
+
agentex_sdk-0.4.8.dist-info/METADATA,sha256=_ZN2ZmRBA_8REs6q2Q8gsidbWdcI2kqDPPvoDgqkdZQ,15094
|
304
|
+
agentex_sdk-0.4.8.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
305
|
+
agentex_sdk-0.4.8.dist-info/entry_points.txt,sha256=V7vJuMZdF0UlvgX6KiBN7XUvq_cxF5kplcYvc1QlFaQ,62
|
306
|
+
agentex_sdk-0.4.8.dist-info/licenses/LICENSE,sha256=Q1AOx2FtRcMlyMgQJ9eVN2WKPq2mQ33lnB4tvWxabLA,11337
|
307
|
+
agentex_sdk-0.4.8.dist-info/RECORD,,
|
@@ -1,171 +0,0 @@
|
|
1
|
-
from enum import Enum
|
2
|
-
from typing import Annotated, Literal
|
3
|
-
|
4
|
-
from pydantic import Field, model_validator
|
5
|
-
|
6
|
-
from agentex.types.task_message import TaskMessage
|
7
|
-
from agentex.types.task_message_content import TaskMessageContent
|
8
|
-
from agentex.lib.utils.model_utils import BaseModel
|
9
|
-
|
10
|
-
|
11
|
-
class BaseTaskMessageDelta(BaseModel):
|
12
|
-
"""
|
13
|
-
Base class for all delta updates
|
14
|
-
|
15
|
-
Attributes:
|
16
|
-
type: The type of delta update
|
17
|
-
"""
|
18
|
-
|
19
|
-
type: Literal["text", "data", "tool_request", "tool_response"]
|
20
|
-
|
21
|
-
|
22
|
-
class TextDelta(BaseTaskMessageDelta):
|
23
|
-
"""
|
24
|
-
Delta for text updates
|
25
|
-
|
26
|
-
Attributes:
|
27
|
-
type: The type of delta update
|
28
|
-
text_delta: The delta for the text
|
29
|
-
"""
|
30
|
-
|
31
|
-
type: Literal["text"] = "text"
|
32
|
-
text_delta: str | None = ""
|
33
|
-
|
34
|
-
|
35
|
-
class DataDelta(BaseTaskMessageDelta):
|
36
|
-
"""
|
37
|
-
Delta for data updates
|
38
|
-
|
39
|
-
Attributes:
|
40
|
-
type: The type of delta update
|
41
|
-
data_delta: The delta for the data
|
42
|
-
"""
|
43
|
-
|
44
|
-
type: Literal["data"] = "data"
|
45
|
-
data_delta: str | None = ""
|
46
|
-
|
47
|
-
|
48
|
-
class ToolRequestDelta(BaseTaskMessageDelta):
|
49
|
-
"""
|
50
|
-
Delta for tool request updates
|
51
|
-
|
52
|
-
Attributes:
|
53
|
-
type: The type of delta update
|
54
|
-
name: The name of the tool
|
55
|
-
arguments_delta: The delta for the arguments
|
56
|
-
"""
|
57
|
-
|
58
|
-
type: Literal["tool_request"] = "tool_request"
|
59
|
-
tool_call_id: str
|
60
|
-
name: str
|
61
|
-
arguments_delta: str | None = ""
|
62
|
-
|
63
|
-
|
64
|
-
class ToolResponseDelta(BaseTaskMessageDelta):
|
65
|
-
"""
|
66
|
-
Delta for tool response updates
|
67
|
-
|
68
|
-
Attributes:
|
69
|
-
type: The type of delta update
|
70
|
-
tool_response_delta: The delta for the tool response
|
71
|
-
"""
|
72
|
-
|
73
|
-
type: Literal["tool_response"] = "tool_response"
|
74
|
-
tool_call_id: str
|
75
|
-
name: str
|
76
|
-
tool_response_delta: str | None = ""
|
77
|
-
|
78
|
-
|
79
|
-
TaskMessageDelta = Annotated[
|
80
|
-
TextDelta | DataDelta | ToolRequestDelta | ToolResponseDelta,
|
81
|
-
Field(discriminator="type"),
|
82
|
-
]
|
83
|
-
|
84
|
-
|
85
|
-
class StreamTaskMessage(BaseModel):
|
86
|
-
"""Base class for all task message stream events
|
87
|
-
|
88
|
-
Attributes:
|
89
|
-
type: The type of task message update
|
90
|
-
parent_task_message: The parent task message
|
91
|
-
index: The index of the task message
|
92
|
-
"""
|
93
|
-
|
94
|
-
type: Literal["start", "delta", "full", "done"]
|
95
|
-
# Used for streaming chunks to a direct parent_task_message
|
96
|
-
parent_task_message: TaskMessage | None = None
|
97
|
-
# Used to correlate chunks of different task messages with each other
|
98
|
-
# directly in the Sync ACP case
|
99
|
-
index: int | None = None
|
100
|
-
|
101
|
-
@model_validator(mode="after")
|
102
|
-
def validate_message_correlation(self):
|
103
|
-
"""Ensure exactly one of index or parent_task_message is set"""
|
104
|
-
has_parent = self.parent_task_message is not None
|
105
|
-
has_index = self.index is not None
|
106
|
-
|
107
|
-
if not has_parent and not has_index:
|
108
|
-
raise ValueError("Either 'index' or 'parent_task_message' must be set")
|
109
|
-
|
110
|
-
if has_parent and has_index:
|
111
|
-
raise ValueError(
|
112
|
-
"Cannot set both 'index' and 'parent_task_message' - only one is allowed"
|
113
|
-
)
|
114
|
-
|
115
|
-
return self
|
116
|
-
|
117
|
-
|
118
|
-
# Everything is streamed as a partial json blob, except for text.
|
119
|
-
class StreamTaskMessageStart(StreamTaskMessage):
|
120
|
-
"""Event for starting a streaming message
|
121
|
-
|
122
|
-
Attributes:
|
123
|
-
type: The type of task message update
|
124
|
-
content: The content of the task message
|
125
|
-
"""
|
126
|
-
|
127
|
-
type: Literal["start"] = "start"
|
128
|
-
content: TaskMessageContent
|
129
|
-
|
130
|
-
|
131
|
-
class StreamTaskMessageDelta(StreamTaskMessage):
|
132
|
-
"""Event for streaming chunks of content
|
133
|
-
|
134
|
-
Attributes:
|
135
|
-
type: The type of task message update
|
136
|
-
delta: The delta of the task message
|
137
|
-
"""
|
138
|
-
|
139
|
-
type: Literal["delta"] = "delta"
|
140
|
-
delta: TaskMessageDelta | None = None
|
141
|
-
|
142
|
-
|
143
|
-
class StreamTaskMessageFull(StreamTaskMessage):
|
144
|
-
"""Event for streaming the full content
|
145
|
-
|
146
|
-
Attributes:
|
147
|
-
type: The type of task message update
|
148
|
-
content: The content of the task message
|
149
|
-
"""
|
150
|
-
|
151
|
-
type: Literal["full"] = "full"
|
152
|
-
content: TaskMessageContent
|
153
|
-
|
154
|
-
|
155
|
-
class StreamTaskMessageDone(StreamTaskMessage):
|
156
|
-
"""Event for indicating the task is done
|
157
|
-
|
158
|
-
Attributes:
|
159
|
-
type: The type of task message update
|
160
|
-
"""
|
161
|
-
|
162
|
-
type: Literal["done"] = "done"
|
163
|
-
|
164
|
-
|
165
|
-
TaskMessageUpdate = Annotated[
|
166
|
-
StreamTaskMessageStart
|
167
|
-
| StreamTaskMessageDelta
|
168
|
-
| StreamTaskMessageFull
|
169
|
-
| StreamTaskMessageDone,
|
170
|
-
Field(discriminator="type"),
|
171
|
-
]
|
File without changes
|
File without changes
|
File without changes
|