Commit Graph

99 Commits

Author SHA1 Message Date
wizardchen 92e02c1d49 chore(llm): add fire-once OpenAI-layer stream diagnostic logs
Add per-stream once-only logs at the OpenAI-protocol layer so we can
triage streaming behavior (natural-stop vs tool-call, TTFC, ordering of
reasoning/content/tool_calls) without grepping through every delta.

streamState now tracks:
  - streamStartedAt    : baseline for elapsed_ms on each fire-once log
  - firstContentSeen   : delta.Content first appearance
  - firstReasoningSeen : reasoning_content first appearance
  - firstToolCallSeen / noToolCallStopLogged (existing flags retained)

Logs emitted at most once per stream:
  [LLM Stream] First reasoning_content at OpenAI layer (len, preview, elapsed_ms)
  [LLM Stream] First delta.Content at OpenAI layer (len, preview, tool_call_seen, thinking_seen, elapsed_ms)
  [LLM Stream] First tool_calls delta at OpenAI layer (count, first_id, first_name, first_content_seen, thinking_seen, elapsed_ms)
  [LLM Stream] Natural-stop at OpenAI layer (finish=stop, tool_calls field never observed, thinking_seen, first_content_seen, elapsed_ms)

Together with the existing agent-layer "Natural-stop candidate detected"
log this lets a single grep reconstruct the temporal layout of one stream
(reasoning -> content -> tool_call OR natural-stop) and tell apart:
  (A) tool_calls field truly absent (real natural-stop)
  (B) tool_calls field arrived but high-level marker not yet emitted

Pure logging change; no behavior change. Previews use the existing
truncateForDebug helper (rune-safe, capped at 80 chars).
2026-05-07 18:28:28 +08:00
toy0116 8955bf1aa8 fix(embedding): OpenAIEmbedder.doRequestWithRetry shadows err · returns (nil, nil) on connection failure · caller nil-derefs and SIGSEGVs
Reproduce:

  1. Run WeKnora pointing OPENAI_BASE_URL at any OpenAI-compatible
     embedding endpoint.
  2. Stop that endpoint.
  3. Issue any RAG-mode chat / knowledge_search query — the pipeline
     reaches chunk_search_parallel → knowledgeBaseService.GetQueryEmbedding
     → OpenAIEmbedder.Embed → OpenAIEmbedder.BatchEmbed.
  4. Observe the entire WeKnora process SIGSEGV instead of returning a
     graceful 5xx.

Stack (real, observed in production):

  panic: runtime error: invalid memory address or nil pointer dereference
  [signal SIGSEGV: segmentation violation code=0x2 addr=0x40]

  internal/models/embedding/openai.go:195 +0x458   BatchEmbed
  internal/models/embedding/openai.go:93  +0xb0    Embed
  internal/application/service/knowledgebase_search.go:35
                                                   GetQueryEmbedding
  internal/application/service/chat_pipeline/search.go:371
                                                   searchByTargets.func1

Root cause — variable shadowing in doRequestWithRetry:

  func (e *OpenAIEmbedder) doRequestWithRetry(...) (*http.Response, error) {
      var resp *http.Response
      var err error                                        // outer err
      ...
      for i := 0; i <= e.maxRetries; i++ {
          ...
          req, err := http.NewRequestWithContext(...)      // ← `:=` shadows
                                                           //   outer `err`
                                                           //   because `req`
                                                           //   is new in
                                                           //   the loop scope
          if err != nil { ... continue }
          ...
          resp, err = e.httpClient.Do(req)                 // writes to the
                                                           // shadowed
                                                           // loop-local err
          if err == nil { return resp, nil }
          logger.Errorf("attempt %d failed: %v", i+1, err) // logs the inner err
      }
      return nil, err                                      // returns OUTER
                                                           // err — never set
  }

