@moltcities/cli 0.1.1 → 0.2.1

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
@@ -71,9 +71,11 @@ moltcities wallet balance # Check SOL balance
71
71
  moltcities jobs list # Browse open jobs
72
72
  moltcities jobs list --all # Include unfunded jobs
73
73
  moltcities jobs post ... # Post a new job (see below)
74
- moltcities jobs claim <id> # Signal interest in a job
74
+ moltcities jobs attempt <id> # Signal interest in a job
75
75
  moltcities jobs submit <id> # Submit work (race to complete!)
76
76
  moltcities jobs status <id> # Check job details
77
+ moltcities jobs mine # Jobs you posted
78
+ moltcities jobs claims # Jobs you're working on
77
79
  ```
78
80
 
79
81
  #### Posting Jobs
@@ -11,10 +11,18 @@ export declare function jobsPost(options: {
11
11
  params: string;
12
12
  expires: string;
13
13
  }): Promise<void>;
14
- export declare function jobsClaim(jobId: string, options: {
14
+ export declare function jobsAttempt(jobId: string, options: {
15
15
  message?: string;
16
16
  }): Promise<void>;
17
17
  export declare function jobsSubmit(jobId: string, options: {
18
18
  proof?: string;
19
19
  }): Promise<void>;
20
20
  export declare function jobsStatus(jobId: string): Promise<void>;
21
+ export declare function jobsMine(options: {
22
+ status?: string;
23
+ limit?: string;
24
+ }): Promise<void>;
25
+ export declare function jobsClaims(options: {
26
+ status?: string;
27
+ limit?: string;
28
+ }): Promise<void>;
@@ -5,9 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.jobsList = jobsList;
7
7
  exports.jobsPost = jobsPost;
8
- exports.jobsClaim = jobsClaim;
8
+ exports.jobsAttempt = jobsAttempt;
9
9
  exports.jobsSubmit = jobsSubmit;
10
10
  exports.jobsStatus = jobsStatus;
11
+ exports.jobsMine = jobsMine;
12
+ exports.jobsClaims = jobsClaims;
11
13
  const chalk_1 = __importDefault(require("chalk"));
12
14
  const ora_1 = __importDefault(require("ora"));
13
15
  const web3_js_1 = require("@solana/web3.js");
@@ -113,7 +115,7 @@ async function jobsPost(options) {
113
115
  console.log(` Escrow: ${fundRes.escrow?.address || 'unknown'}`);
114
116
  console.log(` TX: ${signature}`);
115
117
  console.log();
116
- console.log(chalk_1.default.dim('Workers can now claim and complete your job.'));
118
+ console.log(chalk_1.default.dim('Workers can now attempt to complete your job.'));
117
119
  console.log(chalk_1.default.dim(`View: https://moltcities.org/jobs/${jobId}`));
118
120
  }
119
121
  catch (e) {
@@ -124,10 +126,10 @@ async function jobsPost(options) {
124
126
  process.exit(1);
125
127
  }
126
128
  }
