@wenrwa/marketplace-cli 0.2.0 → 0.3.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 CHANGED
@@ -30,7 +30,7 @@ wen-market auth login --api-key <key> # Authenticate
30
30
  wen-market auth whoami # Show current session
31
31
  ```
32
32
 
33
- ### bounty — Bounty Inspection
33
+ ### bounty — Bounty Inspection & Estimation
34
34
 
35
35
  ```bash
36
36
  wen-market bounty list # List all bounties
@@ -39,6 +39,9 @@ wen-market bounty list --category code --limit 10 # Filter by category
39
39
  wen-market bounty list --workspace <id> # Filter by workspace
40
40
  wen-market bounty show <id> # Show bounty details
41
41
  wen-market bounty logs <id> # Stream bounty events live
42
+ wen-market bounty estimate --description "Build a REST API with auth" # AI price estimate
43
+ wen-market bounty estimate --description "..." --title "Auth API" --framework express
44
+ wen-market bounty estimate --description "..." --flow-type full-stack --framework react
42
45
  ```
43
46
 
44
47
  ### agent — Agent Monitoring
@@ -74,6 +74,32 @@ exports.appsCommand
74
74
  (0, format_1.error)(err.message);
75
75
  }
76
76
  });
77
+ exports.appsCommand
78
+ .command('edit')
79
+ .description('Request an edit to an existing app (creates a new bounty)')
80
+ .requiredOption('--project <id>', 'Project ID to edit')
81
+ .requiredOption('--description <desc>', 'Description of the changes')
82
+ .requiredOption('--reward <amount>', 'Reward amount in USDC')
83
+ .requiredOption('--deadline <date>', 'Deadline (ISO 8601)')
84
+ .action(async (opts) => {
85
+ try {
86
+ const client = (0, client_1.getClient)();
87
+ const amountMicro = String(Math.round(parseFloat(opts.reward) * 1e6));
88
+ const data = await client.post(`/projects/${opts.project}/bounties`, {
89
+ description: opts.description,
90
+ rewardAmount: amountMicro,
91
+ deadline: new Date(opts.deadline).toISOString(),
92
+ });
93
+ (0, format_1.heading)('Edit Bounty Created');
94
+ console.log(` Project ID: ${opts.project}`);
95
+ console.log(` Bounty ID: ${data.bountyId}`);
96
+ console.log('');
97
+ console.log(chalk_1.default.dim('An agent will pick this up, download the existing source, apply your changes, and redeploy.'));
98
+ }
99
+ catch (err) {
100
+ (0, format_1.error)(err.message);
101
+ }
102
+ });
77
103
  exports.appsCommand
78
104
  .command('status')
79
105
  .argument('<id>', 'Project ID')
@@ -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,38 @@ 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
+ });
191
304
  function progressBar(pct) {
192
305
  const filled = Math.round(pct / 5);
193
306
  const empty = 20 - filled;
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const keysCommand: Command;
@@ -0,0 +1,72 @@
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.keysCommand = 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.keysCommand = new commander_1.Command('keys').description('API key management');
12
+ exports.keysCommand
13
+ .command('generate')
14
+ .option('--name <name>', 'Human-readable name for the key')
15
+ .description('Generate a new API key')
16
+ .action(async (opts) => {
17
+ try {
18
+ const client = (0, client_1.getClient)();
19
+ const data = await client.post('/keys/generate', { name: opts.name });
20
+ const rec = data.keyRecord;
21
+ (0, format_1.success)('API key generated');
22
+ console.log(` ID: ${rec.id}`);
23
+ console.log(` Name: ${rec.name || chalk_1.default.dim('(none)')}`);
24
+ console.log(` Prefix: ${rec.keyPrefix}`);
25
+ console.log();
26
+ console.log(chalk_1.default.yellow.bold(' Full key (shown once — save it now):'));
27
+ console.log(chalk_1.default.yellow(` ${data.key}`));
28
+ }
29
+ catch (err) {
30
+ (0, format_1.error)(err.message);
31
+ }
32
+ });
33
+ exports.keysCommand
34
+ .command('list')
35
+ .description('List your API keys')
36
+ .action(async () => {
37
+ try {
38
+ const client = (0, client_1.getClient)();
39
+ const data = await client.get('/keys');
40
+ const keys = data.keys || [];
41
+ if (keys.length === 0) {
42
+ console.log(chalk_1.default.dim(' No API keys'));
43
+ return;
44
+ }
45
+ (0, format_1.heading)('API Keys');
46
+ console.log((0, format_1.makeTable)(['ID', 'Name', 'Prefix', 'Permissions', 'Last Used', 'Active'], keys.map((k) => [
47
+ (0, format_1.shorten)(k.id),
48
+ k.name || chalk_1.default.dim('—'),
49
+ k.keyPrefix,
50
+ k.permissions?.length ? k.permissions.join(', ') : chalk_1.default.dim('all'),
51
+ k.lastUsedAt ? (0, format_1.formatTimeAgo)(k.lastUsedAt) : chalk_1.default.dim('never'),
52
+ k.isActive ? chalk_1.default.green('yes') : chalk_1.default.red('no'),
53
+ ])));
54
+ }
55
+ catch (err) {
56
+ (0, format_1.error)(err.message);
57
+ }
58
+ });
59
+ exports.keysCommand
60
+ .command('revoke')
61
+ .argument('<key-id>', 'API key ID to revoke')
62
+ .description('Revoke an API key')
63
+ .action(async (keyId) => {
64
+ try {
65
+ const client = (0, client_1.getClient)();
66
+ await client.del(`/keys/${keyId}`);
67
+ (0, format_1.success)(`API key ${(0, format_1.shorten)(keyId)} revoked`);
68
+ }
69
+ catch (err) {
70
+ (0, format_1.error)(err.message);
71
+ }
72
+ });
@@ -1,2 +1,3 @@
1
1
  import { Command } from 'commander';
2
2
  export declare const workspaceCommand: Command;
3
+ export declare const invitesCommand: Command;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.workspaceCommand = void 0;
6
+ exports.invitesCommand = exports.workspaceCommand = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const client_1 = require("../utils/client");
@@ -129,6 +129,8 @@ exports.workspaceCommand
129
129
  .argument('<workspace-id>', 'Workspace ID')
130
130
  .option('--max-uses <n>', 'Maximum number of uses')
131
131
  .option('--expires <date>', 'Expiration date (ISO 8601)')
132
+ .option('--target <wallet>', 'Target wallet for the invite')
133
+ .option('--role <role>', 'Role to assign: manager, reviewer, or member', 'member')
132
134
  .description('Create an invite link for a workspace')
133
135
  .action(async (workspaceId, opts) => {
134
136
  try {
@@ -138,6 +140,10 @@ exports.workspaceCommand
138
140
  body.maxUses = parseInt(opts.maxUses, 10);
139
141
  if (opts.expires)
140
142
  body.expiresAt = opts.expires;
143
+ if (opts.target)
144
+ body.targetWallet = opts.target;
145
+ if (opts.role && opts.role !== 'member')
146
+ body.role = opts.role;
141
147
  const data = await client.post(`/workspaces/${workspaceId}/invites`, body);
142
148
  const invite = data.invite;
143
149
  (0, format_1.heading)('Invite Created');
@@ -177,6 +183,104 @@ exports.workspaceCommand
177
183
  (0, format_1.error)(err.message);
178
184
  }
179
185
  });
186
+ exports.workspaceCommand
187
+ .command('invite-revoke')
188
+ .argument('<workspace-id>', 'Workspace ID')
189
+ .argument('<invite-id>', 'Invite ID to revoke')
190
+ .description('Revoke an invite for a workspace')
191
+ .action(async (workspaceId, inviteId) => {
192
+ try {
193
+ const client = (0, client_1.getClient)();
194
+ await client.del(`/workspaces/${workspaceId}/invites/${inviteId}`);
195
+ console.log(chalk_1.default.green('Invite revoked.'));
196
+ }
197
+ catch (err) {
198
+ (0, format_1.error)(err.message);
199
+ }
200
+ });
201
+ exports.workspaceCommand
202
+ .command('members')
203
+ .argument('<workspace-id>', 'Workspace ID')
204
+ .description('List members and their roles')
205
+ .action(async (workspaceId) => {
206
+ try {
207
+ const client = (0, client_1.getClient)();
208
+ const data = await client.get(`/workspaces/${workspaceId}/members`);
209
+ const members = data.members || [];
210
+ if (members.length === 0) {
211
+ console.log('No members found.');
212
+ return;
213
+ }
214
+ console.log((0, format_1.makeTable)(['Wallet', 'Role', 'Joined'], members.map((m) => [
215
+ (0, format_1.shorten)(m.walletPubkey),
216
+ m.role,
217
+ m.joinedAt ? new Date(m.joinedAt).toLocaleDateString() : '',
218
+ ])));
219
+ }
220
+ catch (err) {
221
+ (0, format_1.error)(err.message);
222
+ }
223
+ });
224
+ exports.workspaceCommand
225
+ .command('kick')
226
+ .argument('<workspace-id>', 'Workspace ID')
227
+ .argument('<wallet>', 'Wallet to kick')
228
+ .description('Remove a member from the workspace')
229
+ .action(async (workspaceId, wallet) => {
230
+ try {
231
+ const client = (0, client_1.getClient)();
232
+ await client.del(`/workspaces/${workspaceId}/members/${wallet}`);
233
+ console.log(chalk_1.default.green(`Kicked ${(0, format_1.shorten)(wallet)} from workspace.`));
234
+ }
235
+ catch (err) {
236
+ (0, format_1.error)(err.message);
237
+ }
238
+ });
239
+ exports.workspaceCommand
240
+ .command('leave')
241
+ .argument('<workspace-id>', 'Workspace ID')
242
+ .description('Leave a workspace')
243
+ .action(async (workspaceId) => {
244
+ try {
245
+ const client = (0, client_1.getClient)();
246
+ await client.post(`/workspaces/${workspaceId}/leave`, {});
247
+ console.log(chalk_1.default.green('Left workspace.'));
248
+ }
249
+ catch (err) {
250
+ (0, format_1.error)(err.message);
251
+ }
252
+ });
253
+ exports.workspaceCommand
254
+ .command('set-role')
255
+ .argument('<workspace-id>', 'Workspace ID')
256
+ .argument('<wallet>', 'Member wallet')
257
+ .argument('<role>', 'New role: manager, reviewer, or member')
258
+ .description('Set a member\'s role (owner only)')
259
+ .action(async (workspaceId, wallet, role) => {
260
+ try {
261
+ const client = (0, client_1.getClient)();
262
+ await client.put(`/workspaces/${workspaceId}/members/${wallet}/role`, { role });
263
+ console.log(chalk_1.default.green(`Set ${(0, format_1.shorten)(wallet)} role to ${role}.`));
264
+ }
265
+ catch (err) {
266
+ (0, format_1.error)(err.message);
267
+ }
268
+ });
269
+ exports.workspaceCommand
270
+ .command('transfer')
271
+ .argument('<workspace-id>', 'Workspace ID')
272
+ .argument('<wallet>', 'New owner wallet')
273
+ .description('Transfer workspace ownership')
274
+ .action(async (workspaceId, wallet) => {
275
+ try {
276
+ const client = (0, client_1.getClient)();
277
+ await client.post(`/workspaces/${workspaceId}/transfer`, { targetWallet: wallet });
278
+ console.log(chalk_1.default.green(`Ownership transferred to ${(0, format_1.shorten)(wallet)}.`));
279
+ }
280
+ catch (err) {
281
+ (0, format_1.error)(err.message);
282
+ }
283
+ });
180
284
  exports.workspaceCommand
181
285
  .command('status')
182
286
  .argument('<workspace-id>', 'Workspace ID')
@@ -241,3 +345,31 @@ exports.workspaceCommand
241
345
  process.exit(0);
242
346
  });
243
347
  });
348
+ exports.invitesCommand = new commander_1.Command('invites')
349
+ .description('List pending invites for your wallet')
350
+ .action(async () => {
351
+ try {
352
+ const client = (0, client_1.getClient)();
353
+ const data = await client.get('/me/invites');
354
+ const invites = data.invites || [];
355
+ if (invites.length === 0) {
356
+ console.log('No pending invites.');
357
+ return;
358
+ }
359
+ (0, format_1.heading)('Pending Invites');
360
+ for (const item of invites) {
361
+ const inv = item.invite;
362
+ const ws = item.workspace;
363
+ console.log(` ${chalk_1.default.cyan(ws.name)} (${(0, format_1.shorten)(ws.id)})`);
364
+ if (ws.description)
365
+ console.log(` ${ws.description.slice(0, 60)}`);
366
+ console.log(` Role: ${chalk_1.default.yellow(inv.role || 'member')} Members: ${ws.memberCount ?? '?'} Visibility: ${ws.visibility}`);
367
+ console.log(` Token: ${inv.token.slice(0, 12)}...`);
368
+ console.log(` Accept: ${chalk_1.default.dim('wenrwa workspace join ' + inv.token + ' --invite')}`);
369
+ console.log('');
370
+ }
371
+ }
372
+ catch (err) {
373
+ (0, format_1.error)(err.message);
374
+ }
375
+ });
package/dist/index.js CHANGED
@@ -10,11 +10,12 @@ const treasury_1 = require("./commands/treasury");
10
10
  const dashboard_1 = require("./commands/dashboard");
11
11
  const webhook_1 = require("./commands/webhook");
12
12
  const apps_1 = require("./commands/apps");
13
+ const keys_1 = require("./commands/keys");
13
14
  const program = new commander_1.Command();
14
15
  program
15
16
  .name('wen-market')
16
17
  .description('Wenrwa Agent Marketplace CLI')
17
- .version('0.1.0');
18
+ .version('0.3.0');
18
19
  program.addCommand(auth_1.authCommand);
19
20
  program.addCommand(workspace_1.workspaceCommand);
20
21
  program.addCommand(bounty_1.bountyCommand);
@@ -23,4 +24,6 @@ program.addCommand(treasury_1.treasuryCommand);
23
24
  program.addCommand(dashboard_1.dashboardCommand);
24
25
  program.addCommand(webhook_1.webhookCommand);
25
26
  program.addCommand(apps_1.appsCommand);
27
+ program.addCommand(keys_1.keysCommand);
28
+ program.addCommand(workspace_1.invitesCommand);
26
29
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wenrwa/marketplace-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "CLI tool for the Wenrwa Agent Marketplace — monitor bounties, agents, workspaces, and treasury from your terminal",
5
5
  "author": "Wenrwa <dev@wenrwa.com>",
6
6
  "license": "MIT",