When httpClient.Do returns connection errors on every attempt, the loop
logs them faithfully but the outer err stays nil. The function returns
(nil, nil). Caller in BatchEmbed reads:

  resp, err := e.doRequestWithRetry(ctx, jsonData)
  if err != nil { return nil, ... }       // skipped (err is nil)
  if resp.Body != nil {                   // ← line 195 · resp itself is nil
      defer resp.Body.Close()             //   nil pointer dereference
  }                                       //   → SIGSEGV → process dies

Fix — declare `req` separately so the shared `err` variable is not shadowed:

  var req *http.Request
  req, err = http.NewRequestWithContext(...)               // outer err

After the fix, when all retries fail, doRequestWithRetry returns the real
error (e.g. `dial tcp 127.0.0.1:11434: connect: connection refused`),
the caller propagates it as a regular error, the chat pipeline returns a
5xx to the client, and the process keeps running.

Verified by stopping the embedding upstream while WeKnora was serving
queries · process stayed up · returned graceful errors · resumed normal
operation when the upstream came back. Without the patch the same
sequence killed the process within one query.
2026-05-04 23:18:42 +08:00
wizardchen 492e92580b feat(observability): integrate Langfuse for LLM token tracking and tracing
Closes #620 #497. Add opt-in Langfuse observability covering all five
model types (chat, embedding, rerank, VLM, ASR) with HTTP-request-scoped
traces and Docker Compose support (both cloud and self-hosted).

Core package internal/tracing/langfuse:
- HTTP client with batched async ingestion (non-blocking in request path)
- Sampling, environment / release tagging, and graceful fallback when
  LANGFUSE_* env vars are absent (wrappers become no-ops)
- Gin middleware opens one trace per traced request and finishes it after
  the handler chain returns, attaching method / path / user / session
- Trace context is stored under a typed key exported from internal/types
  so logger.CloneContext can preserve it across handler / goroutine
  boundaries (otherwise each LLM call auto-created an orphan trace,
  fragmenting one request into many)

Per-model generation wrappers (opt-in via NewChat/NewEmbedder/...):
- chat: captures prompt, streaming output, token usage + TTFT
- embedding: approximates tokens when the provider omits usage
- rerank: previews query/docs, summarizes results to keep payload small
- vlm: records image count and total bytes, never uploads raw pixels
- asr: records file size and audio duration, never uploads audio bytes

Async title generation (GenerateTitleAsync) now forwards the trace key
into the goroutine so title calls appear under the parent chat trace.

Docker Compose:
- LANGFUSE_* env passthrough on the `app` service for cloud deployments
- Optional `langfuse` profile spins up a self-hosted Langfuse stack that
  reuses WeKnora's existing PostgreSQL (separate database via an idempotent
  init container that fixes ICU collation drift) and Redis (separate DB
  number), adding only ClickHouse, MinIO, web and worker containers
- web/worker entrypoints URL-encode DB_PASSWORD / REDIS_PASSWORD at start
  to avoid Prisma P1013 when passwords contain @ / # / etc.

Docs: docs/Langfuse集成.md covers cloud vs self-hosted, per-model usage
strategy, code map, and resource footprint.
2026-04-24 10:29:19 +08:00
wizardchen fd3e2992b1 feat(models): support custom HTTP headers across all remote model calls
Introduce per-model `custom_headers` config (similar to OpenAI Python SDK's
`extra_headers`) so users can inject gateway auth tokens, trace IDs, etc.
into every outbound API request for chat / embedding / rerank / VLLM / ASR
models. Reserved headers like Authorization / Content-Type are always
preserved to avoid breaking auth or signing flows.

Along the way, unify production and "test connection" paths onto a single
`ConfigFromModel(*types.Model, appID, appSecret)` constructor in each
model package. Both `service.modelService.GetXxxModel` and the four
`handler.initialization.Check*Model` / `TestEmbeddingModel` endpoints now
go through the same field mapping, so new parameters only need to be
added in one place.

Backend:
- Add `CustomHeaders map[string]string` to `types.ModelParameters` with
  JSON/YAML `omitempty` tags for forward compatibility.
