@wenrwa/marketplace-cli 0.2.0 → 0.4.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 +82 -7
- package/dist/__tests__/bridge-config-mcp.test.d.ts +1 -0
- package/dist/__tests__/bridge-config-mcp.test.js +117 -0
- package/dist/__tests__/bridge-server.test.d.ts +1 -0
- package/dist/__tests__/bridge-server.test.js +137 -0
- package/dist/__tests__/bridge-session-manager.test.d.ts +1 -0
- package/dist/__tests__/bridge-session-manager.test.js +104 -0
- package/dist/__tests__/config.test.js +3 -3
- package/dist/bridge/config.d.ts +11 -0
- package/dist/bridge/config.js +79 -0
- package/dist/bridge/mcpRegister.d.ts +28 -0
- package/dist/bridge/mcpRegister.js +35 -0
- package/dist/bridge/realPty.d.ts +2 -0
- package/dist/bridge/realPty.js +88 -0
- package/dist/bridge/server.d.ts +14 -0
- package/dist/bridge/server.js +182 -0
- package/dist/bridge/sessionManager.d.ts +42 -0
- package/dist/bridge/sessionManager.js +79 -0
- package/dist/commands/agent.js +98 -1
- package/dist/commands/apps.js +79 -0
- package/dist/commands/bounty.js +374 -7
- package/dist/commands/bridge.d.ts +3 -0
- package/dist/commands/bridge.js +122 -0
- package/dist/commands/credits.d.ts +2 -0
- package/dist/commands/credits.js +128 -0
- package/dist/commands/keys.d.ts +2 -0
- package/dist/commands/keys.js +72 -0
- package/dist/commands/prompts.d.ts +2 -0
- package/dist/commands/prompts.js +136 -0
- package/dist/commands/repo.d.ts +2 -0
- package/dist/commands/repo.js +197 -0
- package/dist/commands/workspace.d.ts +1 -0
- package/dist/commands/workspace.js +294 -12
- package/dist/index.js +12 -1
- package/dist/utils/client.d.ts +1 -0
- package/dist/utils/client.js +3 -0
- package/dist/utils/config.js +3 -3
- package/package.json +10 -15
package/dist/commands/bounty.js
CHANGED
|
@@ -70,8 +70,15 @@ exports.bountyCommand
|
|
|
70
70
|
console.log(` Deliverable: ${labels[b.expected_deliverable_type] || b.expected_deliverable_type}`);
|
|
71
71
|
}
|
|
72
72
|
console.log(` Deadline: ${b.deadline || '—'}`);
|
|
73
|
+
if (b.bidding_ends_at) {
|
|
74
|
+
const biddingEnd = new Date(b.bidding_ends_at);
|
|
75
|
+
const isOpen = biddingEnd > new Date();
|
|
76
|
+
console.log(` Bidding ends: ${b.bidding_ends_at} ${isOpen ? chalk_1.default.green('(open)') : chalk_1.default.dim('(closed)')}`);
|
|
77
|
+
}
|
|
73
78
|
console.log(` Max retries: ${b.max_retries ?? 0}`);
|
|
74
79
|
console.log(` Retry count: ${b.retry_count ?? 0}`);
|
|
80
|
+
console.log(` Max revisions: ${b.max_revisions ?? 2}`);
|
|
81
|
+
console.log(` Revision count: ${b.revision_count ?? 0}`);
|
|
75
82
|
console.log(` Created: ${b.created_at}`);
|
|
76
83
|
if (b.blocked_by?.length) {
|
|
77
84
|
console.log(` Blocked by: ${b.blocked_by.join(', ')}`);
|
|
@@ -92,13 +99,32 @@ exports.bountyCommand
|
|
|
92
99
|
const bidData = await client.get(`/bounties/${bountyId}/bids`);
|
|
93
100
|
const bids = bidData.bids || [];
|
|
94
101
|
if (bids.length > 0) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
const hasBidding = !!b.bidding_ends_at;
|
|
103
|
+
(0, format_1.heading)(hasBidding ? `Bids (${bids.length}) — Ranked by value score` : 'Bids');
|
|
104
|
+
const headers = hasBidding
|
|
105
|
+
? ['#', 'Agent', 'Amount', 'Score', 'Rep', 'Status', 'Message']
|
|
106
|
+
: ['Agent', 'Amount', 'Status', 'Message'];
|
|
107
|
+
const rows = bids.map((bid, i) => {
|
|
108
|
+
const agent = bid.agent_name || (0, format_1.shorten)(bid.agent_wallet);
|
|
109
|
+
if (hasBidding) {
|
|
110
|
+
return [
|
|
111
|
+
String(i + 1),
|
|
112
|
+
agent,
|
|
113
|
+
(0, format_1.formatReward)(bid.amount || bid.bid_amount, b.reward_symbol),
|
|
114
|
+
bid.value_score != null ? bid.value_score.toFixed(1) : '—',
|
|
115
|
+
bid.weighted_reputation != null ? `${bid.weighted_reputation.toFixed(1)}/5` : '—',
|
|
116
|
+
(0, format_1.statusColor)(bid.status || 'pending'),
|
|
117
|
+
(bid.message || '').slice(0, 30),
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
return [
|
|
121
|
+
agent,
|
|
122
|
+
(0, format_1.formatReward)(bid.amount || bid.bid_amount, b.reward_symbol),
|
|
123
|
+
(0, format_1.statusColor)(bid.status || 'pending'),
|
|
124
|
+
(bid.message || '').slice(0, 40),
|
|
125
|
+
];
|
|
126
|
+
});
|
|
127
|
+
console.log((0, format_1.makeTable)(headers, rows));
|
|
102
128
|
}
|
|
103
129
|
}
|
|
104
130
|
catch {
|
|
@@ -109,6 +135,61 @@ exports.bountyCommand
|
|
|
109
135
|
(0, format_1.error)(err.message);
|
|
110
136
|
}
|
|
111
137
|
});
|
|
138
|
+
exports.bountyCommand
|
|
139
|
+
.command('bids')
|
|
140
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
141
|
+
.description('List bids on a bounty with agent stats and value scores')
|
|
142
|
+
.action(async (bountyId) => {
|
|
143
|
+
try {
|
|
144
|
+
const client = (0, client_1.getClient)();
|
|
145
|
+
const [bountyData, bidData] = await Promise.all([
|
|
146
|
+
client.get(`/bounties/${bountyId}`),
|
|
147
|
+
client.get(`/bounties/${bountyId}/bids`),
|
|
148
|
+
]);
|
|
149
|
+
const b = bountyData.bounty;
|
|
150
|
+
const bids = bidData.bids || [];
|
|
151
|
+
if (bids.length === 0) {
|
|
152
|
+
console.log('No bids yet.');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const hasBidding = !!b.bidding_ends_at;
|
|
156
|
+
if (hasBidding) {
|
|
157
|
+
const biddingEnd = new Date(b.bidding_ends_at);
|
|
158
|
+
const isOpen = biddingEnd > new Date();
|
|
159
|
+
console.log(`${chalk_1.default.dim('Bidding deadline:')} ${b.bidding_ends_at} ${isOpen ? chalk_1.default.green('(open)') : chalk_1.default.dim('(closed)')}`);
|
|
160
|
+
console.log(`${chalk_1.default.dim('Reward (max budget):')} ${(0, format_1.formatReward)(b.reward_amount, b.reward_symbol)}\n`);
|
|
161
|
+
}
|
|
162
|
+
(0, format_1.heading)(`Bids (${bids.length})${hasBidding ? ' — Ranked by value score' : ''}`);
|
|
163
|
+
const headers = hasBidding
|
|
164
|
+
? ['#', 'Agent', 'Amount', 'Score', 'Reputation', 'Completed', 'Status', 'Message']
|
|
165
|
+
: ['Agent', 'Amount', 'Status', 'Message'];
|
|
166
|
+
const rows = bids.map((bid, i) => {
|
|
167
|
+
const agent = bid.agent_name || (0, format_1.shorten)(bid.agent_wallet);
|
|
168
|
+
if (hasBidding) {
|
|
169
|
+
return [
|
|
170
|
+
String(i + 1),
|
|
171
|
+
agent,
|
|
172
|
+
(0, format_1.formatReward)(bid.bid_amount || bid.amount, b.reward_symbol),
|
|
173
|
+
bid.value_score != null ? bid.value_score.toFixed(1) : '—',
|
|
174
|
+
bid.weighted_reputation != null ? `${bid.weighted_reputation.toFixed(1)}/5` : '—',
|
|
175
|
+
bid.completed_count != null ? String(bid.completed_count) : '—',
|
|
176
|
+
(0, format_1.statusColor)(bid.status || 'pending'),
|
|
177
|
+
(bid.message || '').slice(0, 35),
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
return [
|
|
181
|
+
agent,
|
|
182
|
+
(0, format_1.formatReward)(bid.bid_amount || bid.amount, b.reward_symbol),
|
|
183
|
+
(0, format_1.statusColor)(bid.status || 'pending'),
|
|
184
|
+
(bid.message || '').slice(0, 45),
|
|
185
|
+
];
|
|
186
|
+
});
|
|
187
|
+
console.log((0, format_1.makeTable)(headers, rows));
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
(0, format_1.error)(err.message);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
112
193
|
exports.bountyCommand
|
|
113
194
|
.command('progress')
|
|
114
195
|
.argument('<bounty-id>', 'Bounty ID')
|
|
@@ -188,6 +269,292 @@ exports.bountyCommand
|
|
|
188
269
|
(0, format_1.error)(err.message);
|
|
189
270
|
}
|
|
190
271
|
});
|
|
272
|
+
exports.bountyCommand
|
|
273
|
+
.command('estimate')
|
|
274
|
+
.description('Get an AI-powered USDC price estimate for a bounty description')
|
|
275
|
+
.requiredOption('--description <text>', 'Bounty description (min 50 chars)')
|
|
276
|
+
.option('--title <title>', 'Bounty title')
|
|
277
|
+
.option('--flow-type <type>', 'Flow type: hosted-app, code, or document')
|
|
278
|
+
.option('--framework <framework>', 'Framework (e.g. next, react, express)')
|
|
279
|
+
.action(async (opts) => {
|
|
280
|
+
try {
|
|
281
|
+
if (opts.description.length < 50) {
|
|
282
|
+
(0, format_1.error)('Description must be at least 50 characters');
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const client = (0, client_1.getClient)();
|
|
286
|
+
const body = { description: opts.description };
|
|
287
|
+
if (opts.title)
|
|
288
|
+
body.title = opts.title;
|
|
289
|
+
if (opts.flowType)
|
|
290
|
+
body.flowType = opts.flowType;
|
|
291
|
+
if (opts.framework)
|
|
292
|
+
body.framework = opts.framework;
|
|
293
|
+
const data = await client.post('/bounties/estimate', body);
|
|
294
|
+
(0, format_1.heading)('Bounty Price Estimate');
|
|
295
|
+
const dots = '●'.repeat(data.complexity) + '○'.repeat(5 - data.complexity);
|
|
296
|
+
console.log(` Range: ${chalk_1.default.green(`$${data.low}`)} – ${chalk_1.default.green(`$${data.high}`)} USDC`);
|
|
297
|
+
console.log(` Complexity: ${dots} (${data.complexity}/5)`);
|
|
298
|
+
console.log(` Reasoning: ${chalk_1.default.dim(data.reasoning)}`);
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
(0, format_1.error)(err.message);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
const CODE_CATEGORIES = ['code-review', 'bug-fix', 'feature', 'audit', 'testing', 'deployment'];
|
|
305
|
+
exports.bountyCommand
|
|
306
|
+
.command('create')
|
|
307
|
+
.description('Create a new bounty')
|
|
308
|
+
.requiredOption('--title <title>', 'Bounty title')
|
|
309
|
+
.requiredOption('--description <text>', 'Task description')
|
|
310
|
+
.requiredOption('--reward <amount>', 'Reward in USDC (e.g. "100")')
|
|
311
|
+
.option('--category <cat>', 'Category', 'feature')
|
|
312
|
+
.option('--deadline <date>', 'Deadline (ISO 8601)')
|
|
313
|
+
.option('--workspace <id>', 'Workspace ID')
|
|
314
|
+
.option('--repo-url <url>', 'GitHub repository URL (required for code categories)')
|
|
315
|
+
.option('--branch <branch>', 'Branch name')
|
|
316
|
+
.option('--file-paths <paths>', 'Comma-separated file paths')
|
|
317
|
+
.option('--issue-numbers <numbers>', 'Comma-separated issue numbers')
|
|
318
|
+
.action(async (opts) => {
|
|
319
|
+
try {
|
|
320
|
+
if (CODE_CATEGORIES.includes(opts.category) && !opts.repoUrl) {
|
|
321
|
+
(0, format_1.error)(`--repo-url is required for code category "${opts.category}"`);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const client = (0, client_1.getClient)();
|
|
325
|
+
const taskSchema = { instructions: opts.description };
|
|
326
|
+
if (opts.repoUrl) {
|
|
327
|
+
const github = { repoUrl: opts.repoUrl };
|
|
328
|
+
if (opts.branch)
|
|
329
|
+
github.branch = opts.branch;
|
|
330
|
+
if (opts.filePaths)
|
|
331
|
+
github.filePaths = opts.filePaths.split(',').map(s => s.trim()).filter(Boolean);
|
|
332
|
+
if (opts.issueNumbers)
|
|
333
|
+
github.issueNumbers = opts.issueNumbers.split(',').map(s => s.trim()).filter(Boolean);
|
|
334
|
+
taskSchema.github = github;
|
|
335
|
+
}
|
|
336
|
+
const body = {
|
|
337
|
+
title: opts.title,
|
|
338
|
+
category: opts.category,
|
|
339
|
+
taskSchema,
|
|
340
|
+
rewardAmount: String(Math.round(parseFloat(opts.reward) * 1e6)),
|
|
341
|
+
deadline: opts.deadline || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
342
|
+
};
|
|
343
|
+
if (opts.workspace)
|
|
344
|
+
body.workspaceId = opts.workspace;
|
|
345
|
+
const data = await client.post('/bounties', body);
|
|
346
|
+
(0, format_1.heading)('Bounty Created');
|
|
347
|
+
console.log(` ID: ${data.bounty.id}`);
|
|
348
|
+
console.log(` Title: ${data.bounty.title}`);
|
|
349
|
+
console.log(` Reward: ${(0, format_1.formatReward)(data.bounty.reward_amount, data.bounty.reward_symbol)}`);
|
|
350
|
+
console.log(` Status: ${(0, format_1.statusColor)(data.bounty.status)}`);
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
(0, format_1.error)(err.message);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
exports.bountyCommand
|
|
357
|
+
.command('cancel')
|
|
358
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
359
|
+
.description('Cancel an open bounty and refund escrow')
|
|
360
|
+
.action(async (bountyId) => {
|
|
361
|
+
try {
|
|
362
|
+
const client = (0, client_1.getClient)();
|
|
363
|
+
await client.del(`/bounties/${bountyId}`);
|
|
364
|
+
console.log(chalk_1.default.green('Bounty cancelled.'));
|
|
365
|
+
}
|
|
366
|
+
catch (err) {
|
|
367
|
+
(0, format_1.error)(err.message);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
exports.bountyCommand
|
|
371
|
+
.command('bid')
|
|
372
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
373
|
+
.requiredOption('--amount <amount>', 'Bid amount in USDC')
|
|
374
|
+
.option('--message <msg>', 'Bid message')
|
|
375
|
+
.description('Place a bid on a bounty')
|
|
376
|
+
.action(async (bountyId, opts) => {
|
|
377
|
+
try {
|
|
378
|
+
const client = (0, client_1.getClient)();
|
|
379
|
+
const body = { bidAmount: String(Math.round(parseFloat(opts.amount) * 1e6)) };
|
|
380
|
+
if (opts.message)
|
|
381
|
+
body.message = opts.message;
|
|
382
|
+
const data = await client.post(`/bounties/${bountyId}/bid`, body);
|
|
383
|
+
(0, format_1.heading)('Bid Placed');
|
|
384
|
+
console.log(` Bid ID: ${data.bid.id}`);
|
|
385
|
+
console.log(` Amount: ${opts.amount} USDC`);
|
|
386
|
+
}
|
|
387
|
+
catch (err) {
|
|
388
|
+
(0, format_1.error)(err.message);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
exports.bountyCommand
|
|
392
|
+
.command('accept-bid')
|
|
393
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
394
|
+
.requiredOption('--bid-id <id>', 'Bid ID to accept')
|
|
395
|
+
.description('Accept an agent bid')
|
|
396
|
+
.action(async (bountyId, opts) => {
|
|
397
|
+
try {
|
|
398
|
+
const client = (0, client_1.getClient)();
|
|
399
|
+
await client.post(`/bounties/${bountyId}/accept-bid`, { bidId: opts.bidId });
|
|
400
|
+
console.log(chalk_1.default.green('Bid accepted. Agent is now assigned.'));
|
|
401
|
+
}
|
|
402
|
+
catch (err) {
|
|
403
|
+
(0, format_1.error)(err.message);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
exports.bountyCommand
|
|
407
|
+
.command('submit')
|
|
408
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
409
|
+
.option('--result-hash <hash>', 'Result hash')
|
|
410
|
+
.option('--result-url <url>', 'Result URL')
|
|
411
|
+
.description('Submit completed work')
|
|
412
|
+
.action(async (bountyId, opts) => {
|
|
413
|
+
try {
|
|
414
|
+
const client = (0, client_1.getClient)();
|
|
415
|
+
const body = {};
|
|
416
|
+
if (opts.resultHash)
|
|
417
|
+
body.resultHash = opts.resultHash;
|
|
418
|
+
if (opts.resultUrl)
|
|
419
|
+
body.resultUrl = opts.resultUrl;
|
|
420
|
+
const data = await client.post(`/bounties/${bountyId}/submit`, body);
|
|
421
|
+
console.log(chalk_1.default.green(`Work submitted. Status: ${data.bounty.status}`));
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
(0, format_1.error)(err.message);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
exports.bountyCommand
|
|
428
|
+
.command('approve')
|
|
429
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
430
|
+
.description('Approve submitted work and release payment')
|
|
431
|
+
.action(async (bountyId) => {
|
|
432
|
+
try {
|
|
433
|
+
const client = (0, client_1.getClient)();
|
|
434
|
+
await client.post(`/bounties/${bountyId}/approve`, {});
|
|
435
|
+
console.log(chalk_1.default.green('Work approved. Payment released.'));
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
(0, format_1.error)(err.message);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
exports.bountyCommand
|
|
442
|
+
.command('dispute')
|
|
443
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
444
|
+
.requiredOption('--reason <reason>', 'Reason for the dispute')
|
|
445
|
+
.description('Dispute submitted work')
|
|
446
|
+
.action(async (bountyId, opts) => {
|
|
447
|
+
try {
|
|
448
|
+
const client = (0, client_1.getClient)();
|
|
449
|
+
await client.post(`/bounties/${bountyId}/dispute`, { reason: opts.reason });
|
|
450
|
+
console.log(chalk_1.default.green('Dispute filed.'));
|
|
451
|
+
}
|
|
452
|
+
catch (err) {
|
|
453
|
+
(0, format_1.error)(err.message);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
exports.bountyCommand
|
|
457
|
+
.command('revision')
|
|
458
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
459
|
+
.requiredOption('--reason <reason>', 'Feedback for the agent')
|
|
460
|
+
.description('Request a revision on submitted work')
|
|
461
|
+
.action(async (bountyId, opts) => {
|
|
462
|
+
try {
|
|
463
|
+
const client = (0, client_1.getClient)();
|
|
464
|
+
await client.post(`/bounties/${bountyId}/request-revision`, { feedback: opts.reason });
|
|
465
|
+
console.log(chalk_1.default.green('Revision requested.'));
|
|
466
|
+
}
|
|
467
|
+
catch (err) {
|
|
468
|
+
(0, format_1.error)(err.message);
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
exports.bountyCommand
|
|
472
|
+
.command('reassign')
|
|
473
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
474
|
+
.description('Unassign the current agent and reopen for bids')
|
|
475
|
+
.action(async (bountyId) => {
|
|
476
|
+
try {
|
|
477
|
+
const client = (0, client_1.getClient)();
|
|
478
|
+
await client.post(`/bounties/${bountyId}/reassign`, {});
|
|
479
|
+
console.log(chalk_1.default.green('Bounty reassigned. Open for new bids.'));
|
|
480
|
+
}
|
|
481
|
+
catch (err) {
|
|
482
|
+
(0, format_1.error)(err.message);
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
exports.bountyCommand
|
|
486
|
+
.command('extend')
|
|
487
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
488
|
+
.requiredOption('--deadline <date>', 'New deadline (ISO 8601)')
|
|
489
|
+
.description('Extend a bounty deadline')
|
|
490
|
+
.action(async (bountyId, opts) => {
|
|
491
|
+
try {
|
|
492
|
+
const client = (0, client_1.getClient)();
|
|
493
|
+
await client.post(`/bounties/${bountyId}/extend-deadline`, { newDeadline: opts.deadline });
|
|
494
|
+
console.log(chalk_1.default.green(`Deadline extended to ${opts.deadline}.`));
|
|
495
|
+
}
|
|
496
|
+
catch (err) {
|
|
497
|
+
(0, format_1.error)(err.message);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
exports.bountyCommand
|
|
501
|
+
.command('rate')
|
|
502
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
503
|
+
.requiredOption('--quality <n>', 'Quality score (1-5)')
|
|
504
|
+
.requiredOption('--speed <n>', 'Speed score (1-5)')
|
|
505
|
+
.requiredOption('--communication <n>', 'Communication score (1-5)')
|
|
506
|
+
.option('--review <text>', 'Written review')
|
|
507
|
+
.description('Rate an agent after bounty completion')
|
|
508
|
+
.action(async (bountyId, opts) => {
|
|
509
|
+
try {
|
|
510
|
+
const client = (0, client_1.getClient)();
|
|
511
|
+
const body = {
|
|
512
|
+
qualityScore: parseInt(opts.quality, 10),
|
|
513
|
+
speedScore: parseInt(opts.speed, 10),
|
|
514
|
+
communicationScore: parseInt(opts.communication, 10),
|
|
515
|
+
};
|
|
516
|
+
if (opts.review)
|
|
517
|
+
body.reviewText = opts.review;
|
|
518
|
+
await client.post(`/bounties/${bountyId}/rate`, body);
|
|
519
|
+
console.log(chalk_1.default.green('Rating submitted.'));
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
(0, format_1.error)(err.message);
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
exports.bountyCommand
|
|
526
|
+
.command('withdraw')
|
|
527
|
+
.argument('<bounty-id>', 'Bounty ID')
|
|
528
|
+
.description('Withdraw as the assigned agent')
|
|
529
|
+
.action(async (bountyId) => {
|
|
530
|
+
try {
|
|
531
|
+
const client = (0, client_1.getClient)();
|
|
532
|
+
await client.post(`/bounties/${bountyId}/withdraw-agent`, {});
|
|
533
|
+
console.log(chalk_1.default.green('Withdrawn from bounty.'));
|
|
534
|
+
}
|
|
535
|
+
catch (err) {
|
|
536
|
+
(0, format_1.error)(err.message);
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
exports.bountyCommand
|
|
540
|
+
.command('tip')
|
|
541
|
+
.argument('<wallet>', 'Agent wallet address')
|
|
542
|
+
.requiredOption('--amount <amount>', 'Tip amount in USDC')
|
|
543
|
+
.option('--message <msg>', 'Optional message')
|
|
544
|
+
.description('Send a USDC tip to an agent')
|
|
545
|
+
.action(async (wallet, opts) => {
|
|
546
|
+
try {
|
|
547
|
+
const client = (0, client_1.getClient)();
|
|
548
|
+
const body = { tipAmount: String(Math.round(parseFloat(opts.amount) * 1e6)) };
|
|
549
|
+
if (opts.message)
|
|
550
|
+
body.message = opts.message;
|
|
551
|
+
await client.post(`/agents/${wallet}/tip`, body);
|
|
552
|
+
console.log(chalk_1.default.green(`Tipped ${opts.amount} USDC to ${(0, format_1.shorten)(wallet)}.`));
|
|
553
|
+
}
|
|
554
|
+
catch (err) {
|
|
555
|
+
(0, format_1.error)(err.message);
|
|
556
|
+
}
|
|
557
|
+
});
|
|
191
558
|
function progressBar(pct) {
|
|
192
559
|
const filled = Math.round(pct / 5);
|
|
193
560
|
const empty = 20 - filled;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.bridgeCommand = exports.DEFAULT_BRIDGE_PORT = void 0;
|
|
40
|
+
/**
|
|
41
|
+
* bct-05 — `wen-market bridge`: the local Terminal Bridge.
|
|
42
|
+
*
|
|
43
|
+
* Hosts PTYs on the user's machine and serves them to the arena Terminal
|
|
44
|
+
* Pane over a loopback-only WebSocket. The user runs Claude Code themselves
|
|
45
|
+
* inside the terminal (their subscription, Anthropic's client) — this
|
|
46
|
+
* process never drives it (ADR-0028 in wenrwa-arena).
|
|
47
|
+
*/
|
|
48
|
+
const crypto = __importStar(require("crypto"));
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const child_process_1 = require("child_process");
|
|
51
|
+
const commander_1 = require("commander");
|
|
52
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
53
|
+
const sessionManager_1 = require("../bridge/sessionManager");
|
|
54
|
+
const server_1 = require("../bridge/server");
|
|
55
|
+
const realPty_1 = require("../bridge/realPty");
|
|
56
|
+
const config_1 = require("../bridge/config");
|
|
57
|
+
const mcpRegister_1 = require("../bridge/mcpRegister");
|
|
58
|
+
const config_2 = require("../utils/config");
|
|
59
|
+
exports.DEFAULT_BRIDGE_PORT = 8377;
|
|
60
|
+
const DEFAULT_ORIGIN = 'https://app.hiveop.io';
|
|
61
|
+
// Unlike the dev-oriented CLI default (localhost), bridge users are end users:
|
|
62
|
+
// the MCP registration must point at production unless explicitly overridden.
|
|
63
|
+
const DEFAULT_BRIDGE_API_URL = 'https://api.wenrwa.com/api/v1';
|
|
64
|
+
function bridgeApiUrl() {
|
|
65
|
+
return process.env.MARKETPLACE_API_URL || (0, config_2.loadConfig)()?.apiUrl || DEFAULT_BRIDGE_API_URL;
|
|
66
|
+
}
|
|
67
|
+
const execRunner = (cmd, args) => new Promise((resolve, reject) => {
|
|
68
|
+
(0, child_process_1.execFile)(cmd, args, (err, stdout) => {
|
|
69
|
+
if (err && !stdout)
|
|
70
|
+
reject(err);
|
|
71
|
+
else
|
|
72
|
+
resolve({ stdout: stdout ?? '', code: 0 });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
exports.bridgeCommand = new commander_1.Command('bridge')
|
|
76
|
+
.description('Run the local Terminal Bridge for the arena Terminal Pane (BYO Claude Code)')
|
|
77
|
+
.option('--token <connectToken>', 'Connect Token from arena settings (stored on first run, never logged)')
|
|
78
|
+
.option('--port <port>', 'port to listen on (loopback only)', String(exports.DEFAULT_BRIDGE_PORT))
|
|
79
|
+
.option('--origin <origin>', 'allowed browser origin', process.env.WENRWA_BRIDGE_ORIGIN || DEFAULT_ORIGIN)
|
|
80
|
+
.action(async (opts) => {
|
|
81
|
+
// 1. Connect Token: flag on first run, config thereafter.
|
|
82
|
+
if (opts.token) {
|
|
83
|
+
if (!opts.token.startsWith('wm_ct_')) {
|
|
84
|
+
console.error(chalk_1.default.red('That does not look like a Connect Token (wm_ct_…). Mint one in arena settings.'));
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
(0, config_1.saveBridgeConfig)({ connectToken: opts.token });
|
|
88
|
+
console.log(chalk_1.default.green('✓ Connect Token stored (~/.wen-market/bridge-config.json, 0600)'));
|
|
89
|
+
}
|
|
90
|
+
const config = (0, config_1.loadBridgeConfig)();
|
|
91
|
+
if (!config) {
|
|
92
|
+
console.error(chalk_1.default.red('No Connect Token. Run: wen-market bridge --token <wm_ct_…> (mint one in arena settings)'));
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
// 2. Idempotent MCP registration into the user's Claude Code — loud.
|
|
96
|
+
const mcp = await (0, mcpRegister_1.registerMcpServer)({
|
|
97
|
+
connectToken: config.connectToken,
|
|
98
|
+
apiUrl: bridgeApiUrl(),
|
|
99
|
+
run: execRunner,
|
|
100
|
+
// A token passed on the command line is fresh — replace any stale registration.
|
|
101
|
+
forceUpdate: Boolean(opts.token),
|
|
102
|
+
});
|
|
103
|
+
if (mcp.action === 'registered' || mcp.action === 're-registered')
|
|
104
|
+
console.log(chalk_1.default.green(`✓ ${mcp.action === 're-registered' ? 'Re-registered' : 'Registered'} MCP server: ${(0, mcpRegister_1.redactToken)(mcp.command ?? '')}`));
|
|
105
|
+
else if (mcp.action === 'already-registered')
|
|
106
|
+
console.log(chalk_1.default.dim('• wenrwa-marketplace MCP server already registered — skipped'));
|
|
107
|
+
else
|
|
108
|
+
console.log(chalk_1.default.yellow('! claude binary not found — bridge will run, but install Claude Code for MCP world-wiring'));
|
|
109
|
+
// 3. Serve.
|
|
110
|
+
const sessionToken = crypto.randomBytes(16).toString('hex');
|
|
111
|
+
const handle = await (0, server_1.startBridgeServer)({
|
|
112
|
+
sessionToken,
|
|
113
|
+
allowedOrigin: opts.origin,
|
|
114
|
+
sessions: new sessionManager_1.SessionManager((0, realPty_1.realPtyFactory)()),
|
|
115
|
+
port: Number(opts.port),
|
|
116
|
+
});
|
|
117
|
+
(0, config_1.writeDiscoveryFile)({ port: handle.port, sessionToken });
|
|
118
|
+
fs.appendFileSync((0, config_1.bridgeLogPath)(), `${new Date().toISOString()} bridge up on ${handle.address}:${handle.port}\n`);
|
|
119
|
+
console.log(chalk_1.default.cyan(`Terminal Bridge listening on ${handle.address}:${handle.port} (origin: ${opts.origin})`));
|
|
120
|
+
console.log(chalk_1.default.dim('Open your arena workspace and add a Terminal pane — it will connect automatically.'));
|
|
121
|
+
console.log(chalk_1.default.dim('Ctrl+C stops the bridge (terminal sessions end with it).'));
|
|
122
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.creditsCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const client_1 = require("../utils/client");
|
|
10
|
+
const format_1 = require("../utils/format");
|
|
11
|
+
exports.creditsCommand = new commander_1.Command('credits').description('Credits management');
|
|
12
|
+
exports.creditsCommand
|
|
13
|
+
.command('balance')
|
|
14
|
+
.description('Show your current credits balance')
|
|
15
|
+
.action(async () => {
|
|
16
|
+
try {
|
|
17
|
+
const client = (0, client_1.getClient)();
|
|
18
|
+
const data = await client.get('/me/hive/credits');
|
|
19
|
+
(0, format_1.heading)('Credits Balance');
|
|
20
|
+
console.log(` ${chalk_1.default.bold.yellow(data.balance.toLocaleString())} credits`);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
(0, format_1.error)(err.message);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
exports.creditsCommand
|
|
27
|
+
.command('history')
|
|
28
|
+
.description('Show recent credits transactions')
|
|
29
|
+
.option('--limit <n>', 'Max results', '20')
|
|
30
|
+
.option('--offset <n>', 'Pagination offset', '0')
|
|
31
|
+
.action(async (opts) => {
|
|
32
|
+
try {
|
|
33
|
+
const client = (0, client_1.getClient)();
|
|
34
|
+
const data = await client.get(`/me/hive/credits/history?limit=${opts.limit}&offset=${opts.offset}`);
|
|
35
|
+
const history = data.history || [];
|
|
36
|
+
if (history.length === 0) {
|
|
37
|
+
console.log('No credits transactions yet.');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log((0, format_1.makeTable)(['Type', 'Amount', 'Balance After', 'Reference', 'Date'], history.map((h) => [
|
|
41
|
+
h.type,
|
|
42
|
+
h.amount > 0
|
|
43
|
+
? chalk_1.default.green(`+${h.amount.toLocaleString()}`)
|
|
44
|
+
: chalk_1.default.red(h.amount.toLocaleString()),
|
|
45
|
+
h.balance_after?.toLocaleString() ?? '—',
|
|
46
|
+
h.reference_id ? h.reference_id.slice(0, 12) + '...' : '—',
|
|
47
|
+
h.created_at ? new Date(h.created_at).toLocaleString() : '—',
|
|
48
|
+
])));
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
(0, format_1.error)(err.message);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
exports.creditsCommand
|
|
55
|
+
.command('deposit')
|
|
56
|
+
.argument('<amount>', 'USDC amount to deposit')
|
|
57
|
+
.description('Deposit USDC for credits (gas-sponsored)')
|
|
58
|
+
.action(async (amountStr) => {
|
|
59
|
+
try {
|
|
60
|
+
const amount = parseFloat(amountStr);
|
|
61
|
+
if (isNaN(amount) || amount <= 0) {
|
|
62
|
+
(0, format_1.error)('Invalid amount. Must be a positive number.');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const client = (0, client_1.getClient)();
|
|
66
|
+
const data = await client.post('/me/hive/credits/deposit-tx', { amountUsdc: amount });
|
|
67
|
+
// Mock mode: credits added immediately
|
|
68
|
+
if (data.credits != null) {
|
|
69
|
+
(0, format_1.heading)('Credits Deposited (Mock Mode)');
|
|
70
|
+
console.log(` Credits: ${chalk_1.default.green(`+${data.credits.toLocaleString()}`)}`);
|
|
71
|
+
console.log(` Balance: ${chalk_1.default.yellow(data.balance.toLocaleString())}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Anchor mode: show transaction info
|
|
75
|
+
(0, format_1.heading)('Deposit Transaction Created');
|
|
76
|
+
console.log(` Deposit ID: ${data.depositId}`);
|
|
77
|
+
console.log(` Credits: ${data.creditsAmount.toLocaleString()}`);
|
|
78
|
+
console.log(` Expires: ${data.expiresAt}`);
|
|
79
|
+
console.log(` Sponsored: ${data.sponsoredTx ? chalk_1.default.green('Yes') : 'No'}`);
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log(chalk_1.default.dim('Sign the transaction with your wallet and submit:'));
|
|
82
|
+
console.log(chalk_1.default.dim(` wen-market credits confirm ${data.depositId} <tx-signature>`));
|
|
83
|
+
console.log('');
|
|
84
|
+
console.log(chalk_1.default.dim('Unsigned TX (base64):'));
|
|
85
|
+
console.log(chalk_1.default.dim(data.sponsoredTx || data.unsignedTx));
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
(0, format_1.error)(err.message);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
exports.creditsCommand
|
|
92
|
+
.command('confirm')
|
|
93
|
+
.argument('<deposit-id>', 'Deposit ID from deposit command')
|
|
94
|
+
.argument('<tx-signature>', 'Solana transaction signature')
|
|
95
|
+
.description('Confirm a credits deposit after signing')
|
|
96
|
+
.action(async (depositId, txSignature) => {
|
|
97
|
+
try {
|
|
98
|
+
const client = (0, client_1.getClient)();
|
|
99
|
+
const data = await client.post('/transactions/submit', {
|
|
100
|
+
depositId,
|
|
101
|
+
txSignature,
|
|
102
|
+
operationType: 'deposit_credits',
|
|
103
|
+
});
|
|
104
|
+
(0, format_1.heading)('Deposit Confirmed');
|
|
105
|
+
console.log(` Credits: ${chalk_1.default.green(`+${data.credits.toLocaleString()}`)}`);
|
|
106
|
+
console.log(` Balance: ${chalk_1.default.yellow(data.balance.toLocaleString())}`);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
(0, format_1.error)(err.message);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
exports.creditsCommand
|
|
113
|
+
.command('buy')
|
|
114
|
+
.argument('<tier>', 'Checkout tier (tier_1, tier_5, tier_20, tier_50)')
|
|
115
|
+
.description('Open Stripe checkout URL to purchase credits')
|
|
116
|
+
.action(async (tierId) => {
|
|
117
|
+
try {
|
|
118
|
+
const client = (0, client_1.getClient)();
|
|
119
|
+
const data = await client.post('/me/hive/credits/checkout', { tierId });
|
|
120
|
+
console.log(chalk_1.default.green('Checkout session created.'));
|
|
121
|
+
console.log(` URL: ${data.url}`);
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log(chalk_1.default.dim('Open this URL in a browser to complete the purchase.'));
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
(0, format_1.error)(err.message);
|
|
127
|
+
}
|
|
128
|
+
});
|