agentrun-inner-test 0.0.46__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. agentrun/__init__.py +325 -0
  2. agentrun/agent_runtime/__client_async_template.py +466 -0
  3. agentrun/agent_runtime/__endpoint_async_template.py +345 -0
  4. agentrun/agent_runtime/__init__.py +53 -0
  5. agentrun/agent_runtime/__runtime_async_template.py +477 -0
  6. agentrun/agent_runtime/api/__data_async_template.py +58 -0
  7. agentrun/agent_runtime/api/__init__.py +6 -0
  8. agentrun/agent_runtime/api/control.py +1362 -0
  9. agentrun/agent_runtime/api/data.py +98 -0
  10. agentrun/agent_runtime/client.py +868 -0
  11. agentrun/agent_runtime/endpoint.py +649 -0
  12. agentrun/agent_runtime/model.py +362 -0
  13. agentrun/agent_runtime/runtime.py +904 -0
  14. agentrun/credential/__client_async_template.py +177 -0
  15. agentrun/credential/__credential_async_template.py +216 -0
  16. agentrun/credential/__init__.py +28 -0
  17. agentrun/credential/api/__init__.py +5 -0
  18. agentrun/credential/api/control.py +606 -0
  19. agentrun/credential/client.py +319 -0
  20. agentrun/credential/credential.py +381 -0
  21. agentrun/credential/model.py +248 -0
  22. agentrun/integration/__init__.py +21 -0
  23. agentrun/integration/agentscope/__init__.py +12 -0
  24. agentrun/integration/agentscope/adapter.py +17 -0
  25. agentrun/integration/agentscope/builtin.py +65 -0
  26. agentrun/integration/agentscope/message_adapter.py +185 -0
  27. agentrun/integration/agentscope/model_adapter.py +60 -0
  28. agentrun/integration/agentscope/tool_adapter.py +59 -0
  29. agentrun/integration/builtin/__init__.py +16 -0
  30. agentrun/integration/builtin/model.py +93 -0
  31. agentrun/integration/builtin/sandbox.py +1234 -0
  32. agentrun/integration/builtin/toolset.py +47 -0
  33. agentrun/integration/crewai/__init__.py +12 -0
  34. agentrun/integration/crewai/adapter.py +9 -0
  35. agentrun/integration/crewai/builtin.py +65 -0
  36. agentrun/integration/crewai/model_adapter.py +31 -0
  37. agentrun/integration/crewai/tool_adapter.py +26 -0
  38. agentrun/integration/google_adk/__init__.py +12 -0
  39. agentrun/integration/google_adk/adapter.py +15 -0
  40. agentrun/integration/google_adk/builtin.py +65 -0
  41. agentrun/integration/google_adk/message_adapter.py +144 -0
  42. agentrun/integration/google_adk/model_adapter.py +46 -0
  43. agentrun/integration/google_adk/tool_adapter.py +235 -0
  44. agentrun/integration/langchain/__init__.py +30 -0
  45. agentrun/integration/langchain/adapter.py +15 -0
  46. agentrun/integration/langchain/builtin.py +71 -0
  47. agentrun/integration/langchain/message_adapter.py +141 -0
  48. agentrun/integration/langchain/model_adapter.py +37 -0
  49. agentrun/integration/langchain/tool_adapter.py +50 -0
  50. agentrun/integration/langgraph/__init__.py +35 -0
  51. agentrun/integration/langgraph/adapter.py +20 -0
  52. agentrun/integration/langgraph/agent_converter.py +1073 -0
  53. agentrun/integration/langgraph/builtin.py +65 -0
  54. agentrun/integration/pydantic_ai/__init__.py +12 -0
  55. agentrun/integration/pydantic_ai/adapter.py +13 -0
  56. agentrun/integration/pydantic_ai/builtin.py +65 -0
  57. agentrun/integration/pydantic_ai/model_adapter.py +44 -0
  58. agentrun/integration/pydantic_ai/tool_adapter.py +19 -0
  59. agentrun/integration/utils/__init__.py +112 -0
  60. agentrun/integration/utils/adapter.py +560 -0
  61. agentrun/integration/utils/canonical.py +164 -0
  62. agentrun/integration/utils/converter.py +134 -0
  63. agentrun/integration/utils/model.py +110 -0
  64. agentrun/integration/utils/tool.py +1759 -0
  65. agentrun/model/__client_async_template.py +357 -0
  66. agentrun/model/__init__.py +57 -0
  67. agentrun/model/__model_proxy_async_template.py +270 -0
  68. agentrun/model/__model_service_async_template.py +267 -0
  69. agentrun/model/api/__init__.py +6 -0
  70. agentrun/model/api/control.py +1173 -0
  71. agentrun/model/api/data.py +196 -0
  72. agentrun/model/client.py +674 -0
  73. agentrun/model/model.py +235 -0
  74. agentrun/model/model_proxy.py +439 -0
  75. agentrun/model/model_service.py +438 -0
  76. agentrun/sandbox/__aio_sandbox_async_template.py +523 -0
  77. agentrun/sandbox/__browser_sandbox_async_template.py +110 -0
  78. agentrun/sandbox/__client_async_template.py +491 -0
  79. agentrun/sandbox/__code_interpreter_sandbox_async_template.py +463 -0
  80. agentrun/sandbox/__init__.py +69 -0
  81. agentrun/sandbox/__sandbox_async_template.py +463 -0
  82. agentrun/sandbox/__template_async_template.py +152 -0
  83. agentrun/sandbox/aio_sandbox.py +905 -0
  84. agentrun/sandbox/api/__aio_data_async_template.py +335 -0
  85. agentrun/sandbox/api/__browser_data_async_template.py +140 -0
  86. agentrun/sandbox/api/__code_interpreter_data_async_template.py +206 -0
  87. agentrun/sandbox/api/__init__.py +19 -0
  88. agentrun/sandbox/api/__sandbox_data_async_template.py +107 -0
  89. agentrun/sandbox/api/aio_data.py +551 -0
  90. agentrun/sandbox/api/browser_data.py +172 -0
  91. agentrun/sandbox/api/code_interpreter_data.py +396 -0
  92. agentrun/sandbox/api/control.py +1051 -0
  93. agentrun/sandbox/api/playwright_async.py +492 -0
  94. agentrun/sandbox/api/playwright_sync.py +492 -0
  95. agentrun/sandbox/api/sandbox_data.py +154 -0
  96. agentrun/sandbox/browser_sandbox.py +185 -0
  97. agentrun/sandbox/client.py +925 -0
  98. agentrun/sandbox/code_interpreter_sandbox.py +823 -0
  99. agentrun/sandbox/model.py +397 -0
  100. agentrun/sandbox/sandbox.py +848 -0
  101. agentrun/sandbox/template.py +217 -0
  102. agentrun/server/__init__.py +191 -0
  103. agentrun/server/agui_normalizer.py +180 -0
  104. agentrun/server/agui_protocol.py +797 -0
  105. agentrun/server/invoker.py +309 -0
  106. agentrun/server/model.py +427 -0
  107. agentrun/server/openai_protocol.py +535 -0
  108. agentrun/server/protocol.py +140 -0
  109. agentrun/server/server.py +208 -0
  110. agentrun/toolset/__client_async_template.py +62 -0
  111. agentrun/toolset/__init__.py +51 -0
  112. agentrun/toolset/__toolset_async_template.py +204 -0
  113. agentrun/toolset/api/__init__.py +17 -0
  114. agentrun/toolset/api/control.py +262 -0
  115. agentrun/toolset/api/mcp.py +100 -0
  116. agentrun/toolset/api/openapi.py +1251 -0
  117. agentrun/toolset/client.py +102 -0
  118. agentrun/toolset/model.py +321 -0
  119. agentrun/toolset/toolset.py +270 -0
  120. agentrun/utils/__data_api_async_template.py +720 -0
  121. agentrun/utils/__init__.py +5 -0
  122. agentrun/utils/__resource_async_template.py +158 -0
  123. agentrun/utils/config.py +258 -0
  124. agentrun/utils/control_api.py +78 -0
  125. agentrun/utils/data_api.py +1120 -0
  126. agentrun/utils/exception.py +151 -0
  127. agentrun/utils/helper.py +108 -0
  128. agentrun/utils/log.py +77 -0
  129. agentrun/utils/model.py +168 -0
  130. agentrun/utils/resource.py +291 -0
  131. agentrun_inner_test-0.0.46.dist-info/METADATA +263 -0
  132. agentrun_inner_test-0.0.46.dist-info/RECORD +135 -0
  133. agentrun_inner_test-0.0.46.dist-info/WHEEL +5 -0
  134. agentrun_inner_test-0.0.46.dist-info/licenses/LICENSE +201 -0
  135. agentrun_inner_test-0.0.46.dist-info/top_level.txt +1 -0
