133 lines
8.4 KiB
Markdown
133 lines
8.4 KiB
Markdown
# pipeline_service
|
||
|
||
产线执行引擎 —— 任务调度、步骤执行、人工任务交互、LLM 桥接。
|
||
|
||
## 功能
|
||
|
||
- **任务执行**:DAG 步骤调度与状态机
|
||
- **人工任务**:审批/输入等待与交互
|
||
- **LLM 桥接**:统一 LLM 调用接口
|
||
- **Agent Loop**:AI Agent 多轮任务执行
|
||
- **意图分类**:自然语言意图识别
|
||
- **产物管理**:步骤输入输出存储
|
||
|
||
## 数据表
|
||
|
||
| 表 | 说明 |
|
||
|---|------|
|
||
| pipeline_tasks | 任务实例 |
|
||
| pipeline_task_steps | 步骤执行记录 |
|
||
| pipeline_artifacts | 步骤产物 |
|
||
| pipeline_human_tasks | 人工任务 |
|
||
| pipeline_step_types | 步骤类型注册 |
|
||
| pipeline_session_settings | 会话设置(多 tab 项目上下文) |
|
||
| pipeline_conversations | 平台会话消息(回放缓存;2026-09-10 归籍本模块——唯一写入方 agent_loop_v2._save_turn,此前是无 models 定义的孤儿表) |
|
||
| pipeline_agent_instances | 角色 agent 实例注册(项目×角色→稳定实例 id;唯一写入方 agent_instance.py;m0002 建表未进 models,2026-09-10 归籍) |
|
||
| pipeline_agent_settings | 用户 agent 偏好(每用户一行 uk_user:默认模型/当前项目指针;写入方 agent_loop_v2、set_agent_model.dspy、workspace.py;2026-09-10 归籍) |
|
||
| pipeline_project_agents | 项目角色 agent 配置(驾驶舱 v1 start_agent 链路;v2 已走 pipeline_agent_instances,保留至 v1 链路删除决议;2026-09-10 归籍) |
|
||
|
||
## 安装
|
||
|
||
```bash
|
||
cd pkgs/pipeline-service && pip install .
|
||
```
|
||
|
||
## 核心模块
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `executor.py` | 任务/步骤调度引擎 |
|
||
| `storage.py` | 数据库读写 |
|
||
| `llm_bridge.py` | LLM API 调用 |
|
||
| `agent_loop.py` | AI Agent 多轮执行 |
|
||
| `human.py` | 人工任务处理 |
|
||
| `intent_classifier.py` | 意图识别 |
|
||
| `state.py` | 状态机 |
|
||
| `step_registry.py` | 步骤类型注册表 |
|
||
| `agent_loop_v2.py` | Agent Executor v2(会话 agent 执行引擎) |
|
||
| `workspace.py` | 项目/通用会话工作空间目录管理 |
|
||
| `sdlc_ability.py` | SDLC 产线能力包(工具定义 + handler) |
|
||
| `skill_live.py` | 技能实时发布/管理(publish_skill_live + manage_skill_live 多租户隔离) |
|
||
| `bg_jobs.py` | run_command 后台任务(状态文件化 .bg/,跨 worker 可见) |
|
||
| `subagents.py` | 后台并行子 agent 委派(.sub/,spawn/steer/stop/result) |
|
||
| `diagram_gate.py` | 文档配图形态硬门禁(2026-09-15):交付文档/标书章节中的图必须 invoke_model t2i/i2i 真图,确定性检测 mermaid/plantuml/ASCII 伪图;deliver 双路径拦截 + pipeline-bidding write/review_chapter 复用;豁免=文中如实标注「配图缺失:平台无可用文生图模型」 |
|
||
|
||
## 通用会话产线隔离(2026-09-05,7 层纵深防御)
|
||
|
||
规范:通用会话(generic=True,agent_chat_generic.dspy)= 纯通用 agent,
|
||
不挂任何产线工具/技能/角色/记忆,不得看到或操作任何产线的项目。
|
||
|
||
隔离层(缺一层即泄漏,详见技能 cockpit-agent-patterns):
|
||
|
||
1. **工具注册表**:ToolRegistry 每 executor 独立实例(禁全局单例,防跨会话残留)
|
||
2. **默认产线回退**:generic 会话 pipeline_id 空不回退 DEFAULT_ABILITY_ID
|
||
3. **产线能力包**:_execute_ability_tool 对 generic 直接拒绝
|
||
4. **工具 schema**:load_agent_config(pipeline-core)generic 时剔除 project/shell 类工具
|
||
5. **执行层兜底**:_dispatch_sdlc_tool 对 generic 拒绝项目管理工具(别名归一后拦截)
|
||
6. **工作空间**:generic 会话文件根 = `_general/{user_id}` 专属目录(generic_workspace_dir),
|
||
_resolve_ws_path 越界保护圈死;run_command 剔除(shell 无法圈禁);
|
||
resolve_upload_dir(pipeline-core)generic=True 上传落同一专属目录
|
||
7. **历史回放**:_load_history / _t_session_search 对 generic 只读写
|
||
`pipeline_id='' OR IS NULL` 的自身历史(与存库端 store_pl='' 对称),
|
||
禁止按 created_by 全量回放(会带出用户各产线对话中的项目信息)
|
||
|
||
## Hermes 能力对齐:写入侧 + 运行时侧(2026-09-10)
|
||
|
||
四个 handler 在 `agent_loop_v2.py`,工具定义在 pipeline-core `agent_config.py`
|
||
(GENERAL_TOOLS)。全部经测试机服务端直调 31/31 + HTTP 端到端 5/5 实测通过。
|
||
|
||
### 1. memory 工具(持久记忆写入,`_t_memory`)
|
||
- 写入门禁(代码强制,多机构多用户):scope 白名单 user/project/pipeline,
|
||
global/org 种子域禁写;org_id/user_id 强制注入会话真实身份(忽略 LLM 传值);
|
||
无 user_id(无人值守)拒写;remove 只能删本人条目(org+user 双过滤)。
|
||
- 记忆注入改可见性版(`_build_system_prompt` 传 org_id/user_id → store.visible_to
|
||
过滤),修了旧「按域叠加」会带出他机构归属记忆的隐患。
|
||
|
||
### 2. manage_skill 工具(技能增改删,`skill_live.manage_skill_live`)
|
||
- 五动作 create/patch/write_file/remove_file/delete,隔离全在 skill_live:
|
||
只落本租户 orgs/{org}(org≠0)或 users/{uid}(org 0 降级/个人);
|
||
- **fork-on-write**:改 global 原版先整目录继承拷贝到本租户再改(同名覆盖仅本租户
|
||
生效);**校验通过才 fork**(旧「先 fork 后校验」失败会留副本遮蔽原版,已修);
|
||
- org+user 双副本同步改(user 遮蔽 org,防改了被遮蔽那份);产线/角色/项目层拒改;
|
||
delete 只删本租户副本(global 删不到,删后重新可见);子文件限四目录 + realpath 双检。
|
||
|
||
### 3. run_command background + process 工具(`bg_jobs.py`,`_t_run_command`/`_t_process`)
|
||
- 状态文件化 workspace/.bg/{job_id}/(meta.json+output.log),跨 worker/进程可见;
|
||
- 沙箱档位与前台一致(generic 强制 strict bwrap,无 bwrap 拒绝,绝不降级裸 shell);
|
||
- start_new_session 独立进程组 + 超时 SIGTERM 整组(不留孤儿);心跳 stale 判活。
|
||
|
||
### 4. delegate_subtask background + subagent 工具(`subagents.py`,`_t_delegate_subtask`/`_t_subagent`)
|
||
- 后台并行(同 workspace 上限 3),状态文件化 .sub/{sid}/;深度限制 1(子禁再委派);
|
||
- 子会话 session_isolation='none':不读父历史、不写 pipeline_conversations(防污染回放);
|
||
- steer/stop 走文件传递,子 agent 每轮 tool-loop 边界 `subagents.heartbeat` 消费;
|
||
result.txt 流式落盘,stop/崩溃即部分结果(绝不空手)。
|
||
|
||
## 第二批 Hermes 能力对齐:五级工具作用域 + patch_file + 原生视觉(2026-09-10)
|
||
|
||
### 五级作用域工具解析接线(`_resolve_tool_scopes`,解析逻辑在 core `tool_sources.py`)
|
||
- `_init_components` 第 8 步:调 core 五级解析(global/org/pipeline/role/project),
|
||
registry 重建为解析后工具集;capability 工具(技能 frontmatter 声明)合成
|
||
ToolDefinition 注册,执行路由 `capability_tools.exec_capability_tool`。
|
||
- **执行层门禁**(`_execute_tool` 第 0 步):`_allowed_tools` 非 None 时,作用域外
|
||
工具名(幻觉/越权)直接拒绝并回可行动提示(列出本会话可用工具)。解析失败
|
||
降级 `_allowed_tools=None` 不拦截(回退旧行为,不阻断会话)。
|
||
- 隔离走查修复(capability 两层语义):global 层 all/ 概念技能的 capability 声明
|
||
**不作为注入依据**(只当映射手册),否则 generic 会话拿到 ~70 个产线工具击穿
|
||
七层隔离;注入只认 org/pipeline/role/project/user 层技能的声明。
|
||
|
||
### patch_file 工具(`_t_patch_file`)
|
||
old_string 唯一性校验(0/多次拒绝,replace_all 放行)+ 原子写 + `_resolve_ws_path`
|
||
越界防护 + UTF-8 校验(二进制拒绝)。
|
||
|
||
### 原生视觉(多模态消息链)
|
||
- `run(user_input, image_parts)`:image_parts 非空时首条用户消息构造 OpenAI 多模态
|
||
content 数组(text + image_url data URL);llm_bridge→llm_v1 端点→inference 原样透传。
|
||
- `_call_llm` 降级兜底:含图调用失败 → `_degrade_images_if_needed` 剥离图片就地改写
|
||
消息(文本 + 系统说明「如实告知用户当前模型看不了图,建议切视觉模型或 invoke_model
|
||
i2t」)重试一次——绝不假装看过图。只降级一次。
|
||
- `_estimate_tokens`/`_summarize` 兼容 list content(`_content_as_text` 归一,图片按
|
||
1000 token 估)。
|
||
- `gateway.run_message(image_paths)`:build_image_parts 构造 + 超限 notes 注入 content。
|
||
- 实测:中性文件名红蓝两图,agent 正确答「第一张红色、第二张蓝色」,degrade 0 次。
|
||
|