@synergenius/flow-weaver 0.20.7 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/api/command-runner.d.ts +13 -0
  2. package/dist/api/command-runner.js +217 -0
  3. package/dist/api/index.d.ts +1 -0
  4. package/dist/api/index.js +1 -0
  5. package/dist/cli/flow-weaver.mjs +24064 -38374
  6. package/dist/cli/index.js +0 -60
  7. package/dist/doc-metadata/extractors/cli-commands.js +37 -56
  8. package/dist/doc-metadata/extractors/mcp-tools.d.ts +1 -1
  9. package/dist/doc-metadata/extractors/mcp-tools.js +1 -213
  10. package/dist/doc-metadata/types.d.ts +2 -0
  11. package/dist/generated-version.d.ts +1 -1
  12. package/dist/generated-version.js +1 -1
  13. package/dist/mcp/index.d.ts +1 -5
  14. package/dist/mcp/index.js +0 -4
  15. package/dist/mcp/server.js +3 -55
  16. package/dist/mcp/types.d.ts +0 -50
  17. package/dist/mcp/types.js +1 -7
  18. package/dist/mcp/workflow-executor.js +23 -1
  19. package/dist/parser.js +5 -1
  20. package/package.json +1 -2
  21. package/dist/cli/commands/listen.d.ts +0 -16
  22. package/dist/cli/commands/listen.js +0 -39
  23. package/dist/cli/commands/tunnel.d.ts +0 -19
  24. package/dist/cli/commands/tunnel.js +0 -119
  25. package/dist/cli/commands/ui.d.ts +0 -16
  26. package/dist/cli/commands/ui.js +0 -130
  27. package/dist/cli/tunnel/dispatch.d.ts +0 -18
  28. package/dist/cli/tunnel/dispatch.js +0 -36
  29. package/dist/cli/tunnel/file-lock.d.ts +0 -9
  30. package/dist/cli/tunnel/file-lock.js +0 -36
  31. package/dist/cli/tunnel/handlers/ast-ops.d.ts +0 -10
  32. package/dist/cli/tunnel/handlers/ast-ops.js +0 -252
  33. package/dist/cli/tunnel/handlers/execution.d.ts +0 -7
  34. package/dist/cli/tunnel/handlers/execution.js +0 -89
  35. package/dist/cli/tunnel/handlers/file-ops.d.ts +0 -7
  36. package/dist/cli/tunnel/handlers/file-ops.js +0 -204
  37. package/dist/cli/tunnel/handlers/mutations.d.ts +0 -7
  38. package/dist/cli/tunnel/handlers/mutations.js +0 -285
  39. package/dist/cli/tunnel/handlers/stubs.d.ts +0 -7
  40. package/dist/cli/tunnel/handlers/stubs.js +0 -143
  41. package/dist/cli/tunnel/handlers/templates.d.ts +0 -7
  42. package/dist/cli/tunnel/handlers/templates.js +0 -123
  43. package/dist/cli/tunnel/path-resolver.d.ts +0 -17
  44. package/dist/cli/tunnel/path-resolver.js +0 -54
  45. package/dist/defaults.d.ts +0 -3
  46. package/dist/defaults.js +0 -3
  47. package/dist/mcp/editor-connection.d.ts +0 -52
  48. package/dist/mcp/editor-connection.js +0 -142
  49. package/dist/mcp/event-buffer.d.ts +0 -62
  50. package/dist/mcp/event-buffer.js +0 -150
  51. package/dist/mcp/resources.d.ts +0 -14
  52. package/dist/mcp/resources.js +0 -55
  53. package/dist/mcp/tools-editor.d.ts +0 -5
  54. package/dist/mcp/tools-editor.js +0 -283
