Documentation
¶
Overview ¶
Package openaisubscription provides inference authorized against a user's ChatGPT plan through the public Sign in with ChatGPT contract.
Index ¶
- Constants
- Variables
- func NewHostID() (string, error)
- func NewSource(ctx context.Context, input credentials.FactoryInput) (credentials.Source, error)
- func Revoke(ctx context.Context, client *http.Client, state refresh.State) error
- type AvailableModel
- type Client
- func (c *Client) Invoke(ctx context.Context, req inference.Request) (*inference.Response, error)
- func (c *Client) InvokeWithAuth(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*inference.Response, error)
- func (c *Client) InvokeWithAuthorizer(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*inference.Response, error)
- func (c *Client) Stream(ctx context.Context, req inference.Request) (*stream.StreamReader[content.Chunk], error)
- func (c *Client) StreamWithAuth(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*stream.StreamReader[content.Chunk], error)
- func (c *Client) StreamWithAuthorizer(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*stream.StreamReader[content.Chunk], error)
- type IncompleteError
- type LoginOptions
- type Option
- type Registration
- type ResponseError
- type UsageLimitError
Constants ¶
const ( Issuer = "https://auth.openai.com" AuthorizationURL = Issuer + "/api/accounts/authorize" TokenURL = Issuer + "/api/accounts/oauth/token" JWKSURL = Issuer + "/.well-known/jwks.json" DiscoveryURL = Issuer + "/.well-known/openid-configuration" )
const BaseURL = "https://api.openai.com/v1"
Variables ¶
var ( ErrLogin = errors.New("openai-subscription: sign-in failed; retry login") ErrIdentity = errors.New("openai-subscription: identity verification failed") ErrPermission = errors.New("openai-subscription: ChatGPT plan usage permission is required; sign in again and allow plan usage") ErrToken = errors.New("openai-subscription: token exchange failed; sign in again") // grant (a connection that never sent the request, throttling or a server // error). Credentials are preserved; retry with bounded backoff. ErrTokenUnavailable = errors.New("openai-subscription: token endpoint temporarily unavailable; retry later") // ErrTokenUncertain is a refresh whose request may have reached OpenAI but // whose response was lost or unusable. The refresh token may already be // rotated, so it is never submitted again; sign in again. ErrTokenUncertain = errors.New("openai-subscription: token refresh outcome unknown; sign in again") // ErrClient is invalid_client: the saved client registration was // rejected. Retrying or refreshing cannot fix it. ErrClient = errors.New("openai-subscription: OAuth client registration rejected; check the saved client or sign in again") ErrModels = errors.New("openai-subscription: could not retrieve account models") ErrRevoke = errors.New("openai-subscription: remote revocation was not confirmed; disconnect Carbon in ChatGPT settings") )
var ErrUsageLimit = errors.New("openai-subscription: ChatGPT plan usage limit reached; see ChatGPT Settings > Usage")
ErrUsageLimit reports that the ChatGPT plan, or this app's limit on it, is exhausted. OpenAI's recovery is to pause requests that use the plan and point the user at ChatGPT Settings > Usage; it is not rate pressure and must not be retried.
Functions ¶
func NewSource ¶
func NewSource(ctx context.Context, input credentials.FactoryInput) (credentials.Source, error)
NewSource adapts provider-owned continuity to the existing coordinated, versioned refresh machinery. The coordinator must cover the state store.
Types ¶
type AvailableModel ¶
func ListModels ¶
func ListModels(ctx context.Context, source credentials.Source, client *http.Client) ([]AvailableModel, error)
ListModels returns the current selected account's displayable models in server order. Catalog inclusion is not proof an inference request will succeed.
type Client ¶
Client supports call-scoped authorization. Construct through auto.NewWithAuth to bind an OAuth subscription Source to it; no credential is read implicitly.
func (*Client) InvokeWithAuth ¶
func (*Client) InvokeWithAuthorizer ¶
func (c *Client) InvokeWithAuthorizer(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*inference.Response, error)
InvokeWithAuthorizer is a descriptive alias for InvokeWithAuth. It is declared here so the promoted transport alias cannot bypass the mandatory streaming flow.
func (*Client) Stream ¶
func (c *Client) Stream(ctx context.Context, req inference.Request) (*stream.StreamReader[content.Chunk], error)
Stream sends one streaming request with the client's default authorizer.
func (*Client) StreamWithAuth ¶
func (c *Client) StreamWithAuth(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*stream.StreamReader[content.Chunk], error)
StreamWithAuth sends one streaming request with a call-scoped authorizer.
func (*Client) StreamWithAuthorizer ¶
func (c *Client) StreamWithAuthorizer(ctx context.Context, req inference.Request, auth httpauth.Authorizer) (*stream.StreamReader[content.Chunk], error)
StreamWithAuthorizer is a descriptive alias for StreamWithAuth.
type IncompleteError ¶
type IncompleteError struct{ Reason string }
IncompleteError reports response.incomplete. OpenAI documents only response.completed as successful inference, so partial output is never returned as a result. Reason is the bounded incomplete_details.reason (e.g. max_output_tokens, content_filter) when present.
func (*IncompleteError) Error ¶
func (e *IncompleteError) Error() string
type LoginOptions ¶
type Option ¶
type Option func(*config)
func WithRoundTripper ¶
func WithRoundTripper(rt http.RoundTripper) Option
func WithTLSRootCAs ¶
type Registration ¶
type Registration struct {
ClientID string `json:"client_id"`
Subject string `json:"subject"`
Email string `json:"email,omitempty"`
HostID string `json:"host_id"`
IDToken string `json:"id_token,omitempty"`
Scopes string `json:"scopes,omitempty"`
}
Registration is private account continuity, never display metadata. Persist it only in protected state. Formatting and logging deliberately redact it.
func Login ¶
func Login(ctx context.Context, options LoginOptions) (refresh.State, Registration, error)
Login runs a bounded browser flow with a stable callback path. It leaves all local persistence to the caller and never mutates a selected account on failure.
func RegistrationFromState ¶
func RegistrationFromState(state refresh.State) (Registration, error)
func (Registration) AccountName ¶
func (r Registration) AccountName() string
AccountName is a stable non-identifying local label, distinct per client and account.
func (Registration) LogValue ¶
func (r Registration) LogValue() slog.Value
func (Registration) String ¶
func (r Registration) String() string
func (Registration) Validate ¶
func (r Registration) Validate() error
type ResponseError ¶
type ResponseError struct{ Code, Param string }
ResponseError is a Responses failure (response.failed or a top-level error event) after the stream opened. Only bounded code tokens are kept: the provider's free-form message is never retained, so it cannot carry request text or credentials into logs. Param names the rejected input when the provider reports one (e.g. subscription_sharing_unsupported_capability).
func (*ResponseError) Error ¶
func (e *ResponseError) Error() string
func (*ResponseError) GoString ¶
func (e *ResponseError) GoString() string
type UsageLimitError ¶
type UsageLimitError struct{ RequestID string }
UsageLimitError is ErrUsageLimit with the bounded request ID when one was returned. It is deliberately not a *failure.APIError, so generic retry policies (which retry every HTTP 429) do not retry it.
func (*UsageLimitError) Error ¶
func (e *UsageLimitError) Error() string
func (*UsageLimitError) Unwrap ¶
func (e *UsageLimitError) Unwrap() error