- New `internal/utils/extraheaders.go` providing `ApplyCustomHeaders`
  (for hand-rolled HTTP paths) and `WrapHTTPClientWithHeaders` /
  `CustomHeadersRoundTripper` (for SDK paths like go-openai). Reserved
  headers (Authorization, api-key, Content-Type, Accept, Host,
  Content-Length, User-Agent) are filtered out.
- Inject headers in every remote model path: chat (SDK + raw HTTP),
  embedding (openai/aliyun/jina/volcengine/nvidia/azure_openai), rerank
  (remote_api/aliyun/jina/nvidia/zhipu — via shared `customHeaderSetter`
  interface), VLM and ASR (via http.Client wrapping).
- Add `ConfigFromModel` to each of chat/embedding/rerank/vlm/asr,
  consolidating field mapping (ExtraConfig, CustomHeaders, InterfaceType
  defaulting, WeKnoraCloud credentials, etc.) and cover it with
  dedicated unit tests per package.
- Refactor `service/model.go`: replace ~100 lines of hand-written Config
  literals with one-line `ConfigFromModel` calls; drop the now-unused
  `stringMapToAnyMap` helper.
- Refactor `handler/initialization.go` test-connection endpoints: merge
  four ad-hoc request structs into one `ModelTestRequest`, extract
  `buildTestModel` and `resolveTenantWeKnoraCloudCreds` helpers, and
  route all four endpoints through `ConfigFromModel` + `NewXxx` so the
  test path is now behaviorally identical to production.

Frontend:
- Add `custom_headers` to the `ModelConfig` API type.
- `ModelEditorDialog.vue`: new Key-Value header editor (add/remove rows),
  auto-converts map <-> array when loading/saving, and passes the
  current header set to the `Test Connection` button so the preview
  reflects exactly what production will send.
- `ModelSettings.vue`: serialize the header array back into a map for
  the backend (drops empty rows).
- i18n: add custom-header labels / descriptions / placeholders to
  zh-CN, en-US, ru-RU, ko-KR.

Tests:
- `internal/utils/extraheaders_test.go` covers reserved-header filtering
  and round-tripper wrapping (including nil-client fallback).
- New `config_from_model_test.go` in chat / embedding / rerank / vlm /
  asr verifies all fields (CustomHeaders, ExtraConfig, InterfaceType
  defaulting, AppID/AppSecret) are propagated end-to-end.
2026-04-23 23:36:40 +08:00
wizardchen 1ec43b328d refactor: Simplify WeKnoraCloud request customization and message conversion
- Removed redundant struct definitions for WeKnoraCloud requests and messages, streamlining the customization process.
- Updated the weKnoraCloudRequestCustomizer function to directly modify the request object, enhancing clarity and reducing complexity.
- Improved the convertToWeKnoraCloudMessagesFromOpenAI function to maintain the original message structure while ensuring compatibility with WeKnoraCloud requirements.
2026-04-23 17:52:43 +08:00
wizardchen 9f916181db refactor: Simplify logging in RemoteAPIChat HTTP requests
- Removed header printing from the chatWithRawHTTP method to streamline logging.
- Updated log message to focus on endpoint and model name, enhancing clarity while reducing verbosity.
2026-04-23 11:22:44 +08:00
wizardchen a81ef5fbb2 fix: improve tenant access token logging and update test cases
- Enhanced the logging of the tenant access token in the Feishu client to handle variable lengths for prefix and suffix, ensuring accurate display even for shorter tokens.
- Updated the test cases in `connector_test.go` to reflect changes in the endpoint path for file downloads, improving test reliability.
- Adjusted example outputs in `example_test.go` for clarity and consistency.
- Modified image resolution tests to correct expected outcomes based on updated criteria for icon images.
- Added environment variable settings in image resolver tests to ensure localhost accessibility during testing.

