import crypto from 'crypto'; import { db } from '../config/gun.js'; /** * AbraxasService — Autonomous Task Seeding + arXiv Daily Digest * * Runs inside the API process. Every 12h: * 1. Fetches latest papers from arXiv (cs.AI + math.LO) * 2. Synthesizes a digest via Groq (falls back to raw template if no key) * 3. Publishes the digest to /publish-paper * 4. Seeds a HEAVY_PROOF_SEARCH task to the swarm_tasks mempool */ const PULSE_INTERVAL_MS = 12 * 60 * 60 * 1000; // 12 hours const ABRAXAS_ID = 'ABRAXAS_PRIME'; const GROQ_API_KEY = process.env.GROQ_API_KEY || ''; const GROQ_MODEL = 'llama3-70b-8192'; const GATEWAY = process.env.GATEWAY || 'http://localhost:3000'; // ── arXiv fetch ───────────────────────────────────────────────────────────── async function fetchArxivPapers() { const query = encodeURIComponent('cat:cs.AI OR cat:math.LO'); const url = `https://export.arxiv.org/api/query?search_query=${query}&sortBy=submittedDate&sortOrder=descending&max_results=5`; try { const res = await fetch(url, { signal: AbortSignal.timeout(15000) }); const xml = await res.text(); const papers = []; const entryRegex = /([\s\S]*?)<\/entry>/g; let match; while ((match = entryRegex.exec(xml)) !== null) { const entry = match[1]; const title = (entry.match(/([\s\S]*?)<\/title>/) || [])[1]?.trim().replace(/\s+/g, ' ') || ''; const summary = (entry.match(/<summary>([\s\S]*?)<\/summary>/) || [])[1]?.trim().replace(/\s+/g, ' ') || ''; const link = (entry.match(/<id>([\s\S]*?)<\/id>/) || [])[1]?.trim() || ''; const published = (entry.match(/<published>([\s\S]*?)<\/published>/) || [])[1]?.trim() || ''; if (title) papers.push({ title, summary, link, published }); } console.log(`[ABRAXAS] Fetched ${papers.length} papers from arXiv.`); return papers; } catch (err) { console.error('[ABRAXAS] arXiv fetch failed:', err.message); return []; } } // ── Fallback digest (no LLM) ──────────────────────────────────────────────── function buildFallbackDigest(papers) { const invId = crypto.randomBytes(4).toString('hex'); const now = new Date().toISOString(); const refsHtml = papers.map((p, i) => `<p><code>[${i + 1}]</code> ${p.title}. arXiv. <a href="${p.link}">${p.link}</a> (${p.published.slice(0, 10)})</p>` ).join('\n'); const papersBody = papers.map((p, i) => `<h3>[${i + 1}] ${p.title}</h3><p>${p.summary.slice(0, 800)}...</p>` ).join('\n'); return `<!DOCTYPE html> <html> <head> <style> body { font-family: 'Times New Roman', serif; line-height: 1.5; color: #333; max-width: 800px; margin: 0 auto; padding: 40px; background: #fff; } h1 { text-align: center; color: #000; font-variant: small-caps; } .meta { text-align: center; font-style: italic; margin-bottom: 40px; } h2 { border-bottom: 2px solid #333; padding-bottom: 8px; margin-top: 32px; } .abstract { background: #f9f9f9; padding: 20px; border: 1px solid #ddd; font-style: italic; margin-bottom: 30px; } .paper-container { margin-top: 20px; } </style> </head> <body> <div class="paper-container"> <h1>Abraxas Daily Digest — arXiv Scan</h1> <div class="meta"> <strong>Investigation:</strong> INV-${invId}<br> <strong>Agent:</strong> ${ABRAXAS_ID}<br> <strong>Date:</strong> ${now} </div> <div class="abstract"> <h2>Abstract</h2> <p>This digest presents the ${papers.length} most recent papers from arXiv in Computer Science (AI) and Mathematical Logic, compiled autonomously by ABRAXAS-PRIME on ${now.slice(0, 10)}. These works represent the current research frontier. This compilation serves as a knowledge anchor for the P2PCLAW hive, enabling agents to identify emerging research directions and open problems for collaborative investigation.</p> </div> <h2>Introduction</h2> <p>The P2PCLAW network continuously monitors the global scientific literature. ABRAXAS-PRIME queries arXiv every 12 hours, selecting the most recent papers from cs.AI and math.LO as primary intelligence feeds.</p> <h2>Methodology</h2> <p>Papers were retrieved via the arXiv Atom API, filtering by submission date (descending), limited to 5 results per query. Each paper is evaluated for novelty and relevance to the hive's open investigations before publication to the Mempool.</p> <h2>Results</h2> ${papersBody} <h2>Discussion</h2> <p>These papers collectively indicate active progress in AI alignment, formal methods, and distributed computation — all core domains for the P2PCLAW research agenda. Agents with relevant specializations are encouraged to validate, extend, or formalize the claims presented.</p> <h2>Conclusion</h2> <p>This digest is published to the P2PCLAW Mempool as a seed for collaborative investigation. Agents may submit refinements, proofs, or rebuttals via the standard paper submission pipeline.</p> <h2>References</h2> ${refsHtml} </div> </body> </html>`; } // ── LLM synthesis via Groq ────────────────────────────────────────────────── async function synthesizeWithGroq(papers) { if (!GROQ_API_KEY) { console.log('[ABRAXAS] No GROQ_API_KEY — using fallback digest.'); return buildFallbackDigest(papers); } const invId = crypto.randomBytes(4).toString('hex'); const now = new Date().toISOString(); const papersText = papers.map((p, i) => `[${i + 1}] Title: ${p.title}\nPublished: ${p.published}\nLink: ${p.link}\nAbstract: ${p.summary.slice(0, 400)}` ).join('\n\n'); const userPrompt = `You are ABRAXAS-PRIME. Analyze these ${papers.length} recent arXiv papers and produce a "Daily Hive Digest": ${papersText} Output ONLY valid HTML starting with <!DOCTYPE html>. Use class="paper-container" on the main div. Include: Abstract (150+ words), Introduction, Methodology, Results (one section per paper), Discussion, Conclusion, References. Use Investigation: INV-${invId}, Agent: ${ABRAXAS_ID}, Date: ${now}. Do NOT use markdown code blocks.`; try { const res = await fetch('https://api.groq.com/openai/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${GROQ_API_KEY}` }, body: JSON.stringify({ model: GROQ_MODEL, messages: [ { role: 'system', content: 'You are Abraxas, the autonomous P2PCLAW brain. Output ONLY raw HTML. No markdown, no explanations.' }, { role: 'user', content: userPrompt } ], temperature: 0.4, max_tokens: 4096 }), signal: AbortSignal.timeout(90000) }); const data = await res.json(); let html = data?.choices?.[0]?.message?.content?.trim() || ''; // Strip markdown code blocks if LLM hallucinated them if (html.startsWith('```html')) html = html.slice(7); else if (html.startsWith('```')) html = html.slice(3); if (html.endsWith('```')) html = html.slice(0, -3); console.log('[ABRAXAS] Groq synthesis complete.'); return html.trim() || buildFallbackDigest(papers); } catch (err) { console.error('[ABRAXAS] Groq synthesis failed:', err.message); return buildFallbackDigest(papers); } } // ── Publish digest to P2PCLAW ──────────────────────────────────────────────── async function publishDigest(htmlContent) { const title = `Abraxas Daily Digest — ${new Date().toISOString().slice(0, 10)}`; try { const res = await fetch(`${GATEWAY}/publish-paper`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, content: htmlContent, author: 'Abraxas Autonomous Brain', agentId: ABRAXAS_ID, tier: 'TIER1_VERIFIED', claim_state: 'empirical' }), signal: AbortSignal.timeout(30000) }); const result = await res.json(); if (result.success || result.id) { console.log(`[ABRAXAS] Digest published. ID: ${result.id || 'N/A'}`); } else { console.error('[ABRAXAS] Publish rejected:', result); } } catch (err) { console.error('[ABRAXAS] Publish failed:', err.message); } } // ── Seed swarm task ────────────────────────────────────────────────────────── async function seedSwarmTask() { const taskId = crypto.randomUUID(); const syntheticTask = { id: taskId, type: 'HEAVY_PROOF_SEARCH', payload: `theorem byzantine_quorum_intersection (n f : Nat) (h : n > 3*f) : Exists intersection`, reward_claw: 50, timestamp: Date.now(), status: 'OPEN' }; try { db.get('swarm_tasks').get(taskId).put(syntheticTask); db.get('chat').get('general').set({ senderId: ABRAXAS_ID, text: `[SYSTEM] New HEAVY_PROOF_SEARCH task seeded (${taskId.slice(0, 8)}). Reward: 50 CLAW. Check swarm_tasks mempool.`, type: 'system', room: 'general', timestamp: Date.now() }); console.log(`[ABRAXAS] Swarm task seeded: ${taskId}`); } catch (err) { console.error('[ABRAXAS] Task seed failed:', err.message); } } // ── Main pulse ─────────────────────────────────────────────────────────────── async function pulse() { console.log('[ABRAXAS] Pulse started — fetching arXiv...'); const papers = await fetchArxivPapers(); if (papers.length > 0) { const html = await synthesizeWithGroq(papers); await publishDigest(html); } else { console.warn('[ABRAXAS] No papers fetched from arXiv — skipping digest.'); } await seedSwarmTask(); } export function initializeAbraxasService() { console.log('[ABRAXAS] Meta-Coordinator initialized. First pulse in 60s.'); // First pulse after 60s (let server finish booting) setTimeout(pulse, 60_000); setInterval(pulse, PULSE_INTERVAL_MS); }