agstack 1.7.0__tar.gz → 1.8.0__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.
- {agstack-1.7.0 → agstack-1.8.0}/PKG-INFO +3 -3
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/__init__.py +3 -1
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/flow.py +2 -5
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/__init__.py +0 -10
- agstack-1.8.0/agstack/llm/flow/registry.py +139 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack.egg-info/PKG-INFO +3 -3
- {agstack-1.7.0 → agstack-1.8.0}/agstack.egg-info/SOURCES.txt +0 -1
- {agstack-1.7.0 → agstack-1.8.0}/agstack.egg-info/requires.txt +2 -2
- {agstack-1.7.0 → agstack-1.8.0}/pyproject.toml +3 -3
- agstack-1.7.0/agstack/llm/flow/registry.py +0 -81
- agstack-1.7.0/agstack/registry.py +0 -187
- {agstack-1.7.0 → agstack-1.8.0}/LICENSE +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/README.md +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/config/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/config/logger.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/config/manager.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/config/types.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/contexts.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/decorators.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/events.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/exceptions.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/fastapi/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/fastapi/exception.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/fastapi/middleware.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/fastapi/offline.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/fastapi/sse.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/infra/db/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/infra/es/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/infra/kg/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/infra/mq/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/client.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/agent.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/context.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/event.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/exceptions.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/factory.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/loader.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/agent_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/base.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/detect_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/llm_chat_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/llm_embed_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/llm_rerank_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/python_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/nodes/tool_node.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/records.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/sandbox.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/state.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/flow/tool.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/prompts.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/llm/token.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/schema.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/security/__init__.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/security/casbin.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/security/crypt.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack/status.py +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack.egg-info/dependency_links.txt +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/agstack.egg-info/top_level.txt +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/setup.cfg +0 -0
- {agstack-1.7.0 → agstack-1.8.0}/tests/test_flow_io.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agstack
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: Production-ready toolkit for building FastAPI and LLM applications
|
|
5
5
|
Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
6
6
|
Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
@@ -27,7 +27,7 @@ Requires-Dist: fastapi>=0.133.1
|
|
|
27
27
|
Requires-Dist: jwcrypto>=1.5.6
|
|
28
28
|
Requires-Dist: loguru>=0.7.3
|
|
29
29
|
Requires-Dist: nebula3-python>=3.8.3
|
|
30
|
-
Requires-Dist: openai>=2.
|
|
30
|
+
Requires-Dist: openai>=2.28.0
|
|
31
31
|
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
32
32
|
Requires-Dist: pycasbin>=2.8.0
|
|
33
33
|
Requires-Dist: pydantic>=2.12.4
|
|
@@ -35,7 +35,7 @@ Requires-Dist: python-multipart>=0.0.20
|
|
|
35
35
|
Requires-Dist: requests>=2.32.5
|
|
36
36
|
Requires-Dist: RestrictedPython>=7.0
|
|
37
37
|
Requires-Dist: sqlalchemy[asyncio]>=2.0.48
|
|
38
|
-
Requires-Dist: sqlobjects>=1.
|
|
38
|
+
Requires-Dist: sqlobjects>=1.5.0
|
|
39
39
|
Requires-Dist: tiktoken>=0.12.0
|
|
40
40
|
Requires-Dist: uvicorn>=0.41.0
|
|
41
41
|
Dynamic: license-file
|
|
@@ -18,13 +18,15 @@ from .exceptions import (
|
|
|
18
18
|
from .factory import create_agent, create_tool
|
|
19
19
|
from .flow import Flow
|
|
20
20
|
from .loader import FlowLoader
|
|
21
|
-
from .nodes import NodeHandler
|
|
21
|
+
from .nodes import NodeHandler
|
|
22
22
|
from .records import Record, Status
|
|
23
23
|
from .registry import registry
|
|
24
24
|
from .state import FlowState
|
|
25
25
|
from .tool import Tool, ToolResult
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
register_node_handler = registry.register_node_handler
|
|
29
|
+
|
|
28
30
|
__all__ = [
|
|
29
31
|
# 核心抽象
|
|
30
32
|
"Tool",
|
|
@@ -46,12 +46,9 @@ class Flow:
|
|
|
46
46
|
_node_handlers: dict[str, "NodeHandler"] = field(default_factory=dict, init=False, repr=False)
|
|
47
47
|
|
|
48
48
|
def __post_init__(self) -> None:
|
|
49
|
-
from .
|
|
49
|
+
from .registry import registry
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
self._node_handlers[handler.node_type] = handler
|
|
53
|
-
# 全局注册的自定义 handler 可覆盖内置
|
|
54
|
-
self._node_handlers.update(_global_node_handlers)
|
|
51
|
+
self._node_handlers = dict(registry.get_all_node_handlers())
|
|
55
52
|
|
|
56
53
|
# ── 重试策略 ──
|
|
57
54
|
|
|
@@ -23,17 +23,7 @@ builtin_handlers: list[NodeHandler] = [
|
|
|
23
23
|
DetectNodeHandler(),
|
|
24
24
|
]
|
|
25
25
|
|
|
26
|
-
# 全局自定义节点注册
|
|
27
|
-
_global_node_handlers: dict[str, NodeHandler] = {}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def register_node_handler(node_type: str, handler: NodeHandler) -> None:
|
|
31
|
-
"""注册自定义节点处理器(全局,所有 Flow 实例共享)"""
|
|
32
|
-
_global_node_handlers[node_type] = handler
|
|
33
|
-
|
|
34
|
-
|
|
35
26
|
__all__ = [
|
|
36
27
|
"NodeHandler",
|
|
37
28
|
"builtin_handlers",
|
|
38
|
-
"register_node_handler",
|
|
39
29
|
]
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Copyright (c) 2020-2026 XtraVisions, All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Flow 系统注册中心 — 自包含的精简组件注册与创建"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Any, cast
|
|
8
|
+
|
|
9
|
+
from .agent import Agent
|
|
10
|
+
from .tool import Tool
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FlowRegistry:
|
|
14
|
+
"""Flow 系统统一注册中心"""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
self._tools: dict[str, Any] = {}
|
|
18
|
+
self._agents: dict[str, Any] = {}
|
|
19
|
+
self._flows: dict[str, Any] = {}
|
|
20
|
+
self._node_handlers: dict[str, Any] = {}
|
|
21
|
+
self._builtins_loaded = False
|
|
22
|
+
|
|
23
|
+
def _ensure_builtins(self) -> None:
|
|
24
|
+
"""延迟加载内置 node handlers(避免循环导入)"""
|
|
25
|
+
if self._builtins_loaded:
|
|
26
|
+
return
|
|
27
|
+
self._builtins_loaded = True
|
|
28
|
+
from .nodes import builtin_handlers
|
|
29
|
+
|
|
30
|
+
for handler in builtin_handlers:
|
|
31
|
+
self._node_handlers.setdefault(handler.node_type, handler)
|
|
32
|
+
|
|
33
|
+
# ── 注册 ──
|
|
34
|
+
|
|
35
|
+
def register_tool(self, name: str, tool_class) -> None:
|
|
36
|
+
"""注册工具工厂/类/实例"""
|
|
37
|
+
self._tools[name] = tool_class
|
|
38
|
+
|
|
39
|
+
def register_agent(self, name: str, agent_class: type[Agent]) -> None:
|
|
40
|
+
"""注册 Agent 类型"""
|
|
41
|
+
self._agents[name] = agent_class
|
|
42
|
+
|
|
43
|
+
def register_flow(self, name: str, flow_class: type) -> None:
|
|
44
|
+
"""注册 Flow 类型"""
|
|
45
|
+
self._flows[name] = flow_class
|
|
46
|
+
|
|
47
|
+
def register_node_handler(self, node_type: str, handler) -> None:
|
|
48
|
+
"""注册自定义节点处理器(所有 Flow 实例共享)"""
|
|
49
|
+
self._node_handlers[node_type] = handler
|
|
50
|
+
|
|
51
|
+
# ── 创建实例 ──
|
|
52
|
+
|
|
53
|
+
def create_tool(self, name: str, **kwargs) -> Tool | None:
|
|
54
|
+
"""创建工具实例"""
|
|
55
|
+
component = self._tools.get(name)
|
|
56
|
+
if component is None:
|
|
57
|
+
return None
|
|
58
|
+
# 已实例化的 Tool 对象直接返回
|
|
59
|
+
if hasattr(component, "execute_async"):
|
|
60
|
+
return cast(Tool, component)
|
|
61
|
+
# 类或工厂函数:实例化
|
|
62
|
+
if callable(component):
|
|
63
|
+
return cast(Tool, component(**kwargs) if kwargs else component())
|
|
64
|
+
return cast(Tool, component)
|
|
65
|
+
|
|
66
|
+
def create_agent(self, name: str, **kwargs) -> Agent | None:
|
|
67
|
+
"""创建 Agent 实例"""
|
|
68
|
+
component = self._agents.get(name)
|
|
69
|
+
if component is None:
|
|
70
|
+
return None
|
|
71
|
+
if callable(component):
|
|
72
|
+
return cast(Agent, component(**kwargs))
|
|
73
|
+
return cast(Agent, component)
|
|
74
|
+
|
|
75
|
+
def create_flow(self, name: str, **kwargs) -> Any | None:
|
|
76
|
+
"""创建 Flow 实例"""
|
|
77
|
+
component = self._flows.get(name)
|
|
78
|
+
if component is None:
|
|
79
|
+
return None
|
|
80
|
+
if callable(component):
|
|
81
|
+
return component(**kwargs)
|
|
82
|
+
return component
|
|
83
|
+
|
|
84
|
+
def create_tools(self, names: list[str]) -> list[Tool]:
|
|
85
|
+
"""批量创建工具"""
|
|
86
|
+
return [tool for name in names if (tool := self.create_tool(name))]
|
|
87
|
+
|
|
88
|
+
# ── 查询 ──
|
|
89
|
+
|
|
90
|
+
def get_tool_class(self, name: str) -> Any | None:
|
|
91
|
+
"""获取工具工厂/类"""
|
|
92
|
+
return self._tools.get(name)
|
|
93
|
+
|
|
94
|
+
def get_agent_class(self, name: str) -> type[Agent] | None:
|
|
95
|
+
"""获取 Agent 类型"""
|
|
96
|
+
return self._agents.get(name)
|
|
97
|
+
|
|
98
|
+
def get_flow_class(self, name: str) -> type | None:
|
|
99
|
+
"""获取 Flow 类型"""
|
|
100
|
+
return self._flows.get(name)
|
|
101
|
+
|
|
102
|
+
def get_node_handler(self, node_type: str):
|
|
103
|
+
"""获取节点处理器"""
|
|
104
|
+
self._ensure_builtins()
|
|
105
|
+
return self._node_handlers.get(node_type)
|
|
106
|
+
|
|
107
|
+
def get_all_node_handlers(self) -> dict[str, Any]:
|
|
108
|
+
"""获取所有节点处理器(内置 + 自定义)"""
|
|
109
|
+
self._ensure_builtins()
|
|
110
|
+
return dict(self._node_handlers)
|
|
111
|
+
|
|
112
|
+
# ── 列表 ──
|
|
113
|
+
|
|
114
|
+
def list_tools(self) -> list[str]:
|
|
115
|
+
return list(self._tools.keys())
|
|
116
|
+
|
|
117
|
+
def list_agents(self) -> list[str]:
|
|
118
|
+
return list(self._agents.keys())
|
|
119
|
+
|
|
120
|
+
def list_flows(self) -> list[str]:
|
|
121
|
+
return list(self._flows.keys())
|
|
122
|
+
|
|
123
|
+
def get_all_info(self) -> dict[str, list[str]]:
|
|
124
|
+
"""获取所有组件信息"""
|
|
125
|
+
self._ensure_builtins()
|
|
126
|
+
info: dict[str, list[str]] = {}
|
|
127
|
+
if self._tools:
|
|
128
|
+
info["tool"] = self.list_tools()
|
|
129
|
+
if self._agents:
|
|
130
|
+
info["agent"] = self.list_agents()
|
|
131
|
+
if self._flows:
|
|
132
|
+
info["flow"] = self.list_flows()
|
|
133
|
+
if self._node_handlers:
|
|
134
|
+
info["node_handler"] = list(self._node_handlers.keys())
|
|
135
|
+
return info
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# Flow 系统专用实例
|
|
139
|
+
registry = FlowRegistry()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agstack
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: Production-ready toolkit for building FastAPI and LLM applications
|
|
5
5
|
Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
6
6
|
Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
@@ -27,7 +27,7 @@ Requires-Dist: fastapi>=0.133.1
|
|
|
27
27
|
Requires-Dist: jwcrypto>=1.5.6
|
|
28
28
|
Requires-Dist: loguru>=0.7.3
|
|
29
29
|
Requires-Dist: nebula3-python>=3.8.3
|
|
30
|
-
Requires-Dist: openai>=2.
|
|
30
|
+
Requires-Dist: openai>=2.28.0
|
|
31
31
|
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
32
32
|
Requires-Dist: pycasbin>=2.8.0
|
|
33
33
|
Requires-Dist: pydantic>=2.12.4
|
|
@@ -35,7 +35,7 @@ Requires-Dist: python-multipart>=0.0.20
|
|
|
35
35
|
Requires-Dist: requests>=2.32.5
|
|
36
36
|
Requires-Dist: RestrictedPython>=7.0
|
|
37
37
|
Requires-Dist: sqlalchemy[asyncio]>=2.0.48
|
|
38
|
-
Requires-Dist: sqlobjects>=1.
|
|
38
|
+
Requires-Dist: sqlobjects>=1.5.0
|
|
39
39
|
Requires-Dist: tiktoken>=0.12.0
|
|
40
40
|
Requires-Dist: uvicorn>=0.41.0
|
|
41
41
|
Dynamic: license-file
|
|
@@ -5,7 +5,7 @@ fastapi>=0.133.1
|
|
|
5
5
|
jwcrypto>=1.5.6
|
|
6
6
|
loguru>=0.7.3
|
|
7
7
|
nebula3-python>=3.8.3
|
|
8
|
-
openai>=2.
|
|
8
|
+
openai>=2.28.0
|
|
9
9
|
passlib[bcrypt]>=1.7.4
|
|
10
10
|
pycasbin>=2.8.0
|
|
11
11
|
pydantic>=2.12.4
|
|
@@ -13,6 +13,6 @@ python-multipart>=0.0.20
|
|
|
13
13
|
requests>=2.32.5
|
|
14
14
|
RestrictedPython>=7.0
|
|
15
15
|
sqlalchemy[asyncio]>=2.0.48
|
|
16
|
-
sqlobjects>=1.
|
|
16
|
+
sqlobjects>=1.5.0
|
|
17
17
|
tiktoken>=0.12.0
|
|
18
18
|
uvicorn>=0.41.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agstack"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.8.0"
|
|
4
4
|
description = "Production-ready toolkit for building FastAPI and LLM applications"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -46,7 +46,7 @@ dependencies = [
|
|
|
46
46
|
"jwcrypto>=1.5.6",
|
|
47
47
|
"loguru>=0.7.3",
|
|
48
48
|
"nebula3-python>=3.8.3",
|
|
49
|
-
"openai>=2.
|
|
49
|
+
"openai>=2.28.0",
|
|
50
50
|
"passlib[bcrypt]>=1.7.4",
|
|
51
51
|
"pycasbin>=2.8.0",
|
|
52
52
|
"pydantic>=2.12.4",
|
|
@@ -54,7 +54,7 @@ dependencies = [
|
|
|
54
54
|
"requests>=2.32.5",
|
|
55
55
|
"RestrictedPython>=7.0",
|
|
56
56
|
"sqlalchemy[asyncio]>=2.0.48",
|
|
57
|
-
"sqlobjects>=1.
|
|
57
|
+
"sqlobjects>=1.5.0",
|
|
58
58
|
"tiktoken>=0.12.0",
|
|
59
59
|
"uvicorn>=0.41.0",
|
|
60
60
|
]
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2020-2026 XtraVisions, All rights reserved.
|
|
2
|
-
|
|
3
|
-
"""Flow 系统注册中心 - 提供类型安全的组件注册和创建接口
|
|
4
|
-
|
|
5
|
-
此模块是对全局注册中心的类型安全封装,为 Flow 系统提供:
|
|
6
|
-
- 强类型的返回值(Tool、Agent、Flow 等)
|
|
7
|
-
- Flow 系统的统一命名空间
|
|
8
|
-
- 方便的批量操作和查询方法
|
|
9
|
-
|
|
10
|
-
推荐在 Flow 模块内部使用此 registry 实例。
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from ...registry import registry as global_registry
|
|
14
|
-
from .agent import Agent
|
|
15
|
-
from .tool import Tool
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class FlowRegistry:
|
|
19
|
-
"""统一注册中心 - Flow 系统适配器"""
|
|
20
|
-
|
|
21
|
-
def __init__(self):
|
|
22
|
-
self.global_registry = global_registry
|
|
23
|
-
|
|
24
|
-
def register_tool(self, name: str, tool_factory) -> None:
|
|
25
|
-
"""注册工具工厂"""
|
|
26
|
-
self.global_registry.register_tool(name, tool_factory)
|
|
27
|
-
|
|
28
|
-
def register_agent(self, name: str, agent_class: type[Agent]) -> None:
|
|
29
|
-
"""注册 Agent 类型"""
|
|
30
|
-
self.global_registry.register_agent(name, agent_class)
|
|
31
|
-
|
|
32
|
-
def register_flow(self, name: str, flow_class: type) -> None:
|
|
33
|
-
"""注册 Flow 类型"""
|
|
34
|
-
self.global_registry.register_flow(name, flow_class)
|
|
35
|
-
|
|
36
|
-
def create_tool(self, name: str) -> Tool | None:
|
|
37
|
-
"""创建工具实例"""
|
|
38
|
-
return self.global_registry.create_tool(name)
|
|
39
|
-
|
|
40
|
-
def create_agent(self, name: str, **kwargs) -> Agent | None:
|
|
41
|
-
"""创建 Agent 实例"""
|
|
42
|
-
return self.global_registry.create_agent(name, **kwargs)
|
|
43
|
-
|
|
44
|
-
def create_flow(self, name: str, **kwargs):
|
|
45
|
-
"""创建 Flow 实例"""
|
|
46
|
-
return self.global_registry.create_flow(name, **kwargs)
|
|
47
|
-
|
|
48
|
-
def create_tools(self, names: list[str]) -> list[Tool]:
|
|
49
|
-
"""批量创建工具"""
|
|
50
|
-
return self.global_registry.create_tools(names)
|
|
51
|
-
|
|
52
|
-
def get_tool_class(self, name: str):
|
|
53
|
-
"""获取工具工厂(兼容性)"""
|
|
54
|
-
manifest = self.global_registry.get("tool", name)
|
|
55
|
-
return manifest.component if manifest else None
|
|
56
|
-
|
|
57
|
-
def get_agent_class(self, name: str) -> type[Agent] | None:
|
|
58
|
-
"""获取 Agent 类型"""
|
|
59
|
-
manifest = self.global_registry.get("agent", name)
|
|
60
|
-
return manifest.component if manifest else None
|
|
61
|
-
|
|
62
|
-
def get_flow_class(self, name: str) -> type | None:
|
|
63
|
-
"""获取 Flow 类型"""
|
|
64
|
-
manifest = self.global_registry.get("flow", name)
|
|
65
|
-
return manifest.component if manifest else None
|
|
66
|
-
|
|
67
|
-
def list_tools(self) -> list[str]:
|
|
68
|
-
"""列出所有工具"""
|
|
69
|
-
return self.global_registry.list("tool")
|
|
70
|
-
|
|
71
|
-
def list_agents(self) -> list[str]:
|
|
72
|
-
"""列出所有 Agent"""
|
|
73
|
-
return self.global_registry.list("agent")
|
|
74
|
-
|
|
75
|
-
def list_flows(self) -> list[str]:
|
|
76
|
-
"""列出所有 Flow"""
|
|
77
|
-
return self.global_registry.list("flow")
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# Flow 系统专用实例
|
|
81
|
-
registry = FlowRegistry()
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2020-2025 XtraVisions, All rights reserved.
|
|
2
|
-
|
|
3
|
-
"""全局统一注册中心"""
|
|
4
|
-
|
|
5
|
-
from __future__ import annotations
|
|
6
|
-
|
|
7
|
-
from collections import defaultdict
|
|
8
|
-
from dataclasses import dataclass, field
|
|
9
|
-
from typing import Any
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@dataclass
|
|
13
|
-
class ComponentManifest:
|
|
14
|
-
"""组件清单"""
|
|
15
|
-
|
|
16
|
-
name: str # 组件唯一标识
|
|
17
|
-
type: str # 组件类型 (tool/agent/flow/router/preprocessor)
|
|
18
|
-
component: Any # 实际组件对象
|
|
19
|
-
metadata: dict[str, Any] = field(default_factory=dict) # 扩展元数据
|
|
20
|
-
dependencies: list[str] = field(default_factory=list) # 依赖关系
|
|
21
|
-
version: str = "1.0.0" # 版本信息
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class Registry:
|
|
25
|
-
"""统一注册中心"""
|
|
26
|
-
|
|
27
|
-
def __init__(self):
|
|
28
|
-
self._components: dict[str, dict[str, ComponentManifest]] = defaultdict(dict)
|
|
29
|
-
|
|
30
|
-
# 底层通用接口
|
|
31
|
-
def register(self, manifest: ComponentManifest) -> None:
|
|
32
|
-
"""注册组件"""
|
|
33
|
-
self._components[manifest.type][manifest.name] = manifest
|
|
34
|
-
|
|
35
|
-
def get(self, component_type: str, name: str) -> ComponentManifest | None:
|
|
36
|
-
"""获取组件清单"""
|
|
37
|
-
return self._components[component_type].get(name)
|
|
38
|
-
|
|
39
|
-
def list(self, component_type: str) -> list[str]:
|
|
40
|
-
"""列出指定类型的所有组件名称"""
|
|
41
|
-
return list(self._components[component_type].keys())
|
|
42
|
-
|
|
43
|
-
# 快捷注册接口
|
|
44
|
-
def register_tool(
|
|
45
|
-
self,
|
|
46
|
-
name: str,
|
|
47
|
-
tool_class: Any,
|
|
48
|
-
metadata: dict[str, Any] | None = None,
|
|
49
|
-
dependencies: list[str] | None = None, # noqa
|
|
50
|
-
version: str = "1.0.0",
|
|
51
|
-
) -> None:
|
|
52
|
-
"""注册工具"""
|
|
53
|
-
manifest = ComponentManifest(
|
|
54
|
-
name=name,
|
|
55
|
-
type="tool",
|
|
56
|
-
component=tool_class,
|
|
57
|
-
metadata=metadata or {},
|
|
58
|
-
dependencies=dependencies or [],
|
|
59
|
-
version=version,
|
|
60
|
-
)
|
|
61
|
-
self.register(manifest)
|
|
62
|
-
|
|
63
|
-
def register_agent(
|
|
64
|
-
self,
|
|
65
|
-
name: str,
|
|
66
|
-
agent_class: Any,
|
|
67
|
-
metadata: dict[str, Any] | None = None,
|
|
68
|
-
dependencies: list[str] | None = None, # noqa
|
|
69
|
-
version: str = "1.0.0",
|
|
70
|
-
) -> None:
|
|
71
|
-
"""注册代理"""
|
|
72
|
-
manifest = ComponentManifest(
|
|
73
|
-
name=name,
|
|
74
|
-
type="agent",
|
|
75
|
-
component=agent_class,
|
|
76
|
-
metadata=metadata or {},
|
|
77
|
-
dependencies=dependencies or [],
|
|
78
|
-
version=version,
|
|
79
|
-
)
|
|
80
|
-
self.register(manifest)
|
|
81
|
-
|
|
82
|
-
def register_flow(
|
|
83
|
-
self,
|
|
84
|
-
name: str,
|
|
85
|
-
flow_class: Any,
|
|
86
|
-
metadata: dict[str, Any] | None = None,
|
|
87
|
-
dependencies: list[str] | None = None, # noqa
|
|
88
|
-
version: str = "1.0.0",
|
|
89
|
-
) -> None:
|
|
90
|
-
"""注册工作流"""
|
|
91
|
-
manifest = ComponentManifest(
|
|
92
|
-
name=name,
|
|
93
|
-
type="flow",
|
|
94
|
-
component=flow_class,
|
|
95
|
-
metadata=metadata or {},
|
|
96
|
-
dependencies=dependencies or [],
|
|
97
|
-
version=version,
|
|
98
|
-
)
|
|
99
|
-
self.register(manifest)
|
|
100
|
-
|
|
101
|
-
def register_router(
|
|
102
|
-
self,
|
|
103
|
-
name: str,
|
|
104
|
-
router: Any,
|
|
105
|
-
metadata: dict[str, Any] | None = None,
|
|
106
|
-
dependencies: list[str] | None = None, # noqa
|
|
107
|
-
version: str = "1.0.0",
|
|
108
|
-
) -> None:
|
|
109
|
-
"""注册路由"""
|
|
110
|
-
manifest = ComponentManifest(
|
|
111
|
-
name=name,
|
|
112
|
-
type="router",
|
|
113
|
-
component=router,
|
|
114
|
-
metadata=metadata or {},
|
|
115
|
-
dependencies=dependencies or [],
|
|
116
|
-
version=version,
|
|
117
|
-
)
|
|
118
|
-
self.register(manifest)
|
|
119
|
-
|
|
120
|
-
def register_preprocessor(
|
|
121
|
-
self,
|
|
122
|
-
name: str,
|
|
123
|
-
processor_class: Any,
|
|
124
|
-
metadata: dict[str, Any] | None = None,
|
|
125
|
-
dependencies: list[str] | None = None, # noqa
|
|
126
|
-
version: str = "1.0.0",
|
|
127
|
-
) -> None:
|
|
128
|
-
"""注册预处理器"""
|
|
129
|
-
manifest = ComponentManifest(
|
|
130
|
-
name=name,
|
|
131
|
-
type="preprocessor",
|
|
132
|
-
component=processor_class,
|
|
133
|
-
metadata=metadata or {},
|
|
134
|
-
dependencies=dependencies or [],
|
|
135
|
-
version=version,
|
|
136
|
-
)
|
|
137
|
-
self.register(manifest)
|
|
138
|
-
|
|
139
|
-
# 创建实例接口
|
|
140
|
-
def create_tool(self, name: str, **kwargs) -> Any | None:
|
|
141
|
-
"""创建工具实例"""
|
|
142
|
-
manifest = self.get("tool", name)
|
|
143
|
-
if not manifest:
|
|
144
|
-
return None
|
|
145
|
-
|
|
146
|
-
component = manifest.component
|
|
147
|
-
# 已实例化的 Tool 对象直接返回
|
|
148
|
-
if hasattr(component, "execute_async"):
|
|
149
|
-
return component
|
|
150
|
-
# 类或工厂函数:实例化
|
|
151
|
-
if callable(component):
|
|
152
|
-
return component(**kwargs) if kwargs else component()
|
|
153
|
-
return component
|
|
154
|
-
|
|
155
|
-
def create_agent(self, name: str, **kwargs) -> Any | None:
|
|
156
|
-
"""创建代理实例"""
|
|
157
|
-
manifest = self.get("agent", name)
|
|
158
|
-
if not manifest:
|
|
159
|
-
return None
|
|
160
|
-
|
|
161
|
-
component = manifest.component
|
|
162
|
-
if callable(component):
|
|
163
|
-
return component(**kwargs)
|
|
164
|
-
return component
|
|
165
|
-
|
|
166
|
-
def create_flow(self, name: str, **kwargs) -> Any | None:
|
|
167
|
-
"""创建工作流实例"""
|
|
168
|
-
manifest = self.get("flow", name)
|
|
169
|
-
if not manifest:
|
|
170
|
-
return None
|
|
171
|
-
|
|
172
|
-
component = manifest.component
|
|
173
|
-
if callable(component):
|
|
174
|
-
return component(**kwargs)
|
|
175
|
-
return component
|
|
176
|
-
|
|
177
|
-
def create_tools(self, names: list[str]) -> list[Any]: # noqa
|
|
178
|
-
"""批量创建工具"""
|
|
179
|
-
return [tool for name in names if (tool := self.create_tool(name))]
|
|
180
|
-
|
|
181
|
-
def get_all_info(self) -> dict[str, list[str]]: # noqa
|
|
182
|
-
"""获取所有组件信息"""
|
|
183
|
-
return {component_type: list(components.keys()) for component_type, components in self._components.items()}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
# 全局注册中心实例
|
|
187
|
-
registry = Registry()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|