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>
This commit is contained in:
claude-code-best
2026-06-13 20:07:18 +08:00
parent 91cffe16e2
commit d236880bc3
106 changed files with 16127 additions and 834 deletions

View File

@@ -0,0 +1,75 @@
import { expect, test } from 'bun:test'
import type { AgentProgress, RunProgress } from '../progress/store.js'
import {
STATUS_DOT,
RUN_STATUS_COLOR,
PHASE_MARK,
PHASE_COLOR,
agentVisual,
} from '../panel/status.js'
test('STATUS_DOT / RUN_STATUS_COLOR 覆盖四种 run 状态且为非空字符', () => {
const statuses: RunProgress['status'][] = [
'running',
'completed',
'failed',
'killed',
]
for (const s of statuses) {
expect(STATUS_DOT[s].length).toBeGreaterThan(0)
expect(RUN_STATUS_COLOR[s]).toBeTruthy()
}
expect(STATUS_DOT.running).toBe('●')
expect(STATUS_DOT.completed).toBe('✓')
expect(STATUS_DOT.failed).toBe('✗')
expect(STATUS_DOT.killed).toBe('■')
})
test('PHASE_MARK / PHASE_COLOR 覆盖 running/done/pending', () => {
expect(PHASE_MARK.running).toBe('●')
expect(PHASE_MARK.done).toBe('✓')
expect(PHASE_MARK.pending).toBe('○')
expect(PHASE_COLOR.pending).toBe('subtle')
})
test('agentVisualrunning → ● warning running', () => {
const a: AgentProgress = { id: 1, status: 'running' }
expect(agentVisual(a)).toEqual({
mark: '●',
color: 'warning',
suffix: 'running',
})
})
test('agentVisualdone·object → ✓ success object', () => {
const a: AgentProgress = {
id: 1,
status: 'done',
resultKind: 'ok',
outputShape: 'object',
}
expect(agentVisual(a)).toEqual({
mark: '✓',
color: 'success',
suffix: 'object',
})
})
test('agentVisualdone·text → ✓ success text', () => {
const a: AgentProgress = {
id: 1,
status: 'done',
resultKind: 'ok',
outputShape: 'text',
}
expect(agentVisual(a)).toEqual({
mark: '✓',
color: 'success',
suffix: 'text',
})
})
test('agentVisualdead → ✗ error dead', () => {
const a: AgentProgress = { id: 1, status: 'done', resultKind: 'dead' }
expect(agentVisual(a)).toEqual({ mark: '✗', color: 'error', suffix: 'dead' })
})