發佈 0.1.8:支援傳圖/傳檔給使用者,新增連網開關
摘要: 1. 交件匣機制:每輪 prompt 附系統規則,Codex 把要給使用者的檔案放進 工作目錄的 .tgcodex-outbox/,回覆後 bot 自動傳到 Telegram(圖片走 sendPhoto、其餘或超過 10MB 走 sendDocument)並清空,一輪上限 10 個檔案。 2. bot 設定新增「允許 Codex 連網」開關(-c sandbox_workspace_write.network_access), 開啟後可用 codex 的 imagegen 技能生圖,已實測產出 PNG 進交件匣。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+36
-1
@@ -55,6 +55,13 @@ function buildFooter(config, usage, modelMeta, codexDefaults) {
|
||||
return `\n\n${parts.join(' | ')}`;
|
||||
}
|
||||
|
||||
// Codex 要傳檔案給使用者的交件匣(在工作目錄底下,沙盒內可寫)
|
||||
const OUTBOX_DIRNAME = '.tgcodex-outbox';
|
||||
const OUTBOX_RULE =
|
||||
`【系統規則】若要把圖片或檔案傳給使用者,請將檔案寫入工作目錄下的 ${OUTBOX_DIRNAME}/ 資料夾,` +
|
||||
'bot 會在回覆後自動傳送到 Telegram 並清空該資料夾。';
|
||||
const MAX_OUTBOX_FILES = 10;
|
||||
|
||||
const NEW_COMMANDS = ['/new', '!clear', '!reset', '!new', '!清除', '!重置', '!新會話'];
|
||||
const STATUS_COMMANDS = ['/status', '!status', '!狀態'];
|
||||
const HELP_COMMANDS = ['/start', '/help', '!help', '!幫助'];
|
||||
@@ -93,6 +100,33 @@ function startBot(config) {
|
||||
return commands.includes(head.toLowerCase());
|
||||
}
|
||||
|
||||
// 把 codex 放進交件匣的檔案傳到 Telegram,傳完清掉
|
||||
async function flushOutbox(chatId, replyTo) {
|
||||
const dir = path.join(config.workDir, OUTBOX_DIRNAME);
|
||||
let files = [];
|
||||
try {
|
||||
files = fs.readdirSync(dir)
|
||||
.map((f) => path.join(dir, f))
|
||||
.filter((p) => { try { return fs.statSync(p).isFile(); } catch { return false; } })
|
||||
.sort();
|
||||
} catch {
|
||||
return; // 沒有交件匣就沒事
|
||||
}
|
||||
const skipped = files.length - MAX_OUTBOX_FILES;
|
||||
for (const file of files.slice(0, MAX_OUTBOX_FILES)) {
|
||||
try {
|
||||
await t.sendFile(chatId, file, { replyTo });
|
||||
fs.unlinkSync(file);
|
||||
} catch (err) {
|
||||
console.error('傳送交件匣檔案失敗:', file, err.message);
|
||||
await t.sendMessage(chatId, `⚠️ 檔案傳送失敗:${path.basename(file)}(${err.message})`).catch(() => {});
|
||||
}
|
||||
}
|
||||
if (skipped > 0) {
|
||||
await t.sendMessage(chatId, `⚠️ 交件匣一次最多傳 ${MAX_OUTBOX_FILES} 個檔案,還有 ${skipped} 個留在 ${OUTBOX_DIRNAME}/`).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
function cleanTmp() {
|
||||
const ttl = 24 * 60 * 60 * 1000;
|
||||
try {
|
||||
@@ -123,7 +157,7 @@ function startBot(config) {
|
||||
const from = message.from || {};
|
||||
const name = [from.first_name, from.last_name].filter(Boolean).join(' ') || '未知使用者';
|
||||
const sender = from.username ? `${name}(@${from.username})` : name;
|
||||
const parts = [];
|
||||
const parts = [OUTBOX_RULE];
|
||||
const replied = message.reply_to_message;
|
||||
if (replied && replied.from?.id !== botId && (replied.text || replied.caption)) {
|
||||
parts.push(`【被回覆的訊息】\n${replied.text || replied.caption}`);
|
||||
@@ -256,6 +290,7 @@ function startBot(config) {
|
||||
const footer = buildFooter(config, result.usage, modelMeta, codexDefaults);
|
||||
const html = t.mdToTgHtml(sessionResetNote + (result.text || '(Codex 沒有回覆文字)') + footer);
|
||||
await t.editOrSplit(chatId, statusMsg.message_id, html, { html: true });
|
||||
await flushOutbox(chatId, message.message_id);
|
||||
await t.react(chatId, message.message_id, '👍');
|
||||
} catch (error) {
|
||||
console.error('處理訊息失敗:', error);
|
||||
|
||||
Reference in New Issue
Block a user