Sign the completion and the probe with the same token (V-673)
llm.Client carries a bearer credential and sets it on the completion, and Pair signs the /health probe with it too. An unsigned probe would answer 401, Pair would read that as a card that is busy, and every workstation turn would fall back to the resident model with nothing naming why. The token comes from workstation.token, expanded from MAVEN_GPU_TOKEN like every other secret in that file. Missing, and voicewire says so at startup: the fallback is silent by design and this failure would otherwise be invisible. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ESv8hqNPseYt1CnotZpqDz
This commit is contained in:
@@ -51,6 +51,10 @@ type Client struct {
|
||||
base string
|
||||
swap SwapGate
|
||||
http *http.Client
|
||||
// token — the bearer credential for a server that asks for one. Empty for
|
||||
// the resident model, which is reached over loopback on the same box.
|
||||
// mavgpud on the workstation requires it: that hop is on the LAN.
|
||||
token string
|
||||
|
||||
// gate / background — priority on the single llama-server slot. Set once
|
||||
// at wiring time (SetGate), read on every request. nil gate ⇒ no gating,
|
||||
@@ -101,6 +105,27 @@ func New(baseURL string, timeout time.Duration) *Client {
|
||||
return &Client{base: baseURL, http: &http.Client{Timeout: timeout}}
|
||||
}
|
||||
|
||||
// SetToken installs the bearer credential this client sends. Wiring-time, like
|
||||
// SetGate: an empty token means the server is not asking for one.
|
||||
func (c *Client) SetToken(t string) {
|
||||
c.mu.Lock()
|
||||
c.token = t
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// authorize adds the credential when there is one. Exported to the package so
|
||||
// the Pair prober signs /health with the same token as the completion — a
|
||||
// probe that answers 401 would otherwise read as a workstation that is down,
|
||||
// and Maven would fall back forever without saying why.
|
||||
func (c *Client) authorize(req *http.Request) {
|
||||
c.mu.RLock()
|
||||
t := c.token
|
||||
c.mu.RUnlock()
|
||||
if t != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+t)
|
||||
}
|
||||
}
|
||||
|
||||
// SetBaseURL re-points the client at another llama-server. Safe to call while
|
||||
// requests are in flight: a request that already read the old base finishes
|
||||
// against the old base (or fails, and every caller of Complete has a fallback),
|
||||
@@ -196,6 +221,7 @@ func (c *Client) Complete(ctx context.Context, r Req) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
c.authorize(req)
|
||||
httpResp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
Reference in New Issue
Block a user