Dax 6 месяцев назад
Родитель
Сommit
f19586cebd

+ 1 - 0
bun.lock

@@ -15,6 +15,7 @@
       "name": "@opencode/cloud-app",
       "name": "@opencode/cloud-app",
       "dependencies": {
       "dependencies": {
         "@ibm/plex": "6.4.1",
         "@ibm/plex": "6.4.1",
+        "@openauthjs/openauth": "0.0.0-20250322224806",
         "@solidjs/meta": "^0.29.4",
         "@solidjs/meta": "^0.29.4",
         "@solidjs/router": "^0.15.0",
         "@solidjs/router": "^0.15.0",
         "@solidjs/start": "^1.1.0",
         "@solidjs/start": "^1.1.0",

+ 1 - 0
cloud/app/package.json

@@ -9,6 +9,7 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "@ibm/plex": "6.4.1",
     "@ibm/plex": "6.4.1",
+    "@openauthjs/openauth": "0.0.0-20250322224806",
     "@solidjs/meta": "^0.29.4",
     "@solidjs/meta": "^0.29.4",
     "@solidjs/router": "^0.15.0",
     "@solidjs/router": "^0.15.0",
     "@solidjs/start": "^1.1.0",
     "@solidjs/start": "^1.1.0",

+ 28 - 0
cloud/app/src/context/auth.tsx

@@ -0,0 +1,28 @@
+import { useSession } from "vinxi/http"
+import { createClient } from "@openauthjs/openauth/client"
+
+export const AuthClient = createClient({
+  clientID: "app",
+  issuer: "https://auth.dev.opencode.ai",
+})
+
+export interface AuthSession {
+  account: Record<string, {
+    id: string
+    email: string
+  }>
+  current?: string
+}
+
+export function useAuthSession() {
+  "use server"
+
+  return useSession<AuthSession>({
+    password: "0".repeat(32),
+    name: "auth"
+  })
+}
+
+
+export function AuthProvider() {
+}

+ 7 - 0
cloud/app/src/routes/auth/authorize.ts

@@ -0,0 +1,7 @@
+import type { APIEvent } from "@solidjs/start/server"
+import { AuthClient } from "~/context/auth"
+
+export async function GET(input: APIEvent) {
+  const result = await AuthClient.authorize(new URL("./callback", input.request.url).toString(), "code")
+  return Response.redirect(result.url, 302)
+}

+ 36 - 0
cloud/app/src/routes/auth/callback.ts

@@ -0,0 +1,36 @@
+import type { APIEvent } from "@solidjs/start/server"
+import { AuthClient, useAuthSession } from "~/context/auth"
+
+export async function GET(input: APIEvent) {
+  const url = new URL(input.request.url)
+  const code = url.searchParams.get("code")
+  if (!code) throw new Error("No code found")
+  const redirectURI = `${url.origin}${url.pathname}`
+  console.log({
+    redirectURI,
+    code,
+  })
+  const result = await AuthClient.exchange(code, `${url.origin}${url.pathname}`)
+  if (result.err) {
+    throw new Error(result.err.message)
+  }
+  const decoded = AuthClient.decode(result.tokens.access, {} as any)
+  if (decoded.err) throw new Error(decoded.err.message)
+  const session = await useAuthSession()
+  const id = decoded.subject.properties.accountID
+  await session.update((value) => {
+    return {
+      ...value,
+      account: {
+        [id]: {
+          id,
+          email: decoded.subject.properties.email,
+        },
+      },
+      current: id,
+    }
+  })
+  return {
+    result,
+  }
+}

+ 1 - 1
cloud/app/src/routes/index.tsx

@@ -51,7 +51,7 @@ export default function Home() {
             <a href="/docs">Get Started</a>
             <a href="/docs">Get Started</a>
           </div>
           </div>
           <div data-slot="right">
           <div data-slot="right">
-            <button data-copy data-slot="command" data-command="curl -fsSL https://opencode.ai/install | bash">
+            <button data-copy data-slot="command">
               <span>
               <span>
                 <span>curl -fsSL&nbsp;</span>
                 <span>curl -fsSL&nbsp;</span>
                 <span data-slot="protocol">https://</span>
                 <span data-slot="protocol">https://</span>

+ 28 - 12
packages/opencode/src/cli/cmd/auth.ts

@@ -176,12 +176,20 @@ export const AuthLoginCommand = cmd({
               spinner.stop("Failed to authorize", 1)
               spinner.stop("Failed to authorize", 1)
             }
             }
             if (result.type === "success") {
             if (result.type === "success") {
-              await Auth.set(provider, {
-                type: "oauth",
-                refresh: result.refresh,
-                access: result.access,
-                expires: result.expires,
-              })
+              if ("refresh" in result) {
+                await Auth.set(provider, {
+                  type: "oauth",
+                  refresh: result.refresh,
+                  access: result.access,
+                  expires: result.expires,
+                })
+              }
+              if ("key" in result) {
+                await Auth.set(provider, {
+                  type: "api",
+                  key: result.key,
+                })
+              }
               spinner.stop("Login successful")
               spinner.stop("Login successful")
             }
             }
           }
           }
@@ -197,12 +205,20 @@ export const AuthLoginCommand = cmd({
               prompts.log.error("Failed to authorize")
               prompts.log.error("Failed to authorize")
             }
             }
             if (result.type === "success") {
             if (result.type === "success") {
-              await Auth.set(provider, {
-                type: "oauth",
-                refresh: result.refresh,
-                access: result.access,
-                expires: result.expires,
-              })
+              if ("refresh" in result) {
+                await Auth.set(provider, {
+                  type: "oauth",
+                  refresh: result.refresh,
+                  access: result.access,
+                  expires: result.expires,
+                })
+              }
+              if ("key" in result) {
+                await Auth.set(provider, {
+                  type: "api",
+                  key: result.key,
+                })
+              }
               prompts.log.success("Login successful")
               prompts.log.success("Login successful")
             }
             }
           }
           }

