Files
CLIProxyAPI/internal/runtime/executor/helps/websocket_observer_helpers.go
Luis Pater 4b5f1eab25 feat(plugin): support observing upstream websocket response events
- Introduce `WebSocketResponseObserver` capability and bump plugin ABI schema version to 4.
- Forward upstream WebSocket response frames from Codex and xAI executors to configured observers.
- Wire `WebSocketResponseObserver` across API handlers and plugin host dispatchers.

Closes: #5248
2026-08-27 05:30:19 +08:00

49 lines
1.5 KiB
Go

package helps
import (
"context"
cliproxyauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/executor"
"github.com/tidwall/gjson"
)
// EmitWebSocketResponseEvent delivers an upstream WebSocket response frame to any configured observer.
func EmitWebSocketResponseEvent(ctx context.Context, opts cliproxyexecutor.Options, auth *cliproxyauth.Auth, provider, model string, payload []byte) {
if opts.WebSocketResponseObserver == nil || len(payload) == 0 {
return
}
var authID, authLabel, authType string
if auth != nil {
authID = auth.ID
authLabel = auth.Label
authType, _ = auth.AccountInfo()
}
eventType := gjson.GetBytes(payload, "type").String()
var requestID string
var traceID string
if opts.Metadata != nil {
if reqID, ok := opts.Metadata["request_id"].(string); ok {
requestID = reqID
}
if trID, ok := opts.Metadata["trace_id"].(string); ok {
traceID = trID
}
}
requestedModel := PayloadRequestedModel(opts, model)
opts.WebSocketResponseObserver(ctx, cliproxyexecutor.WebSocketResponseEvent{
RequestID: requestID,
TraceID: traceID,
SourceFormat: opts.SourceFormat.String(),
Model: model,
RequestedModel: requestedModel,
Provider: provider,
AuthID: authID,
AuthLabel: authLabel,
AuthType: authType,
EventType: eventType,
Payload: payload,
Metadata: opts.Metadata,
})
}