harvesthealth commited on
Commit
4a597ee
·
verified ·
1 Parent(s): 6ebb297

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -50
app.py CHANGED
@@ -3,8 +3,11 @@ import os
3
  import logging
4
  from fastapi import FastAPI, Request, Response
5
 
6
- # Set up logging
7
- logging.basicConfig(level=logging.DEBUG)
 
 
 
8
  logger = logging.getLogger(__name__)
9
 
10
  app = FastAPI()
@@ -13,6 +16,7 @@ proc = None
13
  @app.on_event("startup")
14
  async def startup_event():
15
  global proc
 
16
  # Get the token from an environment variable on the Hugging Face Space
17
  # This is a more secure way to handle the token
18
  token = os.environ.get("GITHUB_PERSONAL_ACCESS_TOKEN")
@@ -38,6 +42,7 @@ async def startup_event():
38
  else:
39
  logger.warning("Subprocess may have exited immediately with code: %s", proc.returncode)
40
  asyncio.create_task(log_stderr())
 
41
  except Exception as e:
42
  logger.error("Failed to create subprocess: %s", str(e))
43
  raise
@@ -45,8 +50,11 @@ async def startup_event():
45
  async def log_stderr():
46
  if proc and proc.stderr:
47
  logger.info("Starting stderr logging task")
48
- while not proc.stderr.at_eof():
49
- try:
 
 
 
50
  line = await proc.stderr.readline()
51
  if line:
52
  logger.debug("github-mcp-server stderr: %s", line.decode().strip())
@@ -58,86 +66,137 @@ async def log_stderr():
58
 
59
  @app.post("/")
60
  async def proxy(request: Request):
 
 
 
 
61
  if not proc or not proc.stdin or not proc.stdout:
62
- logger.error("Subprocess not running")
63
  return Response(status_code=500, content="Subprocess not running")
64
 
65
  # Log incoming request
66
  body = await request.body()
67
- logger.info("Received request: %s", body.decode())
68
-
69
  # Token verification for debugging
70
  import requests
71
-
72
  token = os.environ.get("GITHUB_PERSONAL_ACCESS_TOKEN")
73
  if token:
74
  try:
 
75
  response = requests.get("https://api.github.com/user", headers={"Authorization": f"token {token}"})
 
76
  if response.status_code == 200:
77
  logger.info("GitHub token verification successful")
78
  else:
79
  logger.error("GitHub token verification failed with status code: %s", response.status_code)
80
  except Exception as e:
81
  logger.error("Error verifying GitHub token: %s", str(e))
82
-
 
83
 
84
  # Send to subprocess
85
- logger.info("Sending to subprocess...")
86
- proc.stdin.write(body)
87
- await proc.stdin.drain()
 
 
 
 
 
88
 
89
- # Read response
 
90
  response = bytearray()
91
- logger.info("Reading response...")
92
- while True:
93
- try:
94
- chunk = await proc.stdout.read(1024)
95
- if not chunk:
96
- logger.info("EOF reached")
 
 
 
 
97
  break
98
- response.extend(chunk)
99
- logger.debug("Received chunk: %s", chunk)
100
- # Check if we have a complete JSON message
101
  try:
102
- response_str = bytes(response).decode("utf-8")
103
- logger.debug("Decoded response: %s", response_str)
104
- # More robust JSON-RPC detection
105
- # Check if we have a complete JSON object
106
- if len(response_str.strip()) > 0:
107
- # Try to parse as JSON
108
- import json
109
- try:
110
- json_data = json.loads(response_str)
111
- # Check if it's a valid JSON-RPC response
112
- if isinstance(json_data, dict) and "jsonrpc" in json_data:
113
- # Check if it's a response (has id or error)
114
- if "id" in json_data or "error" in json_data:
115
- logger.info("Complete JSON-RPC response detected")
116
- break
117
- except json.JSONDecodeError as e:
118
- # If JSON parsing fails, continue reading
119
- logger.debug("JSON parsing failed: %s", str(e))
120
- # Continue reading
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  continue
122
- else:
123
- # Empty response, continue reading
 
