@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.
Files changed (38) hide show
  1. package/README.md +82 -7
  2. package/dist/__tests__/bridge-config-mcp.test.d.ts +1 -0
  3. package/dist/__tests__/bridge-config-mcp.test.js +117 -0
  4. package/dist/__tests__/bridge-server.test.d.ts +1 -0
  5. package/dist/__tests__/bridge-server.test.js +137 -0
  6. package/dist/__tests__/bridge-session-manager.test.d.ts +1 -0
  7. package/dist/__tests__/bridge-session-manager.test.js +104 -0
  8. package/dist/__tests__/config.test.js +3 -3
  9. package/dist/bridge/config.d.ts +11 -0
  10. package/dist/bridge/config.js +79 -0
  11. package/dist/bridge/mcpRegister.d.ts +28 -0
  12. package/dist/bridge/mcpRegister.js +35 -0
  13. package/dist/bridge/realPty.d.ts +2 -0
  14. package/dist/bridge/realPty.js +88 -0
  15. package/dist/bridge/server.d.ts +14 -0
  16. package/dist/bridge/server.js +182 -0
  17. package/dist/bridge/sessionManager.d.ts +42 -0
  18. package/dist/bridge/sessionManager.js +79 -0
  19. package/dist/commands/agent.js +98 -1
  20. package/dist/commands/apps.js +79 -0
  21. package/dist/commands/bounty.js +374 -7
  22. package/dist/commands/bridge.d.ts +3 -0
  23. package/dist/commands/bridge.js +122 -0
  24. package/dist/commands/credits.d.ts +2 -0
  25. package/dist/commands/credits.js +128 -0
  26. package/dist/commands/keys.d.ts +2 -0
  27. package/dist/commands/keys.js +72 -0
  28. package/dist/commands/prompts.d.ts +2 -0
  29. package/dist/commands/prompts.js +136 -0
  30. package/dist/commands/repo.d.ts +2 -0
  31. package/dist/commands/repo.js +197 -0
  32. package/dist/commands/workspace.d.ts +1 -0
  33. package/dist/commands/workspace.js +294 -12
  34. package/dist/index.js +12 -1
  35. package/dist/utils/client.d.ts +1 -0
  36. package/dist/utils/client.js +3 -0
  37. package/dist/utils/config.js +3 -3
  38. package/package.json +10 -15
@@ -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
- (0, format_1.heading)('Bids');
96
- console.log((0, format_1.makeTable)(['Agent', 'Amount', 'Status', 'Message'], bids.map((bid) => [
97
- (0, format_1.shorten)(bid.agent_wallet),
98
- (0, format_1.formatReward)(bid.amount, b.reward_symbol),
99
- (0, format_1.statusColor)(bid.status || 'pending'),
100
- (bid.message || '').slice(0, 40),
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,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const DEFAULT_BRIDGE_PORT = 8377;
3
+ export declare const bridgeCommand: Command;
@@ -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,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const creditsCommand: Command;
@@ -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
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const keysCommand: Command;