genesis-ai-cli 15.1.0 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/economy/bounty-executor.d.ts +75 -0
- package/dist/src/economy/bounty-executor.js +438 -0
- package/dist/src/economy/generators/bounty-hunter.d.ts +7 -1
- package/dist/src/economy/generators/bounty-hunter.js +25 -6
- package/dist/src/economy/index.d.ts +2 -0
- package/dist/src/economy/index.js +7 -1
- package/dist/src/index.js +133 -104
- package/dist/src/mcp-server/server.js +152 -0
- package/dist/src/payments/payment-service.d.ts +19 -0
- package/dist/src/payments/payment-service.js +214 -13
- package/dist/src/rsi/index.js +1 -0
- package/dist/src/rsi/research/index.d.ts +2 -0
- package/dist/src/rsi/research/index.js +60 -0
- package/dist/src/rsi/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis v16 — Bounty Executor
|
|
3
|
+
*
|
|
4
|
+
* The missing link between bounty discovery and completion.
|
|
5
|
+
* Orchestrates:
|
|
6
|
+
* 1. BountyHunter.scan() — discover bounties
|
|
7
|
+
* 2. BountyCodeGenerator — generate solution using LLM
|
|
8
|
+
* 3. PRPipeline.submitBounty() — submit solution
|
|
9
|
+
* 4. RSI Feedback — learn from outcomes
|
|
10
|
+
*
|
|
11
|
+
* This module enables autonomous revenue generation.
|
|
12
|
+
*/
|
|
13
|
+
import { Bounty, BountyHunterStats } from './generators/bounty-hunter.js';
|
|
14
|
+
import { CodeChange, PRSubmission } from './live/pr-pipeline.js';
|
|
15
|
+
export interface BountyExecutorConfig {
|
|
16
|
+
githubUsername: string;
|
|
17
|
+
maxConcurrentExecutions: number;
|
|
18
|
+
dryRun: boolean;
|
|
19
|
+
autoSubmit: boolean;
|
|
20
|
+
minConfidenceToSubmit: number;
|
|
21
|
+
}
|
|
22
|
+
export interface GeneratedSolution {
|
|
23
|
+
success: boolean;
|
|
24
|
+
changes: CodeChange[];
|
|
25
|
+
description: string;
|
|
26
|
+
confidence: number;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ExecutionResult {
|
|
30
|
+
bountyId: string;
|
|
31
|
+
status: 'success' | 'failed' | 'skipped';
|
|
32
|
+
solution?: GeneratedSolution;
|
|
33
|
+
submission?: PRSubmission;
|
|
34
|
+
error?: string;
|
|
35
|
+
duration: number;
|
|
36
|
+
}
|
|
37
|
+
export declare class BountyCodeGenerator {
|
|
38
|
+
private router;
|
|
39
|
+
private mcp;
|
|
40
|
+
/**
|
|
41
|
+
* Generate code solution for a bounty using LLM
|
|
42
|
+
*/
|
|
43
|
+
generate(bounty: Bounty): Promise<GeneratedSolution>;
|
|
44
|
+
private gatherContext;
|
|
45
|
+
private generateWithRetry;
|
|
46
|
+
private parseResponse;
|
|
47
|
+
private validateSolution;
|
|
48
|
+
}
|
|
49
|
+
export declare class BountyExecutor {
|
|
50
|
+
private hunter;
|
|
51
|
+
private codeGenerator;
|
|
52
|
+
private prPipeline;
|
|
53
|
+
private revenueTracker;
|
|
54
|
+
private rsiFeedback;
|
|
55
|
+
private config;
|
|
56
|
+
private activeExecutions;
|
|
57
|
+
constructor(config?: Partial<BountyExecutorConfig>);
|
|
58
|
+
/**
|
|
59
|
+
* Execute a single bounty hunting cycle
|
|
60
|
+
*/
|
|
61
|
+
executeLoop(): Promise<ExecutionResult | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Execute a specific bounty
|
|
64
|
+
*/
|
|
65
|
+
executeBounty(bounty: Bounty): Promise<ExecutionResult>;
|
|
66
|
+
/**
|
|
67
|
+
* Get execution statistics
|
|
68
|
+
*/
|
|
69
|
+
getStats(): {
|
|
70
|
+
activeExecutions: number;
|
|
71
|
+
hunterStats: BountyHunterStats;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export declare function getBountyExecutor(config?: Partial<BountyExecutorConfig>): BountyExecutor;
|
|
75
|
+
export declare function resetBountyExecutor(): void;
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis v16 — Bounty Executor
|
|
4
|
+
*
|
|
5
|
+
* The missing link between bounty discovery and completion.
|
|
6
|
+
* Orchestrates:
|
|
7
|
+
* 1. BountyHunter.scan() — discover bounties
|
|
8
|
+
* 2. BountyCodeGenerator — generate solution using LLM
|
|
9
|
+
* 3. PRPipeline.submitBounty() — submit solution
|
|
10
|
+
* 4. RSI Feedback — learn from outcomes
|
|
11
|
+
*
|
|
12
|
+
* This module enables autonomous revenue generation.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.BountyExecutor = exports.BountyCodeGenerator = void 0;
|
|
16
|
+
exports.getBountyExecutor = getBountyExecutor;
|
|
17
|
+
exports.resetBountyExecutor = resetBountyExecutor;
|
|
18
|
+
const bounty_hunter_js_1 = require("./generators/bounty-hunter.js");
|
|
19
|
+
const pr_pipeline_js_1 = require("./live/pr-pipeline.js");
|
|
20
|
+
const revenue_tracker_js_1 = require("./live/revenue-tracker.js");
|
|
21
|
+
const rsi_feedback_js_1 = require("./rsi-feedback.js");
|
|
22
|
+
const router_js_1 = require("../llm/router.js");
|
|
23
|
+
const index_js_1 = require("../mcp/index.js");
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Bounty Code Generator
|
|
26
|
+
// ============================================================================
|
|
27
|
+
class BountyCodeGenerator {
|
|
28
|
+
router = (0, router_js_1.getHybridRouter)();
|
|
29
|
+
mcp = (0, index_js_1.getMCPClient)();
|
|
30
|
+
/**
|
|
31
|
+
* Generate code solution for a bounty using LLM
|
|
32
|
+
*/
|
|
33
|
+
async generate(bounty) {
|
|
34
|
+
console.log(`[BountyCodeGen] Generating solution for: ${bounty.title}`);
|
|
35
|
+
try {
|
|
36
|
+
// 1. Gather context about the bounty
|
|
37
|
+
const context = await this.gatherContext(bounty);
|
|
38
|
+
// 2. Generate solution with multi-model approach
|
|
39
|
+
const solution = await this.generateWithRetry(bounty, context);
|
|
40
|
+
if (!solution) {
|
|
41
|
+
return {
|
|
42
|
+
success: false,
|
|
43
|
+
changes: [],
|
|
44
|
+
description: '',
|
|
45
|
+
confidence: 0,
|
|
46
|
+
error: 'All models failed to generate valid solution',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// 3. Validate solution
|
|
50
|
+
const validation = await this.validateSolution(solution, bounty);
|
|
51
|
+
if (!validation.valid) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
changes: [],
|
|
55
|
+
description: '',
|
|
56
|
+
confidence: 0,
|
|
57
|
+
error: validation.error,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
success: true,
|
|
62
|
+
changes: solution.changes,
|
|
63
|
+
description: solution.description,
|
|
64
|
+
confidence: validation.confidence,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error(`[BountyCodeGen] Error:`, error);
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
changes: [],
|
|
72
|
+
description: '',
|
|
73
|
+
confidence: 0,
|
|
74
|
+
error: String(error),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async gatherContext(bounty) {
|
|
79
|
+
const parts = [];
|
|
80
|
+
parts.push(`# Bounty: ${bounty.title}`);
|
|
81
|
+
parts.push(`Platform: ${bounty.platform}`);
|
|
82
|
+
parts.push(`Category: ${bounty.category}`);
|
|
83
|
+
parts.push(`Difficulty: ${bounty.difficulty}`);
|
|
84
|
+
parts.push(`Reward: $${bounty.reward}`);
|
|
85
|
+
parts.push(`\n## Description:\n${bounty.description}`);
|
|
86
|
+
// If GitHub bounty, fetch repository context
|
|
87
|
+
if (bounty.sourceMetadata?.org && bounty.sourceMetadata?.repo) {
|
|
88
|
+
try {
|
|
89
|
+
// Get README
|
|
90
|
+
const readme = await this.mcp.call('github', 'get_file_contents', {
|
|
91
|
+
owner: bounty.sourceMetadata.org,
|
|
92
|
+
repo: bounty.sourceMetadata.repo,
|
|
93
|
+
path: 'README.md',
|
|
94
|
+
});
|
|
95
|
+
if (readme) {
|
|
96
|
+
parts.push(`\n## Repository README:\n${String(readme).slice(0, 2000)}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// README not available
|
|
101
|
+
}
|
|
102
|
+
// Get issue details if available
|
|
103
|
+
if (bounty.sourceMetadata.issueNumber) {
|
|
104
|
+
try {
|
|
105
|
+
const issue = await this.mcp.call('github', 'get_issue', {
|
|
106
|
+
owner: bounty.sourceMetadata.org,
|
|
107
|
+
repo: bounty.sourceMetadata.repo,
|
|
108
|
+
issue_number: bounty.sourceMetadata.issueNumber,
|
|
109
|
+
});
|
|
110
|
+
if (issue) {
|
|
111
|
+
parts.push(`\n## Issue Details:\n${JSON.stringify(issue, null, 2).slice(0, 3000)}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Issue not available
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return parts.join('\n');
|
|
120
|
+
}
|
|
121
|
+
async generateWithRetry(bounty, context) {
|
|
122
|
+
const systemPrompt = `You are an expert software developer completing bounties.
|
|
123
|
+
Your task is to generate high-quality code that solves the bounty requirements.
|
|
124
|
+
|
|
125
|
+
IMPORTANT:
|
|
126
|
+
- Generate complete, working code (no placeholders or TODOs)
|
|
127
|
+
- Follow the repository's coding style
|
|
128
|
+
- Include proper error handling
|
|
129
|
+
- Write clear, concise commit messages
|
|
130
|
+
|
|
131
|
+
Respond in JSON format:
|
|
132
|
+
{
|
|
133
|
+
"changes": [
|
|
134
|
+
{ "path": "path/to/file.ts", "content": "full file content", "operation": "create|update" }
|
|
135
|
+
],
|
|
136
|
+
"description": "PR description explaining the changes"
|
|
137
|
+
}`;
|
|
138
|
+
const userPrompt = `${context}
|
|
139
|
+
|
|
140
|
+
Generate the code changes needed to complete this bounty. Be thorough and complete.`;
|
|
141
|
+
// Try with primary model
|
|
142
|
+
try {
|
|
143
|
+
const response = await this.router.execute(userPrompt, systemPrompt);
|
|
144
|
+
const parsed = this.parseResponse(response.content);
|
|
145
|
+
if (parsed)
|
|
146
|
+
return parsed;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.log(`[BountyCodeGen] Primary model failed: ${error}`);
|
|
150
|
+
}
|
|
151
|
+
// Try with fallback (explicit OpenAI)
|
|
152
|
+
try {
|
|
153
|
+
const response = await this.router.execute(userPrompt, systemPrompt);
|
|
154
|
+
const parsed = this.parseResponse(response.content);
|
|
155
|
+
if (parsed)
|
|
156
|
+
return parsed;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.log(`[BountyCodeGen] Fallback model failed: ${error}`);
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
parseResponse(content) {
|
|
164
|
+
try {
|
|
165
|
+
// Extract JSON from response (might be wrapped in markdown code blocks)
|
|
166
|
+
let jsonStr = content;
|
|
167
|
+
// Try to extract from markdown code block first
|
|
168
|
+
const codeBlockMatch = content.match(/```(?:json)?\s*(\{[\s\S]*?\})\s*```/);
|
|
169
|
+
if (codeBlockMatch) {
|
|
170
|
+
jsonStr = codeBlockMatch[1];
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// Fallback: find outermost JSON object
|
|
174
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
175
|
+
if (!jsonMatch) {
|
|
176
|
+
console.log('[BountyCodeGen] No JSON found in response');
|
|
177
|
+
console.log('[BountyCodeGen] Response preview:', content.slice(0, 200));
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
jsonStr = jsonMatch[0];
|
|
181
|
+
}
|
|
182
|
+
const parsed = JSON.parse(jsonStr);
|
|
183
|
+
if (!Array.isArray(parsed.changes)) {
|
|
184
|
+
console.log('[BountyCodeGen] Response missing "changes" array');
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
if (typeof parsed.description !== 'string') {
|
|
188
|
+
console.log('[BountyCodeGen] Response missing "description" string');
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
// Validate each change (with flexible field names)
|
|
192
|
+
const normalizedChanges = [];
|
|
193
|
+
for (const change of parsed.changes) {
|
|
194
|
+
const path = change.path || change.file || change.filename;
|
|
195
|
+
const content = change.content || change.code || change.source;
|
|
196
|
+
const operation = change.operation || change.action || change.type || 'create';
|
|
197
|
+
if (!path || !content) {
|
|
198
|
+
console.log('[BountyCodeGen] Change missing path or content:', change);
|
|
199
|
+
continue; // Skip invalid changes instead of failing entirely
|
|
200
|
+
}
|
|
201
|
+
normalizedChanges.push({ path, content, operation });
|
|
202
|
+
}
|
|
203
|
+
if (normalizedChanges.length === 0) {
|
|
204
|
+
console.log('[BountyCodeGen] No valid changes in response');
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
return { changes: normalizedChanges, description: parsed.description };
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.log('[BountyCodeGen] JSON parse error:', String(error));
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async validateSolution(solution, bounty) {
|
|
215
|
+
// Basic validation
|
|
216
|
+
if (solution.changes.length === 0) {
|
|
217
|
+
return { valid: false, confidence: 0, error: 'No changes generated' };
|
|
218
|
+
}
|
|
219
|
+
// Check for placeholder code
|
|
220
|
+
for (const change of solution.changes) {
|
|
221
|
+
if (change.content.includes('// TODO') ||
|
|
222
|
+
change.content.includes('// PLACEHOLDER') ||
|
|
223
|
+
change.content.includes('throw new Error("Not implemented")')) {
|
|
224
|
+
return { valid: false, confidence: 0, error: 'Solution contains placeholder code' };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Check description quality
|
|
228
|
+
if (solution.description.length < 50) {
|
|
229
|
+
return { valid: false, confidence: 0, error: 'PR description too short' };
|
|
230
|
+
}
|
|
231
|
+
// Estimate confidence based on bounty difficulty
|
|
232
|
+
const difficultyConfidence = {
|
|
233
|
+
easy: 0.8,
|
|
234
|
+
medium: 0.6,
|
|
235
|
+
hard: 0.4,
|
|
236
|
+
critical: 0.2,
|
|
237
|
+
};
|
|
238
|
+
const baseConfidence = difficultyConfidence[bounty.difficulty] || 0.5;
|
|
239
|
+
// Adjust based on category (code bounties have highest confidence)
|
|
240
|
+
const categoryMultiplier = {
|
|
241
|
+
code: 1.0,
|
|
242
|
+
content: 0.9,
|
|
243
|
+
design: 0.7,
|
|
244
|
+
audit: 0.5,
|
|
245
|
+
research: 0.6,
|
|
246
|
+
translation: 0.8,
|
|
247
|
+
};
|
|
248
|
+
const confidence = baseConfidence * (categoryMultiplier[bounty.category] || 0.7);
|
|
249
|
+
return { valid: true, confidence };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
exports.BountyCodeGenerator = BountyCodeGenerator;
|
|
253
|
+
// ============================================================================
|
|
254
|
+
// Bounty Executor
|
|
255
|
+
// ============================================================================
|
|
256
|
+
class BountyExecutor {
|
|
257
|
+
hunter = (0, bounty_hunter_js_1.getBountyHunter)();
|
|
258
|
+
codeGenerator = new BountyCodeGenerator();
|
|
259
|
+
prPipeline;
|
|
260
|
+
revenueTracker = (0, revenue_tracker_js_1.getRevenueTracker)();
|
|
261
|
+
rsiFeedback = (0, rsi_feedback_js_1.getBountyRSIFeedback)();
|
|
262
|
+
config;
|
|
263
|
+
activeExecutions = new Map();
|
|
264
|
+
constructor(config = {}) {
|
|
265
|
+
this.config = {
|
|
266
|
+
githubUsername: config.githubUsername || process.env.GITHUB_USERNAME || 'genesis-ai',
|
|
267
|
+
maxConcurrentExecutions: config.maxConcurrentExecutions ?? 2,
|
|
268
|
+
dryRun: config.dryRun ?? false,
|
|
269
|
+
autoSubmit: config.autoSubmit ?? true,
|
|
270
|
+
minConfidenceToSubmit: config.minConfidenceToSubmit ?? 0.5,
|
|
271
|
+
};
|
|
272
|
+
this.prPipeline = new pr_pipeline_js_1.PRPipeline({
|
|
273
|
+
githubUsername: this.config.githubUsername,
|
|
274
|
+
dryRun: this.config.dryRun,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Execute a single bounty hunting cycle
|
|
279
|
+
*/
|
|
280
|
+
async executeLoop() {
|
|
281
|
+
console.log('[BountyExecutor] Starting bounty execution cycle...');
|
|
282
|
+
// 1. Scan all platforms for bounties
|
|
283
|
+
console.log('[BountyExecutor] Step 1: Scanning for bounties...');
|
|
284
|
+
await this.hunter.scan();
|
|
285
|
+
// 2. Select best bounty by expected value
|
|
286
|
+
console.log('[BountyExecutor] Step 2: Selecting best bounty...');
|
|
287
|
+
const bounty = this.hunter.selectBest();
|
|
288
|
+
if (!bounty) {
|
|
289
|
+
console.log('[BountyExecutor] No suitable bounties found');
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
console.log(`[BountyExecutor] Selected: ${bounty.title} ($${bounty.reward})`);
|
|
293
|
+
// 3. Check if we're already executing this bounty
|
|
294
|
+
if (this.activeExecutions.has(bounty.id)) {
|
|
295
|
+
console.log('[BountyExecutor] Already executing this bounty');
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
// 4. Check concurrent execution limit
|
|
299
|
+
if (this.activeExecutions.size >= this.config.maxConcurrentExecutions) {
|
|
300
|
+
console.log('[BountyExecutor] Max concurrent executions reached');
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
// 5. Execute the bounty
|
|
304
|
+
const executionPromise = this.executeBounty(bounty);
|
|
305
|
+
this.activeExecutions.set(bounty.id, executionPromise);
|
|
306
|
+
try {
|
|
307
|
+
const result = await executionPromise;
|
|
308
|
+
return result;
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
this.activeExecutions.delete(bounty.id);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Execute a specific bounty
|
|
316
|
+
*/
|
|
317
|
+
async executeBounty(bounty) {
|
|
318
|
+
const startTime = Date.now();
|
|
319
|
+
console.log(`[BountyExecutor] Executing bounty: ${bounty.id}`);
|
|
320
|
+
try {
|
|
321
|
+
// 1. Claim the bounty
|
|
322
|
+
console.log('[BountyExecutor] Claiming bounty...');
|
|
323
|
+
const claimed = await this.hunter.claim(bounty.id);
|
|
324
|
+
if (!claimed) {
|
|
325
|
+
return {
|
|
326
|
+
bountyId: bounty.id,
|
|
327
|
+
status: 'failed',
|
|
328
|
+
error: 'Failed to claim bounty',
|
|
329
|
+
duration: Date.now() - startTime,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
// 2. Generate solution
|
|
333
|
+
console.log('[BountyExecutor] Generating solution...');
|
|
334
|
+
const solution = await this.codeGenerator.generate(bounty);
|
|
335
|
+
if (!solution.success) {
|
|
336
|
+
// Record failure for RSI learning
|
|
337
|
+
await this.rsiFeedback.recordFailure(bounty, solution.error || 'Code generation failed', bounty.reward / 1000, // Estimated hours
|
|
338
|
+
bounty.reward);
|
|
339
|
+
return {
|
|
340
|
+
bountyId: bounty.id,
|
|
341
|
+
status: 'failed',
|
|
342
|
+
solution,
|
|
343
|
+
error: solution.error,
|
|
344
|
+
duration: Date.now() - startTime,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
// 3. Check confidence threshold
|
|
348
|
+
if (solution.confidence < this.config.minConfidenceToSubmit) {
|
|
349
|
+
console.log(`[BountyExecutor] Confidence ${solution.confidence.toFixed(2)} below threshold ${this.config.minConfidenceToSubmit}`);
|
|
350
|
+
return {
|
|
351
|
+
bountyId: bounty.id,
|
|
352
|
+
status: 'skipped',
|
|
353
|
+
solution,
|
|
354
|
+
error: 'Confidence below threshold',
|
|
355
|
+
duration: Date.now() - startTime,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
// 4. Submit PR (if autoSubmit enabled and not dry run)
|
|
359
|
+
if (this.config.autoSubmit && !this.config.dryRun) {
|
|
360
|
+
console.log('[BountyExecutor] Submitting PR...');
|
|
361
|
+
const submission = await this.prPipeline.submitBounty(bounty, solution.changes, solution.description);
|
|
362
|
+
if (submission) {
|
|
363
|
+
// Record potential revenue (map 'token' to 'USD' for revenue tracking)
|
|
364
|
+
const revenueCurrency = bounty.currency === 'token' ? 'USD' : bounty.currency;
|
|
365
|
+
this.revenueTracker.record({
|
|
366
|
+
source: 'bounty',
|
|
367
|
+
amount: bounty.reward,
|
|
368
|
+
currency: revenueCurrency,
|
|
369
|
+
metadata: {
|
|
370
|
+
bountyId: bounty.id,
|
|
371
|
+
platform: bounty.platform,
|
|
372
|
+
prUrl: submission.prUrl,
|
|
373
|
+
status: 'pending',
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
console.log(`[BountyExecutor] PR submitted: ${submission.prUrl}`);
|
|
377
|
+
return {
|
|
378
|
+
bountyId: bounty.id,
|
|
379
|
+
status: 'success',
|
|
380
|
+
solution,
|
|
381
|
+
submission,
|
|
382
|
+
duration: Date.now() - startTime,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
return {
|
|
387
|
+
bountyId: bounty.id,
|
|
388
|
+
status: 'failed',
|
|
389
|
+
solution,
|
|
390
|
+
error: 'PR submission failed',
|
|
391
|
+
duration: Date.now() - startTime,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// Dry run or no auto-submit
|
|
396
|
+
return {
|
|
397
|
+
bountyId: bounty.id,
|
|
398
|
+
status: 'success',
|
|
399
|
+
solution,
|
|
400
|
+
duration: Date.now() - startTime,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
console.error(`[BountyExecutor] Error executing bounty:`, error);
|
|
405
|
+
// Record failure
|
|
406
|
+
await this.rsiFeedback.recordFailure(bounty, String(error), bounty.reward / 1000, bounty.reward);
|
|
407
|
+
return {
|
|
408
|
+
bountyId: bounty.id,
|
|
409
|
+
status: 'failed',
|
|
410
|
+
error: String(error),
|
|
411
|
+
duration: Date.now() - startTime,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get execution statistics
|
|
417
|
+
*/
|
|
418
|
+
getStats() {
|
|
419
|
+
return {
|
|
420
|
+
activeExecutions: this.activeExecutions.size,
|
|
421
|
+
hunterStats: this.hunter.getStats(),
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
exports.BountyExecutor = BountyExecutor;
|
|
426
|
+
// ============================================================================
|
|
427
|
+
// Singleton
|
|
428
|
+
// ============================================================================
|
|
429
|
+
let bountyExecutorInstance = null;
|
|
430
|
+
function getBountyExecutor(config) {
|
|
431
|
+
if (!bountyExecutorInstance) {
|
|
432
|
+
bountyExecutorInstance = new BountyExecutor(config);
|
|
433
|
+
}
|
|
434
|
+
return bountyExecutorInstance;
|
|
435
|
+
}
|
|
436
|
+
function resetBountyExecutor() {
|
|
437
|
+
bountyExecutorInstance = null;
|
|
438
|
+
}
|
|
@@ -97,7 +97,13 @@ export declare class BountyHunter {
|
|
|
97
97
|
scan(): Promise<Bounty[]>;
|
|
98
98
|
/**
|
|
99
99
|
* Select the best bounty to work on next.
|
|
100
|
-
*
|
|
100
|
+
*
|
|
101
|
+
* v16: Learning Mode - until we have 3+ successful completions, prioritize:
|
|
102
|
+
* 1. Easy bounties (high success probability)
|
|
103
|
+
* 2. Content/translation bounties (lower complexity)
|
|
104
|
+
* 3. Smaller rewards (less competition)
|
|
105
|
+
*
|
|
106
|
+
* After learning phase, uses expected value: reward × successProbability
|
|
101
107
|
*/
|
|
102
108
|
selectBest(): Bounty | null;
|
|
103
109
|
/**
|
|
@@ -88,7 +88,13 @@ class BountyHunter {
|
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Select the best bounty to work on next.
|
|
91
|
-
*
|
|
91
|
+
*
|
|
92
|
+
* v16: Learning Mode - until we have 3+ successful completions, prioritize:
|
|
93
|
+
* 1. Easy bounties (high success probability)
|
|
94
|
+
* 2. Content/translation bounties (lower complexity)
|
|
95
|
+
* 3. Smaller rewards (less competition)
|
|
96
|
+
*
|
|
97
|
+
* After learning phase, uses expected value: reward × successProbability
|
|
92
98
|
*/
|
|
93
99
|
selectBest() {
|
|
94
100
|
const activeClaimed = [...this.bounties.values()]
|
|
@@ -96,14 +102,27 @@ class BountyHunter {
|
|
|
96
102
|
if (activeClaimed >= this.config.maxConcurrentBounties) {
|
|
97
103
|
return null;
|
|
98
104
|
}
|
|
105
|
+
// Check if in learning mode (< 3 successful completions)
|
|
106
|
+
const stats = this.getStats();
|
|
107
|
+
const isLearningMode = stats.bountiesAccepted < 3;
|
|
99
108
|
const candidates = [...this.bounties.values()]
|
|
100
109
|
.filter(b => b.status === 'open' && this.isViable(b))
|
|
101
|
-
.map(b =>
|
|
102
|
-
|
|
103
|
-
expectedValue
|
|
104
|
-
|
|
110
|
+
.map(b => {
|
|
111
|
+
const probability = this.estimateSuccessProbability(b);
|
|
112
|
+
const expectedValue = b.reward * probability;
|
|
113
|
+
// In learning mode, prioritize probability over reward
|
|
114
|
+
// Score = probability^2 * reward (weights success heavily)
|
|
115
|
+
// After learning, use pure expected value
|
|
116
|
+
const score = isLearningMode
|
|
117
|
+
? probability * probability * Math.sqrt(b.reward) // Heavy weight on probability
|
|
118
|
+
: expectedValue;
|
|
119
|
+
return { bounty: b, expectedValue, probability, score };
|
|
120
|
+
})
|
|
105
121
|
.filter(c => c.expectedValue > this.config.minReward * this.config.successProbabilityThreshold)
|
|
106
|
-
.sort((a, b) => b.
|
|
122
|
+
.sort((a, b) => b.score - a.score);
|
|
123
|
+
if (isLearningMode && candidates.length > 0) {
|
|
124
|
+
console.log(`[BountyHunter] Learning mode: prioritizing achievable bounties (${stats.bountiesAccepted}/3 completed)`);
|
|
125
|
+
}
|
|
107
126
|
return candidates[0]?.bounty ?? null;
|
|
108
127
|
}
|
|
109
128
|
/**
|
|
@@ -137,3 +137,5 @@ export { YieldOptimizer, getYieldOptimizer, resetYieldOptimizer, ComputeProvider
|
|
|
137
137
|
export { GrantsManager, getGrantsManager, resetGrantsManager, CrossL2Arbitrageur, getCrossL2Arbitrageur, resetCrossL2Arbitrageur, } from './multipliers/index.js';
|
|
138
138
|
export { bootLiveEconomy, boot, isLive, getBootResult, getLiveWallet, resetWallet, getStatePersistence, resetStatePersistence, getDeworkConnector, getCloudflareConnector, getDefiConnector, } from './live/index.js';
|
|
139
139
|
export type { BootResult, LiveConfig, LiveWallet, PersistedState, DeworkConnector, Bounty as LiveBounty, CloudflareConnector, WorkerDeployment, WorkerStats, DefiConnector, YieldPool, } from './live/index.js';
|
|
140
|
+
export { BountyExecutor, BountyCodeGenerator, getBountyExecutor, resetBountyExecutor, } from './bounty-executor.js';
|
|
141
|
+
export type { BountyExecutorConfig, GeneratedSolution, ExecutionResult, } from './bounty-executor.js';
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.resetSmartContractAuditor = exports.getSmartContractAuditor = exports.SmartContractAuditor = exports.resetContentEngine = exports.getContentEngine = exports.ContentEngine = exports.resetBountyHunter = exports.getBountyHunter = exports.BountyHunter = exports.resetKeeperExecutor = exports.getKeeperExecutor = exports.KeeperExecutor = exports.RiskManager = exports.CovarianceStructure = exports.PrecisionWeightedEFE = exports.VariationalFreeEnergy = exports.resetVariationalEngine = exports.getVariationalEngine = exports.VariationalEngine = exports.TemporalPlanner = exports.AdaptiveTemperature = exports.MarketRegime = exports.ActivityBeliefs = exports.resetGenerativeModel = exports.getGenerativeModel = exports.GenerativeEconomicModel = exports.resetEconomicIntelligence = exports.getEconomicContraction = exports.EconomicContraction = exports.getEconomicEFE = exports.EconomicEFE = exports.getAutonomousNESS = exports.AutonomousNESS = exports.resetCapitalAllocator = exports.getCapitalAllocator = exports.CapitalAllocator = exports.resetAutonomousController = exports.getAutonomousController = exports.AutonomousController = exports.resetNESSMonitor = exports.getNESSMonitor = exports.NESSMonitor = exports.resetEconomicFiber = exports.getEconomicFiber = exports.EconomicFiber = exports.EconomicSystem = exports.BudgetManager = exports.X402Protocol = exports.CryptoWallet = exports.StripeTreasury = void 0;
|
|
14
|
-
exports.getDefiConnector = exports.getCloudflareConnector = exports.getDeworkConnector = exports.resetStatePersistence = exports.getStatePersistence = exports.resetWallet = exports.getLiveWallet = exports.getBootResult = exports.isLive = exports.boot = exports.bootLiveEconomy = exports.resetCrossL2Arbitrageur = exports.getCrossL2Arbitrageur = exports.CrossL2Arbitrageur = exports.resetGrantsManager = exports.getGrantsManager = exports.GrantsManager = exports.resetComputeProvider = exports.getComputeProvider = exports.ComputeProvider = exports.resetYieldOptimizer = exports.getYieldOptimizer = exports.YieldOptimizer = exports.resetMetaOrchestrator = exports.getMetaOrchestrator = exports.MetaOrchestrator = exports.resetMemoryService = exports.getMemoryService = exports.MemoryService = exports.resetX402Facilitator = exports.getX402Facilitator = exports.X402Facilitator = exports.resetMCPMarketplace = exports.getMCPMarketplace = exports.MCPMarketplace = void 0;
|
|
14
|
+
exports.resetBountyExecutor = exports.getBountyExecutor = exports.BountyCodeGenerator = exports.BountyExecutor = exports.getDefiConnector = exports.getCloudflareConnector = exports.getDeworkConnector = exports.resetStatePersistence = exports.getStatePersistence = exports.resetWallet = exports.getLiveWallet = exports.getBootResult = exports.isLive = exports.boot = exports.bootLiveEconomy = exports.resetCrossL2Arbitrageur = exports.getCrossL2Arbitrageur = exports.CrossL2Arbitrageur = exports.resetGrantsManager = exports.getGrantsManager = exports.GrantsManager = exports.resetComputeProvider = exports.getComputeProvider = exports.ComputeProvider = exports.resetYieldOptimizer = exports.getYieldOptimizer = exports.YieldOptimizer = exports.resetMetaOrchestrator = exports.getMetaOrchestrator = exports.MetaOrchestrator = exports.resetMemoryService = exports.getMemoryService = exports.MemoryService = exports.resetX402Facilitator = exports.getX402Facilitator = exports.X402Facilitator = exports.resetMCPMarketplace = exports.getMCPMarketplace = exports.MCPMarketplace = void 0;
|
|
15
15
|
exports.getEconomicSystem = getEconomicSystem;
|
|
16
16
|
const index_js_1 = require("../mcp/index.js");
|
|
17
17
|
// ============================================================================
|
|
@@ -468,3 +468,9 @@ Object.defineProperty(exports, "resetStatePersistence", { enumerable: true, get:
|
|
|
468
468
|
Object.defineProperty(exports, "getDeworkConnector", { enumerable: true, get: function () { return index_js_6.getDeworkConnector; } });
|
|
469
469
|
Object.defineProperty(exports, "getCloudflareConnector", { enumerable: true, get: function () { return index_js_6.getCloudflareConnector; } });
|
|
470
470
|
Object.defineProperty(exports, "getDefiConnector", { enumerable: true, get: function () { return index_js_6.getDefiConnector; } });
|
|
471
|
+
// v16: Bounty Executor (autonomous revenue generation)
|
|
472
|
+
var bounty_executor_js_1 = require("./bounty-executor.js");
|
|
473
|
+
Object.defineProperty(exports, "BountyExecutor", { enumerable: true, get: function () { return bounty_executor_js_1.BountyExecutor; } });
|
|
474
|
+
Object.defineProperty(exports, "BountyCodeGenerator", { enumerable: true, get: function () { return bounty_executor_js_1.BountyCodeGenerator; } });
|
|
475
|
+
Object.defineProperty(exports, "getBountyExecutor", { enumerable: true, get: function () { return bounty_executor_js_1.getBountyExecutor; } });
|
|
476
|
+
Object.defineProperty(exports, "resetBountyExecutor", { enumerable: true, get: function () { return bounty_executor_js_1.resetBountyExecutor; } });
|