evaluate.ts•4.59 kB
import { z } from 'zod';
import { Logger } from '../server/logger';
import { MetricsCollector } from '../server/metrics';
import { DapEvaluateRequest } from '../schemas/dap-tools.schemas';
/**
* dap.evaluate tool implementation
*
* Evaluates expressions in the debugging context
*/
export class DapEvaluateTool {
private logger: Logger;
private metrics: MetricsCollector;
constructor() {
this.logger = new Logger('dap.evaluate');
this.metrics = MetricsCollector.getInstance();
}
/**
* Execute the dap.evaluate tool
*/
async execute(args: any): Promise<any> {
this.metrics.startTimer('dap.evaluate.tool');
this.metrics.increment('dap.evaluate.count');
try {
// Validate input
const validatedArgs = this.validateArgs(args);
this.logger.debug('Evaluating expression', {
expression: validatedArgs.expression,
frameId: validatedArgs.frameId,
context: validatedArgs.context,
});
// Evaluate expression in debugging context
const result = await this.evaluateExpression(validatedArgs);
this.logger.info('Expression evaluated', {
expression: validatedArgs.expression,
result: result.result,
});
this.metrics.stopTimer('dap.evaluate.tool');
return this.createSuccessResponse(result);
} catch (error) {
this.logger.error('dap.evaluate failed:', error);
this.metrics.increment('dap.evaluate.error.count');
this.metrics.stopTimer('dap.evaluate.tool');
return this.createErrorResponse((error as Error).message);
}
}
/**
* Validate input arguments
*/
private validateArgs(args: any): DapEvaluateRequest['arguments'] {
const schema = z.object({
expression: z.string(),
frameId: z.number().optional(),
context: z.enum(['hover', 'watch', 'repl', 'clipboard']).optional().default('repl'),
});
const parsed = schema.parse(args);
return {
...parsed,
__type__: 'EvaluateArguments' as const,
};
}
/**
* Evaluate expression in debugging context
*/
private async evaluateExpression(args: DapEvaluateRequest['arguments']) {
// Mock implementation - in real implementation this would evaluate in the debugging adapter
const expression = args.expression.trim();
let result = '';
let type = '';
let variablesReference = 0;
let presentationHint = undefined;
// Simple expression evaluation for demo
if (expression === '1 + 1') {
result = '2';
type = 'Number';
} else if (expression === '"hello".length') {
result = '5';
type = 'Number';
} else if (expression === 'Math.random()') {
result = Math.random().toString();
type = 'Number';
} else if (expression === '[1, 2, 3].length') {
result = '3';
type = 'Number';
} else if (expression.startsWith('JSON.stringify')) {
try {
const match = expression.match(/JSON\.stringify\((.*)\)/);
if (match && match[1]) {
const obj = JSON.parse(match[1]);
result = JSON.stringify(obj, null, 2);
type = 'String';
}
} catch (e) {
result = 'Invalid JSON';
type = 'Error';
}
} else if (expression.includes('.')) {
// Mock object property access
result = `[Object: ${expression}]`;
type = 'Object';
variablesReference = 1;
presentationHint = { kind: 'class' };
} else {
result = `Reference to '${expression}'`;
type = 'Reference';
variablesReference = 1;
presentationHint = { kind: 'property' };
}
return {
result,
type,
variablesReference,
presentationHint,
indexedVariables: 0,
namedVariables: 0,
};
}
/**
* Create success response
*/
private createSuccessResponse(body: any): any {
return {
type: 'response',
seq: 1,
command: 'evaluate',
request_seq: 1,
success: true,
body,
};
}
/**
* Create error response
*/
private createErrorResponse(message: string): any {
return {
type: 'response',
seq: 1,
command: 'evaluate',
request_seq: 1,
success: false,
message,
body: {
error: 'Failed to evaluate expression',
format: `{message}`,
showUser: true,
},
};
}
}
// Singleton instance
export const dapEvaluateTool = new DapEvaluateTool();
// Tool execution function
export async function executeDapEvaluate(args: any): Promise<any> {
return await dapEvaluateTool.execute(args);
}