hyperpocket-langgraph 0.1.9__tar.gz → 0.2.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,6 +14,7 @@ __pycache__/
14
14
  build/
15
15
  develop-eggs/
16
16
  dist/
17
+ !tools/**/dist/
17
18
  downloads/
18
19
  eggs/
19
20
  .eggs/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperpocket-langgraph
3
- Version: 0.1.9
3
+ Version: 0.2.0
4
4
  Author-email: Hyperpocket Team <hyperpocket@vessl.ai>
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: hyperpocket>=0.0.3
@@ -17,13 +17,13 @@ Description-Content-Type: text/markdown
17
17
  ## Get Pocket Subgraph
18
18
 
19
19
  ```python
20
- from hyperpocket.tool import from_git
20
+
21
21
 
22
22
  from hyperpocket_langgraph import PocketLanggraph
23
23
 
24
24
  pocket = PocketLanggraph(tools=[
25
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
26
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
25
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
26
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
27
27
  "https://github.com/my-org/some-awesome-tool",
28
28
  ])
29
29
 
@@ -36,14 +36,13 @@ pocket_node = pocket.get_tool_node()
36
36
  ```python
37
37
  import os
38
38
 
39
- from hyperpocket.tool import from_git
40
39
  from langchain_openai import ChatOpenAI
41
40
 
42
41
  from hyperpocket_langgraph import PocketLanggraph
43
42
 
44
43
  pocket = PocketLanggraph(tools=[
45
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
46
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
44
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
45
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
47
46
  ])
48
47
 
49
48
  # get tools from pocket to bind llm
@@ -60,7 +59,6 @@ llm_with_tools = llm.bind_tools(tools)
60
59
  import os
61
60
  from typing import Annotated
62
61
 
63
- from hyperpocket.tool import from_git
64
62
  from langchain_core.runnables import RunnableConfig
65
63
  from langchain_openai import ChatOpenAI
66
64
  from langgraph.checkpoint.memory import MemorySaver
@@ -73,8 +71,8 @@ from hyperpocket_langgraph import PocketLanggraph
73
71
 
74
72
  # Define pocket tools
75
73
  pocket = PocketLanggraph(tools=[
76
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
77
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
74
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
75
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
78
76
  ])
79
77
 
80
78
  # Get Pocket ToolNode
@@ -131,14 +129,14 @@ by setting the `should_interrupt` flag when calling `get_tool_node`
131
129
  Perform authentication in a multi-turn way
132
130
 
133
131
  ```python
134
- from hyperpocket.tool import from_git
132
+
135
133
 
136
134
  from hyperpocket_langgraph import PocketLanggraph
137
135
 
138
136
  # Define pocket tools
139
137
  pocket = PocketLanggraph(tools=[
140
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
141
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
138
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
139
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
142
140
  ])
143
141
 
144
142
  # Get Pocket ToolNode
@@ -148,14 +146,14 @@ pocket_node = pocket.get_tool_node(should_interrupt=False) # multi turn
148
146
  ### Human-in-the-loop Auth
149
147
 
150
148
  ```python
151
- from hyperpocket.tool import from_git
149
+
152
150
 
153
151
  from hyperpocket_langgraph import PocketLanggraph
154
152
 
155
153
  # Define pocket tools
156
154
  pocket = PocketLanggraph(tools=[
157
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
158
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
155
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
156
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
159
157
  ])
160
158
 
161
159
  # Get Pocket ToolNode
@@ -8,13 +8,13 @@
8
8
  ## Get Pocket Subgraph
9
9
 
10
10
  ```python
11
- from hyperpocket.tool import from_git
11
+
12
12
 
13
13
  from hyperpocket_langgraph import PocketLanggraph
14
14
 
15
15
  pocket = PocketLanggraph(tools=[
16
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
17
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
16
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
17
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
18
18
  "https://github.com/my-org/some-awesome-tool",
19
19
  ])
20
20
 
@@ -27,14 +27,13 @@ pocket_node = pocket.get_tool_node()
27
27
  ```python
28
28
  import os
29
29
 
30
- from hyperpocket.tool import from_git
31
30
  from langchain_openai import ChatOpenAI
