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,560 @@
1
+ """适配器接口定义 / Adapter Interface Definition
2
+
3
+ 定义统一的适配器接口,所有框架适配器都实现这些接口。
4
+ Defines unified adapter interfaces that all framework adapters implement.
5
+
6
+ 这样可以确保一致的转换行为,并最大化代码复用。
7
+ This ensures consistent conversion behavior and maximizes code reuse.
8
+ """
9
+
10
+ from abc import ABC, abstractmethod
11
+ import inspect
12
+ import re
13
+ from typing import Any, Callable, Dict, List, Optional, Union
14
+
15
+ from pydantic import create_model, Field
16
+
17
+ from agentrun.integration.utils.canonical import CanonicalMessage, CanonicalTool
18
+ from agentrun.integration.utils.model import CommonModel
19
+ from agentrun.integration.utils.tool import normalize_tool_name
20
+
21
+ # 用于缓存动态创建的 Pydantic 模型,避免重复创建
22
+ _dynamic_models_cache: Dict[str, type] = {}
23
+
24
+
25
+ def _resolve_schema_ref(
26
+ ref: str, root_schema: Dict[str, Any]
27
+ ) -> Optional[Dict[str, Any]]:
28
+ """解析 JSON Schema $ref 引用
29
+
30
+ Args:
31
+ ref: $ref 字符串,如 "#/$defs/MyType" 或 "#/definitions/MyType"
32
+ root_schema: 根 schema,包含 $defs 或 definitions
33
+
34
+ Returns:
35
+ 解析后的 schema,如果无法解析则返回 None
36
+ """
37
+ if not ref or not ref.startswith("#/"):
38
+ return None
39
+
40
+ # 解析路径,如 "#/$defs/MyType" -> ["$defs", "MyType"]
41
+ path_parts = ref[2:].split("/")
42
+ current = root_schema
43
+
44
+ for part in path_parts:
45
+ if not isinstance(current, dict) or part not in current:
46
+ return None
47
+ current = current[part]
48
+
49
+ return current if isinstance(current, dict) else None
50
+
51
+
52
+ def _generate_model_name(
53
+ schema: Dict[str, Any], prefix: str = "Dynamic"
54
+ ) -> str:
55
+ """为 schema 生成唯一的模型名称"""
56
+ # 优先使用 schema 中的 title
57
+ title = schema.get("title")
58
+ if title:
59
+ # 清理名称,只保留字母数字
60
+ clean_name = re.sub(r"[^a-zA-Z0-9]", "", title)
61
+ if clean_name:
62
+ return clean_name
63
+
64
+ # 使用属性名生成名称
65
+ properties = schema.get("properties", {})
66
+ if properties:
67
+ prop_names = sorted(properties.keys())[:3] # 最多取3个属性名
68
+ name = "".join(n.title() for n in prop_names)
69
+ return f"{prefix}{name}Model"
70
+
71
+ return f"{prefix}Model"
72
+
73
+
74
+ def _schema_to_type_description(
75
+ schema: Dict[str, Any],
76
+ root_schema: Optional[Dict[str, Any]] = None,
77
+ indent: int = 0,
78
+ ) -> str:
79
+ """将 JSON Schema 转换为人类可读的类型描述
80
+
81
+ 用于在函数文档字符串中描述复杂类型结构,
82
+ 帮助不支持精确类型的框架(如 Google ADK)理解参数类型。
83
+
84
+ Args:
85
+ schema: JSON Schema 定义
86
+ root_schema: 根 schema,用于解析 $ref 引用
87
+ indent: 缩进级别
88
+
89
+ Returns:
90
+ 类型描述字符串
91
+ """
92
+ if not schema or not isinstance(schema, dict):
93
+ return "any"
94
+
95
+ if root_schema is None:
96
+ root_schema = schema
97
+
98
+ indent_prefix = " " * indent
99
+
100
+ # 处理 $ref 引用
101
+ if "$ref" in schema:
102
+ resolved = _resolve_schema_ref(schema["$ref"], root_schema)
103
+ if resolved:
104
+ return _schema_to_type_description(resolved, root_schema, indent)
105
+ return "object"
106
+
107
+ schema_type = schema.get("type")
108
+
109
+ # 处理 anyOf / oneOf
110
+ if "anyOf" in schema:
111
+ types = [
112
+ _schema_to_type_description(s, root_schema, indent)
113
+ for s in schema["anyOf"]
114
+ ]
115
+ return " | ".join(types)
116
+
117
+ if "oneOf" in schema:
118
+ types = [
119
+ _schema_to_type_description(s, root_schema, indent)
120
+ for s in schema["oneOf"]
121
+ ]
122
+ return " | ".join(types)
123
+
124
+ # null 类型
125
+ if schema_type == "null":
126
+ return "null"
127
+
128
+ # 数组类型
129
+ if schema_type == "array":
130
+ items_schema = schema.get("items")
131
+ if items_schema:
132
+ item_desc = _schema_to_type_description(
133
+ items_schema, root_schema, indent
134
+ )
135
+ return f"array[{item_desc}]"
136
+ return "array"
137
+
138
+ # 对象类型 - 详细描述属性
139
+ if schema_type == "object":
140
+ properties = schema.get("properties", {})
141
+ required = set(schema.get("required", []))
142
+
143
+ if not properties:
144
+ return "object"
145
+
146
+ # 获取标题
147
+ title = schema.get("title", "object")
148
+ lines = [f"{title} {{"]
149
+
150
+ for prop_name, prop_schema in properties.items():
151
+ prop_desc = _schema_to_type_description(
152
+ prop_schema, root_schema, indent + 1
153
+ )
154
+ description = prop_schema.get("description", "")
155
+ optional_marker = "" if prop_name in required else "?"
156
+
157
+ prop_line = (
158
+ f"{indent_prefix} {prop_name}{optional_marker}: {prop_desc}"
159
+ )
160
+ if description:
161
+ prop_line += f" # {description}"
162
+ lines.append(prop_line)
163
+
164
+ lines.append(f"{indent_prefix}}}")
165
+ return "\n".join(lines)
166
+
167
+ # 基本类型
168
+ type_names = {
169
+ "string": "string",
170
+ "integer": "integer",
171
+ "number": "number",
172
+ "boolean": "boolean",
173
+ }
174
+
175
+ if schema_type in type_names:
176
+ # 添加枚举值信息
177
+ enum_values = schema.get("enum")
178
+ if enum_values:
179
+ enum_str = ", ".join(repr(v) for v in enum_values)
180
+ return f"{type_names[schema_type]}({enum_str})"
181
+ return type_names[schema_type]
182
+
183
+ return "any"
184
+
185
+
186
+ def _generate_params_docstring(
187
+ parameters_schema: Dict[str, Any],
188
+ ) -> str:
189
+ """生成参数的详细文档字符串
190
+
191
+ 为复杂类型生成详细的类型描述,用于不支持精确类型的框架。
192
+
193
+ Args:
194
+ parameters_schema: 参数的 JSON Schema
195
+
196
+ Returns:
197
+ 参数文档字符串
198
+ """
199
+ properties = parameters_schema.get("properties", {})
200
+ required = set(parameters_schema.get("required", []))
201
+
202
+ if not properties:
203
+ return ""
204
+
205
+ lines = ["\n\nArgs:"]
206
+
207
+ for param_name, param_schema in properties.items():
208
+ # 基础描述
209
+ description = param_schema.get("description", "")
210
+ optional_marker = " (optional)" if param_name not in required else ""
211
+
212
+ # 获取类型描述
213
+ type_desc = _schema_to_type_description(param_schema, parameters_schema)
214
+
215
+ # 检查是否是复杂类型(包含换行的描述)
216
+ if "\n" in type_desc:
217
+ # 复杂类型,使用多行格式
218
+ lines.append(f" {param_name}{optional_marker}:")
219
+ if description:
220
+ lines.append(f" {description}")
221
+ lines.append(" Type:")
222
+ # 缩进复杂类型描述
223
+ for type_line in type_desc.split("\n"):
224
+ lines.append(f" {type_line}")
225
+ else:
226
+ # 简单类型
227
+ param_line = f" {param_name} ({type_desc}){optional_marker}"
228
+ if description:
229
+ param_line += f": {description}"
230
+ lines.append(param_line)
231
+
232
+ return "\n".join(lines)
233
+
234
+
235
+ def _schema_to_pydantic_model(
236
+ schema: Dict[str, Any],
237
+ root_schema: Optional[Dict[str, Any]] = None,
238
+ model_name: Optional[str] = None,
239
+ ) -> type:
240
+ """将 JSON Schema 转换为 Pydantic 模型
241
+
242
+ Args:
243
+ schema: 对象类型的 JSON Schema
244
+ root_schema: 根 schema,用于解析 $ref
245
+ model_name: 可选的模型名称
246
+
247
+ Returns:
248
+ 动态创建的 Pydantic 模型类
249
+ """
250
+ if root_schema is None:
251
+ root_schema = schema
252
+
253
+ # 生成模型名称
254
+ if not model_name:
255
+ model_name = _generate_model_name(schema)
256
+
257
+ # 检查缓存
258
+ cache_key = f"{model_name}_{id(schema)}"
259
+ if cache_key in _dynamic_models_cache:
260
+ return _dynamic_models_cache[cache_key]
261
+
262
+ properties = schema.get("properties", {})
263
+ required_fields = set(schema.get("required", []))
264
+
265
+ if not properties:
266
+ # 无属性的对象,返回基础 dict
267
+ return dict
268
+
269
+ fields: Dict[str, Any] = {}
270
+
271
+ for field_name, field_schema in properties.items():
272
+ # 递归获取字段类型
273
+ field_type = schema_to_python_type(field_schema, root_schema)
274
+
275
+ # 获取字段描述
276
+ description = field_schema.get("description", "")
277
+ default = field_schema.get("default")
278
+
279
+ # 构建字段定义
280
+ if field_name in required_fields:
281
+ fields[field_name] = (field_type, Field(description=description))
282
+ else:
283
+ # 可选字段
284
+ fields[field_name] = (
285
+ Optional[field_type],
286
+ Field(default=default, description=description),
287
+ )
288
+
289
+ # 动态创建 Pydantic 模型
290
+ try:
291
+ model = create_model(model_name, **fields)
292
+ _dynamic_models_cache[cache_key] = model
293
+ return model
294
+ except Exception:
295
+ # 如果创建失败,回退到 dict
296
+ return dict
297
+
298
+
299
+ def schema_to_python_type(
300
+ schema: Dict[str, Any],
301
+ root_schema: Optional[Dict[str, Any]] = None,
302
+ ) -> Any:
303
+ """将 JSON Schema 转换为 Python 类型注解
304
+
305
+ 支持复杂类型:嵌套对象、数组元素类型、联合类型、$ref 引用等。
306
+ 对于嵌套对象,会动态创建 Pydantic 模型以保留完整的类型信息。
307
+
308
+ Args:
309
+ schema: JSON Schema 定义
310
+ root_schema: 根 schema,用于解析 $ref 引用。
311
+ 如果未提供,则使用 schema 本身作为根。
312
+
313
+ Returns:
314
+ Python 类型注解(可能是基本类型、List、Optional、Union 或 Pydantic 模型)
315
+ """
316
+ if not schema or not isinstance(schema, dict):
317
+ return Any
318
+
319
+ # 如果没有提供 root_schema,使用当前 schema 作为根
320
+ if root_schema is None:
321
+ root_schema = schema
322
+
323
+ # 处理 $ref 引用
324
+ if "$ref" in schema:
325
+ resolved = _resolve_schema_ref(schema["$ref"], root_schema)
326
+ if resolved:
327
+ return schema_to_python_type(resolved, root_schema)
328
+ # 无法解析 $ref,返回 dict(对象类型的默认)
329
+ return dict
330
+
331
+ schema_type = schema.get("type")
332
+
333
+ # 处理 anyOf / oneOf(联合类型)
334
+ if "anyOf" in schema:
335
+ types = [schema_to_python_type(s, root_schema) for s in schema["anyOf"]]
336
+ # 过滤掉 None 类型,用于构造 Optional
337
+ non_none_types = [t for t in types if t is not type(None)]
338
+ has_none = any(t is type(None) for t in types)
339
+
340
+ if len(non_none_types) == 1 and has_none:
341
+ return Optional[non_none_types[0]]
342
+ elif len(non_none_types) > 1:
343
+ return Union[tuple(non_none_types)]
344
+ elif non_none_types:
345
+ return non_none_types[0]
346
+ return Any
347
+
348
+ if "oneOf" in schema:
349
+ types = [schema_to_python_type(s, root_schema) for s in schema["oneOf"]]
350
+ non_none_types = [t for t in types if t is not type(None)]
351
+ if len(non_none_types) > 1:
352
+ return Union[tuple(non_none_types)]
353
+ elif non_none_types:
354
+ return non_none_types[0]
355
+ return Any
356
+
357
+ # 处理 null 类型
358
+ if schema_type == "null":
359
+ return type(None)
360
+
361
+ # 处理数组类型
362
+ if schema_type == "array":
363
+ items_schema = schema.get("items")
364
+ if items_schema:
365
+ item_type = schema_to_python_type(items_schema, root_schema)
366
+ return List[item_type]
367
+ return List[Any]
368
+
369
+ # 处理对象类型 - 动态创建 Pydantic 模型
370
+ if schema_type == "object":
371
+ properties = schema.get("properties")
372
+ if properties:
373
+ # 有属性定义,创建 Pydantic 模型
374
+ return _schema_to_pydantic_model(schema, root_schema)
375
+ # 无属性的通用对象
376
+ return dict
377
+
378
+ # 基本类型映射
379
+ type_mapping: Dict[str, type] = {
380
+ "string": str,
381
+ "integer": int,
382
+ "number": float,
383
+ "boolean": bool,
384
+ }
385
+
386
+ if schema_type and schema_type in type_mapping:
387
+ return type_mapping[schema_type]
388
+
389
+ return Any
390
+
391
+
392
+ class MessageAdapter(ABC):
393
+ """消息格式适配器接口
394
+
395
+ 用于在 ModelAdapter 内部进行消息格式转换。
396
+ 只需要将框架消息转换为标准 OpenAI 格式。
397
+
398
+ 转换流程:
399
+ - 框架消息 → to_canonical() → CanonicalMessage(OpenAI 格式)
400
+ """
401
+
402
+ @abstractmethod
403
+ def to_canonical(self, messages: Any) -> List[CanonicalMessage]:
404
+ """将框架消息转换为标准格式(供 ModelAdapter 内部使用)
405
+
406
+ Args:
407
+ messages: 框架特定的消息格式
408
+
409
+ Returns:
410
+ 标准格式消息列表
411
+ """
412
+ pass
413
+
414
+
415
+ class ToolAdapter(ABC):
416
+ """工具格式适配器接口 / Utils Adapters
417
+
418
+ 用于将标准工具定义转换为框架特定格式。
419
+ 单向转换:CanonicalTool → 框架工具"""
420
+
421
+ def __init__(self) -> None:
422
+ super().__init__()
423
+
424
+ # 记录工具定义,便于模型适配器回溯参数 schema
425
+ self._registered_tools: Dict[str, CanonicalTool] = {}
426
+
427
+ @abstractmethod
428
+ def from_canonical(self, tools: List[CanonicalTool]) -> Any:
429
+ """将标准工具转换为框架特定格式 / 将标准工具Converts为框架特定格式
430
+
431
+ Args:
432
+ tools: 标准格式工具列表
433
+
434
+ Returns:
435
+ 框架特定的工具格式"""
436
+ pass
437
+
438
+ def function_tools(
439
+ self,
440
+ tools: List[CanonicalTool],
441
+ modify_func: Optional[Callable[..., Any]] = None,
442
+ include_type_docstring: bool = False,
443
+ ):
444
+ """将标准格式转换为可调用函数工具
445
+
446
+ 通过函数的类型注解推断参数,动态创建带注解的函数。
447
+
448
+ Args:
449
+ tools: 标准格式工具列表
450
+ modify_func: 可选的函数调用修改器
451
+ include_type_docstring: 是否在文档字符串中包含详细的类型描述
452
+ 对于不支持精确类型的框架(如 Google ADK),可以设为 True
453
+ 以便在函数文档中包含复杂类型的结构描述"""
454
+ result = []
455
+
456
+ for tool in tools:
457
+ # 记录工具定义
458
+ self._registered_tools[tool.name] = tool
459
+
460
+ # 从 parameters schema 构建函数签名
461
+ parameters_schema = tool.parameters or {
462
+ "type": "object",
463
+ "properties": {},
464
+ }
465
+ properties = parameters_schema.get("properties", {})
466
+ required = set(parameters_schema.get("required", []))
467
+
468
+ # 构建函数参数
469
+ params = []
470
+ annotations = {}
471
+
472
+ for param_name, param_schema in properties.items():
473
+ # 使用递归类型转换处理复杂类型
474
+ # 传入 parameters_schema 作为根 schema 以解析 $ref 引用
475
+ param_type = schema_to_python_type(
476
+ param_schema, parameters_schema
477
+ )
478
+
479
+ # 设置默认值
480
+ default = (
481
+ inspect.Parameter.empty if param_name in required else None
482
+ )
483
+
484
+ params.append(
485
+ inspect.Parameter(
486
+ param_name,
487
+ inspect.Parameter.KEYWORD_ONLY,
488
+ default=default,
489
+ annotation=param_type,
490
+ )
491
+ )
492
+ annotations[param_name] = param_type
493
+
494
+ # 创建带正确签名的函数
495
+ def make_tool_function(
496
+ canonical_tool: CanonicalTool,
497
+ sig: inspect.Signature,
498
+ annots: dict,
499
+ params_schema: dict,
500
+ add_type_doc: bool,
501
+ ):
502
+ def tool_func(**kwargs):
503
+ if canonical_tool.func is None:
504
+ raise NotImplementedError(
505
+ f"Tool function for '{canonical_tool.name}' "
506
+ "is not implemented."
507
+ )
508
+
509
+ if modify_func:
510
+ return modify_func(canonical_tool, **kwargs)
511
+
512
+ return canonical_tool.func(**kwargs)
513
+
514
+ # 设置函数元数据(函数名也需要标准化以防第三方工具名限制)
515
+ tool_func.__name__ = normalize_tool_name(canonical_tool.name)
516
+
517
+ # 生成文档字符串
518
+ base_doc = canonical_tool.description or ""
519
+ if add_type_doc:
520
+ # 对于不支持精确类型的框架,在文档中包含详细的类型描述
521
+ params_doc = _generate_params_docstring(params_schema)
522
+ tool_func.__doc__ = base_doc + params_doc
523
+ else:
524
+ tool_func.__doc__ = base_doc
525
+
526
+ tool_func.__annotations__ = annots
527
+ object.__setattr__(tool_func, "__signature__", sig)
528
+
529
+ return tool_func
530
+
531
+ # 创建签名
532
+ signature = inspect.Signature(params)
533
+ wrapped_func = make_tool_function(
534
+ tool,
535
+ signature,
536
+ annotations,
537
+ parameters_schema,
538
+ include_type_docstring,
539
+ )
540
+
541
+ result.append(wrapped_func)
542
+
543
+ return result
544
+
545
+
546
+ class ModelAdapter(ABC):
547
+ """模型适配器接口 / Utils Model Adapter
548
+
549
+ 用于包装框架模型,使其能够与 CommonModel 协同工作。"""
550
+
551
+ @abstractmethod
552
+ def wrap_model(self, common_model: CommonModel) -> Any:
553
+ """包装 CommonModel 为框架特定的模型格式 / 包装 CommonModel 为framework特定的模型格式
554
+
555
+ Args:
556
+ common_model: CommonModel 实例
557
+
558
+ Returns:
559
+ 框架特定的模型对象"""
560
+ pass