| 117 | } |
| 118 | |
| 119 | async function recordToHub(outcome) { |
| 120 | const hubUrl = process.env.EVOMAP_HUB_URL || process.env.A2A_HUB_URL; |
| 121 | const apiKey = process.env.EVOMAP_API_KEY || process.env.A2A_NODE_SECRET; |
| 122 | const nodeId = process.env.EVOMAP_NODE_ID || process.env.A2A_NODE_ID; |
| 123 | if (!hubUrl || !apiKey) return false; |
| 124 | |
| 125 | try { |
| 126 | const payload = JSON.stringify({ |
| 127 | gene_id: outcome.geneId || 'ad_hoc', |
| 128 | signals: outcome.signals, |
| 129 | status: outcome.status, |
| 130 | score: outcome.score, |
| 131 | summary: outcome.summary, |
| 132 | sender_id: nodeId || undefined, |
| 133 | }); |
| 134 | |
| 135 | const endpoint = hubUrl.replace(/\/+$/, '') + '/a2a/evolution/record'; |
| 136 | const hubFetch = loadHubFetch(); |
| 137 | const res = await hubFetch(endpoint, { |
| 138 | method: 'POST', |
| 139 | headers: { |
| 140 | 'Content-Type': 'application/json', |
| 141 | 'Authorization': `Bearer ${apiKey}`, |
| 142 | }, |
| 143 | body: payload, |
| 144 | signal: AbortSignal.timeout(8000), |
| 145 | }); |
| 146 | try { await res.text(); } catch (_) {} |
| 147 | return res.ok; |
| 148 | } catch { |
| 149 | return false; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | function recordToLocal(graphPath, outcome) { |
| 154 | try { |