These changes enhance the robustness of logging and testing mechanisms across the application.
2026-04-22 21:17:30 +08:00
moineye 4ca0c7a644 fix: ReadEvent incompatible sse data format 2026-04-20 22:29:38 +08:00
wizardchen 53e8e17df4 feat(logger): implement LLM debug logging functionality
- Added a new logger for LLM calls, enabling detailed logging of model interactions, including request and response data.
- Introduced configuration options for enabling and specifying the log directory for LLM debug logs.
- Implemented cleanup for old log files to manage disk space effectively.
- Wrapped existing chat implementations to log calls when debug logging is enabled, enhancing traceability for model interactions.
2026-04-16 23:15:02 +08:00
wizardchen 9ba8582f70 feat(weknoracloud): implement WeKnoraCloud VLM integration
- Added WeKnoraCloudVLM struct to handle interactions with the WeKnoraCloud API, including image and text processing capabilities.
- Enhanced model configuration to include AppID and AppSecret for secure API access.
- Updated modelService to resolve WeKnoraCloud credentials and pass them to the VLM configuration.
- Implemented Predict method for sending requests to the WeKnoraCloud API and processing responses.

This update introduces a new integration with WeKnoraCloud, expanding the application's capabilities in handling multimedia content.
2026-04-15 15:43:08 +08:00
wizardchen 86d26fa9bf feat(video): remove video upload support and update related terminology
- Removed support for video file uploads across the application, including updates to the knowledge base and document processing services.
- Updated internationalization files to reflect the removal of video-related terminology, changing labels and descriptions to focus solely on audio processing.
- Adjusted file type handling to exclude video formats, ensuring users receive accurate feedback regarding supported file types.
- Enhanced error handling to provide clear messages when users attempt to upload unsupported video files.

This update streamlines the application by focusing on audio processing capabilities and improving user experience through clearer messaging.
2026-04-14 22:59:14 +08:00
wizardchen 0fcab3a413 feat(video): update ASR terminology and file type labels for improved clarity
- Changed 'Audio Processing' to 'Audio & Video' in English, Korean, Russian, and Chinese translations to reflect expanded functionality.
- Updated ASR configuration titles and descriptions to include video processing capabilities, enhancing user understanding of the feature.
- Renamed file type labels from 'Audio Files' to 'Audio & Video' across multiple languages for consistency and clarity.
- Enhanced document upload handling in the KnowledgeBase to filter unsupported file types, providing user feedback for filtered images, videos, and audio files.

This update improves the internationalization of the application and clarifies the capabilities of the ASR feature.
2026-04-14 22:59:14 +08:00
wizardchen 0eff63b308 feat(weknoracloud): implement credential management and status checks
- Introduced a new WeKnoraCloudSettings component for managing APPID and APPSECRET.
- Added functionality to save WeKnoraCloud credentials without automatically creating models.
- Implemented credential status checks across various components to provide user feedback on configuration status.
- Updated API endpoints to handle credential saving and status retrieval.
- Enhanced UI elements to guide users in configuring WeKnoraCloud settings.

