deepagents 0.0.12rc3__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deepagents-0.0.12rc3/src/deepagents.egg-info → deepagents-0.1.1}/PKG-INFO +4 -6
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/pyproject.toml +4 -6
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents/graph.py +3 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents/middleware/filesystem.py +9 -2
- deepagents-0.1.1/src/deepagents/middleware/patch_tool_calls.py +44 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents/middleware/subagents.py +8 -6
- {deepagents-0.0.12rc3 → deepagents-0.1.1/src/deepagents.egg-info}/PKG-INFO +4 -6
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents.egg-info/SOURCES.txt +1 -0
- deepagents-0.1.1/src/deepagents.egg-info/requires.txt +10 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/tests/test_middleware.py +131 -0
- deepagents-0.0.12rc3/src/deepagents.egg-info/requires.txt +0 -12
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/LICENSE +0 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/README.md +0 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/setup.cfg +0 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents/__init__.py +0 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents/middleware/__init__.py +0 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents.egg-info/dependency_links.txt +0 -0
- {deepagents-0.0.12rc3 → deepagents-0.1.1}/src/deepagents.egg-info/top_level.txt +0 -0
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: General purpose 'deep agent' with sub-agent spawning, todo list capabilities, and mock file system. Built on LangGraph.
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: <4.0,>=3.11
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist:
|
|
10
|
-
Requires-Dist: langchain
|
|
11
|
-
Requires-Dist: langchain==1.0.
|
|
12
|
-
Requires-Dist: langgraph-prebuilt==0.7.0a2
|
|
13
|
-
Requires-Dist: langchain-core==1.0.0rc3
|
|
9
|
+
Requires-Dist: langchain-anthropic==1.0.0
|
|
10
|
+
Requires-Dist: langchain==1.0.0
|
|
11
|
+
Requires-Dist: langchain-core==1.0.0
|
|
14
12
|
Provides-Extra: dev
|
|
15
13
|
Requires-Dist: pytest; extra == "dev"
|
|
16
14
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "deepagents"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.1.1"
|
|
4
4
|
description = "General purpose 'deep agent' with sub-agent spawning, todo list capabilities, and mock file system. Built on LangGraph."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
7
7
|
requires-python = ">=3.11,<4.0"
|
|
8
8
|
dependencies = [
|
|
9
|
-
"
|
|
10
|
-
"langchain
|
|
11
|
-
"langchain==1.0.
|
|
12
|
-
"langgraph-prebuilt==0.7.0a2",
|
|
13
|
-
"langchain-core==1.0.0rc3"
|
|
9
|
+
"langchain-anthropic==1.0.0",
|
|
10
|
+
"langchain==1.0.0",
|
|
11
|
+
"langchain-core==1.0.0"
|
|
14
12
|
]
|
|
15
13
|
|
|
16
14
|
[project.optional-dependencies]
|
|
@@ -18,6 +18,7 @@ from langgraph.store.base import BaseStore
|
|
|
18
18
|
from langgraph.types import Checkpointer
|
|
19
19
|
|
|
20
20
|
from deepagents.middleware.filesystem import FilesystemMiddleware
|
|
21
|
+
from deepagents.middleware.patch_tool_calls import PatchToolCallsMiddleware
|
|
21
22
|
from deepagents.middleware.subagents import CompiledSubAgent, SubAgent, SubAgentMiddleware
|
|
22
23
|
|
|
23
24
|
BASE_AGENT_PROMPT = "In order to complete the objective that the user asks of you, you have access to a number of standard tools."
|
|
@@ -112,6 +113,7 @@ def create_deep_agent(
|
|
|
112
113
|
messages_to_keep=6,
|
|
113
114
|
),
|
|
114
115
|
AnthropicPromptCachingMiddleware(unsupported_model_behavior="ignore"),
|
|
116
|
+
PatchToolCallsMiddleware(),
|
|
115
117
|
],
|
|
116
118
|
default_interrupt_on=interrupt_on,
|
|
117
119
|
general_purpose_agent=True,
|
|
@@ -122,6 +124,7 @@ def create_deep_agent(
|
|
|
122
124
|
messages_to_keep=6,
|
|
123
125
|
),
|
|
124
126
|
AnthropicPromptCachingMiddleware(unsupported_model_behavior="ignore"),
|
|
127
|
+
PatchToolCallsMiddleware(),
|
|
125
128
|
]
|
|
126
129
|
if interrupt_on is not None:
|
|
127
130
|
deepagent_middleware.append(HumanInTheLoopMiddleware(interrupt_on=interrupt_on))
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# ruff: noqa: E501
|
|
3
3
|
|
|
4
4
|
from collections.abc import Awaitable, Callable, Sequence
|
|
5
|
-
from typing import TYPE_CHECKING, Annotated, Any
|
|
5
|
+
from typing import TYPE_CHECKING, Annotated, Any
|
|
6
|
+
from typing_extensions import NotRequired
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from langgraph.runtime import Runtime
|
|
@@ -442,7 +443,7 @@ def _get_namespace() -> tuple[str] | tuple[str, str]:
|
|
|
442
443
|
return (assistant_id, "filesystem")
|
|
443
444
|
|
|
444
445
|
|
|
445
|
-
def _get_store(runtime:
|
|
446
|
+
def _get_store(runtime: ToolRuntime[None, FilesystemState]) -> BaseStore:
|
|
446
447
|
"""Get the store from the runtime, raising an error if unavailable.
|
|
447
448
|
|
|
448
449
|
Args:
|
|
@@ -721,6 +722,9 @@ def _write_file_tool_generator(custom_description: str | None = None, *, long_te
|
|
|
721
722
|
runtime: ToolRuntime[None, FilesystemState],
|
|
722
723
|
) -> Command | str:
|
|
723
724
|
file_path = _validate_path(file_path)
|
|
725
|
+
if not runtime.tool_call_id:
|
|
726
|
+
value_error_msg = "Tool call ID is required for write_file invocation"
|
|
727
|
+
raise ValueError(value_error_msg)
|
|
724
728
|
if _has_memories_prefix(file_path):
|
|
725
729
|
stripped_file_path = _strip_memories_prefix(file_path)
|
|
726
730
|
store = _get_store(runtime)
|
|
@@ -741,6 +745,9 @@ def _write_file_tool_generator(custom_description: str | None = None, *, long_te
|
|
|
741
745
|
runtime: ToolRuntime[None, FilesystemState],
|
|
742
746
|
) -> Command | str:
|
|
743
747
|
file_path = _validate_path(file_path)
|
|
748
|
+
if not runtime.tool_call_id:
|
|
749
|
+
value_error_msg = "Tool call ID is required for write_file invocation"
|
|
750
|
+
raise ValueError(value_error_msg)
|
|
744
751
|
return _write_file_to_state(runtime.state, runtime.tool_call_id, file_path, content)
|
|
745
752
|
|
|
746
753
|
return write_file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Middleware to patch dangling tool calls in the messages history."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from langchain.agents.middleware import AgentMiddleware, AgentState
|
|
6
|
+
from langchain_core.messages import RemoveMessage, ToolMessage
|
|
7
|
+
from langgraph.graph.message import REMOVE_ALL_MESSAGES
|
|
8
|
+
from langgraph.runtime import Runtime
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PatchToolCallsMiddleware(AgentMiddleware):
|
|
12
|
+
"""Middleware to patch dangling tool calls in the messages history."""
|
|
13
|
+
|
|
14
|
+
def before_agent(self, state: AgentState, runtime: Runtime[Any]) -> dict[str, Any] | None: # noqa: ARG002
|
|
15
|
+
"""Before the agent runs, handle dangling tool calls from any AIMessage."""
|
|
16
|
+
messages = state["messages"]
|
|
17
|
+
if not messages or len(messages) == 0:
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
patched_messages = []
|
|
21
|
+
# Iterate over the messages and add any dangling tool calls
|
|
22
|
+
for i, msg in enumerate(messages):
|
|
23
|
+
patched_messages.append(msg)
|
|
24
|
+
if msg.type == "ai" and msg.tool_calls:
|
|
25
|
+
for tool_call in msg.tool_calls:
|
|
26
|
+
corresponding_tool_msg = next(
|
|
27
|
+
(msg for msg in messages[i:] if msg.type == "tool" and msg.tool_call_id == tool_call["id"]),
|
|
28
|
+
None,
|
|
29
|
+
)
|
|
30
|
+
if corresponding_tool_msg is None:
|
|
31
|
+
# We have a dangling tool call which needs a ToolMessage
|
|
32
|
+
tool_msg = (
|
|
33
|
+
f"Tool call {tool_call['name']} with id {tool_call['id']} was "
|
|
34
|
+
"cancelled - another message came in before it could be completed."
|
|
35
|
+
)
|
|
36
|
+
patched_messages.append(
|
|
37
|
+
ToolMessage(
|
|
38
|
+
content=tool_msg,
|
|
39
|
+
name=tool_call["name"],
|
|
40
|
+
tool_call_id=tool_call["id"],
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
return {"messages": [RemoveMessage(id=REMOVE_ALL_MESSAGES), *patched_messages]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Middleware for providing subagents to an agent via a `task` tool."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Awaitable, Callable, Sequence
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, TypedDict, cast
|
|
5
|
+
from typing_extensions import NotRequired
|
|
5
6
|
|
|
6
7
|
from langchain.agents import create_agent
|
|
7
8
|
from langchain.agents.middleware import HumanInTheLoopMiddleware, InterruptOnConfig
|
|
@@ -13,11 +14,6 @@ from langchain_core.runnables import Runnable
|
|
|
13
14
|
from langchain_core.tools import StructuredTool
|
|
14
15
|
from langgraph.types import Command
|
|
15
16
|
|
|
16
|
-
try:
|
|
17
|
-
from langchain_anthropic.middleware.prompt_caching import AnthropicPromptCachingMiddleware
|
|
18
|
-
except ImportError:
|
|
19
|
-
AnthropicPromptCachingMiddleware = None
|
|
20
|
-
|
|
21
17
|
|
|
22
18
|
class SubAgent(TypedDict):
|
|
23
19
|
"""Specification for an agent.
|
|
@@ -352,6 +348,9 @@ def _create_task_tool(
|
|
|
352
348
|
) -> str | Command:
|
|
353
349
|
subagent, subagent_state = _validate_and_prepare_state(subagent_type, description, runtime)
|
|
354
350
|
result = subagent.invoke(subagent_state)
|
|
351
|
+
if not runtime.tool_call_id:
|
|
352
|
+
value_error_msg = "Tool call ID is required for subagent invocation"
|
|
353
|
+
raise ValueError(value_error_msg)
|
|
355
354
|
return _return_command_with_state_update(result, runtime.tool_call_id)
|
|
356
355
|
|
|
357
356
|
async def atask(
|
|
@@ -361,6 +360,9 @@ def _create_task_tool(
|
|
|
361
360
|
) -> str | Command:
|
|
362
361
|
subagent, subagent_state = _validate_and_prepare_state(subagent_type, description, runtime)
|
|
363
362
|
result = await subagent.ainvoke(subagent_state)
|
|
363
|
+
if not runtime.tool_call_id:
|
|
364
|
+
value_error_msg = "Tool call ID is required for subagent invocation"
|
|
365
|
+
raise ValueError(value_error_msg)
|
|
364
366
|
return _return_command_with_state_update(result, runtime.tool_call_id)
|
|
365
367
|
|
|
366
368
|
return StructuredTool.from_function(
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepagents
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: General purpose 'deep agent' with sub-agent spawning, todo list capabilities, and mock file system. Built on LangGraph.
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: <4.0,>=3.11
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist:
|
|
10
|
-
Requires-Dist: langchain
|
|
11
|
-
Requires-Dist: langchain==1.0.
|
|
12
|
-
Requires-Dist: langgraph-prebuilt==0.7.0a2
|
|
13
|
-
Requires-Dist: langchain-core==1.0.0rc3
|
|
9
|
+
Requires-Dist: langchain-anthropic==1.0.0
|
|
10
|
+
Requires-Dist: langchain==1.0.0
|
|
11
|
+
Requires-Dist: langchain-core==1.0.0
|
|
14
12
|
Provides-Extra: dev
|
|
15
13
|
Requires-Dist: pytest; extra == "dev"
|
|
16
14
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -10,5 +10,6 @@ src/deepagents.egg-info/requires.txt
|
|
|
10
10
|
src/deepagents.egg-info/top_level.txt
|
|
11
11
|
src/deepagents/middleware/__init__.py
|
|
12
12
|
src/deepagents/middleware/filesystem.py
|
|
13
|
+
src/deepagents/middleware/patch_tool_calls.py
|
|
13
14
|
src/deepagents/middleware/subagents.py
|
|
14
15
|
tests/test_middleware.py
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from langchain.agents import create_agent
|
|
3
3
|
from langchain.tools import ToolRuntime
|
|
4
|
+
from langchain_core.messages import (
|
|
5
|
+
AIMessage,
|
|
6
|
+
HumanMessage,
|
|
7
|
+
SystemMessage,
|
|
8
|
+
ToolCall,
|
|
9
|
+
ToolMessage,
|
|
10
|
+
)
|
|
11
|
+
from langgraph.graph.message import add_messages
|
|
4
12
|
|
|
5
13
|
from deepagents.middleware.filesystem import (
|
|
6
14
|
FILESYSTEM_SYSTEM_PROMPT,
|
|
@@ -9,6 +17,7 @@ from deepagents.middleware.filesystem import (
|
|
|
9
17
|
FilesystemMiddleware,
|
|
10
18
|
FilesystemState,
|
|
11
19
|
)
|
|
20
|
+
from deepagents.middleware.patch_tool_calls import PatchToolCallsMiddleware
|
|
12
21
|
from deepagents.middleware.subagents import DEFAULT_GENERAL_PURPOSE_DESCRIPTION, TASK_SYSTEM_PROMPT, TASK_TOOL_DESCRIPTION, SubAgentMiddleware
|
|
13
22
|
|
|
14
23
|
|
|
@@ -171,3 +180,125 @@ class TestSubagentMiddleware:
|
|
|
171
180
|
)
|
|
172
181
|
assert middleware is not None
|
|
173
182
|
assert middleware.system_prompt == "Use the task tool to call a subagent."
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class TestPatchToolCallsMiddleware:
|
|
186
|
+
def test_first_message(self) -> None:
|
|
187
|
+
input_messages = [
|
|
188
|
+
SystemMessage(content="You are a helpful assistant.", id="1"),
|
|
189
|
+
HumanMessage(content="Hello, how are you?", id="2"),
|
|
190
|
+
]
|
|
191
|
+
middleware = PatchToolCallsMiddleware()
|
|
192
|
+
state_update = middleware.before_agent({"messages": input_messages}, None)
|
|
193
|
+
assert state_update is not None
|
|
194
|
+
assert len(state_update["messages"]) == 3
|
|
195
|
+
assert state_update["messages"][0].type == "remove"
|
|
196
|
+
assert state_update["messages"][1].type == "system"
|
|
197
|
+
assert state_update["messages"][1].content == "You are a helpful assistant."
|
|
198
|
+
assert state_update["messages"][2].type == "human"
|
|
199
|
+
assert state_update["messages"][2].content == "Hello, how are you?"
|
|
200
|
+
assert state_update["messages"][2].id == "2"
|
|
201
|
+
|
|
202
|
+
def test_missing_tool_call(self) -> None:
|
|
203
|
+
input_messages = [
|
|
204
|
+
SystemMessage(content="You are a helpful assistant.", id="1"),
|
|
205
|
+
HumanMessage(content="Hello, how are you?", id="2"),
|
|
206
|
+
AIMessage(
|
|
207
|
+
content="I'm doing well, thank you!",
|
|
208
|
+
tool_calls=[ToolCall(id="123", name="get_events_for_days", args={"date_str": "2025-01-01"})],
|
|
209
|
+
id="3",
|
|
210
|
+
),
|
|
211
|
+
HumanMessage(content="What is the weather in Tokyo?", id="4"),
|
|
212
|
+
]
|
|
213
|
+
middleware = PatchToolCallsMiddleware()
|
|
214
|
+
state_update = middleware.before_agent({"messages": input_messages}, None)
|
|
215
|
+
assert state_update is not None
|
|
216
|
+
assert len(state_update["messages"]) == 6
|
|
217
|
+
assert state_update["messages"][0].type == "remove"
|
|
218
|
+
assert state_update["messages"][1] == input_messages[0]
|
|
219
|
+
assert state_update["messages"][2] == input_messages[1]
|
|
220
|
+
assert state_update["messages"][3] == input_messages[2]
|
|
221
|
+
assert state_update["messages"][4].type == "tool"
|
|
222
|
+
assert state_update["messages"][4].tool_call_id == "123"
|
|
223
|
+
assert state_update["messages"][4].name == "get_events_for_days"
|
|
224
|
+
assert state_update["messages"][5] == input_messages[3]
|
|
225
|
+
updated_messages = add_messages(input_messages, state_update["messages"])
|
|
226
|
+
assert len(updated_messages) == 5
|
|
227
|
+
assert updated_messages[0] == input_messages[0]
|
|
228
|
+
assert updated_messages[1] == input_messages[1]
|
|
229
|
+
assert updated_messages[2] == input_messages[2]
|
|
230
|
+
assert updated_messages[3].type == "tool"
|
|
231
|
+
assert updated_messages[3].tool_call_id == "123"
|
|
232
|
+
assert updated_messages[3].name == "get_events_for_days"
|
|
233
|
+
assert updated_messages[4] == input_messages[3]
|
|
234
|
+
|
|
235
|
+
def test_no_missing_tool_calls(self) -> None:
|
|
236
|
+
input_messages = [
|
|
237
|
+
SystemMessage(content="You are a helpful assistant.", id="1"),
|
|
238
|
+
HumanMessage(content="Hello, how are you?", id="2"),
|
|
239
|
+
AIMessage(
|
|
240
|
+
content="I'm doing well, thank you!",
|
|
241
|
+
tool_calls=[ToolCall(id="123", name="get_events_for_days", args={"date_str": "2025-01-01"})],
|
|
242
|
+
id="3",
|
|
243
|
+
),
|
|
244
|
+
ToolMessage(content="I have no events for that date.", tool_call_id="123", id="4"),
|
|
245
|
+
HumanMessage(content="What is the weather in Tokyo?", id="5"),
|
|
246
|
+
]
|
|
247
|
+
middleware = PatchToolCallsMiddleware()
|
|
248
|
+
state_update = middleware.before_agent({"messages": input_messages}, None)
|
|
249
|
+
assert state_update is not None
|
|
250
|
+
assert len(state_update["messages"]) == 6
|
|
251
|
+
assert state_update["messages"][0].type == "remove"
|
|
252
|
+
assert state_update["messages"][1:] == input_messages
|
|
253
|
+
updated_messages = add_messages(input_messages, state_update["messages"])
|
|
254
|
+
assert len(updated_messages) == 5
|
|
255
|
+
assert updated_messages == input_messages
|
|
256
|
+
|
|
257
|
+
def test_two_missing_tool_calls(self) -> None:
|
|
258
|
+
input_messages = [
|
|
259
|
+
SystemMessage(content="You are a helpful assistant.", id="1"),
|
|
260
|
+
HumanMessage(content="Hello, how are you?", id="2"),
|
|
261
|
+
AIMessage(
|
|
262
|
+
content="I'm doing well, thank you!",
|
|
263
|
+
tool_calls=[ToolCall(id="123", name="get_events_for_days", args={"date_str": "2025-01-01"})],
|
|
264
|
+
id="3",
|
|
265
|
+
),
|
|
266
|
+
HumanMessage(content="What is the weather in Tokyo?", id="4"),
|
|
267
|
+
AIMessage(
|
|
268
|
+
content="I'm doing well, thank you!",
|
|
269
|
+
tool_calls=[ToolCall(id="456", name="get_events_for_days", args={"date_str": "2025-01-01"})],
|
|
270
|
+
id="5",
|
|
271
|
+
),
|
|
272
|
+
HumanMessage(content="What is the weather in Tokyo?", id="6"),
|
|
273
|
+
]
|
|
274
|
+
middleware = PatchToolCallsMiddleware()
|
|
275
|
+
state_update = middleware.before_agent({"messages": input_messages}, None)
|
|
276
|
+
assert state_update is not None
|
|
277
|
+
assert len(state_update["messages"]) == 9
|
|
278
|
+
assert state_update["messages"][0].type == "remove"
|
|
279
|
+
assert state_update["messages"][1] == input_messages[0]
|
|
280
|
+
assert state_update["messages"][2] == input_messages[1]
|
|
281
|
+
assert state_update["messages"][3] == input_messages[2]
|
|
282
|
+
assert state_update["messages"][4].type == "tool"
|
|
283
|
+
assert state_update["messages"][4].tool_call_id == "123"
|
|
284
|
+
assert state_update["messages"][4].name == "get_events_for_days"
|
|
285
|
+
assert state_update["messages"][5] == input_messages[3]
|
|
286
|
+
assert state_update["messages"][6] == input_messages[4]
|
|
287
|
+
assert state_update["messages"][7].type == "tool"
|
|
288
|
+
assert state_update["messages"][7].tool_call_id == "456"
|
|
289
|
+
assert state_update["messages"][7].name == "get_events_for_days"
|
|
290
|
+
assert state_update["messages"][8] == input_messages[5]
|
|
291
|
+
updated_messages = add_messages(input_messages, state_update["messages"])
|
|
292
|
+
assert len(updated_messages) == 8
|
|
293
|
+
assert updated_messages[0] == input_messages[0]
|
|
294
|
+
assert updated_messages[1] == input_messages[1]
|
|
295
|
+
assert updated_messages[2] == input_messages[2]
|
|
296
|
+
assert updated_messages[3].type == "tool"
|
|
297
|
+
assert updated_messages[3].tool_call_id == "123"
|
|
298
|
+
assert updated_messages[3].name == "get_events_for_days"
|
|
299
|
+
assert updated_messages[4] == input_messages[3]
|
|
300
|
+
assert updated_messages[5] == input_messages[4]
|
|
301
|
+
assert updated_messages[6].type == "tool"
|
|
302
|
+
assert updated_messages[6].tool_call_id == "456"
|
|
303
|
+
assert updated_messages[6].name == "get_events_for_days"
|
|
304
|
+
assert updated_messages[7] == input_messages[5]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|