Files
claude-code/packages/workflow-engine/examples/research-report/research-report.workflow.mjs
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

125 lines
4.9 KiB
JavaScript
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.
// research-report.workflow.mjs
// 技术研究报告 workflow。
// 由 run.ts 通过 @claude-code-best/workflow-engine 的 runWorkflow() 直接执行——
// 不经 Workflow 工具、不经核心 runAgent。脚本内的 agent / parallel / pipeline /
// phase / log / args 均为引擎运行时注入的全局(见 src/engine/script.ts 的沙箱)。
//
// 编排多角度并行调研parallel 屏障)→ 逐条深挖pipeline 无屏障)→ 综合成报告。
export const meta = {
name: 'research-report',
description:
'Multi-angle tech research → deep-read → synthesize into a Markdown report',
whenToUse: '调研一个技术主题:从多个角度并行研究、逐条深挖、综合成结构化报告',
phases: [
{ title: 'Research', detail: '多角度并行调研parallel 屏障)' },
{ title: 'DeepRead', detail: '逐条深挖pipeline 无屏障)' },
{ title: 'Synthesize', detail: '综合成 Markdown 报告' },
],
}
// agent(schema) 让子 agent 返回「校验对象」而非纯文本。
const ANGLE_SCHEMA = {
type: 'object',
required: ['angle', 'findings'],
properties: {
angle: { type: 'string', description: '本次调研的角度名' },
findings: {
type: 'array',
items: {
type: 'object',
required: ['claim', 'evidence'],
properties: {
claim: { type: 'string', description: '一句话结论' },
evidence: { type: 'string', description: '依据/来源/理由' },
},
},
},
},
}
const DEEP_SCHEMA = {
type: 'object',
required: ['claim', 'analysis', 'confidence'],
properties: {
claim: { type: 'string' },
analysis: { type: 'string', description: '机理/前提/边界/反例' },
confidence: { type: 'string', enum: ['high', 'medium', 'low'] },
},
}
// ---- 输入(由 run.ts 通过 args 透传)----
const topic = args.topic
if (typeof topic !== 'string' || topic.length === 0) {
throw new Error('research-report 需要 args.topic研究主题字符串')
}
const angles =
Array.isArray(args.angles) && args.angles.length > 0
? args.angles
: ['核心概念与原理', '主流方案与对比', '工程实践与权衡', '生态与趋势']
// ---- Phase 1多角度并行调研。parallel = 屏障,等所有角度完成后才继续。----
phase('Research')
log(`主题「${topic}」:${angles.length} 个角度并行调研中`)
const researched = await parallel(
angles.map(
a => () =>
agent(
`你是资深技术研究分析师。针对技术主题「${topic}」,从「${a}」角度调研,给出该角度下 2-4 条最关键的技术发现,每条须附依据。`,
{ label: `research:${a}`, phase: 'Research', schema: ANGLE_SCHEMA },
),
),
)
// parallel 返回 (object|null)[]skipped/dead 的角度为 null过滤后展平
const allFindings = researched
.filter(Boolean)
.flatMap(r => r.findings.map(f => ({ ...f, angle: r.angle })))
log(`收集到 ${allFindings.length} 条发现,进入深挖`)
if (allFindings.length === 0) {
return {
topic,
report: '(所有角度调研均失败,无可用发现)',
anglesCovered: 0,
findingsDeepened: 0,
}
}
// ---- Phase 2逐条深挖。pipeline = 无屏障,每条发现独立跑完所有 stage互不等待。----
phase('DeepRead')
const deepened = await pipeline(
allFindings,
f =>
agent(
`针对以下技术发现,深入分析其机理、成立前提、适用边界与可能的反例:\n结论:${f.claim}\n依据:${f.evidence}\n角度:${f.angle}`,
{ label: `deep:${f.angle}`, phase: 'DeepRead', schema: DEEP_SCHEMA },
),
// 第二个 stage按置信度标注交叉价值演示多 stage pipeline 链式传递)。
// stage-1 若 dead 返回 null这里显式守卫——避免对 null 取属性(否则被 pipeline
// 的 per-item catch 吞掉、整条静默丢失)。
d =>
d
? {
...d,
crossCutting:
d.confidence === 'high' ? '可作为报告主干' : '需谨慎引用或佐证',
}
: null,
)
const deepFindings = deepened.filter(Boolean)
log(`深挖完成 ${deepFindings.length}/${allFindings.length}`)
// ---- Phase 3综合成 Markdown 报告(无 schema → 返回纯文本)----
phase('Synthesize')
const report = await agent(
`你是首席技术分析师。基于以下经深挖的技术发现,综合一份结构化研究报告(纯 Markdown 叙述)。\n要求:含摘要、分角度分析、关键结论、落地建议与风险;用自然语言陈述每条发现并标注 confidence。\n禁止:在报告中粘贴 JSON 代码块或原样引用下方输入数据。\n\n主题:${topic}\n\n深度发现JSON仅供你理解不要原样输出\n${JSON.stringify(deepFindings)}`,
{ label: 'synthesize', phase: 'Synthesize', maxTokens: 8192 },
)
return {
topic,
report,
anglesCovered: angles.length,
findingsDeepened: deepFindings.length,
}