32
31
 
33
32
  from hyperpocket_langgraph import PocketLanggraph
34
33
 
35
34
  pocket = PocketLanggraph(tools=[
36
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
37
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
35
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
36
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
38
37
  ])
39
38
 
40
39
  # get tools from pocket to bind llm
@@ -51,7 +50,6 @@ llm_with_tools = llm.bind_tools(tools)
51
50
  import os
52
51
  from typing import Annotated
53
52
 
54
- from hyperpocket.tool import from_git
55
53
  from langchain_core.runnables import RunnableConfig
56
54
  from langchain_openai import ChatOpenAI
57
55
  from langgraph.checkpoint.memory import MemorySaver
@@ -64,8 +62,8 @@ from hyperpocket_langgraph import PocketLanggraph
64
62
 
65
63
  # Define pocket tools
66
64
  pocket = PocketLanggraph(tools=[
67
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
68
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
65
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
66
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
69
67
  ])
70
68
 
71
69
  # Get Pocket ToolNode
@@ -122,14 +120,14 @@ by setting the `should_interrupt` flag when calling `get_tool_node`
122
120
  Perform authentication in a multi-turn way
123
121
 
124
122
  ```python
125
- from hyperpocket.tool import from_git
123
+
126
124
 
127
125
  from hyperpocket_langgraph import PocketLanggraph
128
126
 
129
127
  # Define pocket tools
130
128
  pocket = PocketLanggraph(tools=[
131
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
132
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
129
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
130
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
133
131
  ])
134
132
 
135
133
  # Get Pocket ToolNode
@@ -139,14 +137,14 @@ pocket_node = pocket.get_tool_node(should_interrupt=False) # multi turn
139
137
  ### Human-in-the-loop Auth
140
138
 
141
139
  ```python
142
- from hyperpocket.tool import from_git
140
+
143
141
 
144
142
  from hyperpocket_langgraph import PocketLanggraph
145
143
 
146
144
  # Define pocket tools
147
145
  pocket = PocketLanggraph(tools=[
148
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/get-message"),
149
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/slack/post-message"),
146
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
147
+ "https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
150
148
  ])
151
149
 
152
150
  # Get Pocket ToolNode
@@ -1,3 +1,3 @@
1
1
  from hyperpocket_langgraph.pocket_langgraph import PocketLanggraph
2
2
 
3
- __all__ = ["PocketLanggraph"]
3
+ __all__ = ["PocketLanggraph"]
@@ -1,26 +1,21 @@
1
1
  import copy
2
2
  from typing import Optional
3
3
 
4
+ from hyperpocket.config import pocket_logger
4
5
  from langchain_core.runnables import RunnableConfig
5
6
  from langgraph.errors import NodeInterrupt
6
7
  from pydantic import BaseModel
7
8
 
8
- from hyperpocket.config import pocket_logger
9
-
10
9
  try:
11
10
  from langchain_core.messages import ToolMessage
12
11
  from langchain_core.tools import BaseTool, StructuredTool
13
12
  except ImportError:
14
- raise ImportError(
15
- "You need to install langchain to use pocket langgraph."
16
- )
13
+ raise ImportError("You need to install langchain to use pocket langgraph.")
17
14
 
18
15
  try:
19
16
  from langgraph.graph import MessagesState
20
17
  except ImportError:
21
- raise ImportError(
22
- "You need to install langgraph to use pocket langgraph"
23
- )
18
+ raise ImportError("You need to install langgraph to use pocket langgraph")
24
19
 
25
20
  from hyperpocket import Pocket
26
21
  from hyperpocket.tool import Tool as PocketTool
@@ -34,16 +29,22 @@ class PocketLanggraph(Pocket):
34
29
  def get_tools(self, use_profile: Optional[bool] = None):
35
30
  if use_profile is not None:
36
31
  self.use_profile = use_profile
