diff --git a/.github/workflows/ai-triage-campaign.lock.yml b/.github/workflows/ai-triage-campaign.lock.yml index 2f1d5a1191..07545248a2 100644 --- a/.github/workflows/ai-triage-campaign.lock.yml +++ b/.github/workflows/ai-triage-campaign.lock.yml @@ -4681,7 +4681,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml index e073f8e996..ac40f7b5bb 100644 --- a/.github/workflows/archie.lock.yml +++ b/.github/workflows/archie.lock.yml @@ -6336,7 +6336,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/artifacts-summary.lock.yml b/.github/workflows/artifacts-summary.lock.yml index 424521be7a..6116883da4 100644 --- a/.github/workflows/artifacts-summary.lock.yml +++ b/.github/workflows/artifacts-summary.lock.yml @@ -4841,7 +4841,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index 531b2f99fb..149d8fee61 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -5607,7 +5607,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/blog-auditor.lock.yml b/.github/workflows/blog-auditor.lock.yml index 5b78f2285f..81b14ff860 100644 --- a/.github/workflows/blog-auditor.lock.yml +++ b/.github/workflows/blog-auditor.lock.yml @@ -4731,7 +4731,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index ff681f8706..2be59bc548 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -6128,7 +6128,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/breaking-change-checker.lock.yml b/.github/workflows/breaking-change-checker.lock.yml index 8f47112b86..421c8c728a 100644 --- a/.github/workflows/breaking-change-checker.lock.yml +++ b/.github/workflows/breaking-change-checker.lock.yml @@ -4921,7 +4921,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml index 5a0c890f08..ba0a7f1dca 100644 --- a/.github/workflows/changeset.lock.yml +++ b/.github/workflows/changeset.lock.yml @@ -5316,7 +5316,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/ci-doctor.lock.yml b/.github/workflows/ci-doctor.lock.yml index 57b590cad1..cd6704f4eb 100644 --- a/.github/workflows/ci-doctor.lock.yml +++ b/.github/workflows/ci-doctor.lock.yml @@ -5607,7 +5607,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/cli-consistency-checker.lock.yml b/.github/workflows/cli-consistency-checker.lock.yml index 37fb195a9d..7a869f91ad 100644 --- a/.github/workflows/cli-consistency-checker.lock.yml +++ b/.github/workflows/cli-consistency-checker.lock.yml @@ -4920,7 +4920,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml index a78c8aba7e..0089a2cd1c 100644 --- a/.github/workflows/cli-version-checker.lock.yml +++ b/.github/workflows/cli-version-checker.lock.yml @@ -4681,7 +4681,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index 11f5cc9e82..7f3d61e886 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -6132,7 +6132,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/close-old-discussions.lock.yml b/.github/workflows/close-old-discussions.lock.yml index b0894f101f..3e6b883022 100644 --- a/.github/workflows/close-old-discussions.lock.yml +++ b/.github/workflows/close-old-discussions.lock.yml @@ -4589,7 +4589,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/commit-changes-analyzer.lock.yml b/.github/workflows/commit-changes-analyzer.lock.yml index 83a1e6a911..91d87ab05f 100644 --- a/.github/workflows/commit-changes-analyzer.lock.yml +++ b/.github/workflows/commit-changes-analyzer.lock.yml @@ -4612,7 +4612,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index fed33cc576..5a20f03c7a 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -5294,7 +5294,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/copilot-pr-merged-report.lock.yml b/.github/workflows/copilot-pr-merged-report.lock.yml index 4ec53522a7..f33c9da4d9 100644 --- a/.github/workflows/copilot-pr-merged-report.lock.yml +++ b/.github/workflows/copilot-pr-merged-report.lock.yml @@ -2372,6 +2372,7 @@ jobs: const http = require("http"); const { randomUUID } = require("crypto"); const { MCPServer } = require("./mcp_server.cjs"); + const { createLogger } = require("./mcp_logger.cjs"); class MCPHTTPTransport { constructor(options = {}) { this.sessionIdGenerator = options.sessionIdGenerator; @@ -2380,6 +2381,7 @@ jobs: this.server = null; this.sessionId = null; this.started = false; + this.logger = createLogger("mcp-http-transport"); } setServer(server) { this.server = server; @@ -2391,15 +2393,23 @@ jobs: this.started = true; } async handleRequest(req, res, parsedBody) { + this.logger.debug(`Incoming ${req.method} request to ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + this.logger.debug(`Headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Mcp-Session-Id"); if (req.method === "OPTIONS") { + this.logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + this.logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -2407,14 +2417,18 @@ jobs: try { let body = parsedBody; if (!body) { + this.logger.debug("Parsing request body from stream"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + this.logger.debug(`Request body length: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + this.logger.debug(`Parsed JSON body: ${JSON.stringify(body)}`); } catch (parseError) { + this.logger.debug(`JSON parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2428,8 +2442,11 @@ jobs: ); return; } + } else { + this.logger.debug(`Using pre-parsed body: ${JSON.stringify(body)}`); } if (!body) { + this.logger.debug("Empty request body"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2444,6 +2461,7 @@ jobs: return; } if (!body.jsonrpc || body.jsonrpc !== "2.0") { + this.logger.debug(`Invalid JSON-RPC version: ${body.jsonrpc}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2457,12 +2475,16 @@ jobs: ); return; } + this.logger.debug(`Processing JSON-RPC method: ${body.method}, id: ${body.id}`); if (this.sessionIdGenerator) { if (body.method === "initialize") { this.sessionId = this.sessionIdGenerator(); + this.logger.debug(`Generated new session ID: ${this.sessionId}`); } else { const requestSessionId = req.headers["mcp-session-id"]; + this.logger.debug(`Validating session ID from header: ${requestSessionId}`); if (!requestSessionId) { + this.logger.debug("Missing Mcp-Session-Id header"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2477,6 +2499,7 @@ jobs: return; } if (requestSessionId !== this.sessionId) { + this.logger.debug(`Session not found: ${requestSessionId} (expected: ${this.sessionId})`); res.writeHead(404, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2490,10 +2513,14 @@ jobs: ); return; } + this.logger.debug("Session ID validated successfully"); } } + this.logger.debug("Forwarding request to MCP server"); const response = await this.server.handleRequest(body); + this.logger.debug(`MCP server response: ${JSON.stringify(response)}`); if (response === null) { + this.logger.debug("Notification handled (no response)"); res.writeHead(204); res.end(); return; @@ -2502,9 +2529,11 @@ jobs: if (this.sessionId) { headers["mcp-session-id"] = this.sessionId; } + this.logger.debug(`Sending response with headers: ${JSON.stringify(headers)}`); res.writeHead(200, headers); res.end(JSON.stringify(response)); } catch (error) { + this.logger.debugError("Error handling request: ", error); if (!res.headersSent) { res.writeHead(500, { "Content-Type": "application/json" }); res.end( @@ -2894,15 +2923,23 @@ jobs: logger.debug(`Server connected to transport successfully`); logger.debug(`Creating HTTP server...`); const httpServer = http.createServer(async (req, res) => { + logger.debug(`HTTP request received: ${req.method} ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + logger.debug(`Request headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); if (req.method === "OPTIONS") { + logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -2910,14 +2947,18 @@ jobs: try { let body = null; if (req.method === "POST") { + logger.debug("Reading request body"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + logger.debug(`Request body size: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + logger.debug(`Parsed request body: ${JSON.stringify(body)}`); } catch (parseError) { + logger.debugError("JSON parse error: ", parseError); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2932,7 +2973,9 @@ jobs: return; } } + logger.debug("Forwarding request to transport handler"); await transport.handleRequest(req, res, body); + logger.debug("Request handled successfully"); } catch (error) { logger.debugError("Error handling request: ", error); if (!res.headersSent) { @@ -3156,9 +3199,28 @@ jobs: exit 1 fi # Check if server is responding - if curl -s -f -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ > /dev/null 2>&1; then + CURL_OUTPUT=$(mktemp) + CURL_HTTP_CODE=$(curl -s -w "%{http_code}" -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ -o "$CURL_OUTPUT" 2>&1) + CURL_EXIT_CODE=$? + if [ $CURL_EXIT_CODE -eq 0 ] && [ "$CURL_HTTP_CODE" = "200" ]; then echo "Safe Inputs MCP server is ready (attempt $i/10)" + rm -f "$CURL_OUTPUT" break + else + # Log detailed failure information + echo "Server check failed (attempt $i/10):" + echo " - curl exit code: $CURL_EXIT_CODE" + echo " - HTTP status code: $CURL_HTTP_CODE" + if [ -f "$CURL_OUTPUT" ] && [ -s "$CURL_OUTPUT" ]; then + echo " - Response content:" + head -20 "$CURL_OUTPUT" + else + echo " - Response content: (empty)" + fi + rm -f "$CURL_OUTPUT" + # Show server log for additional debugging context + echo " - Server log:" + cat /tmp/gh-aw/safe-inputs/logs/server.log 2>/dev/null || echo "(log not available)" fi if [ $i -eq 10 ]; then echo "ERROR: Safe Inputs MCP server failed to start after 10 seconds" @@ -6448,7 +6510,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index 6792e26bb2..2a4840481d 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -6392,7 +6392,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index 5598a32951..af6df1e8cc 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -5481,7 +5481,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index 8d797029ff..78f56635e5 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -6696,7 +6696,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml index 246515a98a..b6e6d7a0cc 100644 --- a/.github/workflows/craft.lock.yml +++ b/.github/workflows/craft.lock.yml @@ -6474,7 +6474,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-assign-issue-to-user.lock.yml b/.github/workflows/daily-assign-issue-to-user.lock.yml index a6dba7f238..8b4fbe39be 100644 --- a/.github/workflows/daily-assign-issue-to-user.lock.yml +++ b/.github/workflows/daily-assign-issue-to-user.lock.yml @@ -5184,7 +5184,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml index 0288cd5233..b8602c949f 100644 --- a/.github/workflows/daily-code-metrics.lock.yml +++ b/.github/workflows/daily-code-metrics.lock.yml @@ -5744,7 +5744,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-copilot-token-report.lock.yml b/.github/workflows/daily-copilot-token-report.lock.yml index 018751a362..436a1f16a7 100644 --- a/.github/workflows/daily-copilot-token-report.lock.yml +++ b/.github/workflows/daily-copilot-token-report.lock.yml @@ -6560,7 +6560,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml index 3ac08d176d..a1c57c55ef 100644 --- a/.github/workflows/daily-doc-updater.lock.yml +++ b/.github/workflows/daily-doc-updater.lock.yml @@ -4406,7 +4406,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-fact.lock.yml b/.github/workflows/daily-fact.lock.yml index fa6bd0e026..be52dc57fe 100644 --- a/.github/workflows/daily-fact.lock.yml +++ b/.github/workflows/daily-fact.lock.yml @@ -4720,7 +4720,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-file-diet.lock.yml b/.github/workflows/daily-file-diet.lock.yml index 2971f9e933..d85e24f2e7 100644 --- a/.github/workflows/daily-file-diet.lock.yml +++ b/.github/workflows/daily-file-diet.lock.yml @@ -4672,7 +4672,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml index fa1af56df6..4c01d25abc 100644 --- a/.github/workflows/daily-firewall-report.lock.yml +++ b/.github/workflows/daily-firewall-report.lock.yml @@ -5972,7 +5972,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn # Upload repo memory as artifacts for push job - name: Upload repo-memory artifact (default) diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml index a239629743..5524b850fd 100644 --- a/.github/workflows/daily-issues-report.lock.yml +++ b/.github/workflows/daily-issues-report.lock.yml @@ -6186,7 +6186,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/daily-malicious-code-scan.lock.yml b/.github/workflows/daily-malicious-code-scan.lock.yml index 6b4f885ab8..c009f56ec8 100644 --- a/.github/workflows/daily-malicious-code-scan.lock.yml +++ b/.github/workflows/daily-malicious-code-scan.lock.yml @@ -5155,7 +5155,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-multi-device-docs-tester.lock.yml b/.github/workflows/daily-multi-device-docs-tester.lock.yml index e6e6a5b155..d82654f041 100644 --- a/.github/workflows/daily-multi-device-docs-tester.lock.yml +++ b/.github/workflows/daily-multi-device-docs-tester.lock.yml @@ -4312,7 +4312,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 151a9130ab..b9563a2374 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -6449,7 +6449,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml index 4e2e1bcf2e..253287adaf 100644 --- a/.github/workflows/daily-performance-summary.lock.yml +++ b/.github/workflows/daily-performance-summary.lock.yml @@ -2955,6 +2955,7 @@ jobs: const http = require("http"); const { randomUUID } = require("crypto"); const { MCPServer } = require("./mcp_server.cjs"); + const { createLogger } = require("./mcp_logger.cjs"); class MCPHTTPTransport { constructor(options = {}) { this.sessionIdGenerator = options.sessionIdGenerator; @@ -2963,6 +2964,7 @@ jobs: this.server = null; this.sessionId = null; this.started = false; + this.logger = createLogger("mcp-http-transport"); } setServer(server) { this.server = server; @@ -2974,15 +2976,23 @@ jobs: this.started = true; } async handleRequest(req, res, parsedBody) { + this.logger.debug(`Incoming ${req.method} request to ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + this.logger.debug(`Headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Mcp-Session-Id"); if (req.method === "OPTIONS") { + this.logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + this.logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -2990,14 +3000,18 @@ jobs: try { let body = parsedBody; if (!body) { + this.logger.debug("Parsing request body from stream"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + this.logger.debug(`Request body length: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + this.logger.debug(`Parsed JSON body: ${JSON.stringify(body)}`); } catch (parseError) { + this.logger.debug(`JSON parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -3011,8 +3025,11 @@ jobs: ); return; } + } else { + this.logger.debug(`Using pre-parsed body: ${JSON.stringify(body)}`); } if (!body) { + this.logger.debug("Empty request body"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -3027,6 +3044,7 @@ jobs: return; } if (!body.jsonrpc || body.jsonrpc !== "2.0") { + this.logger.debug(`Invalid JSON-RPC version: ${body.jsonrpc}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -3040,12 +3058,16 @@ jobs: ); return; } + this.logger.debug(`Processing JSON-RPC method: ${body.method}, id: ${body.id}`); if (this.sessionIdGenerator) { if (body.method === "initialize") { this.sessionId = this.sessionIdGenerator(); + this.logger.debug(`Generated new session ID: ${this.sessionId}`); } else { const requestSessionId = req.headers["mcp-session-id"]; + this.logger.debug(`Validating session ID from header: ${requestSessionId}`); if (!requestSessionId) { + this.logger.debug("Missing Mcp-Session-Id header"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -3060,6 +3082,7 @@ jobs: return; } if (requestSessionId !== this.sessionId) { + this.logger.debug(`Session not found: ${requestSessionId} (expected: ${this.sessionId})`); res.writeHead(404, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -3073,10 +3096,14 @@ jobs: ); return; } + this.logger.debug("Session ID validated successfully"); } } + this.logger.debug("Forwarding request to MCP server"); const response = await this.server.handleRequest(body); + this.logger.debug(`MCP server response: ${JSON.stringify(response)}`); if (response === null) { + this.logger.debug("Notification handled (no response)"); res.writeHead(204); res.end(); return; @@ -3085,9 +3112,11 @@ jobs: if (this.sessionId) { headers["mcp-session-id"] = this.sessionId; } + this.logger.debug(`Sending response with headers: ${JSON.stringify(headers)}`); res.writeHead(200, headers); res.end(JSON.stringify(response)); } catch (error) { + this.logger.debugError("Error handling request: ", error); if (!res.headersSent) { res.writeHead(500, { "Content-Type": "application/json" }); res.end( @@ -3477,15 +3506,23 @@ jobs: logger.debug(`Server connected to transport successfully`); logger.debug(`Creating HTTP server...`); const httpServer = http.createServer(async (req, res) => { + logger.debug(`HTTP request received: ${req.method} ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + logger.debug(`Request headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); if (req.method === "OPTIONS") { + logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -3493,14 +3530,18 @@ jobs: try { let body = null; if (req.method === "POST") { + logger.debug("Reading request body"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + logger.debug(`Request body size: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + logger.debug(`Parsed request body: ${JSON.stringify(body)}`); } catch (parseError) { + logger.debugError("JSON parse error: ", parseError); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -3515,7 +3556,9 @@ jobs: return; } } + logger.debug("Forwarding request to transport handler"); await transport.handleRequest(req, res, body); + logger.debug("Request handled successfully"); } catch (error) { logger.debugError("Error handling request: ", error); if (!res.headersSent) { @@ -4030,9 +4073,28 @@ jobs: exit 1 fi # Check if server is responding - if curl -s -f -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ > /dev/null 2>&1; then + CURL_OUTPUT=$(mktemp) + CURL_HTTP_CODE=$(curl -s -w "%{http_code}" -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ -o "$CURL_OUTPUT" 2>&1) + CURL_EXIT_CODE=$? + if [ $CURL_EXIT_CODE -eq 0 ] && [ "$CURL_HTTP_CODE" = "200" ]; then echo "Safe Inputs MCP server is ready (attempt $i/10)" + rm -f "$CURL_OUTPUT" break + else + # Log detailed failure information + echo "Server check failed (attempt $i/10):" + echo " - curl exit code: $CURL_EXIT_CODE" + echo " - HTTP status code: $CURL_HTTP_CODE" + if [ -f "$CURL_OUTPUT" ] && [ -s "$CURL_OUTPUT" ]; then + echo " - Response content:" + head -20 "$CURL_OUTPUT" + else + echo " - Response content: (empty)" + fi + rm -f "$CURL_OUTPUT" + # Show server log for additional debugging context + echo " - Server log:" + cat /tmp/gh-aw/safe-inputs/logs/server.log 2>/dev/null || echo "(log not available)" fi if [ $i -eq 10 ]; then echo "ERROR: Safe Inputs MCP server failed to start after 10 seconds" @@ -7342,7 +7404,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/daily-repo-chronicle.lock.yml b/.github/workflows/daily-repo-chronicle.lock.yml index e16e4b0776..52379ba01d 100644 --- a/.github/workflows/daily-repo-chronicle.lock.yml +++ b/.github/workflows/daily-repo-chronicle.lock.yml @@ -5993,7 +5993,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/daily-team-status.lock.yml b/.github/workflows/daily-team-status.lock.yml index a922e420be..6bb4fb9232 100644 --- a/.github/workflows/daily-team-status.lock.yml +++ b/.github/workflows/daily-team-status.lock.yml @@ -4748,7 +4748,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/daily-workflow-updater.lock.yml b/.github/workflows/daily-workflow-updater.lock.yml index 3a2e097596..834bdab522 100644 --- a/.github/workflows/daily-workflow-updater.lock.yml +++ b/.github/workflows/daily-workflow-updater.lock.yml @@ -4912,7 +4912,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index 206405ffc6..325de1a925 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -5200,7 +5200,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn # Upload repo memory as artifacts for push job - name: Upload repo-memory artifact (default) diff --git a/.github/workflows/dependabot-go-checker.lock.yml b/.github/workflows/dependabot-go-checker.lock.yml index cc70372d1f..39ac0e801b 100644 --- a/.github/workflows/dependabot-go-checker.lock.yml +++ b/.github/workflows/dependabot-go-checker.lock.yml @@ -5455,7 +5455,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml index d29d56300f..eca4b4f01a 100644 --- a/.github/workflows/dev-hawk.lock.yml +++ b/.github/workflows/dev-hawk.lock.yml @@ -5374,7 +5374,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 39d198943c..7c3a1ace0b 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -961,6 +961,7 @@ jobs: const http = require("http"); const { randomUUID } = require("crypto"); const { MCPServer } = require("./mcp_server.cjs"); + const { createLogger } = require("./mcp_logger.cjs"); class MCPHTTPTransport { constructor(options = {}) { this.sessionIdGenerator = options.sessionIdGenerator; @@ -969,6 +970,7 @@ jobs: this.server = null; this.sessionId = null; this.started = false; + this.logger = createLogger("mcp-http-transport"); } setServer(server) { this.server = server; @@ -980,15 +982,23 @@ jobs: this.started = true; } async handleRequest(req, res, parsedBody) { + this.logger.debug(`Incoming ${req.method} request to ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + this.logger.debug(`Headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Mcp-Session-Id"); if (req.method === "OPTIONS") { + this.logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + this.logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -996,14 +1006,18 @@ jobs: try { let body = parsedBody; if (!body) { + this.logger.debug("Parsing request body from stream"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + this.logger.debug(`Request body length: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + this.logger.debug(`Parsed JSON body: ${JSON.stringify(body)}`); } catch (parseError) { + this.logger.debug(`JSON parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -1017,8 +1031,11 @@ jobs: ); return; } + } else { + this.logger.debug(`Using pre-parsed body: ${JSON.stringify(body)}`); } if (!body) { + this.logger.debug("Empty request body"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -1033,6 +1050,7 @@ jobs: return; } if (!body.jsonrpc || body.jsonrpc !== "2.0") { + this.logger.debug(`Invalid JSON-RPC version: ${body.jsonrpc}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -1046,12 +1064,16 @@ jobs: ); return; } + this.logger.debug(`Processing JSON-RPC method: ${body.method}, id: ${body.id}`); if (this.sessionIdGenerator) { if (body.method === "initialize") { this.sessionId = this.sessionIdGenerator(); + this.logger.debug(`Generated new session ID: ${this.sessionId}`); } else { const requestSessionId = req.headers["mcp-session-id"]; + this.logger.debug(`Validating session ID from header: ${requestSessionId}`); if (!requestSessionId) { + this.logger.debug("Missing Mcp-Session-Id header"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -1066,6 +1088,7 @@ jobs: return; } if (requestSessionId !== this.sessionId) { + this.logger.debug(`Session not found: ${requestSessionId} (expected: ${this.sessionId})`); res.writeHead(404, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -1079,10 +1102,14 @@ jobs: ); return; } + this.logger.debug("Session ID validated successfully"); } } + this.logger.debug("Forwarding request to MCP server"); const response = await this.server.handleRequest(body); + this.logger.debug(`MCP server response: ${JSON.stringify(response)}`); if (response === null) { + this.logger.debug("Notification handled (no response)"); res.writeHead(204); res.end(); return; @@ -1091,9 +1118,11 @@ jobs: if (this.sessionId) { headers["mcp-session-id"] = this.sessionId; } + this.logger.debug(`Sending response with headers: ${JSON.stringify(headers)}`); res.writeHead(200, headers); res.end(JSON.stringify(response)); } catch (error) { + this.logger.debugError("Error handling request: ", error); if (!res.headersSent) { res.writeHead(500, { "Content-Type": "application/json" }); res.end( @@ -1483,15 +1512,23 @@ jobs: logger.debug(`Server connected to transport successfully`); logger.debug(`Creating HTTP server...`); const httpServer = http.createServer(async (req, res) => { + logger.debug(`HTTP request received: ${req.method} ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + logger.debug(`Request headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); if (req.method === "OPTIONS") { + logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -1499,14 +1536,18 @@ jobs: try { let body = null; if (req.method === "POST") { + logger.debug("Reading request body"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + logger.debug(`Request body size: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + logger.debug(`Parsed request body: ${JSON.stringify(body)}`); } catch (parseError) { + logger.debugError("JSON parse error: ", parseError); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -1521,7 +1562,9 @@ jobs: return; } } + logger.debug("Forwarding request to transport handler"); await transport.handleRequest(req, res, body); + logger.debug("Request handled successfully"); } catch (error) { logger.debugError("Error handling request: ", error); if (!res.headersSent) { @@ -1745,9 +1788,28 @@ jobs: exit 1 fi # Check if server is responding - if curl -s -f -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ > /dev/null 2>&1; then + CURL_OUTPUT=$(mktemp) + CURL_HTTP_CODE=$(curl -s -w "%{http_code}" -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ -o "$CURL_OUTPUT" 2>&1) + CURL_EXIT_CODE=$? + if [ $CURL_EXIT_CODE -eq 0 ] && [ "$CURL_HTTP_CODE" = "200" ]; then echo "Safe Inputs MCP server is ready (attempt $i/10)" + rm -f "$CURL_OUTPUT" break + else + # Log detailed failure information + echo "Server check failed (attempt $i/10):" + echo " - curl exit code: $CURL_EXIT_CODE" + echo " - HTTP status code: $CURL_HTTP_CODE" + if [ -f "$CURL_OUTPUT" ] && [ -s "$CURL_OUTPUT" ]; then + echo " - Response content:" + head -20 "$CURL_OUTPUT" + else + echo " - Response content: (empty)" + fi + rm -f "$CURL_OUTPUT" + # Show server log for additional debugging context + echo " - Server log:" + cat /tmp/gh-aw/safe-inputs/logs/server.log 2>/dev/null || echo "(log not available)" fi if [ $i -eq 10 ]; then echo "ERROR: Safe Inputs MCP server failed to start after 10 seconds" @@ -3089,7 +3151,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn # Upload repo memory as artifacts for push job - name: Upload repo-memory artifact (default) diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index f96dd9acbc..eafe0c6880 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -5492,7 +5492,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/dictation-prompt.lock.yml b/.github/workflows/dictation-prompt.lock.yml index 3d231811d9..9bcd43052b 100644 --- a/.github/workflows/dictation-prompt.lock.yml +++ b/.github/workflows/dictation-prompt.lock.yml @@ -4860,7 +4860,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/docs-noob-tester.lock.yml b/.github/workflows/docs-noob-tester.lock.yml index 7fb3400864..ee6b2369f3 100644 --- a/.github/workflows/docs-noob-tester.lock.yml +++ b/.github/workflows/docs-noob-tester.lock.yml @@ -4931,7 +4931,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml index 170ab64d14..b6e7c25850 100644 --- a/.github/workflows/duplicate-code-detector.lock.yml +++ b/.github/workflows/duplicate-code-detector.lock.yml @@ -4503,7 +4503,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/example-permissions-warning.lock.yml b/.github/workflows/example-permissions-warning.lock.yml index 038a29ed7f..e1bdacf813 100644 --- a/.github/workflows/example-permissions-warning.lock.yml +++ b/.github/workflows/example-permissions-warning.lock.yml @@ -2336,7 +2336,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/example-workflow-analyzer.lock.yml b/.github/workflows/example-workflow-analyzer.lock.yml index 124a4ddae0..76da9109c8 100644 --- a/.github/workflows/example-workflow-analyzer.lock.yml +++ b/.github/workflows/example-workflow-analyzer.lock.yml @@ -4188,7 +4188,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml index ed1f165d2d..19b13fb861 100644 --- a/.github/workflows/firewall-escape.lock.yml +++ b/.github/workflows/firewall-escape.lock.yml @@ -2757,7 +2757,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/firewall.lock.yml b/.github/workflows/firewall.lock.yml index 53e5f42990..beda8430ea 100644 --- a/.github/workflows/firewall.lock.yml +++ b/.github/workflows/firewall.lock.yml @@ -2384,7 +2384,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/github-mcp-structural-analysis.lock.yml b/.github/workflows/github-mcp-structural-analysis.lock.yml index 8861aec715..fe166bcc83 100644 --- a/.github/workflows/github-mcp-structural-analysis.lock.yml +++ b/.github/workflows/github-mcp-structural-analysis.lock.yml @@ -5419,7 +5419,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index f1fd931a28..45605fc711 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -5199,7 +5199,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index 1fb62e19d1..0ebebc3b21 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -5887,7 +5887,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml index f13368aaa4..611b58f191 100644 --- a/.github/workflows/go-fan.lock.yml +++ b/.github/workflows/go-fan.lock.yml @@ -4801,7 +4801,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml index 41acddf4be..7e6880aafd 100644 --- a/.github/workflows/go-logger.lock.yml +++ b/.github/workflows/go-logger.lock.yml @@ -4635,7 +4635,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml index a68cf517d4..496e402c5b 100644 --- a/.github/workflows/go-pattern-detector.lock.yml +++ b/.github/workflows/go-pattern-detector.lock.yml @@ -4318,7 +4318,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/grumpy-reviewer.lock.yml b/.github/workflows/grumpy-reviewer.lock.yml index 537e1f5c38..4b4106d7a4 100644 --- a/.github/workflows/grumpy-reviewer.lock.yml +++ b/.github/workflows/grumpy-reviewer.lock.yml @@ -6278,7 +6278,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/instructions-janitor.lock.yml b/.github/workflows/instructions-janitor.lock.yml index bcd6603845..be69372e0a 100644 --- a/.github/workflows/instructions-janitor.lock.yml +++ b/.github/workflows/instructions-janitor.lock.yml @@ -4400,7 +4400,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/issue-arborist.lock.yml b/.github/workflows/issue-arborist.lock.yml index 7371bac3b9..cc53e689f7 100644 --- a/.github/workflows/issue-arborist.lock.yml +++ b/.github/workflows/issue-arborist.lock.yml @@ -4518,7 +4518,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index 227275541c..0e5105b8cf 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -4282,7 +4282,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn conclusion: diff --git a/.github/workflows/issue-monster.lock.yml b/.github/workflows/issue-monster.lock.yml index 3afb0b874e..44fbf68d38 100644 --- a/.github/workflows/issue-monster.lock.yml +++ b/.github/workflows/issue-monster.lock.yml @@ -5549,7 +5549,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/issue-triage-agent.lock.yml b/.github/workflows/issue-triage-agent.lock.yml index 8d424aa563..8af89e2d89 100644 --- a/.github/workflows/issue-triage-agent.lock.yml +++ b/.github/workflows/issue-triage-agent.lock.yml @@ -5027,7 +5027,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/lockfile-stats.lock.yml b/.github/workflows/lockfile-stats.lock.yml index 3fc482e46c..65931c5918 100644 --- a/.github/workflows/lockfile-stats.lock.yml +++ b/.github/workflows/lockfile-stats.lock.yml @@ -4847,7 +4847,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index fab57c5a80..a227a6bb78 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -5527,7 +5527,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml index d9367263cb..a3d47a9706 100644 --- a/.github/workflows/mergefest.lock.yml +++ b/.github/workflows/mergefest.lock.yml @@ -5624,7 +5624,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/notion-issue-summary.lock.yml b/.github/workflows/notion-issue-summary.lock.yml index 4e3d61fdac..dc369ccf0c 100644 --- a/.github/workflows/notion-issue-summary.lock.yml +++ b/.github/workflows/notion-issue-summary.lock.yml @@ -4530,7 +4530,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml index eb891aec0e..06cdf8a865 100644 --- a/.github/workflows/org-health-report.lock.yml +++ b/.github/workflows/org-health-report.lock.yml @@ -6388,7 +6388,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index 0526759c45..1d2c7262ff 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -6297,7 +6297,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index 2072fad753..9581fdc1b8 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -5636,7 +5636,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index 560187a04f..75d0337500 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -7354,7 +7354,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/pr-nitpick-reviewer.lock.yml b/.github/workflows/pr-nitpick-reviewer.lock.yml index 9acb588a15..e90d7934b2 100644 --- a/.github/workflows/pr-nitpick-reviewer.lock.yml +++ b/.github/workflows/pr-nitpick-reviewer.lock.yml @@ -6621,7 +6621,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml index 919a86554f..82827bfae0 100644 --- a/.github/workflows/prompt-clustering-analysis.lock.yml +++ b/.github/workflows/prompt-clustering-analysis.lock.yml @@ -6056,7 +6056,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml index a1e9dac3e2..0700f664db 100644 --- a/.github/workflows/python-data-charts.lock.yml +++ b/.github/workflows/python-data-charts.lock.yml @@ -6622,7 +6622,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index 621c0ca064..a75cfaeb7b 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -6877,7 +6877,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index 42744f2d5a..917abd3861 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -4986,7 +4986,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/repo-tree-map.lock.yml b/.github/workflows/repo-tree-map.lock.yml index c924f1caf4..2e985c2c15 100644 --- a/.github/workflows/repo-tree-map.lock.yml +++ b/.github/workflows/repo-tree-map.lock.yml @@ -4933,7 +4933,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml index 7120983cf3..eb8c38675e 100644 --- a/.github/workflows/repository-quality-improver.lock.yml +++ b/.github/workflows/repository-quality-improver.lock.yml @@ -5840,7 +5840,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/research.lock.yml b/.github/workflows/research.lock.yml index 68401816c8..7c24efe9e3 100644 --- a/.github/workflows/research.lock.yml +++ b/.github/workflows/research.lock.yml @@ -4779,7 +4779,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml index 8aee58cb6b..c8d0caf081 100644 --- a/.github/workflows/safe-output-health.lock.yml +++ b/.github/workflows/safe-output-health.lock.yml @@ -5079,7 +5079,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/schema-consistency-checker.lock.yml b/.github/workflows/schema-consistency-checker.lock.yml index ab635ae1dc..a6d815aa9d 100644 --- a/.github/workflows/schema-consistency-checker.lock.yml +++ b/.github/workflows/schema-consistency-checker.lock.yml @@ -4857,7 +4857,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 071ee0a750..f4b49b2096 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -6190,7 +6190,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/security-fix-pr.lock.yml b/.github/workflows/security-fix-pr.lock.yml index d6b87f29f3..efca9c0c00 100644 --- a/.github/workflows/security-fix-pr.lock.yml +++ b/.github/workflows/security-fix-pr.lock.yml @@ -4338,7 +4338,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/semantic-function-refactor.lock.yml b/.github/workflows/semantic-function-refactor.lock.yml index 2efde5c3a8..df4c57d20e 100644 --- a/.github/workflows/semantic-function-refactor.lock.yml +++ b/.github/workflows/semantic-function-refactor.lock.yml @@ -5112,7 +5112,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 039c7872bf..f85d952e85 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -6021,7 +6021,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index 10ef1802c1..0941d5f699 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -5807,7 +5807,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-copilot-no-firewall.lock.yml b/.github/workflows/smoke-copilot-no-firewall.lock.yml index c4f16c876c..87e64cdcb4 100644 --- a/.github/workflows/smoke-copilot-no-firewall.lock.yml +++ b/.github/workflows/smoke-copilot-no-firewall.lock.yml @@ -6088,7 +6088,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-copilot-playwright.lock.yml b/.github/workflows/smoke-copilot-playwright.lock.yml index d9e1ab5faa..e127bae57a 100644 --- a/.github/workflows/smoke-copilot-playwright.lock.yml +++ b/.github/workflows/smoke-copilot-playwright.lock.yml @@ -6371,7 +6371,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml index 5ce344ab39..2cbf69c7fa 100644 --- a/.github/workflows/smoke-copilot.lock.yml +++ b/.github/workflows/smoke-copilot.lock.yml @@ -6271,7 +6271,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-detector.lock.yml b/.github/workflows/smoke-detector.lock.yml index 80122c7f0a..e09e2bb517 100644 --- a/.github/workflows/smoke-detector.lock.yml +++ b/.github/workflows/smoke-detector.lock.yml @@ -5810,7 +5810,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-srt-custom-config.lock.yml b/.github/workflows/smoke-srt-custom-config.lock.yml index 2ed7bc01a4..fc973a098d 100644 --- a/.github/workflows/smoke-srt-custom-config.lock.yml +++ b/.github/workflows/smoke-srt-custom-config.lock.yml @@ -2327,7 +2327,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/smoke-srt.lock.yml b/.github/workflows/smoke-srt.lock.yml index 99d69d7f29..9bcd457382 100644 --- a/.github/workflows/smoke-srt.lock.yml +++ b/.github/workflows/smoke-srt.lock.yml @@ -4439,7 +4439,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index 4a4cef70d6..06af0f2dd8 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -6486,7 +6486,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/static-analysis-report.lock.yml b/.github/workflows/static-analysis-report.lock.yml index 5fa949b230..75f07be524 100644 --- a/.github/workflows/static-analysis-report.lock.yml +++ b/.github/workflows/static-analysis-report.lock.yml @@ -4883,7 +4883,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index e0f5ee4b5d..8b0801b211 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -5077,7 +5077,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index 60e33d50da..f659fdedd0 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -6140,7 +6140,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/test-python-safe-input.lock.yml b/.github/workflows/test-python-safe-input.lock.yml index 76bd23b7d4..0756ecbd53 100644 --- a/.github/workflows/test-python-safe-input.lock.yml +++ b/.github/workflows/test-python-safe-input.lock.yml @@ -2144,6 +2144,7 @@ jobs: const http = require("http"); const { randomUUID } = require("crypto"); const { MCPServer } = require("./mcp_server.cjs"); + const { createLogger } = require("./mcp_logger.cjs"); class MCPHTTPTransport { constructor(options = {}) { this.sessionIdGenerator = options.sessionIdGenerator; @@ -2152,6 +2153,7 @@ jobs: this.server = null; this.sessionId = null; this.started = false; + this.logger = createLogger("mcp-http-transport"); } setServer(server) { this.server = server; @@ -2163,15 +2165,23 @@ jobs: this.started = true; } async handleRequest(req, res, parsedBody) { + this.logger.debug(`Incoming ${req.method} request to ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + this.logger.debug(`Headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Mcp-Session-Id"); if (req.method === "OPTIONS") { + this.logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + this.logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -2179,14 +2189,18 @@ jobs: try { let body = parsedBody; if (!body) { + this.logger.debug("Parsing request body from stream"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + this.logger.debug(`Request body length: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + this.logger.debug(`Parsed JSON body: ${JSON.stringify(body)}`); } catch (parseError) { + this.logger.debug(`JSON parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2200,8 +2214,11 @@ jobs: ); return; } + } else { + this.logger.debug(`Using pre-parsed body: ${JSON.stringify(body)}`); } if (!body) { + this.logger.debug("Empty request body"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2216,6 +2233,7 @@ jobs: return; } if (!body.jsonrpc || body.jsonrpc !== "2.0") { + this.logger.debug(`Invalid JSON-RPC version: ${body.jsonrpc}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2229,12 +2247,16 @@ jobs: ); return; } + this.logger.debug(`Processing JSON-RPC method: ${body.method}, id: ${body.id}`); if (this.sessionIdGenerator) { if (body.method === "initialize") { this.sessionId = this.sessionIdGenerator(); + this.logger.debug(`Generated new session ID: ${this.sessionId}`); } else { const requestSessionId = req.headers["mcp-session-id"]; + this.logger.debug(`Validating session ID from header: ${requestSessionId}`); if (!requestSessionId) { + this.logger.debug("Missing Mcp-Session-Id header"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2249,6 +2271,7 @@ jobs: return; } if (requestSessionId !== this.sessionId) { + this.logger.debug(`Session not found: ${requestSessionId} (expected: ${this.sessionId})`); res.writeHead(404, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2262,10 +2285,14 @@ jobs: ); return; } + this.logger.debug("Session ID validated successfully"); } } + this.logger.debug("Forwarding request to MCP server"); const response = await this.server.handleRequest(body); + this.logger.debug(`MCP server response: ${JSON.stringify(response)}`); if (response === null) { + this.logger.debug("Notification handled (no response)"); res.writeHead(204); res.end(); return; @@ -2274,9 +2301,11 @@ jobs: if (this.sessionId) { headers["mcp-session-id"] = this.sessionId; } + this.logger.debug(`Sending response with headers: ${JSON.stringify(headers)}`); res.writeHead(200, headers); res.end(JSON.stringify(response)); } catch (error) { + this.logger.debugError("Error handling request: ", error); if (!res.headersSent) { res.writeHead(500, { "Content-Type": "application/json" }); res.end( @@ -2666,15 +2695,23 @@ jobs: logger.debug(`Server connected to transport successfully`); logger.debug(`Creating HTTP server...`); const httpServer = http.createServer(async (req, res) => { + logger.debug(`HTTP request received: ${req.method} ${req.url}`); + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + logger.debug(`Request headers: ${JSON.stringify(sanitizedHeaders)}`); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); if (req.method === "OPTIONS") { + logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; } if (req.method !== "POST") { + logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -2682,14 +2719,18 @@ jobs: try { let body = null; if (req.method === "POST") { + logger.debug("Reading request body"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + logger.debug(`Request body size: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + logger.debug(`Parsed request body: ${JSON.stringify(body)}`); } catch (parseError) { + logger.debugError("JSON parse error: ", parseError); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -2704,7 +2745,9 @@ jobs: return; } } + logger.debug("Forwarding request to transport handler"); await transport.handleRequest(req, res, body); + logger.debug("Request handled successfully"); } catch (error) { logger.debugError("Error handling request: ", error); if (!res.headersSent) { @@ -3021,9 +3064,28 @@ jobs: exit 1 fi # Check if server is responding - if curl -s -f -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ > /dev/null 2>&1; then + CURL_OUTPUT=$(mktemp) + CURL_HTTP_CODE=$(curl -s -w "%{http_code}" -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ -o "$CURL_OUTPUT" 2>&1) + CURL_EXIT_CODE=$? + if [ $CURL_EXIT_CODE -eq 0 ] && [ "$CURL_HTTP_CODE" = "200" ]; then echo "Safe Inputs MCP server is ready (attempt $i/10)" + rm -f "$CURL_OUTPUT" break + else + # Log detailed failure information + echo "Server check failed (attempt $i/10):" + echo " - curl exit code: $CURL_EXIT_CODE" + echo " - HTTP status code: $CURL_HTTP_CODE" + if [ -f "$CURL_OUTPUT" ] && [ -s "$CURL_OUTPUT" ]; then + echo " - Response content:" + head -20 "$CURL_OUTPUT" + else + echo " - Response content: (empty)" + fi + rm -f "$CURL_OUTPUT" + # Show server log for additional debugging context + echo " - Server log:" + cat /tmp/gh-aw/safe-inputs/logs/server.log 2>/dev/null || echo "(log not available)" fi if [ $i -eq 10 ]; then echo "ERROR: Safe Inputs MCP server failed to start after 10 seconds" @@ -6078,7 +6140,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 9a45de5a18..ca63d96f4d 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -5266,7 +5266,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml index 4be819fc60..067c01f88b 100644 --- a/.github/workflows/typist.lock.yml +++ b/.github/workflows/typist.lock.yml @@ -5143,7 +5143,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index 848249d508..c9292a966c 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -5940,7 +5940,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/.github/workflows/video-analyzer.lock.yml b/.github/workflows/video-analyzer.lock.yml index d6a651f330..c1f1f1402c 100644 --- a/.github/workflows/video-analyzer.lock.yml +++ b/.github/workflows/video-analyzer.lock.yml @@ -5121,7 +5121,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Validate agent logs for errors if: always() diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml index d46956ce74..5a2e7633b7 100644 --- a/.github/workflows/weekly-issue-summary.lock.yml +++ b/.github/workflows/weekly-issue-summary.lock.yml @@ -5851,7 +5851,9 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: agent-stdio.log - path: /tmp/gh-aw/agent-stdio.log + path: | + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/safe-inputs/logs/ if-no-files-found: warn - name: Upload safe outputs assets if: always() diff --git a/pkg/workflow/compiler_yaml.go b/pkg/workflow/compiler_yaml.go index b5bc04fc6a..29b5d0b027 100644 --- a/pkg/workflow/compiler_yaml.go +++ b/pkg/workflow/compiler_yaml.go @@ -466,15 +466,17 @@ func (c *Compiler) generateMainJobSteps(yaml *strings.Builder, data *WorkflowDat } func (c *Compiler) generateUploadAgentLogs(yaml *strings.Builder, logFileFull string) { - // Record artifact upload for validation - c.stepOrderTracker.RecordArtifactUpload("Upload Agent Stdio", []string{logFileFull}) + // Record artifact upload for validation (includes agent stdio and safe-inputs logs) + c.stepOrderTracker.RecordArtifactUpload("Upload Agent Stdio", []string{logFileFull, "/tmp/gh-aw/safe-inputs/logs/"}) yaml.WriteString(" - name: Upload Agent Stdio\n") yaml.WriteString(" if: always()\n") yaml.WriteString(fmt.Sprintf(" uses: %s\n", GetActionPin("actions/upload-artifact"))) yaml.WriteString(" with:\n") yaml.WriteString(" name: agent-stdio.log\n") - fmt.Fprintf(yaml, " path: %s\n", logFileFull) + yaml.WriteString(" path: |\n") + fmt.Fprintf(yaml, " %s\n", logFileFull) + yaml.WriteString(" /tmp/gh-aw/safe-inputs/logs/\n") yaml.WriteString(" if-no-files-found: warn\n") } diff --git a/pkg/workflow/js/mcp_http_transport.cjs b/pkg/workflow/js/mcp_http_transport.cjs index d5aeb92e04..4e085f1f2a 100644 --- a/pkg/workflow/js/mcp_http_transport.cjs +++ b/pkg/workflow/js/mcp_http_transport.cjs @@ -21,6 +21,7 @@ const http = require("http"); const { randomUUID } = require("crypto"); const { MCPServer } = require("./mcp_server.cjs"); +const { createLogger } = require("./mcp_logger.cjs"); /** * MCP HTTP Transport implementation @@ -40,6 +41,7 @@ class MCPHTTPTransport { this.server = null; this.sessionId = null; this.started = false; + this.logger = createLogger("mcp-http-transport"); } /** @@ -67,6 +69,15 @@ class MCPHTTPTransport { * @param {Object} [parsedBody] - Pre-parsed request body */ async handleRequest(req, res, parsedBody) { + // Log all incoming requests + this.logger.debug(`Incoming ${req.method} request to ${req.url}`); + // Redact sensitive headers before logging + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + this.logger.debug(`Headers: ${JSON.stringify(sanitizedHeaders)}`); + // Set CORS headers res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); @@ -74,6 +85,7 @@ class MCPHTTPTransport { // Handle OPTIONS preflight if (req.method === "OPTIONS") { + this.logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; @@ -81,6 +93,7 @@ class MCPHTTPTransport { // Only handle POST requests for MCP protocol if (req.method !== "POST") { + this.logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -90,14 +103,18 @@ class MCPHTTPTransport { // Parse request body if not already parsed let body = parsedBody; if (!body) { + this.logger.debug("Parsing request body from stream"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + this.logger.debug(`Request body length: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + this.logger.debug(`Parsed JSON body: ${JSON.stringify(body)}`); } catch (parseError) { + this.logger.debug(`JSON parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -111,9 +128,12 @@ class MCPHTTPTransport { ); return; } + } else { + this.logger.debug(`Using pre-parsed body: ${JSON.stringify(body)}`); } if (!body) { + this.logger.debug("Empty request body"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -130,6 +150,7 @@ class MCPHTTPTransport { // Validate JSON-RPC structure if (!body.jsonrpc || body.jsonrpc !== "2.0") { + this.logger.debug(`Invalid JSON-RPC version: ${body.jsonrpc}`); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -144,15 +165,20 @@ class MCPHTTPTransport { return; } + this.logger.debug(`Processing JSON-RPC method: ${body.method}, id: ${body.id}`); + // Handle session management for stateful mode if (this.sessionIdGenerator) { // For initialize, generate a new session ID if (body.method === "initialize") { this.sessionId = this.sessionIdGenerator(); + this.logger.debug(`Generated new session ID: ${this.sessionId}`); } else { // For other methods, validate session ID const requestSessionId = req.headers["mcp-session-id"]; + this.logger.debug(`Validating session ID from header: ${requestSessionId}`); if (!requestSessionId) { + this.logger.debug("Missing Mcp-Session-Id header"); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -168,6 +194,7 @@ class MCPHTTPTransport { } if (requestSessionId !== this.sessionId) { + this.logger.debug(`Session not found: ${requestSessionId} (expected: ${this.sessionId})`); res.writeHead(404, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -181,14 +208,18 @@ class MCPHTTPTransport { ); return; } + this.logger.debug("Session ID validated successfully"); } } // Process the request through the MCP server + this.logger.debug("Forwarding request to MCP server"); const response = await this.server.handleRequest(body); + this.logger.debug(`MCP server response: ${JSON.stringify(response)}`); // Handle notifications (null response means no reply needed) if (response === null) { + this.logger.debug("Notification handled (no response)"); res.writeHead(204); // No Content res.end(); return; @@ -200,9 +231,11 @@ class MCPHTTPTransport { headers["mcp-session-id"] = this.sessionId; } + this.logger.debug(`Sending response with headers: ${JSON.stringify(headers)}`); res.writeHead(200, headers); res.end(JSON.stringify(response)); } catch (error) { + this.logger.debugError("Error handling request: ", error); if (!res.headersSent) { res.writeHead(500, { "Content-Type": "application/json" }); res.end( diff --git a/pkg/workflow/js/safe_inputs_mcp_server_http.cjs b/pkg/workflow/js/safe_inputs_mcp_server_http.cjs index 21e36c520a..5f85d2a690 100644 --- a/pkg/workflow/js/safe_inputs_mcp_server_http.cjs +++ b/pkg/workflow/js/safe_inputs_mcp_server_http.cjs @@ -166,6 +166,15 @@ async function startHttpServer(configPath, options = {}) { // Create HTTP server logger.debug(`Creating HTTP server...`); const httpServer = http.createServer(async (req, res) => { + // Log all incoming requests + logger.debug(`HTTP request received: ${req.method} ${req.url}`); + // Redact sensitive headers before logging + const sanitizedHeaders = { ...req.headers }; + if (sanitizedHeaders.authorization) { + sanitizedHeaders.authorization = "[REDACTED]"; + } + logger.debug(`Request headers: ${JSON.stringify(sanitizedHeaders)}`); + // Set CORS headers for development res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); @@ -173,6 +182,7 @@ async function startHttpServer(configPath, options = {}) { // Handle OPTIONS preflight if (req.method === "OPTIONS") { + logger.debug("Handling OPTIONS preflight request"); res.writeHead(200); res.end(); return; @@ -180,6 +190,7 @@ async function startHttpServer(configPath, options = {}) { // Only handle POST requests for MCP protocol if (req.method !== "POST") { + logger.debug(`Rejecting non-POST request: ${req.method}`); res.writeHead(405, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Method not allowed" })); return; @@ -189,14 +200,18 @@ async function startHttpServer(configPath, options = {}) { // Parse request body for POST requests let body = null; if (req.method === "POST") { + logger.debug("Reading request body"); const chunks = []; for await (const chunk of req) { chunks.push(chunk); } const bodyStr = Buffer.concat(chunks).toString(); + logger.debug(`Request body size: ${bodyStr.length} bytes`); try { body = bodyStr ? JSON.parse(bodyStr) : null; + logger.debug(`Parsed request body: ${JSON.stringify(body)}`); } catch (parseError) { + logger.debugError("JSON parse error: ", parseError); res.writeHead(400, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -213,7 +228,9 @@ async function startHttpServer(configPath, options = {}) { } // Let the transport handle the request + logger.debug("Forwarding request to transport handler"); await transport.handleRequest(req, res, body); + logger.debug("Request handled successfully"); } catch (error) { logger.debugError("Error handling request: ", error); if (!res.headersSent) { diff --git a/pkg/workflow/safe_inputs_http_integration_test.go b/pkg/workflow/safe_inputs_http_integration_test.go index 2a473b027d..c92d4e12ef 100644 --- a/pkg/workflow/safe_inputs_http_integration_test.go +++ b/pkg/workflow/safe_inputs_http_integration_test.go @@ -93,9 +93,13 @@ Test safe-inputs HTTP server // Verify health check healthCheckItems := []string{ - "curl -s -f -H \"Authorization: Bearer", + "CURL_OUTPUT=$(mktemp)", + "CURL_HTTP_CODE=$(curl -s -w \"%{http_code}\" -H \"Authorization: Bearer", "Safe Inputs MCP server is ready", "ERROR: Safe Inputs MCP server failed to start", + "Server check failed (attempt", + "curl exit code:", + "HTTP status code:", } for _, check := range healthCheckItems { @@ -325,10 +329,16 @@ Test readiness check // Verify readiness check loop readinessChecks := []string{ "for i in {1..10}; do", - "if curl -s -f -H \"Authorization: Bearer", + "CURL_OUTPUT=$(mktemp)", + "CURL_HTTP_CODE=$(curl -s -w \"%{http_code}\" -H \"Authorization: Bearer", "http://localhost:$GH_AW_SAFE_INPUTS_PORT/", + "if [ $CURL_EXIT_CODE -eq 0 ] && [ \"$CURL_HTTP_CODE\" = \"200\" ]; then", "Safe Inputs MCP server is ready", "break", + "Server check failed (attempt $i/10):", + "curl exit code:", + "HTTP status code:", + "Response content:", "if [ $i -eq 10 ]; then", "ERROR: Safe Inputs MCP server failed to start after 10 seconds", "cat /tmp/gh-aw/safe-inputs/logs/server.log", diff --git a/pkg/workflow/sh/start_safe_inputs_server.sh b/pkg/workflow/sh/start_safe_inputs_server.sh index b5e46f3fa9..3fb539cbb0 100644 --- a/pkg/workflow/sh/start_safe_inputs_server.sh +++ b/pkg/workflow/sh/start_safe_inputs_server.sh @@ -41,9 +41,29 @@ for i in {1..10}; do fi # Check if server is responding - if curl -s -f -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ > /dev/null 2>&1; then + CURL_OUTPUT=$(mktemp) + CURL_HTTP_CODE=$(curl -s -w "%{http_code}" -H "Authorization: Bearer $GH_AW_SAFE_INPUTS_API_KEY" http://localhost:$GH_AW_SAFE_INPUTS_PORT/ -o "$CURL_OUTPUT" 2>&1) + CURL_EXIT_CODE=$? + + if [ $CURL_EXIT_CODE -eq 0 ] && [ "$CURL_HTTP_CODE" = "200" ]; then echo "Safe Inputs MCP server is ready (attempt $i/10)" + rm -f "$CURL_OUTPUT" break + else + # Log detailed failure information + echo "Server check failed (attempt $i/10):" + echo " - curl exit code: $CURL_EXIT_CODE" + echo " - HTTP status code: $CURL_HTTP_CODE" + if [ -f "$CURL_OUTPUT" ] && [ -s "$CURL_OUTPUT" ]; then + echo " - Response content:" + head -20 "$CURL_OUTPUT" + else + echo " - Response content: (empty)" + fi + rm -f "$CURL_OUTPUT" + # Show server log for additional debugging context + echo " - Server log:" + cat /tmp/gh-aw/safe-inputs/logs/server.log 2>/dev/null || echo "(log not available)" fi if [ $i -eq 10 ]; then