mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-19 14:55:50 +00:00
feat(workflow): 复刻 ultracode 手册并修复 worktree/inline/opt-in 三处缺口
围绕 ultracode skill 审查 agent 系统一致性后:
- ultracode.ts: 用系统提示版完整 Workflow 编排手册替换中文精简版
- HIGH#1 isolation:'worktree': claudeCodeBackend.run() 用 createAgentWorktree +
runWithCwdOverride 包裹 runAgent + finally 清理实现真正的 cwd 隔离;slug 用
sha256(runId:agentId) 派生以匹配 cleanupStaleAgentWorktrees 清理正则
(修 runId 为 w+base36 非 UUID 导致的泄漏盲区);worktree.ts 注释同步修正
- HIGH#2 inline 持久化: 新增 persistInlineScript,WorkflowTool + service 两条
inline 路径对称持久化到 .claude/workflow-runs/<runId>/script.js,返回可复用
scriptPath(闭环 inline→编辑→scriptPath 重提迭代循环)
- HIGH#3 opt-in 分工: ultracode/WorkflowTool/effort 注明 session reminder 由
harness 注入,repo 内无 ultracode 信号,保持 feature('WORKFLOW_SCRIPTS') +
isEnabled 两层 gate,不自造注入
- 测试: 新增 persistInline.test.ts;扩展 claudeCodeBackend(isolation 4 用例)/
WorkflowTool(inline)/service(scriptPath)/ultracode(harness)
含配套 workflow engine/panel 完善与 run-state-persistence design doc。
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,12 +3,15 @@ import type { AgentProgress, RunProgress } from '../progress/store.js'
|
||||
import {
|
||||
STATUS_DOT,
|
||||
RUN_STATUS_COLOR,
|
||||
RUN_STATUS_TEXT,
|
||||
PHASE_MARK,
|
||||
PHASE_COLOR,
|
||||
agentVisual,
|
||||
formatTokenCount,
|
||||
agentMetaText,
|
||||
} from '../panel/status.js'
|
||||
|
||||
test('STATUS_DOT / RUN_STATUS_COLOR 覆盖四种 run 状态且为非空字符', () => {
|
||||
test('STATUS_DOT / RUN_STATUS_COLOR / RUN_STATUS_TEXT 覆盖四种 run 状态', () => {
|
||||
const statuses: RunProgress['status'][] = [
|
||||
'running',
|
||||
'completed',
|
||||
@@ -18,11 +21,14 @@ test('STATUS_DOT / RUN_STATUS_COLOR 覆盖四种 run 状态且为非空字符',
|
||||
for (const s of statuses) {
|
||||
expect(STATUS_DOT[s].length).toBeGreaterThan(0)
|
||||
expect(RUN_STATUS_COLOR[s]).toBeTruthy()
|
||||
expect(RUN_STATUS_TEXT[s].length).toBeGreaterThan(0)
|
||||
}
|
||||
expect(STATUS_DOT.running).toBe('●')
|
||||
expect(STATUS_DOT.completed).toBe('✓')
|
||||
expect(STATUS_DOT.failed).toBe('✗')
|
||||
expect(STATUS_DOT.killed).toBe('■')
|
||||
expect(RUN_STATUS_TEXT.completed).toBe('done')
|
||||
expect(RUN_STATUS_TEXT.running).toBe('running')
|
||||
})
|
||||
|
||||
test('PHASE_MARK / PHASE_COLOR 覆盖 running/done/pending', () => {
|
||||
@@ -32,44 +38,51 @@ test('PHASE_MARK / PHASE_COLOR 覆盖 running/done/pending', () => {
|
||||
expect(PHASE_COLOR.pending).toBe('subtle')
|
||||
})
|
||||
|
||||
test('agentVisual:running → ● warning running', () => {
|
||||
test('agentVisual:running → ● warning', () => {
|
||||
const a: AgentProgress = { id: 1, status: 'running' }
|
||||
expect(agentVisual(a)).toEqual({
|
||||
mark: '●',
|
||||
color: 'warning',
|
||||
suffix: 'running',
|
||||
})
|
||||
expect(agentVisual(a)).toEqual({ mark: '●', color: 'warning' })
|
||||
})
|
||||
|
||||
test('agentVisual:done·object → ✓ success object', () => {
|
||||
test('agentVisual:done·ok → ✓ success(不再带 outputShape 后缀)', () => {
|
||||
const a: AgentProgress = {
|
||||
id: 1,
|
||||
status: 'done',
|
||||
resultKind: 'ok',
|
||||
outputShape: 'object',
|
||||
}
|
||||
expect(agentVisual(a)).toEqual({
|
||||
mark: '✓',
|
||||
color: 'success',
|
||||
suffix: 'object',
|
||||
})
|
||||
expect(agentVisual(a)).toEqual({ mark: '✓', color: 'success' })
|
||||
})
|
||||
|
||||
test('agentVisual:done·text → ✓ success text', () => {
|
||||
test('agentVisual:dead → ✗ error', () => {
|
||||
const a: AgentProgress = { id: 1, status: 'done', resultKind: 'dead' }
|
||||
expect(agentVisual(a)).toEqual({ mark: '✗', color: 'error' })
|
||||
})
|
||||
|
||||
test('formatTokenCount:<1000 原值,≥1000 保留 1 位小数 + k', () => {
|
||||
expect(formatTokenCount(undefined)).toBe('0')
|
||||
expect(formatTokenCount(0)).toBe('0')
|
||||
expect(formatTokenCount(42)).toBe('42')
|
||||
expect(formatTokenCount(1000)).toBe('1.0k')
|
||||
expect(formatTokenCount(22900)).toBe('22.9k')
|
||||
})
|
||||
|
||||
test('agentMetaText:model · Nk tok · N tool', () => {
|
||||
const a: AgentProgress = {
|
||||
id: 1,
|
||||
status: 'done',
|
||||
resultKind: 'ok',
|
||||
outputShape: 'text',
|
||||
model: 'glm-5.2',
|
||||
tokenCount: 22900,
|
||||
toolCount: 1,
|
||||
}
|
||||
expect(agentVisual(a)).toEqual({
|
||||
mark: '✓',
|
||||
color: 'success',
|
||||
suffix: 'text',
|
||||
})
|
||||
expect(agentMetaText(a)).toBe('glm-5.2 · 22.9k tok · 1 tool')
|
||||
})
|
||||
|
||||
test('agentVisual:dead → ✗ error dead', () => {
|
||||
const a: AgentProgress = { id: 1, status: 'done', resultKind: 'dead' }
|
||||
expect(agentVisual(a)).toEqual({ mark: '✗', color: 'error', suffix: 'dead' })
|
||||
test('agentMetaText:无 model 时省略前段', () => {
|
||||
const a: AgentProgress = {
|
||||
id: 1,
|
||||
status: 'running',
|
||||
tokenCount: 500,
|
||||
toolCount: 2,
|
||||
}
|
||||
expect(agentMetaText(a)).toBe('500 tok · 2 tool')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user