37
- return [self._get_langgraph_tool(tool_impl) for tool_impl in
38
- self.core.tools.values()]
39
-
40
- def get_tool_node(self, should_interrupt: bool = False, use_profile: Optional[bool] = None):
32
+ return [
33
+ self._get_langgraph_tool(tool_impl)
34
+ for tool_impl in self.core.tools.values()
35
+ ]
36
+
37
+ def get_tool_node(
38
+ self, should_interrupt: bool = False, use_profile: Optional[bool] = None
39
+ ):
41
40
  if use_profile is not None:
42
41
  self.use_profile = use_profile
43
42
 
44
- async def _tool_node(state: PocketLanggraphBaseState, config: RunnableConfig) -> dict:
43
+ async def _tool_node(
44
+ state: PocketLanggraphBaseState, config: RunnableConfig
45
+ ) -> dict:
45
46
  thread_id = config.get("configurable", {}).get("thread_id", "default")
46
- last_message = state['messages'][-1]
47
+ last_message = state["messages"][-1]
47
48
  tool_calls = last_message.tool_calls
48
49
 
49
50
  # 01. prepare
@@ -54,9 +55,9 @@ class PocketLanggraph(Pocket):
54
55
  pocket_logger.debug(f"prepare tool {tool_call}")
55
56
  _tool_call = copy.deepcopy(tool_call)
56
57
 
57
- tool_call_id = _tool_call['id']
58
- tool_name = _tool_call['name']
59
- tool_args = _tool_call['args']
58
+ tool_call_id = _tool_call["id"]
59
+ tool_name = _tool_call["name"]
60
+ tool_args = _tool_call["args"]
60
61
 
61
62
  if self.use_profile:
62
63
  body = tool_args.pop("body")
@@ -68,27 +69,42 @@ class PocketLanggraph(Pocket):
68
69
  if isinstance(body, BaseModel):
69
70
  body = body.model_dump()
70
71
 
71
- prepare = await self.prepare_in_subprocess(tool_name, body=body, thread_id=thread_id,
72
- profile=profile)
72
+ prepare = await self.prepare_in_subprocess(
73
+ tool_name, body=body, thread_id=thread_id, profile=profile
74
+ )
73
75
  need_prepare |= True if prepare else False
74
76
 
75
77
  if prepare is None:
76
- prepare_done_list.append(ToolMessage(content="prepare done", tool_call_id=tool_call_id))
78
+ prepare_done_list.append(
79
+ ToolMessage(content="prepare done", tool_call_id=tool_call_id)
80
+ )
77
81
  else:
78
- prepare_list.append(ToolMessage(content=prepare, tool_call_id=tool_call_id))
82
+ prepare_list.append(
83
+ ToolMessage(content=prepare, tool_call_id=tool_call_id)
84
+ )
79
85
 
80
86
  if need_prepare:
81
87
  pocket_logger.debug(f"need prepare : {prepare_list}")
82
88
  if should_interrupt: # interrupt
83
- pocket_logger.debug(f"{last_message.name}({last_message.id}) is interrupt.")
84
- result = "\n\t" + "\n\t".join(set(msg.content for msg in prepare_list))
85
- raise NodeInterrupt(f'{result}\n\nThe tool execution interrupted. Please talk to me to resume.')
89
+ pocket_logger.debug(
90
+ f"{last_message.name}({last_message.id}) is interrupt."
91
+ )
92
+ result = "\n\t" + "\n\t".join(
93
+ set(msg.content for msg in prepare_list)
94
+ )
95
+ raise NodeInterrupt(
96
+ f"{result}\n\nThe tool execution interrupted. Please talk to me to resume."
97
+ )
86
98
 
87
99
  else: # multi turn
88
- pocket_logger.debug(f"{last_message.name}({last_message.id}) is multi-turn")
100
+ pocket_logger.debug(
101
+ f"{last_message.name}({last_message.id}) is multi-turn"
102
+ )
89
103
  return {"messages": prepare_done_list + prepare_list}
90
104
 
91
- pocket_logger.debug(f"no need prepare {last_message.name}({last_message.id})")
105
+ pocket_logger.debug(
106
+ f"no need prepare {last_message.name}({last_message.id})"
107
+ )
92
108
 
93
109
  # 02. authenticate and tool call
94
110
  tool_messages = []
