@codemcp/workflows 5.0.1 → 5.1.1

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 (77) hide show
  1. package/package.json +6 -2
  2. package/skill/SKILL.md +23 -0
  3. package/.prettierignore +0 -2
  4. package/.turbo/turbo-build.log +0 -4
  5. package/.vibe/conversation-state.sqlite +0 -0
  6. package/src/components/beads/beads-instruction-generator.ts +0 -230
  7. package/src/components/beads/beads-plan-manager.ts +0 -333
  8. package/src/components/beads/beads-task-backend-client.ts +0 -229
  9. package/src/index.ts +0 -93
  10. package/src/notification-service.ts +0 -23
  11. package/src/plugin-system/beads-plugin.ts +0 -649
  12. package/src/plugin-system/commit-plugin.ts +0 -252
  13. package/src/plugin-system/index.ts +0 -20
  14. package/src/plugin-system/plugin-interfaces.ts +0 -153
  15. package/src/plugin-system/plugin-registry.ts +0 -190
  16. package/src/resource-handlers/conversation-state.ts +0 -55
  17. package/src/resource-handlers/development-plan.ts +0 -48
  18. package/src/resource-handlers/index.ts +0 -73
  19. package/src/resource-handlers/system-prompt.ts +0 -55
  20. package/src/resource-handlers/workflow-resource.ts +0 -132
  21. package/src/response-renderer.ts +0 -116
  22. package/src/server-config.ts +0 -760
  23. package/src/server-helpers.ts +0 -245
  24. package/src/server-implementation.ts +0 -277
  25. package/src/server.ts +0 -9
  26. package/src/tool-handlers/base-tool-handler.ts +0 -151
  27. package/src/tool-handlers/conduct-review.ts +0 -190
  28. package/src/tool-handlers/get-tool-info.ts +0 -273
  29. package/src/tool-handlers/index.ts +0 -115
  30. package/src/tool-handlers/list-workflows.ts +0 -78
  31. package/src/tool-handlers/no-idea.ts +0 -47
  32. package/src/tool-handlers/proceed-to-phase.ts +0 -296
  33. package/src/tool-handlers/reset-development.ts +0 -90
  34. package/src/tool-handlers/resume-workflow.ts +0 -378
  35. package/src/tool-handlers/setup-project-docs.ts +0 -232
  36. package/src/tool-handlers/start-development.ts +0 -746
  37. package/src/tool-handlers/whats-next.ts +0 -246
  38. package/src/types.ts +0 -135
  39. package/src/version-info.ts +0 -213
  40. package/test/e2e/beads-plugin-integration.test.ts +0 -1623
  41. package/test/e2e/commit-plugin-integration.test.ts +0 -222
  42. package/test/e2e/core-functionality.test.ts +0 -167
  43. package/test/e2e/git-branch-detection.test.ts +0 -351
  44. package/test/e2e/mcp-contract.test.ts +0 -509
  45. package/test/e2e/plan-management.test.ts +0 -334
  46. package/test/e2e/plugin-system-integration.test.ts +0 -1410
  47. package/test/e2e/state-management.test.ts +0 -387
  48. package/test/e2e/workflow-integration.test.ts +0 -498
  49. package/test/unit/beads-instruction-generator.test.ts +0 -979
  50. package/test/unit/beads-phase-task-id-integration.test.ts +0 -535
  51. package/test/unit/beads-plugin-behavioral.test.ts +0 -545
  52. package/test/unit/beads-plugin.test.ts +0 -117
  53. package/test/unit/commit-plugin.test.ts +0 -196
  54. package/test/unit/conduct-review.test.ts +0 -151
  55. package/test/unit/conversation-not-found-error.test.ts +0 -120
  56. package/test/unit/plugin-error-handling.test.ts +0 -240
  57. package/test/unit/proceed-to-phase-plugin-integration.test.ts +0 -150
  58. package/test/unit/reset-functionality.test.ts +0 -72
  59. package/test/unit/resume-workflow.test.ts +0 -193
  60. package/test/unit/server-config-plugin-registry.test.ts +0 -99
  61. package/test/unit/server-tools.test.ts +0 -310
  62. package/test/unit/setup-project-docs-handler.test.ts +0 -268
  63. package/test/unit/start-development-artifact-detection.test.ts +0 -387
  64. package/test/unit/start-development-gitignore.test.ts +0 -178
  65. package/test/unit/start-development-goal-extraction.test.ts +0 -226
  66. package/test/unit/system-prompt-resource.test.ts +0 -102
  67. package/test/unit/tool-handlers/no-idea.test.ts +0 -40
  68. package/test/utils/e2e-test-setup.ts +0 -451
  69. package/test/utils/run-server-in-dir.sh +0 -27
  70. package/test/utils/temp-files.ts +0 -320
  71. package/test/utils/test-access.ts +0 -79
  72. package/test/utils/test-helpers.ts +0 -288
  73. package/test/utils/test-setup.ts +0 -77
  74. package/tsconfig.build.json +0 -10
  75. package/tsconfig.build.tsbuildinfo +0 -1
  76. package/tsconfig.json +0 -12
  77. package/vitest.config.ts +0 -19
