@codemcp/workflows-core 3.1.21 → 3.2.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.
- package/package.json +9 -5
- package/resources/templates/architecture/arc42/arc42-template-EN.md +1077 -0
- package/resources/templates/architecture/arc42/images/01_2_iso-25010-topics-EN.drawio-2023.png +0 -0
- package/resources/templates/architecture/arc42/images/01_2_iso-25010-topics-EN.drawio.png +0 -0
- package/resources/templates/architecture/arc42/images/05_building_blocks-EN.png +0 -0
- package/resources/templates/architecture/arc42/images/08-concepts-EN.drawio.png +0 -0
- package/resources/templates/architecture/arc42/images/arc42-logo.png +0 -0
- package/resources/templates/architecture/c4.md +224 -0
- package/resources/templates/architecture/freestyle.md +53 -0
- package/resources/templates/architecture/none.md +17 -0
- package/resources/templates/design/comprehensive.md +207 -0
- package/resources/templates/design/freestyle.md +37 -0
- package/resources/templates/design/none.md +17 -0
- package/resources/templates/requirements/ears.md +90 -0
- package/resources/templates/requirements/freestyle.md +42 -0
- package/resources/templates/requirements/none.md +17 -0
- package/resources/workflows/big-bang-conversion.yaml +539 -0
- package/resources/workflows/boundary-testing.yaml +334 -0
- package/resources/workflows/bugfix.yaml +185 -0
- package/resources/workflows/business-analysis.yaml +671 -0
- package/resources/workflows/c4-analysis.yaml +485 -0
- package/resources/workflows/epcc.yaml +161 -0
- package/resources/workflows/greenfield.yaml +189 -0
- package/resources/workflows/minor.yaml +127 -0
- package/resources/workflows/posts.yaml +207 -0
- package/resources/workflows/slides.yaml +256 -0
- package/resources/workflows/tdd.yaml +157 -0
- package/resources/workflows/waterfall.yaml +195 -0
- package/.turbo/turbo-build.log +0 -4
- package/src/config-manager.ts +0 -96
- package/src/conversation-manager.ts +0 -489
- package/src/database.ts +0 -427
- package/src/file-detection-manager.ts +0 -302
- package/src/git-manager.ts +0 -64
- package/src/index.ts +0 -28
- package/src/instruction-generator.ts +0 -210
- package/src/interaction-logger.ts +0 -109
- package/src/logger.ts +0 -353
- package/src/path-validation-utils.ts +0 -261
- package/src/plan-manager.ts +0 -323
- package/src/project-docs-manager.ts +0 -523
- package/src/state-machine-loader.ts +0 -365
- package/src/state-machine-types.ts +0 -72
- package/src/state-machine.ts +0 -370
- package/src/system-prompt-generator.ts +0 -122
- package/src/template-manager.ts +0 -328
- package/src/transition-engine.ts +0 -386
- package/src/types.ts +0 -60
- package/src/workflow-manager.ts +0 -606
- package/test/unit/conversation-manager.test.ts +0 -179
- package/test/unit/custom-workflow-loading.test.ts +0 -174
- package/test/unit/directory-linking-and-extensions.test.ts +0 -338
- package/test/unit/file-linking-integration.test.ts +0 -256
- package/test/unit/git-commit-integration.test.ts +0 -91
- package/test/unit/git-manager.test.ts +0 -86
- package/test/unit/install-workflow.test.ts +0 -138
- package/test/unit/instruction-generator.test.ts +0 -247
- package/test/unit/list-workflows-filtering.test.ts +0 -68
- package/test/unit/none-template-functionality.test.ts +0 -224
- package/test/unit/project-docs-manager.test.ts +0 -337
- package/test/unit/state-machine-loader.test.ts +0 -234
- package/test/unit/template-manager.test.ts +0 -217
- package/test/unit/validate-workflow-name.test.ts +0 -150
- package/test/unit/workflow-domain-filtering.test.ts +0 -75
- package/test/unit/workflow-enum-generation.test.ts +0 -92
- package/test/unit/workflow-manager-enhanced-path-resolution.test.ts +0 -369
- package/test/unit/workflow-manager-path-resolution.test.ts +0 -150
- package/test/unit/workflow-migration.test.ts +0 -155
- package/test/unit/workflow-override-by-name.test.ts +0 -116
- package/test/unit/workflow-prioritization.test.ts +0 -38
- package/test/unit/workflow-validation.test.ts +0 -303
- package/test/utils/e2e-test-setup.ts +0 -453
- package/test/utils/run-server-in-dir.sh +0 -27
- package/test/utils/temp-files.ts +0 -308
- package/test/utils/test-access.ts +0 -79
- package/test/utils/test-helpers.ts +0 -286
- package/test/utils/test-setup.ts +0 -78
- package/tsconfig.build.json +0 -21
- package/tsconfig.json +0 -8
- package/vitest.config.ts +0 -18
@@ -1,453 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* End-to-End Test Setup Utilities
|
3
|
-
*
|
4
|
-
* Provides utilities for testing the MCP server end-to-end without
|
5
|
-
* spawning separate processes or using transport layers. Tests the
|
6
|
-
* server's public interface directly for true consumer perspective testing.
|
7
|
-
*/
|
8
|
-
|
9
|
-
import { vi } from 'vitest';
|
10
|
-
import {
|
11
|
-
ResponsibleVibeMCPServer,
|
12
|
-
createResponsibleVibeMCPServer,
|
13
|
-
ServerConfig,
|
14
|
-
} from '../../packages/mcp-server/src/server.js';
|
15
|
-
import { TempProject } from './temp-files.js';
|
16
|
-
import { join } from 'node:path';
|
17
|
-
import { tmpdir } from 'node:os';
|
18
|
-
import { mkdirSync, rmSync, existsSync } from 'node:fs';
|
19
|
-
import type { ServerContext } from '../../packages/mcp-server/src/types';
|
20
|
-
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
21
|
-
|
22
|
-
// Disable fs mocking for E2E tests
|
23
|
-
vi.unmock('fs');
|
24
|
-
vi.unmock('fs/promises');
|
25
|
-
|
26
|
-
/**
|
27
|
-
* Suite-level test isolation manager
|
28
|
-
* Ensures each test suite gets its own isolated temporary directory
|
29
|
-
*/
|
30
|
-
export class TestSuiteIsolation {
|
31
|
-
private static suiteDirectories = new Map<string, string>();
|
32
|
-
private static cleanupCallbacks = new Map<string, (() => void)[]>();
|
33
|
-
|
34
|
-
/**
|
35
|
-
* Get or create an isolated directory for a test suite
|
36
|
-
*/
|
37
|
-
static getSuiteDirectory(suiteName: string): string {
|
38
|
-
if (!this.suiteDirectories.has(suiteName)) {
|
39
|
-
// Create unique directory for this suite
|
40
|
-
const suiteId = `${suiteName.replace(/[^a-zA-Z0-9]/g, '-')}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
41
|
-
const suiteDir = join(tmpdir(), 'responsible-vibe-e2e-suites', suiteId);
|
42
|
-
|
43
|
-
// Ensure directory exists
|
44
|
-
mkdirSync(suiteDir, { recursive: true });
|
45
|
-
|
46
|
-
this.suiteDirectories.set(suiteName, suiteDir);
|
47
|
-
this.cleanupCallbacks.set(suiteName, []);
|
48
|
-
}
|
49
|
-
|
50
|
-
const directory = this.suiteDirectories.get(suiteName);
|
51
|
-
if (!directory) {
|
52
|
-
throw new Error(`Suite directory not found for ${suiteName}`);
|
53
|
-
}
|
54
|
-
return directory;
|
55
|
-
}
|
56
|
-
|
57
|
-
/**
|
58
|
-
* Register a cleanup callback for a suite
|
59
|
-
*/
|
60
|
-
static registerCleanup(suiteName: string, cleanup: () => void): void {
|
61
|
-
const callbacks = this.cleanupCallbacks.get(suiteName) || [];
|
62
|
-
callbacks.push(cleanup);
|
63
|
-
this.cleanupCallbacks.set(suiteName, callbacks);
|
64
|
-
}
|
65
|
-
|
66
|
-
/**
|
67
|
-
* Clean up all resources for a test suite
|
68
|
-
*/
|
69
|
-
static async cleanupSuite(suiteName: string): Promise<void> {
|
70
|
-
// Run all registered cleanup callbacks
|
71
|
-
const callbacks = this.cleanupCallbacks.get(suiteName) || [];
|
72
|
-
for (const cleanup of callbacks) {
|
73
|
-
try {
|
74
|
-
cleanup();
|
75
|
-
} catch (error) {
|
76
|
-
console.warn(`Cleanup callback failed for suite ${suiteName}:`, error);
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
80
|
-
// Remove the suite directory
|
81
|
-
const suiteDir = this.suiteDirectories.get(suiteName);
|
82
|
-
if (suiteDir && existsSync(suiteDir)) {
|
83
|
-
try {
|
84
|
-
rmSync(suiteDir, { recursive: true, force: true });
|
85
|
-
} catch (error) {
|
86
|
-
console.warn(`Failed to remove suite directory ${suiteDir}:`, error);
|
87
|
-
}
|
88
|
-
}
|
89
|
-
|
90
|
-
// Clean up tracking
|
91
|
-
this.suiteDirectories.delete(suiteName);
|
92
|
-
this.cleanupCallbacks.delete(suiteName);
|
93
|
-
}
|
94
|
-
|
95
|
-
/**
|
96
|
-
* Clean up all suites (for global teardown)
|
97
|
-
*/
|
98
|
-
static async cleanupAll(): Promise<void> {
|
99
|
-
const suiteNames = Array.from(this.suiteDirectories.keys());
|
100
|
-
for (const suiteName of suiteNames) {
|
101
|
-
await this.cleanupSuite(suiteName);
|
102
|
-
}
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
/**
|
107
|
-
* E2E test context that provides direct access to MCP server
|
108
|
-
*/
|
109
|
-
export interface E2ETestContext {
|
110
|
-
server: ResponsibleVibeMCPServer;
|
111
|
-
tempProject: TempProject;
|
112
|
-
cleanup: () => Promise<void>;
|
113
|
-
}
|
114
|
-
|
115
|
-
/**
|
116
|
-
* Direct Server Interface
|
117
|
-
* Provides a consumer-like interface that calls server methods directly
|
118
|
-
* without going through MCP transport layer
|
119
|
-
*/
|
120
|
-
export class DirectServerInterface {
|
121
|
-
constructor(private server: ResponsibleVibeMCPServer) {}
|
122
|
-
|
123
|
-
/**
|
124
|
-
* Call a tool on the server directly
|
125
|
-
*/
|
126
|
-
async callTool<T = unknown>(name: string, arguments_: unknown): Promise<T> {
|
127
|
-
try {
|
128
|
-
// Call the server's tool handlers directly based on tool name
|
129
|
-
switch (name) {
|
130
|
-
case 'whats_next':
|
131
|
-
return await this.server.handleWhatsNext(arguments_);
|
132
|
-
|
133
|
-
case 'proceed_to_phase':
|
134
|
-
return await this.server.handleProceedToPhase(arguments_);
|
135
|
-
|
136
|
-
case 'start_development':
|
137
|
-
return await this.server.handleStartDevelopment(arguments_);
|
138
|
-
|
139
|
-
default:
|
140
|
-
throw new Error(`Unknown tool: ${name}`);
|
141
|
-
}
|
142
|
-
} catch (error) {
|
143
|
-
// Return errors as objects instead of throwing them
|
144
|
-
// This matches the expected behavior in tests
|
145
|
-
return {
|
146
|
-
error: error instanceof Error ? error.message : String(error),
|
147
|
-
};
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
/**
|
152
|
-
* Read a resource from the server directly
|
153
|
-
*/
|
154
|
-
async readResource<T = unknown>(uri: string): Promise<T> {
|
155
|
-
// Call the server's resource handlers directly based on URI
|
156
|
-
switch (uri) {
|
157
|
-
case 'state://current':
|
158
|
-
return await this.getConversationState();
|
159
|
-
|
160
|
-
case 'plan://current':
|
161
|
-
return await this.getDevelopmentPlan();
|
162
|
-
|
163
|
-
case 'system-prompt://':
|
164
|
-
return await this.getSystemPrompt();
|
165
|
-
|
166
|
-
default:
|
167
|
-
throw new Error(`Unknown resource URI: ${uri}`);
|
168
|
-
}
|
169
|
-
}
|
170
|
-
|
171
|
-
/**
|
172
|
-
* Get conversation state directly
|
173
|
-
*/
|
174
|
-
private async getConversationState(): Promise<unknown> {
|
175
|
-
const conversationManager = this.server.getConversationManager();
|
176
|
-
const conversationContext =
|
177
|
-
await conversationManager.getConversationContext();
|
178
|
-
|
179
|
-
const stateData = {
|
180
|
-
conversationId: conversationContext.conversationId,
|
181
|
-
currentPhase: conversationContext.currentPhase,
|
182
|
-
projectPath: conversationContext.projectPath,
|
183
|
-
timestamp: new Date().toISOString(),
|
184
|
-
};
|
185
|
-
|
186
|
-
return {
|
187
|
-
contents: [
|
188
|
-
{
|
189
|
-
uri: 'state://current',
|
190
|
-
mimeType: 'application/json',
|
191
|
-
text: JSON.stringify(stateData, null, 2),
|
192
|
-
},
|
193
|
-
],
|
194
|
-
};
|
195
|
-
}
|
196
|
-
|
197
|
-
/**
|
198
|
-
* Get development plan directly
|
199
|
-
*/
|
200
|
-
private async getDevelopmentPlan(): Promise<unknown> {
|
201
|
-
const conversationManager = this.server.getConversationManager();
|
202
|
-
const planManager = this.server.getPlanManager();
|
203
|
-
|
204
|
-
const conversationContext =
|
205
|
-
await conversationManager.getConversationContext();
|
206
|
-
const planFilePath = conversationContext.planFilePath;
|
207
|
-
|
208
|
-
let planContent: string;
|
209
|
-
try {
|
210
|
-
planContent = await planManager.getPlanFileContent(planFilePath);
|
211
|
-
} catch {
|
212
|
-
// If plan file doesn't exist yet, return a default message
|
213
|
-
planContent = `# Development Plan\n\nPlan file will be created when development begins.\n\nConversation ID: ${conversationContext.conversationId}`;
|
214
|
-
}
|
215
|
-
|
216
|
-
return {
|
217
|
-
contents: [
|
218
|
-
{
|
219
|
-
uri: 'plan://current',
|
220
|
-
mimeType: 'text/markdown',
|
221
|
-
text: planContent,
|
222
|
-
},
|
223
|
-
],
|
224
|
-
};
|
225
|
-
}
|
226
|
-
|
227
|
-
/**
|
228
|
-
* Get system prompt resource directly
|
229
|
-
*/
|
230
|
-
async getSystemPrompt(): Promise<unknown> {
|
231
|
-
// Use the system prompt handler directly with the default workflow
|
232
|
-
const { SystemPromptResourceHandler } = await import(
|
233
|
-
'../../packages/mcp-server/src/resource-handlers/system-prompt.js'
|
234
|
-
);
|
235
|
-
const handler = new SystemPromptResourceHandler();
|
236
|
-
|
237
|
-
// Create a minimal context - system prompt doesn't need full server context
|
238
|
-
const result = await handler.handle(
|
239
|
-
new URL('system-prompt://'),
|
240
|
-
{} as ServerContext
|
241
|
-
);
|
242
|
-
|
243
|
-
return {
|
244
|
-
contents: [
|
245
|
-
{
|
246
|
-
uri: 'system-prompt://',
|
247
|
-
mimeType: result.mimeType,
|
248
|
-
text: result.text,
|
249
|
-
},
|
250
|
-
],
|
251
|
-
};
|
252
|
-
}
|
253
|
-
|
254
|
-
/**
|
255
|
-
* List available tools (for testing completeness)
|
256
|
-
*/
|
257
|
-
async listTools(): Promise<{ tools: { name: string }[] }> {
|
258
|
-
return {
|
259
|
-
tools: [{ name: 'whats_next' }, { name: 'proceed_to_phase' }],
|
260
|
-
};
|
261
|
-
}
|
262
|
-
|
263
|
-
/**
|
264
|
-
* List available resources (for testing completeness)
|
265
|
-
*/
|
266
|
-
async listResources(): Promise<{ resources: { uri: string }[] }> {
|
267
|
-
return {
|
268
|
-
resources: [
|
269
|
-
{ uri: 'state://current' },
|
270
|
-
{ uri: 'plan://current' },
|
271
|
-
{ uri: 'system-prompt://' },
|
272
|
-
],
|
273
|
-
};
|
274
|
-
}
|
275
|
-
|
276
|
-
/**
|
277
|
-
* Get a prompt (if we add prompt support later)
|
278
|
-
*/
|
279
|
-
async getPrompt(name: string, arguments_: unknown = {}): Promise<unknown> {
|
280
|
-
// For now, just return a placeholder
|
281
|
-
return {
|
282
|
-
description: `Prompt for ${name}`,
|
283
|
-
messages: [
|
284
|
-
{
|
285
|
-
role: 'user',
|
286
|
-
content: {
|
287
|
-
type: 'text',
|
288
|
-
text: `Prompt: ${name} with args: ${JSON.stringify(arguments_)}`,
|
289
|
-
},
|
290
|
-
},
|
291
|
-
],
|
292
|
-
};
|
293
|
-
}
|
294
|
-
}
|
295
|
-
|
296
|
-
/**
|
297
|
-
* Setup end-to-end test environment with real MCP server
|
298
|
-
*/
|
299
|
-
export async function setupE2ETest(
|
300
|
-
options: {
|
301
|
-
tempProject: TempProject;
|
302
|
-
serverConfig?: Partial<ServerConfig>;
|
303
|
-
} = {} as {
|
304
|
-
tempProject: TempProject;
|
305
|
-
serverConfig?: Partial<ServerConfig>;
|
306
|
-
}
|
307
|
-
): Promise<E2ETestContext> {
|
308
|
-
const { tempProject, serverConfig = {} } = options;
|
309
|
-
|
310
|
-
// Create server with test configuration
|
311
|
-
const server = await createResponsibleVibeMCPServer({
|
312
|
-
projectPath: tempProject.projectPath,
|
313
|
-
enableLogging: false, // Disable logging in tests
|
314
|
-
...serverConfig,
|
315
|
-
});
|
316
|
-
|
317
|
-
// Initialize server
|
318
|
-
await server.initialize();
|
319
|
-
|
320
|
-
return {
|
321
|
-
server,
|
322
|
-
tempProject,
|
323
|
-
cleanup: async () => {
|
324
|
-
await server.cleanup();
|
325
|
-
},
|
326
|
-
};
|
327
|
-
}
|
328
|
-
|
329
|
-
/**
|
330
|
-
* Create direct server interface for testing
|
331
|
-
*/
|
332
|
-
export function createDirectServerInterface(
|
333
|
-
server: ResponsibleVibeMCPServer
|
334
|
-
): DirectServerInterface {
|
335
|
-
return new DirectServerInterface(server);
|
336
|
-
}
|
337
|
-
|
338
|
-
/**
|
339
|
-
* Helper to safely parse JSON responses, handling both success and error cases
|
340
|
-
*/
|
341
|
-
export function parseToolResponse(result: unknown): unknown {
|
342
|
-
// If result is already an object (direct server call), return as-is
|
343
|
-
if (typeof result === 'object' && result !== null) {
|
344
|
-
return result;
|
345
|
-
}
|
346
|
-
|
347
|
-
// If it's a string, try to parse as JSON
|
348
|
-
if (typeof result === 'string') {
|
349
|
-
try {
|
350
|
-
return JSON.parse(result);
|
351
|
-
} catch {
|
352
|
-
return { error: result };
|
353
|
-
}
|
354
|
-
}
|
355
|
-
|
356
|
-
return result;
|
357
|
-
}
|
358
|
-
|
359
|
-
/**
|
360
|
-
* Assert that a tool call was successful and return the response
|
361
|
-
*/
|
362
|
-
export function assertToolSuccess(result: unknown): CallToolResult {
|
363
|
-
// Parse result if it's a string
|
364
|
-
const parsed = typeof result === 'string' ? JSON.parse(result) : result;
|
365
|
-
|
366
|
-
if (parsed.error) {
|
367
|
-
throw new Error(`Tool call failed: ${parsed.error}`);
|
368
|
-
}
|
369
|
-
|
370
|
-
return parsed;
|
371
|
-
}
|
372
|
-
|
373
|
-
/**
|
374
|
-
* Initialize development for tests by calling start_development with a workflow
|
375
|
-
* This must be called before any other tools in tests due to the new requirement
|
376
|
-
*
|
377
|
-
* @param client - The DirectServerInterface instance
|
378
|
-
* @param workflow - The workflow to use (defaults to 'waterfall')
|
379
|
-
* @param commitBehaviour - The commit behavior to use (defaults to 'none' for tests)
|
380
|
-
* @returns The response from start_development
|
381
|
-
*/
|
382
|
-
export async function initializeDevelopment(
|
383
|
-
client: DirectServerInterface,
|
384
|
-
workflow: string = 'waterfall',
|
385
|
-
commitBehaviour: 'step' | 'phase' | 'end' | 'none' = 'none'
|
386
|
-
): Promise<unknown> {
|
387
|
-
const result = await client.callTool('start_development', {
|
388
|
-
workflow,
|
389
|
-
commit_behaviour: commitBehaviour,
|
390
|
-
});
|
391
|
-
return assertToolSuccess(result);
|
392
|
-
}
|
393
|
-
|
394
|
-
/**
|
395
|
-
* Helper to create a complete E2E test scenario
|
396
|
-
*/
|
397
|
-
export async function createE2EScenario(options: {
|
398
|
-
tempProject: TempProject;
|
399
|
-
serverConfig?: Partial<ServerConfig>;
|
400
|
-
}): Promise<{
|
401
|
-
client: DirectServerInterface;
|
402
|
-
server: ResponsibleVibeMCPServer;
|
403
|
-
tempProject: TempProject;
|
404
|
-
cleanup: () => Promise<void>;
|
405
|
-
}> {
|
406
|
-
const context = await setupE2ETest(options);
|
407
|
-
const client = createDirectServerInterface(context.server);
|
408
|
-
|
409
|
-
return {
|
410
|
-
client,
|
411
|
-
server: context.server,
|
412
|
-
tempProject: context.tempProject,
|
413
|
-
cleanup: context.cleanup,
|
414
|
-
};
|
415
|
-
}
|
416
|
-
|
417
|
-
/**
|
418
|
-
* Create a suite-isolated E2E scenario
|
419
|
-
* Each test suite gets its own isolated temporary directory
|
420
|
-
*/
|
421
|
-
export async function createSuiteIsolatedE2EScenario(options: {
|
422
|
-
suiteName: string;
|
423
|
-
tempProjectFactory: (baseDir?: string) => TempProject;
|
424
|
-
serverConfig?: Partial<ServerConfig>;
|
425
|
-
}): Promise<{
|
426
|
-
client: DirectServerInterface;
|
427
|
-
server: ResponsibleVibeMCPServer;
|
428
|
-
tempProject: TempProject;
|
429
|
-
cleanup: () => Promise<void>;
|
430
|
-
}> {
|
431
|
-
const { suiteName, tempProjectFactory, serverConfig = {} } = options;
|
432
|
-
|
433
|
-
// Get suite-isolated directory
|
434
|
-
const suiteDir = TestSuiteIsolation.getSuiteDirectory(suiteName);
|
435
|
-
|
436
|
-
// Create temp project in the suite directory
|
437
|
-
const tempProject = tempProjectFactory(suiteDir);
|
438
|
-
|
439
|
-
// Register temp project cleanup with the suite
|
440
|
-
TestSuiteIsolation.registerCleanup(suiteName, () => {
|
441
|
-
tempProject.cleanup();
|
442
|
-
});
|
443
|
-
|
444
|
-
const context = await setupE2ETest({ tempProject, serverConfig });
|
445
|
-
const client = createDirectServerInterface(context.server);
|
446
|
-
|
447
|
-
return {
|
448
|
-
client,
|
449
|
-
server: context.server,
|
450
|
-
tempProject: context.tempProject,
|
451
|
-
cleanup: context.cleanup,
|
452
|
-
};
|
453
|
-
}
|
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
|
3
|
-
# Server Runner Script
|
4
|
-
#
|
5
|
-
# This script changes the current working directory to the specified path
|
6
|
-
# before running the server. This ensures that the server operates in the
|
7
|
-
# correct directory context for testing.
|
8
|
-
#
|
9
|
-
# This is necessary because the server uses process.cwd() to determine the project path,
|
10
|
-
# and the StdioClientTransport's cwd option doesn't properly isolate the server process.
|
11
|
-
# By explicitly changing directory in a wrapper script, we ensure the server operates
|
12
|
-
# on a clean test directory rather than the current project directory.
|
13
|
-
|
14
|
-
# Get the target directory from command line arguments
|
15
|
-
TARGET_DIR="$1"
|
16
|
-
SERVER_PATH="$2"
|
17
|
-
|
18
|
-
if [ -z "$TARGET_DIR" ] || [ -z "$SERVER_PATH" ]; then
|
19
|
-
echo "Usage: ./run-server-in-dir.sh <target-directory> <server-path>"
|
20
|
-
exit 1
|
21
|
-
fi
|
22
|
-
|
23
|
-
# Change to the target directory
|
24
|
-
cd "$TARGET_DIR" || exit 1
|
25
|
-
|
26
|
-
# Run the server
|
27
|
-
node "$SERVER_PATH"
|