mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-22 18:24:21 +01:00
experimental well-known auth support
This commit is contained in:
@@ -16,7 +16,13 @@ export namespace Auth {
|
|||||||
key: z.string(),
|
key: z.string(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const Info = z.discriminatedUnion("type", [Oauth, Api])
|
export const WellKnown = z.object({
|
||||||
|
type: z.literal("wellknown"),
|
||||||
|
key: z.string(),
|
||||||
|
token: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const Info = z.discriminatedUnion("type", [Oauth, Api, WellKnown])
|
||||||
export type Info = z.infer<typeof Info>
|
export type Info = z.infer<typeof Info>
|
||||||
|
|
||||||
const filepath = path.join(Global.Path.data, "auth.json")
|
const filepath = path.join(Global.Path.data, "auth.json")
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const AuthCommand = cmd({
|
|||||||
describe: "manage credentials",
|
describe: "manage credentials",
|
||||||
builder: (yargs) =>
|
builder: (yargs) =>
|
||||||
yargs.command(AuthLoginCommand).command(AuthLogoutCommand).command(AuthListCommand).demandCommand(),
|
yargs.command(AuthLoginCommand).command(AuthLogoutCommand).command(AuthListCommand).demandCommand(),
|
||||||
async handler() { },
|
async handler() {},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const AuthListCommand = cmd({
|
export const AuthListCommand = cmd({
|
||||||
@@ -61,20 +61,45 @@ export const AuthListCommand = cmd({
|
|||||||
prompts.log.info(`${provider} ${UI.Style.TEXT_DIM}${envVar}`)
|
prompts.log.info(`${provider} ${UI.Style.TEXT_DIM}${envVar}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
prompts.outro(
|
prompts.outro(`${activeEnvVars.length} environment variable` + (activeEnvVars.length === 1 ? "" : "s"))
|
||||||
`${activeEnvVars.length} environment variable`
|
|
||||||
+ (activeEnvVars.length === 1 ? "" : "s")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const AuthLoginCommand = cmd({
|
export const AuthLoginCommand = cmd({
|
||||||
command: "login",
|
command: "login [url]",
|
||||||
describe: "log in to a provider",
|
describe: "log in to a provider",
|
||||||
async handler() {
|
builder: (yargs) =>
|
||||||
UI.empty()
|
yargs.positional("url", {
|
||||||
|
describe: "opencode auth provider",
|
||||||
|
type: "string",
|
||||||
|
}),
|
||||||
|
async handler(args) {
|
||||||
prompts.intro("Add credential")
|
prompts.intro("Add credential")
|
||||||
|
if (args.url) {
|
||||||
|
const wellknown = await fetch(`${args.url}/.well-known/opencode`).then((x) => x.json())
|
||||||
|
prompts.log.info(`Running \`${wellknown.auth.command.join(" ")}\``)
|
||||||
|
const proc = Bun.spawn({
|
||||||
|
cmd: wellknown.auth.command,
|
||||||
|
stdout: "pipe",
|
||||||
|
})
|
||||||
|
const exit = await proc.exited
|
||||||
|
if (exit !== 0) {
|
||||||
|
prompts.log.error("Failed")
|
||||||
|
prompts.outro("Done")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const token = await new Response(proc.stdout).text()
|
||||||
|
await Auth.set(args.url, {
|
||||||
|
type: "wellknown",
|
||||||
|
key: wellknown.auth.env,
|
||||||
|
token: token.trim(),
|
||||||
|
})
|
||||||
|
prompts.log.success("Logged into " + args.url)
|
||||||
|
prompts.outro("Done")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UI.empty()
|
||||||
const providers = await ModelsDev.get()
|
const providers = await ModelsDev.get()
|
||||||
const priority: Record<string, number> = {
|
const priority: Record<string, number> = {
|
||||||
anthropic: 0,
|
anthropic: 0,
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ import { lazy } from "../util/lazy"
|
|||||||
import { NamedError } from "../util/error"
|
import { NamedError } from "../util/error"
|
||||||
import matter from "gray-matter"
|
import matter from "gray-matter"
|
||||||
import { Flag } from "../flag/flag"
|
import { Flag } from "../flag/flag"
|
||||||
|
import { Auth } from "../auth"
|
||||||
|
|
||||||
export namespace Config {
|
export namespace Config {
|
||||||
const log = Log.create({ service: "config" })
|
const log = Log.create({ service: "config" })
|
||||||
|
|
||||||
export const state = App.state("config", async (app) => {
|
export const state = App.state("config", async (app) => {
|
||||||
|
const auth = await Auth.all()
|
||||||
let result = await global()
|
let result = await global()
|
||||||
for (const file of ["opencode.jsonc", "opencode.json"]) {
|
for (const file of ["opencode.jsonc", "opencode.json"]) {
|
||||||
const found = await Filesystem.findUp(file, app.path.cwd, app.path.root)
|
const found = await Filesystem.findUp(file, app.path.cwd, app.path.root)
|
||||||
@@ -30,6 +32,14 @@ export namespace Config {
|
|||||||
log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG })
|
log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(auth)) {
|
||||||
|
if (value.type === "wellknown") {
|
||||||
|
process.env[value.key] = value.token
|
||||||
|
const wellknown = await fetch(`${key}/.well-known/opencode`).then((x) => x.json())
|
||||||
|
result = mergeDeep(result, await loadRaw(JSON.stringify(wellknown.config ?? {}), process.cwd()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.agent = result.agent || {}
|
result.agent = result.agent || {}
|
||||||
const markdownAgents = [
|
const markdownAgents = [
|
||||||
...(await Filesystem.globUp("agent/*.md", Global.Path.config, Global.Path.config)),
|
...(await Filesystem.globUp("agent/*.md", Global.Path.config, Global.Path.config)),
|
||||||
@@ -307,7 +317,10 @@ export namespace Config {
|
|||||||
throw new JsonError({ path: configPath }, { cause: err })
|
throw new JsonError({ path: configPath }, { cause: err })
|
||||||
})
|
})
|
||||||
if (!text) return {}
|
if (!text) return {}
|
||||||
|
return loadRaw(text, configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadRaw(text: string, configPath: string) {
|
||||||
text = text.replace(/\{env:([^}]+)\}/g, (_, varName) => {
|
text = text.replace(/\{env:([^}]+)\}/g, (_, varName) => {
|
||||||
return process.env[varName] || ""
|
return process.env[varName] || ""
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user