"io"
"net/http"
"os"
+ "path/filepath"
"strings"
"sync"
"time"
)
const (
+ // chatgptURL is the Responses endpoint of the ChatGPT backend.
+ chatgptURL = "https://chatgpt.com/backend-api/codex/responses"
+
+ // apiURL is the Responses endpoint of the OpenAI API.
+ apiURL = "https://api.openai.com/v1/responses"
+
// quotaPrefix starts the names of the quota headers of the ChatGPT
// backend, in canonical form.
quotaPrefix = "X-Codex-"
} `json:"content"`
}
+// modelEndpoint returns the URL and the authorizer of the endpoint in config.
+// The ChatGPT backend uses the token file in dir. The OpenAI API uses the key in
+// OPENAI_API_KEY, and there is no fallback from one to the other. All clients
+// share the authorizer, so one refresh runs at a time.
+func modelEndpoint(config Config, dir string) (string, authorizer, error) {
+ if config.Endpoint == endpointAPI {
+ key := os.Getenv("OPENAI_API_KEY")
+ if key == "" {
+ return "", nil, errors.New("endpoint api needs OPENAI_API_KEY")
+ }
+
+ return apiURL, apiKey(key), nil
+ }
+
+ return chatgptURL, newChatGPTAuth(filepath.Join(dir, tokenFileName), authIssuer), nil
+}
+
// newClient returns a client for the Responses endpoint at url. It records
// each call in the usage file at usagePath.
func newClient(url string, auth authorizer, cacheKey, usagePath string) *Client {