From 51c734e4388a4b6b3000348290d7ff81386dbfbc Mon Sep 17 00:00:00 2001 From: mac Date: Thu, 2 Apr 2026 17:06:26 +0800 Subject: [PATCH] fix: GitHub Copilot token refresh and reasoning field stripping - Strip reasoning_text/reasoning_content from assistant messages in GitHub executor to prevent upstream 400 'Invalid signature in thinking block' errors - Sync refreshed copilotToken to top-level credentials in checkAndRefreshToken so buildHeaders() uses the fresh token instead of the stale one - Include providerSpecificData in refreshCredentials return value so onCredentialsRefreshed persists the new token to DB correctly --- open-sse/executors/github.ts | 21 +++++++++++++++++++++ src/sse/services/tokenRefresh.ts | 2 ++ 2 files changed, 23 insertions(+) diff --git a/open-sse/executors/github.ts b/open-sse/executors/github.ts index 95c8f1f762..42abe949a7 100644 --- a/open-sse/executors/github.ts +++ b/open-sse/executors/github.ts @@ -55,6 +55,19 @@ export class GithubExecutor extends BaseExecutor { ); delete modifiedBody.response_format; } + + // Strip reasoning_text / reasoning_content from assistant messages. + // GitHub Copilot converts these into Anthropic thinking blocks but cannot + // supply a valid `signature`, causing upstream 400 errors. + if (Array.isArray(modifiedBody.messages)) { + for (const msg of modifiedBody.messages) { + if (msg.role === "assistant") { + delete msg.reasoning_text; + delete msg.reasoning_content; + } + } + } + return modifiedBody; } @@ -167,6 +180,10 @@ export class GithubExecutor extends BaseExecutor { ...githubTokens, copilotToken: copilotResult.token, copilotTokenExpiresAt: copilotResult.expiresAt, + providerSpecificData: { + copilotToken: copilotResult.token, + copilotTokenExpiresAt: copilotResult.expiresAt, + }, }; } return githubTokens; @@ -179,6 +196,10 @@ export class GithubExecutor extends BaseExecutor { refreshToken: credentials.refreshToken, copilotToken: copilotResult.token, copilotTokenExpiresAt: copilotResult.expiresAt, + providerSpecificData: { + copilotToken: copilotResult.token, + copilotTokenExpiresAt: copilotResult.expiresAt, + }, }; } diff --git a/src/sse/services/tokenRefresh.ts b/src/sse/services/tokenRefresh.ts index 87231e96a9..520e2d9992 100644 --- a/src/sse/services/tokenRefresh.ts +++ b/src/sse/services/tokenRefresh.ts @@ -141,6 +141,8 @@ export async function checkAndRefreshToken(provider: string, credentials: any) { copilotToken: copilotToken.token, copilotTokenExpiresAt: copilotToken.expiresAt, }; + // Sync to top-level so buildHeaders() picks up the fresh token + updatedCredentials.copilotToken = copilotToken.token; } } }