]> git.giacomolli.uk - onechat/blobdiff - model.go
Make intentional error discards explicit
[onechat] / model.go
index 074ff600758bc27edee0a9c131cbb6daf560b664..c443a12981c8f47546396fd4c6150b2cc9fbdd18 100644 (file)
--- a/model.go
+++ b/model.go
@@ -374,73 +374,6 @@ func (u *ModelUsageLog) Write(record ModelUsageRecord) (err error) {
        return nil
 }
 
-// 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, ModelAuthorizer, error) {
-       if config.Endpoint == configEndpointAPI {
-               key := os.Getenv("OPENAI_API_KEY")
-               if key == "" {
-                       return "", nil, errors.New("endpoint api needs OPENAI_API_KEY")
-               }
-
-               return modelAPIURL, ModelAPIKey(key), nil
-       }
-
-       return modelChatGPTURL, newChatGPTAuth(filepath.Join(dir, chatgptTokenFileName), chatgptIssuer), nil
-}
-
-// modelUserMessage returns a user input item with one text part for each text.
-func modelUserMessage(texts ...string) any {
-       content := make([]ModelInputPart, len(texts))
-       for n, text := range texts {
-               content[n] = ModelInputPart{
-                       Type: "input_text",
-                       Text: text,
-               }
-       }
-
-       return modelUserParts(content)
-}
-
-// modelUserParts keeps text and image parts in one user message.
-func modelUserParts(content []ModelInputPart) any {
-       return struct {
-               Role    string           `json:"role"`
-               Content []ModelInputPart `json:"content"`
-       }{
-               Role:    "user",
-               Content: content,
-       }
-}
-
-// modelOutputText returns the text of the message items of output.
-func modelOutputText(output []json.RawMessage) (string, error) {
-       var text strings.Builder
-
-       for _, raw := range output {
-               var item ModelOutputItem
-
-               err := json.Unmarshal(raw, &item)
-               if err != nil {
-                       return "", fmt.Errorf("decode output item: %w", err)
-               }
-
-               if item.Type != "message" {
-                       continue
-               }
-
-               for _, part := range item.Content {
-                       if part.Type == "output_text" {
-                               text.WriteString(part.Text)
-                       }
-               }
-       }
-
-       return text.String(), nil
-}
-
 // modelQuotaHeaders returns the x-codex-* headers, with lowercase names,
 // without the turn state.
 func modelQuotaHeaders(header http.Header) map[string]string {
@@ -552,3 +485,70 @@ func modelReadEvent(response *ModelResponse, data []byte) (bool, error) {
 
        return false, nil
 }
+
+// modelOutputText returns the text of the message items of output.
+func modelOutputText(output []json.RawMessage) (string, error) {
+       var text strings.Builder
+
+       for _, raw := range output {
+               var item ModelOutputItem
+
+               err := json.Unmarshal(raw, &item)
+               if err != nil {
+                       return "", fmt.Errorf("decode output item: %w", err)
+               }
+
+               if item.Type != "message" {
+                       continue
+               }
+
+               for _, part := range item.Content {
+                       if part.Type == "output_text" {
+                               text.WriteString(part.Text)
+                       }
+               }
+       }
+
+       return text.String(), nil
+}
+
+// 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, ModelAuthorizer, error) {
+       if config.Endpoint == configEndpointAPI {
+               key := os.Getenv("OPENAI_API_KEY")
+               if key == "" {
+                       return "", nil, errors.New("endpoint api needs OPENAI_API_KEY")
+               }
+
+               return modelAPIURL, ModelAPIKey(key), nil
+       }
+
+       return modelChatGPTURL, newChatGPTAuth(filepath.Join(dir, chatgptTokenFileName), chatgptIssuer), nil
+}
+
+// modelUserMessage returns a user input item with one text part for each text.
+func modelUserMessage(texts ...string) any {
+       content := make([]ModelInputPart, len(texts))
+       for n, text := range texts {
+               content[n] = ModelInputPart{
+                       Type: "input_text",
+                       Text: text,
+               }
+       }
+
+       return modelUserParts(content)
+}
+
+// modelUserParts keeps text and image parts in one user message.
+func modelUserParts(content []ModelInputPart) any {
+       return struct {
+               Role    string           `json:"role"`
+               Content []ModelInputPart `json:"content"`
+       }{
+               Role:    "user",
+               Content: content,
+       }
+}