+ 0 - 0
packages/opencode/src/cli/cmd/opentui/opentui.ts


+ 1 - 1
packages/opencode/src/plugin/index.ts

@@ -26,7 +26,7 @@ export namespace Plugin {
     const plugins = [...(config.plugin ?? [])]
     const plugins = [...(config.plugin ?? [])]
     if (!Flag.OPENCODE_DISABLE_DEFAULT_PLUGINS) {
     if (!Flag.OPENCODE_DISABLE_DEFAULT_PLUGINS) {
       plugins.push("opencode-copilot-auth")
       plugins.push("opencode-copilot-auth")
-      plugins.push("opencode-anthropic-auth")
+      plugins.push("opencode-anthropic-auth@0.0.2")
     }
     }
     for (let plugin of plugins) {
     for (let plugin of plugins) {
       log.info("loading plugin", { path: plugin })
       log.info("loading plugin", { path: plugin })

+ 18 - 10
packages/plugin/src/index.ts

@@ -32,12 +32,16 @@ export interface Hooks {
               | {
               | {
                   method: "auto"
                   method: "auto"
                   callback(): Promise<
                   callback(): Promise<
-                    | {
+                    | ({
                         type: "success"
                         type: "success"
-                        refresh: string
-                        access: string
-                        expires: number
-                      }
+                      } & (
+                        | {
+                            refresh: string
+                            access: string
+                            expires: number
+                          }
+                        | { key: string }
+                      ))
                     | {
                     | {
                         type: "failed"
                         type: "failed"
                       }
                       }
@@ -46,12 +50,16 @@ export interface Hooks {
               | {
               | {
                   method: "code"
                   method: "code"
                   callback(code: string): Promise<
                   callback(code: string): Promise<
-                    | {
+                    | ({
                         type: "success"
                         type: "success"
-                        refresh: string
-                        access: string
-                        expires: number
-                      }
+                      } & (
+                        | {
+                            refresh: string
+                            access: string
+                            expires: number
+                          }
+                        | { key: string }
+                      ))
                     | {
                     | {
                         type: "failed"
                         type: "failed"
                       }
                       }