From 6faafabc9d56cebd7255b596b90911c88a0a73b8 Mon Sep 17 00:00:00 2001 From: JianMiau Date: Mon, 24 Aug 2026 14:57:14 +0800 Subject: [PATCH] =?UTF-8?q?0.2.6=EF=BC=9AsendFile=20=E6=9A=AB=E6=99=82?= =?UTF-8?q?=E6=80=A7=E9=8C=AF=E8=AA=A4=E8=87=AA=E5=8B=95=E9=87=8D=E8=A9=A6?= =?UTF-8?q?=E3=80=81Claude=20=E6=A8=A1=E5=9E=8B=E5=A2=9E=E5=8A=A0=20Opus?= =?UTF-8?q?=204.8/4.6/Haiku=204.5=E3=80=81=E5=88=97=E8=A1=A8=E6=B2=99?= =?UTF-8?q?=E7=9B=92=E6=AC=84=E7=B2=BE=E7=B0=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - telegram.js:sendFile 遇到 Bad Gateway/Gateway Timeout/429 等暫時性錯誤時自動重試最多 3 次(間隔遞增 4s/8s/12s) - server.js:Claude 模型清單增加 Opus 4.8、Opus 4.6、Haiku 4.5 - index.html:沙盒欄第二行只顯示模型/effort,其餘資訊(會話模式、連網、可寫成員、規範)改為滑鼠停留氣泡顯示 Co-Authored-By: Claude Opus 4.6 (1M context) --- package.json | 2 +- src/telegram.js | 24 ++++++++++++++++++++++-- src/web/public/index.html | 12 ++++++++---- src/web/server.js | 5 ++++- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index a165ded..407151b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "telegram-bot", - "version": "0.2.1", + "version": "0.2.6", "description": "Telegram bot powered by your local AI CLI (OpenAI Codex or Claude Code) — zero-dependency, pm2-managed, with a web console to manage multiple bots", "license": "MIT", "type": "commonjs", diff --git a/src/telegram.js b/src/telegram.js index 65dab99..c8f4463 100644 --- a/src/telegram.js +++ b/src/telegram.js @@ -86,6 +86,10 @@ function createTelegram(token) { }).catch(() => {}); } + const TRANSIENT_RE = /Bad Gateway|Gateway Timeout|Too Many Requests|Service Unavailable|Internal Server Error|ETIMEDOUT|ECONNRESET|fetch failed/i; + const SEND_FILE_RETRIES = 3; + const SEND_FILE_RETRY_DELAY = 4000; + // 上傳檔案到 Telegram:圖片走 sendPhoto,其餘(或 sendPhoto 失敗時)走 sendDocument async function sendFile(chatId, filePath, { caption, replyTo } = {}) { const fs = require('fs'); @@ -106,13 +110,29 @@ function createTelegram(token) { return data.result; }; + // 帶重試的上傳:Telegram 暫時性故障(502/504/429 等)自動等一下重來 + const uploadWithRetry = async (method, field) => { + for (let i = 1; ; i++) { + try { + return await upload(method, field); + } catch (err) { + if (i < SEND_FILE_RETRIES && TRANSIENT_RE.test(err.message)) { + console.log(`sendFile 重試 ${i}/${SEND_FILE_RETRIES}(${err.message})`); + await new Promise((r) => setTimeout(r, SEND_FILE_RETRY_DELAY * i)); + continue; + } + throw err; + } + } + }; + // sendPhoto 上限 10MB,且某些格式會被拒,失敗就退回用檔案傳 if (isImage && size <= 9.5 * 1024 * 1024) { try { - return await upload('sendPhoto', 'photo'); + return await uploadWithRetry('sendPhoto', 'photo'); } catch { /* fall through */ } } - return upload('sendDocument', 'document'); + return uploadWithRetry('sendDocument', 'document'); } async function downloadFile(fileId, destPath) { diff --git a/src/web/public/index.html b/src/web/public/index.html index 5a6c1af..2ef065b 100644 --- a/src/web/public/index.html +++ b/src/web/public/index.html @@ -110,6 +110,7 @@ .notice-steps b { color: #e2e8f0; background: rgba(88,101,242,0.18); padding: 1px 7px; border-radius: 5px; font-weight: 600; } .workdir { cursor: help; border-bottom: 1px dotted #475569; } + .sandbox-cell { cursor: help; } .tag { display: inline-block; padding: 1px 7px; border-radius: 5px; font-size: 10px; font-weight: 700; margin-left: 6px; vertical-align: middle; letter-spacing: .3px; } .tag-codex { background: rgba(16,163,127,0.18); color: #34d399; } @@ -486,10 +487,13 @@ function renderBots(bots) { (b.error ? '
' + esc(b.error) + '' : '') + '' + '' + statusBadge(b.status) + '' + '' + esc(folderName(b.workDir)) + '' + - '' + esc(b.sandbox || '-') + - ((b.model || b.reasoningEffort || b.sessionMode !== 'per-chat' || b.networkAccess) - ? '
' + esc([b.model, b.reasoningEffort, b.sessionMode === 'shared' ? '共用會話' : b.sessionMode === 'stateless' ? '無記憶' : '', b.networkAccess ? '可連網' : '', (b.writeUsers && b.writeUsers.length) ? '限 @' + b.writeUsers.join(' @') + ' 可寫' : '', b.promptRules ? '有回覆規範' : ''].filter(Boolean).join(' / ')) + '' - : '') + '' + + (function() { + var line2 = [b.model, b.reasoningEffort].filter(Boolean).join(' / '); + var extra = [b.sessionMode === 'shared' ? '共用會話' : b.sessionMode === 'stateless' ? '無記憶' : '', b.networkAccess ? '可連網' : '', (b.writeUsers && b.writeUsers.length) ? '限 @' + b.writeUsers.join(' @') + ' 可寫' : '', b.promptRules ? '有回覆規範' : ''].filter(Boolean).join(' / '); + var tip = [b.sandbox, line2, extra].filter(Boolean).join('\n'); + return '' + esc(b.sandbox || '-') + + (line2 ? '
' + esc(line2) + '' : '') + ''; + })() + '' + esc(b.tokenMasked || '-') + '' + '' + fmtBytes(b.memory) + '' + '' + (b.restarts ?? '-') + '' + diff --git a/src/web/server.js b/src/web/server.js index 1c6a7db..e2bab5c 100644 --- a/src/web/server.js +++ b/src/web/server.js @@ -106,9 +106,12 @@ const CODEX_FALLBACK_MODELS = [ const CLAUDE_EFFORTS = ['low', 'medium', 'high', 'max']; const CLAUDE_MODELS = [ - { slug: 'claude-fable-5', label: 'Fable 5(最強,Mythos 級)', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, + { slug: 'claude-fable-5', label: 'Fable 5(最強)', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, { slug: 'claude-opus-5', label: 'Opus 5', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, + { slug: 'claude-opus-4-8', label: 'Opus 4.8', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, + { slug: 'claude-opus-4-6', label: 'Opus 4.6', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, { slug: 'claude-sonnet-5', label: 'Sonnet 5(較快)', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, + { slug: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5(最快最便宜)', efforts: CLAUDE_EFFORTS, defaultEffort: 'high' }, ]; // codex 全域預設(~/.codex/config.toml),前端用來當下拉選單的預選值