@@ -96,9 +112,9 @@ class PocketLanggraph(Pocket):
96
112
  pocket_logger.debug(f"authenticate and call {tool_call}")
97
113
  _tool_call = copy.deepcopy(tool_call)
98
114
 
99
- tool_call_id = _tool_call['id']
100
- tool_name = _tool_call['name']
101
- tool_args = _tool_call['args']
115
+ tool_call_id = _tool_call["id"]
116
+ tool_name = _tool_call["name"]
117
+ tool_args = _tool_call["args"]
102
118
  if self.use_profile:
103
119
  body = tool_args.pop("body")
104
120
  profile = tool_args.pop("profile", "default")
@@ -111,27 +127,48 @@ class PocketLanggraph(Pocket):
111
127
 
112
128
  try:
113
129
  auth = await self.authenticate_in_subprocess(
114
- tool_name, body=body, thread_id=thread_id, profile=profile)
130
+ tool_name, body=body, thread_id=thread_id, profile=profile
131
+ )
115
132
  except Exception as e:
116
- pocket_logger.error(f"occur exception during authenticate. error : {e}")
133
+ pocket_logger.error(
134
+ f"occur exception during authenticate. error : {e}"
135
+ )
117
136
  tool_messages.append(
118
- ToolMessage(content=f"occur exception during authenticate. error : {e}", tool_name=tool_name,
119
- tool_call_id=tool_call_id))
137
+ ToolMessage(
138
+ content=f"occur exception during authenticate. error : {e}",
139
+ tool_name=tool_name,
140
+ tool_call_id=tool_call_id,
141
+ )
142
+ )
120
143
  continue
121
144
 
122
145
  try:
123
146
  result = await self.tool_call_in_subprocess(
124
- tool_name, body=body, envs=auth, thread_id=thread_id,
125
- profile=tool_args.get("profile", "default"))
147
+ tool_name,
148
+ body=body,
149
+ envs=auth,
150
+ thread_id=thread_id,
151
+ profile=tool_args.get("profile", "default"),
152
+ )
126
153
  except Exception as e:
127
- pocket_logger.error(f"occur exception during tool calling. error : {e}")
154
+ pocket_logger.error(
155
+ f"occur exception during tool calling. error : {e}"
156
+ )
128
157
  tool_messages.append(
129
- ToolMessage(content=f"occur exception during tool calling. error : {e}", tool_name=tool_name,
130
- tool_call_id=tool_call_id))
158
+ ToolMessage(
159
+ content=f"occur exception during tool calling. error : {e}",
160
+ tool_name=tool_name,
161
+ tool_call_id=tool_call_id,
162
+ )
163
+ )
131
164
  continue
132
165
 
133
166
  pocket_logger.debug(f"{tool_name} tool result : {result}")
134
- tool_messages.append(ToolMessage(content=result, tool_name=tool_name, tool_call_id=tool_call_id))
167
+ tool_messages.append(
168
+ ToolMessage(
169
+ content=result, tool_name=tool_name, tool_call_id=tool_call_id
170
+ )
171
+ )
135
172
 
136
173
  return {"messages": tool_messages}
137
174
 
@@ -151,10 +188,12 @@ class PocketLanggraph(Pocket):
151
188
  if isinstance(body, BaseModel):
152
189
  body = body.model_dump()
153
190
 
154
- result, interrupted = self.invoke_with_state(pocket_tool.name, body, thread_id, profile, **kwargs)
191
+ result, interrupted = self.invoke_with_state(
192
+ pocket_tool.name, body, thread_id, profile, **kwargs
193
+ )
155
194
  say = result
156
195
  if interrupted:
157
- say = f'{say}\n\nThe tool execution interrupted. Please talk to me to resume.'
196
+ say = f"{say}\n\nThe tool execution interrupted. Please talk to me to resume."
158
197
  return say
159
198
 
160
199
  async def _ainvoke(**kwargs) -> str:
@@ -170,10 +209,12 @@ class PocketLanggraph(Pocket):
170
209
  if isinstance(body, BaseModel):
171
210
  body = body.model_dump()
172
211
 