@@ -1,245 +0,0 @@
1
- /**
2
- * Server Helper Functions
3
- *
4
- * Common utility functions used across the server implementation.
5
- * These are pure functions that don't depend on server state.
6
- */
7
-
8
- import { homedir } from 'node:os';
9
- import { createLogger } from '@codemcp/workflows-core';
10
- import { HandlerResult } from './types.js';
11
-
12
- const logger = createLogger('ServerHelpers');
13
-
14
- /**
15
- * Normalize and validate project path
16
- * Ensures we have a valid project path, defaulting to home directory if needed
17
- */
18
- export function normalizeProjectPath(projectPath?: string): string {
19
- const path = projectPath || process.cwd();
20
-
21
- if (path === '/' || path === '') {
22
- const homePath = homedir();
23
- logger.info('Invalid project path detected, using home directory', {
24
- originalPath: path,
25
- normalizedPath: homePath,
26
- });
27
- return homePath;
28
- }
29
-
30
- return path;
31
- }
32
-
33
- /**
34
- * Create a standardized success result
35
- */
36
- export function createSuccessResult<T>(
37
- data: T,
38
- metadata?: Record<string, unknown>
39
- ): HandlerResult<T> {
40
- return {
41
- success: true,
42
- data,
43
- metadata,
44
- };
45
- }
46
-
47
- /**
48
- * Create a standardized error result
49
- */
50
- export function createErrorResult(
51
- error: string | Error,
52
- metadata?: Record<string, unknown>
53
- ): HandlerResult<never> {
54
- const errorMessage = error instanceof Error ? error.message : error;
55
-
56
- return {
57
- success: false,
58
- error: errorMessage,
59
- metadata,
60
- };
61
- }
62
-
63
- /**
64
- * Safely execute an async operation and return a HandlerResult
65
- * This provides consistent error handling across all handlers
66
- */
67
- export async function safeExecute<T>(
68
- operation: () => Promise<T>,
69
- errorContext?: string
70
- ): Promise<HandlerResult<T>> {
71
- try {
72
- const result = await operation();
73
- return createSuccessResult(result);
74
- } catch (error) {
75
- const errorMessage =
76
- error instanceof Error ? error.message : 'Unknown error';
77
- const contextualError = errorContext
78
- ? `${errorContext}: ${errorMessage}`
79
- : errorMessage;
80
-
81
- logger.error('Operation failed', error as Error, { errorContext });
82
- return createErrorResult(contextualError);
83
- }
84
- }
85
-
86
- /**
87
- * Validate required arguments for tool handlers
88
- * Throws an error if any required arguments are missing
89
- */
90
- export function validateRequiredArgs(
91
- args: unknown,
92
- requiredFields: string[]
93
- ): void {
94
- const missingFields = requiredFields.filter(
95
- field =>
96
- (args as Record<string, unknown>)[field] === undefined ||
97
- (args as Record<string, unknown>)[field] === null
98
- );
99
-
100
- if (missingFields.length > 0) {
101
- throw new Error(`Missing required arguments: ${missingFields.join(', ')}`);
102
- }
103
- }
104
-
105
- /**
106
- * Check if a conversation exists and provide helpful error if not
107
- */
108
- export function createConversationNotFoundResult(
109
- availableWorkflows: string[] = []
110
- ): HandlerResult<never> {
111
- if (availableWorkflows.length === 0) {
112
- return createErrorResult(
113
- 'No development conversation has been started for this project. Please call start_development() to begin. First, set up workflows by adjusting the VIBE_WORKFLOW_DOMAINS environment variable or copying a workflow to .vibe/workflows/ directory.',
114
- {
115
- suggestion:
116
- 'Set VIBE_WORKFLOW_DOMAINS=code,architecture,office or copy a workflow file to .vibe/workflows/',
117
- availableWorkflows: [],
118
- }
119
- );
120
- }
121
-
122
- return createErrorResult(
123
- 'No development conversation has been started for this project. Please call start_development() with a workflow parameter to begin development.',
124
- {
125
- suggestion: 'Call start_development() to begin',
126
- availableWorkflows,
127
- }
128
- );
129
- }
130
-
131
- /**
132
- * Extract workflow names for enum generation
133
- * Used by server configuration to build Zod schemas
134
- */
135
- export function buildWorkflowEnum(
136
- workflowNames: string[]
137
- ): [string, ...string[]] {
138
- const allWorkflows = [...workflowNames, 'custom'];
139
-
140
- // Ensure we have at least one element for TypeScript
141
- if (allWorkflows.length === 0) {
142
- return ['waterfall'];
143
- }
144
-
145
- return allWorkflows as [string, ...string[]];
146
- }
147
-
148
- /**
149
- * Generate workflow description for tool schemas
150
- */
151
- export function generateWorkflowDescription(
152
- workflows: Array<{
153
- name: string;
154
- displayName: string;
155
- description: string;
156
- metadata?: {
157
- complexity?: 'low' | 'medium' | 'high';
158
- bestFor?: string[];
159
- useCases?: string[];
160
- examples?: string[];
161
- };
162
- }>
163
- ): string {
164
- let description = 'Choose your development workflow:\n\n';
165
-
166
- for (const workflow of workflows) {
167
- description += `• **${workflow.name}**: ${workflow.displayName} - ${workflow.description}`;
168
-
169
- // Add enhanced metadata if available
170
- if (workflow.metadata) {
171
- const meta = workflow.metadata;
172
-
173
- // Add complexity
174
- if (meta.complexity) {
175
- description += `\n Complexity: ${meta.complexity}`;
176
- }
177
-
178
- // Add best for information
179
- if (meta.bestFor && meta.bestFor.length > 0) {
180
- description += `\n Best for: ${meta.bestFor.join(', ')}`;
181
- }
182
-
183
- // Add examples
184
- if (meta.examples && meta.examples.length > 0) {
185
- description += `\n Examples: ${meta.examples.slice(0, 2).join(', ')}`;
186
- if (meta.examples.length > 2) {
187
- description += `, and ${meta.examples.length - 2} more`;
188
- }
189
- }
190
- }
191
-
192
- description += '\n';
193
- }
194
-
195
- description +=
196
- '• **custom**: Use custom workflow from .vibe/workflows in your project\n\n';
197
-
198
- return description;
199
- }
200
-
201
- /**
202
- * Log handler execution for debugging
203
- */
204
- export function logHandlerExecution(handlerName: string, args: unknown): void {
205
- logger.debug(`Executing ${handlerName} handler`, {
206
- handlerName,
207
- argsKeys: Object.keys(args || {}),
208
- });
209
- }
210
-
211
- /**
212
- * Log handler completion for debugging
213
- */
214
- export function logHandlerCompletion(
215
- handlerName: string,
216
- result: HandlerResult<unknown>
217
- ): void {
218
- logger.debug(`Completed ${handlerName} handler`, {
219
- handlerName,
220
- success: result.success,
221
- hasData: !!result.data,
222
- hasError: !!result.error,
223
- });
224
- }
225
-
226
- /**
227
- * Strip /.vibe suffix from project path if present
228
- *
229
- * @param providedPath - Optional project path provided by user
230
- * @param defaultPath - Default project path from context
231
- * @returns Normalized project root path
232
- */
233
- export function stripVibePathSuffix(
234
- providedPath: string | undefined,
235
- defaultPath: string
236
- ): string {
237
- if (!providedPath) {
238
- return defaultPath;
239
- }
240
-
241
- // Strip /.vibe suffix if present to get project root
242
- return providedPath.endsWith('/.vibe')
243
- ? providedPath.slice(0, -6) // Remove '/.vibe'
244
- : providedPath;
245
- }
@@ -1,277 +0,0 @@
1
- /**
2
- * Refactored Vibe Feature MCP Server
3
- *
4
- * Main server orchestrator that brings together all the modular components.
5
- * This replaces the monolithic server.ts with a clean, modular architecture.
6
- */
7
-
8
- import { setMcpServerForLogging, createLogger } from '@codemcp/workflows-core';
9
- import { ServerConfig } from './types.js';
10
- import {
11
- initializeServerComponents,
12
- registerMcpTools,
13
- registerMcpResources,
14
- ServerComponents,
15
- } from './server-config.js';
16
- import { createToolRegistry } from './tool-handlers/index.js';
17
- import { createResourceRegistry } from './resource-handlers/index.js';
18
- import { createResponseRenderer } from './response-renderer.js';
19
- import type {
20
- ProceedToPhaseArgs,
21
- ProceedToPhaseResult,
22
- StartDevelopmentArgs,
23
- StartDevelopmentResult,
24
- ResumeWorkflowArgs,
25
- ResumeWorkflowResult,
26
- ResetDevelopmentArgs,
27
- ResetDevelopmentResult,
28
- } from './tool-handlers/index.js';
29
-
30
- const logger = createLogger('ResponsibleVibeMCPServer');
31
-
32
- /**
33
- * Factory function to create a server with real components
34
- */
35
- export async function createResponsibleVibeMCPServer(
36
- config: ServerConfig = {}
37
- ): Promise<ResponsibleVibeMCPServer> {
38
- const components = await initializeServerComponents(config);
39
- return new ResponsibleVibeMCPServer(config, components);
40
- }
41
-
42
- /**
43
- * Main server class that orchestrates all components
44
- * Can be used both as a standalone process and in-process for testing
45
- */
46
- export class ResponsibleVibeMCPServer {
47
- private components: ServerComponents | null = null;
48
-
49
- constructor(
50
- private config: ServerConfig,
51
- private serverComponents: ServerComponents
52
- ) {
53
- logger.debug('ResponsibleVibeMCPServer created', {
54
- config: JSON.stringify(this.config),
55
- });
56
- }
57
-
58
- /**
59
- * Initialize the server and all its components
60
- */
61
- async initialize(): Promise<void> {
62
- logger.debug('Initializing ResponsibleVibeMCPServer');
63
-
64
- try {
65
- // Use injected components
66
- this.components = this.serverComponents;
67
-
68
- // Create registries and renderer
69
- const toolRegistry = createToolRegistry();
70
- const resourceRegistry = createResourceRegistry();
71
- const responseRenderer = createResponseRenderer();
72
-
73
- // Update components with registries and renderer
74
- this.components.toolRegistry = toolRegistry;
75
- this.components.resourceRegistry = resourceRegistry;
76
- this.components.responseRenderer = responseRenderer;
77
-
78
- // Register MCP server for logging notifications
79
- setMcpServerForLogging(this.components.mcpServer);
80
-
81
- // Register tools and resources with MCP server
82
- await registerMcpTools(
83
- this.components.mcpServer,
84
- toolRegistry,
85
- responseRenderer,
86
- this.components.context
87
- );
88
-
89
- registerMcpResources(
90
- this.components.mcpServer,
91
- resourceRegistry,
92
- responseRenderer,
93
- this.components.context
94
- );
95
- } catch (error) {
96
- logger.error(
97
- 'Failed to initialize ResponsibleVibeMCPServer',
98
- error as Error
99
- );
100
- throw error;
101
- }
102
- }
103
-
104
- /**
105
- * Get the underlying MCP server instance
106
- * This allows for both transport-based and direct testing
107
- */
108
- public getMcpServer() {
109
- if (!this.components) {
110
- throw new Error('Server not initialized. Call initialize() first.');
111
- }
112
- return this.components.mcpServer;
113
- }
114
-
115
- /**
116
- * Get project path
117
- */
118
- public getProjectPath(): string {
119
- if (!this.components) {
120
- throw new Error('Server not initialized. Call initialize() first.');
121
- }
122
- return this.components.context.projectPath;
123
- }
124
-
125
- /**
126
- * Get conversation manager (for testing)
127
- */
128
- public getConversationManager() {
129
- if (!this.components) {
130
- throw new Error('Server not initialized. Call initialize() first.');
131
- }
132
- return this.components.context.conversationManager;
133
- }
134
-
135
- /**
136
- * Get plan manager (for testing)
137
- */
138
- public getPlanManager() {
139
- if (!this.components) {
140
- throw new Error('Server not initialized. Call initialize() first.');
141
- }
142
- return this.components.context.planManager;
143
- }
144
-
145
- /**
146
- * Direct access to tool handlers for testing
147
- */
148
- public async handleWhatsNext(args: unknown): Promise<unknown> {
149
- if (!this.components) {
150
- throw new Error('Server not initialized. Call initialize() first.');
151
- }
152
-
153
- const handler = this.components.toolRegistry.get('whats_next');
154
- if (!handler) {
155
- throw new Error('whats_next handler not found');
156
- }
157
-
158
- const result = await handler.handle(args, this.components.context);
159
- if (!result.success) {
160
- throw new Error(result.error || 'Handler execution failed');
161
- }
162
-
163
- return result.data;
164
- }
165
-
166
- /**
167
- * Direct access to tool handlers for testing
168
- */
169
- public async handleProceedToPhase(
170
- args: ProceedToPhaseArgs
171
- ): Promise<ProceedToPhaseResult> {
172
- if (!this.components) {
173
- throw new Error('Server not initialized. Call initialize() first.');
174
- }
175
-
176
- const handler = this.components.toolRegistry.get('proceed_to_phase');
177
- if (!handler) {
178
- throw new Error('proceed_to_phase handler not found');
179
- }
180
-
181
- const result = await handler.handle(args, this.components.context);
182
- if (!result.success) {
183
- throw new Error(result.error || 'Handler execution failed');
184
- }
185
-
186
- return result.data as ProceedToPhaseResult;
187
- }
188
-
189
- /**
190
- * Direct access to tool handlers for testing
191
- */
192
- public async handleStartDevelopment(
193
- args: StartDevelopmentArgs
194
- ): Promise<StartDevelopmentResult> {
195
- if (!this.components) {
196
- throw new Error('Server not initialized. Call initialize() first.');
197
- }
198
-
199
- const handler = this.components.toolRegistry.get('start_development');
200
- if (!handler) {
201
- throw new Error('start_development handler not found');
202
- }
203
-
204
- const result = await handler.handle(args, this.components.context);
205
- if (!result.success) {
206
- throw new Error(result.error || 'Handler execution failed');
207
- }
208
-
209
- return result.data as StartDevelopmentResult;
210
- }
211
-
212
- /**
213
- * Direct access to tool handlers for testing
214
- */
215
- public async handleResumeWorkflow(
216
- args: ResumeWorkflowArgs
217
- ): Promise<ResumeWorkflowResult> {
218
- if (!this.components) {
219
- throw new Error('Server not initialized. Call initialize() first.');
220
- }
221
-
222
- const handler = this.components.toolRegistry.get('resume_workflow');
223
- if (!handler) {
224
- throw new Error('resume_workflow handler not found');
225
- }
226
-
227
- const result = await handler.handle(args, this.components.context);
228
- if (!result.success) {
229
- throw new Error(result.error || 'Handler execution failed');
230
- }
231
-
232
- return result.data as ResumeWorkflowResult;
233
- }
234
-
235
- /**
236
- * Direct access to tool handlers for testing
237
- */
238
- public async handleResetDevelopment(
239
- args: ResetDevelopmentArgs
240
- ): Promise<ResetDevelopmentResult> {
241
- if (!this.components) {
242
- throw new Error('Server not initialized. Call initialize() first.');
243
- }
244
-
245
- const handler = this.components.toolRegistry.get('reset_development');
246
- if (!handler) {
247
- throw new Error('reset_development handler not found');
248
- }
249
-
250
- const result = await handler.handle(args, this.components.context);
251
- if (!result.success) {
252
- throw new Error(result.error || 'Handler execution failed');
253
- }
254
-
255
- return result.data as ResetDevelopmentResult;
256
- }
257
-
258
- /**
259
- * Cleanup server resources
260
- */
261
- public async cleanup(): Promise<void> {
262
- logger.debug('Cleaning up server resources');
263
-
264
- if (this.components?.database) {
265
- await this.components.database.close();
266
- }
267
-
268
- logger.info('Server cleanup completed');
269
- }
270
- }
271
-
272
- // Export all types and utilities for external use
273
- export * from './types.js';
274
- export * from './server-helpers.js';
275
- export * from './response-renderer.js';
276
- export * from './tool-handlers/index.js';
277
- export * from './resource-handlers/index.js';
package/src/server.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * Vibe Feature MCP Server Core
3
- */
4
-
5
- export {
6
- ResponsibleVibeMCPServer,
7
- createResponsibleVibeMCPServer,
8
- } from './server-implementation.js';
9
- export type { ServerConfig } from './types.js';
@@ -1,151 +0,0 @@
1
- /**
2
- * Base Tool Handler
3
- *
4
- * Provides common functionality for all tool handlers including
5
- * error handling, logging, and conversation state management.
6
- */
7
-
8
- import { createLogger } from '@codemcp/workflows-core';
9
- import { ToolHandler, ServerContext, HandlerResult } from '../types.js';
10
- import type { ConversationContext } from '@codemcp/workflows-core';
11
- import {
12
- safeExecute,
13
- logHandlerExecution,
14
- logHandlerCompletion,
15
- createConversationNotFoundResult,
16
- } from '../server-helpers.js';
17
-
18
- /**
19
- * Abstract base class for tool handlers
20
- * Provides common functionality and enforces consistent patterns
21
- */
22
- export abstract class BaseToolHandler<
23
- TArgs = unknown,
24
- TResult = unknown,
25
- > implements ToolHandler<TArgs, TResult> {
26
- protected readonly logger: ReturnType<typeof createLogger>;
27
-
28
- constructor() {
29
- this.logger = createLogger(this.constructor.name);
30
- }
31
-
32
- /**
33
- * Main handler method - implements consistent error handling and logging
34
- */
35
- async handle(
36
- args: TArgs,
37
- context: ServerContext
38
- ): Promise<HandlerResult<TResult>> {
39
- const handlerName = this.constructor.name;
40
- logHandlerExecution(handlerName, args);
41
-
42
- const result = await safeExecute(
43
- () => this.executeHandler(args, context),
44
- `${handlerName} execution failed`
45
- );
46
-
47
- // Check if this is a CONVERSATION_NOT_FOUND error and provide helpful guidance
48
- if (!result.success && result.error?.includes('CONVERSATION_NOT_FOUND')) {
49
- const availableWorkflows = context.workflowManager.getWorkflowNames();
50
- const helpfulError = createConversationNotFoundResult(availableWorkflows);
51
- logHandlerCompletion(handlerName, helpfulError);
52
- return helpfulError as HandlerResult<TResult>;
53
- }
54
-
55
- logHandlerCompletion(handlerName, result);
56
- return result;
57
- }
58
-
59
- /**
60
- * Abstract method that subclasses must implement
61
- * Contains the actual business logic for the tool
62
- */
63
- protected abstract executeHandler(
64
- args: TArgs,
65
- context: ServerContext
66
- ): Promise<TResult>;
67
-
68
- /**
69
- * Helper method to get conversation context with proper error handling
70
- */
71
- protected async getConversationContext(context: ServerContext) {
72
- try {
73
- return await context.conversationManager.getConversationContext();
74
- } catch (error) {
75
- this.logger.info('Conversation not found', { error });
76
- throw new Error('CONVERSATION_NOT_FOUND');
77
- }
78
- }
79
-
80
- /**
81
- * Helper method to ensure state machine is loaded for a project
82
- */
83
- protected ensureStateMachineForProject(
84
- context: ServerContext,
85
- projectPath: string,
86
- workflowName?: string
87
- ): void {
88
- const stateMachine = context.transitionEngine.getStateMachine(
89
- projectPath,
90
- workflowName
91
- );
92
- context.planManager.setStateMachine(stateMachine);
93
- context.instructionGenerator.setStateMachine(stateMachine);
94
- }
95
-
96
- /**
97
- * Helper method to log interactions if logger is available
98
- */
99
- protected async logInteraction(
100
- context: ServerContext,
101
- conversationId: string,
102
- toolName: string,
103
- args: unknown,
104
- response: unknown,
105
- phase: string
106
- ): Promise<void> {
107
- if (context.interactionLogger) {
108
- await context.interactionLogger.logInteraction(
109
- conversationId,
110
- toolName,
111
- args,
112
- response,
113
- phase
114
- );
115
- }
116
- }
117
- }
118
-
119
- /**
120
- * Base class for tool handlers that require an existing conversation
121
- * Automatically handles the conversation-not-found case
122
- */
123
- export abstract class ConversationRequiredToolHandler<
124
- TArgs = unknown,
125
- TResult = unknown,
126
- > extends BaseToolHandler<TArgs, TResult> {
127
- protected async executeHandler(
128
- args: TArgs,
129
- context: ServerContext
130
- ): Promise<TResult> {
131
- let conversationContext;
132
-
133
- try {
134
- conversationContext = await this.getConversationContext(context);
135
- } catch (_error) {
136
- // Return a special error result that the response renderer can handle
137
- throw new Error('CONVERSATION_NOT_FOUND');
138
- }
139
-
140
- return this.executeWithConversation(args, context, conversationContext);
141
- }
142
-
143
- /**
144
- * Abstract method for handlers that need conversation context
145
- */
146
- protected abstract executeWithConversation(
147
- args: TArgs,
148
- context: ServerContext,
149
- conversationContext: ConversationContext
150
- ): Promise<TResult>;
151
- }