mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 22:35:51 +00:00
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:
76
packages/workflow-engine/src/__tests__/context.test.ts
Normal file
76
packages/workflow-engine/src/__tests__/context.test.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { expect, test } from 'bun:test'
|
||||
import { createBufferingEmitter } from '../progress/events.js'
|
||||
import {
|
||||
createEngineContext,
|
||||
createSharedResources,
|
||||
} from '../engine/context.js'
|
||||
import { WorkflowError } from '../engine/errors.js'
|
||||
import { createHostHandle, type WorkflowPorts } from '../ports.js'
|
||||
|
||||
function mockPorts(): WorkflowPorts {
|
||||
return {
|
||||
agentRunner: { runAgentToResult: async () => ({ kind: 'dead' }) },
|
||||
progressEmitter: { emit: () => {} },
|
||||
taskRegistrar: {
|
||||
register: () => ({ runId: 'r', signal: new AbortController().signal }),
|
||||
complete: () => {},
|
||||
fail: () => {},
|
||||
kill: () => {},
|
||||
pendingAction: () => null,
|
||||
},
|
||||
journalStore: {
|
||||
read: async () => [],
|
||||
append: async () => {},
|
||||
truncate: async () => {},
|
||||
},
|
||||
permissionGate: { isAborted: () => false },
|
||||
logger: { debug: () => {}, event: () => {} },
|
||||
hostFactory: () => ({
|
||||
handle: createHostHandle(null),
|
||||
cwd: '/tmp',
|
||||
budgetTotal: null,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
test('createSharedResources 初始化预算与计数', () => {
|
||||
const r = createSharedResources(100)
|
||||
expect(r.budget.total).toBe(100)
|
||||
expect(r.agentCountBox.value).toBe(0)
|
||||
expect(r.depth).toBe(0)
|
||||
})
|
||||
|
||||
test('createEngineContext 复制 journal 并重置游标', () => {
|
||||
const journal = [
|
||||
{
|
||||
key: 'k',
|
||||
seq: 0,
|
||||
result: { kind: 'ok' as const, output: 'x', usage: { outputTokens: 1 } },
|
||||
},
|
||||
]
|
||||
const ctx = createEngineContext({
|
||||
ports: mockPorts(),
|
||||
host: createHostHandle(null),
|
||||
signal: new AbortController().signal,
|
||||
runId: 'r1',
|
||||
workflowName: 'w',
|
||||
cwd: '/tmp',
|
||||
budgetTotal: null,
|
||||
journal,
|
||||
})
|
||||
expect(ctx.journal).toHaveLength(1)
|
||||
expect(ctx.journalIndex).toBe(0)
|
||||
expect(ctx.journalInvalidated).toBe(false)
|
||||
})
|
||||
|
||||
test('createBufferingEmitter 收集事件', () => {
|
||||
const { emitter, events } = createBufferingEmitter()
|
||||
emitter.emit({ type: 'log', runId: 'r', message: 'hi' })
|
||||
expect(events).toHaveLength(1)
|
||||
})
|
||||
|
||||
test('WorkflowError 可识别', () => {
|
||||
const e = new WorkflowError('boom')
|
||||
expect(e).toBeInstanceOf(Error)
|
||||
expect(e.message).toBe('boom')
|
||||
})
|
||||
Reference in New Issue
Block a user