mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 22:05:50 +00:00
将 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>
125 lines
3.7 KiB
TypeScript
125 lines
3.7 KiB
TypeScript
/**
|
||
* registry 多后端路由演示(mock adapter,无需 API key)。
|
||
*
|
||
* 两个 adapter:strong(被 researcher 路由命中)+ fast(默认)。
|
||
* 脚本里 agent({agentType:'researcher'}) → strong,其余 → fast。
|
||
* 证明 agent 后端可通过 AgentAdapterRegistry 插拔 + 路由,引擎不关心实现。
|
||
*
|
||
* 用法:bun run packages/workflow-engine/examples/registry-demo.ts
|
||
*/
|
||
import { tmpdir } from 'node:os'
|
||
import { join } from 'node:path'
|
||
import {
|
||
AgentAdapterRegistry,
|
||
createFileJournalStore,
|
||
createHostHandle,
|
||
runWorkflow,
|
||
type AgentAdapter,
|
||
type AgentRunParams,
|
||
type AgentRunResult,
|
||
type WorkflowPorts,
|
||
} from '@claude-code-best/workflow-engine'
|
||
|
||
const strongAdapter: AgentAdapter = {
|
||
id: 'strong',
|
||
capabilities: { structuredOutput: true, tools: true },
|
||
async run(p: AgentRunParams): Promise<AgentRunResult> {
|
||
return {
|
||
kind: 'ok',
|
||
output: `[strong] ← ${p.prompt}`,
|
||
usage: { outputTokens: 1 },
|
||
}
|
||
},
|
||
}
|
||
|
||
const fastAdapter: AgentAdapter = {
|
||
id: 'fast',
|
||
capabilities: { structuredOutput: false },
|
||
async run(p: AgentRunParams): Promise<AgentRunResult> {
|
||
return {
|
||
kind: 'ok',
|
||
output: `[fast] ← ${p.prompt}`,
|
||
usage: { outputTokens: 1 },
|
||
}
|
||
},
|
||
}
|
||
|
||
const registry = new AgentAdapterRegistry()
|
||
.register(strongAdapter)
|
||
.register(fastAdapter)
|
||
.route({ kind: 'agentType', agentType: 'researcher', adapter: 'strong' })
|
||
.default('fast')
|
||
|
||
const SCRIPT = `
|
||
export const meta = { name: 'registry-demo', description: 'multi-adapter routing' }
|
||
phase('Route')
|
||
const research = await agent('深度调研任务', { agentType: 'researcher', label: 'research' })
|
||
const quick = await agent('快速小任务', { label: 'quick' })
|
||
return { research, quick }
|
||
`
|
||
|
||
function makePorts(runsDir: string): WorkflowPorts {
|
||
return {
|
||
// registry 优先,agentRunner 仅作形状占位(不会被调到)
|
||
agentRunner: { runAgentToResult: async () => ({ kind: 'dead' }) },
|
||
agentAdapterRegistry: registry,
|
||
progressEmitter: {
|
||
emit: e => {
|
||
if (e.type === 'phase_started') console.log(`\n━ phase: ${e.phase}`)
|
||
else if (e.type === 'agent_done') {
|
||
const out =
|
||
e.result.kind === 'ok'
|
||
? String(e.result.output)
|
||
: `[${e.result.kind}]`
|
||
console.log(` ✓ ${e.label} → ${out}`)
|
||
}
|
||
},
|
||
},
|
||
taskRegistrar: {
|
||
register: () => ({
|
||
runId: 'demo',
|
||
signal: new AbortController().signal,
|
||
}),
|
||
complete() {},
|
||
fail() {},
|
||
kill() {},
|
||
pendingAction: () => null,
|
||
},
|
||
journalStore: createFileJournalStore(runsDir),
|
||
permissionGate: { isAborted: () => false },
|
||
logger: { debug: () => {}, event: () => {} },
|
||
hostFactory: () => ({
|
||
handle: createHostHandle(null),
|
||
cwd: process.cwd(),
|
||
budgetTotal: null,
|
||
}),
|
||
}
|
||
}
|
||
|
||
if (import.meta.main) {
|
||
await registry.initializeAll()
|
||
try {
|
||
const result = await runWorkflow({
|
||
script: SCRIPT,
|
||
runId: `demo-${Date.now()}`,
|
||
ports: makePorts(join(tmpdir(), 'wf-registry-demo')),
|
||
host: createHostHandle(null),
|
||
signal: new AbortController().signal,
|
||
cwd: process.cwd(),
|
||
budgetTotal: null,
|
||
})
|
||
console.log(`\n■ ${result.status}`)
|
||
if (result.status === 'completed') {
|
||
const ret = result.returnValue as { research: string; quick: string }
|
||
console.log(
|
||
`research(agentType:researcher) → ${ret.research.startsWith('[strong]') ? 'strong adapter ✓' : '??'}`,
|
||
)
|
||
console.log(
|
||
`quick(默认) → ${ret.quick.startsWith('[fast]') ? 'fast adapter ✓' : '??'}`,
|
||
)
|
||
}
|
||
} finally {
|
||
await registry.disposeAll()
|
||
}
|
||
}
|