opencode-kilocode-auth 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/constants.ts +16 -6
- package/src/kilocode/auth.ts +12 -1
- package/src/plugin.ts +33 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-kilocode-auth",
|
|
3
3
|
"module": "index.ts",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.9",
|
|
5
5
|
"author": "ported from Kilo Code",
|
|
6
6
|
"description": "OpenCode plugin for Kilo Code authentication with support for various models including Giga Potato",
|
|
7
7
|
"files": [
|
package/src/constants.ts
CHANGED
|
@@ -17,21 +17,31 @@ export const KILOCODE_API_BASE_URL = "https://api.kilo.ai";
|
|
|
17
17
|
*/
|
|
18
18
|
export const KILOCODE_PROVIDER_ID = "kilocode";
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Kilo Code extension version (must match official extension)
|
|
22
|
+
*/
|
|
23
|
+
export const KILOCODE_VERSION = "4.151.0";
|
|
24
|
+
|
|
20
25
|
/**
|
|
21
26
|
* Default headers for Kilo Code API requests
|
|
27
|
+
* EXACT match from kilocode/src/api/providers/constants.ts DEFAULT_HEADERS
|
|
22
28
|
*/
|
|
23
29
|
export const DEFAULT_HEADERS = {
|
|
24
30
|
"Content-Type": "application/json",
|
|
25
|
-
"
|
|
31
|
+
"HTTP-Referer": "https://kilocode.ai",
|
|
32
|
+
"X-Title": "Kilo Code",
|
|
33
|
+
"X-KiloCode-Version": KILOCODE_VERSION,
|
|
34
|
+
"User-Agent": `Kilo-Code/${KILOCODE_VERSION}`,
|
|
26
35
|
} as const;
|
|
27
36
|
|
|
28
37
|
/**
|
|
29
|
-
* Kilo Code custom headers
|
|
38
|
+
* Kilo Code custom headers (EXACT casing from kilocode/src/shared/kilocode/headers.ts)
|
|
30
39
|
*/
|
|
31
|
-
export const
|
|
32
|
-
export const
|
|
33
|
-
export const
|
|
34
|
-
export const
|
|
40
|
+
export const X_KILOCODE_VERSION = "X-KiloCode-Version";
|
|
41
|
+
export const X_KILOCODE_ORGANIZATIONID = "X-KiloCode-OrganizationId";
|
|
42
|
+
export const X_KILOCODE_TASKID = "X-KiloCode-TaskId";
|
|
43
|
+
export const X_KILOCODE_PROJECTID = "X-KiloCode-ProjectId";
|
|
44
|
+
export const X_KILOCODE_EDITORNAME = "X-KiloCode-EditorName";
|
|
35
45
|
|
|
36
46
|
/**
|
|
37
47
|
* Default model ID if none is specified
|
package/src/kilocode/auth.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
DEFAULT_HEADERS,
|
|
5
5
|
DEVICE_AUTH_POLL_INTERVAL_MS,
|
|
6
6
|
DEFAULT_MODEL_ID,
|
|
7
|
+
X_KILOCODE_EDITORNAME,
|
|
7
8
|
} from "../constants";
|
|
8
9
|
import type {
|
|
9
10
|
DeviceAuthInitiateResponse,
|
|
@@ -82,6 +83,13 @@ export async function pollDeviceAuth(code: string): Promise<DeviceAuthPollRespon
|
|
|
82
83
|
return (await response.json()) as DeviceAuthPollResponse;
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Get editor name header value (matches Kilo Code VSCode extension)
|
|
88
|
+
*/
|
|
89
|
+
function getEditorNameHeader(): string {
|
|
90
|
+
return "Visual Studio Code 1.96.0";
|
|
91
|
+
}
|
|
92
|
+
|
|
85
93
|
/**
|
|
86
94
|
* Fetch user profile from Kilo Code API
|
|
87
95
|
*/
|
|
@@ -90,6 +98,7 @@ export async function getKilocodeProfile(token: string): Promise<KilocodeProfile
|
|
|
90
98
|
headers: {
|
|
91
99
|
...DEFAULT_HEADERS,
|
|
92
100
|
Authorization: `Bearer ${token}`,
|
|
101
|
+
[X_KILOCODE_EDITORNAME]: getEditorNameHeader(),
|
|
93
102
|
},
|
|
94
103
|
});
|
|
95
104
|
|
|
@@ -119,6 +128,7 @@ export async function getKilocodeDefaultModel(
|
|
|
119
128
|
headers: {
|
|
120
129
|
...DEFAULT_HEADERS,
|
|
121
130
|
Authorization: `Bearer ${token}`,
|
|
131
|
+
[X_KILOCODE_EDITORNAME]: getEditorNameHeader(),
|
|
122
132
|
},
|
|
123
133
|
});
|
|
124
134
|
|
|
@@ -146,10 +156,11 @@ export async function getKilocodeModels(
|
|
|
146
156
|
const headers: Record<string, string> = {
|
|
147
157
|
...DEFAULT_HEADERS,
|
|
148
158
|
Authorization: `Bearer ${token}`,
|
|
159
|
+
[X_KILOCODE_EDITORNAME]: getEditorNameHeader(),
|
|
149
160
|
};
|
|
150
161
|
|
|
151
162
|
if (organizationId) {
|
|
152
|
-
headers["X-
|
|
163
|
+
headers["X-KiloCode-OrganizationId"] = organizationId;
|
|
153
164
|
}
|
|
154
165
|
|
|
155
166
|
const response = await fetch(baseUrl, { headers });
|
package/src/plugin.ts
CHANGED
|
@@ -130,8 +130,40 @@ export async function KilocodeAuthPlugin(input: PluginInput): Promise<Hooks> {
|
|
|
130
130
|
// Map to Kilo Code OpenRouter-compatible endpoint
|
|
131
131
|
// Kilo Code uses: https://api.kilo.ai/api/openrouter/chat/completions
|
|
132
132
|
let url: URL
|
|
133
|
+
let body = init?.body
|
|
134
|
+
|
|
133
135
|
if (parsed.pathname.includes("/chat/completions")) {
|
|
134
136
|
url = new URL(getApiUrl("/api/openrouter/chat/completions", currentToken))
|
|
137
|
+
|
|
138
|
+
// Modify request body to match Kilo Code format EXACTLY
|
|
139
|
+
if (body && typeof body === "string") {
|
|
140
|
+
try {
|
|
141
|
+
const payload = JSON.parse(body)
|
|
142
|
+
|
|
143
|
+
// Add stream_options like Kilo Code does (ALWAYS included)
|
|
144
|
+
if (payload.stream !== false) {
|
|
145
|
+
payload.stream_options = { include_usage: true }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (payload.messages && Array.isArray(payload.messages)) {
|
|
149
|
+
// Find system message and prepend Kilo Code role
|
|
150
|
+
const systemIdx = payload.messages.findIndex((m: any) => m.role === "system")
|
|
151
|
+
const kiloCodeRole = "You are Kilo Code, a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices."
|
|
152
|
+
|
|
153
|
+
if (systemIdx >= 0) {
|
|
154
|
+
// Prepend Kilo Code role to existing system message
|
|
155
|
+
payload.messages[systemIdx].content = kiloCodeRole + "\n\n" + payload.messages[systemIdx].content
|
|
156
|
+
} else {
|
|
157
|
+
// Add system message at the beginning
|
|
158
|
+
payload.messages.unshift({ role: "system", content: kiloCodeRole })
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
body = JSON.stringify(payload)
|
|
163
|
+
} catch {
|
|
164
|
+
// Keep original body if parsing fails
|
|
165
|
+
}
|
|
166
|
+
}
|
|
135
167
|
} else if (parsed.pathname.includes("/models")) {
|
|
136
168
|
url = new URL(getApiUrl("/api/openrouter/models", currentToken))
|
|
137
169
|
} else {
|
|
@@ -141,6 +173,7 @@ export async function KilocodeAuthPlugin(input: PluginInput): Promise<Hooks> {
|
|
|
141
173
|
return fetch(url, {
|
|
142
174
|
...init,
|
|
143
175
|
headers,
|
|
176
|
+
body,
|
|
144
177
|
})
|
|
145
178
|
},
|
|
146
179
|
}
|