124
  continue
125
- except Exception as e:
126
- logger.warning("Decoding failed: %s", str(e))
127
- # Continue reading
128
  continue
129
- except Exception as e:
130
- logger.error("Error reading response: %s", str(e))
131
- break
 
 
 
 
132
 
133
  # Log final response
134
- logger.info("Final response: %s", bytes(response).decode())
 
 
 
 
 
 
 
 
 
 
135
  return Response(content=bytes(response))
136
 
137
  @app.on_event("shutdown")
138
  async def shutdown_event():
 
139
  if proc:
140
  logger.info("Shutting down subprocess...")
141
  proc.kill()
142
  await proc.wait()
143
  logger.info("Subprocess shut down")
 
 
3
  import logging
4
  from fastapi import FastAPI, Request, Response
5
 
6
+ # Set up logging with more detailed configuration
7
+ logging.basicConfig(
8
+ level=logging.DEBUG,
9
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
10
+ )
11
  logger = logging.getLogger(__name__)
12
 
13
  app = FastAPI()
 
16
  @app.on_event("startup")
17
  async def startup_event():
18
  global proc
19
+ logger.info("=== STARTUP EVENT ===")
20
  # Get the token from an environment variable on the Hugging Face Space
21
  # This is a more secure way to handle the token
22
  token = os.environ.get("GITHUB_PERSONAL_ACCESS_TOKEN")
 
42
  else:
43
  logger.warning("Subprocess may have exited immediately with code: %s", proc.returncode)
44
  asyncio.create_task(log_stderr())
45
+ logger.info("=== STARTUP COMPLETE ===")
46
  except Exception as e:
47
  logger.error("Failed to create subprocess: %s", str(e))
48
  raise
 
50
  async def log_stderr():
51
  if proc and proc.stderr:
52
  logger.info("Starting stderr logging task")
53
+ while
54
+
55
+ << 35 Characters hidden >>
56
+
57
+ try:
58
  line = await proc.stderr.readline()
59
  if line:
60
  logger.debug("github-mcp-server stderr: %s", line.decode().strip())
 
66
 
67
  @app.post("/")
68
  async def proxy(request: Request):
69
+ logger.info("=== NEW REQUEST RECEIVED ===")
70
+ logger.info("Request method: %s", request.method)
71
+ logger.info("Request headers: %s", dict(request.headers))
72
+
73
  if not proc or not proc.stdin or not proc.stdout:
74
+ logger.error("Subprocess not running - returning 500")
75
  return Response(status_code=500, content="Subprocess not running")
76
 
77
  # Log incoming request
78
  body = await request.body()
79
+ logger.info("Received request body: %s", body.decode())
80
+
81
  # Token verification for debugging
82
  import requests
 
83
  token = os.environ.get("GITHUB_PERSONAL_ACCESS_TOKEN")
84
  if token:
85
  try:
86
+ logger.info("Testing GitHub token with API call...")
87
  response = requests.get("https://api.github.com/user", headers={"Authorization": f"token {token}"})
88
+ logger.info("Token verification response status: %s", response.status_code)
89
  if response.status_code == 200:
90
  logger.info("GitHub token verification successful")
91
  else:
92
  logger.error("GitHub token verification failed with status code: %s", response.status_code)
93
  except Exception as e:
94
  logger.error("Error verifying GitHub token: %s", str(e))
95
+ else:
96
+ logger.warning("No GitHub token found in environment")
97
 
98
  # Send to subprocess
99
+ logger.info("Sending request to subprocess...")
100
+ try:
101
+ proc.stdin.write(body)
102
+ await proc.stdin.drain()
103
+ logger.info("Successfully wrote to subprocess stdin")
104
+ except Exception as e:
105
+ logger.error("Error writing to subprocess stdin: %s", str(e))
106
+ return Response(status_code=500, content=f"Error writing to subprocess: {str(e)}")
107
 
