Repository navigation
fix(github): drop trailing assistant prefill for Copilot chat - #5802
Conversation
GitHub Copilot's /chat/completions endpoint rejects a conversation that ends with an assistant message: "This model does not support assistant message prefill. The conversation must end with a user message." (HTTP 400). Anthropic clients such as newest Claude Desktop send a trailing assistant turn as a prefill seed — the Anthropic API honors it, but Copilot does not. Add a self-contained GithubExecutor.dropTrailingAssistantPrefill() that strips trailing assistant message(s) before dispatch, called at the end of transformRequest right after the existing sanitizeChatCompletionsMessage map. Scoped to the GitHub executor only — the shared translator/contextManager and other providers that do honor prefill (e.g. Mistral's dedicated Set) are untouched. Never empties the array (an assistant-only conversation keeps its last message); no-op (same array reference) when the conversation already ends with a user/tool message. Two pre-existing executor-github.test.ts fixtures incidentally ended in a bare trailing assistant message while testing unrelated behavior (reasoning-field stripping, tool_calls pass-through); extended them with a trailing user/tool turn so they keep exercising their original intent instead of tripping the new prefill guard. Regression guard: tests/unit/executor-github-prefill-sanitize.test.ts (8 cases — single/multiple trailing assistant, user/tool no-op with reference identity, assistant-only never-empty, null/empty safety, and two end-to-end transformRequest checks). Port of decolua/9router#2143. Co-authored-by: Manuel <baslr@users.noreply.github.com> Inspired-by: decolua/9router#2143
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Code Review
This pull request introduces a mechanism to drop trailing assistant messages (prefill seeds) from conversations sent to the GitHub Copilot executor, preventing HTTP 400 errors. It adds a helper method dropTrailingAssistantPrefill and corresponding unit tests, while updating existing tests to prevent unexpected message stripping. The reviewer suggested making the role check case-insensitive to handle potential variations in role casing (such as Assistant or ASSISTANT) robustly.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| dropTrailingAssistantPrefill(messages: any): any { | ||
| if (!Array.isArray(messages) || messages.length === 0) return messages; | ||
| let end = messages.length; | ||
| while (end > 1 && messages[end - 1]?.role === "assistant") end--; |
There was a problem hiding this comment.
The check for the assistant role is case-sensitive (messages[end - 1]?.role === "assistant"). However, some clients may send roles in mixed-case or uppercase (e.g., "Assistant" or "ASSISTANT"). To ensure robustness and prevent unexpected HTTP 400 errors from GitHub Copilot, the role check should be case-insensitive, similar to how it is handled in transformRequest.
| while (end > 1 && messages[end - 1]?.role === "assistant") end--; | |
| while (end > 1 && typeof messages[end - 1]?.role === "string" && messages[end - 1].role.toLowerCase() === "assistant") end--; |
…r-2143-github-prefill
…GitHub Copilot prefill bullet
…r-2143-github-prefill
…r-inference#5802) Integrated into release/v3.8.43
Summary
GitHub Copilot's
/chat/completionsrejects (400) a request whose last message is an assistant prefill. This strips trailing assistant message(s) before dispatching to GitHub Copilot, scoped to the GitHub executor only (real Anthropic/OpenAI upstreams honor prefill, so the shared translator is untouched).Changes
open-sse/executors/github.ts— newdropTrailingAssistantPrefill(messages)method, called at the end oftransformRequest(right aftersanitizeChatCompletionsMessage). Returns the same array reference when the conversation already ends inuser/tool(no-op); never empties an assistant-only array; null/empty safe.executor-github.test.tsfixtures that incidentally ended in a bare trailing assistant were given a realistic trailinguser/toolturn so they keep testing their original intent (response_format injection, tool_calls pass-through) instead of tripping the new guard — no assertions removed or weakened.Attribution
Thanks to @baslr for the original implementation.
Testing
TDD (Hard Rule #18): new
tests/unit/executor-github-prefill-sanitize.test.ts(8 cases) fails before the method exists (7/8 red), passes after (8/8). Fullexecutor-github.test.ts+ related GitHub-executor suites green (25/25).typecheck:core,eslint,check:any-budget:t11clean.