mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 14:25:51 +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:
@@ -1,5 +1,7 @@
|
||||
import {
|
||||
createWorkflowTool,
|
||||
workflowInputSchema,
|
||||
WORKFLOW_TOOL_NAME,
|
||||
type WorkflowToolDescriptor,
|
||||
} from '@claude-code-best/workflow-engine'
|
||||
import { buildTool, type Tool } from '../Tool.js'
|
||||
@@ -8,25 +10,37 @@ import { getWorkflowService } from './service.js'
|
||||
/**
|
||||
* 把引擎自包含描述符适配为 buildTool 兼容的 Tool。
|
||||
* 描述符统一走 service 单例(共享 ports/registry/store)。
|
||||
*
|
||||
* ports 解析延迟到首次实际方法调用(lazy):tools.ts 在模块加载阶段(feature-gated)
|
||||
* 调用 createWorkflowToolCore(),若此时立即解析 ports 会触发 service 实例化,
|
||||
* 进而调用 getProjectRoot 等模块级副作用——这在 bootstrap 完成前可能拿到错误路径。
|
||||
* Tool 对象本身的单例由 createWorkflowToolCore 的 cached 保证(PermissionRequest
|
||||
* 按引用匹配),ports 单例由 getWorkflowService 保证。
|
||||
*/
|
||||
function buildWorkflowTool(): Tool {
|
||||
const { ports } = getWorkflowService()
|
||||
const descriptor: WorkflowToolDescriptor = createWorkflowTool(ports)
|
||||
let cachedDescriptor: WorkflowToolDescriptor | null = null
|
||||
const descriptor = (): WorkflowToolDescriptor => {
|
||||
if (!cachedDescriptor) {
|
||||
const { ports } = getWorkflowService()
|
||||
cachedDescriptor = createWorkflowTool(ports)
|
||||
}
|
||||
return cachedDescriptor
|
||||
}
|
||||
return buildTool({
|
||||
name: descriptor.name,
|
||||
name: WORKFLOW_TOOL_NAME,
|
||||
maxResultSizeChars: 50_000,
|
||||
inputSchema: descriptor.inputSchema,
|
||||
isEnabled: () => descriptor.isEnabled(),
|
||||
isReadOnly: input => descriptor.isReadOnly(input),
|
||||
inputSchema: workflowInputSchema,
|
||||
isEnabled: () => descriptor().isEnabled(),
|
||||
isReadOnly: input => descriptor().isReadOnly(input),
|
||||
isConcurrencySafe: () => true,
|
||||
async description() {
|
||||
return descriptor.description()
|
||||
return descriptor().description()
|
||||
},
|
||||
async prompt() {
|
||||
return descriptor.prompt()
|
||||
return descriptor().prompt()
|
||||
},
|
||||
async call(input, context, canUseTool, parentMessage, onProgress) {
|
||||
const result = await descriptor.call(
|
||||
const result = await descriptor().call(
|
||||
input,
|
||||
context,
|
||||
canUseTool,
|
||||
@@ -35,9 +49,9 @@ function buildWorkflowTool(): Tool {
|
||||
)
|
||||
return { data: result.data }
|
||||
},
|
||||
renderToolUseMessage: input => descriptor.renderToolUseMessage(input),
|
||||
renderToolUseMessage: input => descriptor().renderToolUseMessage(input),
|
||||
mapToolResultToToolResultBlockParam: (data, toolUseId) =>
|
||||
descriptor.mapToolResultToToolResultBlockParam(data, toolUseId),
|
||||
descriptor().mapToolResultToToolResultBlockParam(data, toolUseId),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user