feat: implement OpenAI compatible API provider support
This PR implements OpenAI compatible API provider support to resolve the issue where environment variables for OpenAI compatible endpoints were not working.
Changes
- Add WHODB_OPENAI_COMPATIBLE_LABEL environment variable for custom labeling
- Create OpenAI compatible provider when API key and endpoint are configured
- Add OpenAI-Compatible LLM type with request/response handling
- Support custom models from WHODB_CUSTOM_MODELS environment variable
- Reuse existing OpenAI-compatible API structure without requiring new API code
Fixes #496
Generated with Claude Code
Bug Report
| Name | Severity | Example test case | Description |
|---|---|---|---|
| Incorrect SSE Handling in OpenAI-Compatible Streaming | Medium | Use an OpenAI-compatible API that returns Server-Sent Events (SSE). Send a prompt and observe that the response parsing fails. | The parseOpenAICompatibleResponse function doesn't handle the 'data: ' prefix in SSE responses, leading to JSON unmarshaling errors. |
Comments? Email us. Your free trial ends in 7 days.
@claude could you take a look at the issue by the Jazzberry bot?
Claude finished @modelorona's task —— View job
Fixed SSE Handling Bug ✅
I investigated and fixed the SSE handling issue reported by Jazzberry bot.
Todo List:
- [x] Read the OpenAI compatible client implementation
- [x] Analyze the
parseOpenAICompatibleResponsefunction - [x] Identify the SSE parsing issue with 'data: ' prefix
- [x] Implement fix for proper SSE handling
- [x] Test and commit the changes
Bug Analysis:
Found the issue in core/src/llm/openai_compatible_client.go:74. The function was trying to unmarshal raw SSE lines directly, but SSE format includes "data: " prefix that must be stripped before JSON parsing.
Fix Applied:
- Strip "data: " prefix from SSE lines before JSON parsing
- Handle "[DONE]" control message to properly terminate streams
- Prevents JSON unmarshaling errors in streaming responses
Fixed in commit: dba2272 - The OpenAI-compatible streaming should now work correctly with proper SSE handling.
Bug Report
| Name | Severity | Example test case | Description |
|---|---|---|---|
| Truncated Streaming Response | Medium | Configure the application to use an OpenAI-compatible API that sends the "[DONE]" message immediately after the last content chunk, without a "stop" FinishReason. Send a prompt that generates a multi-chunk response. Observe that the last part of the response is missing. |
The streaming response parsing logic in parseOpenAICompatibleResponse terminates prematurely when the "[DONE]" message is received, potentially truncating the last part of the response. The code should send the accumulated response to the receiverChan before breaking the loop upon receiving the "[DONE]" message to ensure the complete response is delivered. Also, the code should check for the FinishReason being "stop" before sending the final response. |
Comments? Email us. Your free trial ends in 7 days.
@claude can you look at the latest Jazzberry comment?
Claude finished @modelorona's task —— View job
Fixed Truncated Streaming Response Bug ✅
I've analyzed and fixed the "Truncated Streaming Response" bug reported by Jazzberry bot.
Todo List:
- [x] Read the OpenAI compatible client implementation
- [x] Analyze the
parseOpenAICompatibleResponsefunction for truncation issue - [x] Identify the problem with "[DONE]" message handling
- [x] Implement fix to ensure complete response delivery
- [x] Test and commit the changes
Bug Analysis:
Found the exact issue in core/src/llm/openai_compatible_client.go:72-74. The current logic:
// Skip SSE control messages
if line == "[DONE]" {
break // ❌ This breaks immediately without sending final response
}
Problem: When "[DONE]" is received, the function broke immediately, potentially losing the last accumulated response.
Fix Applied:
- Send accumulated response before breaking on "[DONE]": Modified the "[DONE]" handler to check if there's accumulated content in
responseBuilderand return it before terminating the stream - Handle normal stream termination: Added fallback logic to return accumulated response when the stream ends normally (EOF)
Changes in commit d28ec08:
- Lines 72-78: Send final response before breaking on "[DONE]" message
- Lines 127-131: Return accumulated response when stream ends normally
This ensures complete responses are delivered regardless of whether the stream ends with "[DONE]" or EOF, preventing truncation issues.
Bug Report
| Name | Severity | Example test case | Description |
|---|---|---|---|
| OpenAI-Compatible SSE Injection | High | Set up a malicious OpenAI-compatible endpoint that injects JavaScript code into the SSE stream. | The application blindly trusts the SSE stream from the OpenAI-compatible endpoint, leading to potential injection attacks and client-side code execution. |
Comments? Email us. Your free trial ends in 6 days.
Any update on this? Thanks!!
@nicopace we're just doing some local testing on our end!
@nicopace we've merged this to main and are creating a new release! make sure to pull again from docker :)
let us know how you get on. I was playing around with the same API you tried and didn't run into issues.
you might need to clear your browser cache/storage due to how the providers are stored/managed in the frontend