@codemcp/workflows 3.3.6 → 3.4.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.
@@ -1,185 +0,0 @@
1
- /**
2
- * Install Workflow Tool Handler
3
- *
4
- * Installs workflows to .vibe/workflows/ directory from various sources
5
- */
6
-
7
- import { z } from 'zod';
8
- import { BaseToolHandler } from './base-tool-handler.js';
9
- import { createLogger } from '@codemcp/workflows-core';
10
- import { notificationService } from '../notification-service.js';
11
- import fs from 'node:fs';
12
- import path from 'node:path';
13
- import { ServerContext } from '../types.js';
14
-
15
- const logger = createLogger('InstallWorkflowHandler');
16
-
17
- /**
18
- * Schema for install_workflow tool arguments
19
- */
20
- const InstallWorkflowArgsSchema = z.object({
21
- source: z
22
- .string()
23
- .describe(
24
- 'Source workflow name (from unloaded workflows) or URL to workflow file'
25
- ),
26
- name: z
27
- .string()
28
- .optional()
29
- .describe('Custom name for installed workflow (defaults to source name)'),
30
- });
31
-
32
- type InstallWorkflowArgs = z.infer<typeof InstallWorkflowArgsSchema>;
33
-
34
- interface InstallWorkflowResponse {
35
- success: boolean;
36
- message: string;
37
- installedPath?: string;
38
- }
39
-
40
- /**
41
- * Tool handler for installing workflows
42
- */
43
- export class InstallWorkflowHandler extends BaseToolHandler<
44
- InstallWorkflowArgs,
45
- InstallWorkflowResponse
46
- > {
47
- protected readonly argsSchema = InstallWorkflowArgsSchema;
48
-
49
- async executeHandler(
50
- args: InstallWorkflowArgs,
51
- context: ServerContext
52
- ): Promise<InstallWorkflowResponse> {
53
- logger.info('Installing workflow', {
54
- source: args.source,
55
- name: args.name,
56
- projectPath: context.projectPath,
57
- });
58
-
59
- try {
60
- // Create .vibe/workflows directory if it doesn't exist
61
- const workflowsDir = path.join(context.projectPath, '.vibe', 'workflows');
62
- fs.mkdirSync(workflowsDir, { recursive: true });
63
-
64
- // Determine if source is a workflow name or URL
65
- const isUrl =
66
- args.source.startsWith('http://') || args.source.startsWith('https://');
67
-
68
- if (isUrl) {
69
- return await this.installFromUrl(args.source, args.name, workflowsDir);
70
- } else {
71
- return await this.installFromPredefined(
72
- args.source,
73
- args.name,
74
- workflowsDir,
75
- context
76
- );
77
- }
78
- } catch (error) {
79
- const errorMessage = `Failed to install workflow: ${error instanceof Error ? error.message : 'Unknown error'}`;
80
- logger.error('Workflow installation failed', error as Error, {
81
- source: args.source,
82
- name: args.name,
83
- });
84
-
85
- return {
86
- success: false,
87
- message: errorMessage,
88
- };
89
- }
90
- }
91
-
92
- private async installFromUrl(
93
- _url: string,
94
- _customName: string | undefined,
95
- _workflowsDir: string
96
- ): Promise<InstallWorkflowResponse> {
97
- // For now, return not implemented for URLs
98
- return {
99
- success: false,
100
- message:
101
- 'URL-based workflow installation not yet implemented. Use predefined workflow names.',
102
- };
103
- }
104
-
105
- private async installFromPredefined(
106
- workflowName: string,
107
- customName: string | undefined,
108
- workflowsDir: string,
109
- context: ServerContext
110
- ): Promise<InstallWorkflowResponse> {
111
- // Get all available workflows (including unloaded ones)
112
- const allWorkflows = context.workflowManager.getAllAvailableWorkflows();
113
- const sourceWorkflow = allWorkflows.find(w => w.name === workflowName);
114
-
115
- if (!sourceWorkflow) {
116
- return {
117
- success: false,
118
- message: `Workflow '${workflowName}' not found. Use list_workflows({include_unloaded: true}) to see available workflows.`,
119
- };
120
- }
121
-
122
- // Find the source workflow file
123
- const workflowsSourceDir = this.findWorkflowsDirectory();
124
- const sourceFile = path.join(workflowsSourceDir, `${workflowName}.yaml`);
125
-
126
- if (!fs.existsSync(sourceFile)) {
127
- return {
128
- success: false,
129
- message: `Source workflow file not found: ${sourceFile}`,
130
- };
131
- }
132
-
133
- // Determine target filename
134
- const targetName = customName || workflowName;
135
- const targetFile = path.join(workflowsDir, `${targetName}.yaml`);
136
-
137
- // Check if target already exists
138
- if (fs.existsSync(targetFile)) {
139
- return {
140
- success: false,
141
- message: `Workflow '${targetName}' already exists in .vibe/workflows/. Remove it first or use a different name.`,
142
- };
143
- }
144
-
145
- // Copy the workflow file
146
- fs.copyFileSync(sourceFile, targetFile);
147
-
148
- // Reload project workflows to make the installed workflow immediately available
149
- context.workflowManager.loadProjectWorkflows(context.projectPath);
150
-
151
- logger.info('Workflow installed successfully', {
152
- source: workflowName,
153
- target: targetName,
154
- path: targetFile,
155
- });
156
-
157
- // Notify MCP client that tool list has changed. There is no specific
158
- // notification for parameter description changes, so we reuse tool list change.
159
- // most MCP hosts will however not support this properly, thus we'll instruct the user to restart the server.
160
- await notificationService.notifyToolListChanged();
161
-
162
- return {
163
- success: true,
164
- message: `Workflow '${workflowName}' installed as '${targetName}' in .vibe/workflows/ . You may need to restart your agent to use it.`,
165
- installedPath: targetFile,
166
- };
167
- }
168
-
169
- private findWorkflowsDirectory(): string {
170
- // Same logic as WorkflowManager
171
- const possiblePaths = [
172
- path.join(process.cwd(), 'resources', 'workflows'),
173
- path.join(process.cwd(), 'dist', '..', 'resources', 'workflows'),
174
- path.join(process.cwd(), 'src', '..', 'resources', 'workflows'),
175
- ];
176
-
177
- for (const workflowsPath of possiblePaths) {
178
- if (fs.existsSync(workflowsPath)) {
179
- return workflowsPath;
180
- }
181
- }
182
-
183
- throw new Error('Workflows directory not found');
184
- }
185
- }