@eoasmxd/freya 0.3.0 → 0.4.1
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.
- package/README.md +9 -3
- package/core/dist/command/commands/skill-commands.js +5 -4
- package/core/dist/config/config-manager.d.ts +5 -1
- package/core/dist/config/config-manager.js +13 -1
- package/core/dist/kernel.js +2 -2
- package/core/dist/skill/skill-registry.d.ts +12 -2
- package/core/dist/skill/skill-registry.js +89 -8
- package/core/dist/tools/meta/index.d.ts +3 -1
- package/core/dist/tools/meta/index.js +9 -1
- package/core/dist/web/config-api.js +18 -0
- package/core/package.json +2 -2
- package/doc/_index.md +20 -7
- package/doc/getting-started.md +1 -1
- package/doc/installation-guide.md +2 -2
- package/doc/{architecture-design.md → specifications/architecture-design.md} +7 -4
- package/doc/{config-spec.md → specifications/config-spec.md} +1 -1
- package/doc/{llm-interface-params.md → specifications/llm-interface-params.md} +8 -8
- package/doc/{prompt-system.md → specifications/prompt-system.md} +1 -1
- package/doc/tutorials/_index.md +96 -0
- package/doc/tutorials/part0_basic/0.1_probability_prediction.md +155 -0
- package/doc/tutorials/part0_basic/0.2_attention_and_context.md +145 -0
- package/doc/tutorials/part0_basic/0.3_generation_parameters.md +132 -0
- package/doc/tutorials/part0_basic/0.4_debugging_token.md +99 -0
- package/doc/tutorials/part0_basic/1.1_stateless_and_history.md +143 -0
- package/doc/tutorials/part0_basic/1.2_chat_data_structure.md +179 -0
- package/doc/tutorials/part0_basic/1.3_system_user_assistant.md +147 -0
- package/doc/tutorials/part0_basic/1.4_freya_model_proxy.md +203 -0
- package/doc/tutorials/part0_basic/_index.md +28 -0
- package/doc/tutorials/part1_react/2.1_agency_vs_chatbot.md +127 -0
- package/doc/tutorials/part1_react/2.2_react_mind_model.md +144 -0
- package/doc/tutorials/part1_react/2.3_freya_agent_executor.md +233 -0
- package/doc/tutorials/part1_react/2.4_debugging_loop_deadlock.md +160 -0
- package/doc/tutorials/part1_react/3.1_hardcoded_prompt_pain.md +104 -0
- package/doc/tutorials/part1_react/3.2_decoupled_architecture.md +138 -0
- package/doc/tutorials/part1_react/3.3_freya_dual_read_probe.md +152 -0
- package/doc/tutorials/part1_react/3.4_debugging_composition_placeholder.md +97 -0
- package/doc/tutorials/part1_react/_index.md +28 -0
- package/doc/tutorials/part2_tools/4.1_json_schema_mapping.md +119 -0
- package/doc/tutorials/part2_tools/4.2_tool_call_raw_packet.md +105 -0
- package/doc/tutorials/part2_tools/4.3_freya_tool_execution.md +145 -0
- package/doc/tutorials/part2_tools/4.4_debugging_observation_fix.md +154 -0
- package/doc/tutorials/part2_tools/5.1_observation_injection.md +131 -0
- package/doc/tutorials/part2_tools/5.2_openai_vs_gemini_protocol.md +125 -0
- package/doc/tutorials/part2_tools/5.3_freya_llm_proxy_mapping.md +162 -0
- package/doc/tutorials/part2_tools/5.4_debugging_parallel_call_chaos.md +135 -0
- package/doc/tutorials/part2_tools/_index.md +28 -0
- package/doc/tutorials/part3_memory/6.1_session_state_lifecycle.md +143 -0
- package/doc/tutorials/part3_memory/6.2_physical_sandbox_separation.md +108 -0
- package/doc/tutorials/part3_memory/6.3_freya_session_storage.md +139 -0
- package/doc/tutorials/part3_memory/6.4_debugging_session_concurrency.md +161 -0
- package/doc/tutorials/part3_memory/7.1_context_overflow_loss.md +109 -0
- package/doc/tutorials/part3_memory/7.2_sliding_window_vs_summary.md +85 -0
- package/doc/tutorials/part3_memory/7.3_freya_compactor_impl.md +142 -0
- package/doc/tutorials/part3_memory/7.4_debugging_summarize_deadlock.md +160 -0
- package/doc/tutorials/part3_memory/_index.md +28 -0
- package/doc/tutorials/part4_streaming/8.1_sse_protocol_basics.md +119 -0
- package/doc/tutorials/part4_streaming/8.2_hiding_thoughts_in_stream.md +132 -0
- package/doc/tutorials/part4_streaming/8.3_freya_event_bus.md +104 -0
- package/doc/tutorials/part4_streaming/8.4_debugging_stream_decoder.md +158 -0
- package/doc/tutorials/part4_streaming/9.1_abort_signal_braking.md +162 -0
- package/doc/tutorials/part4_streaming/9.2_async_event_channels.md +142 -0
- package/doc/tutorials/part4_streaming/9.3_freya_abort_billing.md +122 -0
- package/doc/tutorials/part4_streaming/9.4_debugging_abort_lock_deadlock.md +187 -0
- package/doc/tutorials/part4_streaming/_index.md +28 -0
- package/doc/tutorials/part5_plugins/10.1_microkernel_decoupling.md +142 -0
- package/doc/tutorials/part5_plugins/10.2_plugin_metadata_security.md +125 -0
- package/doc/tutorials/part5_plugins/10.3_channel_plugin_development.md +149 -0
- package/doc/tutorials/part5_plugins/10.4_debugging_channel_reconnection.md +160 -0
- package/doc/tutorials/part5_plugins/_index.md +21 -0
- package/doc/tutorials/part6_advanced/11.1_react_model_flaws.md +111 -0
- package/doc/tutorials/part6_advanced/11.2_reflexion_mind_model.md +103 -0
- package/doc/tutorials/part6_advanced/11.3_reflexion_hands_on.md +182 -0
- package/doc/tutorials/part6_advanced/11.4_debugging_reflexion_convergence.md +108 -0
- package/doc/tutorials/part6_advanced/12.1_single_agent_limits.md +100 -0
- package/doc/tutorials/part6_advanced/12.2_multi_agent_patterns.md +121 -0
- package/doc/tutorials/part6_advanced/12.3_freya_multi_agent_routing.md +143 -0
- package/doc/tutorials/part6_advanced/12.4_multi_agent_hands_on.md +176 -0
- package/doc/tutorials/part6_advanced/_index.md +28 -0
- package/doc/tutorials/preface.md +30 -0
- package/package.json +3 -2
- package/plugins/plugin-gemini/package.json +1 -1
- package/plugins/plugin-openai/package.json +1 -1
- package/plugins/plugin-telegram-channel/package.json +1 -1
- package/plugins/plugin-tool-fs/package.json +1 -1
- package/plugins/plugin-tool-memory/package.json +1 -1
- package/plugins/plugin-tool-mysql/config/prompts/plugin.prompt.mysql.md +9 -0
- package/plugins/plugin-tool-mysql/config/prompts/plugin.prompt.mysql.select.audit.md +26 -0
- package/plugins/plugin-tool-mysql/dist/audit.d.ts +13 -0
- package/plugins/plugin-tool-mysql/dist/audit.js +87 -0
- package/plugins/plugin-tool-mysql/dist/index.d.ts +14 -0
- package/plugins/plugin-tool-mysql/dist/index.js +34 -0
- package/plugins/plugin-tool-mysql/dist/pool-manager.d.ts +32 -0
- package/plugins/plugin-tool-mysql/dist/pool-manager.js +113 -0
- package/plugins/plugin-tool-mysql/dist/tools.d.ts +11 -0
- package/plugins/plugin-tool-mysql/dist/tools.js +88 -0
- package/plugins/plugin-tool-mysql/package.json +33 -0
- package/plugins/plugin-tool-mysql/schema.json +83 -0
- package/plugins/plugin-tool-web/package.json +1 -1
- package/plugins/plugin-wecom-channel/package.json +1 -1
- package/plugins/plugin-weixin-channel/package.json +1 -1
- package/src/packages/core/src/command/commands/skill-commands.ts +6 -5
- package/src/packages/core/src/config/config-manager.ts +15 -1
- package/src/packages/core/src/kernel.ts +3 -2
- package/src/packages/core/src/skill/skill-registry.ts +100 -8
- package/src/packages/core/src/tools/meta/index.ts +9 -1
- package/src/packages/core/src/web/config-api.ts +20 -0
- package/src/packages/ui/src/features/config/ConfigModal.tsx +13 -1
- package/src/packages/ui/src/features/config/panels/SkillConfigPanel.tsx +137 -0
- package/src/plugins/plugin-tool-mysql/src/audit.ts +103 -0
- package/src/plugins/plugin-tool-mysql/src/index.ts +44 -0
- package/src/plugins/plugin-tool-mysql/src/pool-manager.ts +132 -0
- package/src/plugins/plugin-tool-mysql/src/tools.ts +100 -0
- package/ui/assets/{index-Be0cAgdB.js → index-BqPQMflk.js} +14 -14
- package/ui/index.html +1 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "12.2 多智能体协作经典范式"
|
|
3
|
+
weight: 20
|
|
4
|
+
description: "对比集中式路由器模式(Hub-and-Spoke)与分布式对等体协作模式(Peer-to-Peer)的设计精髓,设计事件传播步数限制器防御乒乓球死循环。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 12.2 多智能体协作经典范式
|
|
8
|
+
|
|
9
|
+
在 12.1 节中,我们确立了单智能体在处理海量工具和冲突人设时的认知极限,并论证了社会化分工的必要性。然而,当我们的系统里并存着多个功能各异的智能体时,它们应该以怎样的组织结构去进行通信与分工?
|
|
10
|
+
|
|
11
|
+
在当前的 Multi-Agent 领域,业界演化出了两套最经典的组织拓扑范式:**集中式路由器模式(Hub-and-Spoke / Router Pattern)** 与 **分布式对等协作模式(Peer-to-Peer / Decentralized Pattern)**。
|
|
12
|
+
|
|
13
|
+
本节我们将对比解剖这两大模式的技术原理与工程利弊,并针对多体交互中最头疼的“乒乓球死循环消息风暴”提供底座级的防御解决方案。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 一、 集中式路由器模式 (Hub-and-Spoke):星形控制网
|
|
18
|
+
|
|
19
|
+
集中式路由器模式模拟了传统企业中的“垂直管理体制”。
|
|
20
|
+
|
|
21
|
+
在这个体系中,有一个唯一的 **Router Agent(主控路由 / 分发大管家)** 扮演星形网络的核心(Hub),其他所有专注于垂直领域的智能体(如 Database Agent、Writer Agent)都是它手下的螺丝钉(Spokes)。
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
┌──────────────────────────────────────┐
|
|
25
|
+
│ Router Agent (主控路由器) │
|
|
26
|
+
└──────▲──────────────────┬───▲────────┘
|
|
27
|
+
│ 调度 │ │ 调度
|
|
28
|
+
▼ ▼ │
|
|
29
|
+
┌──────────────────────┐ ┌──────┴───────────────┐
|
|
30
|
+
│ Database Agent (数据) │ │ Writer Agent (文案) │
|
|
31
|
+
└──────────────────────┘ └──────────────────────┘
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 1. 物理时序流转
|
|
35
|
+
1. **用户** 向系统发送指令:“*查询今年二季度的销售报表,并润色成一篇分析文案发给老板。*”
|
|
36
|
+
2. **Router Agent** 率先读取此指令。它并不直接调用任何业务工具,它的唯一工具就是“唤醒其他 Agent”。
|
|
37
|
+
3. Router 首先发出指令,调用并等待 **Database Agent** 返回二季度销售数据。
|
|
38
|
+
4. Router 拿到数据后,再次发起指令,把数据投喂给 **Writer Agent** 进行润色。
|
|
39
|
+
5. Router 整合最终结果,呈献给用户。
|
|
40
|
+
|
|
41
|
+
### 2. 优缺点评估
|
|
42
|
+
* **优点(高度可控)**:
|
|
43
|
+
决策树清晰,主控 Router 拥有全局掌控权,可以对子智能体的中间输出进行严格把关和过滤,防止子智能体之间产生废话;对于客户端而言,交互简单,只需要与唯一的 Router 入口保持通信即可。
|
|
44
|
+
* **缺点(Router 认知瓶颈)**:
|
|
45
|
+
Router 作为唯一的总指挥,面临巨大的心智压力(Context Window 消耗最大)。一旦 Router 在第一步意图识别发生失误,整套子系统将彻底陷入瘫痪。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 二、 分布式对等协作模式 (Peer-to-Peer):网状自组织网络
|
|
50
|
+
|
|
51
|
+
分布式对等协作模式则模拟了“扁平化的小组敏捷协作”或物理网络中的“发布/订阅(Pub/Sub)”机制。
|
|
52
|
+
|
|
53
|
+
在这个网络里,没有唯一的“总指挥”,所有的 Agent 地位平等(Peers),它们被共同挂载在底座的**进程内事件总线(EventBus)**上,通过事件进行自发激活。
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
[事件总线 EventBus] ─── 'code:need_audit' ───> [Auditor Agent] (监听激活,执行审计)
|
|
57
|
+
│
|
|
58
|
+
▼ (审计完毕,广播结果)
|
|
59
|
+
[事件总线 EventBus] <─── 'code:audited' ─── [Auditor Agent]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 1. 物理时序流转
|
|
63
|
+
1. **代码提交插件** 向 EventBus 广播事件 `'code:submitted'`,透传代码文本。
|
|
64
|
+
2. **代码编译器 Agent** 在总线上监听该事件,被动激活并尝试在本地编译。编译成功后,向总线广播 `'code:compiled'`。
|
|
65
|
+
3. **安全审计员 Agent** 监听 `'code:compiled'`,被动激活执行漏洞扫描,审计通过后广播 `'code:audited'`。
|
|
66
|
+
4. **通知通道插件** 监听 `'code:audited'`,立刻将代码审核通过的消息推送给微信或 Telegram 终端。
|
|
67
|
+
|
|
68
|
+
### 2. 优缺点评估
|
|
69
|
+
* **优点(无限扩展与极致解耦)**:
|
|
70
|
+
系统弹性极佳。新加入一个审查智能体,不需要通知任何人,只需让其在 EventBus 上挂接对应的监听事件即可。整个系统去中心化运行,单个 Agent 的故障不会拖垮其他平行的 Agent 链路。
|
|
71
|
+
* **缺点(乒乓球死循环风暴)**:
|
|
72
|
+
由于缺乏中心指挥官,如果两个 Agent 的监听机制设计不严谨,极易诱发致命的**乒乓球死循环风暴(Ping-Pong Deadlock)**:
|
|
73
|
+
* *场景*:Agent A 监听 `'code:updated'` 优化了代码并广播。Agent B 监听 `'code:updated'` 发现有微小排版问题,微调了缩进并重新广播 `'code:updated'`...
|
|
74
|
+
* *后果*:两个 Agent 像打乒乓球一样在后台无限次地高频对刷事件,在极短时间内产生数万次事件洪水,瘫痪 CPU 内存并瞬间刷爆 API 额度账单。
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 三、 【避坑防线】设计“有向无环图限制器 (Hop Counter)”
|
|
79
|
+
|
|
80
|
+
为了防止 P2P 网状自组织模式下可能发生的事件乒乓球死循环大坑,底座在事件总线(EventBus)层面,必须设立强力的**有向无环图传播限制器(DAG Event Limiter)**:
|
|
81
|
+
|
|
82
|
+
### 1. 物理防线机理
|
|
83
|
+
底座在分发消息和事件时,强制要求每笔业务请求必须携带唯一的 `traceId`,并在事件荷载中挂载 `hopCount`(传播跳数计数器):
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
export interface FreyaEventPayload {
|
|
87
|
+
traceId: string; // 唯一请求跟踪 ID
|
|
88
|
+
hopCount: number; // 传播跳数,每经过一个 Agent 转发,该值物理加 1
|
|
89
|
+
data: any;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2. 限制器熔断代码实现
|
|
94
|
+
EventBus 在接收到 `emit` 动作时,拦截器会无条件核对 `hopCount`。**一旦超限,强行熔断**:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
export class DagEventLimiter {
|
|
98
|
+
private readonly MAX_HOPS = 10; // 💡 物理极限:单次交互在多体网络中最多流转 10 步
|
|
99
|
+
|
|
100
|
+
intercept(event: string, payload: any): boolean {
|
|
101
|
+
if (payload && typeof payload.hopCount === 'number') {
|
|
102
|
+
// 1. 传播步数自增
|
|
103
|
+
payload.hopCount++;
|
|
104
|
+
|
|
105
|
+
// 2. 💡 物理熔断防线:一旦传播跳数超出 10 步
|
|
106
|
+
// 说明系统已经陷入了多体乒乓球死循环或复杂的依赖回环
|
|
107
|
+
if (payload.hopCount > this.MAX_HOPS) {
|
|
108
|
+
console.error(`🚨 [EventStormGuard] 触发多体事件传播熔断!traceId: ${payload.traceId},当前跳数: ${payload.hopCount} 超过物理安全上限 ${this.MAX_HOPS}。当前阻断事件: ${event}`);
|
|
109
|
+
|
|
110
|
+
// 强制向总线发出系统级中止信号,解除所有活跃 Session 锁定
|
|
111
|
+
return false; // 拒绝该事件广播
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return true; // 正常放行
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
通过这套有向无环图限制器,我们在 EventBus 的物理网络管道中,强制为多体自组织协作划定了“热熔断丝”。无论插件之间的 Pub/Sub 关系网有多么错综复杂,事件空转风暴都能在第 10 步时被瞬间物理斩断,牢牢捍卫了服务器内存与账单账目的绝对安全。
|
|
120
|
+
|
|
121
|
+
本节我们对比了集中式路由器与分布式对等体协作的设计精髓与利弊,并引入了 Hop Counter 事件熔断器。在下一小节中,我们将实际切入 Freya 的多体拓扑源码,白盒解剖基于事件总线的多体路由与子 Agent 级联的 TS 物理实现。
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "12.3 【白盒剖析】基于事件总线的多体路由"
|
|
3
|
+
weight: 30
|
|
4
|
+
description: "白盒解剖 SpawnSubagentTool 派生工具与 AgentService 子代路由源码,拆解多体混合模型级联与 Session 路由指纹注入机制。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 12.3 【白盒剖析】基于事件总线的多体路由
|
|
8
|
+
|
|
9
|
+
在 12.2 节中,我们对比了集中式路由器星形拓扑与分布式自组织网状拓扑的利弊。在 Freya 底座的实际落地中,为了实现对子智能体的安全治理,底座采用了一种**“通过声明式工具(Tool)派生子代”**的集中中继路由模式。
|
|
10
|
+
|
|
11
|
+
父智能体在大脑推理过程中,如果判定任务过于庞大,会主动通过调用特定的 Tool 接口,在后台拉起一个完全隔离的“子智能体”。
|
|
12
|
+
|
|
13
|
+
本节我们将实际白盒解剖派生子智能体工具(位于 `packages/core/src/tools/session/tools.ts`)与核心服务(位于 `packages/core/src/agent/agent-service.ts`)的级联调度源码,探秘多体混合模型级联与 Session 路由指纹注入的 TypeScript 物理实现。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 一、 声明式派生工具:SpawnSubagentTool 的定义
|
|
18
|
+
|
|
19
|
+
为了将“派生子代”的能力暴露给大模型,内核在 `packages/core/src/tools/session/tools.ts` 中,实现了一个特殊的 `SpawnSubagentTool`:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
export class SpawnSubagentTool implements FreyaTool {
|
|
23
|
+
private agentService?: FreyaAgentService;
|
|
24
|
+
|
|
25
|
+
constructor(private sessionManager: FreyaSessionManager) {}
|
|
26
|
+
|
|
27
|
+
getDefinition(): ToolDefinition {
|
|
28
|
+
return {
|
|
29
|
+
name: 'spawn_subagent',
|
|
30
|
+
description: '派生出一个相对隔离的子任务去执行。系统会在后台为此任务运行独立的感知-决策-行动大循环。该工具是同步阻塞的,执行完毕后会直接返回结果。',
|
|
31
|
+
parameters: {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {
|
|
34
|
+
prompt: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: '派发给子任务的具体描述(如:"查询并整理关于大模型技术发展的最新行业分析报告")'
|
|
37
|
+
},
|
|
38
|
+
providerId: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: '子任务调用的模型提供商 ID(可选)'
|
|
41
|
+
},
|
|
42
|
+
modelId: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description: '子任务调用的具体模型 ID(可选)'
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
required: ['prompt']
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 物理设计优势:
|
|
55
|
+
在参数中设计 `providerId` 和 `modelId` 允许系统实现**混合模型级联(Hybrid Model Cascade)**:
|
|
56
|
+
* 父智能体在宏观拆解任务时,使用高昂但高智商的模型(如 GPT-4o)作为总指挥。
|
|
57
|
+
* 当它派生子任务去跑具体的网络爬虫、文件读取等重活时,可以指定便宜、快速的小模型(如 Llama-3-8B),极大地控本增效。
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 二、 路由指纹的注入与子 Session 派生
|
|
62
|
+
|
|
63
|
+
当父智能体做出了 `Action: spawn_subagent(prompt="...")` 时,底座执行器进入 `execute()` 方法:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
async execute(args: Record<string, any>, ctx: FreyaContext): Promise<string> {
|
|
67
|
+
if (!args.prompt) {
|
|
68
|
+
return '❌ 参数错误:必须提供具体子任务 prompt 描述。';
|
|
69
|
+
}
|
|
70
|
+
if (!this.agentService) {
|
|
71
|
+
throw new Error('AgentService 尚未注入,无法派生子任务。');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 1. 💡 路由安全指纹提取:从 arguments 隐式属性中读取当前父会话的 ID
|
|
75
|
+
const parentSessionId = args.__sessionId || 'unknown_parent';
|
|
76
|
+
|
|
77
|
+
// 2. 动态生成时间戳后缀的子会话 UUID,确保物理命名空间完全隔离
|
|
78
|
+
const childSessionId = `${parentSessionId}_sub_${Date.now()}`;
|
|
79
|
+
|
|
80
|
+
ctx.logger.info(`[SubagentTool] 派生子会话任务: 父会话 "${parentSessionId}" -> 子会话 "${childSessionId}"`);
|
|
81
|
+
|
|
82
|
+
// 3. 🚀 调度 AgentService 启动后台子任务运行循环,并同步阻塞等待其返回结果
|
|
83
|
+
return await this.agentService.runSubAgent(parentSessionId, childSessionId, args.prompt, args);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### `__sessionId` 路由指纹的妙用:
|
|
88
|
+
在 2.3 节的 ReAct 执行器中,底座在把工具 Schema 发送给 LLM 前,会在底座层默默往 arguments 字典里注入 `__sessionId: sessionId` 属性。
|
|
89
|
+
这让 `SpawnSubagentTool` 可以在运行时**零引用**、安全地得知“是哪一个父智能体调用了我”,从而动态构建出带前缀的 `childSessionId`,杜绝了多体状态的混乱。
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 三、 子代生命周期接管与同步阻塞等待 (runSubAgent)
|
|
94
|
+
|
|
95
|
+
在中枢 `AgentService` 中,`runSubAgent` 接管了子代智能体完整的生命周期运行:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
async runSubAgent(
|
|
99
|
+
parentSessionId: string,
|
|
100
|
+
childSessionId: string,
|
|
101
|
+
prompt: string,
|
|
102
|
+
options?: { providerId?: string; modelId?: string }
|
|
103
|
+
): Promise<string> {
|
|
104
|
+
const ctrl = new AbortController();
|
|
105
|
+
const key = `${parentSessionId}_sub_${childSessionId}`;
|
|
106
|
+
this.abortControllers.set(key, ctrl); // 1. 注册子代紧急刹车控制器
|
|
107
|
+
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
try {
|
|
110
|
+
// 2. 创建一个纯净的、完全隔离的子 Session
|
|
111
|
+
await this.sessionManager.createSession(childSessionId, { parentId: parentSessionId, prompt });
|
|
112
|
+
|
|
113
|
+
// 3. 注入子任务提问
|
|
114
|
+
await this.sessionManager.appendMessage(childSessionId, { role: 'user', content: prompt });
|
|
115
|
+
|
|
116
|
+
// 4. 💡 启动子 Agent 独立的 while(loop) ReAct 决策循环,并透传子信号,实现同步阻塞等待
|
|
117
|
+
const replyMessage = await this.agentExecutor.run(childSessionId, {
|
|
118
|
+
signal: ctrl.signal,
|
|
119
|
+
providerId: options?.providerId,
|
|
120
|
+
modelId: options?.modelId
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const durationMs = Date.now() - startTime;
|
|
124
|
+
// 5. 任务成功,更新子会话状态为 'completed'
|
|
125
|
+
await this.sessionManager.updateSession(childSessionId, { status: 'completed', durationMs });
|
|
126
|
+
return replyMessage.content; // 将子智能体最终的心智结晶作为 Observation 返回给父智能体
|
|
127
|
+
} catch (err: any) {
|
|
128
|
+
const durationMs = Date.now() - startTime;
|
|
129
|
+
// 6. 任务失败,更新子会话状态为 'failed',向上游抛出 Error 引导父智能体自我反思
|
|
130
|
+
await this.sessionManager.updateSession(childSessionId, { status: 'failed', durationMs });
|
|
131
|
+
throw err;
|
|
132
|
+
} finally {
|
|
133
|
+
this.abortControllers.delete(key); // 7. 销毁子控制器释放内存
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 级联阻断与因果回溯:
|
|
139
|
+
在 `runSubAgent` 中,子智能体的运行被优雅地包裹在一个标准的 `async/await` 异步栈中。对于父智能体而言,**派生一个子智能体去执行复杂任务,其心智认知就像是“调用了一个普通的查数据库 API 工具”一样扁平!**
|
|
140
|
+
|
|
141
|
+
父智能体只需要阻塞等待 `spawn_subagent` 工具返回的纯文本 Observation 字符串,即可将子任务的产出成果完美缝合进自己的主上下文历史中。这套设计在微内核层面实现了绝伦的级联对齐。
|
|
142
|
+
|
|
143
|
+
本节我们白盒剖析了子智能体派生、Session 路由指纹注入与级联调度阻塞等待的 TS 实现。在下一小节中,我们将在本地亲自部署运行,进行多智能体联合协作的工程动手实验。
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "12.4 动手实验与三体协同工作流"
|
|
3
|
+
weight: 40
|
|
4
|
+
description: "动手部署一个三体协同自动软件交付流水线,前沿展望自组织智能体 Swarms 拓扑演进,设计全局链路费用熔断闸防范 Token 财务雪崩。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 12.4 动手实验与三体协同工作流
|
|
8
|
+
|
|
9
|
+
在 12.3 节中,我们白盒解密了 Freya 派生子任务工具 `SpawnSubagentTool` 的参数级联与中枢调度生命周期。本节我们将通过**动手实验**,在本地亲自部署并运行一个模拟开发团队进行软件改错和质量把关的**“三体协作自动软件交付工作流”**。
|
|
10
|
+
|
|
11
|
+
我们将直观目睹主策划(Planner)、程序员(Coder)与测试裁判(Tester)在底座的穿针引引线下精密交响的物理全过程。
|
|
12
|
+
|
|
13
|
+
随后,我们将前沿展望自组织智能体集群(Agent Swarms)的未来演进,并针对多体级联交互中极易引爆的“Token 财务雪崩”提供全局链路级费用熔断防波堤。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 一、 实验设计:三体协同自动软件交付流水线
|
|
18
|
+
|
|
19
|
+
为了模拟企业开发环境,我们设计了三个不同的智能体角色:
|
|
20
|
+
1. **Planner Agent (总主控 / 路由管家)**:只负责理解用户的原始需求,派发任务,并对交付的代码包进行最终合规性签字(Sign-off)。
|
|
21
|
+
2. **Coder Agent (程序员 / 业务 Sub Agent)**:人设是极速编码。它专门负责编写算法逻辑,并吸取测试报错的反思经验。
|
|
22
|
+
3. **Tester Agent (测试裁判 / 质量 Sub Agent)**:人设是严厉挑剔的测试工程师。它专门负责执行边界测试,不通过则无情打回。
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 二、 动手实验:三体级联协作控制脚本
|
|
27
|
+
|
|
28
|
+
让我们在本地新建 `multi_agent_flow.js`,实现多体级联通信:
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
const { OpenAI } = require("openai");
|
|
32
|
+
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
33
|
+
|
|
34
|
+
// 1. 模拟 Coder 智能体 (程序员)
|
|
35
|
+
async function runCoderAgent(taskDescription, errorReport, reflection) {
|
|
36
|
+
console.log("👨💻 [Coder Agent]: 收到任务,开始编写代码...");
|
|
37
|
+
let systemPrompt = "你是一个高效的程序员。请编写纯 JavaScript 导出函数。";
|
|
38
|
+
if (errorReport) {
|
|
39
|
+
systemPrompt += `\n\n⚠️ 上一次测试报错: ${errorReport}\n请吸取教训,进行反思修改:${reflection}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const res = await openai.chat.completions.create({
|
|
43
|
+
model: "gpt-4o-mini",
|
|
44
|
+
messages: [
|
|
45
|
+
{ role: "system", content: systemPrompt },
|
|
46
|
+
{ role: "user", content: taskDescription }
|
|
47
|
+
]
|
|
48
|
+
});
|
|
49
|
+
return res.choices[0].message.content.replace(/```javascript|```/g, "").trim();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 2. 模拟 Tester 智能体 (测试裁判)
|
|
53
|
+
function runTesterAgent(codeString) {
|
|
54
|
+
console.log("🧪 [Tester Agent]: 收到代码,正在进行边界单元测试...");
|
|
55
|
+
try {
|
|
56
|
+
const sandbox = {};
|
|
57
|
+
require("node:vm").runInNewContext(codeString, sandbox);
|
|
58
|
+
const fn = sandbox.add;
|
|
59
|
+
|
|
60
|
+
// 注入严格边界测试用例:必须支持数字和字符串数字相加
|
|
61
|
+
if (fn(1, 2) !== 3) throw new Error("测试失败:1 + 2 不等于 3");
|
|
62
|
+
if (fn("2", 3) !== 5) throw new Error("测试失败:字符 \"2\" + 3 不等于 5 (未做自动类型强制转换)");
|
|
63
|
+
|
|
64
|
+
return { passed: true };
|
|
65
|
+
} catch (err) {
|
|
66
|
+
return { passed: false, error: err.message };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 3. 模拟 Planner Agent (总控路由) 驱动三体流水线
|
|
71
|
+
async function runPlannerWorkflow() {
|
|
72
|
+
const task = "请编写一个名为 add(a, b) 的函数,要求必须支持自动将字符串类型的数字转换为数值类型再相加。";
|
|
73
|
+
console.log(`🎬 [Planner Workflow 启动]: 原始需求 —— "${task}"`);
|
|
74
|
+
|
|
75
|
+
let codeDraft = "";
|
|
76
|
+
let errorReport = null;
|
|
77
|
+
let reflection = null;
|
|
78
|
+
let round = 0;
|
|
79
|
+
|
|
80
|
+
while (round < 3) {
|
|
81
|
+
round++;
|
|
82
|
+
console.log(`\n--- ⏳ 流水线第 ${round} 次迭代迭代 ---`);
|
|
83
|
+
|
|
84
|
+
// 💡 派生步骤一:主控路由派发任务给 Coder 子智能体
|
|
85
|
+
codeDraft = await runCoderAgent(task, errorReport, reflection);
|
|
86
|
+
console.log("👨💻 [Coder 交付的代码草稿]:\n", codeDraft);
|
|
87
|
+
|
|
88
|
+
// 💡 派生步骤二:主控将代码草稿送往 Tester 智能体进行动态质量评估
|
|
89
|
+
const testResult = runTesterAgent(codeDraft);
|
|
90
|
+
if (testResult.passed) {
|
|
91
|
+
console.log("\n🎉🎉🎉 [Tester Agent 签字通过]: 质量合格!测试通过!");
|
|
92
|
+
console.log("🏆 [Planner 最终交付]: 项目顺利交付!");
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log("❌ [Tester Agent 拒绝]: 质量不合格,打回!报错为:", testResult.error);
|
|
97
|
+
errorReport = testResult.error;
|
|
98
|
+
|
|
99
|
+
// 💡 步骤三:派发反思任务给 Coder 自我分析
|
|
100
|
+
console.log("🧠 [Planner 调度 Coder 自我反思...]");
|
|
101
|
+
const refRes = await openai.chat.completions.create({
|
|
102
|
+
model: "gpt-4o", // 反思使用高级模型
|
|
103
|
+
messages: [
|
|
104
|
+
{ role: "system", content: "你是一个经验丰富的代码架构师。请简要反思这个 Bug 是怎么发生的,并指导程序员在下一步中怎么改。" },
|
|
105
|
+
{ role: "user", content: `代码:\n${codeDraft}\n\n报错:\n${errorReport}` }
|
|
106
|
+
]
|
|
107
|
+
});
|
|
108
|
+
reflection = refRes.choices[0].message.content.trim();
|
|
109
|
+
console.log(`💡 [Coder 反思结晶]: "${reflection}"`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
runPlannerWorkflow();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
通过这一段三体协作脚本,我们模拟出了一个微型、高度自动化的**DevOps 智能体交付流水线**。各 Agent 在各自的“人设”和“工具约束”下各司其职,完成了复杂的级联改错。
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 三、 前沿技术展望:自组织智能体集群 (Agent Swarms) 的兴起
|
|
121
|
+
|
|
122
|
+
当前的智能体系统大多基于我们手动指定的、硬编码的拓扑网进行工作。
|
|
123
|
+
|
|
124
|
+
### 1. 什么是 Swarms(智能体集群)?
|
|
125
|
+
未来的演进方向是**去中心化自组织的智能体集群(Swarms)**。
|
|
126
|
+
* **自发发现(Self-Discovery)**:Agent 不需要被硬编码写在 spawn 工具里。当 Agent 遇到无法解决的问题时,它会将任务特征打包广播到总线上。
|
|
127
|
+
* **契约握手(Contractual Handshake)**:总线上其他处于闲置状态的 Agent 根据自己的静态 `Schema` 匹配度,自发向主 Agent 发起服务握手(Bid),自动缝合出临时的、动态有向无环图(Dynamic DAG)协作链。
|
|
128
|
+
* **社会化自进化**:这相当于在操作系统的运行时层面上,自发形成了一个由数万个微型智能体构成的庞大“社会”,涌现出超乎想象的复杂心智。
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 四、 【避坑指南】设计“全局链路费用熔断闸”防范 Token 财务雪崩
|
|
133
|
+
|
|
134
|
+
在多体级联体系(父拉起子,子又拉起孙,孙又自我反思)中,一次看似普通的用户发问,会在后台像雪崩一样引爆几十次并发大模型请求。
|
|
135
|
+
|
|
136
|
+
如果某个子 Agent 发生了“鬼打墙”死锁,**整套集群系统会在几秒钟内疯狂空转并燃烧完几百美元的 Token 授信额度。**
|
|
137
|
+
|
|
138
|
+
### 🌟 黄金防御规范:全局 Trace 计费累加器
|
|
139
|
+
为了防止发生大坝崩溃式的财务灾难,智能体底座在 EventBus 网络管道与计费模块中,必须设立**全局链路费用熔断闸(Global Trace Cost Limiter)**:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
export class GlobalTraceCostLimiter {
|
|
143
|
+
// 记录每个全局 Trace ID (一次用户发问产生的全部父子孙调用链) 的真实累积消费
|
|
144
|
+
private traceCosts = new Map<string, number>();
|
|
145
|
+
private readonly TRACE_BUDGET_LIMIT = 0.50; // 💡 物理红线:单次交互在整个多体链路内最大消费限制为 0.5 美元
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 每次任何一个子/孙 Agent 调用完 LLM 返回 Billing 计费时,强行扣减审计
|
|
149
|
+
*/
|
|
150
|
+
async auditAndAccumulate(traceId: string, currentCost: number, abortControllers: Map<string, AbortController>): Promise<void> {
|
|
151
|
+
const accumulated = this.traceCosts.get(traceId) || 0;
|
|
152
|
+
const newTotal = parseFloat((accumulated + currentCost).toFixed(7));
|
|
153
|
+
this.traceCosts.set(traceId, newTotal);
|
|
154
|
+
|
|
155
|
+
// 💡 财务红线拦截
|
|
156
|
+
if (newTotal > this.TRACE_BUDGET_LIMIT) {
|
|
157
|
+
console.error(`🚨 [FinancialAvalancheGuard] 财务红色警报!Trace ID: ${traceId} 的累积消费已达 $${newTotal},超出了安全上限 $${this.TRACE_BUDGET_LIMIT}。底座强制熔断!`);
|
|
158
|
+
|
|
159
|
+
// 遍历并强行拉下该全局 Trace ID 对应下的所有活跃子/孙控制器的刹车闸
|
|
160
|
+
for (const [key, ctrl] of abortControllers.entries()) {
|
|
161
|
+
if (key.startsWith(traceId) || key.includes(`_sub_${traceId}`)) {
|
|
162
|
+
ctrl.abort(); // 物理掐断网络,停止一切后台空转推理
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
throw new Error(`[FinancialLimitExceeded] 当前任务链的 Token 消费超出了安全上限 ($${this.TRACE_BUDGET_LIMIT}),底座已强行切断连接以防止财务损失。请优化您的提示词并拆分任务重试。`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
通过这套全局 Trace 计费累加与强力 abort 熔断拦截器,底座成功在大模型的贪婪空转与公司信用卡额度之间建立了无坚不摧的物理防浪墙,彻底破除了企业在落地多体系统时对“Token 费用失控”的根本恐惧。
|
|
173
|
+
|
|
174
|
+
本节我们通过部署 DevOps 三体协同交付流水线完成了动手实验,展望了 Swarms 自组织演进,并利用全局 Trace 计费累加器锁死了财务雪崩漏洞。
|
|
175
|
+
|
|
176
|
+
恭喜您!至此,我们已经完整编写并生成了本套教程的全部核心小节正文内容。在最后的章节中,我们将通过一键组装,将这本饱含白盒源码剖析与工程防线的书,完整编译成漂亮的静态网站。
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "第六部分:前沿展望"
|
|
3
|
+
weight: 70
|
|
4
|
+
bookCollapseSection: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 第六部分:前沿展望与架构演进 —— 走向更高级的 Agent
|
|
8
|
+
|
|
9
|
+
本部分将深入解密智能体的未来演进流派。我们将剖析经典的 ReAct 决策环物理缺陷、引入反思与自纠错心智模型,并探究多智能体(Multi-Agent)事件驱动总线通信与联合路由的物理范式。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🧭 章节导学与阅读清单
|
|
14
|
+
|
|
15
|
+
### 🧠 第 11 章:超越 ReAct:自我反思 (Self-Reflection) 与复杂规划 (Planning)
|
|
16
|
+
分析 ReAct 处理复杂长链路任务易偏离目标或死循环的局限,学习 Plan-and-Solve 与 Reflexion 反思框架,实操在 executor 中织造自我纠错轮次。
|
|
17
|
+
* 👉 **[11.1 ReAct 决策环的物理缺陷](11.1_react_model_flaws.md)**
|
|
18
|
+
* 👉 **[11.2 进阶反思心智模型解析](11.2_reflexion_mind_model.md)**
|
|
19
|
+
* 👉 **[11.3 动手实验:反射循环开发](11.3_reflexion_hands_on.md)**
|
|
20
|
+
* 👉 **[11.4 调试与避坑指南:评估反思开销与收敛成功率](11.4_debugging_reflexion_convergence.md)**
|
|
21
|
+
|
|
22
|
+
### 🤝 第 12 章:从单体走向多智能体协作 (Multi-Agent Systems)
|
|
23
|
+
了解单 Agent 能力边界并学习任务拆解,掌握 Master-Worker 与 Pipeline 拓扑流转,剖析基于 EventBus 的 Agent 间 Observation 推送。
|
|
24
|
+
* 👉 **[12.1 独木难支:单 Agent 的能力与认知限界](12.1_single_agent_limits.md)**
|
|
25
|
+
* 👉 **[12.2 多智能体协作经典范式](12.2_multi_agent_patterns.md)**
|
|
26
|
+
* 👉 **[12.3 【白盒剖析】基于事件总线的多体路由](12.3_freya_multi_agent_routing.md)**
|
|
27
|
+
* 👉 **[12.4 动手实验与三体协同工作流](12.4_multi_agent_hands_on.md)**
|
|
28
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "序言"
|
|
3
|
+
weight: 2
|
|
4
|
+
description: "智能体的第一推动力 —— 从黑盒调用到白盒物理沙箱"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 序言:智能体的第一推动力 —— 从黑盒调用到白盒物理沙箱
|
|
8
|
+
|
|
9
|
+
我们正在经历一场前所未有的范式变革。
|
|
10
|
+
|
|
11
|
+
在过去的几年里,大语言模型(LLM)的爆发让整个行业陷入了对“提示词魔法”的狂热。人们惊叹于只要在聊天输入框里敲入几行自然语言,AI 就能写出通顺的文案、甚至跑出能运行的简易程序。然而,狂热退去之后,开发者们很快撞上了玻璃天花板:
|
|
12
|
+
* 为什么我的聊天机器人聊着聊着就会“遗忘”上文?
|
|
13
|
+
* 为什么让它调用一个简单的天气 API,它却经常传错参数?
|
|
14
|
+
* 为什么在处理复杂的长链路任务时,它会陷入反复确认的“鬼打墙”状态?
|
|
15
|
+
|
|
16
|
+
这些问题的答案,隐藏在“文字接龙聊天助手”与“能动的智能体(Agent)”之间的鸿沟里。
|
|
17
|
+
|
|
18
|
+
市面上绝大多数教程会教你如何安装 LangChain、LlamaIndex 或是使用 AutoGPT 等黑盒框架。它们通过层层叠叠的类(Classes)和复杂的对象抽象,把大模型的 Raw HTTP 调用和心智决策死循环封装在厚厚的冰山之下。初学者往往只需要敲入两行代码 `agent.run("do something")` 就能跑起一个 Demo。然而,一旦程序在生产环境中崩溃,面对成百上千行的报错栈,没人知道那座冰山下面到底发生了什么。
|
|
19
|
+
|
|
20
|
+
**这正是我们编写这本书的初衷:拆掉冰山,还你物理世界。**
|
|
21
|
+
|
|
22
|
+
本书不依赖任何第三方臃肿的 Agent 框架。我们将大模型的底层文字接龙机制、JSON Schema 的参数推导控制流、OpenAI 与 Gemini 的 Function Calling 网络原始数据包,乃至流式传输的 SSE Delta 协议,像解剖生物标本一样,毫无保留地摊在你的面前。
|
|
23
|
+
|
|
24
|
+
为了让你能够看清这些底层原理在代码中的物理投射,我们为你提供了一个完全透明、极致精炼的开源白盒沙箱 —— **Freya**。
|
|
25
|
+
|
|
26
|
+
在接下来的 13 个章节中,Freya 将成为你的白盒透视镜。你将跟着我们,一步步读懂 `agent-executor.ts` 中的 `while(loop)` 决策死循环,看清 `SessionCompactor` 如何在 Token 溢出时调用 LLM 剔除冗余,以及 Abort 信号如何在多层异步流中层层传递、强行“刹车”。
|
|
27
|
+
|
|
28
|
+
这不是一本教你如何“调包”的手册,而是一部教你如何从零制造一台智能体引擎的“手艺人指南”。
|
|
29
|
+
|
|
30
|
+
欢迎来到智能体的物理世界。让我们开始。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eoasmxd/freya",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Freya - 微内核智能体系统",
|
|
@@ -35,8 +35,9 @@
|
|
|
35
35
|
"src"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@eoasmxd/freya-sdk": "^0.
|
|
38
|
+
"@eoasmxd/freya-sdk": "^0.4.1",
|
|
39
39
|
"ws": "^8.18.0",
|
|
40
|
+
"mysql2": "^3.11.0",
|
|
40
41
|
"qrcode-terminal": "^0.12.0"
|
|
41
42
|
},
|
|
42
43
|
"scripts": {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MySQL 数据库查询工具箱。
|
|
2
|
+
|
|
3
|
+
提供执行标准 SQL 只读查询语句并返回结构化 JSON 数据结果的能力。
|
|
4
|
+
|
|
5
|
+
使用规范:
|
|
6
|
+
1. 本工具仅支持执行 SELECT 查询语句,严禁执行任何非 SELECT 语句,禁止执行任何增删改或 DDL 破坏性语句。
|
|
7
|
+
2. 严禁主观猜测表名与字段名,必须严格基于上下文或业务 Skill 指南中确定、已知的数据结构编写 SQL。
|
|
8
|
+
3. 支持通过 `connection` 参数指定目标数据库连接名称,若不传则自动使用默认连接。
|
|
9
|
+
4. 单次查询返回结果条数受到系统安全限制截断,编写查询时建议显式使用合理的 `LIMIT` 子句。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
你是一个严格的 SQL 安全与完整性审查审计员。你的唯一职责是对待执行的 SQL 查询语句进行安全与完整性审查。
|
|
2
|
+
|
|
3
|
+
审查准则:
|
|
4
|
+
1. **完整性审查**:
|
|
5
|
+
- SQL 语句必须语法结构完整、语义明确。
|
|
6
|
+
- 严禁包含伪代码、截断残缺语句或未闭合的括号/引号。
|
|
7
|
+
|
|
8
|
+
2. **只读安全约束**:
|
|
9
|
+
- 必须仅为 SELECT 查询操作(仅允许 SELECT 查询语句,严禁执行 SHOW、EXPLAIN、DESCRIBE 等其他语句)。
|
|
10
|
+
- 严禁包含任何数据修改语句(如 INSERT、UPDATE、DELETE、REPLACE 等)。
|
|
11
|
+
- 严禁包含任何数据定义与删除语句(如 DROP、TRUNCATE、ALTER、CREATE 等)。
|
|
12
|
+
- 严禁包含权限管理、事务控制等系统级命令(如 GRANT、REVOKE、LOCK TABLES 等)。
|
|
13
|
+
- 严禁利用分号 `;` 拼接多条执行语句进行批处理或 SQL 注入攻击。
|
|
14
|
+
- 严禁包含高危文件读写或外部系统交互指令(如 INTO OUTFILE、INTO DUMPFILE、LOAD DATA、LOAD_FILE 等)。
|
|
15
|
+
|
|
16
|
+
输出规范:
|
|
17
|
+
请直接返回合法且不包含 Markdown 代码块标记(如 ```json)的纯 JSON 字符串,格式如下:
|
|
18
|
+
{
|
|
19
|
+
"passed": true,
|
|
20
|
+
"reason": "审核通过,为合法的只读查询语句。"
|
|
21
|
+
}
|
|
22
|
+
或
|
|
23
|
+
{
|
|
24
|
+
"passed": false,
|
|
25
|
+
"reason": "具体的拦截阻断原因"
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FreyaContext } from '@eoasmxd/freya-sdk';
|
|
2
|
+
export interface AuditResult {
|
|
3
|
+
passed: boolean;
|
|
4
|
+
reason: string;
|
|
5
|
+
}
|
|
6
|
+
/** 前置 SQL 安全与完整性审查审计服务 */
|
|
7
|
+
export declare class SqlAuditService {
|
|
8
|
+
private cachedPrompt;
|
|
9
|
+
/** 双通道探针加载审计提示词模板 */
|
|
10
|
+
private loadAuditPrompt;
|
|
11
|
+
/** 执行前置独立 LLM 分析审查 */
|
|
12
|
+
audit(sql: string, connectionName: string, ctx: FreyaContext): Promise<AuditResult>;
|
|
13
|
+
}
|