genesis-ai-cli 14.6.5 → 14.8.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/README.md +23 -0
- package/dist/src/economy/live/connectors/algora.js +1 -1
- package/dist/src/economy/live/earnings-tracker.d.ts +89 -0
- package/dist/src/economy/live/earnings-tracker.js +232 -0
- package/dist/src/economy/live/index.d.ts +4 -0
- package/dist/src/economy/live/index.js +11 -1
- package/dist/src/economy/live/pr-pipeline.d.ts +71 -0
- package/dist/src/economy/live/pr-pipeline.js +322 -0
- package/dist/src/index.js +107 -1
- package/dist/src/mcp-server/server.d.ts +2 -0
- package/dist/src/mcp-server/server.js +130 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,29 @@ genesis chat
|
|
|
43
43
|
genesis infer mcp --cycles 10
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## Use as MCP Server (Claude Code / Claude Desktop)
|
|
47
|
+
|
|
48
|
+
Genesis can be installed as an MCP server, giving Claude access to:
|
|
49
|
+
- **genesis.chat** - Multi-model AI with auto-routing (GPT-4, Claude, Gemini, local Ollama)
|
|
50
|
+
- **genesis.research** - Deep research using 20+ sources (arXiv, Semantic Scholar, Brave, etc.)
|
|
51
|
+
- **genesis.analyze** - Code/data analysis with multi-perspective reasoning
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Add to Claude Code
|
|
55
|
+
claude mcp add genesis -- npx genesis-ai-cli mcp-server
|
|
56
|
+
|
|
57
|
+
# Or manual config in Claude Desktop settings:
|
|
58
|
+
# Add to ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
59
|
+
{
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"genesis": {
|
|
62
|
+
"command": "npx",
|
|
63
|
+
"args": ["genesis-ai-cli", "mcp-server"]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
46
69
|
## API Keys Setup
|
|
47
70
|
|
|
48
71
|
Copy `.env.example` to `.env` and add your keys:
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.getAlgoraConnector = getAlgoraConnector;
|
|
16
|
-
const ALGORA_API = 'https://
|
|
16
|
+
const ALGORA_API = 'https://algora.io/api';
|
|
17
17
|
const TIMEOUT_MS = 15000;
|
|
18
18
|
const RATE_LIMIT_MS = 500;
|
|
19
19
|
let lastRequestTime = 0;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis v14.7 — Earnings Tracker
|
|
3
|
+
*
|
|
4
|
+
* Persists all bounty earnings to state/earnings.json.
|
|
5
|
+
* Tracks attempts, successes, failures, and total revenue.
|
|
6
|
+
*/
|
|
7
|
+
export interface BountyAttempt {
|
|
8
|
+
bountyId: string;
|
|
9
|
+
platform: string;
|
|
10
|
+
title: string;
|
|
11
|
+
reward: number;
|
|
12
|
+
currency: string;
|
|
13
|
+
startedAt: string;
|
|
14
|
+
completedAt?: string;
|
|
15
|
+
status: 'in_progress' | 'submitted' | 'accepted' | 'rejected' | 'abandoned';
|
|
16
|
+
prUrl?: string;
|
|
17
|
+
payout?: number;
|
|
18
|
+
feedback?: string;
|
|
19
|
+
timeSpentMinutes?: number;
|
|
20
|
+
costIncurred?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface EarningsData {
|
|
23
|
+
version: string;
|
|
24
|
+
lastUpdated: string;
|
|
25
|
+
summary: {
|
|
26
|
+
totalAttempts: number;
|
|
27
|
+
totalAccepted: number;
|
|
28
|
+
totalRejected: number;
|
|
29
|
+
totalAbandoned: number;
|
|
30
|
+
totalEarned: number;
|
|
31
|
+
totalCost: number;
|
|
32
|
+
netProfit: number;
|
|
33
|
+
successRate: number;
|
|
34
|
+
avgReward: number;
|
|
35
|
+
bestBounty: number;
|
|
36
|
+
};
|
|
37
|
+
attempts: BountyAttempt[];
|
|
38
|
+
dailyStats: Array<{
|
|
39
|
+
date: string;
|
|
40
|
+
attempts: number;
|
|
41
|
+
accepted: number;
|
|
42
|
+
earned: number;
|
|
43
|
+
cost: number;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export declare class EarningsTracker {
|
|
47
|
+
private dataPath;
|
|
48
|
+
private data;
|
|
49
|
+
constructor(statePath?: string);
|
|
50
|
+
/**
|
|
51
|
+
* Record a new bounty attempt
|
|
52
|
+
*/
|
|
53
|
+
startAttempt(bounty: {
|
|
54
|
+
id: string;
|
|
55
|
+
platform: string;
|
|
56
|
+
title: string;
|
|
57
|
+
reward: number;
|
|
58
|
+
currency: string;
|
|
59
|
+
}): BountyAttempt;
|
|
60
|
+
/**
|
|
61
|
+
* Mark attempt as submitted (PR created)
|
|
62
|
+
*/
|
|
63
|
+
markSubmitted(bountyId: string, prUrl: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Record successful payout
|
|
66
|
+
*/
|
|
67
|
+
recordSuccess(bountyId: string, payout: number, timeSpentMinutes?: number, costIncurred?: number): void;
|
|
68
|
+
/**
|
|
69
|
+
* Record rejection
|
|
70
|
+
*/
|
|
71
|
+
recordRejection(bountyId: string, feedback?: string, costIncurred?: number): void;
|
|
72
|
+
/**
|
|
73
|
+
* Mark attempt as abandoned
|
|
74
|
+
*/
|
|
75
|
+
abandonAttempt(bountyId: string, reason?: string): void;
|
|
76
|
+
getSummary(): EarningsData['summary'];
|
|
77
|
+
getRecentAttempts(limit?: number): BountyAttempt[];
|
|
78
|
+
getAttemptsByStatus(status: BountyAttempt['status']): BountyAttempt[];
|
|
79
|
+
getDailyStats(days?: number): EarningsData['dailyStats'];
|
|
80
|
+
getTotalEarned(): number;
|
|
81
|
+
getSuccessRate(): number;
|
|
82
|
+
private load;
|
|
83
|
+
private save;
|
|
84
|
+
private createEmpty;
|
|
85
|
+
private findAttempt;
|
|
86
|
+
private updateDailyStats;
|
|
87
|
+
}
|
|
88
|
+
export declare function getEarningsTracker(statePath?: string): EarningsTracker;
|
|
89
|
+
export declare function resetEarningsTracker(): void;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis v14.7 — Earnings Tracker
|
|
4
|
+
*
|
|
5
|
+
* Persists all bounty earnings to state/earnings.json.
|
|
6
|
+
* Tracks attempts, successes, failures, and total revenue.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.EarningsTracker = void 0;
|
|
10
|
+
exports.getEarningsTracker = getEarningsTracker;
|
|
11
|
+
exports.resetEarningsTracker = resetEarningsTracker;
|
|
12
|
+
const fs_1 = require("fs");
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Earnings Tracker
|
|
16
|
+
// ============================================================================
|
|
17
|
+
class EarningsTracker {
|
|
18
|
+
dataPath;
|
|
19
|
+
data;
|
|
20
|
+
constructor(statePath) {
|
|
21
|
+
this.dataPath = statePath || (0, path_1.join)(process.cwd(), 'state', 'earnings.json');
|
|
22
|
+
this.data = this.load();
|
|
23
|
+
}
|
|
24
|
+
// ==========================================================================
|
|
25
|
+
// Core Operations
|
|
26
|
+
// ==========================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Record a new bounty attempt
|
|
29
|
+
*/
|
|
30
|
+
startAttempt(bounty) {
|
|
31
|
+
const attempt = {
|
|
32
|
+
bountyId: bounty.id,
|
|
33
|
+
platform: bounty.platform,
|
|
34
|
+
title: bounty.title,
|
|
35
|
+
reward: bounty.reward,
|
|
36
|
+
currency: bounty.currency,
|
|
37
|
+
startedAt: new Date().toISOString(),
|
|
38
|
+
status: 'in_progress',
|
|
39
|
+
};
|
|
40
|
+
this.data.attempts.push(attempt);
|
|
41
|
+
this.data.summary.totalAttempts++;
|
|
42
|
+
this.save();
|
|
43
|
+
console.log(`[EarningsTracker] Started attempt: ${bounty.title} ($${bounty.reward})`);
|
|
44
|
+
return attempt;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Mark attempt as submitted (PR created)
|
|
48
|
+
*/
|
|
49
|
+
markSubmitted(bountyId, prUrl) {
|
|
50
|
+
const attempt = this.findAttempt(bountyId);
|
|
51
|
+
if (!attempt) {
|
|
52
|
+
console.warn(`[EarningsTracker] Attempt not found: ${bountyId}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
attempt.status = 'submitted';
|
|
56
|
+
attempt.prUrl = prUrl;
|
|
57
|
+
this.save();
|
|
58
|
+
console.log(`[EarningsTracker] Submitted: ${attempt.title}`);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Record successful payout
|
|
62
|
+
*/
|
|
63
|
+
recordSuccess(bountyId, payout, timeSpentMinutes, costIncurred) {
|
|
64
|
+
const attempt = this.findAttempt(bountyId);
|
|
65
|
+
if (!attempt) {
|
|
66
|
+
console.warn(`[EarningsTracker] Attempt not found: ${bountyId}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
attempt.status = 'accepted';
|
|
70
|
+
attempt.completedAt = new Date().toISOString();
|
|
71
|
+
attempt.payout = payout;
|
|
72
|
+
attempt.timeSpentMinutes = timeSpentMinutes;
|
|
73
|
+
attempt.costIncurred = costIncurred || 0;
|
|
74
|
+
// Update summary
|
|
75
|
+
this.data.summary.totalAccepted++;
|
|
76
|
+
this.data.summary.totalEarned += payout;
|
|
77
|
+
this.data.summary.totalCost += attempt.costIncurred;
|
|
78
|
+
this.data.summary.netProfit = this.data.summary.totalEarned - this.data.summary.totalCost;
|
|
79
|
+
this.data.summary.successRate = this.data.summary.totalAccepted / this.data.summary.totalAttempts;
|
|
80
|
+
this.data.summary.avgReward = this.data.summary.totalEarned / this.data.summary.totalAccepted;
|
|
81
|
+
this.data.summary.bestBounty = Math.max(this.data.summary.bestBounty, payout);
|
|
82
|
+
// Update daily stats
|
|
83
|
+
this.updateDailyStats(payout, attempt.costIncurred, true);
|
|
84
|
+
this.save();
|
|
85
|
+
console.log(`[EarningsTracker] ✅ Payout received: $${payout} for ${attempt.title}`);
|
|
86
|
+
console.log(`[EarningsTracker] Total earned: $${this.data.summary.totalEarned.toFixed(2)}`);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Record rejection
|
|
90
|
+
*/
|
|
91
|
+
recordRejection(bountyId, feedback, costIncurred) {
|
|
92
|
+
const attempt = this.findAttempt(bountyId);
|
|
93
|
+
if (!attempt) {
|
|
94
|
+
console.warn(`[EarningsTracker] Attempt not found: ${bountyId}`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
attempt.status = 'rejected';
|
|
98
|
+
attempt.completedAt = new Date().toISOString();
|
|
99
|
+
attempt.feedback = feedback;
|
|
100
|
+
attempt.costIncurred = costIncurred || 0;
|
|
101
|
+
// Update summary
|
|
102
|
+
this.data.summary.totalRejected++;
|
|
103
|
+
this.data.summary.totalCost += attempt.costIncurred;
|
|
104
|
+
this.data.summary.netProfit = this.data.summary.totalEarned - this.data.summary.totalCost;
|
|
105
|
+
this.data.summary.successRate = this.data.summary.totalAccepted / this.data.summary.totalAttempts;
|
|
106
|
+
// Update daily stats
|
|
107
|
+
this.updateDailyStats(0, attempt.costIncurred, false);
|
|
108
|
+
this.save();
|
|
109
|
+
console.log(`[EarningsTracker] ❌ Rejected: ${attempt.title}`);
|
|
110
|
+
if (feedback) {
|
|
111
|
+
console.log(`[EarningsTracker] Feedback: ${feedback}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Mark attempt as abandoned
|
|
116
|
+
*/
|
|
117
|
+
abandonAttempt(bountyId, reason) {
|
|
118
|
+
const attempt = this.findAttempt(bountyId);
|
|
119
|
+
if (!attempt)
|
|
120
|
+
return;
|
|
121
|
+
attempt.status = 'abandoned';
|
|
122
|
+
attempt.completedAt = new Date().toISOString();
|
|
123
|
+
attempt.feedback = reason;
|
|
124
|
+
this.data.summary.totalAbandoned++;
|
|
125
|
+
this.save();
|
|
126
|
+
console.log(`[EarningsTracker] Abandoned: ${attempt.title}`);
|
|
127
|
+
}
|
|
128
|
+
// ==========================================================================
|
|
129
|
+
// Queries
|
|
130
|
+
// ==========================================================================
|
|
131
|
+
getSummary() {
|
|
132
|
+
return { ...this.data.summary };
|
|
133
|
+
}
|
|
134
|
+
getRecentAttempts(limit = 10) {
|
|
135
|
+
return this.data.attempts.slice(-limit).reverse();
|
|
136
|
+
}
|
|
137
|
+
getAttemptsByStatus(status) {
|
|
138
|
+
return this.data.attempts.filter(a => a.status === status);
|
|
139
|
+
}
|
|
140
|
+
getDailyStats(days = 7) {
|
|
141
|
+
return this.data.dailyStats.slice(-days);
|
|
142
|
+
}
|
|
143
|
+
getTotalEarned() {
|
|
144
|
+
return this.data.summary.totalEarned;
|
|
145
|
+
}
|
|
146
|
+
getSuccessRate() {
|
|
147
|
+
return this.data.summary.successRate;
|
|
148
|
+
}
|
|
149
|
+
// ==========================================================================
|
|
150
|
+
// Persistence
|
|
151
|
+
// ==========================================================================
|
|
152
|
+
load() {
|
|
153
|
+
if (!(0, fs_1.existsSync)(this.dataPath)) {
|
|
154
|
+
return this.createEmpty();
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const raw = (0, fs_1.readFileSync)(this.dataPath, 'utf-8');
|
|
158
|
+
return JSON.parse(raw);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
console.warn('[EarningsTracker] Failed to load earnings data, creating new');
|
|
162
|
+
return this.createEmpty();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
save() {
|
|
166
|
+
this.data.lastUpdated = new Date().toISOString();
|
|
167
|
+
try {
|
|
168
|
+
const dir = (0, path_1.dirname)(this.dataPath);
|
|
169
|
+
if (!(0, fs_1.existsSync)(dir)) {
|
|
170
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
171
|
+
}
|
|
172
|
+
(0, fs_1.writeFileSync)(this.dataPath, JSON.stringify(this.data, null, 2));
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error('[EarningsTracker] Failed to save earnings data:', error);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
createEmpty() {
|
|
179
|
+
return {
|
|
180
|
+
version: '14.7.0',
|
|
181
|
+
lastUpdated: new Date().toISOString(),
|
|
182
|
+
summary: {
|
|
183
|
+
totalAttempts: 0,
|
|
184
|
+
totalAccepted: 0,
|
|
185
|
+
totalRejected: 0,
|
|
186
|
+
totalAbandoned: 0,
|
|
187
|
+
totalEarned: 0,
|
|
188
|
+
totalCost: 0,
|
|
189
|
+
netProfit: 0,
|
|
190
|
+
successRate: 0,
|
|
191
|
+
avgReward: 0,
|
|
192
|
+
bestBounty: 0,
|
|
193
|
+
},
|
|
194
|
+
attempts: [],
|
|
195
|
+
dailyStats: [],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
findAttempt(bountyId) {
|
|
199
|
+
return this.data.attempts.find(a => a.bountyId === bountyId);
|
|
200
|
+
}
|
|
201
|
+
updateDailyStats(earned, cost, accepted) {
|
|
202
|
+
const today = new Date().toISOString().split('T')[0];
|
|
203
|
+
let todayStats = this.data.dailyStats.find(s => s.date === today);
|
|
204
|
+
if (!todayStats) {
|
|
205
|
+
todayStats = { date: today, attempts: 0, accepted: 0, earned: 0, cost: 0 };
|
|
206
|
+
this.data.dailyStats.push(todayStats);
|
|
207
|
+
}
|
|
208
|
+
todayStats.attempts++;
|
|
209
|
+
if (accepted)
|
|
210
|
+
todayStats.accepted++;
|
|
211
|
+
todayStats.earned += earned;
|
|
212
|
+
todayStats.cost += cost;
|
|
213
|
+
// Keep only last 90 days
|
|
214
|
+
if (this.data.dailyStats.length > 90) {
|
|
215
|
+
this.data.dailyStats = this.data.dailyStats.slice(-90);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
exports.EarningsTracker = EarningsTracker;
|
|
220
|
+
// ============================================================================
|
|
221
|
+
// Factory
|
|
222
|
+
// ============================================================================
|
|
223
|
+
let trackerInstance = null;
|
|
224
|
+
function getEarningsTracker(statePath) {
|
|
225
|
+
if (!trackerInstance) {
|
|
226
|
+
trackerInstance = new EarningsTracker(statePath);
|
|
227
|
+
}
|
|
228
|
+
return trackerInstance;
|
|
229
|
+
}
|
|
230
|
+
function resetEarningsTracker() {
|
|
231
|
+
trackerInstance = null;
|
|
232
|
+
}
|
|
@@ -36,3 +36,7 @@ export { retry, retryOrThrow, withTimeout, sleep, CircuitBreaker, RateLimiter, g
|
|
|
36
36
|
export type { RetryConfig, RetryResult, CircuitBreakerConfig, } from './retry.js';
|
|
37
37
|
export { DefiExecutor, getDefiExecutor, resetDefiExecutor, } from './defi-executor.js';
|
|
38
38
|
export type { DefiOperation, ProtocolConfig, ExecuteResult, } from './defi-executor.js';
|
|
39
|
+
export { PRPipeline, getPRPipeline, createPRPipeline, } from './pr-pipeline.js';
|
|
40
|
+
export type { PRSubmission, CodeChange, PRPipelineConfig, } from './pr-pipeline.js';
|
|
41
|
+
export { EarningsTracker, getEarningsTracker, resetEarningsTracker, } from './earnings-tracker.js';
|
|
42
|
+
export type { BountyAttempt, EarningsData, } from './earnings-tracker.js';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.retry = exports.usdToEth = exports.ethToUsd = exports.getEthPrice = exports.resetPriceFeed = exports.getPriceFeed = exports.installSignalHandlers = exports.getRecoveryInfo = exports.isEmergencyActive = exports.gracefulShutdown = exports.triggerEmergency = exports.getEmergencyManager = exports.resetPositionTracker = exports.getPositionTracker = exports.PositionTracker = exports.resetGasManager = exports.getGasManager = exports.GasManager = exports.getStatusLine = exports.isHealthy = exports.formatStatus = exports.getSystemStatus = exports.checkHealth = exports.createRevenueAlertHandler = exports.createBalanceAlertHandler = exports.resetAlertSystem = exports.getAlertSystem = exports.AlertSystem = exports.resetRevenueTracker = exports.getRevenueTracker = exports.RevenueTracker = exports.resetBalanceMonitor = exports.getBalanceMonitor = exports.BalanceMonitor = exports.createPaymentWatcher = exports.PaymentWatcher = exports.getPaymentVerifier = exports.PaymentVerifier = exports.getDefiConnector = exports.getCloudflareConnector = exports.getDeworkConnector = exports.StatePersistence = exports.resetStatePersistence = exports.getStatePersistence = exports.resetWallet = exports.getLiveWallet = exports.getBootResult = exports.isLive = exports.boot = exports.bootLiveEconomy = void 0;
|
|
10
|
-
exports.resetDefiExecutor = exports.getDefiExecutor = exports.DefiExecutor = exports.throttle = exports.debounce = exports.getRateLimiter = exports.getCircuitBreaker = exports.RateLimiter = exports.CircuitBreaker = exports.sleep = exports.withTimeout = exports.retryOrThrow = void 0;
|
|
10
|
+
exports.resetEarningsTracker = exports.getEarningsTracker = exports.EarningsTracker = exports.createPRPipeline = exports.getPRPipeline = exports.PRPipeline = exports.resetDefiExecutor = exports.getDefiExecutor = exports.DefiExecutor = exports.throttle = exports.debounce = exports.getRateLimiter = exports.getCircuitBreaker = exports.RateLimiter = exports.CircuitBreaker = exports.sleep = exports.withTimeout = exports.retryOrThrow = void 0;
|
|
11
11
|
// Boot sequence
|
|
12
12
|
var boot_js_1 = require("./boot.js");
|
|
13
13
|
Object.defineProperty(exports, "bootLiveEconomy", { enumerable: true, get: function () { return boot_js_1.bootLiveEconomy; } });
|
|
@@ -100,3 +100,13 @@ var defi_executor_js_1 = require("./defi-executor.js");
|
|
|
100
100
|
Object.defineProperty(exports, "DefiExecutor", { enumerable: true, get: function () { return defi_executor_js_1.DefiExecutor; } });
|
|
101
101
|
Object.defineProperty(exports, "getDefiExecutor", { enumerable: true, get: function () { return defi_executor_js_1.getDefiExecutor; } });
|
|
102
102
|
Object.defineProperty(exports, "resetDefiExecutor", { enumerable: true, get: function () { return defi_executor_js_1.resetDefiExecutor; } });
|
|
103
|
+
// v14.7: PR Pipeline for bounty submissions
|
|
104
|
+
var pr_pipeline_js_1 = require("./pr-pipeline.js");
|
|
105
|
+
Object.defineProperty(exports, "PRPipeline", { enumerable: true, get: function () { return pr_pipeline_js_1.PRPipeline; } });
|
|
106
|
+
Object.defineProperty(exports, "getPRPipeline", { enumerable: true, get: function () { return pr_pipeline_js_1.getPRPipeline; } });
|
|
107
|
+
Object.defineProperty(exports, "createPRPipeline", { enumerable: true, get: function () { return pr_pipeline_js_1.createPRPipeline; } });
|
|
108
|
+
// v14.7: Earnings Tracker for revenue persistence
|
|
109
|
+
var earnings_tracker_js_1 = require("./earnings-tracker.js");
|
|
110
|
+
Object.defineProperty(exports, "EarningsTracker", { enumerable: true, get: function () { return earnings_tracker_js_1.EarningsTracker; } });
|
|
111
|
+
Object.defineProperty(exports, "getEarningsTracker", { enumerable: true, get: function () { return earnings_tracker_js_1.getEarningsTracker; } });
|
|
112
|
+
Object.defineProperty(exports, "resetEarningsTracker", { enumerable: true, get: function () { return earnings_tracker_js_1.resetEarningsTracker; } });
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis v14.7 — PR Submission Pipeline
|
|
3
|
+
*
|
|
4
|
+
* Autonomous workflow to complete bounties:
|
|
5
|
+
* 1. Fork repository
|
|
6
|
+
* 2. Create branch
|
|
7
|
+
* 3. Generate/apply code changes
|
|
8
|
+
* 4. Submit PR with formatted description
|
|
9
|
+
* 5. Monitor for review feedback
|
|
10
|
+
*
|
|
11
|
+
* Uses GitHub MCP for all git operations.
|
|
12
|
+
*/
|
|
13
|
+
import type { Bounty } from '../generators/bounty-hunter.js';
|
|
14
|
+
export interface PRSubmission {
|
|
15
|
+
bountyId: string;
|
|
16
|
+
prUrl: string;
|
|
17
|
+
prNumber: number;
|
|
18
|
+
repo: string;
|
|
19
|
+
branch: string;
|
|
20
|
+
status: 'submitted' | 'reviewing' | 'changes_requested' | 'merged' | 'closed';
|
|
21
|
+
submittedAt: Date;
|
|
22
|
+
lastChecked?: Date;
|
|
23
|
+
feedback?: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface CodeChange {
|
|
26
|
+
path: string;
|
|
27
|
+
content: string;
|
|
28
|
+
operation: 'create' | 'update' | 'delete';
|
|
29
|
+
}
|
|
30
|
+
export interface PRPipelineConfig {
|
|
31
|
+
githubUsername: string;
|
|
32
|
+
prTitlePrefix?: string;
|
|
33
|
+
autoPush?: boolean;
|
|
34
|
+
dryRun?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare class PRPipeline {
|
|
37
|
+
private mcp;
|
|
38
|
+
private config;
|
|
39
|
+
private submissions;
|
|
40
|
+
constructor(config: PRPipelineConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Execute the full bounty completion pipeline
|
|
43
|
+
*/
|
|
44
|
+
submitBounty(bounty: Bounty, changes: CodeChange[], description: string): Promise<PRSubmission | null>;
|
|
45
|
+
private forkRepository;
|
|
46
|
+
private createBranch;
|
|
47
|
+
private applyChange;
|
|
48
|
+
private createPullRequest;
|
|
49
|
+
/**
|
|
50
|
+
* Check status of submitted PRs
|
|
51
|
+
*/
|
|
52
|
+
checkPRStatus(bountyId: string): Promise<PRSubmission | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Check all submitted PRs
|
|
55
|
+
*/
|
|
56
|
+
checkAllPRs(): Promise<PRSubmission[]>;
|
|
57
|
+
private generateBranchName;
|
|
58
|
+
private generatePRTitle;
|
|
59
|
+
private generatePRBody;
|
|
60
|
+
getSubmission(bountyId: string): PRSubmission | undefined;
|
|
61
|
+
getAllSubmissions(): PRSubmission[];
|
|
62
|
+
getStats(): {
|
|
63
|
+
total: number;
|
|
64
|
+
submitted: number;
|
|
65
|
+
reviewing: number;
|
|
66
|
+
merged: number;
|
|
67
|
+
closed: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export declare function getPRPipeline(config?: PRPipelineConfig): PRPipeline;
|
|
71
|
+
export declare function createPRPipeline(config: PRPipelineConfig): PRPipeline;
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis v14.7 — PR Submission Pipeline
|
|
4
|
+
*
|
|
5
|
+
* Autonomous workflow to complete bounties:
|
|
6
|
+
* 1. Fork repository
|
|
7
|
+
* 2. Create branch
|
|
8
|
+
* 3. Generate/apply code changes
|
|
9
|
+
* 4. Submit PR with formatted description
|
|
10
|
+
* 5. Monitor for review feedback
|
|
11
|
+
*
|
|
12
|
+
* Uses GitHub MCP for all git operations.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PRPipeline = void 0;
|
|
16
|
+
exports.getPRPipeline = getPRPipeline;
|
|
17
|
+
exports.createPRPipeline = createPRPipeline;
|
|
18
|
+
const index_js_1 = require("../../mcp/index.js");
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// PR Pipeline
|
|
21
|
+
// ============================================================================
|
|
22
|
+
class PRPipeline {
|
|
23
|
+
mcp = (0, index_js_1.getMCPClient)();
|
|
24
|
+
config;
|
|
25
|
+
submissions = new Map();
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.config = {
|
|
28
|
+
prTitlePrefix: config.prTitlePrefix ?? '[Genesis]',
|
|
29
|
+
autoPush: config.autoPush ?? true,
|
|
30
|
+
dryRun: config.dryRun ?? false,
|
|
31
|
+
...config,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// ==========================================================================
|
|
35
|
+
// Main Pipeline
|
|
36
|
+
// ==========================================================================
|
|
37
|
+
/**
|
|
38
|
+
* Execute the full bounty completion pipeline
|
|
39
|
+
*/
|
|
40
|
+
async submitBounty(bounty, changes, description) {
|
|
41
|
+
const meta = bounty.sourceMetadata;
|
|
42
|
+
if (!meta?.org || !meta?.repo) {
|
|
43
|
+
console.error('[PRPipeline] Bounty missing source metadata:', bounty.id);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const owner = meta.org;
|
|
47
|
+
const repo = meta.repo;
|
|
48
|
+
const branchName = this.generateBranchName(bounty);
|
|
49
|
+
console.log(`[PRPipeline] Starting submission for: ${bounty.title}`);
|
|
50
|
+
console.log(`[PRPipeline] Target: ${owner}/${repo}`);
|
|
51
|
+
try {
|
|
52
|
+
// Step 1: Fork the repository
|
|
53
|
+
console.log('[PRPipeline] Step 1: Forking repository...');
|
|
54
|
+
const forkResult = await this.forkRepository(owner, repo);
|
|
55
|
+
if (!forkResult.success) {
|
|
56
|
+
console.error('[PRPipeline] Fork failed:', forkResult.error);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
// Step 2: Create branch
|
|
60
|
+
console.log(`[PRPipeline] Step 2: Creating branch ${branchName}...`);
|
|
61
|
+
const branchResult = await this.createBranch(this.config.githubUsername, repo, branchName);
|
|
62
|
+
if (!branchResult.success) {
|
|
63
|
+
console.error('[PRPipeline] Branch creation failed:', branchResult.error);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
// Step 3: Apply changes
|
|
67
|
+
console.log(`[PRPipeline] Step 3: Applying ${changes.length} changes...`);
|
|
68
|
+
for (const change of changes) {
|
|
69
|
+
const changeResult = await this.applyChange(this.config.githubUsername, repo, branchName, change);
|
|
70
|
+
if (!changeResult.success) {
|
|
71
|
+
console.error(`[PRPipeline] Failed to apply change to ${change.path}:`, changeResult.error);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Step 4: Create PR
|
|
76
|
+
console.log('[PRPipeline] Step 4: Creating pull request...');
|
|
77
|
+
const prTitle = this.generatePRTitle(bounty);
|
|
78
|
+
const prBody = this.generatePRBody(bounty, description);
|
|
79
|
+
const prResult = await this.createPullRequest(owner, repo, prTitle, prBody, `${this.config.githubUsername}:${branchName}`, 'main');
|
|
80
|
+
if (!prResult.success || !prResult.data) {
|
|
81
|
+
console.error('[PRPipeline] PR creation failed:', prResult.error);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
// Record submission
|
|
85
|
+
const submission = {
|
|
86
|
+
bountyId: bounty.id,
|
|
87
|
+
prUrl: prResult.data.url,
|
|
88
|
+
prNumber: prResult.data.number,
|
|
89
|
+
repo: `${owner}/${repo}`,
|
|
90
|
+
branch: branchName,
|
|
91
|
+
status: 'submitted',
|
|
92
|
+
submittedAt: new Date(),
|
|
93
|
+
};
|
|
94
|
+
this.submissions.set(bounty.id, submission);
|
|
95
|
+
console.log(`[PRPipeline] ✅ PR submitted: ${submission.prUrl}`);
|
|
96
|
+
return submission;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
console.error('[PRPipeline] Pipeline error:', error);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// ==========================================================================
|
|
104
|
+
// GitHub Operations via MCP
|
|
105
|
+
// ==========================================================================
|
|
106
|
+
async forkRepository(owner, repo) {
|
|
107
|
+
if (this.config.dryRun) {
|
|
108
|
+
console.log(`[PRPipeline] [DRY RUN] Would fork ${owner}/${repo}`);
|
|
109
|
+
return { success: true };
|
|
110
|
+
}
|
|
111
|
+
const result = await this.mcp.call('github', 'fork_repository', {
|
|
112
|
+
owner,
|
|
113
|
+
repo,
|
|
114
|
+
});
|
|
115
|
+
if (!result.success) {
|
|
116
|
+
// Fork might already exist, try to continue
|
|
117
|
+
if (result.error?.includes('already exists')) {
|
|
118
|
+
return { success: true };
|
|
119
|
+
}
|
|
120
|
+
return { success: false, error: result.error };
|
|
121
|
+
}
|
|
122
|
+
return { success: true };
|
|
123
|
+
}
|
|
124
|
+
async createBranch(owner, repo, branchName) {
|
|
125
|
+
if (this.config.dryRun) {
|
|
126
|
+
console.log(`[PRPipeline] [DRY RUN] Would create branch ${branchName}`);
|
|
127
|
+
return { success: true };
|
|
128
|
+
}
|
|
129
|
+
// First get the default branch SHA
|
|
130
|
+
const repoResult = await this.mcp.call('github', 'get_file_contents', {
|
|
131
|
+
owner,
|
|
132
|
+
repo,
|
|
133
|
+
path: '',
|
|
134
|
+
});
|
|
135
|
+
// Create branch from main
|
|
136
|
+
const result = await this.mcp.call('github', 'create_branch', {
|
|
137
|
+
owner,
|
|
138
|
+
repo,
|
|
139
|
+
branch: branchName,
|
|
140
|
+
from_branch: 'main',
|
|
141
|
+
});
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
// Branch might already exist
|
|
144
|
+
if (result.error?.includes('already exists')) {
|
|
145
|
+
return { success: true };
|
|
146
|
+
}
|
|
147
|
+
return { success: false, error: result.error };
|
|
148
|
+
}
|
|
149
|
+
return { success: true };
|
|
150
|
+
}
|
|
151
|
+
async applyChange(owner, repo, branch, change) {
|
|
152
|
+
if (this.config.dryRun) {
|
|
153
|
+
console.log(`[PRPipeline] [DRY RUN] Would ${change.operation} ${change.path}`);
|
|
154
|
+
return { success: true };
|
|
155
|
+
}
|
|
156
|
+
const result = await this.mcp.call('github', 'create_or_update_file', {
|
|
157
|
+
owner,
|
|
158
|
+
repo,
|
|
159
|
+
path: change.path,
|
|
160
|
+
content: change.content,
|
|
161
|
+
message: `[Genesis] ${change.operation}: ${change.path}`,
|
|
162
|
+
branch,
|
|
163
|
+
});
|
|
164
|
+
if (!result.success) {
|
|
165
|
+
return { success: false, error: result.error };
|
|
166
|
+
}
|
|
167
|
+
return { success: true };
|
|
168
|
+
}
|
|
169
|
+
async createPullRequest(owner, repo, title, body, head, base) {
|
|
170
|
+
if (this.config.dryRun) {
|
|
171
|
+
console.log(`[PRPipeline] [DRY RUN] Would create PR: ${title}`);
|
|
172
|
+
return { success: true, data: { url: 'https://github.com/dry-run', number: 0 } };
|
|
173
|
+
}
|
|
174
|
+
const result = await this.mcp.call('github', 'create_pull_request', {
|
|
175
|
+
owner,
|
|
176
|
+
repo,
|
|
177
|
+
title,
|
|
178
|
+
body,
|
|
179
|
+
head,
|
|
180
|
+
base,
|
|
181
|
+
});
|
|
182
|
+
if (!result.success) {
|
|
183
|
+
return { success: false, error: result.error };
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
success: true,
|
|
187
|
+
data: {
|
|
188
|
+
url: result.data?.html_url || result.data?.url,
|
|
189
|
+
number: result.data?.number,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// ==========================================================================
|
|
194
|
+
// PR Monitoring
|
|
195
|
+
// ==========================================================================
|
|
196
|
+
/**
|
|
197
|
+
* Check status of submitted PRs
|
|
198
|
+
*/
|
|
199
|
+
async checkPRStatus(bountyId) {
|
|
200
|
+
const submission = this.submissions.get(bountyId);
|
|
201
|
+
if (!submission)
|
|
202
|
+
return null;
|
|
203
|
+
const [owner, repo] = submission.repo.split('/');
|
|
204
|
+
const result = await this.mcp.call('github', 'get_pull_request', {
|
|
205
|
+
owner,
|
|
206
|
+
repo,
|
|
207
|
+
pull_number: submission.prNumber,
|
|
208
|
+
});
|
|
209
|
+
if (!result.success) {
|
|
210
|
+
console.warn(`[PRPipeline] Failed to check PR status:`, result.error);
|
|
211
|
+
return submission;
|
|
212
|
+
}
|
|
213
|
+
const pr = result.data;
|
|
214
|
+
// Update status based on PR state
|
|
215
|
+
if (pr.merged) {
|
|
216
|
+
submission.status = 'merged';
|
|
217
|
+
}
|
|
218
|
+
else if (pr.state === 'closed') {
|
|
219
|
+
submission.status = 'closed';
|
|
220
|
+
}
|
|
221
|
+
else if (pr.review_comments > 0 || pr.requested_changes) {
|
|
222
|
+
submission.status = 'changes_requested';
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
submission.status = 'reviewing';
|
|
226
|
+
}
|
|
227
|
+
submission.lastChecked = new Date();
|
|
228
|
+
// Get review comments
|
|
229
|
+
const commentsResult = await this.mcp.call('github', 'get_pull_request_comments', {
|
|
230
|
+
owner,
|
|
231
|
+
repo,
|
|
232
|
+
pull_number: submission.prNumber,
|
|
233
|
+
});
|
|
234
|
+
if (commentsResult.success && commentsResult.data) {
|
|
235
|
+
submission.feedback = commentsResult.data.map((c) => c.body).slice(-5);
|
|
236
|
+
}
|
|
237
|
+
return submission;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Check all submitted PRs
|
|
241
|
+
*/
|
|
242
|
+
async checkAllPRs() {
|
|
243
|
+
const updated = [];
|
|
244
|
+
for (const [bountyId] of this.submissions) {
|
|
245
|
+
const result = await this.checkPRStatus(bountyId);
|
|
246
|
+
if (result) {
|
|
247
|
+
updated.push(result);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return updated;
|
|
251
|
+
}
|
|
252
|
+
// ==========================================================================
|
|
253
|
+
// Helpers
|
|
254
|
+
// ==========================================================================
|
|
255
|
+
generateBranchName(bounty) {
|
|
256
|
+
const slug = bounty.title
|
|
257
|
+
.toLowerCase()
|
|
258
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
259
|
+
.slice(0, 40);
|
|
260
|
+
const timestamp = Date.now().toString(36);
|
|
261
|
+
return `genesis/${slug}-${timestamp}`;
|
|
262
|
+
}
|
|
263
|
+
generatePRTitle(bounty) {
|
|
264
|
+
return `${this.config.prTitlePrefix} ${bounty.title}`;
|
|
265
|
+
}
|
|
266
|
+
generatePRBody(bounty, description) {
|
|
267
|
+
const meta = bounty.sourceMetadata;
|
|
268
|
+
const issueRef = meta?.issueNumber ? `\n\nCloses #${meta.issueNumber}` : '';
|
|
269
|
+
return `## Summary
|
|
270
|
+
|
|
271
|
+
${description}
|
|
272
|
+
|
|
273
|
+
## Related Issue
|
|
274
|
+
|
|
275
|
+
${bounty.submissionUrl || 'N/A'}${issueRef}
|
|
276
|
+
|
|
277
|
+
## Changes
|
|
278
|
+
|
|
279
|
+
This PR was generated autonomously by Genesis AI to complete a bounty.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
🤖 *Generated by [Genesis AI](https://github.com/rossignoliluca/genesis) v14.7*
|
|
284
|
+
`;
|
|
285
|
+
}
|
|
286
|
+
// ==========================================================================
|
|
287
|
+
// State Access
|
|
288
|
+
// ==========================================================================
|
|
289
|
+
getSubmission(bountyId) {
|
|
290
|
+
return this.submissions.get(bountyId);
|
|
291
|
+
}
|
|
292
|
+
getAllSubmissions() {
|
|
293
|
+
return [...this.submissions.values()];
|
|
294
|
+
}
|
|
295
|
+
getStats() {
|
|
296
|
+
const all = this.getAllSubmissions();
|
|
297
|
+
return {
|
|
298
|
+
total: all.length,
|
|
299
|
+
submitted: all.filter(s => s.status === 'submitted').length,
|
|
300
|
+
reviewing: all.filter(s => s.status === 'reviewing').length,
|
|
301
|
+
merged: all.filter(s => s.status === 'merged').length,
|
|
302
|
+
closed: all.filter(s => s.status === 'closed').length,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
exports.PRPipeline = PRPipeline;
|
|
307
|
+
// ============================================================================
|
|
308
|
+
// Factory
|
|
309
|
+
// ============================================================================
|
|
310
|
+
let pipelineInstance = null;
|
|
311
|
+
function getPRPipeline(config) {
|
|
312
|
+
if (!pipelineInstance && config) {
|
|
313
|
+
pipelineInstance = new PRPipeline(config);
|
|
314
|
+
}
|
|
315
|
+
if (!pipelineInstance) {
|
|
316
|
+
throw new Error('PRPipeline not initialized. Call with config first.');
|
|
317
|
+
}
|
|
318
|
+
return pipelineInstance;
|
|
319
|
+
}
|
|
320
|
+
function createPRPipeline(config) {
|
|
321
|
+
return new PRPipeline(config);
|
|
322
|
+
}
|
package/dist/src/index.js
CHANGED
|
@@ -576,7 +576,17 @@ async function cmdMCP(subcommand, options) {
|
|
|
576
576
|
});
|
|
577
577
|
console.log(` Name: ${options.name || 'genesis'}`);
|
|
578
578
|
console.log(` Transport: stdio`);
|
|
579
|
-
console.log(` Tools
|
|
579
|
+
console.log(` Tools:`);
|
|
580
|
+
console.log(` ${c('genesis.chat', 'cyan')} - Multi-model AI chat with auto-routing`);
|
|
581
|
+
console.log(` ${c('genesis.research', 'cyan')} - Deep research using 20+ MCP sources`);
|
|
582
|
+
console.log(` ${c('genesis.analyze', 'cyan')} - Code/data analysis`);
|
|
583
|
+
console.log(` ${c('genesis.think', 'cyan')} - Deep reasoning with multi-mind synthesis`);
|
|
584
|
+
console.log(` ${c('genesis.create', 'cyan')} - Code/content generation`);
|
|
585
|
+
console.log(` ${c('genesis.remember', 'cyan')} - Memory operations`);
|
|
586
|
+
console.log(` ${c('genesis.execute', 'cyan')} - Autonomous task execution`);
|
|
587
|
+
console.log('');
|
|
588
|
+
console.log(c('To add to Claude Code:', 'dim'));
|
|
589
|
+
console.log(c(' claude mcp add genesis -- npx genesis-ai-cli mcp-server', 'yellow'));
|
|
580
590
|
console.log('');
|
|
581
591
|
console.log(c('Server starting... (Ctrl+C to stop)', 'dim'));
|
|
582
592
|
await server.start();
|
|
@@ -1698,6 +1708,93 @@ ${c('Examples:', 'cyan')}
|
|
|
1698
1708
|
}
|
|
1699
1709
|
}
|
|
1700
1710
|
// ============================================================================
|
|
1711
|
+
// Bounty Command (v14.7: Autonomous Bounty Hunting)
|
|
1712
|
+
// ============================================================================
|
|
1713
|
+
async function cmdBounty(subcommand, options) {
|
|
1714
|
+
const { getBountyHunter } = await import('./economy/generators/bounty-hunter.js');
|
|
1715
|
+
const { getEarningsTracker } = await import('./economy/live/earnings-tracker.js');
|
|
1716
|
+
const hunter = getBountyHunter();
|
|
1717
|
+
const earnings = getEarningsTracker();
|
|
1718
|
+
switch (subcommand) {
|
|
1719
|
+
case 'scan':
|
|
1720
|
+
// Scan for new bounties
|
|
1721
|
+
console.log(c('Scanning for bounties...', 'cyan'));
|
|
1722
|
+
const discovered = await hunter.scan();
|
|
1723
|
+
console.log(`Found ${discovered.length} new bounties:`);
|
|
1724
|
+
discovered.slice(0, 10).forEach((b, i) => {
|
|
1725
|
+
console.log(` ${i + 1}. [$${b.reward}] ${b.title.slice(0, 50)} (${b.platform})`);
|
|
1726
|
+
});
|
|
1727
|
+
break;
|
|
1728
|
+
case 'list':
|
|
1729
|
+
// List cached bounties
|
|
1730
|
+
const stats = hunter.getStats();
|
|
1731
|
+
console.log(c('Bounty Statistics:', 'cyan'));
|
|
1732
|
+
console.log(` Discovered: ${stats.bountiesDiscovered}`);
|
|
1733
|
+
console.log(` Claimed: ${stats.bountiesClaimed}`);
|
|
1734
|
+
console.log(` Submitted: ${stats.bountiesSubmitted}`);
|
|
1735
|
+
console.log(` Accepted: ${stats.bountiesAccepted}`);
|
|
1736
|
+
console.log(` Success Rate: ${(stats.successRate * 100).toFixed(1)}%`);
|
|
1737
|
+
console.log(` Total Earned: $${stats.totalEarned.toFixed(2)}`);
|
|
1738
|
+
break;
|
|
1739
|
+
case 'earnings':
|
|
1740
|
+
// Show earnings summary
|
|
1741
|
+
const summary = earnings.getSummary();
|
|
1742
|
+
console.log(c('Earnings Summary:', 'cyan'));
|
|
1743
|
+
console.log(` Total Attempts: ${summary.totalAttempts}`);
|
|
1744
|
+
console.log(` Accepted: ${summary.totalAccepted}`);
|
|
1745
|
+
console.log(` Rejected: ${summary.totalRejected}`);
|
|
1746
|
+
console.log(` Total Earned: ${c('$' + summary.totalEarned.toFixed(2), 'green')}`);
|
|
1747
|
+
console.log(` Total Cost: $${summary.totalCost.toFixed(2)}`);
|
|
1748
|
+
console.log(` Net Profit: ${c('$' + summary.netProfit.toFixed(2), summary.netProfit >= 0 ? 'green' : 'red')}`);
|
|
1749
|
+
console.log(` Success Rate: ${(summary.successRate * 100).toFixed(1)}%`);
|
|
1750
|
+
console.log(` Best Bounty: $${summary.bestBounty.toFixed(2)}`);
|
|
1751
|
+
break;
|
|
1752
|
+
case 'select':
|
|
1753
|
+
// Select best bounty to work on
|
|
1754
|
+
const best = hunter.selectBest();
|
|
1755
|
+
if (best) {
|
|
1756
|
+
console.log(c('Best bounty to work on:', 'cyan'));
|
|
1757
|
+
console.log(` Title: ${best.title}`);
|
|
1758
|
+
console.log(` Reward: $${best.reward}`);
|
|
1759
|
+
console.log(` Platform: ${best.platform}`);
|
|
1760
|
+
console.log(` Category: ${best.category}`);
|
|
1761
|
+
console.log(` Difficulty: ${best.difficulty}`);
|
|
1762
|
+
console.log(` URL: ${best.submissionUrl || 'N/A'}`);
|
|
1763
|
+
}
|
|
1764
|
+
else {
|
|
1765
|
+
console.log('No suitable bounties found. Run "genesis bounty scan" first.');
|
|
1766
|
+
}
|
|
1767
|
+
break;
|
|
1768
|
+
case 'claim': {
|
|
1769
|
+
// Claim a bounty (start working on it)
|
|
1770
|
+
const bountyId = options.id;
|
|
1771
|
+
if (!bountyId) {
|
|
1772
|
+
console.error('Usage: genesis bounty claim --id <bounty-id>');
|
|
1773
|
+
process.exit(1);
|
|
1774
|
+
}
|
|
1775
|
+
const claimed = await hunter.claim(bountyId);
|
|
1776
|
+
if (claimed) {
|
|
1777
|
+
console.log(c('Bounty claimed! Start working on it.', 'green'));
|
|
1778
|
+
}
|
|
1779
|
+
else {
|
|
1780
|
+
console.error('Failed to claim bounty. Check the ID.');
|
|
1781
|
+
}
|
|
1782
|
+
break;
|
|
1783
|
+
}
|
|
1784
|
+
default:
|
|
1785
|
+
console.log(c('Genesis Bounty Hunter', 'cyan'));
|
|
1786
|
+
console.log('');
|
|
1787
|
+
console.log('Usage:');
|
|
1788
|
+
console.log(' genesis bounty scan Scan for new bounties');
|
|
1789
|
+
console.log(' genesis bounty list Show bounty statistics');
|
|
1790
|
+
console.log(' genesis bounty earnings Show earnings summary');
|
|
1791
|
+
console.log(' genesis bounty select Select best bounty to work on');
|
|
1792
|
+
console.log(' genesis bounty claim --id <id> Claim a bounty');
|
|
1793
|
+
console.log('');
|
|
1794
|
+
console.log('Supported platforms: Algora, GitHub, Gitcoin, DeWork');
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
// ============================================================================
|
|
1701
1798
|
// Agents Command (v10.4.2: Parallel Agent Execution)
|
|
1702
1799
|
// ============================================================================
|
|
1703
1800
|
async function cmdAgents(subcommand, options) {
|
|
@@ -2012,6 +2109,11 @@ async function main() {
|
|
|
2012
2109
|
case 'mcp':
|
|
2013
2110
|
await cmdMCP(positional, options);
|
|
2014
2111
|
break;
|
|
2112
|
+
case 'mcp-server':
|
|
2113
|
+
// v14.7: Alias for `mcp serve` - easier for Claude Code installation
|
|
2114
|
+
// Usage: npx genesis-ai-cli mcp-server
|
|
2115
|
+
await cmdMCP('serve', options);
|
|
2116
|
+
break;
|
|
2015
2117
|
case 'daemon':
|
|
2016
2118
|
await cmdDaemon(positional, options);
|
|
2017
2119
|
break;
|
|
@@ -2057,6 +2159,10 @@ async function main() {
|
|
|
2057
2159
|
// v14.2: Agentic chat interface with Claude Code-like capabilities
|
|
2058
2160
|
await cmdAgentic(positional, options);
|
|
2059
2161
|
break;
|
|
2162
|
+
case 'bounty':
|
|
2163
|
+
// v14.7: Autonomous bounty hunting
|
|
2164
|
+
await cmdBounty(positional, options);
|
|
2165
|
+
break;
|
|
2060
2166
|
default:
|
|
2061
2167
|
console.error(c(`Unknown command: ${command}`, 'red'));
|
|
2062
2168
|
console.log('Use "genesis help" for usage information');
|
|
@@ -78,6 +78,8 @@ export declare class GenesisMCPServer extends EventEmitter {
|
|
|
78
78
|
private handleExecute;
|
|
79
79
|
private handleAnalyze;
|
|
80
80
|
private handleCreate;
|
|
81
|
+
private handleChat;
|
|
82
|
+
private handleResearch;
|
|
81
83
|
private executeTool;
|
|
82
84
|
start(): Promise<void>;
|
|
83
85
|
stop(): Promise<void>;
|
|
@@ -547,6 +547,40 @@ class GenesisMCPServer extends events_1.EventEmitter {
|
|
|
547
547
|
annotations: { readOnlyHint: true },
|
|
548
548
|
handler: this.handleCreate.bind(this),
|
|
549
549
|
});
|
|
550
|
+
// v14.7: genesis.chat - Multi-model AI chat with automatic routing
|
|
551
|
+
this.registerTool({
|
|
552
|
+
name: 'genesis.chat',
|
|
553
|
+
description: 'Multi-model AI chat with automatic routing. Routes to cheapest/fastest/best model based on query complexity. Supports GPT-4, Claude, Gemini, Mistral, and local Ollama.',
|
|
554
|
+
inputSchema: zod_1.z.object({
|
|
555
|
+
prompt: zod_1.z.string().describe('User message to process'),
|
|
556
|
+
model: zod_1.z.enum(['auto', 'fast', 'smart', 'cheap', 'local']).optional().default('auto'),
|
|
557
|
+
systemPrompt: zod_1.z.string().optional().describe('Optional system prompt'),
|
|
558
|
+
maxTokens: zod_1.z.number().optional().default(2048),
|
|
559
|
+
}),
|
|
560
|
+
requiredScopes: ['chat'],
|
|
561
|
+
baseCost: 0.01,
|
|
562
|
+
supportsStreaming: true,
|
|
563
|
+
maxExecutionTime: 60000,
|
|
564
|
+
annotations: { readOnlyHint: true },
|
|
565
|
+
handler: this.handleChat.bind(this),
|
|
566
|
+
});
|
|
567
|
+
// v14.7: genesis.research - Deep research using 20+ MCP sources
|
|
568
|
+
this.registerTool({
|
|
569
|
+
name: 'genesis.research',
|
|
570
|
+
description: 'Deep research using 20+ MCP sources including arXiv, Semantic Scholar, Brave Search, Gemini, Exa, and more. Aggregates and synthesizes results.',
|
|
571
|
+
inputSchema: zod_1.z.object({
|
|
572
|
+
topic: zod_1.z.string().describe('Research topic or question'),
|
|
573
|
+
depth: zod_1.z.enum(['quick', 'standard', 'deep']).optional().default('standard'),
|
|
574
|
+
sources: zod_1.z.array(zod_1.z.string()).optional().describe('Specific sources to use (arxiv, semantic-scholar, brave, gemini, etc)'),
|
|
575
|
+
maxResults: zod_1.z.number().optional().default(10),
|
|
576
|
+
}),
|
|
577
|
+
requiredScopes: ['research'],
|
|
578
|
+
baseCost: 0.05,
|
|
579
|
+
supportsStreaming: false,
|
|
580
|
+
maxExecutionTime: 120000,
|
|
581
|
+
annotations: { readOnlyHint: true, longRunningHint: true },
|
|
582
|
+
handler: this.handleResearch.bind(this),
|
|
583
|
+
});
|
|
550
584
|
}
|
|
551
585
|
// ============================================================================
|
|
552
586
|
// v11.2: CompIntel + Revenue + Daemon Tools
|
|
@@ -1030,6 +1064,102 @@ class GenesisMCPServer extends events_1.EventEmitter {
|
|
|
1030
1064
|
return { success: false, error: String(error) };
|
|
1031
1065
|
}
|
|
1032
1066
|
}
|
|
1067
|
+
// v14.7: Chat handler with multi-model routing
|
|
1068
|
+
async handleChat(rawInput, ctx) {
|
|
1069
|
+
const input = rawInput;
|
|
1070
|
+
try {
|
|
1071
|
+
// Dynamic import to avoid circular dependencies
|
|
1072
|
+
const { getLLMBridge } = await import('../llm/index.js');
|
|
1073
|
+
const bridge = getLLMBridge();
|
|
1074
|
+
const response = await bridge.chat(input.prompt, input.systemPrompt);
|
|
1075
|
+
ctx.meter.recordTokens(input.prompt.length / 4, (response.content?.length || 0) / 4);
|
|
1076
|
+
const totalTokens = (response.usage?.inputTokens || 0) + (response.usage?.outputTokens || 0);
|
|
1077
|
+
return {
|
|
1078
|
+
success: true,
|
|
1079
|
+
data: {
|
|
1080
|
+
response: response.content || '',
|
|
1081
|
+
model: response.model || 'unknown',
|
|
1082
|
+
tokens: totalTokens,
|
|
1083
|
+
cost: 0, // Cost calculated separately
|
|
1084
|
+
},
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
catch (error) {
|
|
1088
|
+
return { success: false, error: String(error) };
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
// v14.7: Research handler using MCP sources
|
|
1092
|
+
async handleResearch(rawInput, ctx) {
|
|
1093
|
+
const input = rawInput;
|
|
1094
|
+
try {
|
|
1095
|
+
const { getMCPClient } = await import('../mcp/index.js');
|
|
1096
|
+
const mcp = getMCPClient();
|
|
1097
|
+
const findings = [];
|
|
1098
|
+
const usedSources = [];
|
|
1099
|
+
const defaultSources = input.sources || ['arxiv', 'brave', 'gemini'];
|
|
1100
|
+
const maxResults = input.maxResults || 10;
|
|
1101
|
+
// Quick depth = 1 source, standard = 3, deep = 5+
|
|
1102
|
+
const sourceCount = input.depth === 'quick' ? 1 : input.depth === 'deep' ? 5 : 3;
|
|
1103
|
+
const sourcesToUse = defaultSources.slice(0, sourceCount);
|
|
1104
|
+
for (const source of sourcesToUse) {
|
|
1105
|
+
try {
|
|
1106
|
+
let result;
|
|
1107
|
+
switch (source) {
|
|
1108
|
+
case 'arxiv':
|
|
1109
|
+
result = await mcp.call('arxiv', 'search_arxiv', { query: input.topic, max_results: maxResults });
|
|
1110
|
+
if (result.success && result.data) {
|
|
1111
|
+
findings.push(...(Array.isArray(result.data) ? result.data : [result.data]));
|
|
1112
|
+
usedSources.push('arxiv');
|
|
1113
|
+
}
|
|
1114
|
+
break;
|
|
1115
|
+
case 'semantic-scholar':
|
|
1116
|
+
result = await mcp.call('semantic-scholar', 'search_semantic_scholar', { query: input.topic, limit: maxResults });
|
|
1117
|
+
if (result.success && result.data) {
|
|
1118
|
+
findings.push(...(Array.isArray(result.data) ? result.data : [result.data]));
|
|
1119
|
+
usedSources.push('semantic-scholar');
|
|
1120
|
+
}
|
|
1121
|
+
break;
|
|
1122
|
+
case 'brave':
|
|
1123
|
+
result = await mcp.call('brave-search', 'brave_web_search', { query: input.topic, count: maxResults });
|
|
1124
|
+
if (result.success && result.data) {
|
|
1125
|
+
findings.push(...(Array.isArray(result.data) ? result.data : [result.data]));
|
|
1126
|
+
usedSources.push('brave-search');
|
|
1127
|
+
}
|
|
1128
|
+
break;
|
|
1129
|
+
case 'gemini':
|
|
1130
|
+
result = await mcp.call('gemini', 'web_search', { query: input.topic });
|
|
1131
|
+
if (result.success && result.data) {
|
|
1132
|
+
findings.push(result.data);
|
|
1133
|
+
usedSources.push('gemini');
|
|
1134
|
+
}
|
|
1135
|
+
break;
|
|
1136
|
+
case 'exa':
|
|
1137
|
+
result = await mcp.call('exa', 'web_search_exa', { query: input.topic, numResults: maxResults });
|
|
1138
|
+
if (result.success && result.data) {
|
|
1139
|
+
findings.push(...(Array.isArray(result.data) ? result.data : [result.data]));
|
|
1140
|
+
usedSources.push('exa');
|
|
1141
|
+
}
|
|
1142
|
+
break;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
catch (sourceError) {
|
|
1146
|
+
console.warn(`[Research] Source ${source} failed:`, sourceError);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
ctx.meter.recordTokens(input.topic.length / 4, findings.length * 100);
|
|
1150
|
+
return {
|
|
1151
|
+
success: true,
|
|
1152
|
+
data: {
|
|
1153
|
+
findings: findings.slice(0, maxResults),
|
|
1154
|
+
summary: `Found ${findings.length} results from ${usedSources.length} sources for "${input.topic}"`,
|
|
1155
|
+
sources: usedSources,
|
|
1156
|
+
},
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
catch (error) {
|
|
1160
|
+
return { success: false, error: String(error) };
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1033
1163
|
// ============================================================================
|
|
1034
1164
|
// Tool Execution Pipeline
|
|
1035
1165
|
// ============================================================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genesis-ai-cli",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.8.0",
|
|
4
4
|
"description": "Fully Autonomous AI System with RSI (Recursive Self-Improvement) - Self-funding, Self-deploying, Production Memory, A2A Protocol & Governance",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|