opencode-kilocode-auth 1.0.4 → 1.0.6

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/plugin.ts +74 -4
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",
4
+ "version": "1.0.6",
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/plugin.ts CHANGED
@@ -2,11 +2,15 @@ import type { Hooks, PluginInput } from "@opencode-ai/plugin"
2
2
  import {
3
3
  KILOCODE_PROVIDER_ID,
4
4
  DEFAULT_MODEL_ID,
5
+ DEVICE_AUTH_POLL_INTERVAL_MS,
5
6
  } from "./constants"
6
7
  import {
8
+ initiateDeviceAuth,
9
+ pollDeviceAuth,
7
10
  getKilocodeProfile,
8
11
  getKilocodeDefaultModel,
9
12
  getKilocodeModels,
13
+ openBrowserUrl,
10
14
  getApiUrl,
11
15
  } from "./kilocode/auth"
12
16
 
@@ -76,7 +80,7 @@ export async function KilocodeAuthPlugin(input: PluginInput): Promise<Hooks> {
76
80
 
77
81
  const currentKilocodeAuth = currentAuth as KilocodeAuth
78
82
  const currentToken = currentKilocodeAuth.type === "api"
79
- ? currentKilocodeAuth.apiKey
83
+ ? currentKilocodeAuth.key
80
84
  : currentKilocodeAuth.refresh
81
85
 
82
86
  if (!currentToken) {
@@ -101,10 +105,11 @@ export async function KilocodeAuthPlugin(input: PluginInput): Promise<Hooks> {
101
105
 
102
106
  // Set Kilo Code authorization and required headers
103
107
  headers.set("Authorization", `Bearer ${currentToken}`)
108
+ headers.set("x-api-key", currentToken) // Kilo Code uses both
104
109
  headers.set("HTTP-Referer", "https://kilocode.ai")
105
110
  headers.set("X-Title", "Kilo Code")
106
- headers.set("X-KiloCode-Version", "3.16.3")
107
- headers.set("User-Agent", "Kilo-Code/3.16.3")
111
+ headers.set("X-KiloCode-Version", "4.151.0")
112
+ headers.set("User-Agent", "Kilo-Code/4.151.0")
108
113
  headers.set("X-KiloCode-EditorName", "Visual Studio Code 1.96.0")
109
114
 
110
115
  // Add organization header if present
@@ -138,7 +143,72 @@ export async function KilocodeAuthPlugin(input: PluginInput): Promise<Hooks> {
138
143
  },
139
144
 
140
145
  methods: [
141
- // API key is the primary method - get it from https://app.kilo.ai
146
+ {
147
+ type: "oauth",
148
+ label: "Login with Kilo Code (Device Auth)",
149
+ async authorize() {
150
+ const authData = await initiateDeviceAuth()
151
+ const { code, verificationUrl, expiresIn } = authData
152
+
153
+ openBrowserUrl(verificationUrl)
154
+
155
+ return {
156
+ url: verificationUrl,
157
+ instructions: `Enter code: ${code}`,
158
+ method: "auto" as const,
159
+
160
+ async callback() {
161
+ const maxAttempts = Math.ceil((expiresIn * 1000) / DEVICE_AUTH_POLL_INTERVAL_MS)
162
+ let attempt = 0
163
+
164
+ while (attempt < maxAttempts) {
165
+ await new Promise((resolve) => setTimeout(resolve, DEVICE_AUTH_POLL_INTERVAL_MS))
166
+
167
+ try {
168
+ const pollResult = await pollDeviceAuth(code)
169
+
170
+ if (pollResult.status === "approved" && pollResult.token) {
171
+ let organizationId: string | undefined
172
+ try {
173
+ const profile = await getKilocodeProfile(pollResult.token)
174
+ if (profile.organizations && profile.organizations.length > 0) {
175
+ organizationId = profile.organizations[0].id
176
+ }
177
+ } catch {
178
+ // Continue without organization
179
+ }
180
+
181
+ const model = await getKilocodeDefaultModel(pollResult.token, organizationId)
182
+
183
+ return {
184
+ type: "success" as const,
185
+ refresh: pollResult.token,
186
+ access: pollResult.token,
187
+ expires: Date.now() + 365 * 24 * 60 * 60 * 1000,
188
+ organizationId,
189
+ model,
190
+ } as any
191
+ }
192
+
193
+ if (pollResult.status === "denied") {
194
+ return { type: "failed" as const }
195
+ }
196
+
197
+ if (pollResult.status === "expired") {
198
+ return { type: "failed" as const }
199
+ }
200
+ } catch {
201
+ // Continue polling on error
202
+ }
203
+
204
+ attempt++
205
+ }
206
+
207
+ return { type: "failed" as const }
208
+ },
209
+ }
210
+ },
211
+ },
142
212
  {
143
213
  type: "api",
144
214
  label: "Enter API Key (get from app.kilo.ai)",