This update improves the integration of WeKnoraCloud by allowing users to manage their credentials more effectively and receive real-time feedback on their configuration status.
2026-04-14 17:36:01 +08:00
begoniezhao 5082460cc0 fix(embedding): remove hardcoded TruncatePromptTokens in BatchEmbed
Remove the hardcoded TruncatePromptTokens: 512 limit from WeKnoraCloud
BatchEmbed to allow the API to use its default truncation behavior,
avoiding unexpected truncation of longer input texts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:29:49 +08:00
begoniezhao d4edd374df refactor: replace CryptoService with utils AES helpers and simplify encryption
- Remove infrastructure/crypto package (CryptoService, config, PBKDF2-based encryption)
- Replace with lightweight utils.GetAESKey/EncryptAESGCM/DecryptAESGCM helpers
- Remove cryptoSvc dependency from modelService, tenantService, weKnoraCloudService
- Remove crypto state persistence logic from container initialization
- Add TruncatePromptTokens field to WeKnoraCloud embed request
- Update frontend hint text for WeKnoraCloud credential errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:55:39 +08:00
begoniezhao 2c0c1b8bab feat: integrate ChatBot provider and docreader 2026-04-13 17:47:24 +08:00
DaWesen b80bdb1079 feat: add video multimodal functionality 2026-04-09 19:19:42 +08:00
liweixin 2b10cc54de test: remove unnecessary OpenAI dimensions regression test 2026-04-09 19:19:25 +08:00
liweixin 5233394d01 fix: gate Azure OpenAI dimensions support 2026-04-09 19:19:25 +08:00
liweixin bf514ff68a test: harden remote api chat fixture for SSRF validation 2026-04-09 19:19:25 +08:00
liweixin c663182a00 feat: add support for dimensions parameter in Azure OpenAI and OpenAI embedding requests 2026-04-09 19:19:25 +08:00
liweixin c6215405a5 fix: override AzureModelMapperFunc to preserve deployment name as-is 2026-04-09 19:19:25 +08:00
liweixin 2eb2dea634 feat: add Azure OpenAI support for embedding models 2026-04-09 19:19:25 +08:00
liweixin 3cfd034eec feat: add Azure OpenAI support for VLM models 2026-04-09 19:19:25 +08:00
liweixin 22ec575727 feat: add Azure OpenAI support for chat models 2026-04-09 19:19:25 +08:00
liweixin c9001ef9d9 feat: add Azure OpenAI provider registration with metadata 2026-04-09 19:19:25 +08:00
liweixin 8ceb0b194b feat: add Azure OpenAI provider constants and URL detection 2026-04-09 19:19:25 +08:00
AndyYang f63c9f6dbe fix: resolve tool name duplication in streaming tool calls 2026-04-05 18:25:45 +08:00
wizardchen c93f4e94ae feat(asr): add ASR model connection check and update related components
- Implemented a new function to check ASR model connectivity via the /v1/audio/transcriptions endpoint.
- Updated ModelEditorDialog.vue to integrate ASR model checks and adjust UI elements accordingly.
- Enhanced localization files to reflect changes in ASR terminology and descriptions.
- Added ASR configuration options to the knowledge base and updated related migration scripts.
- Refactored model handling to support ASR as a distinct model type in the application.
2026-04-02 21:27:27 +08:00
wizardchen 624e24ba49 feat(asr): integrate Automatic Speech Recognition (ASR) support
- Added ASR configuration options to the knowledge base and model settings.
- Implemented ASR model selection and transcription capabilities in the knowledge processing pipeline.
- Enhanced file upload support to include audio formats for ASR processing.
- Updated localization files to include ASR-related labels and descriptions.
- Refactored model handling to accommodate ASR as a new model type.
2026-04-02 21:27:27 +08:00
nullkey d68c94a11a fix(stream): use io.EOF instead of errors.New("EOF") in SSEReader
errors.New("EOF") creates a distinct error instance that doesn't match
io.EOF, causing processRawHTTPStream to silently ignore normal stream
termination without sending a done response.

- SSEReader: return io.EOF instead of errors.New("EOF")
- processRawHTTPStream: handle io.EOF as normal completion, send done
  response with usage/toolCalls (aligned with processStream behavior)

Fixes #860
2026-04-02 18:35:53 +08:00
wizardchen 4dd481560d refactor(chat): simplify temperature option handling in chat request builders
- Streamlined the handling of the temperature option in both OllamaChat and RemoteAPIChat by removing unnecessary conditional checks.
- Ensured that the temperature value is directly assigned when options are provided, improving code clarity and reducing complexity.
2026-03-31 12:19:22 +08:00
wizardchen eaf17e65f8 docs: remove WeCom document integration from data source import documentation
- Deleted references to WeCom document integration in the data source import module documentation.
- Updated the quick start guide and related sections to reflect the removal of WeCom, enhancing clarity and focus on supported platforms.
2026-03-30 20:46:07 +08:00
Manx98 1baabb6c05 feat: support system proxy for remote API 2026-03-30 10:46:19 +08:00
AndyYang 930a953f41 feat: fix enable_thinking for Aliyun Qwen models in streaming mode 2026-03-30 10:42:31 +08:00
Manx98 2a3cc92b99 refactor: use unified NVIDIA API for both chat and VLM 2026-03-30 10:38:50 +08:00
ochan.kwon 380f5d9405 fix(agent): prevent empty response when no Knowledge Base is configured
- guard against empty content completion in analyzeResponse/executeLoop
  with retry (max 2), nudge message, and fallback response