108
+ # Read response with timeout
109
+ logger.info("Reading response from subprocess with timeout...")
110
  response = bytearray()
111
+ try:
112
+ # Set a reasonable timeout (e.g., 30 seconds)
113
+ import asyncio
114
+ timeout_seconds = 30
115
+ start_time = asyncio.get_event_loop().time()
116
+
117
+ while True:
118
+ elapsed = asyncio.get_event_loop().time() - start_time
119
+ if elapsed > timeout_seconds:
120
+ logger.error("Timeout reading response from subprocess after %d seconds", timeout_seconds)
121
  break
122
+
 
 
123
  try:
124
+ chunk = await asyncio.wait_for(proc.stdout.read(1024), timeout=5.0)
125
+ logger.debug("Received chunk of size: %d", len(chunk))
126
+
127
+ if not chunk:
128
+ logger.info("EOF reached from subprocess")
129
+ break
130
+
131
+ response.extend(chunk)
132
+ logger.debug("Extended response with chunk, total size: %d", len(response))
133
+
134
+ # Check if we have a complete JSON message
135
+ try:
136
+ response_str = bytes(response).decode("utf-8")
137
+ logger.debug("Decoded response: %s", response_str[:200] + "..." if len(response_str) > 200 else response_str)
138
+
139
+ # More robust JSON-RPC detection
140
+ # Check if we have a complete JSON object
141
+ if len(response_str.strip()) > 0:
142
+ # Try to parse as JSON
143
+ import json
144
+ try:
145
+ json_data = json.loads(response_str)
146
+ # Check if it's a valid JSON-RPC response
147
+ if isinstance(json_data, dict) and "jsonrpc" in json_data:
148
+ # Check if it's a response (has id or error)
149
+ if "id" in json_data or "error" in json_data:
150
+ logger.info("Complete JSON-RPC response detected")
151
+ logger.info("Full response: %s", response_str)
152
+ break
153
+ else:
154
+ logger.debug("JSON-RPC response missing id or error field")
155
+ except json.JSONDecodeError as e:
156
+ # If JSON parsing fails, continue reading
157
+ logger.debug("JSON parsing failed (expected during partial reads): %s", str(e))
158
+ # Continue reading
159
+ continue
160
+ else:
161
+ # Empty response, continue reading
162
+ logger.debug("Empty response, continuing to read")
163
  continue
164
+ except Exception as e:
165
+ logger.warning("Decoding failed: %s", str(e))
166
+ # Continue reading
167
  continue
168
+ except asyncio.TimeoutError:
169
+ logger.warning("Timeout waiting for chunk from subprocess")
170
+ # Continue reading for more data
171
  continue
172
+ except Exception as e:
173
+ logger.error("Error reading chunk from subprocess: %s", str(e))
174
+ break
175
+
176
+ except Exception as e:
177
+ logger.error("Error in response reading loop: %s", str(e))
178
+ return Response(status_code=500, content=f"Error reading response: {str(e)}")
179
 
180
  # Log final response
181
+ logger.info("Final response size: %d bytes", len(response))
182
+ if len(response) > 0:
183
+ try:
184
+ final_response_str = bytes(response).decode("utf-8")
185
+ logger.info("Final response preview: %s", final_response_str[:200] + "..." if len(final_response_str) > 200 else final_response_str)
186
+ except Exception as e:
187
+ logger.error("Error decoding final response: %s", str(e))
188
+ else:
189
+ logger.warning("Final response is empty")
190
+
191
+ logger.info("=== REQUEST PROCESSING COMPLETE ===")
192
  return Response(content=bytes(response))
193
 
194
  @app.on_event("shutdown")
195
  async def shutdown_event():
196
+ logger.info("=== SHUTDOWN EVENT ===")
197
  if proc:
198
  logger.info("Shutting down subprocess...")
199
  proc.kill()
200
  await proc.wait()
201
  logger.info("Subprocess shut down")
202
+ logger.info("=== SHUTDOWN COMPLETE ===")