Skip to content

Commit 0e98c05

Browse files
committed
refactor: Refactor API headers and add chat completion types
1 parent 43b3d29 commit 0e98c05

File tree

8 files changed

+99
-25
lines changed

8 files changed

+99
-25
lines changed

src/lib/api-config.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { State } from "./state"
2+
13
export const COPILOT_API_CONFIG = {
24
baseURL: "https://api.individual.githubcopilot.com",
35
headers: {
@@ -8,16 +10,20 @@ export const COPILOT_API_CONFIG = {
810
} as const
911

1012
export const COPILOT_API_BASE_URL = "https://api.individual.githubcopilot.com"
11-
const COPILOT_API_SPOOF_HEADERS = {
13+
export const copilotHeaders = (state: State) => ({
14+
Authorization: `token ${state.copilotToken}`,
1215
"copilot-integration-id": "vscode-chat",
13-
}
14-
15-
export const buildCopilotHeaders = (token: string) => ({
16-
Authorization: `token ${token}`,
17-
...COPILOT_API_SPOOF_HEADERS,
1816
})
1917

2018
export const GITHUB_API_BASE_URL = "https://api.github.com"
19+
export const githubHeaders = (state: State) => ({
20+
authorization: `token ${state.githubToken}`,
21+
"editor-version": `vscode/${state.vsCodeVersion}`,
22+
"editor-plugin-version": "copilot-chat/0.24.1",
23+
"user-agent": "GitHubCopilotChat/0.24.1",
24+
"x-github-api-version": "2024-12-15",
25+
"x-vscode-user-agent-library-version": "electron-fetch",
26+
})
2127

2228
export const GITHUB_BASE_URL = "https://github.com"
2329
export const GITHUB_CLIENT_ID = "01ab8ac9400c4e429b23"

src/lib/state.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import type { ModelsResponse } from "~/services/copilot/get-models"
22

3-
interface State {
3+
export interface State {
44
githubToken?: string
55
copilotToken?: string
6+
67
models?: ModelsResponse
8+
vsCodeVersion?: string
79
}
810

911
export const state: State = {}

src/lib/token.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import consola from "consola"
22
import fs from "node:fs/promises"
33

44
import { PATHS } from "~/lib/paths"
5-
import { getCopilotToken } from "~/services/copilot/get-copilot-token"
5+
import { getCopilotToken } from "~/services/github/get-copilot-token"
66
import { getDeviceCode } from "~/services/github/get-device-code"
77
import { getGitHubUser } from "~/services/github/get-user"
88
import { pollAccessToken } from "~/services/github/poll-access-token"
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// https://platform.openai.com/docs/api-reference
2+
3+
export interface Message {
4+
role: "user" | "assistant" | "system"
5+
content: string
6+
}
7+
8+
// Streaming types
9+
10+
export interface ExpectedCompletionChunk {
11+
choices: [Choice]
12+
created: number
13+
object: "chat.completion.chunk"
14+
id: string
15+
model: string
16+
}
17+
18+
interface Delta {
19+
content?: string
20+
role?: string
21+
}
22+
23+
interface Choice {
24+
index: number
25+
delta: Delta
26+
finish_reason: "stop" | null
27+
logprobs: null
28+
}
29+
30+
// Non-streaming types
31+
32+
export interface ExpectedCompletion {
33+
id: string
34+
object: string
35+
created: number
36+
model: string
37+
choices: [ChoiceNonStreaming]
38+
}
39+
40+
interface ChoiceNonStreaming {
41+
index: number
42+
message: Message
43+
logprobs: null
44+
finish_reason: "stop"
45+
}
46+
47+
// Payload types
48+
49+
export interface ExpectedChatCompletionPayload {
50+
model: string
51+
messages: Array<Message>
52+
stream: boolean
53+
}
Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { buildCopilotHeaders, COPILOT_API_BASE_URL } from "~/lib/api-config"
1+
import { events } from "fetch-event-stream"
2+
3+
import { copilotHeaders, COPILOT_API_BASE_URL } from "~/lib/api-config"
24
import { state } from "~/lib/state"
3-
import { copilot } from "~/services/api-instance"
45

56
import type { ChatCompletionResponse, ChatCompletionsPayload } from "./types"
67

@@ -11,7 +12,7 @@ export const createChatCompletions = async (
1112

1213
const response = await fetch(`${COPILOT_API_BASE_URL}/chat/completions`, {
1314
method: "POST",
14-
headers: buildCopilotHeaders(state.copilotToken),
15+
headers: copilotHeaders(state),
1516
body: JSON.stringify(payload),
1617
})
1718

@@ -22,13 +23,8 @@ export const createChatCompletions = async (
2223
}
2324

2425
if (payload.stream) {
26+
return events(response)
2527
}
26-
}
2728

28-
copilot<ChatCompletionResponse>("/chat/completions", {
29-
method: "POST",
30-
body: {
31-
...payload,
32-
stream: false,
33-
},
34-
})
29+
return (await response.json()) as ChatCompletionResponse
30+
}

src/services/copilot/create-embeddings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { buildCopilotHeaders, COPILOT_API_BASE_URL } from "~/lib/api-config"
1+
import { copilotHeaders, COPILOT_API_BASE_URL } from "~/lib/api-config"
22
import { state } from "~/lib/state"
33

44
export const createEmbeddings = async (payload: EmbeddingRequest) => {
55
if (!state.copilotToken) throw new Error("Copilot token not found")
66

77
const response = await fetch(`${COPILOT_API_BASE_URL}/embeddings`, {
88
method: "POST",
9-
headers: buildCopilotHeaders(state.copilotToken),
9+
headers: copilotHeaders(state),
1010
body: JSON.stringify(payload),
1111
})
1212

src/services/get-vscode-version.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const FALLBACK = "1.98.1"
2+
3+
export async function getVSCodeVersion() {
4+
const response = await fetch(
5+
"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin",
6+
)
7+
8+
const pkgbuild = await response.text()
9+
const pkgverRegex = /pkgver=([0-9.]+)/
10+
const match = pkgbuild.match(pkgverRegex)
11+
12+
if (match) {
13+
return match[1]
14+
}
15+
16+
return FALLBACK
17+
}
18+
19+
await getVSCodeVersion()
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import { GITHUB_API_BASE_URL } from "~/lib/api-config"
1+
import { GITHUB_API_BASE_URL, githubHeaders } from "~/lib/api-config"
22
import { state } from "~/lib/state"
33

44
export const getCopilotToken = async () => {
55
const response = await fetch(
66
`${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,
77
{
8-
headers: {
9-
authorization: `token ${state.githubToken}`,
10-
},
8+
headers: githubHeaders(state),
119
},
1210
)
1311

0 commit comments

Comments
 (0)