diff --git a/doc/architecture/overview.md b/doc/architecture/overview.md index e69de29b..c4810832 100644 --- a/doc/architecture/overview.md +++ b/doc/architecture/overview.md @@ -0,0 +1,95 @@ +# 整体架构与运行流 + +Partner 是一个多模块、异步协作的智能体运行时。 + +为平衡扩展性与组件间一致性,Partner 内部具备一个小型的 DI 容器,以及多个具备配套接口的注册中心。它们会在 Agent 启动时有序拉起,并将各自的关闭 Hook 注册进名为 `AgentContext` 的对象中,在 JVM 收到终止信号时有序触发各个 shutdown hook 进行关闭。 + +本文是架构文档入口,用于说明核心文档的阅读顺序和主题边界。下方总览图描述 Partner-Core 中感知、记忆、行动、交流与对话滚动模块在一次运行轮次中的协作关系。 + +## 阅读顺序 + +- [Agent 启动流程](startup.md):说明 `Agent.launch()` 的外层启动顺序。 +- [Agent 注册链](register-chain.md):说明 `AgentRegisterFactory.launch()` 如何扫描、校验、实例化并注入组件与 Capability。 +- [Runtime 输入与模块调度](runtime-flow.md):说明 Gateway 输入如何进入 `AgentRuntime`,以及 Running module 如何被调度。 +- [关闭流程](shutdown.md):说明 JVM shutdown hook、生命周期关闭钩子与 `@Shutdown` 方法的执行顺序。 + +## 核心概念 + +### AgentContext + +`AgentContext` 是注册链和运行时之间的共享容器,主要保存: + +- `modules`:扫描并实例化得到的 Running / Sub / Standalone 模块。 +- `capabilities`:Capability 动态代理、CapabilityCore 实例和方法路由信息。 +- `additionalComponents`:非模块类型的 `@AgentComponent` 实例。 +- `shutdownHooks`:从 `@Shutdown` 方法收集得到的关闭钩子。 +- `preShutdownHooks` / `postShutdownHooks`:框架与应用显式注册的生命周期关闭钩子。 + +### Configurable + +`Configurable` 用于向 `ConfigCenter` 注册配置入口。启动阶段会先注册框架内置和应用传入的 Configurable;随后在 `ConfigCenter.initAll()` 阶段读取配置并触发各自的初始化逻辑。 + +### Gateway + +Gateway 是外部输入协议与 Partner Runtime 之间的边界。Gateway 将协议输入转换成 `RunningFlowContext`,再提交给 `AgentRuntime`。响应输出也通过 `ResponseChannel` 抽象回到具体 Gateway。 + +### Running Module + +Running module 是 `AgentRuntime` 直接调度的模块类型。它们按 `module.order()` 分组执行:order 小的组先执行,同一 order 内并发执行。 + +## Partner-Core 模块链路总览 + +```mermaid +flowchart TD + Wake["wakeSignal"] --> Source["取出 source"] + Source --> Context["构造 Context"] + Context --> Execute["executeTurn"] + + Execute --> Perceive["order = 1
感知上下文"] + Perceive --> Planning["order = 2
记忆 / 行动"] + Planning --> Communication["order = 5
交流生成"] + Communication --> Rolling["order = 7
对话滚动"] + Rolling --> End["本轮结束"] + + Planning -. "MemorySelector" .-> MemoryAsync["异步召回
MEMORY context"] + Planning -. "ActionPlanner" .-> ActionAsync["异步行动
ACTION context"] + Rolling -. "滚动后" .-> MemoryUpdate["异步更新
召回索引"] + + Perceive -.-> Workspace["ContextWorkspace"] + MemoryAsync -.-> Workspace + ActionAsync -.-> Workspace + MemoryUpdate -.-> Workspace + Rolling -. "dialog_history" .-> Workspace + Workspace -. "resolve context" .-> Communication + ActionAsync -. "initiateTurn" .-> Wake + + classDef main fill:#eef6ff,stroke:#2f6f9f,color:#1c3144; + classDef async fill:#fff7e6,stroke:#b7791f,color:#3b2f16,stroke-dasharray: 5 5; + classDef state fill:#f1f8f4,stroke:#3f8f5f,color:#173b24; + + class Wake,Source,Context,Execute,Perceive,Planning,Communication,Rolling,End main; + class MemoryAsync,ActionAsync,MemoryUpdate async; + class Workspace state; +``` + +### 图例说明 + +- 图中蓝色节点表示本轮 `PartnerRunningFlowContext` 在 `AgentRuntime.executeTurn()` 中的同步主链路。`AgentRuntime` 会按 `module.order()` 分组调度 Running module:order 较小的模块组先执行,同一 order 内的模块并发执行。 + +- 黄色节点表示模块内部启动的异步任务。它们不会阻塞当前主链路继续向后执行,因此异步任务写入的 `MEMORY context` 或 `ACTION context` 不保证一定会被本轮 `CommunicationProducer` 读取;如果写入晚于本轮交流生成,则会影响后续 turn。 + +- 绿色节点表示 `ContextWorkspace`。感知、记忆、行动、对话滚动等模块会向其中注册不同 focused domain 的上下文块;`CommunicationProducer` 在生成回复前统一 resolve `COGNITION / ACTION / MEMORY / PERCEIVE` 相关上下文,并与对话历史和当前输入一起组装成模型输入。 + +### 模块链路说明 + +- `PerceiveMonitor` 和 `SystemStatsMonitor` 位于 order 1,主要负责刷新交互时间、采集系统状态,并写入 `PERCEIVE` 域上下文。 + +- `MemorySelector` 和 `ActionPlanner` 位于 order 2。`MemorySelector` 在同步阶段收集本轮输入,并尝试启动异步 recall worker;实际记忆召回、候选切片评估和 `activated_memory_slices` 写入发生在异步任务中。`ActionPlanner` 在同步阶段提取行动意图并写入初始 ACTION 状态,后续评估、确认、执行或调度由异步任务继续处理。 + +- `CommunicationProducer` 位于 order 5,是本轮对外交流的主要出口。它读取 `ContextWorkspace`、当前保留的 conversation history 和本轮输入,生成回复并更新聊天轨迹。 + +- `DialogRolling` 位于 order 7,用于在对话历史达到阈值后执行压缩、总结和滚动。滚动结果会写入记忆系统,并向 `ContextWorkspace` 注册 `dialog_history`,供后续 turn 使用。 + +### 异步回流 + +`ActionPlanner` 的异步任务可能通过 `initiateTurn()` 重新提交输入,从而触发新的 `wakeSignal`。这不是当前 turn 的下一步,而是后续 turn 的入口。也就是说,图中的虚线回流表示“可能产生新的运行轮次”,不是当前同步链路的一部分。 \ No newline at end of file diff --git a/doc/architecture/register-chain.md b/doc/architecture/register-chain.md new file mode 100644 index 00000000..e1caa608 --- /dev/null +++ b/doc/architecture/register-chain.md @@ -0,0 +1,158 @@ +# Agent 注册链 + +本文说明 `AgentRegisterFactory.launch(packageName)` 内部的注册链。注册链的职责是基于应用包与外部模块目录扫描结果,完成组件、模块、Capability、生命周期方法和关闭方法的注册。 + +`AgentRegisterContext` 是注册链上下文。它持有 `Reflections` 扫描器,以及供各阶段读写的 `ComponentFactoryContext`、`CapabilityFactoryContext` 和全局 `AgentContext`。 + +```mermaid +flowchart TD + A["AgentRegisterFactory.launch(packageName)"] --> B["packageNameToURL(packageName)"] + B --> C["创建 AgentRegisterContext"] + + subgraph CTX["AgentRegisterContext"] + direction TB + C1["reflections
扫描字段 / 方法 / 类型注解 / 子类"] + C2["componentFactoryContext
缓存 @Init 扫描结果"] + C3["capabilityFactoryContext
缓存 Capability 扫描结果"] + C4["agentContext
注册运行时组件"] + end + + C --> CTX + + CTX --> F1["ComponentAnnotationValidatorFactory"] + F1 --> F2["ComponentRegisterFactory"] + F2 --> F3["ComponentInjectorFactory"] + F3 --> F4["CapabilityAnnotationValidatorFactory"] + F4 --> F5["CapabilityRegisterFactory"] + F5 --> F6["CapabilityInjectorFactory"] + F6 --> F7["ComponentInitHookExecutorFactory"] + F7 --> F8["ShutdownHookCollectorFactory"] + F8 --> Z["注册链完成"] + + subgraph S1["ComponentAnnotationValidatorFactory"] + direction TB + S1A["校验 @Init"] + S1B["校验 @InjectModule"] + S1C["将 @Init 方法缓存到 componentFactoryContext"] + S1A --> S1B --> S1C + end + + subgraph S2["ComponentRegisterFactory"] + direction TB + S2A["扫描 @AgentComponent"] + S2B["反射调用无参构造器实例化"] + S2C{"是否 AbstractAgentModule?"} + S2D["注册到 AgentContext.modules"] + S2E["注册到 AgentContext.additionalComponents"] + S2F{"模块类型"} + S2G["ModuleContextData.Running
order / modelInfo / launchTime"] + S2H["ModuleContextData.Sub
injectTarget / modelInfo / launchTime"] + S2I["ModuleContextData.Standalone
injectTarget / modelInfo / launchTime"] + + S2A --> S2B --> S2C + S2C -->|是| S2D --> S2F + S2C -->|否| S2E + S2F -->|Running| S2G + S2F -->|Sub| S2H + S2F -->|Standalone| S2I + end + + subgraph S3["ComponentInjectorFactory"] + direction TB + S3A["读取 AgentContext.modules"] + S3B["按 Running / Sub / Standalone 分类"] + S3C["处理 @InjectModule"] + S3D["记录 injectTarget"] + S3A --> S3B --> S3C --> S3D + end + + subgraph S4["CapabilityAnnotationValidatorFactory"] + direction TB + S4A["扫描 @CapabilityCore"] + S4B["扫描 @Capability"] + S4C["扫描 @CapabilityMethod"] + S4D["校验 Capability value 唯一"] + S4E["校验 CapabilityMethod 位置与唯一实现"] + S4F["校验 @InjectCapability"] + S4G["写入 capabilityFactoryContext"] + S4A --> S4D + S4B --> S4D + S4C --> S4E + S4D --> S4E --> S4F --> S4G + end + + subgraph S5["CapabilityRegisterFactory"] + direction TB + S5A["读取 capabilityFactoryContext"] + S5B["实例化 CapabilityCore"] + S5C["构建方法路由表"] + S5D["为 @Capability 接口创建动态代理"] + S5E["注册到 AgentContext.capabilities"] + S5A --> S5B --> S5C --> S5D --> S5E + end + + subgraph S6["CapabilityInjectorFactory"] + direction TB + S6A["读取 modules + additionalComponents"] + S6B["读取 AgentContext.capabilities"] + S6C["处理 @InjectCapability 字段"] + S6A --> S6C + S6B --> S6C + end + + subgraph S7["ComponentInitHookExecutorFactory"] + direction TB + S7A["读取 componentFactoryContext 中的 @Init 方法"] + S7B["目标为 modules + additionalComponents"] + S7C["按 @Init.order 升序执行"] + S7A --> S7C + S7B --> S7C + end + + subgraph S8["ShutdownHookCollectorFactory"] + direction TB + S8A["扫描 @Shutdown 方法"] + S8B["校验位置与参数"] + S8C["AgentContext.addShutdownHook(method, order)"] + S8A --> S8B --> S8C + end + + F1 -.-> S1 + F2 -.-> S2 + F3 -.-> S3 + F4 -.-> S4 + F5 -.-> S5 + F6 -.-> S6 + F7 -.-> S7 + F8 -.-> S8 +``` + +## AgentContext + +`AgentContext` 是注册链的主要产物。它不是单轮对话上下文,而是运行时组件注册结果和关闭逻辑的集中容器。 + +```mermaid +flowchart TD + A["AgentContext"] --> B["modules"] + A --> C["capabilities"] + A --> D["additionalComponents"] + A --> E["metadata"] + A --> F["shutdownHooks"] + A --> G["preShutdownHooks"] + A --> H["postShutdownHooks"] + + B --> B1["ModuleContextData.Running"] + B --> B2["ModuleContextData.Sub"] + B --> B3["ModuleContextData.Standalone"] + + C --> C1["CapabilityImplementation"] + C1 --> C2["capability instance"] + C1 --> C3["capability cores"] + C1 --> C4["capability methods"] + + F --> F1["RUNNING"] + F --> F2["ADDITIONAL"] + F --> F3["STANDALONE"] + F --> F4["SUB"] + F --> F5["CAPABILITY"] +``` diff --git a/doc/architecture/runtime-flow.md b/doc/architecture/runtime-flow.md new file mode 100644 index 00000000..e9db1ca3 --- /dev/null +++ b/doc/architecture/runtime-flow.md @@ -0,0 +1,98 @@ +# Runtime 输入与模块调度 + +本文说明外部输入如何经由 Gateway 进入 `AgentRuntime`,以及 `AgentRuntime` 如何按 `source` 聚合输入、去重、debounce 并调度 Running module。 + +## Gateway 与输入提交 + +Gateway 负责把外部输入转换成 `RunningFlowContext`,再提交给 `AgentRuntime`。`AgentRuntime` 不直接感知 WebSocket 等具体输入协议。 + +```mermaid +flowchart TD + A["外部输入\nWebSocket / 其他 Gateway"] --> B["AgentGateway.receive(inputData)"] + B --> C["parseRunningFlowContext(inputData)"] + C --> D["AgentRuntime.submit(context)"] + + D --> E["按 context.source 聚合输入"] + E --> E1["latestContextsBySource[source]\n旧 context 与新 context mergedWith"] + E --> E2["sourceVersions[source] + 1"] + E --> E3["sourceQueue 加入 source\n队列内 source 不重复"] + + E3 --> F{"当前是否正在执行同一 source?"} + F -->|是| G["currentExecutingContext.status.interrupted = true"] + F -->|否| H["发送 wakeSignal"] + + G --> H + H --> I["AgentRuntime 后台协程消费 wakeSignal"] + I --> J["drainQueue()"] + J --> K["executeSource(source)"] +``` + +## 模块运行时 + +`AgentRuntime` 采用按 `source` 聚合的异步执行模型。同一个 `source` 的连续输入会合并为最新的 `RunningFlowContext`;如果新输入到达时该 `source` 正在执行,当前上下文会被标记为 interrupted,当前轮结束后 runtime 会从 Running module 链头重新执行最新合并后的上下文。 + +```mermaid +flowchart TD + A["AgentRuntime 后台协程"] --> B["收到 wakeSignal"] + B --> C["drainQueue()"] + C --> D["取 sourceQueue.firstOrNull()"] + D --> E{"是否存在 source?"} + E -->|否| Z["返回,等待下一次 wakeSignal"] + E -->|是| F["executeSource(source)"] + + F --> G["awaitDebouncedExecution(source)"] + G --> G1{"debounceWindow > 0?"} + G1 -->|是| G2["等待 debounceWindow"] + G2 --> G3{"sourceVersions 是否变化?"} + G3 -->|变化| G2 + G3 -->|稳定| H["构造 SourceExecution(context, version)"] + G1 -->|否| H + + H --> I["标记 currentExecutingSource/context"] + I --> J["executeTurn(context)"] + + J --> K{"runningModules 是否为空?"} + K -->|是| L["refreshRunningModules()"] + K -->|否| M["按 order 遍历 Running modules"] + L --> M + + M --> N["过滤 maskedModules"] + N --> O["按 order 分组并排序"] + O --> P["同一 order 内 coroutineScope + async 并发执行"] + P --> Q["module.execute(runningFlowContext)"] + Q --> R{"context.status.interrupted?"} + + R -->|是| S["本轮中断"] + R -->|否| T["本轮完成"] + + S --> U["检查 latest version"] + T --> U + + U --> V{"执行期间是否有新输入或版本变化?"} + V -->|是| W["保留 source\n从链头重新执行最新 merged context"] + W --> G + + V -->|否| X["清理 latestContextsBySource/sourceQueue/sourceVersions"] + X --> Z +``` + +Running module 的执行顺序由 `module.order()` 决定。order 较小的组先执行,同一 order 内的模块并发执行。 + +```mermaid +flowchart LR + A["Running modules from AgentContext.modules"] --> B["过滤 maskedModules"] + B --> C["按 module.order() 分组"] + C --> D["order 小的组先执行"] + + D --> E1["order = 10"] + D --> E2["order = 20"] + D --> E3["order = 30"] + + E1 --> F1["同组模块并发执行"] + F1 --> E2 + E2 --> F2["同组模块并发执行"] + F2 --> E3 + E3 --> F3["同组模块并发执行"] + + F3 --> G["所有 order 执行完成"] +``` diff --git a/doc/architecture/shutdown.md b/doc/architecture/shutdown.md new file mode 100644 index 00000000..72ec298a --- /dev/null +++ b/doc/architecture/shutdown.md @@ -0,0 +1,50 @@ +# 关闭流程 + +本文说明 Partner 在 JVM 终止时的关闭顺序。 + +关闭阶段由 `AgentContext` 安装到 JVM 的 shutdown hook 统一触发。生命周期 Hook 与注解式 `@Shutdown` Hook 是两套机制:前者用于框架级收尾,如关闭 Gateway、保存状态、关闭配置监听;后者用于模块、额外组件与 Capability Core 自己声明的关闭逻辑。 + +当前关闭顺序为: + +1. `preShutdownHooks` +2. `RUNNING` +3. `ADDITIONAL` +4. `STANDALONE` +5. `SUB` +6. `CAPABILITY` +7. `postShutdownHooks` + +```mermaid +flowchart TD + A["JVM 收到终止信号"] --> B["Runtime.addShutdownHook 触发"] + B --> C["AgentContext.computeInstances()"] + + C --> C1["收集 Running module 实例"] + C --> C2["收集 Standalone module 实例"] + C --> C3["收集 Sub module 实例"] + C --> C4["收集 additional component 实例"] + C --> C5["收集 capability core 实例"] + + C1 --> D["执行 preShutdownHooks"] + C2 --> D + C3 --> D + C4 --> D + C5 --> D + + D --> D1["AgentGatewayRegistry.close()"] + D1 --> D2["停止所有 running gateway channel"] + D2 --> D3["AgentRuntime.unregisterResponseChannel(channel)"] + D3 --> D4["默认响应通道恢复为 LogChannel"] + + D --> E["执行 @Shutdown: RUNNING"] + E --> F["执行 @Shutdown: ADDITIONAL"] + F --> G["执行 @Shutdown: STANDALONE"] + G --> H["执行 @Shutdown: SUB"] + H --> I["执行 @Shutdown: CAPABILITY"] + + I --> J["执行 postShutdownHooks"] + J --> J1["StateCenter.save()"] + J1 --> J2["TraceSinkRegistry.close()"] + J2 --> J3["ConfigCenter.close()"] + J3 --> K["关闭流程结束"] +``` diff --git a/doc/architecture/startup.md b/doc/architecture/startup.md new file mode 100644 index 00000000..b208edd7 --- /dev/null +++ b/doc/architecture/startup.md @@ -0,0 +1,55 @@ +# Agent 启动流程 + +本文说明 `Agent.newAgent(appClass).launch()` 的外层启动顺序。 + +`Agent.launch()` 负责拉起基础单例、注册配置参与者、注册 Gateway、安装关闭钩子、添加外部模块目录,并启动注册工厂。组件扫描、模块实例化和能力注册的细节见 [注册链](register-chain.md)。 + +```mermaid +flowchart TD + A["Agent.newAgent(appClass).launch()"] --> B["加载基础单例
ConfigCenter / StateCenter"] + + B --> C["注册 ExceptionReporter"] + + C --> D + + subgraph D["注册 Configurable"] + direction TB + D1["LogAdviceProvider.register()"] + D2["ModelRuntimeRegistry.register()"] + D3["AgentGatewayRegistry.register()"] + D4["应用传入的 Configurable.register()"] + end + + D --> E["注册 AgentGatewayRegistration"] + + E --> F + + subgraph F["注册关闭钩子"] + direction TB + F1["preShutdown
AgentGatewayRegistry.close()"] + F2["preShutdown hooks"] + F3["postShutdown
StateCenter.save()"] + F4["postShutdown
TraceSinkRegistry.close()"] + F5["postShutdown
ConfigCenter.close()"] + F6["postShutdown hooks"] + F1 --> F2 + F3 --> F4 --> F5 --> F6 + end + + F --> G["添加外部模块扫描目录
resources/module"] + G --> H["启动注册工厂
AgentRegisterFactory.launch(application package)"] + + H --> I + + subgraph I["初始化配置系统"] + direction TB + I1["ConfigCenter.initAll()
初始化已注册的 Configurable"] + I2["触发各 Configurable.init(config, json)"] + I3["ConfigCenter.start()
启动配置监听"] + I1 --> I2 --> I3 + end + + I --> K["Agent 启动完成"] +``` + +Gateway 的实际 `launch()` 不在 `AgentGatewayRegistration.register()` 中直接发生。Gateway registration 只把可用通道注册到 `AgentGatewayRegistry`;真正的通道创建、启动和默认响应通道设置发生在 `ConfigCenter.initAll()` 阶段,由 `AgentGatewayRegistry.init()` 根据 `gateway.json` 执行。 diff --git a/doc/config/configuration.md b/doc/config/configuration.md index e69de29b..6316f03b 100644 --- a/doc/config/configuration.md +++ b/doc/config/configuration.md @@ -0,0 +1,26 @@ +# 配置中心 + +本章主要用于介绍 Partner 可用的配置内容。在 Partner 中,所有配置都通过 ConfigCenter、Configurable、以及配套的 ConfigRegistration 来承担,故大部分都借助文件监听,提供热重载能力。 +> 具体配置详情,参考[配置说明](#配置说明)章节。 + +## 运行流程 +```mermaid + +``` +> ConfigCenter 生效流程 + +## 配置说明 + +### 目录 + +### AgentGateway + +### ModelRuntime + +### AgentRuntime + +### LogAdvice + +### ExecutionPolicy + +### VectorClient