Merge remote-tracking branch 'origin/master' into feat/sandbox

# Conflicts:
#	src/langbot/pkg/api/http/controller/groups/plugins.py
#	src/langbot/pkg/core/app.py
#	src/langbot/pkg/core/stages/build_app.py
#	src/langbot/templates/config.yaml
#	uv.lock
#	web/src/app/home/components/home-sidebar/HomeSidebar.tsx
#	web/src/app/home/components/home-sidebar/SidebarDataContext.tsx
#	web/src/app/home/layout.tsx
#	web/src/app/home/plugins/components/plugin-market/PluginMarketComponent.tsx
#	web/src/i18n/locales/en-US.ts
#	web/src/i18n/locales/es-ES.ts
#	web/src/i18n/locales/ja-JP.ts
#	web/src/i18n/locales/th-TH.ts
#	web/src/i18n/locales/vi-VN.ts
#	web/src/i18n/locales/zh-Hans.ts
#	web/src/i18n/locales/zh-Hant.ts
#	web/src/router.tsx
This commit is contained in:
Junyan Qin
2026-05-05 14:05:53 +08:00
90 changed files with 7488 additions and 871 deletions
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Qiniu</title><path d="M23.111 4.6a.914.914 0 00-.861.161A13.443 13.443 0 017.947 8.897L7.38 6.831a1.076 1.076 0 00-1.211-.698l.27 2.18c-1.816-.827-2.313-.946-3.587-2.45C2.674 5.729 1.263 4.472.89 4.6a11.906 11.906 0 005.892 6.497l.738 5.97s.33 2.286 2.473 2.286h4.586c2.144 0 2.474-2.286 2.474-2.286l.518-4.28c-1.393-.11-2.268.857-2.546 1.814-.465 1.614-.465 1.716-.557 1.998-.188.575-.806.644-.806.644h-2.753s-.617-.07-.806-.644c-.12-.371-.727-2.54-1.335-4.74A11.877 11.877 0 0023.11 4.599V4.6z" fill="#06AEEF"></path></svg>

After

Width:  |  Height:  |  Size: 649 B

@@ -0,0 +1,45 @@
from __future__ import annotations
import typing
import openai
from . import chatcmpl
class QiniuChatCompletions(chatcmpl.OpenAIChatCompletions):
"""七牛云 ChatCompletion API 请求器"""
client: openai.AsyncClient
default_config: dict[str, typing.Any] = {
'base_url': 'https://api.qnaigc.com/v1',
'timeout': 120,
}
async def scan_models(self, api_key: str | None = None) -> dict[str, typing.Any]:
try:
result = await super().scan_models(api_key)
except Exception:
return self._qiniu_fallback_scan_result()
models = result.get('models') or []
if not models:
return self._qiniu_fallback_scan_result()
return result
def _qiniu_fallback_scan_result(self) -> dict[str, typing.Any]:
mid = 'deepseek-v3'
return {
'models': [
{
'id': mid,
'name': mid,
'type': 'llm',
'abilities': [],
}
],
'debug': {
'request': {'method': 'GET', 'url': '', 'headers': {}},
'response': {},
},
}
@@ -0,0 +1,31 @@
apiVersion: v1
kind: LLMAPIRequester
metadata:
name: qiniu-chat-completions
label:
en_US: Qiniu
zh_Hans: 七牛云
icon: qiniu.svg
spec:
config:
- name: base_url
label:
en_US: Base URL
zh_Hans: 基础 URL
type: string
required: true
default: https://api.qnaigc.com/v1
- name: timeout
label:
en_US: Timeout
zh_Hans: 超时时间
type: integer
required: true
default: 120
support_type:
- llm
provider_category: maas
execution:
python:
path: ./qiniuchatcmpl.py
attr: QiniuChatCompletions
@@ -187,6 +187,12 @@ class N8nServiceAPIRunner(runner.RequestRunner):
if not query.session.using_conversation.uuid:
query.session.using_conversation.uuid = str(uuid.uuid4())
# Keep query variables in sync with the generated/new conversation id.
# query.variables is later merged into payload and would otherwise
# overwrite the generated conversation_id with the stale preprocessor
# value (usually None for a new conversation).
query.variables['conversation_id'] = query.session.using_conversation.uuid
# 预处理用户消息
plain_text = await self._preprocess_user_message(query)