feat(webui): support document attachments with ingress safeguards (#4771)

* feat: support document attachments in webui

* fix(webui): normalize document attachment MIME

* refactor(webui): move attachment policy out of channel

* fix(webui): reject oversized attachments before send

* fix(webui): align Portuguese attachment errors

* refactor(webui): separate ingress and transport limits

* fix(webui): reject malformed attachment payloads
This commit is contained in:
chengyongru
2026-07-14 14:47:42 +08:00
committed by GitHub
parent b2759e8a6b
commit b7048cf76a
36 changed files with 1398 additions and 332 deletions
+7 -2
View File
@@ -909,7 +909,7 @@
"edit": "Edit guidance",
"drag": "Drag to reorder"
},
"attachImage": "Attach image",
"attachImage": "Attach files",
"imageMode": {
"label": "Image Generation",
"toggle": "Toggle image generation mode",
@@ -1034,12 +1034,17 @@
"encoding": "Encoding…",
"remove": "Remove attachment",
"normalizedSizeHint": "{{orig}} → {{current}} (auto)",
"textTooLarge": "Message text is too large (max {{max}})",
"imageRejected": {
"unsupported_type": "Unsupported file type",
"empty_file": "Empty files cannot be attached",
"too_many_attachments": "Max {{max}} attachments per message",
"too_many_images": "Max {{max}} images per message",
"magic_mismatch": "File doesn't look like a real image",
"decode_failed": "Couldn't decode this image",
"too_large": "Image is too large — try a smaller one",
"too_large": "File is too large — try a smaller one",
"total_too_large": "Attachments are too large together — remove some or use smaller files",
"transport_too_large": "This attachment would exceed the gateway transport limit",
"io": "Couldn't read this file"
},
"workspace": {
+7 -2
View File
@@ -896,7 +896,7 @@
"edit": "Editar guía",
"drag": "Arrastrar para reordenar"
},
"attachImage": "Adjuntar imagen",
"attachImage": "Adjuntar archivos",
"imageMode": {
"label": "Generar imagen",
"toggle": "Activar o desactivar modo de generación de imágenes",
@@ -1011,12 +1011,17 @@
"encoding": "Procesando…",
"remove": "Quitar adjunto",
"normalizedSizeHint": "{{orig}} → {{current}} (auto)",
"textTooLarge": "El texto del mensaje es demasiado grande (máximo {{max}})",
"imageRejected": {
"unsupported_type": "Tipo de archivo no compatible",
"empty_file": "No se pueden adjuntar archivos vacíos",
"too_many_attachments": "Máximo {{max}} adjuntos por mensaje",
"too_many_images": "Máximo {{max}} imágenes por mensaje",
"magic_mismatch": "El archivo no parece una imagen real",
"decode_failed": "No se pudo decodificar esta imagen",
"too_large": "Imagen demasiado grande — prueba una más pequeña",
"too_large": "Archivo demasiado grande — prueba uno más pequeño",
"total_too_large": "Los archivos adjuntos son demasiado grandes en conjunto; elimina algunos o usa archivos más pequeños",
"transport_too_large": "Este archivo adjunto superaría el límite de transporte de la puerta de enlace",
"io": "No se pudo leer este archivo"
},
"mentions": {
+7 -2
View File
@@ -895,7 +895,7 @@
"edit": "Modifier le guidage",
"drag": "Faire glisser pour réordonner"
},
"attachImage": "Joindre une image",
"attachImage": "Joindre des fichiers",
"imageMode": {
"label": "Génération dimage",
"toggle": "Activer ou désactiver le mode génération dimage",
@@ -1010,12 +1010,17 @@
"encoding": "Traitement…",
"remove": "Retirer la pièce jointe",
"normalizedSizeHint": "{{orig}} → {{current}} (auto)",
"textTooLarge": "Le texte du message est trop volumineux (maximum {{max}})",
"imageRejected": {
"unsupported_type": "Type de fichier non pris en charge",
"empty_file": "Impossible de joindre des fichiers vides",
"too_many_attachments": "Maximum {{max}} pièces jointes par message",
"too_many_images": "Maximum {{max}} images par message",
"magic_mismatch": "Ce fichier n'est pas une image",
"decode_failed": "Impossible de décoder cette image",
"too_large": "Image trop grande — essayez-en une plus petite",
"too_large": "Fichier trop volumineux — essayez-en un plus petit",
"total_too_large": "Les pièces jointes sont trop volumineuses ensemble — supprimez-en ou utilisez des fichiers plus petits",
"transport_too_large": "Cette pièce jointe dépasserait la limite de transport de la passerelle",
"io": "Impossible de lire ce fichier"
},
"mentions": {
+7 -2
View File
@@ -895,7 +895,7 @@
"edit": "Edit panduan",
"drag": "Seret untuk mengurutkan"
},
"attachImage": "Lampirkan gambar",
"attachImage": "Lampirkan file",
"imageMode": {
"label": "Buat gambar",
"toggle": "Alihkan mode pembuatan gambar",
@@ -1010,12 +1010,17 @@
"encoding": "Memproses…",
"remove": "Hapus lampiran",
"normalizedSizeHint": "{{orig}} → {{current}} (auto)",
"textTooLarge": "Teks pesan terlalu besar (maksimum {{max}})",
"imageRejected": {
"unsupported_type": "Tipe file tidak didukung",
"empty_file": "File kosong tidak dapat dilampirkan",
"too_many_attachments": "Maksimal {{max}} lampiran per pesan",
"too_many_images": "Maksimal {{max}} gambar per pesan",
"magic_mismatch": "File ini tampaknya bukan gambar asli",
"decode_failed": "Tidak dapat mendekode gambar ini",
"too_large": "Gambar terlalu besar — coba yang lebih kecil",
"too_large": "File terlalu besar — coba yang lebih kecil",
"total_too_large": "Total lampiran terlalu besar — hapus beberapa atau gunakan file yang lebih kecil",
"transport_too_large": "Lampiran ini akan melebihi batas transport gateway",
"io": "Tidak dapat membaca file ini"
},
"mentions": {
+7 -2
View File
@@ -895,7 +895,7 @@
"edit": "ガイドを編集",
"drag": "ドラッグして並べ替え"
},
"attachImage": "画像を添付",
"attachImage": "ファイルを添付",
"imageMode": {
"label": "画像生成",
"toggle": "画像生成モードを切り替え",
@@ -1010,12 +1010,17 @@
"encoding": "処理中…",
"remove": "添付を削除",
"normalizedSizeHint": "{{orig}} → {{current}}(自動圧縮)",
"textTooLarge": "メッセージ本文が大きすぎます(最大 {{max}})",
"imageRejected": {
"unsupported_type": "対応していないファイル形式です",
"empty_file": "空のファイルは添付できません",
"too_many_attachments": "1 メッセージにつき最大 {{max}} 件までです",
"too_many_images": "1 メッセージにつき最大 {{max}} 枚です",
"magic_mismatch": "画像ファイルではないようです",
"decode_failed": "この画像をデコードできません",
"too_large": "画像が大きすぎます。小さいものを選んでください",
"too_large": "ファイルが大きすぎます。小さいものを選んでください",
"total_too_large": "添付ファイルの合計サイズが大きすぎます。いくつか削除するか、より小さいファイルを使用してください",
"transport_too_large": "この添付ファイルはゲートウェイの転送上限を超えます",
"io": "このファイルを読み込めません"
},
"mentions": {
+7 -2
View File
@@ -895,7 +895,7 @@
"edit": "안내 수정",
"drag": "드래그하여 순서 변경"
},
"attachImage": "이미지 첨부",
"attachImage": "파일 첨부",
"imageMode": {
"label": "이미지 생성",
"toggle": "이미지 생성 모드 전환",
@@ -1010,12 +1010,17 @@
"encoding": "처리 중…",
"remove": "첨부 제거",
"normalizedSizeHint": "{{orig}} → {{current}} (자동 압축)",
"textTooLarge": "메시지 텍스트가 너무 큽니다(최대 {{max}})",
"imageRejected": {
"unsupported_type": "지원하지 않는 파일 형식입니다",
"empty_file": "빈 파일은 첨부할 수 없습니다",
"too_many_attachments": "메시지당 최대 {{max}}개까지 가능합니다",
"too_many_images": "메시지당 최대 {{max}}장까지 가능합니다",
"magic_mismatch": "이미지 파일이 아닌 것 같습니다",
"decode_failed": "이 이미지를 디코딩할 수 없습니다",
"too_large": "이미지가 너무 큽니다. 더 작은 걸로 시도해 주세요",
"too_large": "파일이 너무 큽니다. 더 작은 파일을 선택해 주세요",
"total_too_large": "첨부 파일의 전체 크기가 너무 큽니다. 일부를 제거하거나 더 작은 파일을 사용해 주세요",
"transport_too_large": "이 첨부 파일은 게이트웨이 전송 한도를 초과합니다",
"io": "이 파일을 읽을 수 없습니다"
},
"mentions": {
+5
View File
@@ -1034,12 +1034,17 @@
"encoding": "Codificando…",
"remove": "Remover anexo",
"normalizedSizeHint": "{{orig}} → {{current}} (auto)",
"textTooLarge": "O texto da mensagem é grande demais (máximo de {{max}})",
"imageRejected": {
"unsupported_type": "Tipo de arquivo não compatível",
"empty_file": "Arquivos vazios não podem ser anexados",
"too_many_attachments": "Máx. de {{max}} anexos por mensagem",
"too_many_images": "Máx. de {{max}} imagens por mensagem",
"magic_mismatch": "O arquivo não parece uma imagem real",
"decode_failed": "Não foi possível decodificar esta imagem",
"too_large": "A imagem é grande demais — tente uma menor",
"total_too_large": "Os anexos são grandes demais em conjunto — remova alguns ou use arquivos menores",
"transport_too_large": "Este anexo excederia o limite de transporte do gateway",
"io": "Não foi possível ler este arquivo"
},
"workspace": {
+7 -2
View File
@@ -895,7 +895,7 @@
"edit": "Sửa hướng dẫn",
"drag": "Kéo để sắp xếp"
},
"attachImage": "Đính kèm ảnh",
"attachImage": "Đính kèm tệp",
"imageMode": {
"label": "Tạo ảnh",
"toggle": "Bật/tắt chế độ tạo ảnh",
@@ -1010,12 +1010,17 @@
"encoding": "Đang xử lý…",
"remove": "Xóa tệp đính kèm",
"normalizedSizeHint": "{{orig}} → {{current}} (tự động)",
"textTooLarge": "Nội dung tin nhắn quá lớn (tối đa {{max}})",
"imageRejected": {
"unsupported_type": "Loại tệp không được hỗ trợ",
"empty_file": "Không thể đính kèm tệp trống",
"too_many_attachments": "Tối đa {{max}} tệp đính kèm mỗi tin nhắn",
"too_many_images": "Tối đa {{max}} ảnh mỗi tin nhắn",
"magic_mismatch": "Tệp này không phải là một ảnh thực",
"decode_failed": "Không thể giải mã ảnh này",
"too_large": "Ảnh quá lớn — hãy thử ảnh nhỏ hơn",
"too_large": "Tệp quá lớn — hãy thử tệp nhỏ hơn",
"total_too_large": "Tổng dung lượng tệp đính kèm quá lớn — hãy xóa bớt hoặc dùng tệp nhỏ hơn",
"transport_too_large": "Tệp đính kèm này sẽ vượt quá giới hạn truyền tải của gateway",
"io": "Không thể đọc tệp này"
},
"mentions": {
+7 -2
View File
@@ -908,7 +908,7 @@
"edit": "编辑引导",
"drag": "拖动排序"
},
"attachImage": "添加图片",
"attachImage": "添加文件",
"imageMode": {
"label": "图片生成",
"toggle": "切换图片生成模式",
@@ -1033,12 +1033,17 @@
"encoding": "处理中…",
"remove": "移除附件",
"normalizedSizeHint": "{{orig}} → {{current}}(已自动压缩)",
"textTooLarge": "消息文本过大(最大 {{max}}",
"imageRejected": {
"unsupported_type": "不支持的文件类型",
"empty_file": "不能附加空文件",
"too_many_attachments": "每条消息最多 {{max}} 个附件",
"too_many_images": "每条消息最多 {{max}} 张图片",
"magic_mismatch": "文件看起来不像真实的图片",
"decode_failed": "无法解码这张图片",
"too_large": "图片太大,请换一小一点的",
"too_large": "文件太大,请换一小一点的",
"total_too_large": "附件总大小过大,请移除部分文件或使用更小的文件",
"transport_too_large": "该附件会超过网关的传输上限",
"io": "无法读取该文件"
},
"goalStateCloseAria": "关闭目标",
+7 -2
View File
@@ -895,7 +895,7 @@
"edit": "編輯引導",
"drag": "拖曳排序"
},
"attachImage": "附加圖片",
"attachImage": "附加檔案",
"imageMode": {
"label": "圖片生成",
"toggle": "切換圖片生成模式",
@@ -1010,12 +1010,17 @@
"encoding": "處理中…",
"remove": "移除附件",
"normalizedSizeHint": "{{orig}} → {{current}}(已自動壓縮)",
"textTooLarge": "訊息文字過大(最大 {{max}}",
"imageRejected": {
"unsupported_type": "不支援的檔案類型",
"empty_file": "無法附加空白檔案",
"too_many_attachments": "每則訊息最多 {{max}} 個附件",
"too_many_images": "每則訊息最多 {{max}} 張圖片",
"magic_mismatch": "檔案看起來不像真正的圖片",
"decode_failed": "無法解碼這張圖片",
"too_large": "圖片太大,請換一小一點的",
"too_large": "檔案太大,請換一小一點的",
"total_too_large": "附件總大小過大,請移除部分檔案或使用更小的檔案",
"transport_too_large": "此附件會超過閘道的傳輸上限",
"io": "無法讀取這個檔案"
},
"mentions": {