api key integration

This commit is contained in:
2026-09-24 11:01:16 +05:30
parent 697b77f8c1
commit 9698de32d5
9 changed files with 503 additions and 10 deletions

View File

@@ -214,7 +214,7 @@ func (c *openAIChat) Complete(ctx context.Context, req ChatRequest) (ChatReply,
if c.cfg.APIKey != "" {
auth = "Bearer " + c.cfg.APIKey
}
if err := postJSON(ctx, c.client, c.base+"/chat/completions", auth, body, &out); err != nil {
if err := postJSON(ctx, c.client, "assistant", c.base+"/chat/completions", auth, body, &out); err != nil {
return ChatReply{}, err
}
if out.Error != nil {

View File

@@ -93,7 +93,7 @@ func (e *openAIEmbedder) Embed(ctx context.Context, text string) ([]float32, err
Message string `json:"message"`
} `json:"error"`
}
if err := postJSON(ctx, e.client, e.base+"/embeddings", "Bearer "+e.cfg.APIKey, body, &out); err != nil {
if err := postJSON(ctx, e.client, "embedding", e.base+"/embeddings", "Bearer "+e.cfg.APIKey, body, &out); err != nil {
return nil, err
}
if out.Error != nil {
@@ -140,7 +140,7 @@ func (e *geminiEmbedder) Embed(ctx context.Context, text string) ([]float32, err
} `json:"error"`
}
url := fmt.Sprintf("%s/%s:embedContent", e.base, model)
if err := postJSON(ctx, e.client, url, "", body, &out, "x-goog-api-key", e.cfg.APIKey); err != nil {
if err := postJSON(ctx, e.client, "embedding", url, "", body, &out, "x-goog-api-key", e.cfg.APIKey); err != nil {
return nil, err
}
if out.Error != nil {
@@ -154,7 +154,14 @@ func (e *geminiEmbedder) Embed(ctx context.Context, text string) ([]float32, err
// postJSON is the one HTTP call both providers make. Extra header pairs
// follow the body; `auth` is sent as Authorization when non-empty.
func postJSON(ctx context.Context, client *http.Client, url, auth string, body, out interface{}, headers ...string) error {
// postJSON is shared by the embedder and the chat gateway.
//
// `what` names the caller, and it is a parameter rather than a constant because
// it reaches a person. This helper used to say "embedding:" on every failure,
// so a rate-limited assistant told a shopkeeper "embedding: HTTP 429" — a
// sentence about a subsystem they have never heard of, describing something
// that was not involved.
func postJSON(ctx context.Context, client *http.Client, what, url, auth string, body, out interface{}, headers ...string) error {
payload, err := json.Marshal(body)
if err != nil {
return err
@@ -173,7 +180,7 @@ func postJSON(ctx context.Context, client *http.Client, url, auth string, body,
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("embedding: %w", err)
return fmt.Errorf("%s: %w", what, err)
}
defer resp.Body.Close()
@@ -181,18 +188,18 @@ func postJSON(ctx context.Context, client *http.Client, url, auth string, body,
// the end of the internet.
raw, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20))
if err != nil {
return fmt.Errorf("embedding: %w", err)
return fmt.Errorf("%s: %w", what, err)
}
if err := json.Unmarshal(raw, out); err != nil {
return fmt.Errorf("embedding: HTTP %d, unreadable body: %w", resp.StatusCode, err)
return fmt.Errorf("%s: HTTP %d, unreadable body: %w", what, resp.StatusCode, err)
}
if resp.StatusCode/100 != 2 {
// The decoded body carries the provider's message where there is one;
// this is the fallback for a bare status.
if msg := extractMessage(raw); msg != "" {
return fmt.Errorf("embedding: HTTP %d: %s", resp.StatusCode, msg)
return fmt.Errorf("%s: HTTP %d: %s", what, resp.StatusCode, msg)
}
return fmt.Errorf("embedding: HTTP %d", resp.StatusCode)
return fmt.Errorf("%s: HTTP %d", what, resp.StatusCode)
}
return nil
}