173
- result, interrupted = await self.ainvoke_with_state(pocket_tool.name, body, thread_id, profile, **kwargs)
212
+ result, interrupted = await self.ainvoke_with_state(
213
+ pocket_tool.name, body, thread_id, profile, **kwargs
214
+ )
174
215
  say = result
175
216
  if interrupted:
176
- say = f'{say}\n\nThe tool execution interrupted. Please talk to me to resume.'
217
+ say = f"{say}\n\nThe tool execution interrupted. Please talk to me to resume."
177
218
  return say
178
219
 
179
220
  return StructuredTool.from_function(
@@ -1,7 +1,7 @@
1
1
 
2
2
  [project]
3
3
  name = "hyperpocket-langgraph"
4
- version = "0.1.9"
4
+ version = "0.2.0"
5
5
  description = ""
6
6
  authors = [{ name = "Hyperpocket Team", email = "hyperpocket@vessl.ai" }]
7
7
  requires-python = ">=3.10"
@@ -12,31 +12,12 @@ dependencies = ["langgraph>=0.2.59", "hyperpocket>=0.0.3"]
12
12
  hyperpocket = { path = "../../hyperpocket", editable = true }
13
13
 
14
14
  [dependency-groups]
15
- dev = [
16
- "pytest>=8.3.4",
17
- "ruff>=0.8.6",
18
- ]
19
- test = [
20
- "langchain-openai>=0.3.1",
21
- ]
15
+ dev = ["pytest>=8.3.4", "ruff>=0.8.6"]
16
+ test = ["langchain-openai>=0.3.1"]
22
17
 
23
18
  [build-system]
24
19
  requires = ["hatchling"]
25
20
  build-backend = "hatchling.build"
26
21
 
27
- [tool.ruff.lint]
28
- select = [
29
- "E", # pycodestyle errors,
30
- "F", # pyflakes errors,
31
- "I", # isort errors,
32
- ]
33
- ignore = [
34
- "E501", # line too long, handled by formatting
35
- ]
36
-
37
22
  [tool.ruff]
38
- line-length = 88
39
- target-version = "py310"
40
-
41
- [tool.ruff.lint.per-file-ignores]
42
- "__init__.py" = ["F401"]
23
+ extend = "../../../.ruff.toml"
@@ -1,20 +1,18 @@
1
1
  import ast
2
2
  from unittest.async_case import IsolatedAsyncioTestCase
3
3
 
4
+ from hyperpocket.config import config, secret
5
+ from hyperpocket.tool import from_git
4
6
  from langchain_openai import ChatOpenAI
5
- from langgraph.constants import START, END
7
+ from langgraph.constants import END, START
6
8
  from langgraph.graph import MessagesState, StateGraph
7
9
  from langgraph.prebuilt import tools_condition
8
10
  from pydantic import BaseModel
9
11
 
10
- from hyperpocket.config import config, secret
11
- from hyperpocket.tool import from_git
12
12
  from hyperpocket_langgraph import PocketLanggraph
13
13
 
14
14
 
15
15
  class TestPocketLanggraphNoProfile(IsolatedAsyncioTestCase):
16
-
17
-
18
16
  async def asyncSetUp(self):
19
17
  config.public_server_port = "https"
20
18
  config.public_hostname = "localhost"
@@ -24,15 +22,21 @@ class TestPocketLanggraphNoProfile(IsolatedAsyncioTestCase):
24
22
 
25
23
  self.pocket = PocketLanggraph(
26
24
  tools=[
27
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/none/simple-echo-tool"),
25
+ from_git(
26
+ "https://github.com/vessl-ai/hyperawesometools",
27
+ "main",
28
+ "managed-tools/none/simple-echo-tool",
29
+ ),
28
30
  self.add,
29
- self.sub_pydantic_args
31
+ self.sub_pydantic_args,
30
32
  ],
31
- use_profile=False
33
+ use_profile=False,
32
34
  )
33
35
  tools = self.pocket.get_tools()
34
36
  tool_node = self.pocket.get_tool_node()
35
- self.llm = ChatOpenAI(model="gpt-4o", api_key=secret["OPENAI_API_KEY"]).bind_tools(tools=tools)
37
+ self.llm = ChatOpenAI(
38
+ model="gpt-4o", api_key=secret["OPENAI_API_KEY"]
39
+ ).bind_tools(tools=tools)
36
40
 
37
41
  def chatbot(state: MessagesState):
38
42
  return {"messages": [self.llm.invoke(state["messages"])]}
@@ -52,7 +56,6 @@ class TestPocketLanggraphNoProfile(IsolatedAsyncioTestCase):
52
56
  async def asyncTearDown(self):
53
57
  self.pocket._teardown_server()
54
58
 
55
-
56
59
  async def test_function_tool_no_profile(self):
57
60
  # when
58
61
  response = await self.graph.ainvoke({"messages": [("user", "add 1, 2")]})
@@ -62,10 +65,7 @@ class TestPocketLanggraphNoProfile(IsolatedAsyncioTestCase):
62
65
 
63
66
  # then
64
67
  self.assertEqual(tool_call.tool_calls[0]["name"], "add")
65
- self.assertEqual(tool_call.tool_calls[0]["args"], {
66
- 'a': 1,
67
- 'b': 2
68
- })
68
+ self.assertEqual(tool_call.tool_calls[0]["args"], {"a": 1, "b": 2})
69
69
  self.assertEqual(tool_result.content, "3")
70
70
 
71
71
  async def test_pydantic_function_tool_no_profile(self):
@@ -77,15 +77,16 @@ class TestPocketLanggraphNoProfile(IsolatedAsyncioTestCase):
77
77
 
78
78
  # then
79
79
  self.assertEqual(tool_call.tool_calls[0]["name"], "sub_pydantic_args")
80
- self.assertEqual(tool_call.tool_calls[0]["args"], {
81
- 'a': {"first": 1},
82
- 'b': {"second": 2}
83
- })
80
+ self.assertEqual(
81
+ tool_call.tool_calls[0]["args"], {"a": {"first": 1}, "b": {"second": 2}}
82
+ )
84
83
  self.assertEqual(tool_result.content, "-1")
85
84
 
86
85
  async def test_wasm_tool_no_profile(self):
87
86
  # when
88
- response = await self.graph.ainvoke({"messages": [("user", "echo 'hello world'")]})
87
+ response = await self.graph.ainvoke(
88
+ {"messages": [("user", "echo 'hello world'")]}
89
+ )
89
90
 
90
91
  tool_call = response["messages"][1]
91
92
  tool_result = response["messages"][2]
@@ -94,9 +95,7 @@ class TestPocketLanggraphNoProfile(IsolatedAsyncioTestCase):
94
95
 
95
96
  # then
96
97
  self.assertEqual(tool_call.tool_calls[0]["name"], "simple_echo_text")
97
- self.assertEqual(tool_call.tool_calls[0]["args"], {
98
- 'text': 'hello world'
99
- })
98
+ self.assertEqual(tool_call.tool_calls[0]["args"], {"text": "hello world"})
100
99
  self.assertTrue(output["stdout"].startswith("echo message : hello world"))
101
100
 
102
101
  @staticmethod
@@ -1,20 +1,18 @@
1
1
  import ast
2
2
  from unittest.async_case import IsolatedAsyncioTestCase
3
3
 
4
+ from hyperpocket.config import config, secret
5
+ from hyperpocket.tool import from_git
4
6
  from langchain_openai import ChatOpenAI
5
- from langgraph.constants import START, END
7
+ from langgraph.constants import END, START
6
8
  from langgraph.graph import MessagesState, StateGraph
7
9
  from langgraph.prebuilt import tools_condition
8
10
  from pydantic import BaseModel
9
11
 
10
- from hyperpocket.config import config, secret
11
- from hyperpocket.tool import from_git
12
12
  from hyperpocket_langgraph import PocketLanggraph
13
13
 
14
14
 
15
15
  class TestPocketLanggraphUseProfile(IsolatedAsyncioTestCase):
16
-
17
-
18
16
  async def asyncSetUp(self):
19
17
  config.public_server_port = "https"
20
18
  config.public_hostname = "localhost"
@@ -24,15 +22,21 @@ class TestPocketLanggraphUseProfile(IsolatedAsyncioTestCase):
24
22
 
25
23
  self.pocket = PocketLanggraph(
26
24
  tools=[
27
- from_git("https://github.com/vessl-ai/hyperawesometools", "main", "managed-tools/none/simple-echo-tool"),
25
+ from_git(
26
+ "https://github.com/vessl-ai/hyperawesometools",
27
+ "main",
28
+ "managed-tools/none/simple-echo-tool",
29
+ ),
28
30
  self.add,
29
- self.sub_pydantic_args
31
+ self.sub_pydantic_args,
30
32
  ],
31
- use_profile=True
33
+ use_profile=True,
32
34
  )
33
35
  tools = self.pocket.get_tools()
34
36
  tool_node = self.pocket.get_tool_node()
35
- self.llm = ChatOpenAI(model="gpt-4o", api_key=secret["OPENAI_API_KEY"]).bind_tools(tools=tools)
37
+ self.llm = ChatOpenAI(
38
+ model="gpt-4o", api_key=secret["OPENAI_API_KEY"]
39
+ ).bind_tools(tools=tools)
36
40
 
37
41
  def chatbot(state: MessagesState):
38
42
  return {"messages": [self.llm.invoke(state["messages"])]}
@@ -52,7 +56,6 @@ class TestPocketLanggraphUseProfile(IsolatedAsyncioTestCase):
52
56
  async def asyncTearDown(self):
53
57
  self.pocket._teardown_server()
54
58
 
55
-
56
59
  async def test_function_tool_use_profile(self):
57
60
  # when
58
61
  response = await self.graph.ainvoke({"messages": [("user", "add 1, 2")]})
@@ -62,10 +65,7 @@ class TestPocketLanggraphUseProfile(IsolatedAsyncioTestCase):
62
65
 
63
66
  # then
64
67
  self.assertEqual(tool_call.tool_calls[0]["name"], "add")
65
- self.assertEqual(tool_call.tool_calls[0]["args"]["body"], {
66
- 'a': 1,
67
- 'b': 2
68
- })
68
+ self.assertEqual(tool_call.tool_calls[0]["args"]["body"], {"a": 1, "b": 2})
69
69
  self.assertEqual(tool_result.content, "3")
70
70
 
71
71
  async def test_pydantic_function_tool_use_profile(self):
@@ -77,15 +77,17 @@ class TestPocketLanggraphUseProfile(IsolatedAsyncioTestCase):
77
77
 
78
78
  # then
79
79
  self.assertEqual(tool_call.tool_calls[0]["name"], "sub_pydantic_args")
80
- self.assertEqual(tool_call.tool_calls[0]["args"]["body"], {
81
- 'a': {"first": 1},
82
- 'b': {"second": 2}
83
- })
80
+ self.assertEqual(
81
+ tool_call.tool_calls[0]["args"]["body"],
82
+ {"a": {"first": 1}, "b": {"second": 2}},
83
+ )
84
84
  self.assertEqual(tool_result.content, "-1")
85
85
 
86
86
  async def test_wasm_tool_use_profile(self):
87
87
  # when
88
- response = await self.graph.ainvoke({"messages": [("user", "echo 'hello world'")]})
88
+ response = await self.graph.ainvoke(
89
+ {"messages": [("user", "echo 'hello world'")]}
90
+ )
89
91
 
90
92
  tool_call = response["messages"][1]
91
93
  tool_result = response["messages"][2]
@@ -94,9 +96,9 @@ class TestPocketLanggraphUseProfile(IsolatedAsyncioTestCase):
94
96
 
95
97
  # then
96
98
  self.assertEqual(tool_call.tool_calls[0]["name"], "simple_echo_text")
97
- self.assertEqual(tool_call.tool_calls[0]["args"]["body"], {
98
- 'text': 'hello world'
99
- })
99
+ self.assertEqual(
100
+ tool_call.tool_calls[0]["args"]["body"], {"text": "hello world"}
101
+ )
100
102
  self.assertTrue(output["stdout"].startswith("echo message : hello world"))
101
103
 
102
104
  @staticmethod