agentic-blocks 0.1.14__tar.gz → 0.1.16__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-blocks
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Simple building blocks for agentic AI systems with MCP client and conversation management
5
5
  Author-email: Magnus Bjelkenhed <bjelkenhed@gmail.com>
6
6
  License: MIT
@@ -14,7 +14,7 @@ agentic_blocks = []
14
14
 
15
15
  [project]
16
16
  name = "agentic-blocks"
17
- version = "0.1.14"
17
+ version = "0.1.16"
18
18
  description = "Simple building blocks for agentic AI systems with MCP client and conversation management"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.11"
@@ -2,22 +2,23 @@
2
2
  Utilities for working with tools across different formats.
3
3
  """
4
4
 
5
+ import json
5
6
  from typing import Dict, Any, List
6
7
 
7
8
 
8
9
  def langchain_tool_to_openai_format(tool) -> Dict[str, Any]:
9
10
  """
10
11
  Convert a LangChain StructuredTool to OpenAI function calling format.
11
-
12
+
12
13
  Args:
13
14
  tool: A langchain_core.tools.structured.StructuredTool instance
14
-
15
+
15
16
  Returns:
16
- Dictionary in OpenAI function calling format, compatible with
17
+ Dictionary in OpenAI function calling format, compatible with
17
18
  MCPClient.list_tools() output and call_llm() tools parameter
18
19
  """
19
20
  schema = tool.args_schema.model_json_schema()
20
-
21
+
21
22
  # Resolve $ref references by flattening $defs into the schema
22
23
  # OpenAI doesn't support $ref/$defs, so we need to inline all definitions
23
24
  def resolve_refs(obj, defs):
@@ -38,39 +39,39 @@ def langchain_tool_to_openai_format(tool) -> Dict[str, Any]:
38
39
  return [resolve_refs(item, defs) for item in obj]
39
40
  else:
40
41
  return obj
41
-
42
+
42
43
  # Get definitions for reference resolution
43
44
  defs = schema.get("$defs", {})
44
-
45
+
45
46
  # Resolve references in properties
46
47
  resolved_properties = resolve_refs(schema.get("properties", {}), defs)
47
-
48
+
48
49
  # Build parameters object without $defs
49
50
  parameters = {
50
51
  "type": "object",
51
52
  "properties": resolved_properties,
52
- "required": schema.get("required", [])
53
+ "required": schema.get("required", []),
53
54
  }
54
-
55
+
55
56
  return {
56
57
  "type": "function",
57
58
  "function": {
58
59
  "name": schema.get("title", tool.name),
59
60
  "description": tool.description or schema.get("description", ""),
60
- "parameters": parameters
61
- }
61
+ "parameters": parameters,
62
+ },
62
63
  }
63
64
 
64
65
 
65
66
  def langchain_tools_to_openai_format(tools: List) -> List[Dict[str, Any]]:
66
67
  """
67
68
  Convert a list of LangChain StructuredTools to OpenAI function calling format.
68
-
69
+
69
70
  Args:
70
71
  tools: List of langchain_core.tools.structured.StructuredTool instances
71
-
72
+
72
73
  Returns:
73
- List of dictionaries in OpenAI function calling format, compatible with
74
+ List of dictionaries in OpenAI function calling format, compatible with
74
75
  MCPClient.list_tools() output and call_llm() tools parameter
75
76
  """
76
77
  return [langchain_tool_to_openai_format(tool) for tool in tools]
@@ -79,128 +80,141 @@ def langchain_tools_to_openai_format(tools: List) -> List[Dict[str, Any]]:
79
80
  def create_tool_registry(tools: List) -> Dict[str, Any]:
80
81
  """
81
82
  Create a registry mapping tool names to LangChain tool instances.
82
-
83
+
83
84
  Args:
84
85
  tools: List of langchain_core.tools.structured.StructuredTool instances
85
-
86
+
86
87
  Returns:
87
88
  Dictionary mapping tool names to tool instances
88
89
  """
89
90
  return {tool.name: tool for tool in tools}
90
91
 
91
92
 
92
- def execute_tool_call(tool_call: Dict[str, Any], tool_registry: Dict[str, Any]) -> Dict[str, Any]:
93
+ def execute_tool_call(
94
+ tool_call: Dict[str, Any], tool_registry: Dict[str, Any]
95
+ ) -> Dict[str, Any]:
93
96
  """
94
97
  Execute a single tool call using LangChain tool registry.
95
-
98
+
96
99
  Args:
97
100
  tool_call: Dictionary with 'tool_name', 'arguments', and 'tool_call_id' keys
98
101
  tool_registry: Registry mapping tool names to tool instances
99
-
102
+
100
103
  Returns:
101
104
  Dictionary with 'tool_call_id', 'result', and 'is_error' keys
