@@ -13,6 +13,7 @@ import { existsSync, readdirSync, mkdirSync } from 'fs';
13
13
import { spawn } from 'child_process' ;
14
14
import { promisify } from 'util' ;
15
15
import { exec } from 'child_process' ;
16
+ import * as fs from 'fs' ; // Import the 'fs' module
16
17
17
18
import { Server } from '@modelcontextprotocol/sdk/server/index.js' ;
18
19
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' ;
@@ -1010,31 +1011,44 @@ class GodotServer {
1010
1011
commandArgs . push ( '--debug' ) ;
1011
1012
}
1012
1013
1014
+ // Define the log file path within the project directory
1015
+ const logFilePath = join ( args . projectPath , 'cline_godot_run.log' ) ;
1016
+ // Add the --log-file argument for Godot
1017
+ commandArgs . push ( '--log-file' , logFilePath ) ;
1018
+ this . logDebug ( `Using Godot's --log-file argument: ${ logFilePath } ` ) ;
1019
+
1020
+
1013
1021
this . logDebug ( `Spawning Godot project: "${ this . godotPath } " with args: ${ commandArgs . join ( ' ' ) } ` ) ;
1014
1022
1015
1023
try {
1016
- // Use spawn to manage the running process and capture output
1017
- const godotProcess = spawn ( `"${ this . godotPath } "` , commandArgs , {
1018
- shell : true , // Using shell might be necessary depending on how GODOT_PATH is set
1019
- stdio : [ 'ignore' , 'pipe' , 'pipe' ] , // Ignore stdin, capture stdout/stderr
1024
+ // Use spawn, revert stdio back to pipes to capture potential early launch errors
1025
+ const godotProcess = spawn ( this . godotPath , commandArgs , {
1026
+ shell : false , // Keep shell false
1027
+ detached : false , // Keep attached to monitor exit/errors more easily initially
1028
+ stdio : [ 'ignore' , 'pipe' , 'pipe' ] , // Ignore stdin, capture stdout/stderr via pipes
1020
1029
} ) ;
1021
1030
1031
+ // No need to unref if not detached
1032
+
1022
1033
this . activeProcess = {
1023
1034
process : godotProcess ,
1024
- output : [ ] ,
1025
- errors : [ ] ,
1035
+ output : [ ] , // Capture output via pipes again
1036
+ errors : [ ] , // Capture errors via pipes again
1026
1037
} ;
1027
1038
1039
+ // Capture piped output/error
1028
1040
godotProcess . stdout . on ( 'data' , ( data ) => {
1029
1041
const output = data . toString ( ) ;
1030
1042
this . activeProcess ?. output . push ( output ) ;
1031
- this . logDebug ( `Project stdout: ${ output } ` ) ;
1043
+ // Optionally log to server console, but primary log is the file
1044
+ // this.logDebug(`Project stdout pipe: ${output}`);
1032
1045
} ) ;
1033
1046
1034
1047
godotProcess . stderr . on ( 'data' , ( data ) => {
1035
1048
const errorOutput = data . toString ( ) ;
1036
1049
this . activeProcess ?. errors . push ( errorOutput ) ;
1037
- console . error ( `Project stderr: ${ errorOutput } ` ) ;
1050
+ // Log stderr immediately to server console for visibility
1051
+ console . error ( `Project stderr pipe: ${ errorOutput } ` ) ;
1038
1052
} ) ;
1039
1053
1040
1054
godotProcess . on ( 'close' , ( code ) => {
@@ -1062,21 +1076,36 @@ class GodotServer {
1062
1076
/**
1063
1077
* Handle the get_debug_output tool
1064
1078
*/
1065
- private async handleGetDebugOutput ( ) {
1066
- this . logDebug ( 'Handling get_debug_output' ) ;
1067
- if ( this . activeProcess ) {
1068
- // Return copies of the arrays
1069
- return {
1070
- content : [
1071
- { type : 'text' , text : `Output lines: ${ this . activeProcess . output . length } , Error lines: ${ this . activeProcess . errors . length } ` }
1072
- ] ,
1073
- output : [ ...this . activeProcess . output ] ,
1074
- errors : [ ...this . activeProcess . errors ]
1075
- } ;
1076
- } else {
1077
- return this . createErrorResponse ( 'No active Godot project is running.' ) ;
1078
- }
1079
- }
1079
+ private async handleGetDebugOutput ( ) {
1080
+ this . logDebug ( 'Handling get_debug_output' ) ;
1081
+ if ( this . activeProcess ) {
1082
+ // Limit the number of error lines returned
1083
+ const maxErrorLines = 100 ; // Keep the last 100 error lines
1084
+ const totalErrorLines = this . activeProcess . errors . length ;
1085
+ const recentErrors = this . activeProcess . errors . slice ( - maxErrorLines ) ;
1086
+ const recentErrorsText = recentErrors . join ( '\n' ) ;
1087
+
1088
+ let responseText = `--- Recent Errors (${ Math . min ( maxErrorLines , totalErrorLines ) } /${ totalErrorLines } lines shown) ---\n` ;
1089
+ responseText += recentErrorsText || '(No recent errors)' ;
1090
+
1091
+ // Also include total output line count for context
1092
+ const totalOutputLines = this . activeProcess . output . length ;
1093
+ responseText += `\n(Total output lines: ${ totalOutputLines } )` ;
1094
+
1095
+
1096
+ return {
1097
+ content : [
1098
+ { type : 'text' , text : responseText }
1099
+ ] ,
1100
+ // Return only the sliced recent errors and a limited amount of recent output for context if needed
1101
+ // For now, let's keep the full arrays but the primary content is limited
1102
+ output : [ ...this . activeProcess . output ] , // Keep full output array for now
1103
+ errors : [ ...this . activeProcess . errors ] // Keep full error array for now
1104
+ } ;
1105
+ } else {
1106
+ return this . createErrorResponse ( 'No active Godot project is running.' ) ;
1107
+ }
1108
+ }
1080
1109
1081
1110
/**
1082
1111
* Handle the stop_project tool
0 commit comments