/** * Builds GitHub Copilot provider compatibility headers from message content. */ import type { Context } from "../llm/types.js"; /** @deprecated GitHub Copilot provider-owned helper; do not use from third-party plugins. */ export const COPILOT_EDITOR_VERSION = "vscode/1.107.0"; /** @deprecated GitHub Copilot provider-owned helper; do not use from third-party plugins. */ export const COPILOT_USER_AGENT = "GitHubCopilotChat/0.35.0"; /** @deprecated GitHub Copilot provider-owned helper; do not use from third-party plugins. */ export const COPILOT_EDITOR_PLUGIN_VERSION = "copilot-chat/0.35.0"; /** @deprecated GitHub Copilot provider-owned helper; do not use from third-party plugins. */ export const COPILOT_GITHUB_API_VERSION = "2025-04-01"; /** @deprecated GitHub Copilot provider-owned helper; do not use from third-party plugins. */ export const COPILOT_INTEGRATION_ID = "vscode-chat"; /** @deprecated GitHub Copilot provider-owned helper; do not use from third-party plugins. */ export function buildCopilotIdeHeaders( params: { includeApiVersion?: boolean; } = {}, ): Record { return { "Accept-Encoding": "identity", "Editor-Version": COPILOT_EDITOR_VERSION, "Editor-Plugin-Version": COPILOT_EDITOR_PLUGIN_VERSION, "User-Agent": COPILOT_USER_AGENT, ...(params.includeApiVersion ? { "X-Github-Api-Version": COPILOT_GITHUB_API_VERSION } : {}), }; } function inferCopilotInitiator(messages: Context["messages"]): "agent" | "user" { const last = messages[messages.length - 1]; if (!last) { return "user"; } if (last.role === "user" && containsCopilotContentType(last.content, "tool_result")) { return "agent"; } return last.role === "user" ? "user" : "agent"; } function containsCopilotContentType(value: unknown, type: string): boolean { if (Array.isArray(value)) { return value.some((item) => containsCopilotContentType(item, type)); } if (!value || typeof value !== "object") { return false; } const entry = value as { type?: unknown; content?: unknown }; return entry.type === type || containsCopilotContentType(entry.content, type); } /** Return true when Copilot should receive its vision request header. */ export function hasCopilotVisionInput(messages: Context["messages"]): boolean { return messages.some((message) => { if (message.role === "user" && Array.isArray(message.content)) { return message.content.some((item) => containsCopilotContentType(item, "image")); } if (message.role === "toolResult" && Array.isArray(message.content)) { return message.content.some((item) => containsCopilotContentType(item, "image")); } return false; }); } /** Build per-request Copilot headers, including initiator and vision flags. */ export function buildCopilotDynamicHeaders(params: { messages: Context["messages"]; hasImages: boolean; }): Record { return { ...buildCopilotIdeHeaders(), "Copilot-Integration-Id": COPILOT_INTEGRATION_ID, "Openai-Organization": "github-copilot", "x-initiator": inferCopilotInitiator(params.messages), ...(params.hasImages ? { "Copilot-Vision-Request": "true" } : {}), }; }