102
105
  """
103
- tool_name = tool_call.get('tool_name')
104
- arguments = tool_call.get('arguments', {})
105
- tool_call_id = tool_call.get('tool_call_id')
106
-
106
+ tool_name = tool_call.get("tool_name")
107
+ arguments = tool_call.get("arguments", {})
108
+ tool_call_id = tool_call.get("tool_call_id")
109
+
107
110
  try:
108
111
  if tool_name not in tool_registry:
109
112
  raise ValueError(f"Tool '{tool_name}' not found in registry")
110
-
113
+
111
114
  tool = tool_registry[tool_name]
112
115
  result = tool.invoke(arguments)
113
-
114
- return {
115
- 'tool_call_id': tool_call_id,
116
- 'result': result,
117
- 'is_error': False
118
- }
116
+
117
+ return {"tool_call_id": tool_call_id, "result": result, "is_error": False}
119
118
  except Exception as e:
120
119
  return {
121
- 'tool_call_id': tool_call_id,
122
- 'result': f"Error executing tool '{tool_name}': {str(e)}",
123
- 'is_error': True
120
+ "tool_call_id": tool_call_id,
121
+ "result": f"Error executing tool '{tool_name}': {str(e)}",
122
+ "is_error": True,
124
123
  }
125
124
 
126
125
 
127
- def execute_pending_tool_calls(messages, tool_registry: Dict[str, Any]) -> List[Dict[str, Any]]:
126
+ def execute_pending_tool_calls(
127
+ messages, tool_registry: Dict[str, Any]
128
+ ) -> List[Dict[str, Any]]:
128
129
  """
129
130
  Execute all pending tool calls from a Messages instance and add responses back.
130
-
131
+
131
132
  Args:
132
133
  messages: Messages instance with pending tool calls
133
134
  tool_registry: Registry mapping tool names to tool instances
134
-
135
+
135
136
  Returns:
136
137
  List of execution results compatible with Messages.add_tool_responses format
137
138
  """
138
139
  pending_tool_calls = messages.get_pending_tool_calls()
139
140
  results = []
140
-
141
+
141
142
  for tool_call in pending_tool_calls:
142
143
  result = execute_tool_call(tool_call, tool_registry)
143
-
144
+
144
145
  # Convert to format expected by Messages.add_tool_responses
145
- if result['is_error']:
146
+ if result["is_error"]:
146
147
  tool_response = {
147
- 'tool_call_id': result['tool_call_id'],
148
- 'is_error': True,
149
- 'error': result['result']
148
+ "tool_call_id": result["tool_call_id"],
149
+ "is_error": True,
150
+ "error": result["result"],
150
151
  }
151
152
  else:
152
153
  tool_response = {
153
- 'tool_call_id': result['tool_call_id'],
154
- 'is_error': False,
155
- 'tool_response': result['result']
154
+ "tool_call_id": result["tool_call_id"],
155
+ "is_error": False,
156
+ "tool_response": result["result"],
156
157
  }
157
-
158
+
158
159
  results.append(tool_response)
159
-
160
+
160
161
  # Add tool response back to messages using individual method
161
- if result['is_error']:
162
- messages.add_tool_response(result['tool_call_id'], result['result'])
163
- else:
164
- messages.add_tool_response(result['tool_call_id'], str(result['result']))
165
-
162
+ # if result['is_error']:
163
+ # messages.add_tool_response(result['tool_call_id'], result['result'])
164
+ # else:
165
+ # messages.add_tool_response(result['tool_call_id'], str(result['result']))
166
+
166
167
  return results
167
168
 
168
169
 
169
- def execute_and_add_tool_responses(messages, tool_registry: Dict[str, Any]) -> List[Dict[str, Any]]:
170
+ def execute_and_add_tool_responses(
171
+ messages, tool_registry: Dict[str, Any]
172
+ ) -> List[Dict[str, Any]]:
170
173
  """
171
174
  Execute all pending tool calls and add them using Messages.add_tool_responses batch method.
172
-
175
+
173
176
  Args:
174
177
  messages: Messages instance with pending tool calls
175
178
  tool_registry: Registry mapping tool names to tool instances
176
-
179
+
177
180
  Returns:
178
181
  List of execution results compatible with Messages.add_tool_responses format
179
182
  """
180
183
  pending_tool_calls = messages.get_pending_tool_calls()
181
184
  results = []
182
-
185
+
183
186
  for tool_call in pending_tool_calls:
184
187
  result = execute_tool_call(tool_call, tool_registry)
185
-
188
+
186
189
  # Convert to format expected by Messages.add_tool_responses
187
- if result['is_error']:
190
+ if result["is_error"]:
188
191
  tool_response = {
189
- 'tool_call_id': result['tool_call_id'],
190
- 'is_error': True,
191
- 'error': result['result']
192
+ "tool_call_id": result["tool_call_id"],
193
+ "is_error": True,
194
+ "error": result["result"],
192
195
  }
193
196
  else:
194
197
  tool_response = {
195
- 'tool_call_id': result['tool_call_id'],
196
- 'is_error': False,
197
- 'tool_response': result['result']
198
+ "tool_call_id": result["tool_call_id"],
199
+ "is_error": False,
200
+ "tool_response": result["result"],
198
201
  }
199
-
202
+
200
203
  results.append(tool_response)
201
-
204
+
202
205
  # Add all responses at once using the batch method
203
206
  if results:
204
207
  messages.add_tool_responses(results)
208
+
209
+ return results
210
+
211
+
212
+ def print_tool(tool) -> None:
213
+ """
214
+ Print a single LangChain tool in OpenAI format in a readable JSON structure.
205
215
 
206
- return results
216
+ Args:
217
+ tool: A langchain_core.tools.structured.StructuredTool instance
218
+ """
219
+ openai_tool = langchain_tool_to_openai_format(tool)
220
+ print(json.dumps(openai_tool, indent=2))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-blocks
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Simple building blocks for agentic AI systems with MCP client and conversation management
5
5
  Author-email: Magnus Bjelkenhed <bjelkenhed@gmail.com>
6
6
  License: MIT
File without changes