@@ -0,0 +1,235 @@
1
+ """Google ADK 工具适配器 / Google ADK Tool Adapter
2
+
3
+ 将标准工具定义转换为 Google ADK 函数格式。"""
4
+
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ from agentrun.integration.utils.adapter import ToolAdapter
8
+ from agentrun.integration.utils.canonical import CanonicalTool
9
+ from agentrun.integration.utils.tool import normalize_tool_name
10
+
11
+
12
+ def _json_schema_to_google_schema(
13
+ schema: Dict[str, Any],
14
+ root_schema: Optional[Dict[str, Any]] = None,
15
+ ) -> Any:
16
+ """将 JSON Schema 转换为 Google ADK Schema
17
+
18
+ Google ADK 不支持 $ref 和 $defs,所以需要内联所有引用。
19
+
20
+ Args:
21
+ schema: JSON Schema 定义
22
+ root_schema: 根 schema,用于解析 $ref 引用
23
+
24
+ Returns:
25
+ Google ADK types.Schema 对象
26
+ """
27
+ from google.genai import types
28
+
29
+ if not schema or not isinstance(schema, dict):
30
+ return types.Schema(type=types.Type.OBJECT)
31
+
32
+ if root_schema is None:
33
+ root_schema = schema
34
+
35
+ # 处理 $ref 引用
36
+ if "$ref" in schema:
37
+ ref = schema["$ref"]
38
+ resolved = _resolve_schema_ref(ref, root_schema)
39
+ if resolved:
40
+ return _json_schema_to_google_schema(resolved, root_schema)
41
+ return types.Schema(type=types.Type.OBJECT)
42
+
43
+ schema_type = schema.get("type")
44
+ description = schema.get("description")
45
+
46
+ # 类型映射
47
+ type_mapping = {
48
+ "string": types.Type.STRING,
49
+ "integer": types.Type.INTEGER,
50
+ "number": types.Type.NUMBER,
51
+ "boolean": types.Type.BOOLEAN,
52
+ "array": types.Type.ARRAY,
53
+ "object": types.Type.OBJECT,
54
+ }
55
+
56
+ google_type = type_mapping.get(
57
+ str(schema_type or "object"), types.Type.OBJECT
58
+ )
59
+
60
+ # 处理数组类型
61
+ if schema_type == "array":
62
+ items_schema = schema.get("items")
63
+ items = None
64
+ if items_schema:
65
+ items = _json_schema_to_google_schema(items_schema, root_schema)
66
+ return types.Schema(
67
+ type=google_type,
68
+ description=description,
69
+ items=items,
70
+ )
71
+
72
+ # 处理对象类型
73
+ if schema_type == "object":
74
+ props = schema.get("properties", {})
75
+ required = schema.get("required", [])
76
+
77
+ google_props = {}
78
+ for prop_name, prop_schema in props.items():
79
+ google_props[prop_name] = _json_schema_to_google_schema(
80
+ prop_schema, root_schema
81
+ )
82
+
83
+ return types.Schema(
84
+ type=google_type,
85
+ description=description,
86
+ properties=google_props if google_props else None,
87
+ required=required if required else None,
88
+ )
89
+
90
+ # 基本类型
91
+ return types.Schema(
92
+ type=google_type,
93
+ description=description,
94
+ )
95
+
96
+
97
+ def _resolve_schema_ref(
98
+ ref: str, root_schema: Dict[str, Any]
99
+ ) -> Optional[Dict[str, Any]]:
100
+ """解析 JSON Schema $ref 引用
101
+
102
+ Args:
103
+ ref: $ref 字符串,如 "#/$defs/MyType" 或 "#/definitions/MyType"
104
+ root_schema: 根 schema,包含 $defs 或 definitions
105
+
106
+ Returns:
107
+ 解析后的 schema,如果无法解析则返回 None
108
+ """
109
+ if not ref or not ref.startswith("#/"):
110
+ return None
111
+
112
+ # 解析路径,如 "#/$defs/MyType" -> ["$defs", "MyType"]
113
+ path_parts = ref[2:].split("/")
114
+ current = root_schema
115
+
116
+ for part in path_parts:
117
+ if not isinstance(current, dict) or part not in current:
118
+ return None
119
+ current = current[part]
120
+
121
+ return current if isinstance(current, dict) else None
122
+
123
+
124
+ def _create_custom_function_tool_class():
125
+ """创建自定义 FunctionTool 类
126
+
127
+ 延迟创建以避免在模块导入时依赖 google.adk。
128
+ """
129
+ from google.adk.tools.base_tool import BaseTool
130
+
131
+ class CustomFunctionTool(BaseTool):
132
+ """自定义 Google ADK 工具类
133
+
134
+ 允许手动指定 FunctionDeclaration,避免 Pydantic 模型的 $ref 问题。
135
+ 继承自 google.adk.tools.BaseTool 以确保与 ADK Agent 兼容。
136
+ """
137
+
138
+ def __init__(
139
+ self,
140
+ func,
141
+ declaration,
142
+ ):
143
+ # 调用父类 __init__,传递 name 和 description
144
+ super().__init__(
145
+ name=declaration.name,
146
+ description=declaration.description or "",
147
+ )
148
+ self._func = func
149
+ self._declaration = declaration
150
+
151
+ def _get_declaration(self):
152
+ return self._declaration
153
+
154
+ async def run_async(self, *, args: Dict[str, Any], tool_context):
155
+ """异步执行工具函数"""
156
+ return self._func(**args)
157
+
158
+ return CustomFunctionTool
159
+
160
+
161
+ # 缓存类,避免重复创建
162
+ _CustomFunctionToolClass = None
163
+
164
+
165
+ def _get_custom_function_tool_class():
166
+ """获取 CustomFunctionTool 类(延迟加载)"""
167
+ global _CustomFunctionToolClass
168
+ if _CustomFunctionToolClass is None:
169
+ _CustomFunctionToolClass = _create_custom_function_tool_class()
170
+ return _CustomFunctionToolClass
171
+
172
+
173
+ class GoogleADKToolAdapter(ToolAdapter):
174
+ """Google ADK 工具适配器 / Google ADK Tool Adapter
175
+
176
+ 实现 CanonicalTool → Google ADK 函数的转换。
177
+ 由于 Google ADK 不支持复杂的 JSON Schema(包含 $ref 和 $defs),
178
+ 此适配器会手动构建 FunctionDeclaration 并使用自定义工具类。
179
+ """
180
+
181
+ def get_registered_tool(self, name: str) -> Optional[CanonicalTool]:
182
+ """根据名称获取最近注册的工具定义 / Google ADK Tool Adapter"""
183
+ return self._registered_tools.get(normalize_tool_name(name))
184
+
185
+ def from_canonical(self, tools: List[CanonicalTool]):
186
+ """将标准格式转换为 Google ADK 工具 / Google ADK Tool Adapter
187
+
188
+ 为每个工具创建自定义的 FunctionTool,手动指定参数 schema,
189
+ 以避免 Pydantic 模型产生的 $ref 问题。
190
+ """
191
+ from google.genai import types
192
+
193
+ result = []
194
+
195
+ for tool in tools:
196
+ # 记录工具定义
197
+ self._registered_tools[tool.name] = tool
198
+
199
+ # 从 parameters schema 构建 Google ADK Schema
200
+ parameters_schema = tool.parameters or {
201
+ "type": "object",
202
+ "properties": {},
203
+ }
204
+
205
+ google_schema = _json_schema_to_google_schema(
206
+ parameters_schema, parameters_schema
207
+ )
208
+
209
+ # 创建 FunctionDeclaration
210
+ declaration = types.FunctionDeclaration(
211
+ name=normalize_tool_name(tool.name),
212
+ description=tool.description or "",
213
+ parameters=google_schema,
214
+ )
215
+
216
+ # 创建包装函数
217
+ def make_wrapper(canonical_tool: CanonicalTool):
218
+ def wrapper(**kwargs):
219
+ if canonical_tool.func is None:
220
+ raise NotImplementedError(
221
+ f"Tool function for '{canonical_tool.name}' "
222
+ "is not implemented."
223
+ )
224
+ return canonical_tool.func(**kwargs)
225
+
226
+ return wrapper
227
+
228
+ wrapper_func = make_wrapper(tool)
229
+
230
+ # 创建自定义工具
231
+ CustomFunctionTool = _get_custom_function_tool_class()
232
+ custom_tool = CustomFunctionTool(wrapper_func, declaration)
233
+ result.append(custom_tool)
234
+
235
+ return result
@@ -0,0 +1,30 @@
1
+ """LangChain 集成模块
2
+
3
+ 使用 AgentRunConverter 将 LangChain 事件转换为 AG-UI 协议事件:
4
+
5
+ >>> from agentrun.integration.langchain import AgentRunConverter
6
+ >>>
7
+ >>> async def invoke_agent(request: AgentRequest):
8
+ ... converter = AgentRunConverter()
9
+ ... async for event in agent.astream_events(input_data, version="v2"):
10
+ ... for item in converter.convert(event):
11
+ ... yield item
12
+
13
+ 支持多种调用方式:
14
+ - agent.astream_events(input, version="v2") - 支持 token by token
15
+ - agent.stream(input, stream_mode="updates") - 按节点输出
16
+ - agent.astream(input, stream_mode="updates") - 异步按节点输出
17
+ """
18
+
19
+ from agentrun.integration.langgraph.agent_converter import (
20
+ AgentRunConverter,
21
+ ) # 向后兼容
22
+
23
+ from .builtin import model, sandbox_toolset, toolset
24
+
25
+ __all__ = [
26
+ "AgentRunConverter",
27
+ "model",
28
+ "toolset",
29
+ "sandbox_toolset",
30
+ ]
@@ -0,0 +1,15 @@
1
+ """LangChain 适配器 / LangChain Adapters
2
+
3
+ 提供 LangChain 框架的消息、工具和模型适配器。"""
4
+
5
+ from agentrun.integration.langchain.message_adapter import (
6
+ LangChainMessageAdapter,
7
+ )
8
+ from agentrun.integration.langchain.model_adapter import LangChainModelAdapter
9
+ from agentrun.integration.langchain.tool_adapter import LangChainToolAdapter
10
+
11
+ __all__ = [
12
+ "LangChainMessageAdapter",
13
+ "LangChainToolAdapter",
14
+ "LangChainModelAdapter",
15
+ ]
@@ -0,0 +1,71 @@
1
+ """LangChain 内置集成函数 / LangChain Built-in Integration Functions
2
+
3
+ 提供快速创建 LangChain 兼容模型和工具的便捷函数。
4
+ Provides convenient functions for quickly creating LangChain-compatible models and tools.
5
+ """
6
+
7
+ from typing import Any, Callable, List, Optional, Union
8
+
9
+ from typing_extensions import Unpack
10
+
11
+ from agentrun.integration.builtin import model as _model
12
+ from agentrun.integration.builtin import ModelArgs
13
+ from agentrun.integration.builtin import sandbox_toolset as _sandbox_toolset
14
+ from agentrun.integration.builtin import toolset as _toolset
15
+ from agentrun.integration.utils.tool import Tool
16
+ from agentrun.model import ModelProxy, ModelService
17
+ from agentrun.sandbox import TemplateType
18
+ from agentrun.toolset import ToolSet
19
+ from agentrun.utils.config import Config
20
+
21
+
22
+ def model(
23
+ name: Union[str, ModelProxy, ModelService],
24
+ **kwargs: Unpack[ModelArgs],
25
+ ):
26
+ """获取 AgentRun 模型并转换为 LangChain ``BaseChatModel``。 / LangChain Built-in Integration Functions"""
27
+
28
+ m = _model(input=name, **kwargs)
29
+ return m.to_langchain()
30
+
31
+
32
+ def toolset(
33
+ name: Union[str, ToolSet],
34
+ *,
35
+ prefix: Optional[str] = None,
36
+ modify_tool_name: Optional[Callable[[Tool], Tool]] = None,
37
+ filter_tools_by_name: Optional[Callable[[str], bool]] = None,
38
+ config: Optional[Config] = None,
39
+ ) -> List[Any]:
40
+ """将内置工具集封装为 LangChain ``StructuredTool`` 列表。 / LangChain Built-in Integration Functions"""
41
+
42
+ ts = _toolset(input=name, config=config)
43
+ return ts.to_langchain(
44
+ prefix=prefix,
45
+ modify_tool_name=modify_tool_name,
46
+ filter_tools_by_name=filter_tools_by_name,
47
+ )
48
+
49
+
50
+ def sandbox_toolset(
51
+ template_name: str,
52
+ *,
53
+ template_type: TemplateType = TemplateType.CODE_INTERPRETER,
54
+ sandbox_idle_timeout_seconds: int = 600,
55
+ prefix: Optional[str] = None,
56
+ modify_tool_name: Optional[Callable[[Tool], Tool]] = None,
57
+ filter_tools_by_name: Optional[Callable[[str], bool]] = None,
58
+ config: Optional[Config] = None,
59
+ ) -> List[Any]:
60
+ """将沙箱模板封装为 LangChain ``StructuredTool`` 列表。 / LangChain Built-in Integration Functions"""
61
+
62
+ return _sandbox_toolset(
63
+ template_name=template_name,
64
+ template_type=template_type,
65
+ config=config,
66
+ sandbox_idle_timeout_seconds=sandbox_idle_timeout_seconds,
67
+ ).to_langchain(
68
+ prefix=prefix,
69
+ modify_tool_name=modify_tool_name,
70
+ filter_tools_by_name=filter_tools_by_name,
71
+ )
@@ -0,0 +1,141 @@
1
+ """LangChain 消息适配器 / LangChain Message Adapter
2
+
3
+ 将 LangChain BaseMessage 转换为标准格式,供 ModelAdapter 内部使用。
4
+ Converts LangChain BaseMessage to canonical format for internal use by ModelAdapter.
5
+ """
6
+
7
+ import json
8
+ from typing import Any, List
9
+
10
+ from agentrun.integration.utils.adapter import MessageAdapter
11
+ from agentrun.integration.utils.canonical import (
12
+ CanonicalMessage,
13
+ CanonicalToolCall,
14
+ MessageRole,
15
+ )
16
+
17
+
18
+ class LangChainMessageAdapter(MessageAdapter):
19
+ """LangChain 消息适配器 / LangChain Message Adapter
20
+
21
+ 实现 LangChain BaseMessage → CanonicalMessage 的转换。
22
+ Implements conversion from LangChain BaseMessage to CanonicalMessage.
23
+ """
24
+
25
+ def to_canonical(self, messages: Any) -> List[CanonicalMessage]:
26
+ """将 LangChain BaseMessage 转换为标准格式 / LangChain Message Adapter"""
27
+ try:
28
+ from langchain_core.messages import (
29
+ AIMessage,
30
+ HumanMessage,
31
+ SystemMessage,
32
+ ToolMessage,
33
+ )
34
+ except ImportError as e:
35
+ raise ImportError(
36
+ "LangChain is not installed. "
37
+ "Install it with: pip install langchain-core"
38
+ ) from e
39
+
40
+ canonical = []
41
+ for msg in messages:
42
+ if isinstance(msg, SystemMessage):
43
+ canonical.append(
44
+ CanonicalMessage(
45
+ role=MessageRole.SYSTEM,
46
+ content=msg.content
47
+ if hasattr(msg, "content")
48
+ else None,
49
+ )
50
+ )
51
+ elif isinstance(msg, HumanMessage):
52
+ canonical.append(
53
+ CanonicalMessage(
54
+ role=MessageRole.USER,
55
+ content=msg.content
56
+ if hasattr(msg, "content")
57
+ else None,
58
+ )
59
+ )
60
+ elif isinstance(msg, AIMessage):
61
+ tool_calls = None
62
+ if hasattr(msg, "tool_calls") and msg.tool_calls:
63
+ tool_calls = []
64
+ for call in msg.tool_calls:
65
+ # LangChain tool_calls: {"id": ..., "name": ..., "args": ...}
66
+ call_id = (
67
+ call.get("id")
68
+ if isinstance(call, dict)
69
+ else getattr(call, "id", "")
70
+ )
71
+ call_name = (
72
+ call.get("name")
73
+ if isinstance(call, dict)
74
+ else getattr(call, "name", "")
75
+ )
76
+ call_args = (
77
+ call.get("args")
78
+ if isinstance(call, dict)
79
+ else getattr(call, "args", {})
80
+ )
81
+
82
+ # 如果 args 是字符串,尝试解析
83
+ if isinstance(call_args, str):
84
+ try:
85
+ call_args = json.loads(call_args)
86
+ except json.JSONDecodeError:
87
+ call_args = {}
88
+
89
+ tool_calls.append(
90
+ CanonicalToolCall(
91
+ id=str(call_id),
92
+ name=str(call_name),
93
+ arguments=(
94
+ call_args
95
+ if isinstance(call_args, dict)
96
+ else {}
97
+ ),
98
+ )
99
+ )
100
+
101
+ canonical.append(
102
+ CanonicalMessage(
103
+ role=MessageRole.ASSISTANT,
104
+ content=msg.content
105
+ if hasattr(msg, "content")
106
+ else None,
107
+ tool_calls=tool_calls,
108
+ )
109
+ )
110
+ elif isinstance(msg, ToolMessage):
111
+ content = msg.content
112
+ if type(content) is not str:
113
+ content = str(content)
114
+
115
+ canonical.append(
116
+ CanonicalMessage(
117
+ role=MessageRole.TOOL,
118
+ content=content,
119
+ tool_call_id=(
120
+ msg.tool_call_id
121
+ if hasattr(msg, "tool_call_id")
122
+ else None
123
+ ),
124
+ )
125
+ )
126
+ else:
127
+ # 未知消息类型,尝试提取基本信息
128
+ role_str = getattr(msg, "type", "user").lower()
129
+ if "system" in role_str:
130
+ role = MessageRole.SYSTEM
131
+ elif "assistant" in role_str or "ai" in role_str:
132
+ role = MessageRole.ASSISTANT
133
+ elif "tool" in role_str:
134
+ role = MessageRole.TOOL
135
+ else:
136
+ role = MessageRole.USER
137
+
138
+ content = getattr(msg, "content", None)
139
+ canonical.append(CanonicalMessage(role=role, content=content))
140
+
141
+ return canonical
@@ -0,0 +1,37 @@
1
+ """LangChain 模型适配器 / LangChain Model Adapter
2
+
3
+ 将 CommonModel 包装为 LangChain BaseChatModel。"""
4
+
5
+ import inspect
6
+ import json
7
+ from typing import Any, List, Optional
8
+
9
+ from agentrun.integration.langchain.message_adapter import (
10
+ LangChainMessageAdapter,
11
+ )
12
+ from agentrun.integration.utils.adapter import ModelAdapter
13
+
14
+
15
+ class LangChainModelAdapter(ModelAdapter):
16
+ """LangChain 模型适配器 / LangChain Model Adapter
17
+
18
+ 将 CommonModel 包装为 LangChain BaseChatModel。"""
19
+
20
+ def __init__(self):
21
+ """初始化适配器,创建内部的消息适配器 / LangChain Message Adapter"""
22
+ self._message_adapter = LangChainMessageAdapter()
23
+
24
+ def wrap_model(self, common_model: Any) -> Any:
25
+ """包装 CommonModel 为 LangChain BaseChatModel / LangChain Model Adapter"""
26
+ from langchain_openai import ChatOpenAI
27
+
28
+ info = common_model.get_model_info() # 确保模型可用
29
+ return ChatOpenAI(
30
+ name=info.model,
31
+ api_key=info.api_key,
32
+ model=info.model,
33
+ base_url=info.base_url,
34
+ default_headers=info.headers,
35
+ stream_usage=True,
36
+ streaming=True, # 启用流式输出以支持 token by token
37
+ )
@@ -0,0 +1,50 @@
1
+ """LangChain 工具适配器 / LangChain Tool Adapter
2
+
3
+ 将标准工具定义转换为 LangChain StructuredTool 格式。"""
4
+
5
+ from typing import Any, List
6
+
7
+ from agentrun.integration.utils.adapter import ToolAdapter
8
+ from agentrun.integration.utils.canonical import CanonicalTool
9
+
10
+
11
+ class LangChainToolAdapter(ToolAdapter):
12
+ """LangChain 工具适配器 / LangChain Tool Adapter
13
+
14
+ 实现 CanonicalTool → LangChain StructuredTool 的转换。"""
15
+
16
+ def from_canonical(self, tools: List[CanonicalTool]) -> Any:
17
+ """将标准格式转换为 LangChain StructuredTool / LangChain Tool Adapter"""
18
+ try:
19
+ from langchain_core.tools import StructuredTool
20
+ except ImportError as e:
21
+ raise ImportError(
22
+ "LangChain is not installed. "
23
+ "Install it with: pip install langchain-core"
24
+ ) from e
25
+
26
+ from agentrun.integration.utils.tool import _json_schema_to_pydantic
27
+
28
+ result = []
29
+ for tool in tools:
30
+ # 从 JSON Schema 创建 Pydantic 模型
31
+ args_schema = _json_schema_to_pydantic(
32
+ f"{tool.name}_Args", tool.parameters
33
+ )
34
+
35
+ if args_schema is None:
36
+ # 如果无法创建 schema,使用空模型
37
+ from pydantic import create_model
38
+
39
+ args_schema = create_model(f"{tool.name}_Args")
40
+
41
+ result.append(
42
+ StructuredTool.from_function(
43
+ func=tool.func,
44
+ name=tool.name,
45
+ description=tool.description,
46
+ args_schema=args_schema,
47
+ )
48
+ )
49
+
50
+ return result
@@ -0,0 +1,35 @@
1
+ """LangGraph 集成模块
2
+
3
+ 使用 AgentRunConverter 将 LangGraph 事件转换为 AG-UI 协议事件:
4
+
5
+ >>> from agentrun.integration.langgraph import AgentRunConverter
6
+ >>>
7
+ >>> async def invoke_agent(request: AgentRequest):
8
+ ... converter = AgentRunConverter()
9
+ ... async for event in agent.astream_events(input_data, version="v2"):
10
+ ... for item in converter.convert(event):
11
+ ... yield item
12
+
13
+ 或使用静态方法(无状态):
14
+
15
+ >>> from agentrun.integration.langgraph import AgentRunConverter
16
+ >>>
17
+ >>> async for event in agent.astream_events(input_data, version="v2"):
18
+ ... for item in AgentRunConverter.to_agui_events(event):
19
+ ... yield item
20
+
21
+ 支持多种调用方式:
22
+ - agent.astream_events(input, version="v2") - 支持 token by token
23
+ - agent.stream(input, stream_mode="updates") - 按节点输出
24
+ - agent.astream(input, stream_mode="updates") - 异步按节点输出
25
+ """
26
+
27
+ from .agent_converter import AgentRunConverter
28
+ from .builtin import model, sandbox_toolset, toolset
29
+
30
+ __all__ = [
31
+ "AgentRunConverter",
32
+ "model",
33
+ "toolset",
34
+ "sandbox_toolset",
35
+ ]
@@ -0,0 +1,20 @@
1
+ """LangGraph 适配器 / LangGraph Adapters
2
+
3
+ LangGraph 与 LangChain 完全兼容,因此直接复用 LangChain 的适配器。"""
4
+
5
+ from agentrun.integration.langchain.adapter import (
6
+ LangChainMessageAdapter,
7
+ LangChainModelAdapter,
8
+ LangChainToolAdapter,
9
+ )
10
+
11
+ # LangGraph 使用与 LangChain 相同的适配器
12
+ LangGraphMessageAdapter = LangChainMessageAdapter
13
+ LangGraphToolAdapter = LangChainToolAdapter
14
+ LangGraphModelAdapter = LangChainModelAdapter
15
+
16
+ __all__ = [
17
+ "LangGraphMessageAdapter",
18
+ "LangGraphToolAdapter",
19
+ "LangGraphModelAdapter",
20
+ ]