".
func decodeStateProvider(state string) string {
if i := strings.IndexByte(state, ':'); i > 0 {
return state[:i]
}
return ""
}
// BuildRedirectURI returns the callback URL the OAuth server should
// redirect to.
func (s *Server) BuildRedirectURI() string {
return s.baseURL + "/callback"
}
// Redirect sends an HTTP redirect to u. Used by the TUI to tell the
// browser to bounce through our local server. Not currently used; kept
// for future flows.
func Redirect(w http.ResponseWriter, r *http.Request, u *url.URL) {
http.Redirect(w, r, u.String(), http.StatusFound)
}
// ---- templates ----
//
// All pages share the monochrome monoStyle defined in callback.go so
// the browser tab looks like the tui: black on white, monospace, thin
// rules, no rounded boxes, no color.
var tpl = template.Must(template.New("index").Parse(`zot login` + monoStyle + `
` + logoTag + `
zot login
paste an api key for anthropic or openai. zot probes the provider once, then saves the key to ~/Library/Application Support/zot/auth.json.
anthropic api key →
openai api key →
for a subscription login (claude pro/max · chatgpt plus/pro), close this tab and run /login inside zot.
`))
func init() {
template.Must(tpl.New("apikey").Parse(`zot login` + monoStyle + `
` + logoTag + `
zot login · {{.Provider}} api key
paste your {{.Provider}} api key. zot will probe the provider with it once, then save it if the key is accepted.
`))
template.Must(tpl.New("success").Parse(`zot · logged in` + monoStyle + `
` + logoTag + `
✓ logged in to {{.Provider}}
method: {{.Method}}
zot received the callback. you can close this tab and return to the terminal.
`))
template.Must(tpl.New("error").Parse(`zot · error` + monoStyle + `
` + logoTag + `
✗ login failed
{{.Message}}
go back to zot and try again.
`))
}