@@ -1,36 +0,0 @@
1
- /**
2
- * File mutation lock — serializes concurrent mutations to the same file.
3
- *
4
- * Ported from flow-weaver-platform/src/services/ast-helpers.ts:54-85.
5
- * Prevents file corruption when rapid Studio mutations (e.g. dragging nodes)
6
- * trigger concurrent write operations.
7
- */
8
- import * as path from 'node:path';
9
- const fileMutationLocks = new Map();
10
- export function withFileLock(filePath, operation) {
11
- const normalizedPath = path.resolve(filePath);
12
- const existingChain = fileMutationLocks.get(normalizedPath) || Promise.resolve();
13
- let resolve;
14
- let reject;
15
- const resultPromise = new Promise((res, rej) => {
16
- resolve = res;
17
- reject = rej;
18
- });
19
- const newChain = existingChain.then(async () => {
20
- try {
21
- const result = await operation();
22
- resolve(result);
23
- }
24
- catch (error) {
25
- reject(error);
26
- }
27
- });
28
- fileMutationLocks.set(normalizedPath, newChain);
29
- newChain.finally(() => {
30
- if (fileMutationLocks.get(normalizedPath) === newChain) {
31
- fileMutationLocks.delete(normalizedPath);
32
- }
33
- });
34
- return resultPromise;
35
- }
36
- //# sourceMappingURL=file-lock.js.map
@@ -1,10 +0,0 @@
1
- /**
2
- * AST read-operation handlers for the tunnel CLI.
3
- * Ported from flow-weaver-platform/src/routes/studio-rpc.ts + src/services/ast-helpers.ts.
4
- */
5
- import type { HandlerFn } from '../dispatch.js';
6
- declare function prepareMutationResult(ast: Record<string, unknown>, wsPath: string): Record<string, unknown>;
7
- declare function getWorkflowName(params: Record<string, unknown>): string | undefined;
8
- export { prepareMutationResult, getWorkflowName };
9
- export declare const astOpsHandlers: Record<string, HandlerFn>;
10
- //# sourceMappingURL=ast-ops.d.ts.map
@@ -1,252 +0,0 @@
1
- /**
2
- * AST read-operation handlers for the tunnel CLI.
3
- * Ported from flow-weaver-platform/src/routes/studio-rpc.ts + src/services/ast-helpers.ts.
4
- */
5
- import * as fs from 'node:fs/promises';
6
- import * as path from 'node:path';
7
- import { parser, resolveNpmNodeTypes } from '../../../parser.js';
8
- import { validateWorkflow } from '../../../api/validate.js';
9
- import { resolvePath, toVirtualPath } from '../path-resolver.js';
10
- // ---------------------------------------------------------------------------
11
- // Helpers — ported from studio-rpc.ts lines 98-186
12
- // ---------------------------------------------------------------------------
13
- function ensureASTDefaults(ast) {
14
- return {
15
- ...ast,
16
- instances: ast.instances ?? [],
17
- connections: ast.connections ?? [],
18
- nodeTypes: ast.nodeTypes ?? [],
19
- };
20
- }
21
- function virtualizeASTPaths(ast, wsPath) {
22
- const result = { ...ast };
23
- // 1. sourceFile
24
- if (typeof result.sourceFile === 'string' && result.sourceFile.startsWith(wsPath)) {
25
- result.sourceFile = toVirtualPath(wsPath, result.sourceFile);
26
- }
27
- // 2. nodeTypes[].sourceLocation.file and nodeTypes[].path
28
- if (Array.isArray(result.nodeTypes)) {
29
- result.nodeTypes = result.nodeTypes.map((nt) => {
30
- const copy = { ...nt };
31
- if (copy.sourceLocation?.file?.startsWith(wsPath)) {
32
- copy.sourceLocation = { ...copy.sourceLocation, file: toVirtualPath(wsPath, copy.sourceLocation.file) };
33
- }
34
- if (typeof copy.path === 'string' && copy.path.startsWith(wsPath)) {
35
- copy.path = toVirtualPath(wsPath, copy.path);
36
- }
37
- return copy;
38
- });
39
- }
40
- // 3. instances[].sourceLocation.file
41
- if (Array.isArray(result.instances)) {
42
- result.instances = result.instances.map((inst) => {
43
- if (inst.sourceLocation?.file?.startsWith(wsPath)) {
44
- return {
45
- ...inst,
46
- sourceLocation: { ...inst.sourceLocation, file: toVirtualPath(wsPath, inst.sourceLocation.file) },
47
- };
48
- }
49
- return inst;
50
- });
51
- }
52
- return result;
53
- }
54
- function prepareMutationResult(ast, wsPath) {
55
- return virtualizeASTPaths(ensureASTDefaults(ast), wsPath);
56
- }
57
- function getWorkflowName(params) {
58
- return (params.functionName || params.workflowName || params.exportName);
59
- }
60
- // ---------------------------------------------------------------------------
61
- // Core AST operations — ported from ast-helpers.ts
62
- // ---------------------------------------------------------------------------
63
- async function loadWorkflowAST(filePath, functionName) {
64
- const parsed = parser.parse(filePath);
65
- const workflows = parsed.workflows || [];
66
- if (workflows.length === 0) {
67
- throw new Error(`No workflows found in ${filePath}`);
68
- }
69
- const target = functionName
70
- ? workflows.find((w) => w.functionName === functionName)
71
- : workflows[0];
72
- if (!target) {
73
- throw new Error(`Workflow "${functionName}" not found in ${filePath}`);
74
- }
75
- return resolveNpmNodeTypes(target, path.dirname(filePath));
76
- }
77
- async function loadAllWorkflowsAST(wsPath) {
78
- const entries = await fs.readdir(wsPath, { withFileTypes: true });
79
- const results = [];
80
- for (const entry of entries) {
81
- if (!entry.isFile() || !entry.name.endsWith('.ts'))
82
- continue;
83
- if (entry.name === 'tsconfig.json' || entry.name === 'package.json')
84
- continue;
85
- const fullPath = path.join(wsPath, entry.name);
86
- try {
87
- const parsed = parser.parse(fullPath);
88
- const workflows = parsed.workflows || [];
89
- for (const wf of workflows) {
90
- const resolved = await resolveNpmNodeTypes(wf, wsPath);
91
- results.push({ filePath: fullPath, ast: resolved });
92
- }
93
- }
94
- catch {
95
- // Skip files that fail to parse
96
- }
97
- }
98
- return results;
99
- }
100
- function parseWorkflowFromContent(content) {
101
- const parsed = parser.parseFromString(content);
102
- const workflows = parsed.workflows || [];
103
- return workflows.map((wf) => ({
104
- name: wf.name || wf.functionName,
105
- ast: wf,
106
- }));
107
- }
108
- function getDiagnostics(source) {
109
- const parsed = parser.parseFromString(source);
110
- if ((parsed.errors && parsed.errors.length > 0) || !parsed.workflows?.length) {
111
- return {
112
- valid: false,
113
- errors: (parsed.errors || []).map((e) => ({ message: typeof e === 'string' ? e : e.message || String(e) })),
114
- warnings: [],
115
- };
116
- }
117
- const allErrors = [];
118
- const allWarnings = [];
119
- for (const wf of parsed.workflows) {
120
- const result = validateWorkflow(wf);
121
- if (result.errors)
122
- allErrors.push(...result.errors);
123
- if (result.warnings)
124
- allWarnings.push(...result.warnings);
125
- }
126
- return { valid: allErrors.length === 0, errors: allErrors, warnings: allWarnings };
127
- }
128
- async function extractAllNodeTypes(wsPath) {
129
- const all = await loadAllWorkflowsAST(wsPath);
130
- const typeMap = new Map();
131
- for (const { ast } of all) {
132
- for (const nt of ast.nodeTypes || []) {
133
- if (!typeMap.has(nt.name)) {
134
- typeMap.set(nt.name, nt);
135
- }
136
- }
137
- }
138
- return Array.from(typeMap.values());
139
- }
140
- // ---------------------------------------------------------------------------
141
- // Exported handlers
142
- // ---------------------------------------------------------------------------
143
- export { prepareMutationResult, getWorkflowName };
144
- export const astOpsHandlers = {
145
- loadWorkflowAST: async (params, ctx) => {
146
- const filePath = params.filePath;
147
- if (!filePath)
148
- throw new Error('filePath is required');
149
- const functionName = getWorkflowName(params);
150
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
151
- const ast = await loadWorkflowAST(resolved, functionName);
152
- return virtualizeASTPaths(ensureASTDefaults(ast), ctx.workspaceRoot);
153
- },
154
- loadAllWorkflowsAST: async (_params, ctx) => {
155
- const all = await loadAllWorkflowsAST(ctx.workspaceRoot);
156
- return all.map(({ filePath, ast }) => ({
157
- filePath: toVirtualPath(ctx.workspaceRoot, filePath),
158
- ast: virtualizeASTPaths(ensureASTDefaults(ast), ctx.workspaceRoot),
159
- }));
160
- },
161
- parseWorkflowASTFromContent: async (params) => {
162
- const content = params.content;
163
- if (!content)
164
- throw new Error('content is required');
165
- const functionName = getWorkflowName(params);
166
- const results = parseWorkflowFromContent(content);
167
- if (functionName) {
168
- const match = results.find((r) => r.name === functionName || r.ast?.functionName === functionName);
169
- return match ? ensureASTDefaults(match.ast) : null;
170
- }
171
- return results.length > 0 ? ensureASTDefaults(results[0].ast) : null;
172
- },
173
- getAvailableWorkflowsInFile: async (params, ctx) => {
174
- const filePath = params.filePath;
175
- if (!filePath)
176
- return { availableWorkflows: [] };
177
- try {
178
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
179
- const source = await fs.readFile(resolved, 'utf-8');
180
- const results = parseWorkflowFromContent(source);
181
- return {
182
- availableWorkflows: results.map((w) => ({
183
- name: w.ast?.name || w.name,
184
- functionName: w.ast?.functionName || w.name,
185
- isExported: true,
186
- })),
187
- };
188
- }
189
- catch {
190
- return { availableWorkflows: [] };
191
- }
192
- },
193
- getDiagnostics: async (params, ctx) => {
194
- // Source resolution priority: openFiles > content > file on disk
195
- let source;
196
- const openFiles = params.openFiles;
197
- const filePath = params.filePath;
198
- if (openFiles && filePath && openFiles[filePath]) {
199
- source = openFiles[filePath];
200
- }
201
- else if (typeof params.content === 'string') {
202
- source = params.content;
203
- }
204
- else if (filePath) {
205
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
206
- source = await fs.readFile(resolved, 'utf-8');
207
- }
208
- if (!source)
209
- throw new Error('No source provided for diagnostics');
210
- const { errors, warnings } = getDiagnostics(source);
211
- // Transform to flat array for FileEditorPane
212
- const result = [];
213
- for (const e of errors) {
214
- result.push({
215
- severity: 'error',
216
- message: e.message || String(e),
217
- start: e.location ?? { line: 1, column: 0 },
218
- });
219
- }
220
- for (const w of warnings) {
221
- result.push({
222
- severity: 'warning',
223
- message: w.message || String(w),
224
- start: w.location ?? { line: 1, column: 0 },
225
- });
226
- }
227
- return result;
228
- },
229
- getNodeTypes: async (_params, ctx) => {
230
- const types = await extractAllNodeTypes(ctx.workspaceRoot);
231
- return types.map((t) => ({ name: t.name, label: t.name, nodeType: t }));
232
- },
233
- getNodeTypesBatch: async (params, ctx) => {
234
- const cursor = params.cursor || '0';
235
- const limit = params.limit || 50;
236
- const offset = parseInt(cursor, 10) || 0;
237
- const types = await extractAllNodeTypes(ctx.workspaceRoot);
238
- const all = types.map((t) => ({ name: t.name, label: t.name, nodeType: t }));
239
- const page = all.slice(offset, offset + limit);
240
- const nextCursor = offset + limit < all.length ? String(offset + limit) : null;
241
- return { types: page, cursor: nextCursor };
242
- },
243
- searchNodeTypes: async (params, ctx) => {
244
- const query = (params.query || '').toLowerCase();
245
- const types = await extractAllNodeTypes(ctx.workspaceRoot);
246
- const all = types.map((t) => ({ name: t.name, label: t.name, nodeType: t }));
247
- if (!query)
248
- return all;
249
- return all.filter((t) => t.name.toLowerCase().includes(query) || t.label.toLowerCase().includes(query));
250
- },
251
- };
252
- //# sourceMappingURL=ast-ops.js.map
@@ -1,7 +0,0 @@
1
- /**
2
- * Execution handlers for the tunnel CLI.
3
- * executeFile, compileFile, generateDiagram
4
- */
5
- import type { HandlerFn } from '../dispatch.js';
6
- export declare const executionHandlers: Record<string, HandlerFn>;
7
- //# sourceMappingURL=execution.d.ts.map
@@ -1,89 +0,0 @@
1
- /**
2
- * Execution handlers for the tunnel CLI.
3
- * executeFile, compileFile, generateDiagram
4
- */
5
- import * as fs from 'node:fs/promises';
6
- import { compileWorkflow } from '../../../api/compile.js';
7
- import { resolvePath } from '../path-resolver.js';
8
- let sourceToSVG;
9
- async function loadDiagram() {
10
- if (sourceToSVG)
11
- return sourceToSVG;
12
- try {
13
- const mod = await import('../../../diagram/index.js');
14
- sourceToSVG = mod.sourceToSVG;
15
- return sourceToSVG;
16
- }
17
- catch {
18
- return undefined;
19
- }
20
- }
21
- export const executionHandlers = {
22
- executeFile: async (params, ctx) => {
23
- const filePath = params.filePath;
24
- if (!filePath)
25
- throw new Error('filePath is required');
26
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
27
- const inputData = (params.inputData || params.input || {});
28
- try {
29
- // Dynamic import to avoid bundling issues — uses the MCP workflow executor
30
- const { executeWorkflowFromFile } = await import('../../../mcp/workflow-executor.js');
31
- const result = await executeWorkflowFromFile(resolved, inputData);
32
- return result;
33
- }
34
- catch (err) {
35
- return {
36
- success: false,
37
- error: err instanceof Error ? err.message : String(err),
38
- };
39
- }
40
- },
41
- compileFile: async (params, ctx) => {
42
- const filePath = params.filePath;
43
- if (!filePath)
44
- throw new Error('filePath is required');
45
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
46
- try {
47
- const result = await compileWorkflow(resolved);
48
- return result;
49
- }
50
- catch (err) {
51
- return {
52
- success: false,
53
- error: err instanceof Error ? err.message : String(err),
54
- };
55
- }
56
- },
57
- generateDiagram: async (params, ctx) => {
58
- const filePath = params.filePath;
59
- const content = params.content;
60
- let source;
61
- if (content) {
62
- source = content;
63
- }
64
- else if (filePath) {
65
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
66
- source = await fs.readFile(resolved, 'utf-8');
67
- }
68
- else {
69
- throw new Error('filePath or content is required');
70
- }
71
- const render = await loadDiagram();
72
- if (!render) {
73
- return { success: false, error: 'Diagram module not available' };
74
- }
75
- try {
76
- const svg = render(source, {
77
- workflowName: params.workflowName,
78
- });
79
- return { success: true, svg };
80
- }
81
- catch (err) {
82
- return {
83
- success: false,
84
- error: err instanceof Error ? err.message : String(err),
85
- };
86
- }
87
- },
88
- };
89
- //# sourceMappingURL=execution.js.map
@@ -1,7 +0,0 @@
1
- /**
2
- * File operation handlers for the tunnel CLI.
3
- * Ported from flow-weaver-platform/src/routes/studio-rpc.ts file handlers.
4
- */
5
- import type { HandlerFn } from '../dispatch.js';
6
- export declare const fileOpsHandlers: Record<string, HandlerFn>;
7
- //# sourceMappingURL=file-ops.d.ts.map
@@ -1,204 +0,0 @@
1
- /**
2
- * File operation handlers for the tunnel CLI.
3
- * Ported from flow-weaver-platform/src/routes/studio-rpc.ts file handlers.
4
- */
5
- import * as fs from 'node:fs/promises';
6
- import * as path from 'node:path';
7
- import { resolvePath, toVirtualPath } from '../path-resolver.js';
8
- const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', '.next', '.cache', '.claude']);
9
- const SKIP_FILES = new Set(['package-lock.json']);
10
- async function collectFileInfos(dir, root) {
11
- const results = [];
12
- async function walk(currentDir) {
13
- let entries;
14
- try {
15
- entries = await fs.readdir(currentDir, { withFileTypes: true });
16
- }
17
- catch {
18
- return;
19
- }
20
- for (const entry of entries) {
21
- if (SKIP_DIRS.has(entry.name) || entry.name.startsWith('.'))
22
- continue;
23
- if (SKIP_FILES.has(entry.name))
24
- continue;
25
- const fullPath = path.join(currentDir, entry.name);
26
- const isDir = entry.isDirectory();
27
- results.push({
28
- path: toVirtualPath(root, fullPath),
29
- type: isDir ? 'directory' : 'file',
30
- });
31
- if (isDir) {
32
- await walk(fullPath);
33
- }
34
- }
35
- }
36
- await walk(dir);
37
- return results;
38
- }
39
- export const fileOpsHandlers = {
40
- getCWD: async () => '/',
41
- findProjectRoot: async () => '/',
42
- getFile: async (params, ctx) => {
43
- const filePath = params.filePath;
44
- if (!filePath)
45
- throw new Error('filePath is required');
46
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
47
- return fs.readFile(resolved, 'utf-8');
48
- },
49
- writeFile: async (params, ctx) => {
50
- const filePath = (params.filePath || params.path);
51
- const content = (params.content ?? params.source ?? params.text);
52
- if (!filePath)
53
- throw new Error('filePath is required');
54
- if (content === undefined || content === null)
55
- throw new Error('content is required');
56
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
57
- await fs.mkdir(path.dirname(resolved), { recursive: true });
58
- await fs.writeFile(resolved, content, 'utf-8');
59
- return { saved: true };
60
- },
61
- saveFile: async (params, ctx) => {
62
- // saveFile is an alias for writeFile
63
- return fileOpsHandlers.writeFile(params, ctx);
64
- },
65
- hasFile: async (params, ctx) => {
66
- const filePath = params.filePath;
67
- if (!filePath)
68
- return false;
69
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
70
- try {
71
- await fs.access(resolved);
72
- return true;
73
- }
74
- catch {
75
- return false;
76
- }
77
- },
78
- deleteFile: async (params, ctx) => {
79
- const filePath = params.filePath;
80
- if (!filePath)
81
- throw new Error('filePath is required');
82
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
83
- await fs.unlink(resolved);
84
- return { deleted: true };
85
- },
86
- getFilesStructure: async (_params, ctx) => {
87
- return collectFileInfos(ctx.workspaceRoot, ctx.workspaceRoot);
88
- },
89
- getFilesStructureRecursive: async (_params, ctx) => {
90
- return collectFileInfos(ctx.workspaceRoot, ctx.workspaceRoot);
91
- },
92
- listDirectory: async (params, ctx) => {
93
- let dirPath = (params.dirPath || params.path || params.directory);
94
- if (dirPath?.startsWith('/cloud'))
95
- dirPath = dirPath.slice('/cloud'.length) || undefined;
96
- const resolved = dirPath && dirPath !== '/' && dirPath !== ''
97
- ? resolvePath(ctx.workspaceRoot, dirPath)
98
- : ctx.workspaceRoot;
99
- const entries = await fs.readdir(resolved, { withFileTypes: true });
100
- const results = [];
101
- for (const entry of entries) {
102
- if (entry.name === 'node_modules' || entry.name === 'package-lock.json')
103
- continue;
104
- const fullPath = path.join(resolved, entry.name);
105
- const stat = await fs.stat(fullPath);
106
- const isDir = entry.isDirectory();
107
- results.push({
108
- name: entry.name,
109
- path: toVirtualPath(ctx.workspaceRoot, fullPath),
110
- type: isDir ? 'directory' : 'file',
111
- isDirectory: isDir,
112
- size: stat.size,
113
- modified: stat.mtime.toISOString(),
114
- });
115
- }
116
- return results;
117
- },
118
- findWorkflows: async (_params, ctx) => {
119
- const entries = await fs.readdir(ctx.workspaceRoot, { withFileTypes: true });
120
- const paths = [];
121
- for (const entry of entries) {
122
- if (entry.isFile() && entry.name.endsWith('.ts')) {
123
- paths.push('/' + entry.name);
124
- }
125
- }
126
- return paths;
127
- },
128
- createFolder: async (params, ctx) => {
129
- const dirPath = params.dirPath;
130
- if (!dirPath)
131
- throw new Error('dirPath is required');
132
- const resolved = resolvePath(ctx.workspaceRoot, dirPath);
133
- await fs.mkdir(resolved, { recursive: true });
134
- return { created: true };
135
- },
136
- renameFile: async (params, ctx) => {
137
- const oldPath = params.oldPath;
138
- const newPath = params.newPath;
139
- if (!oldPath || !newPath)
140
- throw new Error('oldPath and newPath are required');
141
- const resolvedOld = resolvePath(ctx.workspaceRoot, oldPath);
142
- const resolvedNew = resolvePath(ctx.workspaceRoot, newPath);
143
- await fs.rename(resolvedOld, resolvedNew);
144
- return { renamed: true };
145
- },
146
- getFileStats: async (params, ctx) => {
147
- const filePath = params.filePath;
148
- if (!filePath)
149
- throw new Error('filePath is required');
150
- const resolved = resolvePath(ctx.workspaceRoot, filePath);
151
- const stat = await fs.stat(resolved);
152
- return {
153
- size: stat.size,
154
- created: stat.birthtime.toISOString(),
155
- modified: stat.mtime.toISOString(),
156
- isFile: stat.isFile(),
157
- isDirectory: stat.isDirectory(),
158
- };
159
- },
160
- hasFolder: async () => true,
161
- deleteDirectory: async () => ({ success: true }),
162
- moveFile: async () => ({ success: true }),
163
- copyFile: async () => ({ success: true }),
164
- copyDirectory: async () => ({ success: true }),
165
- checkLibraryStatus: async (_params, ctx) => {
166
- try {
167
- const pkgPath = path.join(ctx.workspaceRoot, 'node_modules', '@synergenius', 'flow-weaver', 'package.json');
168
- const raw = await fs.readFile(pkgPath, 'utf-8');
169
- const pkg = JSON.parse(raw);
170
- return {
171
- installed: true,
172
- compatible: true,
173
- corrupt: false,
174
- outdated: false,
175
- version: pkg.version,
176
- issues: [],
177
- capabilities: {},
178
- };
179
- }
180
- catch {
181
- return {
182
- installed: false,
183
- compatible: false,
184
- corrupt: false,
185
- outdated: false,
186
- version: null,
187
- issues: ['@synergenius/flow-weaver not installed in project'],
188
- capabilities: {},
189
- };
190
- }
191
- },
192
- getPackages: async (_params, ctx) => {
193
- try {
194
- const raw = await fs.readFile(path.join(ctx.workspaceRoot, 'package.json'), 'utf-8');
195
- const pkg = JSON.parse(raw);
196
- const deps = pkg.dependencies || {};
197
- return Object.entries(deps).map(([name, version]) => ({ name, version }));
198
- }
199
- catch {
200
- return [];
201
- }
202
- },
203
- };
204
- //# sourceMappingURL=file-ops.js.map
@@ -1,7 +0,0 @@
1
- /**
2
- * Workflow mutation handlers for the tunnel CLI.
3
- * Ported from flow-weaver-platform/src/services/ast-helpers.ts mutation wrappers.
4
- */
5
- import type { HandlerFn } from '../dispatch.js';
6
- export declare const mutationHandlers: Record<string, HandlerFn>;
7
- //# sourceMappingURL=mutations.d.ts.map