X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/74583992d2939791ef74155c99eb194269ac3721..ba9faee0cd6c35020997794ef7bf134e8db12e96:/responses.go?ds=sidebyside diff --git a/responses.go b/responses.go index ebffaa3..096439f 100644 --- a/responses.go +++ b/responses.go @@ -27,6 +27,10 @@ const ( // backend, in canonical form. quotaPrefix = "X-Codex-" + // turnStateHeader is an x-codex-* header that holds an opaque state of + // the backend, not quota. + turnStateHeader = "X-Codex-Turn-State" + // errorBytes is the most bytes of an error response that go into the // error. errorBytes = 4096 @@ -44,8 +48,10 @@ type apiKey string // Client sends model calls to a Responses endpoint for one agent. The ChatGPT // backend and the OpenAI API take the same request body and differ only in the // URL and the credentials. Every call sends the fixed cache key of the agent, -// so the turns and the compactions of the agent share one prompt cache. Every -// call is recorded in the usage file. +// so the turns and the compactions of the agent share one prompt cache. The +// ChatGPT backend caches only with the key in the session_id header, so a call +// to it sends the key there and in the body. Every call is recorded in the +// usage file. // // The request never holds max_output_tokens or metadata, because the ChatGPT // backend refuses them. It sets store to false, so the client sends the whole @@ -213,6 +219,11 @@ func (c *Client) Create(ctx context.Context, request Request) (Response, error) return Response{}, fmt.Errorf("authorize model call: %w", err) } + _, chatgpt := c.auth.(*chatgptAuth) + if chatgpt { + httpRequest.Header.Set("session_id", c.cacheKey) + } + record := usageRecord{ Date: time.Now().Format(time.RFC3339Nano), Model: request.Model, @@ -262,7 +273,8 @@ type usageLog struct { } // usageRecord is one line of usage.jsonl. Status is the HTTP status, or 0 when -// no response came. Quota holds the x-codex-* headers of the response. +// no response came. Quota holds the x-codex-* headers of the response, without +// the turn state. type usageRecord struct { Date string `json:"date"` Model string `json:"model"` @@ -331,11 +343,12 @@ func userMessage(texts ...string) any { } } -// quotaHeaders returns the x-codex-* headers, with lowercase names. +// quotaHeaders returns the x-codex-* headers, with lowercase names, without the +// turn state. func quotaHeaders(header http.Header) map[string]string { var quota map[string]string for name, values := range header { - if !strings.HasPrefix(name, quotaPrefix) || len(values) == 0 { + if !strings.HasPrefix(name, quotaPrefix) || name == turnStateHeader || len(values) == 0 { continue }