mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-10 07:46:02 +00:00
feat(models): add provider model scanning (#2106)
* feat(models): add provider model scanning * fix: double close button * feat: update plugin module * fix(monitoring): WeChat Work feedback recording bugs (#2108) * fix(monitoring): fix WeChat Work feedback recording bugs - Fix feedback events silently dropped when stream session expires: dispatch feedback handlers regardless of session availability - Fix IntegrityError on repeated feedback (like→dislike) for same message: implement UPSERT logic in record_feedback() - Fix cancel feedback (type=3) not removing records: add delete logic - Fix inaccurate_reasons validation error: convert int reason codes to strings before creating FeedbackEvent (Pydantic expects List[str]) - Fix feedback timestamps 8 hours off in frontend: use parseUTCTimestamp instead of new Date() for UTC timestamp parsing - Fix StreamSessionManager.cleanup missing _feedback_index cleanup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(monitoring): apply ruff format to wecom feedback files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: 6mvp6 <13727783693@163.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat: add feat for receive files in wecombot * fix: ruff error * fix: always show sidebar plus buttons on touch/mobile devices (#2115) Agent-Logs-Url: https://github.com/langbot-app/LangBot/sessions/e27a4886-fbad-4a7a-8558-67a387852753 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * fix: SPA fallback for all frontend routes, not just /home/* After migrating from Next.js to Vite SPA, routes like /auth/space/callback returned 404 because the static file server only had SPA fallback for /home/*. Now all non-API routes fall back to index.html for React Router to handle. * style: ruff format main.py * feat: add marketplace link when no parser available for file upload Links to /home/market?category=Parser, same pattern as knowledge engine selector. * fix: lint error * fix(user): allow password login and password change for Space accounts with local password set Previously, Space accounts were unconditionally blocked from password login and password change based on account_type. Now the check verifies whether the user actually has a local password set, allowing Space users who have set a local password to authenticate and change it normally. * feat: add edition field to telemetry payload Sends constants.edition (community/saas) with each telemetry event so Space can distinguish between community and SaaS instances. * style: ruff format telemetry.py * fix(dingtalk): use voice recognition text instead of raw audio binary When DingTalk sends a voice message to the bot, the callback JSON contains a 'recognition' field with the speech-to-text result (powered by Qwen). Previously, LangBot only extracted the 'downloadCode' to download the raw audio binary and passed it as 'file_base64' to LLM APIs, which caused 400 errors since most models don't support this content type. This patch: - Extracts the 'recognition' field from DingTalk audio message content - Uses it as plain text input to the LLM instead of raw audio - Falls back to audio binary only when no recognition text is available - Fixes duplicate text issue for audio messages with recognition Fixes voice messages returning 'Request failed' on all LLM models. * feat: integrate Alembic for database migrations Replace manual if-sqlite/if-postgres branching with Alembic: - Add alembic dependency - Create programmatic alembic env (no CLI/alembic.ini needed) - Support async engines via run_sync passthrough - render_as_batch=True for SQLite ALTER TABLE compatibility - Auto-stamp baseline on first run (existing DB at version 25) - Run alembic upgrade head after legacy migrations - Include sample migration showing schema + data migration patterns - Add alembic dir to package-data for distribution * ci: add migration test workflow for SQLite and PostgreSQL Tests alembic upgrade on both databases: - Stamp baseline on existing schema - Upgrade to head - Idempotent re-upgrade - Fresh DB upgrade from scratch * feat: add autogenerate support and CLI entrypoint for alembic - autogenerate: compare ORM models vs DB schema to generate migrations - CLI: python -m langbot.pkg.persistence.alembic_runner <command> - autogenerate, upgrade, stamp, current - Reads data/config.yaml for DB connection * fix: add filereader for dingtalk,lark (#2122) * fix: add filereader for dingtalk * feat: add lark * feat: update uv.lock * chore: update version to 4.9.6 in pyproject.toml, __init__.py, and uv.lock * fix: update langbot-plugin version to 0.3.8 * fix: update langbot-plugin version to 0.3.8 * docs: update database migration instructions in AGENTS.md * fix(dashscopeapi): fix null value check in reasoning content processing logic (#2128) * fix(n8n-runner): fix output_key not applied when n8n returns plain JSON (#2119) * fix: bump dependencies to resolve Dependabot security alerts (#2130) * fix: bump dependencies to resolve Dependabot security alerts Python: - aiohttp: >=3.11.18 → >=3.13.4 (duplicate Host headers, header injection, redirect leak, multipart DoS) - cryptography: >=44.0.3 → >=46.0.7 (buffer overflow with non-contiguous buffers) - pillow: >=11.2.1 → >=12.2.0 (FITS GZIP decompression bomb, HIGH) - langchain-text-splitters: >=0.0.1 → >=1.1.2 (SSRF redirect bypass) - langchain-core: add >=1.2.28 (incomplete f-string validation) - langsmith: add >=0.7.31 (streaming token redaction bypass) - python-multipart: add >=0.0.26 (multipart DoS) - Mako: add >=1.3.11 (path traversal) - pytest: >=8.4.1 → >=9.0.3 (tmpdir handling) - uv: >=0.7.11 → >=0.11.6 (arbitrary file deletion) JavaScript (web/): - vite: ^8.0.3 → ^8.0.5 (fs.deny bypass, WebSocket file read, path traversal, HIGH) - axios: ^1.13.5 → ^1.15.0 (cloud metadata exfiltration) - lodash: ^4.17.23 → ^4.18.0 (code injection via _.template, prototype pollution, HIGH) * fix: update pnpm-lock.yaml for bumped dependencies * feat(ci): add i18n key consistency check for frontend locales (#2133) * feat(ci): add i18n key consistency check workflow Agent-Logs-Url: https://github.com/langbot-app/LangBot/sessions/c7bf50da-189b-49a5-9671-dbe8e70ff9d0 Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * feat(ci): replace eval with line-by-line parser, add permissions block Agent-Logs-Url: https://github.com/langbot-app/LangBot/sessions/c7bf50da-189b-49a5-9671-dbe8e70ff9d0 Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> * feat(models): add provider model scanning * feat(models): add 'select all' functionality and enrich model abilities * fix:ruff * fix:ruff --------- Co-authored-by: WangCham <651122857@qq.com> Co-authored-by: 6mvp6 <119733319+6mvp6@users.noreply.github.com> Co-authored-by: 6mvp6 <13727783693@163.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Guanchao Wang <wangcham233@gmail.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com> Co-authored-by: RockChinQ <rockchinq@gmail.com> Co-authored-by: haiyangbg <zhouhaiyangaa@gmail.com> Co-authored-by: Rock Chin <1010553892@qq.com> Co-authored-by: Amadeus <115918672+AmadeusKurisu1@users.noreply.github.com> Co-authored-by: hzhhong <hung.z.h916@gmail.com> Co-authored-by: fdc310 <2213070223@qq.com>
This commit is contained in:
@@ -181,6 +181,10 @@ const enUS = {
|
||||
mustBeValidNumber: 'Must be a valid number',
|
||||
mustBeTrueOrFalse: 'Must be true or false',
|
||||
requestURL: 'Request URL',
|
||||
scanURL: 'Scan Models URL',
|
||||
scanURLPlaceholder: 'Leave empty to use Request URL + /models',
|
||||
scanURLDescription:
|
||||
'Fill in the actual model-list endpoint when model scanning does not use the same address as model invocation.',
|
||||
apiKey: 'API Key',
|
||||
abilities: 'Abilities',
|
||||
selectModelAbilities: 'Select model abilities',
|
||||
@@ -218,6 +222,20 @@ const enUS = {
|
||||
providerCount: '{{count}} providers',
|
||||
// New keys for provider-based structure
|
||||
addModel: 'Add Model',
|
||||
manualAdd: 'Manual',
|
||||
scanAdd: 'Scan',
|
||||
scanModels: 'Scan Models',
|
||||
scanModelsHint:
|
||||
'Read available models from the current provider, then select which ones to add.',
|
||||
scannedModels: 'Scanned Models',
|
||||
scanDebug: 'Debug Info',
|
||||
searchScannedModels: 'Search scanned models',
|
||||
noScannedModels: 'No scan results yet. Click the button above to scan.',
|
||||
noScannedModelsMatch: 'No matching models',
|
||||
addSelectedModels: 'Add Selected',
|
||||
addSelectedModelsSuccess: '{{count}} model(s) added',
|
||||
selectAll: 'Select All',
|
||||
alreadyAdded: 'Already added',
|
||||
addLLMModel: 'Add LLM Model',
|
||||
addEmbeddingModel: 'Add Embedding Model',
|
||||
provider: 'Provider',
|
||||
|
||||
@@ -227,6 +227,20 @@ const esES = {
|
||||
providerCount: '{{count}} proveedores',
|
||||
// New keys for provider-based structure
|
||||
addModel: 'Añadir modelo',
|
||||
manualAdd: 'Manual',
|
||||
scanAdd: 'Escanear',
|
||||
scanModels: 'Escanear modelos',
|
||||
scanModelsHint:
|
||||
'Lee los modelos disponibles del proveedor actual y luego elige cuáles agregar.',
|
||||
scannedModels: 'Modelos detectados',
|
||||
searchScannedModels: 'Buscar modelos detectados',
|
||||
noScannedModels:
|
||||
'Todavía no hay resultados. Pulsa el botón superior para escanear.',
|
||||
noScannedModelsMatch: 'No hay modelos coincidentes',
|
||||
addSelectedModels: 'Agregar seleccionados',
|
||||
addSelectedModelsSuccess: 'Se agregaron {{count}} modelo(s)',
|
||||
selectAll: 'Seleccionar todo',
|
||||
alreadyAdded: 'Ya agregado',
|
||||
addLLMModel: 'Añadir modelo LLM',
|
||||
addEmbeddingModel: 'Añadir modelo Embedding',
|
||||
provider: 'Proveedor',
|
||||
|
||||
@@ -221,6 +221,20 @@
|
||||
'ローカルモデルがありません。作成ボタンをクリックしてモデルを追加してください。',
|
||||
providerCount: '{{count}} 件のプロバイダー',
|
||||
addModel: 'モデルを追加',
|
||||
manualAdd: '手動追加',
|
||||
scanAdd: 'スキャン追加',
|
||||
scanModels: 'モデルをスキャン',
|
||||
scanModelsHint:
|
||||
'現在のプロバイダーから利用可能なモデルを取得し、追加するモデルを選択します。',
|
||||
scannedModels: 'スキャン結果',
|
||||
searchScannedModels: 'スキャン結果を検索',
|
||||
noScannedModels:
|
||||
'まだスキャン結果がありません。上のボタンからスキャンしてください。',
|
||||
noScannedModelsMatch: '一致するモデルがありません',
|
||||
addSelectedModels: '選択したモデルを追加',
|
||||
addSelectedModelsSuccess: '{{count}} 件のモデルを追加しました',
|
||||
selectAll: 'すべて選択',
|
||||
alreadyAdded: '追加済み',
|
||||
addLLMModel: 'LLMモデルを追加',
|
||||
addEmbeddingModel: '埋め込みモデルを追加',
|
||||
provider: 'プロバイダー',
|
||||
|
||||
@@ -215,6 +215,19 @@ const thTH = {
|
||||
noLocalModels: 'ไม่มีโมเดลท้องถิ่น คลิกสร้างเพื่อเพิ่มโมเดล',
|
||||
providerCount: '{{count}} ผู้ให้บริการ',
|
||||
addModel: 'เพิ่มโมเดล',
|
||||
manualAdd: 'เพิ่มเอง',
|
||||
scanAdd: 'สแกน',
|
||||
scanModels: 'สแกนโมเดล',
|
||||
scanModelsHint:
|
||||
'ดึงรายการโมเดลที่ใช้ได้จากผู้ให้บริการปัจจุบัน แล้วเลือกโมเดลที่ต้องการเพิ่ม',
|
||||
scannedModels: 'ผลการสแกน',
|
||||
searchScannedModels: 'ค้นหาผลการสแกน',
|
||||
noScannedModels: 'ยังไม่มีผลการสแกน กดปุ่มด้านบนเพื่อเริ่มสแกน',
|
||||
noScannedModelsMatch: 'ไม่พบโมเดลที่ตรงกัน',
|
||||
addSelectedModels: 'เพิ่มที่เลือก',
|
||||
addSelectedModelsSuccess: 'เพิ่มแล้ว {{count}} โมเดล',
|
||||
selectAll: 'เลือกทั้งหมด',
|
||||
alreadyAdded: 'เพิ่มแล้ว',
|
||||
addLLMModel: 'เพิ่มโมเดล LLM',
|
||||
addEmbeddingModel: 'เพิ่มโมเดล Embedding',
|
||||
provider: 'ผู้ให้บริการ',
|
||||
|
||||
@@ -222,6 +222,19 @@ const viVN = {
|
||||
noLocalModels: 'Không có mô hình cục bộ. Nhấn Tạo để thêm mô hình.',
|
||||
providerCount: '{{count}} nhà cung cấp',
|
||||
addModel: 'Thêm mô hình',
|
||||
manualAdd: 'Thủ công',
|
||||
scanAdd: 'Quét',
|
||||
scanModels: 'Quét mô hình',
|
||||
scanModelsHint:
|
||||
'Đọc danh sách mô hình khả dụng từ nhà cung cấp hiện tại rồi chọn mô hình cần thêm.',
|
||||
scannedModels: 'Kết quả quét',
|
||||
searchScannedModels: 'Tìm trong kết quả quét',
|
||||
noScannedModels: 'Chưa có kết quả quét. Nhấn nút phía trên để bắt đầu.',
|
||||
noScannedModelsMatch: 'Không có mô hình phù hợp',
|
||||
addSelectedModels: 'Thêm mục đã chọn',
|
||||
addSelectedModelsSuccess: 'Đã thêm {{count}} mô hình',
|
||||
selectAll: 'Chọn tất cả',
|
||||
alreadyAdded: 'Đã thêm',
|
||||
addLLMModel: 'Thêm mô hình LLM',
|
||||
addEmbeddingModel: 'Thêm mô hình Embedding',
|
||||
provider: 'Nhà cung cấp',
|
||||
|
||||
@@ -173,6 +173,10 @@ const zhHans = {
|
||||
mustBeValidNumber: '必须是有效的数字',
|
||||
mustBeTrueOrFalse: '必须是 true 或 false',
|
||||
requestURL: '请求URL',
|
||||
scanURL: '扫描模型地址',
|
||||
scanURLPlaceholder: '留空则默认使用请求URL + /models',
|
||||
scanURLDescription:
|
||||
'当模型扫描接口与模型调用接口不是同一个地址时,在这里填写实际的模型列表接口。',
|
||||
apiKey: 'API Key',
|
||||
abilities: '能力',
|
||||
selectModelAbilities: '选择模型能力',
|
||||
@@ -209,6 +213,19 @@ const zhHans = {
|
||||
providerCount: '共 {{count}} 个自定义供应商',
|
||||
// 供应商结构新增键
|
||||
addModel: '添加模型',
|
||||
manualAdd: '手动添加',
|
||||
scanAdd: '扫描添加',
|
||||
scanModels: '扫描模型',
|
||||
scanModelsHint: '从当前供应商接口读取可用模型,然后勾选要添加的模型。',
|
||||
scannedModels: '扫描结果',
|
||||
scanDebug: '调试信息',
|
||||
searchScannedModels: '搜索扫描结果',
|
||||
noScannedModels: '还没有扫描结果,点击上方按钮开始扫描。',
|
||||
noScannedModelsMatch: '没有匹配的模型',
|
||||
addSelectedModels: '添加所选模型',
|
||||
addSelectedModelsSuccess: '已添加 {{count}} 个模型',
|
||||
selectAll: '全选模型',
|
||||
alreadyAdded: '已添加',
|
||||
addLLMModel: '添加对话模型',
|
||||
addEmbeddingModel: '添加嵌入模型',
|
||||
provider: '供应商',
|
||||
|
||||
@@ -208,6 +208,18 @@ const zhHant = {
|
||||
noLocalModels: '暫無本地模型。點擊建立按鈕新增模型。',
|
||||
providerCount: '共 {{count}} 個供應商',
|
||||
addModel: '新增模型',
|
||||
manualAdd: '手動添加',
|
||||
scanAdd: '掃描添加',
|
||||
scanModels: '掃描模型',
|
||||
scanModelsHint: '從目前供應商介面讀取可用模型,然後勾選要添加的模型。',
|
||||
scannedModels: '掃描結果',
|
||||
searchScannedModels: '搜尋掃描結果',
|
||||
noScannedModels: '尚無掃描結果,點擊上方按鈕開始掃描。',
|
||||
noScannedModelsMatch: '沒有符合的模型',
|
||||
addSelectedModels: '添加所選模型',
|
||||
addSelectedModelsSuccess: '已添加 {{count}} 個模型',
|
||||
selectAll: '全選模型',
|
||||
alreadyAdded: '已添加',
|
||||
addLLMModel: '新增對話模型',
|
||||
addEmbeddingModel: '新增嵌入模型',
|
||||
provider: '供應商',
|
||||
|
||||
Reference in New Issue
Block a user