- propagate actual finish_reason through streaming pipeline instead of
  hardcoding "stop" in streamThinkingToEventBus
- add FinishReason field to StreamResponse and streamLLMResult
- add finish marker chunk in processStreamDelta for empty content scenarios
- propagate lastFinishReason through EOF handler in processStream
- strengthen PureAgent system prompt with MCP tool guidelines and
  graceful fallback instructions for unanswerable questions
- add unit tests for empty response bug and finish_reason propagation
2026-03-27 14:56:12 +08:00
wizardchen 72dfb9ce75 feat(prompt): enhance context and intent classification in templates
- Updated context template to include runtime metadata such as current time and week, improving contextual awareness in user queries.
- Enhanced rewrite template with critical instructions for intent classification, ensuring that rewritten questions preserve essential entities and keywords.
- Refined intent classification logic to prioritize user intents more effectively, improving the accuracy of responses based on user queries.
- Added examples to clarify expected input and output formats for intent classification, enhancing usability for developers.
2026-03-26 18:57:12 +08:00
PR Bot d0811898b0 feat: upgrade MiniMax models from M2.1 to M2.7
Update MiniMax provider description and model references from the legacy
MiniMax-M2.1/M2.1-lightning to the latest MiniMax-M2.7/M2.7-highspeed
models. Also update Novita AI's MiniMax model reference from M2.5 to M2.7.

