Files
claude-code/docs/features/workflow-scripts.md
claude-code-best d236880bc3 feat(workflow): add workflow engine, /workflows panel, /ultracode skill
将 feat/sdk-backend 分支中 workflow 相关的 20 个 commit 压缩为单 commit:

- 工作流引擎核心:phase / agent / parallel / pipeline 编排原语(packages/workflow-engine/)
- /workflows 面板:三区焦点布局(顶部 run tabs + 左侧 phase 侧栏 + 右侧 agent 列表)
- /ultracode skill:多 agent workflow 编排入口
- 进度存储 / journal / notification 系统
- WorkflowService 生命周期管理 + SentryErrorBoundary
- 脚本沙箱:禁用 dynamic import()、JSON args 防御性归一化
- journal 与 named-workflow 路径统一在 projectRoot
- 错误处理:parallel/pipeline hooks 错误日志、failure routing、semaphore abort
- workflow 工具升级为 core 工具 + PascalCase 命名

Co-Authored-By: glm-5.1 <zai-org@claude-code-best.win>
2026-06-13 20:07:18 +08:00

184 lines
11 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.
# WORKFLOW_SCRIPTS — 确定性多 agent 工作流编排
> Feature Flag`FEATURE_WORKFLOW_SCRIPTS=1`
> 引擎包:[`@claude-code-best/workflow-engine`](../../packages/workflow-engine/)(确定性 JS 脚本编排,零核心层运行时依赖)
> 集成层:[`src/workflow/`](../../src/workflow/)
## 一、功能概述
WORKFLOW_SCRIPTS 让 Claude Code 用**确定性 JavaScript 脚本**编排多个子 agent可分解/并行、多视角置信、规模超单上下文、可 resume/可审计。
- **编排原语**`agent` / `parallel` / `pipeline` / `phase` / `log` / `workflow`(见引擎包)。
- **确定性**:脚本在受限沙箱内执行,禁用 `Date.now()` / `Math.random()` / 无参 `new Date()`,保证 journal 可重放。
- **深度后端**:单一 `claude-code` AgentAdapter 接入当前会话体系provider / model / agentType / 工具workflow 内的 `agent()` 调用真实子 agent。
- **监控面板**`/workflows` 双栏实时面板(见 §六)。
- **编排手册**`/ultracode` 注入编排工作法(见 §七)。
> 历史说明:早期版本为 YAML/JSON DSL + 全 Stub 实现(`WorkflowDetailDialog` 等),已全量重写为引擎驱动的 JS 方案。
## 二、实现架构
```
.claude/workflows/<name>.ts Workflow 工具name/script/scriptPath/args/resumeFromRunId
│ │
▼ ▼
namedWorkflowCommands.ts src/workflow/wiring.ts (createWorkflowToolCore)
/<name> 命令发现) │
WorkflowService门面launch/kill/subscribe/listRuns/listNamed
┌────────────────┼─────────────────┐
▼ ▼ ▼
ports.ts registry.ts progress/
(端口聚合) AgentAdapterRegistry bus + store
│ │
▼ ▼
hostHandle.ts backends/claudeCodeBackend.ts
(不透明 host (深度读会话体系,跑真实 agent
@claude-code-best/workflow-engine
runWorkflow / hooks / journal / budget / 并发信号量)
```
### 2.1 模块清单
| 层 | 文件 | 职责 |
|----|------|------|
| 引擎 | `packages/workflow-engine/src/` | 确定性脚本沙箱 + hooks + journal + budget + 信号量;导出 `createWorkflowTool` |
| 工具装配 | `src/workflow/wiring.ts` | `createWorkflowToolCore()` —— 用 `WorkflowService.ports` 组装 `Workflow` 工具 |
| 服务门面 | `src/workflow/service.ts` | `WorkflowService` 单例:`launch` / `kill` / `subscribe` / `listRuns` / `listNamed` / `getWorkflowService()` |
| 端口 | `src/workflow/ports.ts` | `createWorkflowPorts()` 聚合所有端口agentRunner/registry/progress/task/journal/permission/logger/hostFactory |
| 后端注册 | `src/workflow/registry.ts` | `buildRegistry()` 注册 `claude-code` 后端并设为默认 |
| 深度后端 | `src/workflow/backends/claudeCodeBackend.ts` | AgentAdapter`agentType`/`model` 解析会话体系,跑真实子 agent结构化输出 |
| Host 句柄 | `src/workflow/hostHandle.ts` | `buildHostBundle()` 不透明包装 `toolUseContext`/`canUseTool`/`parentMessage` |
| 进度总线 | `src/workflow/progress/bus.ts` | 基于 Set 的进度事件发射 |
| 进度状态 | `src/workflow/progress/store.ts` | reducer`agentId` 精确关联 `agent_done`(修并发竞态) |
| 监控面板 | `src/workflow/panel/*.tsx` | `/workflows` 双栏 UI见 §六) |
| 命名命令 | `src/workflow/namedWorkflowCommands.ts` | 扫描 `.claude/workflows/` 生成 `/<name>` 命令 |
| 权限请求 | `src/workflow/WorkflowPermissionRequest.tsx` | workflow 启动权限 UI |
### 2.2 注册点
| 位置 | 内容 |
|------|------|
| `src/tools.ts:152-153,254` | `createWorkflowToolCore()` 动态加载并注册 `Workflow` 工具feature-gated |
| `src/commands.ts:95-97,392` | `/workflows` 命令local-jsx加载 `panelCall.js` |
| `src/skills/bundled/ultracode.ts` + `index.ts` | `/ultracode` 知识 skill`registerBundledSkill` |
## 三、编排原语
workflow 脚本内可用的钩子(语义详见引擎包 `engine/hooks.ts`
| 原语 | 语义 |
|------|------|
| `agent(prompt, opts?)` | 派发一个子 agent返回最终文本`opts.schema`结构化对象。opts`model` / `agentType` / `label` / `phase` / `schema` |
| `parallel([() => …])` | 并发跑 thunk 数组,**barrier**(等全部完成);单项抛错 → 该项 `null`,其余保留 |
| `pipeline(items, s1, s2, …)` | 每个 item 链式过各 stage**item 间无 barrier**stage 内顺序;单 item 某 stage 抛错 → 该 item `null` |
| `phase(title)` | 标记阶段(面板按此分组展示) |
| `log(msg)` | 进度日志(面板展示,无状态变更) |
| `workflow(name \| { scriptPath }, args?)` | 嵌套一层子 workflow仅允许一层 |
**硬限**:单次 `parallel`/`pipeline``MAX_ITEMS_PER_CALL`4096单 workflow 总 agent ≤ `MAX_TOTAL_AGENTS`1000并发 cap = `min(16, cores - 2)`
## 四、编写 workflow
脚本置于 `.claude/workflows/<name>.js|.mjs`(也接受 `.ts`,但**引擎不转译 TS**,含类型注解会报语法错——推荐 `.js`/`.mjs`),自动成为 `/<name>` 命令。
```js
// .claude/workflows/review-changes.js
export const meta = {
name: 'review-changes',
description: '按维度审查改动并对抗式验证',
phases: [{ title: 'Review' }, { title: 'Verify' }],
}
const DIMENSIONS = [
{ key: 'bugs', prompt: '找正确性 bug' },
{ key: 'perf', prompt: '找性能问题' },
]
const results = await pipeline(
DIMENSIONS,
d => agent(d.prompt, { label: `review:${d.key}`, phase: 'Review' }),
review => parallel(
(review.findings || []).map(f => () =>
agent(`对抗式验证:${f.title}`, { phase: 'Verify' })
)
)
)
return results.flat().filter(Boolean)
```
**脚本执行约束**(引擎执行模型,违反直接报错):
脚本是 `new AsyncFunction` 的**函数体**,不是 ESM 模块:
- **禁 `import`**`agent`/`parallel`/`pipeline`/`phase`/`log`/`workflow``args`/`budget` 是注入的形参,直接用。
- **禁 TS 语法**:不要类型注解(`x: number`)、`interface``enum``as`、泛型。引擎不转译,即便文件是 `.ts` 也会原样报语法错。
- **只允许一处 `export const meta = {...}`**(引擎正则提取剥离);不要 `export` 其他、不要 `export default`
- **顶层 `return` 返回结果**。
**确定性约束**(违反则 resume 失效):
-`Date.now()` / `Math.random()` / 无参 `new Date()`(沙箱强制抛错)。需时间戳/随机种子经 `args` 传入。
- `export const meta = { ... }` 必须是**纯字面量**(无变量、函数调用、模板插值)——加载期求值,否则抛 `ScriptError`
## 五、Workflow 工具
模型通过 `Workflow` 工具启动 workflowinput schema 见引擎包 `tool/schema.ts`
| 字段 | 说明 |
|------|------|
| `script` | 内联脚本字符串 |
| `name` | 命名 workflow 名(对应 `.claude/workflows/<name>` |
| `scriptPath` | 脚本文件路径 |
| `args` | 透传给脚本的 `args`(任意 JSON 值) |
| `resumeFromRunId` | 从既有 runId 重放(已完成 `agent()` 秒回,发散点后现场重跑) |
## 六、监控面板:`/workflows`
`/workflows` 打开三区焦点面板local-jsx全屏
- **顶部 tabs**:每个 run 一个 tab状态圆点 + workflow 名 + `#runId短码`);同名脚本多次跑会多个 tab。
- **左 phase 侧栏**`All` + 合并 meta 声明的 phase未启动 `○` pending 灰)与实际 phase`●` running / `✓` done选中即决定右栏筛选。
- **右 agent 列表**:按选中 phase 过滤;状态色 + 行尾文字(`running` / `object` / `text` / `dead`)。
**键位**`Tab`/`Shift+Tab` 切 run · `←`/`→` 切左右焦点列phases ↔ agents· `↑`/`↓` 列内移动 · `r` resume · `x` kill · `n` 新建提示 · `q`/`Esc` 退出。
**视觉**:无内框,左右一条竖线分隔;聚焦列标题橙粗;选中/光标行铺橙底(`backgroundColor`),文字色不变。
进度按引擎 `agentId` 精确关联 `agent_done`(解决并发 LIFO 竞态。pending phase 来自 `run_started` 事件携带的 `meta.phases`store 落地 `declaredPhases`,面板 `mergePhases` 合并。`useSyncExternalStore` 订阅 `WorkflowService`,稳定快照,无变更不重渲染。
## 七、`/ultracode` skill
`/ultracode``src/skills/bundled/ultracode.ts`)注入多 agent workflow 编排工作法:何时用 / 何时不用、编排原语速查、质量模式库adversarial-verify / judge-panel / loop-until-dry / multi-modal-sweep / completeness-critic、确定性约束、后端路由、resume/budget、文件与命令。
**纯知识 prompt skill**:零运行时副作用,不改主循环、不切换行为开关。调用即把手册注入上下文。
## 八、resume / journal / budget
- **journal**:每次 run 记录到 `.claude/workflow-runs/<runId>/journal.jsonl``resumeFromRunId` 重放 journal已完成 `agent()` 秒回缓存结果。
- **budget**`budget.total` 为 token 硬顶(默认 `null` = 无限);`budget.spent()` / `budget.remaining()` 读实时消耗;耗尽后再发 `agent()` 抛错。
- **并发**:引擎 `Semaphore``min(16, cores - 2)`)限制同时运行的 agent 数。
- **错误**:脚本语法/meta 错 → `parseScript` 即时返错不进后台agent 抛错 → `kind:'dead'``null`workflow 继续(`parallel`/`pipeline` 容错);`WorkflowAbortedError``killed`
## 九、文件索引
| 文件 | 职责 |
|------|------|
| `src/workflow/wiring.ts` | `Workflow` 工具装配(`createWorkflowToolCore` |
| `src/workflow/service.ts` | `WorkflowService` 门面 |
| `src/workflow/ports.ts` | 端口聚合(`createWorkflowPorts` |
| `src/workflow/registry.ts` | `AgentAdapterRegistry` + 默认后端 |
| `src/workflow/backends/claudeCodeBackend.ts` | 深度后端 AgentAdapter |
| `src/workflow/hostHandle.ts` | 不透明 host 句柄(`buildHostBundle` |
| `src/workflow/progress/bus.ts` | 进度事件总线 |
| `src/workflow/progress/store.ts` | 进度 reducer`agentId` 关联) |
| `src/workflow/panel/*.tsx` | `/workflows` 双栏面板 |
| `src/workflow/namedWorkflowCommands.ts` | `/<name>` 命令发现 |
| `src/workflow/WorkflowPermissionRequest.tsx` | 启动权限 UI |
| `src/skills/bundled/ultracode.ts` | `/ultracode` 知识 skill |
| `src/tools.ts:152-153,254` | 工具注册 |
| `src/commands.ts:95-97,392` | `/workflows` 命令注册 |
| `packages/workflow-engine/` | 引擎包hooks / journal / budget / 并发) |