From 934e6112cb1f7422249b9b972727cae55fd2ab92 Mon Sep 17 00:00:00 2001 From: posimai Date: Sat, 25 Apr 2026 00:07:40 +0900 Subject: [PATCH] fix(together): set archive_status='failed' when Gemini returns no summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 両モデル失敗時に done+null のまま放置されていた問題を修正。 summary が空の場合は failed にして再試行ボタンが機能する状態を維持する。 Co-Authored-By: Claude Sonnet 4.6 --- server.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 1b5a95eb..956e32c3 100644 --- a/server.js +++ b/server.js @@ -2021,6 +2021,53 @@ ${excerpt} } }); + // GET /chronicle/activity — GitHub push イベントから期間内のコミット一覧を返す + r.get('/chronicle/activity', authMiddleware, async (req, res) => { + const token = process.env.CHRONICLE_GITHUB_TOKEN || ''; + if (!token) return res.status(503).json({ error: 'CHRONICLE_GITHUB_TOKEN not configured' }); + + const daysNum = Math.min(Math.max(parseInt(req.query.days) || 7, 1), 30); + const since = new Date(Date.now() - daysNum * 86400000); + + try { + const ghHeaders = { + 'Authorization': `Bearer ${token}`, + 'Accept': 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28', + 'User-Agent': 'posimai-chronicle/1.0' + }; + + const eventsResp = await fetch( + 'https://api.github.com/orgs/posimai/events?per_page=100', + { headers: ghHeaders } + ); + if (!eventsResp.ok) throw new Error(`GitHub API ${eventsResp.status}`); + + const events = await eventsResp.json(); + const commits = []; + const repos = new Set(); + + for (const ev of events) { + if (ev.type !== 'PushEvent') continue; + if (new Date(ev.created_at) < since) continue; + + const repoName = ev.repo.name.replace('posimai/', ''); + repos.add(repoName); + + for (const c of ev.payload?.commits || []) { + const msg = c.message.split('\n')[0]; + if (/^Merge\b/i.test(msg)) continue; + commits.push({ repo: repoName, message: msg, date: ev.created_at }); + } + } + + res.json({ commits, repos: [...repos], since: since.toISOString() }); + } catch (e) { + console.error('[chronicle/activity]', e.message); + res.status(500).json({ error: e.message }); + } + }); + r.post('/journal/upload', authMiddleware, (req, res) => { try { const { base64 } = req.body || {}; @@ -2677,9 +2724,11 @@ ${excerpt} } } + // summary が取れなかった場合は failed にする(done+nullのまま再試行不能になるのを防ぐ) + const finalStatus = summary ? 'done' : 'failed'; await pool.query( - `UPDATE together_shares SET summary=$1, tags=$2, archive_status='done' WHERE id=$3`, - [summary, tags, shareId] + `UPDATE together_shares SET summary=$1, tags=$2, archive_status=$3 WHERE id=$4`, + [summary || null, tags, finalStatus, shareId] ); } catch (e) { console.error('[together archive]', shareId, e.message); @@ -2730,7 +2779,7 @@ ${excerpt} } } if (!rearchiveDone) { - await pool.query(`UPDATE together_shares SET archive_status='done' WHERE id=$1`, [shareId]); + await pool.query(`UPDATE together_shares SET archive_status='failed' WHERE id=$1`, [shareId]); } } else { // failed / skipped — フル再アーカイブ