Changes:
- Update MiniMax provider description in minimax.go
- Update Novita provider MiniMax model reference in novita.go
- Update all i18n locale files (en-US, zh-CN, ko-KR, ru-RU)
- Add MiniMax provider validation tests
2026-03-26 18:51:25 +08:00
wizardchen fd5278d62d feat(security): enhance SSRF protection in RemoteAPIChat
- Replaced the default DialContext with SSRFSafeDialContext in the raw HTTP client to improve security against DNS rebinding attacks.
- Added SSRF validation for BaseURL and endpoint in NewRemoteAPIChat and chat methods, ensuring safer URL handling.
- Updated security utility functions to provide consistent SSRF checks across the application.
2026-03-26 11:37:07 +08:00
wizardchen de0169d7c0 feat(chat): add ParallelToolCalls option to ChatOptions and update related functionality
- Introduced a new ParallelToolCalls field in ChatOptions to control parallel execution of tool calls.
- Updated the BuildChatCompletionRequest method to handle the new ParallelToolCalls option, ensuring it is correctly propagated in requests.
- Enhanced the streamThinkingToEventBus function to utilize the ParallelToolCalls setting.
- Added comprehensive tests to validate the behavior of ParallelToolCalls in various scenarios, ensuring correct propagation and default handling.
2026-03-25 22:08:29 +08:00
wizardchen 2b56c4fbac feat(agent): enhance streaming diagnostics and event tracking
- Added diagnostics for streaming events in the AgentEngine, including chunk counts and response type distributions.
- Implemented logging for emitted event types during the thinking process to aid in debugging and performance analysis.
- Updated the session handler to provide more informative warnings when fallback answers are emitted due to non-streaming behavior.
- Introduced a dedicated HTTP client for Ollama to improve connection handling and timeout management during streaming calls.
2026-03-25 22:08:29 +08:00
wizardchen e7c21c0733 feat(chat): add Volcengine support and refactor thinking configuration
- Introduced Volcengine as a new provider in the chat provider specifications.
- Refactored the thinking configuration to a more generic format, applicable to both LKEAP and Volcengine.
- Updated request customizers to handle the new thinking configuration structure for both LKEAP and Volcengine providers.
2026-03-25 22:08:29 +08:00
wizardchen 0bb1a581de feat(agent): enhance token management and context handling in AgentEngine
- Added token usage tracking to the AgentEngine, allowing for better estimation of current context token counts.
- Implemented a new method to estimate current tokens based on previous usage and newly appended messages, improving context management.
- Updated context window management to utilize estimated token counts for more efficient message consolidation.
- Enhanced streaming methods to include token usage information, providing better insights into LLM interactions.
- Refactored the token estimator to support BPE tokenization, ensuring accurate token counts for messages.
- Added unit tests to validate new token estimation and context management functionalities.
2026-03-25 22:08:29 +08:00
wizardchen 9f4fb39e10 feat(chat): introduce provider-specific request customizers and specs
- Added a new `ProviderSpec` struct to define provider-specific behaviors for chat completions.
- Implemented request and endpoint customizers for various providers including Qwen3, LKEAP, DeepSeek, and Generic.
- Refactored the `NewRemoteChat` function to utilize the new provider specs for customizing requests based on the provider and model name.
- Removed legacy chat implementations for LKEAP, NVIDIA, DeepSeek, and Qwen, consolidating their logic into the new structure.
2026-03-25 22:08:29 +08:00
wizardchen e936e0b347 feat(agent): implement LLM call timeout and transient error handling
- Introduced a configurable LLM call timeout with a default value, allowing for better control over LLM call durations.
- Added logic to retry transient errors (e.g., timeouts, rate limits) up to a specified maximum number of retries, improving robustness in error handling.
- Implemented parameter casting for tool arguments to ensure correct types are used, addressing common LLM quirks.
- Enhanced tool execution error messages with guidance for retrying with different approaches.
- Added validation for configuration values to prevent runtime errors.
2026-03-25 22:08:29 +08:00
lyingbug e5c46642e9 fix: handle thinking stream edge cases (unclosed tags + missing done)
Two related fixes for thinking mode streaming:

1. chat_completion_stream.go: When the response channel closes
   unexpectedly (context cancelled, upstream error) while thinking
   is in progress, the <think> tag was left unclosed. This caused
   the stored message to have an incomplete tag, making the frontend
   show a perpetual "thinking..." state on history reload.
   Now we emit a closing </think> tag when the channel ends with
   thinkingStarted=true but thinkingEnded=false.

2. remote_api.go: The thinking Done=true event was only sent when
   the first answer content chunk arrived. If the model produced
   only reasoning with no answer (e.g., finish_reason set with
   empty content), the thinking-done signal was never emitted.
   Now we also check isDone && state.hasThinking at the end of
   processStreamDelta to ensure the done event is always sent.
2026-03-25 22:08:29 +08:00
Alex-wuhu f0c6d0752a feat(provider): add Novita AI as LLM provider
Add Novita AI as a new model provider supporting chat, embedding,
and VLLM model types via OpenAI-compatible API endpoint.

- Add NovitaProvider implementation with OpenAI-compatible API
- Register ProviderNovita in provider registry
- Add ModelSourceNovita constant
- Add Novita to frontend fallback provider options
- Add i18n translations for en-US, zh-CN, ru-RU, ko-KR
2026-03-24 22:10:42 +08:00
Andy Yang 62e6ae960f fix(chat): support reasoning content in streaming responses for vLLM models
- Parse reasoning field together with standard stream response using local struct
- Unify reasoning content extraction from standard and vLLM response paths
- Adapt processStreamDelta to accept reasoning content as a separate parameter
- Send reasoning content as thinking response in the stream when available
- Ensure compatibility with existing SDK logic by constructing standard choice object
2026-03-24 11:56:55 +08:00
Dounx a9c2d61695 fix: add OpenRouter embedding provider support 2026-03-20 15:50:42 +08:00