pipeline-service/README.md

133 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 次。