初次提交
This commit is contained in:
351
source/tools/debug-tools.ts
Normal file
351
source/tools/debug-tools.ts
Normal file
@@ -0,0 +1,351 @@
|
||||
import { ToolDefinition, ToolResponse, ToolExecutor, ConsoleMessage, PerformanceStats, ValidationResult, ValidationIssue } from '../types';
|
||||
|
||||
export class DebugTools implements ToolExecutor {
|
||||
private consoleMessages: ConsoleMessage[] = [];
|
||||
private readonly maxMessages = 1000;
|
||||
|
||||
constructor() {
|
||||
this.setupConsoleCapture();
|
||||
}
|
||||
|
||||
private setupConsoleCapture(): void {
|
||||
// Intercept Editor console messages
|
||||
// Note: Editor.Message.addBroadcastListener may not be available in all versions
|
||||
// This is a placeholder for console capture implementation
|
||||
console.log('Console capture setup - implementation depends on Editor API availability');
|
||||
}
|
||||
|
||||
private addConsoleMessage(message: any): void {
|
||||
this.consoleMessages.push({
|
||||
timestamp: new Date().toISOString(),
|
||||
...message
|
||||
});
|
||||
|
||||
// Keep only latest messages
|
||||
if (this.consoleMessages.length > this.maxMessages) {
|
||||
this.consoleMessages.shift();
|
||||
}
|
||||
}
|
||||
|
||||
getTools(): ToolDefinition[] {
|
||||
return [
|
||||
{
|
||||
name: 'get_console_logs',
|
||||
description: 'Get editor console logs',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Number of recent logs to retrieve',
|
||||
default: 100
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
description: 'Filter logs by type',
|
||||
enum: ['all', 'log', 'warn', 'error', 'info'],
|
||||
default: 'all'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'clear_console',
|
||||
description: 'Clear editor console',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'execute_script',
|
||||
description: 'Execute JavaScript in scene context',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
script: {
|
||||
type: 'string',
|
||||
description: 'JavaScript code to execute'
|
||||
}
|
||||
},
|
||||
required: ['script']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'get_node_tree',
|
||||
description: 'Get detailed node tree for debugging',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
rootUuid: {
|
||||
type: 'string',
|
||||
description: 'Root node UUID (optional, uses scene root if not provided)'
|
||||
},
|
||||
maxDepth: {
|
||||
type: 'number',
|
||||
description: 'Maximum tree depth',
|
||||
default: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'get_performance_stats',
|
||||
description: 'Get performance statistics',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'validate_scene',
|
||||
description: 'Validate current scene for issues',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
checkMissingAssets: {
|
||||
type: 'boolean',
|
||||
description: 'Check for missing asset references',
|
||||
default: true
|
||||
},
|
||||
checkPerformance: {
|
||||
type: 'boolean',
|
||||
description: 'Check for performance issues',
|
||||
default: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'get_editor_info',
|
||||
description: 'Get editor and environment information',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
async execute(toolName: string, args: any): Promise<ToolResponse> {
|
||||
switch (toolName) {
|
||||
case 'get_console_logs':
|
||||
return await this.getConsoleLogs(args.limit, args.filter);
|
||||
case 'clear_console':
|
||||
return await this.clearConsole();
|
||||
case 'execute_script':
|
||||
return await this.executeScript(args.script);
|
||||
case 'get_node_tree':
|
||||
return await this.getNodeTree(args.rootUuid, args.maxDepth);
|
||||
case 'get_performance_stats':
|
||||
return await this.getPerformanceStats();
|
||||
case 'validate_scene':
|
||||
return await this.validateScene(args);
|
||||
case 'get_editor_info':
|
||||
return await this.getEditorInfo();
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${toolName}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async getConsoleLogs(limit: number = 100, filter: string = 'all'): Promise<ToolResponse> {
|
||||
let logs = this.consoleMessages;
|
||||
|
||||
if (filter !== 'all') {
|
||||
logs = logs.filter(log => log.type === filter);
|
||||
}
|
||||
|
||||
const recentLogs = logs.slice(-limit);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
total: logs.length,
|
||||
returned: recentLogs.length,
|
||||
logs: recentLogs
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async clearConsole(): Promise<ToolResponse> {
|
||||
this.consoleMessages = [];
|
||||
|
||||
try {
|
||||
// Note: Editor.Message.send may not return a promise in all versions
|
||||
Editor.Message.send('console', 'clear');
|
||||
return {
|
||||
success: true,
|
||||
message: 'Console cleared successfully'
|
||||
};
|
||||
} catch (err: any) {
|
||||
return { success: false, error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
private async executeScript(script: string): Promise<ToolResponse> {
|
||||
return new Promise((resolve) => {
|
||||
Editor.Message.request('scene', 'execute-script', {
|
||||
script: script
|
||||
}).then((result: any) => {
|
||||
resolve({
|
||||
success: true,
|
||||
data: {
|
||||
result: result,
|
||||
message: 'Script executed successfully'
|
||||
}
|
||||
});
|
||||
}).catch((err: Error) => {
|
||||
resolve({ success: false, error: err.message });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async getNodeTree(rootUuid?: string, maxDepth: number = 10): Promise<ToolResponse> {
|
||||
return new Promise((resolve) => {
|
||||
const buildTree = async (nodeUuid: string, depth: number = 0): Promise<any> => {
|
||||
if (depth >= maxDepth) {
|
||||
return { truncated: true };
|
||||
}
|
||||
|
||||
try {
|
||||
const nodeData = await Editor.Message.request('scene', 'query-node', nodeUuid);
|
||||
|
||||
const tree = {
|
||||
uuid: nodeData.uuid,
|
||||
name: nodeData.name,
|
||||
active: nodeData.active,
|
||||
components: (nodeData as any).components ? (nodeData as any).components.map((c: any) => c.__type__) : [],
|
||||
childCount: nodeData.children ? nodeData.children.length : 0,
|
||||
children: [] as any[]
|
||||
};
|
||||
|
||||
if (nodeData.children && nodeData.children.length > 0) {
|
||||
for (const childId of nodeData.children) {
|
||||
const childTree = await buildTree(childId, depth + 1);
|
||||
tree.children.push(childTree);
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
} catch (err: any) {
|
||||
return { error: err.message };
|
||||
}
|
||||
};
|
||||
|
||||
if (rootUuid) {
|
||||
buildTree(rootUuid).then(tree => {
|
||||
resolve({ success: true, data: tree });
|
||||
});
|
||||
} else {
|
||||
Editor.Message.request('scene', 'query-hierarchy').then(async (hierarchy: any) => {
|
||||
const trees = [];
|
||||
for (const rootNode of hierarchy.children) {
|
||||
const tree = await buildTree(rootNode.uuid);
|
||||
trees.push(tree);
|
||||
}
|
||||
resolve({ success: true, data: trees });
|
||||
}).catch((err: Error) => {
|
||||
resolve({ success: false, error: err.message });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getPerformanceStats(): Promise<ToolResponse> {
|
||||
return new Promise((resolve) => {
|
||||
Editor.Message.request('scene', 'query-performance').then((stats: any) => {
|
||||
const perfStats: PerformanceStats = {
|
||||
nodeCount: stats.nodeCount || 0,
|
||||
componentCount: stats.componentCount || 0,
|
||||
drawCalls: stats.drawCalls || 0,
|
||||
triangles: stats.triangles || 0,
|
||||
memory: stats.memory || {}
|
||||
};
|
||||
resolve({ success: true, data: perfStats });
|
||||
}).catch(() => {
|
||||
// Fallback to basic stats
|
||||
resolve({
|
||||
success: true,
|
||||
data: {
|
||||
message: 'Performance stats not available in edit mode'
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async validateScene(options: any): Promise<ToolResponse> {
|
||||
const issues: ValidationIssue[] = [];
|
||||
|
||||
try {
|
||||
// Check for missing assets
|
||||
if (options.checkMissingAssets) {
|
||||
const assetCheck = await Editor.Message.request('scene', 'check-missing-assets');
|
||||
if (assetCheck && assetCheck.missing) {
|
||||
issues.push({
|
||||
type: 'error',
|
||||
category: 'assets',
|
||||
message: `Found ${assetCheck.missing.length} missing asset references`,
|
||||
details: assetCheck.missing
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check for performance issues
|
||||
if (options.checkPerformance) {
|
||||
const hierarchy = await Editor.Message.request('scene', 'query-hierarchy');
|
||||
const nodeCount = this.countNodes(hierarchy.children);
|
||||
|
||||
if (nodeCount > 1000) {
|
||||
issues.push({
|
||||
type: 'warning',
|
||||
category: 'performance',
|
||||
message: `High node count: ${nodeCount} nodes (recommended < 1000)`,
|
||||
suggestion: 'Consider using object pooling or scene optimization'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const result: ValidationResult = {
|
||||
valid: issues.length === 0,
|
||||
issueCount: issues.length,
|
||||
issues: issues
|
||||
};
|
||||
|
||||
return { success: true, data: result };
|
||||
} catch (err: any) {
|
||||
return { success: false, error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
private countNodes(nodes: any[]): number {
|
||||
let count = nodes.length;
|
||||
for (const node of nodes) {
|
||||
if (node.children) {
|
||||
count += this.countNodes(node.children);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private async getEditorInfo(): Promise<ToolResponse> {
|
||||
const info = {
|
||||
editor: {
|
||||
version: (Editor as any).versions?.editor || 'Unknown',
|
||||
cocosVersion: (Editor as any).versions?.cocos || 'Unknown',
|
||||
platform: process.platform,
|
||||
arch: process.arch,
|
||||
nodeVersion: process.version
|
||||
},
|
||||
project: {
|
||||
name: Editor.Project.name,
|
||||
path: Editor.Project.path,
|
||||
uuid: Editor.Project.uuid
|
||||
},
|
||||
memory: process.memoryUsage(),
|
||||
uptime: process.uptime()
|
||||
};
|
||||
|
||||
return { success: true, data: info };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user