opencode-kilocode-auth 1.0.5 → 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 +71 -2
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.5",
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) {
@@ -139,7 +143,72 @@ export async function KilocodeAuthPlugin(input: PluginInput): Promise<Hooks> {
139
143
  },
140
144
 
141
145
  methods: [
142
- // 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
+ },
143
212
  {
144
213
  type: "api",
145
214
  label: "Enter API Key (get from app.kilo.ai)",