diff --git a/config.example.yaml b/config.example.yaml index 1e084cb4..aca7f4e1 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -69,6 +69,11 @@ quota-exceeded: # When true, enable authentication for the WebSocket API (/v1/ws). ws-auth: false +# Streaming behavior (SSE keep-alives + safe bootstrap retries). +# streaming: +# keepalive-seconds: 15 # Default: 0 (disabled). <= 0 disables keep-alives. +# bootstrap-retries: 1 # Default: 0 (disabled). Retries before first byte is sent. + # Gemini API keys # gemini-api-key: # - api-key: "AIzaSy...01" diff --git a/sdk/api/handlers/handlers.go b/sdk/api/handlers/handlers.go index 50005055..7857f736 100644 --- a/sdk/api/handlers/handlers.go +++ b/sdk/api/handlers/handlers.go @@ -45,8 +45,8 @@ type ErrorDetail struct { const idempotencyKeyMetadataKey = "idempotency_key" const ( - defaultStreamingKeepAliveSeconds = 15 - defaultStreamingBootstrapRetries = 2 + defaultStreamingKeepAliveSeconds = 0 + defaultStreamingBootstrapRetries = 0 ) // BuildErrorResponseBody builds an OpenAI-compatible JSON error response body. @@ -100,7 +100,7 @@ func BuildErrorResponseBody(status int, errText string) []byte { } // StreamingKeepAliveInterval returns the SSE keep-alive interval for this server. -// Returning 0 disables keep-alives. +// Returning 0 disables keep-alives (default when unset). func StreamingKeepAliveInterval(cfg *config.SDKConfig) time.Duration { seconds := defaultStreamingKeepAliveSeconds if cfg != nil && cfg.Streaming.KeepAliveSeconds != nil { @@ -125,6 +125,8 @@ func StreamingBootstrapRetries(cfg *config.SDKConfig) int { } func requestExecutionMetadata(ctx context.Context) map[string]any { + // Idempotency-Key is an optional client-supplied header used to correlate retries. + // It is forwarded as execution metadata; when absent we generate a UUID. key := "" if ctx != nil { if ginCtx, ok := ctx.Value("gin").(*gin.Context); ok && ginCtx != nil && ginCtx.Request != nil { diff --git a/sdk/api/handlers/handlers_stream_bootstrap_test.go b/sdk/api/handlers/handlers_stream_bootstrap_test.go index cd2fdf4d..7f910447 100644 --- a/sdk/api/handlers/handlers_stream_bootstrap_test.go +++ b/sdk/api/handlers/handlers_stream_bootstrap_test.go @@ -94,7 +94,12 @@ func TestExecuteStreamWithAuthManager_RetriesBeforeFirstByte(t *testing.T) { registry.GetGlobalRegistry().UnregisterClient(auth2.ID) }) - handler := NewBaseAPIHandlers(&sdkconfig.SDKConfig{}, manager, nil) + bootstrapRetries := 1 + handler := NewBaseAPIHandlers(&sdkconfig.SDKConfig{ + Streaming: sdkconfig.StreamingConfig{ + BootstrapRetries: &bootstrapRetries, + }, + }, manager, nil) dataChan, errChan := handler.ExecuteStreamWithAuthManager(context.Background(), "openai", "test-model", []byte(`{"model":"test-model"}`), "") if dataChan == nil || errChan == nil { t.Fatalf("expected non-nil channels")