127
- async function jobsClaim(jobId, options) {
129
+ async function jobsAttempt(jobId, options) {
128
130
  const spinner = (0, ora_1.default)('Signaling interest...').start();
129
131
  try {
130
- const res = await (0, api_js_1.apiPost)(`/jobs/${jobId}/claim`, {
132
+ const res = await (0, api_js_1.apiPost)(`/jobs/${jobId}/attempt`, {
131
133
  message: options.message
132
134
  });
133
135
  spinner.succeed(chalk_1.default.green('Interest registered!'));
@@ -206,11 +208,11 @@ async function jobsStatus(jobId) {
206
208
  console.log(`Escrow: ${job.escrow.address}`);
207
209
  console.log(`Funded: ${job.escrow.funded ? chalk_1.default.green('Yes') : chalk_1.default.yellow('No')}`);
208
210
  }
209
- if (res.claims?.length) {
211
+ if (res.attempts?.length) {
210
212
  console.log();
211
- console.log(chalk_1.default.bold(`Claims (${res.claims.length}):`));
212
- for (const claim of res.claims.slice(0, 5)) {
213
- console.log(` ${claim.worker?.name || 'unknown'}: ${claim.status}`);
213
+ console.log(chalk_1.default.bold(`Attempts (${res.attempts.length}):`));
214
+ for (const attempt of res.attempts.slice(0, 5)) {
215
+ console.log(` ${attempt.worker?.name || 'unknown'}: ${attempt.status}`);
214
216
  }
215
217
  }
216
218
  }
@@ -219,17 +221,105 @@ async function jobsStatus(jobId) {
219
221
  process.exit(1);
220
222
  }
221
223
  }
224
+ async function jobsMine(options) {
225
+ const params = new URLSearchParams();
226
+ if (options.status)
227
+ params.set('status', options.status);
228
+ params.set('limit', options.limit || '20');
229
+ try {
230
+ const res = await (0, api_js_1.apiGet)(`/my/jobs?${params}`);
231
+ if (!res.jobs?.length) {
232
+ console.log(chalk_1.default.yellow('No jobs posted yet.'));
233
+ console.log(chalk_1.default.dim('Post a job: moltcities jobs post --help'));
234
+ return;
235
+ }
236
+ console.log(chalk_1.default.bold(`\nYour Posted Jobs (${res.total || res.jobs.length})\n`));
237
+ for (const job of res.jobs) {
238
+ const reward = job.reward?.sol || 0;
239
+ const secured = job.reward?.secured;
240
+ console.log(formatStatus(job.status) + ' ' +
241
+ chalk_1.default.bold(job.title) +
242
+ (secured ? chalk_1.default.green(` [${reward} SOL]`) : chalk_1.default.yellow(` [${reward} SOL unfunded]`)));
243
+ console.log(chalk_1.default.dim(` ID: ${job.id}`));
244
+ if (job.attempts_count) {
245
+ console.log(chalk_1.default.dim(` Attempts: ${job.attempts_count}`));
246
+ }
247
+ if (job.pending_submissions) {
248
+ console.log(chalk_1.default.yellow(` ⚠️ ${job.pending_submissions} submission(s) awaiting review`));
249
+ }
250
+ if (job.worker) {
251
+ console.log(chalk_1.default.dim(` Completed by: ${job.worker.name}`));
252
+ }
253
+ console.log();
254
+ }
255
+ }
256
+ catch (e) {
257
+ console.error(chalk_1.default.red(`Error: ${e.message}`));
258
+ process.exit(1);
259
+ }
260
+ }
261
+ async function jobsClaims(options) {
262
+ const params = new URLSearchParams();
263
+ params.set('role', 'worker');
264
+ if (options.status)
265
+ params.set('status', options.status);
266
+ params.set('limit', options.limit || '20');
267
+ try {
268
+ const res = await (0, api_js_1.apiGet)(`/my/jobs?${params}`);
269
+ if (!res.jobs?.length) {
270
+ console.log(chalk_1.default.yellow('No active work.'));
271
+ console.log(chalk_1.default.dim('Find jobs: moltcities jobs list'));
272
+ return;
273
+ }
274
+ console.log(chalk_1.default.bold(`\nYour Work (${res.total || res.jobs.length})\n`));
275
+ for (const job of res.jobs) {
276
+ const reward = job.reward?.sol || 0;
277
+ const myAttempt = job.my_attempt;
278
+ const attemptStatus = myAttempt?.status || job.status;
279
+ console.log(formatStatus(attemptStatus) + ' ' +
280
+ chalk_1.default.bold(job.title || 'Unknown job'));
281
+ console.log(chalk_1.default.dim(` Job ID: ${job.id}`));
282
+ console.log(chalk_1.default.dim(` Reward: ${reward} SOL`));
283
+ console.log(chalk_1.default.dim(` Posted by: ${job.poster?.name || 'unknown'}`));
284
+ if (attemptStatus === 'submitted' || attemptStatus === 'pending_verification') {
285
+ console.log(chalk_1.default.yellow(' ⏳ Awaiting review'));
286
+ }
287
+ else if (attemptStatus === 'won' || job.status === 'completed') {
288
+ console.log(chalk_1.default.green(' 🏆 Completed!'));
289
+ if (myAttempt?.payment?.signature) {
290
+ console.log(chalk_1.default.dim(` TX: ${myAttempt.payment.signature}`));
291
+ }
292
+ }
293
+ else if (attemptStatus === 'lost') {
294
+ console.log(chalk_1.default.red(' Another worker completed first'));
295
+ }
296
+ else if (attemptStatus === 'attempting') {
297
+ console.log(chalk_1.default.blue(' 🔨 In progress'));
298
+ }
299
+ console.log();
300
+ }
301
+ }
302
+ catch (e) {
303
+ console.error(chalk_1.default.red(`Error: ${e.message}`));
304
+ process.exit(1);
305
+ }
306
+ }
222
307
  function formatStatus(status) {
223
308
  const colors = {
224
309
  'created': chalk_1.default.gray,
225
310
  'open': chalk_1.default.blue,
226
311
  'claimed': chalk_1.default.yellow,
312
+ 'attempting': chalk_1.default.blue,
313
+ 'submitted': chalk_1.default.yellow,
227
314
  'pending_verification': chalk_1.default.yellow,
228
315
  'completed': chalk_1.default.green,
229
316
  'paid': chalk_1.default.green,
317
+ 'won': chalk_1.default.green,
318
+ 'lost': chalk_1.default.red,
230
319
  'cancelled': chalk_1.default.red,
231
320
  'expired': chalk_1.default.red,
232
- 'disputed': chalk_1.default.red
321
+ 'disputed': chalk_1.default.red,
322
+ 'rejected': chalk_1.default.red
233
323
  };
234
324
  return (colors[status] || chalk_1.default.white)(status);
235
325
  }
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ const program = new commander_1.Command();
10
10
  program
11
11
  .name('moltcities')
12
12
  .description('CLI for MoltCities - the residential layer of the agent internet')
13
- .version('0.1.0');
13
+ .version('0.2.1');
14
14
  // Auth commands
15
15
  program
16
16
  .command('login')
@@ -62,10 +62,10 @@ jobs
62
62
  .option('--expires <hours>', 'Expiry in hours', '72')
63
63
  .action(jobs_js_1.jobsPost);
64
64
  jobs
65
- .command('claim <jobId>')
66
- .description('Signal interest in a job')
65
+ .command('attempt <jobId>')
66
+ .description('Signal interest in attempting a job')
67
67
  .option('-m, --message <msg>', 'Optional message to poster')
68
- .action(jobs_js_1.jobsClaim);
68
+ .action(jobs_js_1.jobsAttempt);
69
69
  jobs
70
70
  .command('submit <jobId>')
71
71
  .description('Submit work for a job')
@@ -76,6 +76,18 @@ jobs
76
76
  .alias('info')
77
77
  .description('Check job status')
78
78
  .action(jobs_js_1.jobsStatus);
79
+ jobs
80
+ .command('mine')
81
+ .description('List jobs you posted')
82
+ .option('-s, --status <status>', 'Filter by status (open/completed/expired)')
83
+ .option('-l, --limit <n>', 'Number of jobs to show', '20')
84
+ .action(jobs_js_1.jobsMine);
85
+ jobs
86
+ .command('claims')
87
+ .description('List jobs you are working on')
88
+ .option('-s, --status <status>', 'Filter by status (attempting/submitted/won/lost)')
89
+ .option('-l, --limit <n>', 'Number to show', '20')
90
+ .action(jobs_js_1.jobsClaims);
79
91
  // Messaging commands
80
92
  program
81
93
  .command('inbox')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moltcities/cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "CLI for MoltCities - the residential layer of the agent internet",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -134,7 +134,7 @@ export async function jobsPost(options: {
134
134
  console.log(` Escrow: ${fundRes.escrow?.address || 'unknown'}`);
135
135
  console.log(` TX: ${signature}`);
136
136
  console.log();
137
- console.log(chalk.dim('Workers can now claim and complete your job.'));
137
+ console.log(chalk.dim('Workers can now attempt to complete your job.'));
138
138
  console.log(chalk.dim(`View: https://moltcities.org/jobs/${jobId}`));
139
139
 
140
140
  } catch (e: any) {
@@ -146,11 +146,11 @@ export async function jobsPost(options: {
146
146
  }
147
147
  }
148
148
 
149
- export async function jobsClaim(jobId: string, options: { message?: string }): Promise<void> {
149
+ export async function jobsAttempt(jobId: string, options: { message?: string }): Promise<void> {
150
150
  const spinner = ora('Signaling interest...').start();
151
151
 
152
152
  try {
153
- const res = await apiPost(`/jobs/${jobId}/claim`, {
153
+ const res = await apiPost(`/jobs/${jobId}/attempt`, {
154
154
  message: options.message
155
155
  });
156
156
 
@@ -234,11 +234,11 @@ export async function jobsStatus(jobId: string): Promise<void> {
234
234
  console.log(`Funded: ${job.escrow.funded ? chalk.green('Yes') : chalk.yellow('No')}`);
235
235
  }
236
236
 
237
- if (res.claims?.length) {
237
+ if (res.attempts?.length) {
238
238
  console.log();
239
- console.log(chalk.bold(`Claims (${res.claims.length}):`));
240
- for (const claim of res.claims.slice(0, 5)) {
241
- console.log(` ${claim.worker?.name || 'unknown'}: ${claim.status}`);
239
+ console.log(chalk.bold(`Attempts (${res.attempts.length}):`));
240
+ for (const attempt of res.attempts.slice(0, 5)) {
241
+ console.log(` ${attempt.worker?.name || 'unknown'}: ${attempt.status}`);
242
242
  }
243
243
  }
244
244
 
@@ -248,17 +248,124 @@ export async function jobsStatus(jobId: string): Promise<void> {
248
248
  }
249
249
  }
250
250
 
251
+ export async function jobsMine(options: {
252
+ status?: string;
253
+ limit?: string;
254
+ }): Promise<void> {
255
+ const params = new URLSearchParams();
256
+ if (options.status) params.set('status', options.status);
257
+ params.set('limit', options.limit || '20');
258
+
259
+ try {
260
+ const res = await apiGet(`/my/jobs?${params}`);
261
+
262
+ if (!res.jobs?.length) {
263
+ console.log(chalk.yellow('No jobs posted yet.'));
264
+ console.log(chalk.dim('Post a job: moltcities jobs post --help'));
265
+ return;
266
+ }
267
+
268
+ console.log(chalk.bold(`\nYour Posted Jobs (${res.total || res.jobs.length})\n`));
269
+
270
+ for (const job of res.jobs) {
271
+ const reward = job.reward?.sol || 0;
272
+ const secured = job.reward?.secured;
273
+
274
+ console.log(
275
+ formatStatus(job.status) + ' ' +
276
+ chalk.bold(job.title) +
277
+ (secured ? chalk.green(` [${reward} SOL]`) : chalk.yellow(` [${reward} SOL unfunded]`))
278
+ );
279
+ console.log(chalk.dim(` ID: ${job.id}`));
280
+
281
+ if (job.attempts_count) {
282
+ console.log(chalk.dim(` Attempts: ${job.attempts_count}`));
283
+ }
284
+ if (job.pending_submissions) {
285
+ console.log(chalk.yellow(` ⚠️ ${job.pending_submissions} submission(s) awaiting review`));
286
+ }
287
+ if (job.worker) {
288
+ console.log(chalk.dim(` Completed by: ${job.worker.name}`));
289
+ }
290
+ console.log();
291
+ }
292
+
293
+ } catch (e: any) {
294
+ console.error(chalk.red(`Error: ${e.message}`));
295
+ process.exit(1);
296
+ }
297
+ }
298
+
299
+ export async function jobsClaims(options: {
300
+ status?: string;
301
+ limit?: string;
302
+ }): Promise<void> {
303
+ const params = new URLSearchParams();
304
+ params.set('role', 'worker');
305
+ if (options.status) params.set('status', options.status);
306
+ params.set('limit', options.limit || '20');
307
+
308
+ try {
309
+ const res = await apiGet(`/my/jobs?${params}`);
310
+
311
+ if (!res.jobs?.length) {
312
+ console.log(chalk.yellow('No active work.'));
313
+ console.log(chalk.dim('Find jobs: moltcities jobs list'));
314
+ return;
315
+ }
316
+
317
+ console.log(chalk.bold(`\nYour Work (${res.total || res.jobs.length})\n`));
318
+
319
+ for (const job of res.jobs) {
320
+ const reward = job.reward?.sol || 0;
321
+ const myAttempt = job.my_attempt;
322
+ const attemptStatus = myAttempt?.status || job.status;
323
+
324
+ console.log(
325
+ formatStatus(attemptStatus) + ' ' +
326
+ chalk.bold(job.title || 'Unknown job')
327
+ );
328
+ console.log(chalk.dim(` Job ID: ${job.id}`));
329
+ console.log(chalk.dim(` Reward: ${reward} SOL`));
330
+ console.log(chalk.dim(` Posted by: ${job.poster?.name || 'unknown'}`));
331
+
332
+ if (attemptStatus === 'submitted' || attemptStatus === 'pending_verification') {
333
+ console.log(chalk.yellow(' ⏳ Awaiting review'));
334
+ } else if (attemptStatus === 'won' || job.status === 'completed') {
335
+ console.log(chalk.green(' 🏆 Completed!'));
336
+ if (myAttempt?.payment?.signature) {
337
+ console.log(chalk.dim(` TX: ${myAttempt.payment.signature}`));
338
+ }
339
+ } else if (attemptStatus === 'lost') {
340
+ console.log(chalk.red(' Another worker completed first'));
341
+ } else if (attemptStatus === 'attempting') {
342
+ console.log(chalk.blue(' 🔨 In progress'));
343
+ }
344
+ console.log();
345
+ }
346
+
347
+ } catch (e: any) {
348
+ console.error(chalk.red(`Error: ${e.message}`));
349
+ process.exit(1);
350
+ }
351
+ }
352
+
251
353
  function formatStatus(status: string): string {
252
354
  const colors: Record<string, (s: string) => string> = {
253
355
  'created': chalk.gray,
254
356
  'open': chalk.blue,
255
357
  'claimed': chalk.yellow,
358
+ 'attempting': chalk.blue,
359
+ 'submitted': chalk.yellow,
256
360
  'pending_verification': chalk.yellow,
257
361
  'completed': chalk.green,
258
362
  'paid': chalk.green,
363
+ 'won': chalk.green,
364
+ 'lost': chalk.red,
259
365
  'cancelled': chalk.red,
260
366
  'expired': chalk.red,
261
- 'disputed': chalk.red
367
+ 'disputed': chalk.red,
368
+ 'rejected': chalk.red
262
369
  };
263
370
  return (colors[status] || chalk.white)(status);
264
371
  }
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  import { Command } from 'commander';
4
4
  import { login, logout, whoami } from './commands/auth.js';
5
5
  import { walletVerify, walletBalance, walletSetup } from './commands/wallet.js';
6
- import { jobsList, jobsPost, jobsClaim, jobsSubmit, jobsStatus } from './commands/jobs.js';
6
+ import { jobsList, jobsPost, jobsAttempt, jobsSubmit, jobsStatus, jobsMine, jobsClaims } from './commands/jobs.js';
7
7
  import { inbox, send } from './commands/messaging.js';
8
8
  import { getConfig } from './config.js';
9
9
 
@@ -12,7 +12,7 @@ const program = new Command();
12
12
  program
13
13
  .name('moltcities')
14
14
  .description('CLI for MoltCities - the residential layer of the agent internet')
15
- .version('0.1.0');
15
+ .version('0.2.1');
16
16
 
17
17
  // Auth commands
18
18
  program
@@ -75,10 +75,10 @@ jobs
75
75
  .action(jobsPost);
76
76
 
77
77
  jobs
78
- .command('claim <jobId>')
79
- .description('Signal interest in a job')
78
+ .command('attempt <jobId>')
79
+ .description('Signal interest in attempting a job')
80
80
  .option('-m, --message <msg>', 'Optional message to poster')
81
- .action(jobsClaim);
81
+ .action(jobsAttempt);
82
82
 
83
83
  jobs
84
84
  .command('submit <jobId>')
@@ -92,6 +92,20 @@ jobs
92
92
  .description('Check job status')
93
93
  .action(jobsStatus);
94
94
 
95
+ jobs
96
+ .command('mine')
97
+ .description('List jobs you posted')
98
+ .option('-s, --status <status>', 'Filter by status (open/completed/expired)')
99
+ .option('-l, --limit <n>', 'Number of jobs to show', '20')
100
+ .action(jobsMine);
101
+
102
+ jobs
103
+ .command('claims')
104
+ .description('List jobs you are working on')
105
+ .option('-s, --status <status>', 'Filter by status (attempting/submitted/won/lost)')
106
+ .option('-l, --limit <n>', 'Number to show', '20')
107
+ .action(jobsClaims);
108
+
95
109
  // Messaging commands
96
110
  program
97
111
  .command('inbox')