#!/usr/bin/env node import assert from 'assert'; import fs from 'fs'; import os from 'os'; import path from 'path'; import { ToolRegistry } from './src/core/tool-registry.js'; import { createReadFileTool } from './src/tools/read-file.js'; import { createWorkflowRunTool } from './src/tools/workflow-run.js'; function createTempProject() { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'vlcode-workflow-run-tool-')); fs.mkdirSync(path.join(dir, '.vl-code'), { recursive: true }); fs.writeFileSync(path.join(dir, '.vl-code', 'workspace.json'), '{}'); return dir; } async function main() { const workDir = createTempProject(); const workflowPath = path.join(workDir, 'tool-workflow.json'); const inputPath = path.join(workDir, 'tool-input.txt'); fs.writeFileSync(inputPath, 'workflow-run-tool-ok', 'utf8'); fs.writeFileSync(workflowPath, JSON.stringify({ version: '3.16', name: 'WorkflowRunToolStep', steps: [ { id: 'Tool_010_ReadFile', input: { file_path: '="tool-input.txt"' }, out: { '$content': '=_result' }, next: 'Stop_End', }, { id: 'Stop_End' }, ], }, null, 2), 'utf8'); const events = []; let doneResolve; let doneReject; const donePromise = new Promise((resolve, reject) => { doneResolve = resolve; doneReject = reject; }); const toolRegistry = new ToolRegistry(); toolRegistry.register('ReadFile', createReadFileTool({ workDir })); const config = { workDir, model: 'claude-opus-4-6', llmProvider: 'cli', toolRegistry, _broadcast: (event) => { events.push(event); if (event.type === 'wf_done') doneResolve(event); if (event.type === 'wf_error') doneReject(new Error(event.error || 'workflow error')); }, _recordWorkflowEvent: (event) => events.push({ ...event, recorded: true }), _onWorkflowStart: () => {}, _onWorkflowDone: () => {}, _onWorkflowError: (_, msg) => doneReject(new Error(msg)), _onWorkflowNodeStatus: () => {}, _setActiveExecutor: () => {}, }; const workflowTool = createWorkflowRunTool(config); const response = await workflowTool.execute({ mode: 'local', workflow_path: 'tool-workflow.json' }); const parsed = JSON.parse(response); assert.equal(parsed.status, 'started'); await Promise.race([ donePromise, new Promise((_, reject) => setTimeout(() => reject(new Error('workflow tool timed out')), 5000)), ]); assert(events.some((event) => event.type === 'wf_tool_start' && event.name === 'ReadFile'), 'missing wf_tool_start'); assert(events.some((event) => event.type === 'wf_tool_message' && event.name === 'ReadFile'), 'missing wf_tool_message'); assert(events.some((event) => event.type === 'wf_tool_done' && event.name === 'ReadFile'), 'missing wf_tool_done'); assert(events.some((event) => event.type === 'wf_done'), 'missing wf_done'); fs.rmSync(workDir, { recursive: true, force: true }); console.log('\n── WorkflowRun Tool Step ──'); console.log('PASS test-workflow-run-tool-step.js'); process.exit(0); } main().catch((err) => { console.error(err); process.exit(1); });