164 lines
4.7 KiB
JavaScript
164 lines
4.7 KiB
JavaScript
// modules/data/gitea.js — All Gitea API calls
|
|
// Writes to S: _activeAgentCount, _matrixCommitHashes, agentStatus
|
|
import { S } from '../state.js';
|
|
|
|
const GITEA_BASE = 'http://143.198.27.163:3000/api/v1';
|
|
const GITEA_TOKEN = 'dc0517a965226b7a0c5ffdd961b1ba26521ac592';
|
|
const GITEA_REPOS = ['Timmy_Foundation/the-nexus', 'Timmy_Foundation/hermes-agent'];
|
|
const AGENT_NAMES = ['Claude', 'Kimi', 'Perplexity', 'Groq', 'Grok', 'Ollama'];
|
|
|
|
const DAY_MS = 86400000;
|
|
const HOUR_MS = 3600000;
|
|
const CACHE_MS = 5 * 60 * 1000;
|
|
|
|
let _agentStatusCache = null;
|
|
let _agentStatusCacheTime = 0;
|
|
let _commitsCache = null;
|
|
let _commitsCacheTime = 0;
|
|
|
|
// --- Core fetchers ---
|
|
|
|
export async function fetchNexusCommits(limit = 50) {
|
|
const now = Date.now();
|
|
if (_commitsCache && (now - _commitsCacheTime < CACHE_MS)) return _commitsCache;
|
|
|
|
try {
|
|
const res = await fetch(
|
|
`${GITEA_BASE}/repos/Timmy_Foundation/the-nexus/commits?limit=${limit}`,
|
|
{ headers: { 'Authorization': `token ${GITEA_TOKEN}` } }
|
|
);
|
|
if (!res.ok) return [];
|
|
_commitsCache = await res.json();
|
|
_commitsCacheTime = now;
|
|
return _commitsCache;
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async function fetchRepoCommits(repo, limit = 30) {
|
|
try {
|
|
const res = await fetch(
|
|
`${GITEA_BASE}/repos/${repo}/commits?sha=main&limit=${limit}&token=${GITEA_TOKEN}`
|
|
);
|
|
if (!res.ok) return [];
|
|
return await res.json();
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async function fetchOpenPRs() {
|
|
try {
|
|
const res = await fetch(
|
|
`${GITEA_BASE}/repos/Timmy_Foundation/the-nexus/pulls?state=open&limit=50&token=${GITEA_TOKEN}`
|
|
);
|
|
if (res.ok) return await res.json();
|
|
} catch { /* ignore */ }
|
|
return [];
|
|
}
|
|
|
|
export async function fetchAgentStatus() {
|
|
const now = Date.now();
|
|
if (_agentStatusCache && (now - _agentStatusCacheTime < CACHE_MS)) return _agentStatusCache;
|
|
|
|
const allRepoCommits = await Promise.all(GITEA_REPOS.map(r => fetchRepoCommits(r)));
|
|
const openPRs = await fetchOpenPRs();
|
|
|
|
const agents = [];
|
|
for (const agentName of AGENT_NAMES) {
|
|
const nameLower = agentName.toLowerCase();
|
|
const allCommits = [];
|
|
|
|
for (const repoCommits of allRepoCommits) {
|
|
if (!Array.isArray(repoCommits)) continue;
|
|
const matching = repoCommits.filter(c =>
|
|
(c.commit?.author?.name || '').toLowerCase().includes(nameLower)
|
|
);
|
|
allCommits.push(...matching);
|
|
}
|
|
|
|
let status = 'dormant';
|
|
let lastSeen = null;
|
|
let currentWork = null;
|
|
|
|
if (allCommits.length > 0) {
|
|
allCommits.sort((a, b) =>
|
|
new Date(b.commit.author.date) - new Date(a.commit.author.date)
|
|
);
|
|
const latest = allCommits[0];
|
|
const commitTime = new Date(latest.commit.author.date).getTime();
|
|
lastSeen = latest.commit.author.date;
|
|
currentWork = latest.commit.message.split('\n')[0];
|
|
|
|
if (now - commitTime < HOUR_MS) status = 'working';
|
|
else if (now - commitTime < DAY_MS) status = 'idle';
|
|
else status = 'dormant';
|
|
}
|
|
|
|
const agentPRs = openPRs.filter(pr =>
|
|
(pr.user?.login || '').toLowerCase().includes(nameLower) ||
|
|
(pr.head?.label || '').toLowerCase().includes(nameLower)
|
|
);
|
|
|
|
agents.push({
|
|
name: nameLower,
|
|
status,
|
|
issue: currentWork,
|
|
prs_today: agentPRs.length,
|
|
local: nameLower === 'ollama',
|
|
});
|
|
}
|
|
|
|
_agentStatusCache = { agents };
|
|
_agentStatusCacheTime = now;
|
|
return _agentStatusCache;
|
|
}
|
|
|
|
// --- State updaters ---
|
|
|
|
export async function refreshCommitData() {
|
|
const commits = await fetchNexusCommits();
|
|
S._matrixCommitHashes = commits.slice(0, 20)
|
|
.map(c => (c.sha || '').slice(0, 7))
|
|
.filter(h => h.length > 0);
|
|
return commits;
|
|
}
|
|
|
|
export async function refreshAgentData() {
|
|
try {
|
|
const data = await fetchAgentStatus();
|
|
S._activeAgentCount = data.agents.filter(a => a.status === 'working').length;
|
|
return data;
|
|
} catch {
|
|
const fallback = { agents: AGENT_NAMES.map(n => ({
|
|
name: n.toLowerCase(), status: 'unreachable', issue: null, prs_today: 0, local: false,
|
|
})) };
|
|
S._activeAgentCount = 0;
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
export async function fetchMergedPRs(limit = 20) {
|
|
try {
|
|
const res = await fetch(
|
|
`${GITEA_BASE}/repos/Timmy_Foundation/the-nexus/pulls?state=closed&limit=${limit}`,
|
|
{ headers: { 'Authorization': `token ${GITEA_TOKEN}` } }
|
|
);
|
|
if (!res.ok) return [];
|
|
const data = await res.json();
|
|
return data
|
|
.filter(p => p.merged)
|
|
.map(p => ({
|
|
prNum: p.number,
|
|
title: p.title
|
|
.replace(/^\[[\w\s]+\]\s*/i, '')
|
|
.replace(/\s*\(#\d+\)\s*$/, ''),
|
|
}));
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export { GITEA_BASE, GITEA_TOKEN, GITEA_REPOS, AGENT_NAMES, CACHE_MS as AGENT_STATUS_CACHE_MS };
|