forked from anomalyco/opencode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcopilot.ts
More file actions
85 lines (73 loc) · 2.71 KB
/
copilot.ts
File metadata and controls
85 lines (73 loc) · 2.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { Installation } from "opencode/installation"
import { ModelsDev } from "opencode/provider/models"
const TOKEN_HEADER = "x-copilot-token"
const BASE_URL = "https://api.githubcopilot.com"
function detect(url: string, init?: RequestInit) {
try {
const body = typeof init?.body === "string" ? JSON.parse(init.body) : init?.body
// Completions API
if (body?.messages && url.includes("completions")) {
const last = body.messages[body.messages.length - 1]
return {
vision: body.messages.some(
(msg: any) => Array.isArray(msg.content) && msg.content.some((part: any) => part.type === "image_url"),
),
agent: last?.role !== "user",
}
}
// Responses API
if (body?.input) {
const last = body.input[body.input.length - 1]
return {
vision: body.input.some(
(item: any) => Array.isArray(item?.content) && item.content.some((part: any) => part.type === "input_image"),
),
agent: last?.role !== "user",
}
}
// Messages API
if (body?.messages) {
const last = body.messages[body.messages.length - 1]
const hasNonTool = Array.isArray(last?.content) && last.content.some((part: any) => part?.type !== "tool_result")
return {
vision: body.messages.some(
(item: any) =>
Array.isArray(item?.content) &&
item.content.some(
(part: any) =>
part?.type === "image" ||
(part?.type === "tool_result" &&
Array.isArray(part?.content) &&
part.content.some((nested: any) => nested?.type === "image")),
),
),
agent: !(last?.role === "user" && hasNonTool),
}
}
} catch {}
return { vision: false, agent: false }
}
export async function copilotFetch(request: RequestInfo | URL, init?: RequestInit) {
const incoming = (init?.headers ?? {}) as Record<string, string>
const token = incoming[TOKEN_HEADER]
if (!token) return fetch(request, init)
const url = request instanceof URL ? request.href : request.toString()
const { vision, agent } = detect(url, init)
const headers: Record<string, string> = {
"x-initiator": agent ? "agent" : "user",
...incoming,
"User-Agent": `opencode/${Installation.VERSION}`,
Authorization: `Bearer ${token}`,
"Openai-Intent": "conversation-edits",
}
if (vision) headers["Copilot-Vision-Request"] = "true"
delete headers[TOKEN_HEADER]
delete headers["x-api-key"]
delete headers["authorization"]
return fetch(request, { ...init, headers })
}
export { TOKEN_HEADER, BASE_URL }
export async function models() {
const data = await ModelsDev.get()
return data["github-copilot"]?.models ?? {}
}