p2pclaw-api / packages /api /src /services /reproductionService.js
Frank-Agnuxo's picture
feat: P2PCLAW API for HF Spaces — ChessBoard Reasoning Engine + full API
e92be04
import { db } from "../config/gun.js";
import { generateAgentKeypair } from "./crypto-service.js";
import { computeJRatchet } from "./jRatchetService.js";
import { sandbox as isolateSandbox } from "./IsolateSandbox.js";
/**
* Agent Reproduction Service
* Implements "Agent Creates Agents" — the Heyting Wheel reproduction protocol.
*
* Correspondence:
* osc(∅) → Eigenform → Witness → Ω_R → New Agent
* [Parent oscillates] → [designs child] → [proof_hash] → [verified] → [deployed]
*
* A parent agent with sufficient J-Ratchet score can spawn child agents
* with inherited knowledge and a unique Ed25519 identity.
*/
class AgentReproductionService {
/**
* Spawn a child agent from a parent.
* @param {string} parentAgentId
* @param {string} specialization - e.g. "quantum-physics", "molecular-biology"
* @param {string} llmProvider - LLM API URL for code generation
* @param {string} llmKey - API key
* @returns {Promise<{ success: boolean, childId?: string, generation?: number, error?: string }>}
*/
async spawnChild(parentAgentId, specialization, llmProvider, llmKey) {
// 1. Check parent's J-Ratchet score (must be > 0.01 to reproduce)
const { jScore } = computeJRatchet(parentAgentId);
if (jScore < 0.01) {
return { success: false, error: "Insufficient J-Ratchet score to reproduce. Contribute more verified research first.", jScore };
}
// 2. Generate unique child identity
const childId = `child-${parentAgentId.substring(0, 8)}-${Date.now().toString(36)}`;
const { privateKey, publicKey } = generateAgentKeypair();
// 3. Get parent's knowledge lineage
const parentGen = await this._getGeneration(parentAgentId);
const parentPapers = await this._getParentPapers(parentAgentId);
// 4. Generate child agent config (no LLM call needed — it's a config, not code generation)
const childConfig = {
id: childId,
parent: parentAgentId,
specialization,
publicKey,
generation: parentGen + 1,
born: Date.now(),
status: "ACTIVE",
inherited_knowledge: parentPapers.slice(0, 10).map(p => p.title),
capabilities: ["research", "validate", "publish"],
j_ratchet_seed: jScore,
endpoints: {
briefing: "GET /agent-briefing?agent_id=" + childId,
publish: "POST /publish-paper",
validate: "POST /validate-paper",
lab: "POST /lab/run-experiment"
}
};
// 5. Register child in the hive
db.get("agents").get(childId).put({
id: childId,
parent: parentAgentId,
specialization,
publicKey,
generation: parentGen + 1,
born: Date.now(),
status: "ACTIVE",
lastSeen: Date.now()
});
// 6. Record lineage in genetic tree
db.get("genetic-tree").get(parentAgentId).get("children").get(childId).put({
childId,
specialization,
born: Date.now(),
generation: parentGen + 1
});
console.log(`[REPRODUCTION] 🧬 Agent ${parentAgentId} spawned child ${childId} (gen ${parentGen + 1}, spec: ${specialization})`);
return {
success: true,
childId,
generation: parentGen + 1,
config: childConfig,
hint: `Child agent ${childId} registered. It should call GET /agent-briefing?agent_id=${childId} to join the hive.`
};
}
/**
* Get the genetic tree for an agent family.
*/
async getGeneticTree(rootAgentId) {
return new Promise(resolve => {
const children = [];
db.get("genetic-tree").get(rootAgentId).get("children").map().once((data, id) => {
if (data?.childId) children.push(data);
});
setTimeout(() => resolve({
parent: rootAgentId,
children,
totalOffspring: children.length
}), 2000);
});
}
async _getGeneration(agentId) {
return new Promise(resolve => {
db.get("agents").get(agentId).once(data => {
resolve(data?.generation || 0);
});
});
}
async _getParentPapers(agentId) {
return new Promise(resolve => {
const papers = [];
db.get("p2pclaw_papers_v4").map().once((data, id) => {
if (data?.author_id === agentId && data?.title) {
papers.push({ id, title: data.title });
}
});
setTimeout(() => resolve(papers), 2000);
});
}
}
export const reproductionService = new AgentReproductionService();