mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-09-18 15:42:26 +02:00
feat: manage task process lifetimes and preserve turn history
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 依赖与代理 | `go.mod` 直接依赖 `github.com/cloudwego/eino`、`eino-ext/.../openai`;`go.mod` 注释与 `scripts/bootstrap-go.sh` 指导 **GOPROXY**(如 `https://goproxy.cn,direct`)。 |
|
||||
| 依赖与代理 | `go.mod` 直接依赖 `github.com/cloudwego/eino`、`eino-ext/.../openai`;`go.mod` 注释指导 **GOPROXY**(如 `https://goproxy.cn,direct`)。 |
|
||||
| 配置 | `config.yaml` → `agent.max_iterations` 为全局 ReAct 上限(主/子代理统一);`multi_agent`:`enabled`、`robot_use_multi_agent`、`sub_agents`(含可选 `bind_role`)、`eino_skills`、`eino_middleware` 等;结构体见 `internal/config/config.go`。 |
|
||||
| Markdown 子代理 / 主代理 | 在 `agents_dir` 下放 `*.md`。**子代理**:供 Deep `task` 与 `supervisor` `transfer`。**主代理(按模式分离)**:`orchestrator.md`(或 `kind: orchestrator` 的**单个**其他 .md)→ **Deep**;固定名 `orchestrator-plan-execute.md` → **plan_execute**;固定名 `orchestrator-supervisor.md` → **supervisor**。正文优先于 YAML:`multi_agent.orchestrator_instruction`、`orchestrator_instruction_plan_execute`、`orchestrator_instruction_supervisor`;plan_execute / supervisor **不会**回退到 Deep 的 `orchestrator_instruction`。皆空时 plan_execute / supervisor 使用代码内置默认提示。管理:**Agents → Agent管理**;API:`/api/multi-agent/markdown-agents*`。 |
|
||||
| MCP 桥 | `internal/einomcp`:`ToolsFromDefinitions` + 会话 ID 持有者,执行走 `Agent.ExecuteMCPToolForConversation`。 |
|
||||
|
||||
@@ -103,15 +103,7 @@ docs/en-US/
|
||||
- `docs/zh-CN/README.md`
|
||||
- `docs/en-US/README.md`
|
||||
|
||||
提交文档变更前运行:
|
||||
|
||||
```bash
|
||||
python3 scripts/check-docs.py
|
||||
```
|
||||
|
||||
该检查会验证本地链接、代码块闭合、中英文文件名对齐、语言导航覆盖率,以及根 README 中的 Go 版本是否与 `go.mod` 一致。版本化示例应尽量从 `go.mod`、`config.example.yaml` 等权威文件派生,避免手工同步。
|
||||
|
||||
当文档、`go.mod` 或检查脚本变更时,GitHub Actions 中的 `Documentation` 工作流会自动运行同一条命令。
|
||||
提交文档变更前,请检查本地链接、代码块闭合、中英文文件名对齐、语言导航覆盖率,以及根 README 中的 Go 版本是否与 `go.mod` 一致。版本化示例应尽量从 `go.mod`、`config.example.yaml` 等权威文件派生,避免手工同步。
|
||||
|
||||
## Review 关注点
|
||||
|
||||
|
||||
@@ -221,3 +221,62 @@ PY
|
||||
|
||||
- 外部 MCP 的远端 server 内部如何采集输出不由 CyberStrikeAI 控制;CyberStrikeAI 会在结果进入本系统后统一兜底、限并发和熔断。
|
||||
- 超长工具输出会在截断前写入本地 `tmp/reduction/.../trunc/<id>`(或 `reduction_root_dir`),bounded result 中包含可 `read_file` 的绝对路径。
|
||||
|
||||
## 本轮任务的进程生命周期
|
||||
|
||||
每轮任务有独立 `runId`,本地进程与异步 MCP worker 都通过 context 保留归属。取消 context、工具返回、SSE 断线不等于资源已回收。
|
||||
|
||||
- `exec ... &` 与 Eino 后台执行立即返回,但仍属于本轮任务;无任务归属的后台启动被拒绝。前台工具退出时清理遗留子进程,跨工具调用运行的任务应使用显式后台入口。
|
||||
- 完成、失败、超时收尾、用户停止、服务正常关闭都会封闭启动入口、取消 worker、终止进程并等待回收。“中断并继续”保留本轮归属。
|
||||
- Unix 首先给进程组 3 秒退出宽限期,再强制终止并验证;内核隔离、守护进程退出与 worker 收尾各有有界等待。清理期间仍占用本轮任务;失败保留 `cleanup_failed`、进程组/worker ID,每 15 秒巡检重试。
|
||||
- 工具 worker 的登记与任务关闭互斥;即使 MCP 使用 `WithoutCancel`,任务也会等待其退出。旧轮次的延迟回调无法接管新轮次的进程或提交新 worker。
|
||||
|
||||
### 操作系统隔离和崩溃回收
|
||||
|
||||
| 平台 | 实现 | 崩溃回收与限制 |
|
||||
| --- | --- | --- |
|
||||
| Linux,已配置 cgroup v2 | 每轮创建独立 cgroup,使用 `clone3(CLONE_INTO_CGROUP)` 在创建时归组;配置进程数、内存、CPU 限额 | 独立守护进程在主程序管道 EOF 后写 `cgroup.kill`,验证 `populated=0`;启动时独占委派根并回收遗留任务组。`setsid` 不会脱离 cgroup |
|
||||
| Windows | 每轮 Job Object,守护进程先加入 Job;任务通过原子父进程属性继承 Job,避免启动后再分配的竞态 | `KILL_ON_JOB_CLOSE`、主动 `TerminateJobObject` 和活跃进程数验证;进程数、内存与可选 CPU 限额 |
|
||||
| macOS/未配置 cgroup 的 Unix | 独立进程组和守护进程,子进程在登记确认前通过管道等待 | 主程序被强杀后,管道 EOF 触发整组清理;无法限制主动 `setsid` 逃逸,不能作为强隔离部署 |
|
||||
|
||||
守护进程自身异常退出时,仍存活的宿主会终止相应资源;IPC 有超时。Linux 的遗留回收依据独占目录与随机任务标识,不重放历史 PID。
|
||||
|
||||
这属于生命周期隔离,不是针对同权限恶意代码的完整安全沙箱。能够修改 cgroup、取得外部父进程句柄或杀死宿主与守护进程的程序仍需要容器/不同操作系统身份及权限策略限制。Linux 容器部署应使用 init 回收孤儿进程。`required` 模式在缺少相应内核能力或权限时拒绝运行,不会悄悄降级。
|
||||
|
||||
### 配置与上线
|
||||
|
||||
默认 `auto` 在 Windows 使用 Job Object;Unix 未指定 cgroup 根时使用进程组守护。Linux 生产部署需配置独立的 systemd 服务,设置 `Delegate=cpu memory pids`、`KillMode=control-group` 和 `Restart=on-failure`,将以下严格隔离配置 **合并到现有配置**:
|
||||
|
||||
```yaml
|
||||
security:
|
||||
process_isolation:
|
||||
mode: required
|
||||
cgroup_root: auto
|
||||
max_processes: 256
|
||||
memory_max_bytes: 2147483648
|
||||
cpu_quota_micros: 200000
|
||||
```
|
||||
|
||||
需要 Linux 5.14+、cgroup v2、允许 `clone3`,以及 `Delegate=cpu memory pids`。`cgroup_root: auto` 用于 systemd 的独立委派单元;也可指定受控的绝对路径,禁止使用整台主机的层级根。配置改变需要重启。Windows 留空 `cgroup_root`,可以使用 `required`;macOS 的 `required` 会明确报错。
|
||||
|
||||
服务启动时会真正创建并回收一个探测进程,验证权限和内核支持;也可在不启动 HTTP/MCP 服务的情况下单独运行:
|
||||
|
||||
```sh
|
||||
./cyberstrike-ai --check-process-isolation -config config.yaml
|
||||
```
|
||||
|
||||
输出 `cgroup_v2`、`windows_job` 或 `process_group_watchdog`。运行/历史任务 API 的 `isolationBackend` 字段提供每轮实际采用的后端。systemd 的 `KillMode=control-group` 和失败重启为整个服务额外兜底;它与每任务 cgroup 配合使用。
|
||||
|
||||
### 远端 MCP 取消
|
||||
|
||||
普通 MCP 取消通知不提供远端退出回执。适配器可实现 `ExternalCancellationConfirmer`,使用服务端任务状态、租约或取消回执确认结束。没有确认时,不再标成“已终止”:工具记录持久化为 `orphaned` 并说明原因;本地 worker 和进程清理完成后,任务历史保留 `cleanup_unconfirmed`,响应明确提示远端状态待确认。它不是自动重试成功,也不是远端零残留保证。仍未返回的本地 worker 则保持 `cleanup_failed` 并继续追踪。
|
||||
|
||||
### 回归验证
|
||||
|
||||
```sh
|
||||
go test -race ./internal/processguard ./internal/mcp ./internal/handler ./internal/security
|
||||
```
|
||||
|
||||
`Process isolation` GitHub Actions 工作流还会执行 Linux cgroup 集成测试,命令直接保存在 `.github/workflows/process-isolation.yml` 中。该测试使用一次性、私有 cgroup 命名空间的 Docker 容器,不挂载宿主 cgroup 或 Docker socket。测试覆盖宿主 `SIGKILL`、启动登记竞态、`setsid`、资源限额、启动时遗留回收、worker 取消和远端未确认状态。Windows Job Object 测试已纳入跨平台 CI;交叉编译不等于 Windows 实机测试。
|
||||
|
||||
参考:[Go os/exec](https://pkg.go.dev/os/exec)、[Linux cgroup v2](https://cdn.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html)、[Windows Job Objects](https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects)、[MCP cancellation](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation)。
|
||||
|
||||
Reference in New Issue
Block a user