Files
claude-code/src/skills/bundled/__tests__/ultracode.test.ts
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

92 lines
3.5 KiB
TypeScript
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.
import { afterEach, describe, expect, test } from 'bun:test'
import type { PromptCommand } from '../../../types/command.js'
import { clearBundledSkills, getBundledSkills } from '../../bundledSkills.js'
import { registerUltracodeSkill } from '../ultracode.js'
// Command is a union; source/getPromptForCommand only exist on the prompt
// variant. Narrow via type assertion once we've confirmed type === 'prompt'.
function asPrompt(c: { type: string }): PromptCommand {
return c as unknown as PromptCommand
}
// bundledSkills is a process-global registry (per CLAUDE.md mock/state rules,
// module-level singletons leak across test files in one bun test process).
// Clear after each test so `ultracode` never leaks into other suites that
// enumerate registered skills (e.g. skill-search prefetch discovery).
afterEach(() => {
clearBundledSkills()
})
describe('registerUltracodeSkill', () => {
test('registers a user-invocable prompt command named ultracode', () => {
clearBundledSkills()
registerUltracodeSkill()
const skills = getBundledSkills()
const ultracode = skills.find(s => s.name === 'ultracode')
expect(ultracode).toBeDefined()
expect(ultracode!.type).toBe('prompt')
expect(ultracode!.userInvocable).toBe(true)
expect(ultracode!.whenToUse).toBeTruthy()
expect(ultracode!.description).toContain('workflow')
const promptCmd = asPrompt(ultracode!)
expect(promptCmd.source).toBe('bundled')
})
test('getPromptForCommand injects the orchestration playbook with key sections', async () => {
clearBundledSkills()
registerUltracodeSkill()
const ultracode = getBundledSkills().find(s => s.name === 'ultracode')!
const blocks = await asPrompt(ultracode).getPromptForCommand(
'',
{} as never,
)
expect(blocks).toHaveLength(1)
expect(blocks[0]!.type).toBe('text')
const text = (blocks[0] as { type: 'text'; text: string }).text
expect(text).toContain('编排原语')
expect(text).toContain('parallel')
expect(text).toContain('pipeline')
expect(text).toContain('resumeFromRunId')
expect(text).toContain('AgentAdapterRegistry')
expect(text).toContain('确定性约束')
// 脚本执行模型约束(非 ESM / 禁 import / 禁 TS / 单 export / 顶层 return
expect(text).toContain('脚本编写约束')
expect(text).toContain('不转译 TS')
expect(text).toContain('禁 `import`')
})
test('appends user-provided args to the prompt when given', async () => {
clearBundledSkills()
registerUltracodeSkill()
const ultracode = getBundledSkills().find(s => s.name === 'ultracode')!
const blocks = await asPrompt(ultracode).getPromptForCommand(
'迁移 auth 模块',
{} as never,
)
const text = (blocks[0] as { type: 'text'; text: string }).text
expect(text.endsWith('迁移 auth 模块\n')).toBe(true)
expect(text).toContain('用户输入')
})
test('is not gated behind USER_TYPE — registers with no env set', () => {
// No USER_TYPE env is configured in this test process. If the skill were
// ant-gated (like stuck.ts), it would not appear here.
const previousUserType = process.env.USER_TYPE
delete process.env.USER_TYPE
clearBundledSkills()
registerUltracodeSkill()
const skills = getBundledSkills()
expect(skills.some(s => s.name === 'ultracode')).toBe(true)
// Restore so we never mutate the process env for other test files.
if (previousUserType === undefined) delete process.env.USER_TYPE
else process.env.USER_TYPE = previousUserType
})
})