Changeset 0.22.0.1 (#94)
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
@@ -50,6 +51,15 @@ type CompletionHandler struct {
|
||||
hub *events.Hub // WebSocket hub for browser tool bridge
|
||||
objStore storage.ObjectStore // file storage for attachment content (nil = disabled)
|
||||
embedder *knowledge.Embedder // for memory semantic recall (v0.18.0)
|
||||
health HealthRecorder // provider health tracking (v0.22.0, nil = disabled)
|
||||
}
|
||||
|
||||
// HealthRecorder is the interface for recording provider call outcomes.
|
||||
// Matches health.Accumulator methods without importing the package.
|
||||
type HealthRecorder interface {
|
||||
RecordSuccess(providerConfigID string, latencyMs int)
|
||||
RecordError(providerConfigID string, latencyMs int, errMsg string)
|
||||
RecordTimeout(providerConfigID string, latencyMs int, errMsg string)
|
||||
}
|
||||
|
||||
// NewCompletionHandler creates a new handler.
|
||||
@@ -57,6 +67,11 @@ func NewCompletionHandler(vault *crypto.KeyResolver, stores store.Stores, hub *e
|
||||
return &CompletionHandler{vault: vault, stores: stores, hub: hub, objStore: objStore, embedder: embedder}
|
||||
}
|
||||
|
||||
// SetHealthRecorder attaches the provider health accumulator.
|
||||
func (h *CompletionHandler) SetHealthRecorder(hr HealthRecorder) {
|
||||
h.health = hr
|
||||
}
|
||||
|
||||
// ── Chat Completion ─────────────────────────
|
||||
// POST /api/v1/chat/completions
|
||||
//
|
||||
@@ -371,7 +386,7 @@ func (h *CompletionHandler) multiModelStream(
|
||||
}
|
||||
|
||||
// Stream this model's response using the shared streaming core
|
||||
result := streamModelResponse(c, provider, providerCfg, &provReq, model, target.DisplayName, userID, channelID, personaID, workspaceID, h.hub)
|
||||
result := streamModelResponse(c, provider, providerCfg, &provReq, model, target.DisplayName, userID, channelID, personaID, workspaceID, configID, h.hub, h.health)
|
||||
|
||||
// Persist assistant message with model attribution
|
||||
if result.Content != "" {
|
||||
@@ -536,7 +551,7 @@ func (h *CompletionHandler) streamCompletion(
|
||||
req providers.CompletionRequest,
|
||||
channelID, userID, model, configID, providerScope, personaID, workspaceID string,
|
||||
) {
|
||||
result := streamWithToolLoop(c, provider, cfg, &req, model, userID, channelID, personaID, workspaceID, h.hub)
|
||||
result := streamWithToolLoop(c, provider, cfg, &req, model, userID, channelID, personaID, workspaceID, configID, h.hub, h.health)
|
||||
|
||||
// Persist assistant response
|
||||
if result.Content != "" {
|
||||
@@ -566,7 +581,9 @@ func (h *CompletionHandler) syncCompletion(
|
||||
var allToolActivity []map[string]interface{}
|
||||
|
||||
for iteration := 0; iteration < maxToolIterations; iteration++ {
|
||||
callStart := time.Now()
|
||||
resp, err := provider.ChatCompletion(c.Request.Context(), cfg, req)
|
||||
h.recordHealth(configID, callStart, err)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": "provider error: " + err.Error()})
|
||||
return
|
||||
@@ -1175,3 +1192,21 @@ func calcCost(tokens int, pricePerM *float64) *float64 {
|
||||
cost := float64(tokens) * *pricePerM / 1_000_000.0
|
||||
return &cost
|
||||
}
|
||||
|
||||
// recordHealth records provider call outcome for health tracking (v0.22.0).
|
||||
func (h *CompletionHandler) recordHealth(configID string, start time.Time, err error) {
|
||||
if h.health == nil || configID == "" {
|
||||
return
|
||||
}
|
||||
latencyMs := int(time.Since(start).Milliseconds())
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
if strings.Contains(errMsg, "context deadline exceeded") || strings.Contains(errMsg, "timeout") {
|
||||
h.health.RecordTimeout(configID, latencyMs, errMsg)
|
||||
} else {
|
||||
h.health.RecordError(configID, latencyMs, errMsg)
|
||||
}
|
||||
} else {
|
||||
h.health.RecordSuccess(configID, latencyMs)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user