feat: Docker 容器化、Cookie 鉴权、Coordinator 编排、FTS5 搜索与 P1-P3 全面收尾
Docker 容器化部署
- 提供 Mode A (Alpine musl, ~23MB) 和 Mode B (Distroless glibc, ~87MB)
两种镜像,Docker Compose 一键启动
- build.rs 支持 SKIP_DASHBOARD_BUILD 跳过前端构建
- 国内镜像加速 (npm/apt/apk) 通过 USE_MIRRORS build-arg 控制
安全:Cookie-Based 鉴权系统
- HttpOnly/SameSite=Strict Cookie 会话管理(24h 过期自动清理)
- 登录/登出/验证接口 + 中间件注入
- 前端登录页面 + 退出按钮
- 三层 CORS:localhost 鉴权 / 全放通 bookmarklet / 受保护路由
- 书签脚本 fetch 添加 credentials:'include'
Coordinator 模式 (P2)
- 4 个 meta-tool (delegate_task/check_task/task_stop/synthesize)
- WorkerPool + Semaphore 并发控制 + 超时保护
- 前端协调者模式开关
Hook 系统:UserPromptSubmit 事件 (P2)
- 第 13 个生命周期事件,fire-and-forget 审计
FTS5 全文搜索 (P3)
- agent_sessions_fts + agent_messages_fts 虚拟表
- search_history Agent 工具 + /api/search/history HTTP 接口
- 前端防抖搜索框 + 仅当前会话筛选
工具加载优化 (P3)
- defer_loading 延迟加载 (7 个重型工具)
- is_readonly 只读标记 (9 个查询工具)
- classifier_summary 工具目录供 LLM 按需判断
模型回退策略 (P3)
- LLM_FALLBACK_MODEL 优先回退 + LLM_FALLBACK_CHAIN 链式轮换
- LlmClient model 改为 Arc<RwLock> 支持运行时切换
- 连续 3 次过载后自动切换
压缩记忆桥接 (P3)
- 压缩丢弃消息 → 子代理提取持久记忆 (extract_memories_from_compaction)
git2 依赖修复
- 切换到 vendored-libgit2,消除 OpenSSL 系统依赖
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
对 Claude Code (`/home/fmq/program/claudecode/src/`) 和 Hermes-Agent (`libs/hermes-agent/`)
|
||||
源码的全面架构分析,记录对 AstroResearch Agent 系统的参考价值与改进方向。
|
||||
|
||||
> 分析日期: 2026-06-22 | 最后更新: 2026-06-22
|
||||
> 分析日期: 2026-06-22 | 最后更新: 2026-06-23
|
||||
|
||||
## 实施状态
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
| P1 | PermissionRequest / PermissionDenied Hooks | ✅ 已完成 | `hooks/types.rs`, `traits.rs`, `dispatch.rs`, `mod.rs` |
|
||||
| P1 | Auto-mode Classifier | ⏳ 待定 | — |
|
||||
| P2 | Self-improving Skills(模式检测 + 自动创建 + Curator) | ✅ 已完成 | `skills/pattern_detector.rs` + `curator.rs` + `SkillCreator` |
|
||||
| P2 | Coordinator Mode | ⏳ 待定 | — |
|
||||
| P2 | UserPromptSubmit / PreCompact / PostCompact Hook | ⏳ 待定 | — |
|
||||
| P3 | FTS5 跨 session 搜索 | ⏳ 待定 | — |
|
||||
| P3 | Tool `defer_loading` / `classifier_summary` | ⏳ 待定 | — |
|
||||
| P3 | 模型回退策略 | ⏳ 待定 | — |
|
||||
| P3 | Session Memory Compaction | ⏳ 待定 | — |
|
||||
| P2 | Coordinator Mode | ✅ 已完成 | `src/agent/coordinator/` |
|
||||
| P2 | UserPromptSubmit / PreCompact / PostCompact Hook | ✅ 已完成 | `hooks/types.rs`, `dispatch.rs` |
|
||||
| P3 | FTS5 跨 session 搜索 | ✅ 已完成 | `agent_sessions_fts` + `agent_messages_fts` |
|
||||
| P3 | Tool `defer_loading` / `classifier_summary` | ✅ 已完成 | `tools/mod.rs` |
|
||||
| P3 | 模型回退策略 | ✅ 已完成 | `error_recovery.rs` (LLM_FALLBACK_MODEL/LLM_FALLBACK_CHAIN) |
|
||||
| P3 | Session Memory Compaction | ✅ 已完成 | `memory/mod.rs` (extract_memories_from_compaction) |
|
||||
|
||||
---
|
||||
|
||||
@@ -625,27 +625,33 @@ Coordinator Mode 架构:
|
||||
|
||||
### 9.3 AstroResearch 的现状
|
||||
|
||||
AstroResearch 有 `SubAgentTool` + `TeamManager`,但没有 Coordinator 的概念。Team
|
||||
是平级的(lead ↔ teammates),不是层级编排。
|
||||
AstroResearch 现已实现 Coordinator Mode(`src/agent/coordinator/`,2026-06-23),
|
||||
包含 4 个 meta-tools(delegate_task / check_task / task_stop / synthesize)
|
||||
+ WorkerPool + SubAgentRunner。Team 的平级通信仍然可用,Coordinator 提供层级编排。
|
||||
|
||||
### 9.4 建议改进
|
||||
|
||||
**P2: Coordinator Mode 原型**
|
||||
**P2: Coordinator Mode — 已实现** ✅
|
||||
|
||||
```
|
||||
当 Agent 检测到复杂多步骤任务时,自动切换为 Coordinator 模式:
|
||||
实现架构:
|
||||
src/agent/coordinator/
|
||||
├── mod.rs # CoordinatorRuntime, CoordinatorConfig
|
||||
├── tools.rs # 4 meta-tools: delegate_task, check_task, task_stop, synthesize
|
||||
├── worker_pool.rs # WorkerPool: 异步 Worker 生命周期管理
|
||||
└── runner.rs # SubAgentRunner: Worker 执行器
|
||||
|
||||
用户请求
|
||||
→ Coordinator 做任务分解
|
||||
→ 并行子代理执行 (SubAgentTool, async)
|
||||
→ 结果综合
|
||||
→ 并行 Worker 执行 (delegate_task, async)
|
||||
→ 结果综合 (synthesize)
|
||||
→ 减少单 Agent 的步骤数和 token 消耗
|
||||
|
||||
关键实现:
|
||||
1. Coordinator system prompt: 类似 Claude Code coordinatorMode.ts
|
||||
2. 仅暴露 SubAgentTool + 少量管理工具
|
||||
3. 子代理结果以结构化格式注入
|
||||
4. 综合阶段由 Coordinator 处理
|
||||
1. Coordinator system prompt: 仅暴露 4 个 meta-tools,屏蔽文件/bash 操作
|
||||
2. WorkerPool + SubAgentRunner: 异步并发 Worker 管理
|
||||
3. 子代理结果以结构化格式注入 `<task-notification>`
|
||||
4. 综合阶段由 Coordinator 的 synthesize 工具处理
|
||||
```
|
||||
|
||||
---
|
||||
@@ -718,10 +724,11 @@ hermes-agent/
|
||||
4. Curator 管理 Skill 生命周期
|
||||
5. 下次相似查询直接加载 Skill,无需重新探索
|
||||
|
||||
AstroResearch 已有 Skills 系统 (skills.rs),缺少:
|
||||
- 自动检测重复模式
|
||||
- Agent 自主创建 Skill
|
||||
- Curator 管理 Skill 质量
|
||||
AstroResearch 现已完整实现 Self-improving Skills(2026-06-22):
|
||||
- `skills/pattern_detector.rs` — 自动检测重复工具调用序列模式
|
||||
- `skills/curator.rs` — Curator 管理 Skill 生命周期(质量评分、清理、pinned、seed_record、CuratorRunner)
|
||||
- `skills.rs: SkillCreator` — Agent 自主创建 SKILL.md 文件
|
||||
- `skills.rs: SelfImprovePipeline` — 一站式管道(检测 → 创建 → 质量审查)
|
||||
```
|
||||
|
||||
**Session FTS5 搜索**
|
||||
@@ -736,27 +743,27 @@ class SessionDB:
|
||||
)
|
||||
```
|
||||
|
||||
AstroResearch 的 `agent_sessions` 表有基本的 title/status 字段,但没有全文搜索。
|
||||
AstroResearch 现已实现 FTS5 全文搜索(2026-06-23):
|
||||
- `agent_sessions_fts` + `agent_messages_fts` SQLite FTS5 虚拟表
|
||||
- `search_history` Agent 工具提供跨会话全文本搜索能力
|
||||
|
||||
### 10.5 建议改进
|
||||
### 10.5 实施成果
|
||||
|
||||
**P2: Self-improving Skills 原型**
|
||||
**P2: Self-improving Skills — 已实现** ✅
|
||||
|
||||
```
|
||||
1. Pattern Detector (自动检测)
|
||||
- 监控 N 个 session 中的工具调用序列
|
||||
- 使用简单的子序列匹配识别重复模式
|
||||
1. Pattern Detector (自动检测) ✅
|
||||
- src/agent/skills/pattern_detector.rs — 子序列匹配识别重复工具调用模式
|
||||
- 阈值: 3 次相似序列 → 候选 Skill
|
||||
|
||||
2. Skill Creator (Agent 自主创建)
|
||||
- 将候选 Skill 展示给用户确认
|
||||
- 生成 SKILL.md 文件(含 when_to_use, steps)
|
||||
- 注册到 SkillRegistry
|
||||
2. Skill Creator (Agent 自主创建) ✅
|
||||
- src/agent/skills.rs: SkillCreator — 生成 SKILL.md 文件(kebab-case 命名 + YAML frontmatter)
|
||||
- src/agent/skills.rs: SelfImprovePipeline — 一站式管道(检测 → 创建 → 审查)
|
||||
|
||||
3. Curator (管理生命周期)
|
||||
- 跟踪 Skill 使用频率
|
||||
- 长时间未用的 Skill 标记为 stale
|
||||
- 提示用户审查或删除
|
||||
3. Curator (管理生命周期) ✅
|
||||
- src/agent/skills/curator.rs — 质量评分、清理候选、pinned 保护
|
||||
- seed_record + NEW_SKILL_GRACE_PERIOD_DAYS=7 — 新 Skill 锚定时钟
|
||||
- CuratorRunner — 后台空闲触发审查(paused/idle/interval 三重检查)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -774,12 +781,12 @@ AstroResearch 的 `agent_sessions` 表有基本的 title/status 字段,但没
|
||||
| **P1** | PermissionRequest / PermissionDenied Hook 事件 | Claude Code | ✅ | 安全审计能力 | ~100 行 | 无 |
|
||||
| **P1** | Auto-mode Classifier(廉价模型预分类) | Claude Code | ⏳ | 消除 80%+ 权限弹窗 | ~300 行 | LLM client 支持 |
|
||||
| **P2** | Self-improving Skills(Agent 保存成功流程) | Hermes | ✅ | 科研场景独特价值 | ~500 行 | Skills 系统 |
|
||||
| **P2** | Coordinator Mode(层级多 Agent 编排) | Claude Code | ⏳ | 复杂任务效果提升 | ~800 行 | SubAgent + Team |
|
||||
| **P2** | UserPromptSubmit / PreCompact / PostCompact Hook | Claude Code | ⏳ | Hook 系统完善 | ~200 行 | 无 |
|
||||
| **P3** | FTS5 跨 session 搜索 | Hermes | ⏳ | 历史研究可复用 | 中 | SQLite 迁移 |
|
||||
| **P3** | Tool `defer_loading` / `classifier_summary` | Claude Code | ⏳ | 减小 tool schema prompt | ~50 行 | 无 |
|
||||
| **P3** | 模型回退策略 (Model Fallback) | Claude Code | ⏳ | 提高可用性 | ~200 行 | ErrorRecovery |
|
||||
| **P3** | Session Memory Compaction | Claude Code | ⏳ | 自动化记忆提取 | ~300 行 | MemoryManager + Compact |
|
||||
| **P2** | Coordinator Mode(层级多 Agent 编排) | Claude Code | ✅ | 复杂任务效果提升 | ~800 行 | SubAgent + Team |
|
||||
| **P2** | UserPromptSubmit / PreCompact / PostCompact Hook | Claude Code | ✅ | Hook 系统完善 | ~200 行 | 无 |
|
||||
| **P3** | FTS5 跨 session 搜索 | Hermes | ✅ | 历史研究可复用 | 中 | SQLite 迁移 |
|
||||
| **P3** | Tool `defer_loading` / `classifier_summary` | Claude Code | ✅ | 减小 tool schema prompt | ~50 行 | 无 |
|
||||
| **P3** | 模型回退策略 (Model Fallback) | Claude Code | ✅ | 提高可用性 | ~200 行 | ErrorRecovery |
|
||||
| **P3** | Session Memory Compaction | Claude Code | ✅ | 自动化记忆提取 | ~300 行 | MemoryManager + Compact |
|
||||
|
||||
### 实施进度(2026-06-22)
|
||||
|
||||
@@ -791,8 +798,14 @@ AstroResearch 的 `agent_sessions` 表有基本的 title/status 字段,但没
|
||||
- ✅ 工具并发分区
|
||||
- ✅ PermissionRequest / PermissionDenied Hook 事件
|
||||
- ⏳ Auto-mode Classifier — 需要设计讨论
|
||||
3. **P2 项在下一个大版本规划**:需要设计讨论和更多测试
|
||||
4. **P3 项作为 backlog**:长期优化方向
|
||||
3. **P2 项 — 全部完成** ✅(2026-06-23)
|
||||
- ✅ Coordinator Mode(`src/agent/coordinator/`: 4 meta-tools + WorkerPool + SubAgentRunner)
|
||||
- ✅ UserPromptSubmit Hook Event(第 13 个生命周期事件)
|
||||
4. **P3 项 — 全部完成** ✅(2026-06-23)
|
||||
- ✅ FTS5 跨会话搜索(`agent_sessions_fts` + `agent_messages_fts` + `search_history` 工具)
|
||||
- ✅ Tool defer_loading / classifier_summary
|
||||
- ✅ 模型回退策略(`LLM_FALLBACK_MODEL` / `LLM_FALLBACK_CHAIN`)
|
||||
- ✅ Session Memory Compaction Bridge(`extract_memories_from_compaction`)
|
||||
|
||||
---
|
||||
|
||||
@@ -907,3 +920,30 @@ AstroResearch 的 `agent_sessions` 表有基本的 title/status 字段,但没
|
||||
**CuratorRunner(后台空闲触发审查)**
|
||||
- `src/agent/skills/curator.rs`: `CuratorRunner` 结构体 + `should_run_now()`(paused/idle/interval 三重检查)+ `record_activity()` 心跳 + `run_once()` + `spawn()` tokio 后台任务 + `pause()`/`resume()`
|
||||
- 5 个新增测试(pinned_always_active、pinned_not_in_cleanup、seed_record、runner_paused、runner_idle)
|
||||
|
||||
### 2026-06-23 — Phase 6: Coordinator Mode + UserPromptSubmit Hook
|
||||
|
||||
**Coordinator Mode 协调者模式**
|
||||
- `src/agent/coordinator/`: 新目录,4 个 meta-tools(delegate_task / check_task / task_stop / synthesize)+ WorkerPool + SubAgentRunner
|
||||
- Coordinator system prompt 层级编排 Workers(仅暴露 4 个管理工具,不暴露文件/bash)
|
||||
- Workers 全异步执行,结果以结构化格式注入 Coordinator
|
||||
- Continue-vs-Spawn 决策矩阵(上下文重叠度 <30% → 新 Worker)
|
||||
|
||||
**UserPromptSubmit Hook Event**
|
||||
- `src/agent/hooks/types.rs`: 新增 `UserPromptSubmit` variant(第 13 个生命周期事件)
|
||||
- `src/agent/hooks/dispatch.rs`: `dispatch()` 新增事件分派
|
||||
|
||||
### 2026-06-23 — Phase 7: P3 优化
|
||||
|
||||
**Tool defer_loading / classifier_summary**
|
||||
- `src/agent/tools/mod.rs`: `ToolDef.defer_loading` 字段 — LLM 初次调用时不发送完整 schema,仅发送 summary;Bash/Read 工具标记 defer_loading
|
||||
|
||||
**Model Fallback 模型回退策略**
|
||||
- `src/agent/runtime/error_recovery.rs`: `LLM_FALLBACK_MODEL` + `LLM_FALLBACK_CHAIN` env vars — 主模型故障时自动回退到备选模型链
|
||||
|
||||
**Session Memory Compaction Bridge**
|
||||
- `src/agent/memory/mod.rs`: `extract_memories_from_compaction()` — 在 compaction 自动摘要后从摘要文本提取记忆写入 MemoryManager
|
||||
|
||||
**FTS5 跨会话搜索**
|
||||
- `agent_sessions_fts` + `agent_messages_fts` SQLite FTS5 虚拟表
|
||||
- `search_history` Agent 工具 — 全文本搜索历史会话和消息
|
||||
|
||||
@@ -317,13 +317,17 @@ RateLimited/Overloaded 不走恢复阶梯,独立执行指数退避重试(最
|
||||
| Hook | 触发时机 | 上下文影响 |
|
||||
|:---|:---|:---|
|
||||
| `OnSessionStart` | 会话创建/恢复 | 通知生命周期开始 |
|
||||
| `UserPromptSubmit` | 用户提交提示词后 | 记录/审计用户输入 (P2) |
|
||||
| `PreToolUse` | 工具执行前 | 可 MutateInput 注入上下文、Block 阻止 |
|
||||
| `PostToolUse` | 工具执行后 | 可 MutateOutput 修改结果、审计日志写入 |
|
||||
| `PostToolUseFailure` | 工具执行失败 | 记录错误信息,可 MutateOutput |
|
||||
| `OnStepComplete` | 每步结束 | 日志消息数/预算使用率 |
|
||||
| `OnPreCompact` | 压缩前 | 记录消息数/预估 tokens |
|
||||
| `OnPostCompact` | 压缩后 | 记录新消息数/压缩方法 |
|
||||
| `OnSubagentStart` | 子代理启动 | 通知子代理创建 |
|
||||
| `OnSubagentStop` | 子代理停止 | 记录结果摘要 |
|
||||
| `PermissionRequest` | 权限请求前 | 可 Override 权限决策 (P1) |
|
||||
| `PermissionDenied` | 权限被拒绝后 | 安全审计日志 (P1) |
|
||||
| `OnSessionStop` | 会话终止 | 清理取消状态、记录终止原因 |
|
||||
|
||||
---
|
||||
@@ -373,6 +377,6 @@ Session → Thought → (ToolCall ↔ ToolResult)* → TextDelta → Usage → D
|
||||
| `src/agent/runtime/finalize.rs` | 会话收尾 + 记忆提取 + 轨迹导出 |
|
||||
| `src/agent/subagent.rs` | 子代理上下文隔离 + 独立 ReAct 循环 |
|
||||
| `src/agent/background.rs` | 后台任务队列 + 通知注入 |
|
||||
| `src/agent/hooks.rs` | 9 个生命周期事件 + 内置 3 Hook |
|
||||
| `src/agent/hooks/` | 13 个生命周期事件 + 内置 3 Hook + AsyncAgentHook trait |
|
||||
| `src/agent/skills.rs` | 两层技能加载 + 热重载 + 条件激活 |
|
||||
| `src/agent/tools/memory.rs` | save_memory 工具 + 写入门控 |
|
||||
|
||||
@@ -125,10 +125,12 @@ Agent 系统的所有可配置参数,按子系统分类。
|
||||
|
||||
| 文件 | 加载的变量 |
|
||||
|:---|:---|
|
||||
| `src/lib.rs` (Config) | `LLM_API_KEY`, `LLM_API_BASE`, `LLM_MODEL`, `EMBEDDING_*`, `ADS_API_KEY`, `DATABASE_URL`, `LIBRARY_DIR`, `SKILLS_DIR`, `PORT`, `QINIU_*`, `MINERU_*` |
|
||||
| `src/lib.rs` (Config) | `LLM_API_KEY`, `LLM_API_BASE`, `LLM_MODEL`, `LLM_FALLBACK_MODEL`, `LLM_FALLBACK_CHAIN`, `EMBEDDING_*`, `ADS_API_KEY`, `DATABASE_URL`, `LIBRARY_DIR`, `SKILLS_DIR`, `PORT`, `QINIU_*`, `MINERU_*` |
|
||||
| `src/main.rs` | `EMBEDDING_DIM` |
|
||||
| `src/services/logging.rs` | `LOG_LEVEL`, `LOG_FORMAT`, `LOG_OUTPUTS`, `LOG_DIR` |
|
||||
| `src/agent/runtime/mod.rs` (AgentConfig) | `AGENT_MAX_STEPS`, `AGENT_TOOL_TIMEOUT_SECS`, `AGENT_MAX_TOOL_OUTPUT_CHARS`, `AGENT_CONTEXT_CHAR_LIMIT`, `AGENT_TOKEN_SOFT_LIMIT`, `AGENT_TOKEN_HARD_LIMIT`, `AGENT_MAX_MESSAGES` |
|
||||
| `src/agent/runtime/mod.rs` (call_llm_with_recovery) | `FALLBACK_MODEL` |
|
||||
| `src/agent/runtime/mod.rs` (call_llm_with_recovery) | `LLM_FALLBACK_MODEL` (原 `FALLBACK_MODEL`), `LLM_FALLBACK_CHAIN` (P3) |
|
||||
| `src/agent/runtime/mod.rs` (AgentRuntime) | `AGENT_COORDINATOR_MAX_WORKERS`, `AGENT_COORDINATOR_WORKER_TIMEOUT` (P2) |
|
||||
| `src/agent/compact.rs` (extract_memories_from_compaction) | `EXTRACT_MEMORY_ENABLED` (P3 压缩记忆桥接) |
|
||||
| `src/agent/memory/extraction.rs` (ExtractionConfig) | `EXTRACT_MEMORY_ENABLED`, `EXTRACT_MEMORY_THROTTLE_TURNS`, `EXTRACT_MEMORY_MAX_STEPS` |
|
||||
| `src/services/download.rs` | `OBSCURA_ALLOW_PRIVATE_NETWORK`(程序自动设置) |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Agent Hooks — 生命周期事件系统
|
||||
|
||||
参考 Claude Code hooks 协议,提供 **12 种生命周期事件回调**,基于 **观察者模式 + 责任链模式** 实现。核心目标:在 Agent ReAct 循环的各个关键节点插入横切关注点(取消检查、指标采集、审计日志、权限增强等),**不污染主循环代码**。
|
||||
参考 Claude Code hooks 协议,提供 **13 种生命周期事件回调**,基于 **观察者模式 + 责任链模式** 实现。核心目标:在 Agent ReAct 循环的各个关键节点插入横切关注点(取消检查、指标采集、审计日志、权限增强等),**不污染主循环代码**。
|
||||
|
||||
---
|
||||
|
||||
@@ -25,7 +25,7 @@ src/agent/hooks/
|
||||
mindmap
|
||||
root((Hook 系统<br/>设计原则))
|
||||
接口隔离
|
||||
10 个生命周期方法
|
||||
11 个生命周期方法
|
||||
+2 个权限专用方法 (on_permission_request/on_permission_denied)
|
||||
全部有默认空实现
|
||||
只覆写关心的 hook 点
|
||||
@@ -112,6 +112,7 @@ classDiagram
|
||||
+timeout() Option~Duration~
|
||||
+match_filter() ToolMatchFilter
|
||||
+on_session_start(ctx)
|
||||
+on_user_prompt_submit(ctx)
|
||||
+pre_tool_use(ctx) PreToolUseAction
|
||||
+post_tool_use(ctx) PostToolUseAction
|
||||
+on_post_tool_use_failure(ctx) PostToolUseAction
|
||||
@@ -137,6 +138,7 @@ classDiagram
|
||||
class HookEvent {
|
||||
<<enumeration>>
|
||||
OnSessionStart
|
||||
UserPromptSubmit
|
||||
PreToolUse
|
||||
PostToolUse
|
||||
PostToolUseFailure
|
||||
@@ -252,6 +254,7 @@ classDiagram
|
||||
+run_pre_tool_use(ctx) PreToolUseResult
|
||||
+run_post_tool_use(ctx) PostToolUseResult
|
||||
+run_on_session_start(ctx)
|
||||
+run_on_user_prompt_submit(ctx)
|
||||
+run_on_step_complete(ctx)
|
||||
+run_on_session_stop(ctx)
|
||||
+run_on_subagent_start(ctx)
|
||||
@@ -285,6 +288,7 @@ classDiagram
|
||||
| 事件 | 上下文类型 | 关键字段 |
|
||||
|------|-----------|---------|
|
||||
| OnSessionStart | `SessionStartContext` | session_id, turn_index, is_resume |
|
||||
| UserPromptSubmit | `UserPromptSubmitContext` | session_id, prompt, turn_index (fire-and-forget) |
|
||||
| PreToolUse | `PreToolUseContext` | session_id, tool_name, tool_args, step |
|
||||
| PostToolUse | `PostToolUseContext` | session_id, agent_name, tool_name, tool_args, output_content, is_error, step, elapsed_ms |
|
||||
| PostToolUseFailure | `PostToolUseFailureContext` | session_id, agent_name, tool_name, error_message, is_interrupt, step, elapsed_ms |
|
||||
@@ -525,6 +529,8 @@ sequenceDiagram
|
||||
RT->>HR: with_builtins(db, cancelled, metrics)
|
||||
RT->>HR: run_on_session_start(ctx) ⚡并行
|
||||
Note over HR: ① OnSessionStart
|
||||
RT->>HR: run_on_user_prompt_submit(ctx) 🔥fire-and-forget
|
||||
Note over HR: ⑬ UserPromptSubmit
|
||||
|
||||
Note over API,CMP: ═══ Phase 2: ReAct 循环 ═══
|
||||
loop 每步 (1..max_steps)
|
||||
@@ -598,7 +604,7 @@ sequenceDiagram
|
||||
flowchart LR
|
||||
subgraph Register["add(hook)"]
|
||||
H["hook: Box<dyn AgentHook>"] --> Subs{"subscribed_events()"}
|
||||
Subs -->|"空 = 全部"| All["遍历所有 12 个 HookEvent<br/>event_index[event].push(idx)"]
|
||||
Subs -->|"空 = 全部"| All["遍历所有 13 个 HookEvent<br/>event_index[event].push(idx)"]
|
||||
Subs -->|"指定"| Spec["仅注册声明的事件<br/>event_index[event].push(idx)"]
|
||||
end
|
||||
|
||||
@@ -842,6 +848,7 @@ registry.remove_session_hook(&session_id, "MyTempHook");
|
||||
| 文件 | 集成点 | 方法 |
|
||||
|------|--------|------|
|
||||
| `runtime/mod.rs` | 会话启动 | `run_on_session_start()` |
|
||||
| `runtime/mod.rs` | 用户输入提交后 | `run_on_user_prompt_submit()` (fire-and-forget) |
|
||||
| `runtime/mod.rs` | ReAct 循环 | `run_on_step_complete()` |
|
||||
| `runtime/mod.rs` | Hook 上下文注入 | `hook_contexts → [system-reminder]` |
|
||||
| `runtime/mod.rs` | 会话终止 | `run_on_session_stop()` |
|
||||
@@ -893,6 +900,7 @@ registry.remove_session_hook(&session_id, "MyTempHook");
|
||||
| 2026-06-22 | Phase 4: AsyncAgentHook trait + async hook 调度 |
|
||||
| 2026-06-22 | 模块拆分: mod.rs(537) ← types/traits/matcher/registry/dispatch/builtins |
|
||||
| 2026-06-22 | Phase 5: PermissionRequest/PermissionDenied 事件 — 权限决策钩子 + fire-and-forget 审计 |
|
||||
| 2026-06-23 | Phase 6: UserPromptSubmit hook — 第 13 个生命周期事件,在用户提交提示词后、context building 前触发(fire-and-forget),hooks 可以检查/记录用户输入 | 120 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -311,6 +311,50 @@ sequenceDiagram
|
||||
- `main_agent_saved_this_session == true`(主代理已通过 `save_memory` 工具写入)
|
||||
- 子代理工具集为受限集(仅 4 个只读工具 + `save_memory`),不能执行 bash、不能搜索论文
|
||||
|
||||
## 压缩记忆桥接 (`compact.rs`, P3)
|
||||
|
||||
上下文压缩(compaction)丢弃旧消息时,其中可能包含有长期价值的科研结论和用户偏好。`extract_memories_from_compaction()` 在压缩后自动从丢弃的消息中提取持久记忆,将"即将消失的上下文"转化为"跨会话可用的记忆"。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant RT as AgentRuntime
|
||||
participant Cmp as compact.rs
|
||||
participant Ext as extract_memories_from_compaction
|
||||
participant Sub as SubAgentRunner
|
||||
participant Mgr as MemoryManager
|
||||
|
||||
RT->>Cmp: compress_context_with_hooks_and_log(messages, ...)
|
||||
Cmp-->>RT: 压缩完成,旧消息将从上下文中移除
|
||||
RT->>Ext: extract_memories_from_compaction(before_messages, sid, mgr, app_state)
|
||||
Ext->>Ext: 检查 EXTRACT_MEMORY_ENABLED → false 则 return
|
||||
Ext->>Ext: 过滤非系统消息 → 每条截断 400 字符 → 拼接
|
||||
alt 拼接文本 < 300 字符
|
||||
Ext->>Ext: return (太少不值得提取)
|
||||
end
|
||||
Ext->>Mgr: lock() → build_manifest_preview() 获取现有记忆清单
|
||||
Ext->>Ext: 构建受限 ToolRegistry (仅 SaveMemoryTool)
|
||||
Ext->>Sub: SubAgentRunner.run(EXTRACTION_SYSTEM_PROMPT, prompt, max_steps=3)
|
||||
Note over Ext,Sub: tokio::spawn (fire-and-forget, 不阻塞压缩/ReAct 循环)
|
||||
Sub-->>Mgr: save_memory() 写入提取结果
|
||||
```
|
||||
|
||||
**与 `run_extraction()` 的区别**:
|
||||
|
||||
| 维度 | `run_extraction()` (会话结束) | `extract_memories_from_compaction()` (压缩桥接) |
|
||||
|:---|:---|:---|
|
||||
| 触发时机 | `finalize_turn()` 会话收尾 | `compress_and_restore()` 压缩完成后 |
|
||||
| 数据来源 | 完整对话历史(已持久化到 DB) | 压缩前即将被丢弃的消息快照 |
|
||||
| 消息范围 | 系统 + 用户 + 助手消息 | 仅用户 + 助手 + 工具(去除 system) |
|
||||
| 节流机制 | `ExtractionTracker` 轮次计数 | 仅靠 `EXTRACT_MEMORY_ENABLED` 开关 |
|
||||
| 阻塞行为 | fire-and-forget | fire-and-forget |
|
||||
| 子代理工具集 | 4 只读工具 + `save_memory` | 仅 `save_memory`(最小化成本) |
|
||||
| 最小内容阈值 | 无显式阈值 | 拼接文本 < 300 字符跳过 |
|
||||
|
||||
**设计原理**:
|
||||
- 压缩是最佳记忆提取时机——此时旧消息尚未被物理删除但即将从上下文中移除,记忆系统可以在"内容消失前最后一刻"将其抢救出来
|
||||
- 截断每条消息到 400 字符平衡了信息完整性和子代理 prompt 长度
|
||||
- fire-and-forget 确保压缩不因 LLM 调用延迟而阻塞主 ReAct 循环
|
||||
|
||||
## 时效性与衰减系统
|
||||
|
||||
**指数时间衰减** (`decay.rs`):
|
||||
@@ -403,6 +447,20 @@ score = e^(-λ × days_old)
|
||||
→ mark_main_agent_wrote()
|
||||
→ 返回: 操作状态 + 质量警告 + 重复提示 + manifest 清单
|
||||
|
||||
会话中(压缩时) ← P3 桥接
|
||||
compact.rs: compress_context_with_hooks_and_log(messages, ...)
|
||||
→ 压缩快照前捕获消息副本 (pre_compact_snapshot)
|
||||
→ 执行压缩(snip/auto/aggro_micro)
|
||||
→ extract_memories_from_compaction(snapshot, sid, mgr, app_state)
|
||||
→ 检查 EXTRACT_MEMORY_ENABLED → false 则 return
|
||||
→ 过滤非系统消息 + 截断 400 字符 + 拼接
|
||||
→ 拼接文本 < 300 字符 → return (太少不值得提取)
|
||||
→ tokio::spawn(子代理)
|
||||
→ build_manifest_preview() 获取现有清单
|
||||
→ SubAgentRunner(仅 SaveMemoryTool, max_steps=3)
|
||||
→ save_memory() 写入提取的记忆
|
||||
→ 恢复文件缓存(不等待子代理完成)
|
||||
|
||||
会话结束
|
||||
finalize.rs: finalize_turn()
|
||||
→ 更新 agent_sessions (turn_count, metrics)
|
||||
|
||||
@@ -38,11 +38,12 @@ graph TD
|
||||
end
|
||||
|
||||
subgraph CrossCutting["横切关注点"]
|
||||
Hooks["HookRegistry (9 事件)"]
|
||||
Hooks["HookRegistry (13 事件)"]
|
||||
Skills["SkillRegistry (两层加载)"]
|
||||
Memory["MemoryManager (项目记忆)"]
|
||||
Permission["PermissionChecker"]
|
||||
FileCache["FileStateCache (Read 去重)"]
|
||||
Coordinator["Coordinator Mode (协调者编排)"]
|
||||
end
|
||||
|
||||
subgraph DB["持久化"]
|
||||
@@ -96,8 +97,14 @@ sequenceDiagram
|
||||
DB-->>RT: 验证存在 + 计算 turn_index
|
||||
end
|
||||
RT->>RT: 触发 OnSessionStart hook
|
||||
RT->>RT: 触发 UserPromptSubmit hook (用户输入审计)
|
||||
RT-->>FE: SSE session { session_id, title }
|
||||
|
||||
opt 协调者模式 (coordinator_mode: true)
|
||||
RT->>RT: run_coordinator_turn() → CoordinatorAgent
|
||||
Note over RT: Coordinator 委托 Worker → 合成结果
|
||||
end
|
||||
|
||||
Note over RT: Phase 2 — 上下文构建
|
||||
RT->>RT: build_initial_context()
|
||||
RT->>RT: ① 组装 SystemPrompt (静态 section + 记忆注入)
|
||||
@@ -172,3 +179,29 @@ sequenceDiagram
|
||||
|
||||
---
|
||||
|
||||
### Coordinator Mode(协调者模式, P2)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
User["用户请求"] --> API["POST /api/chat/agent\n{ coordinator_mode: true }"]
|
||||
API --> RT["AgentRuntime::run_coordinator_turn()"]
|
||||
RT --> CA["CoordinatorAgent (仅元工具)"]
|
||||
CA --> Tool["delegate_task / check_task / task_stop / synthesize"]
|
||||
Tool --> WP["WorkerPool (Semaphore 并发控制)"]
|
||||
WP --> W1["Worker 1 (SubAgentRunner)"]
|
||||
WP --> W2["Worker 2 (SubAgentRunner)"]
|
||||
WP --> W3["Worker N (SubAgentRunner)"]
|
||||
W1 --> Synth["synthesize 收集结果"]
|
||||
W2 --> Synth
|
||||
W3 --> Synth
|
||||
Synth --> Answer["最终答案"]
|
||||
```
|
||||
|
||||
Coordinator 仅拥有 4 个元工具,将实际研究工作委托给拥有完整工具访问权限的 Worker 子代理。Worker 通过 `SubAgentRunner` + `Semaphore` 实现并发控制(默认最大 4 并发)。
|
||||
|
||||
- **委托 → 检查 → 合成** 三步工作流
|
||||
- 前端通过 `coordinator_mode: true` 字段启用
|
||||
- 源码: `src/agent/coordinator/{agent,tools,worker,mod}.rs`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -347,11 +347,60 @@ LLM 调用 subagent(research_prompt, max_steps)
|
||||
.run(system_prompt, research_prompt, max_steps)
|
||||
```
|
||||
|
||||
## 外部集成场景
|
||||
|
||||
`SubAgentRunner` 除了通过 `SubAgentTool` 被父代理调用外,还被以下两个子系统使用:
|
||||
|
||||
### 1. Coordinator WorkerPool(P2)
|
||||
|
||||
协调者模式中,`WorkerPool::delegate()` 为每个委托任务创建一个 `SubAgentRunner` 实例:
|
||||
|
||||
```
|
||||
CoordinatorAgent
|
||||
→ delegate_task(task_description, context)
|
||||
→ WorkerPool::delegate()
|
||||
→ tokio::spawn(Worker)
|
||||
→ SubAgentRunner::new_with_registry(app_state, 完整 ToolRegistry)
|
||||
.with_parent_session(session_id)
|
||||
.with_thinking(enable_thinking)
|
||||
.run(WORKER_SYSTEM_PROMPT, task_description, worker_max_steps)
|
||||
→ 结果写入 CoordinatorTask.result
|
||||
→ synthesize()
|
||||
→ 收集所有已完成 Worker 结果 → 合成最终答案
|
||||
```
|
||||
|
||||
关键特征:
|
||||
- Worker 子代理拥有**完整工具访问权限**(与 Coordinator 的 4 个元工具相对)
|
||||
- 通过 `Semaphore` 控制最大并发(默认 4)
|
||||
- 超时保护(默认 300s),超时后标记为 `TimedOut`
|
||||
- 结果通过共享 `CoordinatorTask` 结构返回,不经过 SSE
|
||||
|
||||
### 2. 压缩记忆提取(P3 桥接)
|
||||
|
||||
`compact::extract_memories_from_compaction()` 创建仅含 `SaveMemoryTool` 的受限子代理:
|
||||
|
||||
```
|
||||
AgentRuntime::compress_and_restore()
|
||||
→ compress_context_with_hooks_and_log(...)
|
||||
→ extract_memories_from_compaction(snapshot, sid, mgr, app_state)
|
||||
→ SubAgentRunner::new_with_registry(app_state, SaveMemoryTool 仅此一个)
|
||||
.with_parent_session(sid)
|
||||
.with_thinking(false)
|
||||
.run(EXTRACTION_SYSTEM_PROMPT, prompt, max_steps=3)
|
||||
→ 写入记忆(fire-and-forget,不阻塞 ReAct 循环)
|
||||
```
|
||||
|
||||
关键特征:
|
||||
- 工具集最小化(仅 `save_memory`)——只做记忆写入,不能读文件或搜索
|
||||
- 思考模式关闭(`with_thinking(false)`)——降低提取成本
|
||||
- 内容阈值保护:拼接文本 < 300 字符时跳过
|
||||
- 与 `run_extraction()`(会话结束时触发)互为补充——详见 [memory.md](memory.md)
|
||||
|
||||
## 当前局限与改进方向
|
||||
|
||||
| # | 问题 | 影响 | 改进方向 |
|
||||
|:---|:---|:---|:---|
|
||||
| 1 | **工具串行执行** | 同一步多个工具调用无法并行,慢工具阻塞快工具 | 复用 `executor::execute_parallel`,或至少对 `is_concurrency_safe()` 工具并行 |
|
||||
| 1 | **工具串行执行** | 同一步多个工具调用无法并行,慢工具阻塞快工具 | ~~复用 executor~~ 已通过 Coordinator WorkerPool 在多 Worker 层面实现并行;单 Worker 内仍串行 |
|
||||
| 2 | **无嵌套深度限制** | 子代理可调用 subagent 创建子子代理,理论上无限递归 | 增加深度计数器,超过 2 层时移除 subagent 工具 |
|
||||
| 3 | **Token 估算粗糙** | `content.len() + 4` 对中文极不准确(中文 1 字符 ≈ 1.5-2 token) | 使用 `tiktoken-rs` 或 tokenizer 精确计数 |
|
||||
| 4 | **fire-and-forget 持久化** | DB 写入失败静默忽略,可能丢失审计数据 | 至少记录 warn 日志;关键消息可改为 await |
|
||||
|
||||
@@ -222,15 +222,18 @@ log.commit(CollapseMethod::LlmSummary, (after_count, before_count), summary);
|
||||
|
||||
## Hook 系统与提示词交互
|
||||
|
||||
9 个生命周期事件:
|
||||
13 个生命周期事件:
|
||||
|
||||
| Hook | 与提示词的关系 |
|
||||
|:---|:---|
|
||||
| `OnSessionStart` | 提示词组装前触发 |
|
||||
| `UserPromptSubmit` | 用户提交提示词后、context building 前触发 (P2) |
|
||||
| `PreToolUse::MutateInput` | 注入 `additional_context`(追加为 user 消息) |
|
||||
| `PostToolUse::MutateOutput` | 修改工具输出(影响 LLM 看到的 context) |
|
||||
| `PostToolUseFailure` | 工具执行失败后修改输出 (P1) |
|
||||
| `PreCompact / PostCompact` | 压缩前后记录指标 + CollapseLog commit |
|
||||
| `OnSubagentStart/Stop` | 传递子代理 prompt 和结果摘要 |
|
||||
| `PermissionRequest / PermissionDenied` | 权限决策覆盖和审计 (P1) |
|
||||
|
||||
详见 [hooks.md](hooks.md)。
|
||||
|
||||
|
||||
@@ -176,14 +176,16 @@ let tool_registry =
|
||||
|
||||
## 4 个团队工具
|
||||
|
||||
工具定义在 `src/agent/tools/team.rs`,均设置 `InterruptBehavior::Block`(中断时先完成副作用再停止):
|
||||
工具定义在 `src/agent/tools/team.rs`,均设置 `InterruptBehavior::Block`(中断时先完成副作用再停止)。P3 工具分类注解已应用:
|
||||
|
||||
| 工具名 | 参数 | 功能 | 接收者 |
|
||||
|:---|:---|:---|:---|
|
||||
| `spawn_teammate` | `name`, `role` | 启动一个后台队友 | — |
|
||||
| `send_teammate_message` | `to`, `content` | 向指定队友发送消息 | 队友收件箱 |
|
||||
| `team_broadcast` | `content` | 向所有队友广播消息 | 所有队友收件箱 |
|
||||
| `check_team_inbox` | `agent_name?` (默认 "lead") | 读取并清空收件箱 | Lead 收件箱 |
|
||||
| 工具名 | 参数 | 功能 | 接收者 | 延迟加载 | 只读 |
|
||||
|:---|:---|:---|:---|:---|:---|
|
||||
| `spawn_teammate` | `name`, `role` | 启动一个后台队友 | — | ✅ `defer_loading` | — |
|
||||
| `send_teammate_message` | `to`, `content` | 向指定队友发送消息 | 队友收件箱 | ✅ `defer_loading` | — |
|
||||
| `team_broadcast` | `content` | 向所有队友广播消息 | 所有队友收件箱 | ✅ `defer_loading` | — |
|
||||
| `check_team_inbox` | `agent_name?` (默认 "lead") | 读取并清空收件箱 | Lead 收件箱 | — | ✅ `is_readonly` |
|
||||
|
||||
> **延迟加载说明**(P3):`spawn_teammate`、`send_teammate_message`、`team_broadcast` 标记为 `defer_loading=true`,不随常驻工具注入 system prompt,仅当 LLM 判断需要多 Agent 协作时通过 `tool_catalog` 按需加载。`check_team_inbox` 标记为 `is_readonly=true`(只读取文件邮箱,不修改队友状态),在 auto 模式下可跳过权限确认。
|
||||
|
||||
典型协作流程:
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ classDiagram
|
||||
+check_permissions(args) PermissionRule[]
|
||||
+causes_sibling_abort() bool
|
||||
+execute_with_progress(args, ctx, tx) ToolOutput
|
||||
+classifier_summary() String
|
||||
+is_readonly() bool
|
||||
+defer_loading() bool
|
||||
}
|
||||
|
||||
class InterruptBehavior {
|
||||
@@ -106,10 +109,13 @@ classDiagram
|
||||
| `check_permissions()` | `Vec<PermissionRule>` | `[]` | 工具自定义权限规则:`Deny{tool, reason}` / `Allow{tool}` / `Ask{tool, message}`。与 `PermissionChecker` 管道协同工作 |
|
||||
| `causes_sibling_abort()` | `bool` | `false` | 该工具错误时是否中止兄弟并行执行。用于 `download_paper`、`parse_paper` 等关键工具 |
|
||||
| `execute_with_progress(args, ctx, tx)` | `ToolOutput` | 委托 `execute()` | 长时间操作可覆写,通过 `progress_tx` 发送进度更新到前端 |
|
||||
| `classifier_summary()` | `String` | 取 `description` 第一句,截断到 100 字符 | 工具简要分类描述(~15 词),供 LLM 判断是否需要加载延迟工具 |
|
||||
| `is_readonly()` | `bool` | `false`(保守) | 是否只读(无副作用)。9 个只读工具覆写为 `true` |
|
||||
| `defer_loading()` | `bool` | `false`(常驻) | 是否延迟加载(不在初始 prompt 中)。7 个重型/小众工具覆写为 `true` |
|
||||
|
||||
---
|
||||
|
||||
## 工具清单(23 个)
|
||||
## 工具清单(24 个)
|
||||
|
||||
### 文件系统工具(6 个)— `filesystem/`
|
||||
|
||||
@@ -140,7 +146,7 @@ classDiagram
|
||||
| `query_target` | ✅ | CDS Sesame 天体目标查询(IAU 名称解析 + 坐标/类型) |
|
||||
| `save_note` | ❌ | 高亮批注持久化到数据库 |
|
||||
|
||||
### Agent 自管理工具(5 个)
|
||||
### Agent 自管理工具(6 个)
|
||||
|
||||
| 工具 | 并发安全 | 中断行为 | 功能 |
|
||||
|:---|:---|:---|:---|
|
||||
@@ -149,6 +155,7 @@ classDiagram
|
||||
| `load_skill` | ✅ | Cancel | 按需加载 SKILL.md 技能文件。支持 **inline** 模式(直接返回内容)和 **fork** 模式(启动子代理按技能指引执行任务) |
|
||||
| `save_memory` | ❌ | Block | 跨会话记忆持久化。写入时门控:质量检查(过短/模糊/瞬时/代码模式)+ Jaccard 70% 去重 |
|
||||
| `ask_user` | N/A | Block | 暂停 ReAct 循环向用户提问。oneshot 通道机制:创建问题 → SSE 推送前端 → 阻塞等待 → 5 分钟超时。子代理中不可用(silent 模式) |
|
||||
| `search_history` | ✅ | Cancel | FTS5 跨会话历史搜索。支持会话标题/摘要和消息内容全文检索,避免重复研究已完成的工作 |
|
||||
|
||||
### 高级编排工具(4 个)
|
||||
|
||||
@@ -270,7 +277,7 @@ sequenceDiagram
|
||||
|
||||
RT->>TR: new_with_queue(queue, skill_registry)
|
||||
TR->>TR: add_base_tools()
|
||||
Note over TR: 注册 19 个基础工具
|
||||
Note over TR: 注册 19 个基础工具(不含 search_history,该工具在 Runtime 中按需注入)
|
||||
TR->>Tools: read_file, grep_files, glob_files, run_bash
|
||||
TR->>Tools: file_write, file_edit
|
||||
TR->>Tools: search_papers, get_paper_metadata
|
||||
@@ -294,6 +301,15 @@ sequenceDiagram
|
||||
TR->>TR: definitions()
|
||||
Note over TR: HashMap 值收集 → 按 name 字母序排序
|
||||
Note over TR: 排序保证跨调用稳定性 → 提升 prompt cache 命中率
|
||||
|
||||
RT->>TR: resident_definitions()
|
||||
Note over TR: 返回常驻工具(defer_loading=false)→ 注入初始 prompt
|
||||
|
||||
RT->>TR: deferred_definitions()
|
||||
Note over TR: 返回延迟工具(defer_loading=true)→ 供 LLM 按需加载
|
||||
|
||||
RT->>TR: tool_catalog()
|
||||
Note over TR: 所有工具的 name + classifier_summary → 供 LLM 判断延迟工具需求
|
||||
```
|
||||
|
||||
### 注册表工厂方法
|
||||
@@ -406,6 +422,43 @@ execute() → ToolOutput { content }
|
||||
|
||||
---
|
||||
|
||||
## 工具加载分类(P3 特性)
|
||||
|
||||
`classifier_summary`、`is_readonly`、`defer_loading` 三个 trait 方法共同支持两维度工具分类:
|
||||
|
||||
### 只读 vs 写入分类 (`is_readonly`)
|
||||
|
||||
只读工具无副作用(不修改文件系统、不触发下载、不写入数据库),可在 Auto 模式下跳过权限确认直接执行。
|
||||
|
||||
| 分类 | `is_readonly` | 工具 |
|
||||
|:---|:---|:---|
|
||||
| 只读 (9) | `true` | `read_file`、`grep_files`、`glob_files`、`search_papers`、`get_paper_metadata`、`get_paper_content`、`rag_search`、`query_target`、`check_team_inbox` |
|
||||
| 写入/副作用 | `false`(默认) | 其余所有工具(包括 `run_bash`、`file_write`、`download_paper`、`save_note` 等) |
|
||||
|
||||
### 常驻 vs 延迟加载 (`defer_loading`)
|
||||
|
||||
常驻工具定义注入初始系统 prompt,延迟工具仅在 LLM 需要时通过 `load_tool` 动态加载,减少 prompt 体积。
|
||||
|
||||
| 分类 | `defer_loading` | 工具 |
|
||||
|:---|:---|:---|
|
||||
| 常驻 (18) | `false`(默认) | 核心文件 I/O、论文搜索/检索、用户交互等高频工具 |
|
||||
| 延迟 (7) | `true` | `parse_paper`、`download_paper`、`bg_task_run`、`bg_task_check`、`spawn_teammate`、`send_teammate_message`、`team_broadcast`、`search_history` |
|
||||
|
||||
### 工作流
|
||||
|
||||
```
|
||||
初始化:
|
||||
resident_definitions() → 注入 system prompt(常驻工具 JSON Schema)
|
||||
tool_catalog() → name + classifier_summary 清单 → 供 LLM 决策
|
||||
|
||||
LLM 运行时:
|
||||
分析 task → 查看 catalog → 判断是否需要延迟工具
|
||||
→ 调用 defer_load_specific(name) → 注入单工具 definition
|
||||
→ 正常执行工具调用
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
@@ -435,5 +488,6 @@ src/agent/tools/
|
||||
├── background.rs # bg_task_run + bg_task_check — 后台异步任务
|
||||
├── team.rs # spawn/send/broadcast/check_inbox — 多 Agent 协作
|
||||
├── memory.rs # save_memory — 带质量门控的跨会话记忆
|
||||
├── search_history.rs # search_history — FTS5 跨会话历史搜索(延迟加载)
|
||||
└── persist.rs # maybe_persist_tool_result — 大输出磁盘持久化
|
||||
```
|
||||
|
||||
+242
-124
@@ -1,10 +1,152 @@
|
||||
# AstroResearch Deployment Guide / 部署指南
|
||||
|
||||
AstroResearch 的后端服务是由 Rust 编译出的单执行文件,它内置托管了前端 React 的静态构建资源,因此生产部署十分简单。
|
||||
AstroResearch 支持两种部署方式:**Docker 容器化部署**(推荐,零依赖)和**传统源码编译部署**。
|
||||
|
||||
---
|
||||
|
||||
## 1. 系统要求与环境依赖 (Requirements)
|
||||
## 1. Docker 部署(推荐)
|
||||
|
||||
Docker 部署无需安装 Rust/Node.js 工具链,一键启动。提供两种镜像模式。
|
||||
|
||||
### 快速开始
|
||||
|
||||
```bash
|
||||
# 1. 配置环境变量
|
||||
cp .env.example .env
|
||||
# 编辑 .env 填入 API Key
|
||||
|
||||
# 2. 启动 (Mode A — 推荐日常使用)
|
||||
docker compose up -d
|
||||
|
||||
# 3. 访问
|
||||
open http://localhost:8000
|
||||
```
|
||||
|
||||
### 两种镜像模式对比
|
||||
|
||||
| | Mode A (`Dockerfile`) | Mode B (`Dockerfile.modeB`) |
|
||||
|---|---|---|
|
||||
| **镜像大小** | ~23 MB | ~87 MB |
|
||||
| **基础镜像** | `alpine:3.21` | `distroless/cc-debian12:nonroot` |
|
||||
| **libc** | musl (静态链接) | glibc (动态链接) |
|
||||
| **二进制体积** | ~12 MB | ~59 MB |
|
||||
| **二进制包含** | Rust + C 依赖 | Rust + C + V8 + BoringSSL |
|
||||
| **运行时依赖** | 无 (静态链接) | `libc` + `libstdc++` + `libgcc_s` (已内置) |
|
||||
| **空闲内存** | ~8.6 MiB | ~8.7 MiB |
|
||||
| **Obscura** | 外部 `bin/` bind mount | 编译在二进制内 |
|
||||
| **容器 Shell** | 有 (`/bin/sh`) | 无 (distroless) |
|
||||
| **Healthcheck** | `wget` TCP probe | 编排层替代 |
|
||||
|
||||
---
|
||||
|
||||
### Mode A:Alpine 外部 Obscura(推荐日常使用)
|
||||
|
||||
镜像最小(23 MB),Obscura 作为外部二进制通过 bind mount 注入,可独立更新。
|
||||
|
||||
**构建:**
|
||||
```bash
|
||||
docker build -t astroresearch:latest .
|
||||
```
|
||||
|
||||
**运行:**
|
||||
```bash
|
||||
docker run -d --name astro -p 8000:8000 --env-file .env \
|
||||
-v ./library:/app/library \
|
||||
-v ./logs:/app/logs \
|
||||
-v ./skills:/app/skills:ro \
|
||||
-v ./bin:/app/bin:ro \
|
||||
astroresearch:latest
|
||||
```
|
||||
|
||||
> `bin/` 目录需包含编译好的 Obscura 二进制文件(`obscura` 和 `obscura-worker`)。
|
||||
|
||||
**docker-compose.yml(已内置):**
|
||||
```yaml
|
||||
services:
|
||||
astroresearch:
|
||||
build:
|
||||
context: .
|
||||
image: astroresearch:latest
|
||||
container_name: astroresearch
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- “${PORT:-8000}:8000”
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- LOG_FORMAT=json
|
||||
- LOG_OUTPUTS=stdout
|
||||
volumes:
|
||||
- ./library:/app/library
|
||||
- ./logs:/app/logs
|
||||
- ./skills:/app/skills:ro
|
||||
- ./bin:/app/bin:ro
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Mode B:Distroless 进程内 Obscura(全功能单体)
|
||||
|
||||
Obscura (V8 + BoringSSL) 编译在二进制内,单容器零外部二进制依赖。适合对外交付的一键部署包。
|
||||
|
||||
**前置条件:**
|
||||
```bash
|
||||
mkdir -p libs
|
||||
git clone https://github.com/h4ckf0r0day/obscura libs/obscura
|
||||
```
|
||||
|
||||
**构建:**
|
||||
```bash
|
||||
docker build -f Dockerfile.modeB -t astroresearch-all:latest .
|
||||
```
|
||||
|
||||
**运行:**
|
||||
```bash
|
||||
docker run -d --name astro -p 8000:8000 --env-file .env \
|
||||
-v ./library:/app/library \
|
||||
-v ./logs:/app/logs \
|
||||
-v ./skills:/app/skills:ro \
|
||||
astroresearch-all:latest
|
||||
```
|
||||
|
||||
> Mode B 基于 [Distroless](https://github.com/GoogleContainerTools/distroless) 构建,无 Shell/包管理器,安全性更高但无法 `docker exec` 进入调试。
|
||||
|
||||
---
|
||||
|
||||
### 国内网络加速
|
||||
|
||||
默认启用镜像加速(`USE_MIRRORS=1`),海外构建可通过 build-arg 禁用:
|
||||
|
||||
```bash
|
||||
docker build --build-arg USE_MIRRORS=0 -t astroresearch:latest .
|
||||
```
|
||||
|
||||
**加速源:**
|
||||
|
||||
| 工具 | 镜像 |
|
||||
|------|------|
|
||||
| npm | `registry.npmmirror.com` |
|
||||
| Alpine apk | `mirrors.aliyun.com` |
|
||||
| Debian apt | `mirrors.ustc.edu.cn` |
|
||||
|
||||
---
|
||||
|
||||
### 持久化数据卷
|
||||
|
||||
| 容器路径 | 说明 | 推荐权限 |
|
||||
|----------|------|---------|
|
||||
| `/app/library` | SQLite 数据库 + PDF/HTML 全文 | 读写 |
|
||||
| `/app/logs` | 应用日志(仅 `LOG_OUTPUTS=file` 时写入) | 读写 |
|
||||
| `/app/skills` | Agent 技能文件 (SKILL.md) | 只读 (`:ro`) |
|
||||
| `/app/bin` | Obscura 外部二进制(仅 Mode A) | 只读 (`:ro`) |
|
||||
|
||||
> **注意**:bind mount 目录的宿主权限必须允许容器内用户(uid 65532)写入。如遇 `Permission denied`,在宿主执行 `chown -R 65532 ./library ./logs`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 传统源码编译部署
|
||||
|
||||
### 系统要求
|
||||
|
||||
- **操作系统**:Linux / macOS / Windows
|
||||
- **运行环境**:
|
||||
@@ -12,170 +154,146 @@ AstroResearch 的后端服务是由 Rust 编译出的单执行文件,它内置
|
||||
- Rust (1.75+) 用以编译后端 Axum 进程
|
||||
- SQLite (自动内置,无需单独部署)
|
||||
|
||||
---
|
||||
### 构建步骤
|
||||
|
||||
## 2. 生产构建步骤 (Production Build Steps)
|
||||
|
||||
### 步骤 1:构建 React 前端静态资源
|
||||
进入 `dashboard` 文件夹,安装依赖并执行编译命令。编译产物会自动输出在 `dashboard/dist` 目录下:
|
||||
**步骤 1:构建前端**
|
||||
```bash
|
||||
cd dashboard
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
产物位于 `dashboard/dist/`。
|
||||
|
||||
### 步骤 2:编译 Rust 后端二进制文件
|
||||
返回项目根目录,通过 Cargo 构建 Release 版本的执行文件。编译后的程序会内置链接 `dashboard/dist` 下的全部静态资源:
|
||||
**步骤 2:编译后端**
|
||||
```bash
|
||||
cd ..
|
||||
cargo build --release
|
||||
```
|
||||
编译产物位于 `target/release/astroresearch`。
|
||||
产物位于 `target/release/astroresearch`。
|
||||
|
||||
### 步骤 3(可选):编译健康检查工具
|
||||
如需在目标服务器上运行馆藏健康度诊断与修复:
|
||||
**步骤 3(可选):健康检查工具**
|
||||
```bash
|
||||
cargo build --release --bin health_check
|
||||
```
|
||||
编译产物位于 `target/release/health_check`。
|
||||
|
||||
### 启动
|
||||
|
||||
```bash
|
||||
cp .env.example .env # 编辑填入 API Key
|
||||
./target/release/astroresearch
|
||||
# 监听 http://localhost:8000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 服务部署与启动 (Running in Production)
|
||||
## 3. Obscura 两种部署模式
|
||||
|
||||
1. 将编译出来的 `target/release/astroresearch` 二进制文件部署到目标服务器。
|
||||
2. 在二进制文件同一目录下,创建并填写 `.env` 环境变量配置文件(可从根目录的 `.env.example` 复制模板)。
|
||||
3. 确保本地相对路径下拥有天文对照词典文件 `dictionary.txt`。
|
||||
4. 运行后端服务:
|
||||
```bash
|
||||
./astroresearch
|
||||
```
|
||||
5. 进程将默认在后台启动并监听 `http://localhost:8000` 端口。你可以通过 Nginx 将此端口反向代理到公网 80/443 端口。
|
||||
系统集成 `Obscura` 无头浏览器框架,用于绕过 WAF/Cloudflare 反爬。支持两种模式:
|
||||
|
||||
### 模式 A:外部命令行 (默认)
|
||||
|
||||
Obscura 作为独立二进制运行,与主进程隔离。适合常规生产环境。
|
||||
|
||||
| 部署方式 | 步骤 |
|
||||
|----------|------|
|
||||
| **Docker** | `docker compose up -d`(自动 bind mount `./bin`) |
|
||||
| **源码** | 下载 obscura 到 `bin/`,赋予执行权限后启动 |
|
||||
|
||||
二进制安装(源码部署时):
|
||||
```bash
|
||||
mkdir -p bin/
|
||||
# 下载 obscura 和 obscura-worker 到 bin/,赋予执行权限
|
||||
chmod +x bin/obscura bin/obscura-worker
|
||||
```
|
||||
|
||||
### 模式 B:进程内集成
|
||||
|
||||
Obscura (V8 + BoringSSL) 编译进二进制,单文件零外部依赖。
|
||||
|
||||
| 部署方式 | 构建命令 |
|
||||
|----------|---------|
|
||||
| **Docker** | `docker build -f Dockerfile.modeB -t astroresearch-all:latest .` |
|
||||
| **源码** | `cargo build --release --features obscura-inprocess` |
|
||||
|
||||
> 源码编译 Mode B 需先克隆 [Obscura 源码](https://github.com/h4ckf0r0day/obscura) 到 `libs/obscura/`。同时需要 `binutils`(`nm` + `objcopy`)和 `libclang-dev` 作为构建依赖。
|
||||
|
||||
---
|
||||
|
||||
## 4. Obscura 两种抓取后备部署模式选择 (Obscura Deployment Modes)
|
||||
## 4. 极致内存与体积优化
|
||||
|
||||
系统集成了 `Obscura` 无头浏览器框架来作为遭遇 WAF/Cloudflare 反爬时的自动后备抓取通道。系统支持以下两种编译与部署模式:
|
||||
对于低配服务器(如 1核512M),系统提供 `release-min` 编译配置。
|
||||
|
||||
### 模式 A:外部命令行模式 (默认,推荐)
|
||||
该模式将主 Web 服务与 V8 浏览器运行引擎相隔离,最适合常规生产环境。它拥有最快的编译时间,且进程隔离确保无头浏览器内核异常(如 OOM 或 Panic)不会拖垮主服务器。
|
||||
> `release-min` 与 Mode B 可共同启用,但效果有限——V8/BoringSSL 静态库占用的 ~50MB 无法被 LTO 消除。追求极致轻量建议用 **Mode A + release-min** 组合。
|
||||
|
||||
1. **编译主服务**:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
2. **下载/配置外部二进制**:
|
||||
从 GitHub Releases 下载编译好的 `obscura-x86_64-linux.tar.gz` 压缩包,解压后将 `obscura` 和 `obscura-worker` 两个二进制文件放到项目根目录的 `bin/` 目录下:
|
||||
```bash
|
||||
mkdir -p bin/
|
||||
# 放入 bin/obscura 和 bin/obscura-worker,并赋予执行权限
|
||||
chmod +x bin/obscura bin/obscura-worker
|
||||
```
|
||||
3. **运行**:
|
||||
```bash
|
||||
./target/release/astroresearch
|
||||
```
|
||||
当遭遇 WAF 拦截时,主进程将自动通过异步子进程调用 `./bin/obscura` 进行抓取。
|
||||
**优化指标 (Mode A, release-min):**
|
||||
|
||||
### 模式 B:进程内集成模式 (In-Process Feature)
|
||||
该模式将整个无头浏览器及 V8 运行引擎直接静态链接编译进单个二进制文件中。这免去了在服务器分发和配置外部可执行程序的步骤,提供了”零配置”的部署体验。
|
||||
| 指标 | release | release-min | 降幅 |
|
||||
|------|---------|-------------|------|
|
||||
| 二进制大小 | 17.0 MB | 8.3 MB | 51% |
|
||||
| 启动 RSS | 34.8 MB | 32.9 MB | 5% |
|
||||
| 虚拟内存 (VSZ) | 1.27 GB | 302 MB | 76% |
|
||||
| 数据段 (VmData) | 60.1 MB | 26.5 MB | 55% |
|
||||
|
||||
> [!WARNING]
|
||||
> 由于需要静态链接 C++ 编写的 V8 引擎,**首次编译会额外多耗时 1 到 3 分钟**,且最终编译生成的**单体可执行文件体积会膨胀约 80MB**。
|
||||
```bash
|
||||
# 源码编译
|
||||
cargo build --profile release-min
|
||||
|
||||
0. **获取 Obscura 依赖源码**(仅首次):
|
||||
`libs/` 目录未被 Git 跟踪(已列入 `.gitignore`),`git clone` 后需要单独拉取 Obscura 浏览器内核源码:
|
||||
```bash
|
||||
mkdir -p libs
|
||||
git clone https://github.com/h4ckf0r0day/obscura libs/obscura
|
||||
```
|
||||
# Docker(已默认使用 release-min)
|
||||
docker build -t astroresearch:latest .
|
||||
```
|
||||
|
||||
1. **启用 Feature 编译**:
|
||||
在构建时指定 `--features obscura-inprocess` 特性标记:
|
||||
```bash
|
||||
cargo build --release --features obscura-inprocess
|
||||
```
|
||||
2. **运行**:
|
||||
```bash
|
||||
./target/release/astroresearch
|
||||
```
|
||||
主服务运行期间,无需在磁盘中放置任何 `bin/obscura` 二进制。当触发反爬时,系统会在后台的专有阻塞线程池上通过独立包装的单线程 runtime 驱动进程内 V8 浏览器内核直接抓取。
|
||||
**限制 Tokio 线程数:**
|
||||
```bash
|
||||
PORT=8000 TOKIO_WORKER_THREADS=1 ./astroresearch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 极致内存与体积优化部署 (Ultra-Low Memory & Size Optimization)
|
||||
|
||||
对于运行在低配/低内存服务器(如 1核512M 或 1核1G 实例)的环境,系统内置了可选的编译与运行时优化策略。
|
||||
|
||||
> [!NOTE]
|
||||
> 极致内存与体积优化编译配置(`release-min`)和“进程内集成模式 (In-Process Feature)”在**技术上可以完全兼容并共同启用**,但它们在**优化目标(指标)上是相互抵消(矛盾)的**。
|
||||
> 如果启用了进程内 V8 特性,C++ 静态链接库本身占用的 80MB+ 空间将无法被剔除,导致无法达成极致轻量化(~8.3MB)的体积指标;且 V8 运行时堆内存也会带来额外的物理内存开销。因此,为追求极致低资源消耗,建议在低配服务器上采用**“模式 A:外部命令行模式”**。
|
||||
>
|
||||
> 如果你执意要在**进程内浏览器集成下尽可能对其体积和依赖进行优化**,可以组合使用 `--profile` 与 `--features` 参数进行编译和运行:
|
||||
> ```bash
|
||||
> # 编译并打包优化后的进程内单二进制文件:
|
||||
> cargo build --profile release-min --features obscura-inprocess
|
||||
>
|
||||
> # 编译并直接运行:
|
||||
> cargo run --profile release-min --features obscura-inprocess
|
||||
> ```
|
||||
|
||||
### 优化指标对比:
|
||||
* **二进制执行文件大小**:由 `17.0 MB` 压缩至 **`8.3 MB`**(缩减约 51%)。
|
||||
* **启动物理常驻内存 (RSS)**:由 `34.8 MB` 降至 **`32.9 MB`**(得益于词典加载后的容量自动收缩)。
|
||||
* **虚拟内存 (VSZ)**:由 `1.27 GB` 降至 **`302 MB`**(缩减约 76%)。
|
||||
* **数据段内存 (VmData)**:由 `60.1 MB` 降至 **`26.5 MB`**(缩减约 55%)。
|
||||
|
||||
### 部署优化步骤:
|
||||
|
||||
1. **使用优化 Profile 进行编译**:
|
||||
在项目根目录下,使用内置的 `release-min` 编译配置:
|
||||
```bash
|
||||
cargo build --profile release-min
|
||||
```
|
||||
编译完成后的执行文件位于 `target/release-min/astroresearch`。该配置开启了 LTO(链接时优化)、剥离了调试符号,并在生成时进行了大小优化。
|
||||
|
||||
2. **限制运行时异步线程数**:
|
||||
默认情况下,异步运行时 Tokio 会根据系统的 CPU 核心数(例如 16 核)创建对应数量的 Worker 线程,这会带来很多虚拟/物理内存浪费。启动服务时,可通过注入 `TOKIO_WORKER_THREADS=1` 环境变量限制线程池大小:
|
||||
```bash
|
||||
PORT=8000 TOKIO_WORKER_THREADS=1 ./astroresearch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 环境变量配置 (Environment Variables)
|
||||
## 5. 环境变量
|
||||
|
||||
| 变量名 | 必需 | 默认值 | 说明 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `DATABASE_URL` | 否 | `sqlite://library/astro_research.db` | SQLite 数据库连接 URL |
|
||||
| `ADS_API_KEY` | 是 | - | NASA ADS API 访问 Token |
|
||||
| `LLM_API_KEY` | 是 | - | 大语言模型 API Key |
|
||||
| `LLM_API_BASE` | 否 | `https://api.openai.com/v1` | 大语言模型 API 基础地址 |
|
||||
| `LLM_MODEL` | 否 | `gpt-4o-mini` | 翻译大模型名称 |
|
||||
| `EMBEDDING_API_KEY` | 否 | 默认与 `LLM_API_KEY` 一致 | 向量模型 API Key |
|
||||
| `EMBEDDING_API_BASE`| 否 | 默认与 `LLM_API_BASE` 一致 | 向量模型 API 基础地址 |
|
||||
| `EMBEDDING_MODEL` | 否 | `text-embedding-3-small` | 向量模型名称 |
|
||||
| `QINIU_AK` | 否 | - | 七牛云 Access Key |
|
||||
| `QINIU_SK` | 否 | - | 七牛云 Secret Key |
|
||||
| `QINIU_BUCKET` | 否 | - | 七牛云存储空间名 |
|
||||
| `QINIU_DOMAIN` | 否 | - | 七牛云外链 CDN 域名 |
|
||||
| `MINERU_API_URL` | 否 | - | MinerU PDF 解析远程 API 地址 |
|
||||
| `MINERU_API_KEY` | 否 | - | MinerU API Token |
|
||||
| `LIBRARY_DIR` | 否 | `./library` | 本地文献馆藏根目录 |
|
||||
| `PORT` | 否 | `8000` | 后端服务监听端口 |
|
||||
| `DATABASE_URL` | 否 | `sqlite:///app/library/astro_research.db` | SQLite 连接 URL |
|
||||
| `ADS_API_KEY` | 是 | - | NASA ADS API Token |
|
||||
| `LLM_API_KEY` | 是 | - | LLM API Key |
|
||||
| `LLM_API_BASE` | 否 | `https://api.openai.com/v1` | LLM API 地址 |
|
||||
| `LLM_MODEL` | 否 | `gpt-4o-mini` | 对话模型 |
|
||||
| `EMBEDDING_API_KEY` | 否 | 同 `LLM_API_KEY` | Embedding API Key |
|
||||
| `EMBEDDING_API_BASE` | 否 | 同 `LLM_API_BASE` | Embedding API 地址 |
|
||||
| `EMBEDDING_MODEL` | 否 | `text-embedding-3-small` | Embedding 模型 |
|
||||
| `LIBRARY_DIR` | 否 | `/app/library` | 文献馆藏根目录 |
|
||||
| `SKILLS_DIR` | 否 | `/app/skills` | Agent 技能目录 |
|
||||
| `LOG_DIR` | 否 | `/app/logs` | 日志目录 |
|
||||
| `LOG_FORMAT` | 否 | `json` | 日志格式 (`plain` / `json`) |
|
||||
| `LOG_OUTPUTS` | 否 | `stdout` | 日志输出 (`stdout` / `file`) |
|
||||
| `PORT` | 否 | `8000` | 监听端口 |
|
||||
| `AGENT_MAX_STEPS` | 否 | `8` | Agent 最大步数 |
|
||||
| `AGENT_TOOL_TIMEOUT_SECS` | 否 | `120` | 工具超时 (秒) |
|
||||
| `QINIU_AK` / `QINIU_SK` | 否 | - | 七牛云存储凭证 |
|
||||
| `MINERU_API_URL` | 否 | - | MinerU PDF 解析 API |
|
||||
|
||||
---
|
||||
|
||||
## 7. 健康检查与维护 (Health Check)
|
||||
|
||||
部署后可定期运行健康检查工具排查馆藏一致性问题:
|
||||
## 6. 健康检查与维护
|
||||
|
||||
**Docker 健康检查(Mode A):**
|
||||
```bash
|
||||
# 只读扫描(不修改任何数据)
|
||||
docker ps --filter “health=healthy” --filter “name=astroresearch”
|
||||
```
|
||||
|
||||
Mode B (distroless) 无内置 healthcheck,可在编排层配置:
|
||||
```yaml
|
||||
# docker-compose 或 k8s
|
||||
healthcheck:
|
||||
test: [“CMD”, “curl”, “-f”, “http://localhost:8000/”]
|
||||
```
|
||||
|
||||
**源码部署健康检查:**
|
||||
```bash
|
||||
# 只读扫描
|
||||
./health_check
|
||||
|
||||
# 自动修复(清理损坏文件、重置无效路径)
|
||||
# 自动修复
|
||||
./health_check -- --fix
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user