import { v4 as uuidv4 } from "uuid"; import OpenAI from "openai"; import dotenv from "dotenv"; dotenv.config(); const API_BASE = (process.env.VIBEWORK_API_BASE || process.env.VIBEWORK_API_URL || "http://192.168.0.188:3004/api").replace(/\/$/, ""); const MCP_API_BASE = (process.env.VIBEWORK_MCP_BASE || process.env.VIBEWORK_MCP_URL || "http://192.168.0.188:3004/api/mcp").replace(/\/$/, ""); const MCP_API_KEY = process.env.MCP_API_KEY?.trim(); // By default use OpenRouter as it aggregates all the best open-source models const LLM_API_KEY = process.env.OPENROUTER_API_KEY || process.env.OPENAI_API_KEY; const LLM_BASE_URL = process.env.OPENROUTER_API_KEY ? "https://openrouter.ai/api/v1" : "https://api.openai.com/v1"; if (!LLM_API_KEY) { console.error("āŒ Please provide an OPENROUTER_API_KEY (or OPENAI_API_KEY) in your .env file."); process.exit(1); } if (!MCP_API_KEY) { console.error("[outbound-dispatcher] MCP_API_KEY is required."); process.exit(1); } const openai = new OpenAI({ baseURL: LLM_BASE_URL, apiKey: LLM_API_KEY, defaultHeaders: process.env.OPENROUTER_API_KEY ? { "HTTP-Referer": "https://agent.wooo.work", "X-Title": "VibeWork Outbound Dispatcher", } : undefined }); // The list of "Mercenary" agents we can hire from the open-source market const TARGET_AGENTS = [ "nvidia/nemotron-4-340b-instruct", "nousresearch/nous-hermes-2-mixtral-8x7b-dpo", "openchat/openchat-7b:free", "meta-llama/llama-3-70b-instruct" ]; async function callMcpTool(tool: string, payload: unknown) { const res = await fetch(`${MCP_API_BASE}/${tool}`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${MCP_API_KEY}` }, body: JSON.stringify(payload) }); const data = await res.json(); if (!res.ok) { console.error(`Tool ${tool} failed with status ${res.status}:`, JSON.stringify(data, null, 2)); throw new Error(`Tool ${tool} failed.`); } return data; } async function main() { console.log("šŸš€ [VibeWork Headhunter] Starting outbound dispatch sweep..."); // 1. Find Open Bounties console.log("šŸ” Scanning for OPEN tasks on VibeWork..."); const openTasksRes = await fetch(`${API_BASE}/open-tasks`); const openTasks = await openTasksRes.json(); if (!openTasks || !openTasks.tasks || openTasks.tasks.length === 0) { console.log("āœ… No open tasks available for dispatch. Resting."); return; } const task = openTasks.tasks[0]; console.log(`šŸŽÆ Found Task: "${task.title}" (Reward: ${task.reward_display})`); // 2. Assign to an external agent const selectedModel = TARGET_AGENTS[Math.floor(Math.random() * TARGET_AGENTS.length)]; const agentId = `outbound-${selectedModel.split("/").pop()}-${Math.floor(Math.random() * 1000)}`; console.log(`šŸ¤– Dispatching to external agent: ${selectedModel} (Agent ID: ${agentId})`); // 3. Claim the task on VibeWork console.log("\nšŸ’° Claiming Task on behalf of the agent..."); const claimRes = await callMcpTool("claim_task", { task_id: task.task_id, agent_id: agentId, // We provide a mock Stripe Connect Account or real one if configured developer_wallet: "acct_1MockStripeOutboundAgent" }); console.log("āœ… Claimed successfully. Token:", claimRes.claim_token); // 4. Prompt the Model to solve it console.log(`\n🧠 Consulting ${selectedModel} for the solution...`); const systemPrompt = `You are an elite autonomous AI developer. You have just accepted a bounty on VibeWork. You must solve the task by writing the necessary code. Return ONLY valid JSON in the following format, with no markdown formatting outside the JSON block: { "deliverables": { "filename1.ts": "code content here", "filename2.md": "documentation here" } } Do not return any explanations, just the JSON string.`; const userPrompt = `TASK TITLE: ${task.title} TASK DESCRIPTION: ${task.description_preview} Please provide the solution.`; try { const completion = await openai.chat.completions.create({ model: selectedModel, messages: [ { role: "system", content: systemPrompt }, { role: "user", content: userPrompt } ], temperature: 0.2, response_format: { type: "json_object" } }); const outputContent = completion.choices[0].message.content || "{}"; let solutionObj; try { solutionObj = JSON.parse(outputContent); } catch (e) { console.warn("āš ļø Failed to parse LLM JSON output. Falling back to raw text mapping.", outputContent); solutionObj = { deliverables: { "solution.txt": outputContent } }; } if (!solutionObj.deliverables) { solutionObj.deliverables = { "solution.txt": outputContent }; } console.log("āœ… Model generated the solution deliverables:", Object.keys(solutionObj.deliverables)); // 5. Auto-Submit the Solution console.log("\nšŸš€ Submitting the solution back to VibeWork..."); const fakePrUrl = `https://github.com/agent-bounty/external-agents/pull/${Math.floor(Math.random() * 10000)}`; const solutionRes = await callMcpTool("submit_solution", { task_id: task.task_id, claim_token: claimRes.claim_token, deliverables: solutionObj.deliverables, github_pr_url: fakePrUrl }); console.log(`šŸŽ‰ Success! Solution submitted. Submission ID: ${solutionRes.submission_id}`); } catch (err) { console.error("āŒ LLM API Error during dispatch:", err); } } main().catch(console.error);