Files
theia-code-os/sync-server.js

73 lines
2.6 KiB
JavaScript

#!/usr/bin/env node
/**
* sync-server.js — runs inside the Theia container on port 3001
* Called by vibn-agent-runner after an agent session auto-commits to Gitea.
* Triggers git pull (or clone) so "Open in Theia" immediately shows new files.
*
* POST /sync { repo: "mark/sportsy" }
* GET /health
*/
const http = require('http');
const { execSync } = require('child_process');
const WORKSPACE = '/home/project';
const GITEA_BASE = process.env.GITEA_API_URL || 'https://git.vibnai.com';
const GITEA_TOKEN = process.env.GITEA_TOKEN || process.env.GITEA_API_TOKEN || '';
const PORT = 3001;
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json');
if (req.url === '/health' && req.method === 'GET') {
res.writeHead(200).end(JSON.stringify({ ok: true, workspace: WORKSPACE }));
return;
}
if (req.url === '/sync' && req.method === 'POST') {
let body = '';
req.on('data', d => { body += d; });
req.on('end', () => {
try {
const { repo } = JSON.parse(body || '{}');
if (!repo || !/^[\w.-]+\/[\w.-]+$/.test(repo)) {
res.writeHead(400).end(JSON.stringify({ error: 'invalid repo' }));
return;
}
const repoName = repo.split('/').pop();
const cloneDir = `${WORKSPACE}/${repoName}`;
const authedUrl = GITEA_BASE.replace('https://', `https://vibn:${GITEA_TOKEN}@`) + `/${repo}.git`;
let action;
try {
if (require('fs').existsSync(`${cloneDir}/.git`)) {
execSync(`git -C "${cloneDir}" fetch --depth=50 origin main 2>&1`, { timeout: 30000 });
execSync(`git -C "${cloneDir}" reset --hard origin/main 2>&1`, { timeout: 10000 });
action = 'pulled';
} else {
execSync(`git clone --depth=50 "${authedUrl}" "${cloneDir}" 2>&1`, { timeout: 60000 });
action = 'cloned';
}
} catch (gitErr) {
console.error('[sync-server] git error:', gitErr.message);
res.writeHead(500).end(JSON.stringify({ ok: false, error: gitErr.message }));
return;
}
console.log(`[sync-server] ${action} ${repo} -> ${cloneDir}`);
res.writeHead(200).end(JSON.stringify({ ok: true, action, repo, path: cloneDir }));
} catch (err) {
console.error('[sync-server] error:', err.message);
res.writeHead(500).end(JSON.stringify({ ok: false, error: err.message }));
}
});
return;
}
res.writeHead(404).end(JSON.stringify({ error: 'not found' }));
});
server.listen(PORT, '0.0.0.0', () => {
console.log(`[sync-server] Listening on :${PORT} - workspace: ${WORKSPACE}`);
});