auto-sync: 2026-05-16 23:27:52

This commit is contained in:
cfdaily
2026-05-16 23:27:52 +08:00
parent b3e21c5c44
commit ae41a58d2f
2 changed files with 27 additions and 4 deletions
+2 -2
View File
@@ -59,7 +59,7 @@ sanguo-moziplus-v2
```
~/.sanguo_projects/sanguo_moziplus_v2/
├── projects/
│ ├── registry.db ← 全局注册表(项目列表+元数据
│ ├── _registry.yaml ← 全局注册表(YAML,人可读,Git 版本管理
│ ├── sanguo_quant_live/
│ │ ├── blackboard.db ← per-project 黑板
│ │ ├── config/
@@ -390,7 +390,7 @@ P1 部署前逐项验证:
- [ ] 项目创建、git init、远程配置完成
- [ ] PM2 配置正确,`pm2 start` 成功
- [ ] 全局注册表 `registry.db` 自动创建
- [ ] 全局注册表 `_registry.yaml` 可读写,项目列表正确
- [ ] CLI `admin.py project create` 创建项目成功
- [ ] per-project `blackboard.db` 自动创建且 schema 正确(含 reviews/experiences/comments.comment_type
- [ ] CLI `blackboard.py read/claim/output/comment/decide/observe/create/review` 全部可用
+25 -2
View File
@@ -240,10 +240,33 @@ def dispatch(task, action_type, project_config):
- Full Agent`subprocess.Popen`(非阻塞),不等返回,下次 tick 检查产出
- Subagent`sessions_spawn`Gateway API),等返回
### 4.3 ActiveAgentCounter(课题11
### 4.3 线程模型:纯 asyncio 单线程
整个 Daemon 运行在单个 asyncio event loop 中(与 FastAPI 共享)。
**关键设计决策**Full Agent spawn 不用 `subprocess.Popen`(同步,会短暂阻塞 event loop),改用 `asyncio.create_subprocess_exec`(异步非阻塞)。这样 API 请求处理、SSE 推送、Daemon tick 三者互不阻塞。
```python
class ActiveAgentCounter:
async def spawn_full_agent(agent_id: str, message: str, new_session: bool = False) -> str:
"""异步非阻塞 spawn,全程 asyncio"""
session_id = str(uuid.uuid4())
cmd = ["openclaw", "agent", "--agent", agent_id,
"--session-id", session_id, "--message", message, "--json"]
proc = await asyncio.create_subprocess_exec(
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
# 不 await proc.wait(),让子进程独立运行
# 下次 tick 通过产出物检查完成状态
_register_session(agent_id, session_id, proc.pid)
return session_id
```
**Subagent spawn** 通过 OpenClaw Gateway 内部 API`sessions_spawn`),天然异步。
### 4.4 ActiveAgentCounter(课题11
纯 asyncio 实现(`asyncio.Semaphore`),与线程模型一致:
"""异步计数器,控制并发"""
def __init__(self, max_global=5, max_per_agent=1):
self._global = asyncio.Semaphore(max_global)