mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-01 23:02:26 +00:00
sync
This commit is contained in:
@@ -3,18 +3,16 @@ import { UI } from "../ui"
|
||||
|
||||
// Example: https://claude.ai/oauth/authorize?code=true&client_id=9d1c250a-e61b-44d9-88ed-5944d1962f5e&response_type=code&redirect_uri=https%3A%2F%2Fconsole.anthropic.com%2Foauth%2Fcode%2Fcallback&scope=org%3Acreate_api_key+user%3Aprofile+user%3Ainference&code_challenge=MdFtFgFap23AWDSN0oa3-eaKjQRFE4CaEhXx8M9fHZg&code_challenge_method=S256&state=rKLtaDzm88GSwekyEqdi0wXX-YqIr13tSzYymSzpvfs
|
||||
|
||||
|
||||
|
||||
export const LoginAnthropicCommand = {
|
||||
command: "anthropic",
|
||||
describe: "Login to Anthropic",
|
||||
handler: async () => {
|
||||
const { url, verifier } = await AuthAnthropic.authorize()
|
||||
|
||||
UI.print("Login to Anthropic")
|
||||
UI.print("Open the following URL in your browser:")
|
||||
UI.print(url)
|
||||
UI.print("")
|
||||
UI.println("Login to Anthropic")
|
||||
UI.println("Open the following URL in your browser:")
|
||||
UI.println(url)
|
||||
UI.println("")
|
||||
|
||||
const code = await UI.input("Paste the authorization code here: ")
|
||||
await AuthAnthropic.exchange(code, verifier)
|
||||
|
||||
129
packages/opencode/src/cli/cmd/provider.ts
Normal file
129
packages/opencode/src/cli/cmd/provider.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { AuthAnthropic } from "../../auth/anthropic"
|
||||
import { AuthKeys } from "../../auth/keys"
|
||||
import { UI } from "../ui"
|
||||
import { cmd } from "./cmd"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import open from "open"
|
||||
|
||||
const OPENCODE = [
|
||||
`█▀▀█ █▀▀█ █▀▀ █▀▀▄ █▀▀ █▀▀█ █▀▀▄ █▀▀`,
|
||||
`█░░█ █░░█ █▀▀ █░░█ █░░ █░░█ █░░█ █▀▀`,
|
||||
`▀▀▀▀ █▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀▀`,
|
||||
]
|
||||
|
||||
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() {
|
||||
prompts.intro("Configured Providers")
|
||||
const keys = await AuthKeys.get()
|
||||
for (const key of Object.keys(keys)) {
|
||||
prompts.log.success(key)
|
||||
}
|
||||
prompts.outro("3 providers configured")
|
||||
},
|
||||
})
|
||||
|
||||
const ProviderAddCommand = cmd({
|
||||
command: "add",
|
||||
describe: "add credentials for various providers",
|
||||
async handler() {
|
||||
UI.empty()
|
||||
for (const row of OPENCODE) {
|
||||
UI.print(" ")
|
||||
for (let i = 0; i < row.length; i++) {
|
||||
const color =
|
||||
i < 18 ? Bun.color("white", "ansi") : Bun.color("gray", "ansi")
|
||||
const char = row[i]
|
||||
UI.print(color + char)
|
||||
}
|
||||
UI.println()
|
||||
}
|
||||
UI.empty()
|
||||
|
||||
prompts.intro("Setup")
|
||||
const keys = await AuthKeys.get()
|
||||
const provider = await prompts.select({
|
||||
message: "Configure a provider",
|
||||
options: [
|
||||
{
|
||||
label: "Anthropic",
|
||||
value: "anthropic",
|
||||
hint: keys["anthropic"] ? "configured" : "",
|
||||
},
|
||||
{
|
||||
label: "OpenAI",
|
||||
value: "openai",
|
||||
hint: keys["openai"] ? "configured" : "",
|
||||
},
|
||||
{
|
||||
label: "Google",
|
||||
value: "google",
|
||||
hint: keys["google"] ? "configured" : "",
|
||||
},
|
||||
],
|
||||
})
|
||||
if (prompts.isCancel(provider)) return
|
||||
|
||||
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)) return
|
||||
|
||||
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)) return
|
||||
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",
|
||||
})
|
||||
if (prompts.isCancel(key)) return
|
||||
await AuthKeys.set(provider, key)
|
||||
|
||||
prompts.outro("Done")
|
||||
},
|
||||
})
|
||||
@@ -16,24 +16,30 @@ export namespace UI {
|
||||
TEXT_INFO_BOLD: "\x1b[94m\x1b[1m",
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function print(...message: string[]) {
|
||||
Bun.stderr.write(message.join(" "))
|
||||
export function println(...message: string[]) {
|
||||
print(...message)
|
||||
Bun.stderr.write("\n")
|
||||
}
|
||||
|
||||
export function print(...message: string[]) {
|
||||
blank = false
|
||||
Bun.stderr.write(message.join(" "))
|
||||
}
|
||||
|
||||
let blank = false
|
||||
export function empty() {
|
||||
print("" + Style.TEXT_NORMAL)
|
||||
if (blank) return
|
||||
println("" + Style.TEXT_NORMAL)
|
||||
blank = true
|
||||
}
|
||||
|
||||
export async function input(prompt: string): Promise<string> {
|
||||
const readline = require('readline')
|
||||
const readline = require("readline")
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
output: process.stdout,
|
||||
})
|
||||
|
||||
|
||||
return new Promise((resolve) => {
|
||||
rl.question(prompt, (answer: string) => {
|
||||
rl.close()
|
||||
|
||||
Reference in New Issue
Block a user