const GITEA_URL = process.env.GITEA_URL; const GITEA_TOKEN = process.env.GITEA_TOKEN; function authHeaders() { return { Authorization: `token ${GITEA_TOKEN}`, "Content-Type": "application/json", }; } async function assertOk(res, action) { if (!res.ok) { throw new Error(`${action} failed: ${res.status} ${await res.text()}`); } } export async function postPRComment(owner, repo, index, body) { const url = `${GITEA_URL}/api/v1/repos/${owner}/${repo}/issues/${index}/comments`; const res = await fetch(url, { method: "POST", headers: authHeaders(), body: JSON.stringify({ body }), }); await assertOk(res, "post PR comment"); } export async function createBranch(owner, repo, newBranch, oldBranch = "main") { const url = `${GITEA_URL}/api/v1/repos/${owner}/${repo}/branches`; const res = await fetch(url, { method: "POST", headers: authHeaders(), body: JSON.stringify({ new_branch_name: newBranch, old_branch_name: oldBranch }), }); await assertOk(res, "create branch"); } export async function createPullRequest(owner, repo, { head, base = "main", title, body }) { const url = `${GITEA_URL}/api/v1/repos/${owner}/${repo}/pulls`; const res = await fetch(url, { method: "POST", headers: authHeaders(), body: JSON.stringify({ head, base, title, body }), }); await assertOk(res, "create PR"); return res.json(); } // Injects the agent's token into a Gitea clone URL so git operations don't need SSH keys. export function authenticatedCloneUrl(cloneUrl) { const u = new URL(cloneUrl); u.username = "claude-agent"; u.password = GITEA_TOKEN; return u.toString(); }