mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-31 14:22:27 +00:00
Refactor authentication system to consolidate auth flow and remove provider-based commands
🤖 Generated with [OpenCode](https://opencode.ai) Co-Authored-By: OpenCode <noreply@opencode.ai>
This commit is contained in:
144
packages/opencode/src/cli/cmd/auth.ts
Normal file
144
packages/opencode/src/cli/cmd/auth.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { AuthAnthropic } from "../../auth/anthropic"
|
||||
import { Auth } from "../../auth"
|
||||
import { cmd } from "./cmd"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import open from "open"
|
||||
import { UI } from "../ui"
|
||||
import { ModelsDev } from "../../provider/models"
|
||||
|
||||
export const AuthCommand = cmd({
|
||||
command: "auth",
|
||||
builder: (yargs) =>
|
||||
yargs
|
||||
.command(AuthLoginCommand)
|
||||
.command(AuthLogoutCommand)
|
||||
.command(AuthListCommand)
|
||||
.demandCommand(),
|
||||
async handler(args) {},
|
||||
})
|
||||
|
||||
export const AuthListCommand = cmd({
|
||||
command: "list",
|
||||
aliases: ["ls"],
|
||||
describe: "list providers",
|
||||
async handler() {
|
||||
UI.empty()
|
||||
prompts.intro("Credentials")
|
||||
const results = await Auth.all().then((x) => Object.entries(x))
|
||||
const database = await ModelsDev.get()
|
||||
|
||||
for (const [providerID, result] of results) {
|
||||
const name = database[providerID]?.name || providerID
|
||||
prompts.log.info(`${name} ${Bun.color("gray", "ansi")}(${result.type})`)
|
||||
}
|
||||
|
||||
prompts.outro(`${results.length} credentials`)
|
||||
},
|
||||
})
|
||||
|
||||
export const AuthLoginCommand = cmd({
|
||||
command: "login",
|
||||
describe: "login to a provider",
|
||||
async handler() {
|
||||
UI.empty()
|
||||
prompts.intro("Add credential")
|
||||
const provider = await prompts.select({
|
||||
message: "Select provider",
|
||||
maxItems: 2,
|
||||
options: [
|
||||
{
|
||||
label: "Anthropic",
|
||||
value: "anthropic",
|
||||
},
|
||||
{
|
||||
label: "OpenAI",
|
||||
value: "openai",
|
||||
},
|
||||
{
|
||||
label: "Google",
|
||||
value: "google",
|
||||
},
|
||||
],
|
||||
})
|
||||
if (prompts.isCancel(provider)) throw new UI.CancelledError()
|
||||
|
||||
if (provider === "anthropic") {
|
||||
const method = await prompts.select({
|
||||
message: "Login method",
|
||||
options: [
|
||||
{
|
||||
label: "Claude Pro/Max",
|
||||
value: "oauth",
|
||||
},
|
||||
{
|
||||
label: "API Key",
|
||||
value: "api",
|
||||
},
|
||||
],
|
||||
})
|
||||
if (prompts.isCancel(method)) throw new UI.CancelledError()
|
||||
|
||||
if (method === "oauth") {
|
||||
// some weird bug where program exits without this
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
const { url, verifier } = await AuthAnthropic.authorize()
|
||||
prompts.note("Opening browser...")
|
||||
await open(url)
|
||||
prompts.log.info(url)
|
||||
|
||||
const code = await prompts.text({
|
||||
message: "Paste the authorization code here: ",
|
||||
validate: (x) => (x.length > 0 ? undefined : "Required"),
|
||||
})
|
||||
if (prompts.isCancel(code)) throw new UI.CancelledError()
|
||||
|
||||
await AuthAnthropic.exchange(code, verifier)
|
||||
.then(() => {
|
||||
prompts.log.success("Login successful")
|
||||
})
|
||||
.catch(() => {
|
||||
prompts.log.error("Invalid code")
|
||||
})
|
||||
prompts.outro("Done")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const key = await prompts.password({
|
||||
message: "Enter your API key",
|
||||
validate: (x) => (x.length > 0 ? undefined : "Required"),
|
||||
})
|
||||
if (prompts.isCancel(key)) throw new UI.CancelledError()
|
||||
await Auth.set(provider, {
|
||||
type: "api",
|
||||
key,
|
||||
})
|
||||
|
||||
prompts.outro("Done")
|
||||
},
|
||||
})
|
||||
|
||||
export const AuthLogoutCommand = cmd({
|
||||
command: "logout",
|
||||
describe: "logout from a configured provider",
|
||||
async handler() {
|
||||
UI.empty()
|
||||
const credentials = await Auth.all().then((x) => Object.entries(x))
|
||||
prompts.intro("Remove credential")
|
||||
if (credentials.length === 0) {
|
||||
prompts.log.error("No credentials found")
|
||||
return
|
||||
}
|
||||
const database = await ModelsDev.get()
|
||||
const providerID = await prompts.select({
|
||||
message: "Select credential",
|
||||
options: credentials.map(([key, value]) => ({
|
||||
label: database[key]?.name || key,
|
||||
value: key,
|
||||
})),
|
||||
})
|
||||
if (prompts.isCancel(providerID)) throw new UI.CancelledError()
|
||||
await Auth.remove(providerID)
|
||||
prompts.outro("Logout successful")
|
||||
},
|
||||
})
|
||||
@@ -1,120 +0,0 @@
|
||||
import { App } from "../../app/app"
|
||||
import { AuthAnthropic } from "../../auth/anthropic"
|
||||
import { AuthKeys } from "../../auth/keys"
|
||||
import { cmd } from "./cmd"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import open from "open"
|
||||
import { VERSION } from "../version"
|
||||
import { Provider } from "../../provider/provider"
|
||||
import { UI } from "../ui"
|
||||
|
||||
export const ProviderCommand = cmd({
|
||||
command: "provider",
|
||||
builder: (yargs) =>
|
||||
yargs
|
||||
.command(ProviderAddCommand)
|
||||
.command(ProviderListCommand)
|
||||
.demandCommand(),
|
||||
describe: "initialize opencode",
|
||||
async handler() {},
|
||||
})
|
||||
|
||||
export const ProviderListCommand = cmd({
|
||||
command: "list",
|
||||
aliases: ["ls"],
|
||||
describe: "list providers",
|
||||
async handler() {
|
||||
await App.provide({ cwd: process.cwd(), version: VERSION }, async () => {
|
||||
prompts.intro("Providers")
|
||||
const providers = await Provider.list().then((x) => Object.values(x))
|
||||
for (const value of providers) {
|
||||
prompts.log.success(value.info.name + " (" + value.source + ")")
|
||||
}
|
||||
prompts.outro(`${providers.length} configured`)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const ProviderAddCommand = cmd({
|
||||
command: "add",
|
||||
describe: "add credentials for various providers",
|
||||
async handler() {
|
||||
await App.provide({ cwd: process.cwd(), version: VERSION }, async () => {
|
||||
const providers = await Provider.list()
|
||||
prompts.intro("Add provider")
|
||||
const provider = await prompts.select({
|
||||
message: "Select",
|
||||
maxItems: 2,
|
||||
options: [
|
||||
{
|
||||
label: "Anthropic",
|
||||
value: "anthropic",
|
||||
hint: providers["anthropic"] ? "configured" : "",
|
||||
},
|
||||
{
|
||||
label: "OpenAI",
|
||||
value: "openai",
|
||||
hint: providers["openai"] ? "configured" : "",
|
||||
},
|
||||
{
|
||||
label: "Google",
|
||||
value: "google",
|
||||
hint: providers["google"] ? "configured" : "",
|
||||
},
|
||||
],
|
||||
})
|
||||
if (prompts.isCancel(provider)) throw new UI.CancelledError({})
|
||||
|
||||
if (provider === "anthropic") {
|
||||
const method = await prompts.select({
|
||||
message: "Login method",
|
||||
options: [
|
||||
{
|
||||
label: "Claude Pro/Max",
|
||||
value: "oauth",
|
||||
},
|
||||
{
|
||||
label: "API Key",
|
||||
value: "api",
|
||||
},
|
||||
],
|
||||
})
|
||||
if (prompts.isCancel(method)) throw new UI.CancelledError({})
|
||||
|
||||
if (method === "oauth") {
|
||||
// some weird bug where program exits without this
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
const { url, verifier } = await AuthAnthropic.authorize()
|
||||
prompts.note("Opening browser...")
|
||||
await open(url)
|
||||
prompts.log.info(url)
|
||||
|
||||
const code = await prompts.text({
|
||||
message: "Paste the authorization code here: ",
|
||||
validate: (x) => (x.length > 0 ? undefined : "Required"),
|
||||
})
|
||||
if (prompts.isCancel(code)) throw new UI.CancelledError({})
|
||||
|
||||
await AuthAnthropic.exchange(code, verifier)
|
||||
.then(() => {
|
||||
prompts.log.success("Login successful")
|
||||
})
|
||||
.catch(() => {
|
||||
prompts.log.error("Invalid code")
|
||||
})
|
||||
prompts.outro("Done")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const key = await prompts.password({
|
||||
message: "Enter your API key",
|
||||
validate: (x) => (x.length > 0 ? undefined : "Required"),
|
||||
})
|
||||
if (prompts.isCancel(key)) throw new UI.CancelledError({})
|
||||
await AuthKeys.set(provider, key)
|
||||
|
||||
prompts.outro("Done")
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -33,7 +33,7 @@ export const RunCommand = {
|
||||
await App.provide(
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
version: "0.0.0",
|
||||
version: VERSION,
|
||||
},
|
||||
async () => {
|
||||
await Share.init()
|
||||
@@ -47,7 +47,7 @@ export const RunCommand = {
|
||||
UI.empty()
|
||||
UI.println(
|
||||
UI.Style.TEXT_INFO_BOLD +
|
||||
"~ https://dev.opencode.ai/s?id=" +
|
||||
"~ https://dev.opencode.ai/s/" +
|
||||
session.id.slice(-8),
|
||||
)
|
||||
UI.empty()
|
||||
|
||||
Reference in New Issue
Block a user