mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-22 00:24:46 +00:00
feat(opencode): Adding options to auth login to skip questions (#14470)
Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>
This commit is contained in:
@@ -20,10 +20,19 @@ type PluginAuth = NonNullable<Hooks["auth"]>
|
|||||||
* Handle plugin-based authentication flow.
|
* Handle plugin-based authentication flow.
|
||||||
* Returns true if auth was handled, false if it should fall through to default handling.
|
* Returns true if auth was handled, false if it should fall through to default handling.
|
||||||
*/
|
*/
|
||||||
async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string): Promise<boolean> {
|
async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string, methodName?: string): Promise<boolean> {
|
||||||
let index = 0
|
let index = 0
|
||||||
if (plugin.auth.methods.length > 1) {
|
if (methodName) {
|
||||||
const method = await prompts.select({
|
const match = plugin.auth.methods.findIndex((x) => x.label.toLowerCase() === methodName.toLowerCase())
|
||||||
|
if (match === -1) {
|
||||||
|
prompts.log.error(
|
||||||
|
`Unknown method "${methodName}" for ${provider}. Available: ${plugin.auth.methods.map((x) => x.label).join(", ")}`,
|
||||||
|
)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
index = match
|
||||||
|
} else if (plugin.auth.methods.length > 1) {
|
||||||
|
const selected = await prompts.select({
|
||||||
message: "Login method",
|
message: "Login method",
|
||||||
options: [
|
options: [
|
||||||
...plugin.auth.methods.map((x, index) => ({
|
...plugin.auth.methods.map((x, index) => ({
|
||||||
@@ -32,8 +41,8 @@ async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string):
|
|||||||
})),
|
})),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
if (prompts.isCancel(method)) throw new UI.CancelledError()
|
if (prompts.isCancel(selected)) throw new UI.CancelledError()
|
||||||
index = parseInt(method)
|
index = parseInt(selected)
|
||||||
}
|
}
|
||||||
const method = plugin.auth.methods[index]
|
const method = plugin.auth.methods[index]
|
||||||
|
|
||||||
@@ -252,10 +261,21 @@ export const AuthLoginCommand = cmd({
|
|||||||
command: "login [url]",
|
command: "login [url]",
|
||||||
describe: "log in to a provider",
|
describe: "log in to a provider",
|
||||||
builder: (yargs) =>
|
builder: (yargs) =>
|
||||||
yargs.positional("url", {
|
yargs
|
||||||
describe: "opencode auth provider",
|
.positional("url", {
|
||||||
type: "string",
|
describe: "opencode auth provider",
|
||||||
}),
|
type: "string",
|
||||||
|
})
|
||||||
|
.option("provider", {
|
||||||
|
alias: ["p"],
|
||||||
|
describe: "provider id or name to log in to (skips provider selection)",
|
||||||
|
type: "string",
|
||||||
|
})
|
||||||
|
.option("method", {
|
||||||
|
alias: ["m"],
|
||||||
|
describe: "login method label (skips method selection)",
|
||||||
|
type: "string",
|
||||||
|
}),
|
||||||
async handler(args) {
|
async handler(args) {
|
||||||
await Instance.provide({
|
await Instance.provide({
|
||||||
directory: process.cwd(),
|
directory: process.cwd(),
|
||||||
@@ -322,60 +342,76 @@ export const AuthLoginCommand = cmd({
|
|||||||
enabled,
|
enabled,
|
||||||
providerNames: Object.fromEntries(Object.entries(config.provider ?? {}).map(([id, p]) => [id, p.name])),
|
providerNames: Object.fromEntries(Object.entries(config.provider ?? {}).map(([id, p]) => [id, p.name])),
|
||||||
})
|
})
|
||||||
let provider = await prompts.autocomplete({
|
const options = [
|
||||||
message: "Select provider",
|
...pipe(
|
||||||
maxItems: 8,
|
providers,
|
||||||
options: [
|
values(),
|
||||||
...pipe(
|
sortBy(
|
||||||
providers,
|
(x) => priority[x.id] ?? 99,
|
||||||
values(),
|
(x) => x.name ?? x.id,
|
||||||
sortBy(
|
|
||||||
(x) => priority[x.id] ?? 99,
|
|
||||||
(x) => x.name ?? x.id,
|
|
||||||
),
|
|
||||||
map((x) => ({
|
|
||||||
label: x.name,
|
|
||||||
value: x.id,
|
|
||||||
hint: {
|
|
||||||
opencode: "recommended",
|
|
||||||
anthropic: "Claude Max or API key",
|
|
||||||
openai: "ChatGPT Plus/Pro or API key",
|
|
||||||
}[x.id],
|
|
||||||
})),
|
|
||||||
),
|
),
|
||||||
...pluginProviders.map((x) => ({
|
map((x) => ({
|
||||||
label: x.name,
|
label: x.name,
|
||||||
value: x.id,
|
value: x.id,
|
||||||
hint: "plugin",
|
hint: {
|
||||||
|
opencode: "recommended",
|
||||||
|
anthropic: "Claude Max or API key",
|
||||||
|
openai: "ChatGPT Plus/Pro or API key",
|
||||||
|
}[x.id],
|
||||||
})),
|
})),
|
||||||
{
|
),
|
||||||
value: "other",
|
...pluginProviders.map((x) => ({
|
||||||
label: "Other",
|
label: x.name,
|
||||||
},
|
value: x.id,
|
||||||
],
|
hint: "plugin",
|
||||||
})
|
})),
|
||||||
|
]
|
||||||
|
|
||||||
if (prompts.isCancel(provider)) throw new UI.CancelledError()
|
let provider: string
|
||||||
|
if (args.provider) {
|
||||||
|
const input = args.provider
|
||||||
|
const byID = options.find((x) => x.value === input)
|
||||||
|
const byName = options.find((x) => x.label.toLowerCase() === input.toLowerCase())
|
||||||
|
const match = byID ?? byName
|
||||||
|
if (!match) {
|
||||||
|
prompts.log.error(`Unknown provider "${input}"`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
provider = match.value
|
||||||
|
} else {
|
||||||
|
const selected = await prompts.autocomplete({
|
||||||
|
message: "Select provider",
|
||||||
|
maxItems: 8,
|
||||||
|
options: [
|
||||||
|
...options,
|
||||||
|
{
|
||||||
|
value: "other",
|
||||||
|
label: "Other",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
if (prompts.isCancel(selected)) throw new UI.CancelledError()
|
||||||
|
provider = selected as string
|
||||||
|
}
|
||||||
|
|
||||||
const plugin = await Plugin.list().then((x) => x.findLast((x) => x.auth?.provider === provider))
|
const plugin = await Plugin.list().then((x) => x.findLast((x) => x.auth?.provider === provider))
|
||||||
if (plugin && plugin.auth) {
|
if (plugin && plugin.auth) {
|
||||||
const handled = await handlePluginAuth({ auth: plugin.auth }, provider)
|
const handled = await handlePluginAuth({ auth: plugin.auth }, provider, args.method)
|
||||||
if (handled) return
|
if (handled) return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (provider === "other") {
|
if (provider === "other") {
|
||||||
provider = await prompts.text({
|
const custom = await prompts.text({
|
||||||
message: "Enter provider id",
|
message: "Enter provider id",
|
||||||
validate: (x) => (x && x.match(/^[0-9a-z-]+$/) ? undefined : "a-z, 0-9 and hyphens only"),
|
validate: (x) => (x && x.match(/^[0-9a-z-]+$/) ? undefined : "a-z, 0-9 and hyphens only"),
|
||||||
})
|
})
|
||||||
if (prompts.isCancel(provider)) throw new UI.CancelledError()
|
if (prompts.isCancel(custom)) throw new UI.CancelledError()
|
||||||
provider = provider.replace(/^@ai-sdk\//, "")
|
provider = custom.replace(/^@ai-sdk\//, "")
|
||||||
if (prompts.isCancel(provider)) throw new UI.CancelledError()
|
|
||||||
|
|
||||||
// Check if a plugin provides auth for this custom provider
|
// Check if a plugin provides auth for this custom provider
|
||||||
const customPlugin = await Plugin.list().then((x) => x.findLast((x) => x.auth?.provider === provider))
|
const customPlugin = await Plugin.list().then((x) => x.findLast((x) => x.auth?.provider === provider))
|
||||||
if (customPlugin && customPlugin.auth) {
|
if (customPlugin && customPlugin.auth) {
|
||||||
const handled = await handlePluginAuth({ auth: customPlugin.auth }, provider)
|
const handled = await handlePluginAuth({ auth: customPlugin.auth }, provider, args.method)
|
||||||
if (handled) return
|
if (handled) return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user