@gopherhole/cli 0.1.7 → 0.1.9

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 (3) hide show
  1. package/dist/index.js +205 -4
  2. package/package.json +1 -1
  3. package/src/index.ts +210 -4
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ const brand = {
19
19
  greenDark: chalk_1.default.hex('#16a34a'), // gopher-600 - emphasis
20
20
  };
21
21
  // Version
22
- const VERSION = '0.1.3';
22
+ const VERSION = '0.1.8';
23
23
  // ASCII art banner
24
24
  function showBanner(context) {
25
25
  const gopher = [
@@ -727,6 +727,125 @@ ${chalk_1.default.bold('Examples:')}
727
727
  process.exit(1);
728
728
  }
729
729
  });
730
+ agents
731
+ .command('config <agentId>')
732
+ .description(`Configure agent settings
733
+
734
+ ${chalk_1.default.bold('Examples:')}
735
+ $ gopherhole agents config agent-abc123 --auto-approve
736
+ $ gopherhole agents config agent-abc123 --no-auto-approve
737
+ $ gopherhole agents config agent-abc123 --price 0.01 --price-unit request
738
+ $ gopherhole agents config agent-abc123 --visibility public
739
+ `)
740
+ .option('--auto-approve', 'Enable auto-approve (instant access for marketplace)')
741
+ .option('--no-auto-approve', 'Disable auto-approve (require manual approval)')
742
+ .option('--price <amount>', 'Set price per unit (e.g., 0.01)')
743
+ .option('--price-unit <unit>', 'Price unit: request, message, task, month, 1000-tokens')
744
+ .option('--clear-price', 'Remove pricing (make free)')
745
+ .option('--visibility <level>', 'Set visibility: public, unlisted, private')
746
+ .option('--category <category>', 'Set category')
747
+ .option('--tags <tags>', 'Set tags (comma-separated)')
748
+ .option('--description <text>', 'Update description')
749
+ .action(async (agentId, options) => {
750
+ const sessionId = config.get('sessionId');
751
+ if (!sessionId) {
752
+ console.log(chalk_1.default.yellow('Not logged in.'));
753
+ console.log(chalk_1.default.gray('Run: gopherhole login'));
754
+ process.exit(1);
755
+ }
756
+ // Build update body
757
+ const body = {};
758
+ if (options.autoApprove === true) {
759
+ body.auto_approve = true;
760
+ }
761
+ else if (options.autoApprove === false) {
762
+ body.auto_approve = false;
763
+ }
764
+ if (options.price !== undefined) {
765
+ body.price_amount = parseFloat(options.price);
766
+ body.price_currency = 'USD';
767
+ body.price_unit = options.priceUnit || 'request';
768
+ }
769
+ if (options.clearPrice) {
770
+ body.price_amount = null;
771
+ body.price_currency = null;
772
+ body.price_unit = null;
773
+ }
774
+ if (options.priceUnit && options.price === undefined && !options.clearPrice) {
775
+ body.price_unit = options.priceUnit;
776
+ }
777
+ if (options.visibility) {
778
+ body.visibility = options.visibility;
779
+ }
780
+ if (options.category) {
781
+ body.category = options.category;
782
+ }
783
+ if (options.tags) {
784
+ body.tags = options.tags.split(',').map((t) => t.trim());
785
+ }
786
+ if (options.description) {
787
+ body.description = options.description;
788
+ }
789
+ if (Object.keys(body).length === 0) {
790
+ console.log(chalk_1.default.yellow('No changes specified.'));
791
+ console.log(chalk_1.default.gray('Use --help to see available options.'));
792
+ return;
793
+ }
794
+ const spinner = (0, ora_1.default)('Updating agent config...').start();
795
+ log('PATCH /agents/' + agentId, body);
796
+ try {
797
+ const res = await fetch(`${API_URL}/agents/${agentId}`, {
798
+ method: 'PATCH',
799
+ headers: {
800
+ 'Content-Type': 'application/json',
801
+ 'X-Session-ID': sessionId,
802
+ },
803
+ body: JSON.stringify(body),
804
+ });
805
+ if (!res.ok) {
806
+ const err = await res.json();
807
+ logError('config', err);
808
+ throw new Error(err.error || 'Failed to update agent');
809
+ }
810
+ spinner.succeed('Agent config updated');
811
+ // Show what was changed
812
+ const changes = [];
813
+ if (body.auto_approve !== undefined) {
814
+ changes.push(` Auto-approve: ${body.auto_approve ? brand.green('enabled ⚡') : chalk_1.default.gray('disabled')}`);
815
+ }
816
+ if (body.price_amount !== undefined) {
817
+ if (body.price_amount === null) {
818
+ changes.push(` Pricing: ${brand.green('FREE')}`);
819
+ }
820
+ else {
821
+ changes.push(` Pricing: ${chalk_1.default.blue(`$${body.price_amount} per ${body.price_unit}`)}`);
822
+ }
823
+ }
824
+ if (body.visibility) {
825
+ changes.push(` Visibility: ${body.visibility}`);
826
+ }
827
+ if (body.category) {
828
+ changes.push(` Category: ${body.category}`);
829
+ }
830
+ if (body.tags) {
831
+ changes.push(` Tags: ${body.tags.join(', ')}`);
832
+ }
833
+ if (body.description) {
834
+ const desc = body.description;
835
+ changes.push(` Description: ${chalk_1.default.gray(desc.slice(0, 50))}${desc.length > 50 ? '...' : ''}`);
836
+ }
837
+ if (changes.length > 0) {
838
+ console.log('');
839
+ console.log(chalk_1.default.bold('Changes:'));
840
+ changes.forEach(c => console.log(c));
841
+ console.log('');
842
+ }
843
+ }
844
+ catch (err) {
845
+ spinner.fail(chalk_1.default.red(err.message));
846
+ process.exit(1);
847
+ }
848
+ });
730
849
  // ========== INIT COMMAND ==========
731
850
  program
732
851
  .command('init')
@@ -1000,8 +1119,26 @@ ${chalk_1.default.bold('Examples:')}
1000
1119
  for (const agent of data.agents) {
1001
1120
  const stars = '★'.repeat(Math.round(agent.avgRating)) + '☆'.repeat(5 - Math.round(agent.avgRating));
1002
1121
  const pricing = agent.pricing === 'free' ? brand.green('FREE') :
1003
- agent.pricing === 'paid' ? chalk_1.default.blue('PAID') : chalk_1.default.gray('CONTACT');
1004
- console.log(` ${chalk_1.default.bold(agent.name)} ${chalk_1.default.yellow(stars)} (${agent.ratingCount})`);
1122
+ agent.pricing === 'paid' ? chalk_1.default.blue('PAID') :
1123
+ agent.pricing === 'freemium' ? chalk_1.default.cyan('FREEMIUM') : chalk_1.default.gray(agent.pricing?.toUpperCase() || 'FREE');
1124
+ // Access status badge
1125
+ let accessBadge = '';
1126
+ if (agent.accessStatus === 'owner') {
1127
+ accessBadge = chalk_1.default.blue('👤YOURS');
1128
+ }
1129
+ else if (agent.accessStatus === 'approved' || agent.accessStatus === 'open') {
1130
+ accessBadge = chalk_1.default.green('✓ACCESS');
1131
+ }
1132
+ else if (agent.accessStatus === 'pending') {
1133
+ accessBadge = chalk_1.default.yellow('⏳PENDING');
1134
+ }
1135
+ else if (agent.accessStatus === 'denied') {
1136
+ accessBadge = chalk_1.default.red('✗DENIED');
1137
+ }
1138
+ else if (agent.autoApprove) {
1139
+ accessBadge = chalk_1.default.magenta('⚡INSTANT');
1140
+ }
1141
+ console.log(` ${chalk_1.default.bold(agent.name)} ${chalk_1.default.yellow(stars)} (${agent.ratingCount}) ${accessBadge}`);
1005
1142
  console.log(` ${chalk_1.default.gray(agent.description || 'No description')}`);
1006
1143
  console.log(` ${chalk_1.default.cyan(agent.id)} | ${pricing} | ${agent.category || 'uncategorized'}`);
1007
1144
  console.log('');
@@ -1053,7 +1190,8 @@ discover
1053
1190
  console.log(chalk_1.default.bold('\n⭐ Featured Agents:\n'));
1054
1191
  for (const agent of data.featured) {
1055
1192
  const stars = '★'.repeat(Math.round(agent.avgRating)) + '☆'.repeat(5 - Math.round(agent.avgRating));
1056
- console.log(` ${chalk_1.default.bold(agent.name)} ${chalk_1.default.yellow(stars)}`);
1193
+ const instant = agent.autoApprove ? chalk_1.default.magenta('⚡INSTANT') : '';
1194
+ console.log(` ${chalk_1.default.bold(agent.name)} ${chalk_1.default.yellow(stars)} ${instant}`);
1057
1195
  console.log(` ${chalk_1.default.gray(agent.description || 'No description')}`);
1058
1196
  console.log(` ${chalk_1.default.cyan(agent.id)}`);
1059
1197
  console.log('');
@@ -1093,6 +1231,30 @@ ${chalk_1.default.bold('Example:')}
1093
1231
  console.log(` ${chalk_1.default.bold('Pricing:')} ${agent.pricing}`);
1094
1232
  console.log(` ${chalk_1.default.bold('Category:')} ${agent.category || 'None'}`);
1095
1233
  console.log(` ${chalk_1.default.bold('By:')} ${agent.tenantName}`);
1234
+ // Show access status
1235
+ let accessLine = '';
1236
+ if (agent.accessStatus === 'owner') {
1237
+ accessLine = chalk_1.default.blue('👤 Your agent');
1238
+ }
1239
+ else if (agent.accessStatus === 'approved') {
1240
+ accessLine = chalk_1.default.green('✓ You have access');
1241
+ }
1242
+ else if (agent.accessStatus === 'open') {
1243
+ accessLine = chalk_1.default.green('✓ Open access (instant)');
1244
+ }
1245
+ else if (agent.accessStatus === 'pending') {
1246
+ accessLine = chalk_1.default.yellow('⏳ Request pending');
1247
+ }
1248
+ else if (agent.accessStatus === 'denied') {
1249
+ accessLine = chalk_1.default.red('✗ Access denied');
1250
+ }
1251
+ else if (agent.autoApprove) {
1252
+ accessLine = chalk_1.default.magenta('⚡ Instant (no approval needed)');
1253
+ }
1254
+ else {
1255
+ accessLine = chalk_1.default.gray('Requires approval - run: gopherhole discover request ' + agentId);
1256
+ }
1257
+ console.log(` ${chalk_1.default.bold('Access:')} ${accessLine}`);
1096
1258
  if (agent.tags.length > 0) {
1097
1259
  console.log(` ${chalk_1.default.bold('Tags:')} ${agent.tags.join(', ')}`);
1098
1260
  }
@@ -1125,6 +1287,45 @@ ${chalk_1.default.bold('Example:')}
1125
1287
  process.exit(1);
1126
1288
  }
1127
1289
  });
1290
+ discover
1291
+ .command('request <agent-id>')
1292
+ .description(`Request access to an agent
1293
+
1294
+ ${chalk_1.default.bold('Example:')}
1295
+ $ gopherhole discover request agent-abc123
1296
+ $ gopherhole discover request agent-abc123 --reason "I want to integrate with my app"
1297
+ `)
1298
+ .option('-r, --reason <reason>', 'Reason for requesting access')
1299
+ .action(async (agentId, options) => {
1300
+ const sessionId = config.get('sessionId');
1301
+ if (!sessionId) {
1302
+ console.log(chalk_1.default.red('Not logged in. Run: gopherhole login'));
1303
+ process.exit(1);
1304
+ }
1305
+ const spinner = (0, ora_1.default)('Requesting access...').start();
1306
+ try {
1307
+ const res = await fetch(`${API_URL}/discover/agents/${agentId}/request-access`, {
1308
+ method: 'POST',
1309
+ headers: {
1310
+ 'Authorization': `Bearer ${sessionId}`,
1311
+ 'Content-Type': 'application/json',
1312
+ },
1313
+ body: JSON.stringify({ reason: options.reason }),
1314
+ });
1315
+ const data = await res.json();
1316
+ if (!res.ok) {
1317
+ spinner.fail(chalk_1.default.red(data.error || 'Failed to request access'));
1318
+ process.exit(1);
1319
+ }
1320
+ spinner.succeed(chalk_1.default.green('Access request sent!'));
1321
+ console.log(chalk_1.default.gray('\nThe agent owner will review your request.'));
1322
+ console.log(chalk_1.default.gray(`Check status: gopherhole discover info ${agentId}`));
1323
+ }
1324
+ catch (err) {
1325
+ spinner.fail(chalk_1.default.red(err.message));
1326
+ process.exit(1);
1327
+ }
1328
+ });
1128
1329
  discover
1129
1330
  .command('top')
1130
1331
  .description(`Show top-rated agents
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gopherhole/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "GopherHole CLI - Connect AI agents to the world",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -18,7 +18,7 @@ const brand = {
18
18
  };
19
19
 
20
20
  // Version
21
- const VERSION = '0.1.3';
21
+ const VERSION = '0.1.8';
22
22
 
23
23
  // ASCII art banner
24
24
  function showBanner(context?: string) {
@@ -809,6 +809,133 @@ ${chalk.bold('Examples:')}
809
809
  }
810
810
  });
811
811
 
812
+ agents
813
+ .command('config <agentId>')
814
+ .description(`Configure agent settings
815
+
816
+ ${chalk.bold('Examples:')}
817
+ $ gopherhole agents config agent-abc123 --auto-approve
818
+ $ gopherhole agents config agent-abc123 --no-auto-approve
819
+ $ gopherhole agents config agent-abc123 --price 0.01 --price-unit request
820
+ $ gopherhole agents config agent-abc123 --visibility public
821
+ `)
822
+ .option('--auto-approve', 'Enable auto-approve (instant access for marketplace)')
823
+ .option('--no-auto-approve', 'Disable auto-approve (require manual approval)')
824
+ .option('--price <amount>', 'Set price per unit (e.g., 0.01)')
825
+ .option('--price-unit <unit>', 'Price unit: request, message, task, month, 1000-tokens')
826
+ .option('--clear-price', 'Remove pricing (make free)')
827
+ .option('--visibility <level>', 'Set visibility: public, unlisted, private')
828
+ .option('--category <category>', 'Set category')
829
+ .option('--tags <tags>', 'Set tags (comma-separated)')
830
+ .option('--description <text>', 'Update description')
831
+ .action(async (agentId, options) => {
832
+ const sessionId = config.get('sessionId') as string;
833
+ if (!sessionId) {
834
+ console.log(chalk.yellow('Not logged in.'));
835
+ console.log(chalk.gray('Run: gopherhole login'));
836
+ process.exit(1);
837
+ }
838
+
839
+ // Build update body
840
+ const body: Record<string, unknown> = {};
841
+
842
+ if (options.autoApprove === true) {
843
+ body.auto_approve = true;
844
+ } else if (options.autoApprove === false) {
845
+ body.auto_approve = false;
846
+ }
847
+
848
+ if (options.price !== undefined) {
849
+ body.price_amount = parseFloat(options.price);
850
+ body.price_currency = 'USD';
851
+ body.price_unit = options.priceUnit || 'request';
852
+ }
853
+ if (options.clearPrice) {
854
+ body.price_amount = null;
855
+ body.price_currency = null;
856
+ body.price_unit = null;
857
+ }
858
+ if (options.priceUnit && options.price === undefined && !options.clearPrice) {
859
+ body.price_unit = options.priceUnit;
860
+ }
861
+ if (options.visibility) {
862
+ body.visibility = options.visibility;
863
+ }
864
+ if (options.category) {
865
+ body.category = options.category;
866
+ }
867
+ if (options.tags) {
868
+ body.tags = options.tags.split(',').map((t: string) => t.trim());
869
+ }
870
+ if (options.description) {
871
+ body.description = options.description;
872
+ }
873
+
874
+ if (Object.keys(body).length === 0) {
875
+ console.log(chalk.yellow('No changes specified.'));
876
+ console.log(chalk.gray('Use --help to see available options.'));
877
+ return;
878
+ }
879
+
880
+ const spinner = ora('Updating agent config...').start();
881
+ log('PATCH /agents/' + agentId, body);
882
+
883
+ try {
884
+ const res = await fetch(`${API_URL}/agents/${agentId}`, {
885
+ method: 'PATCH',
886
+ headers: {
887
+ 'Content-Type': 'application/json',
888
+ 'X-Session-ID': sessionId,
889
+ },
890
+ body: JSON.stringify(body),
891
+ });
892
+
893
+ if (!res.ok) {
894
+ const err = await res.json();
895
+ logError('config', err);
896
+ throw new Error(err.error || 'Failed to update agent');
897
+ }
898
+
899
+ spinner.succeed('Agent config updated');
900
+
901
+ // Show what was changed
902
+ const changes: string[] = [];
903
+ if (body.auto_approve !== undefined) {
904
+ changes.push(` Auto-approve: ${body.auto_approve ? brand.green('enabled ⚡') : chalk.gray('disabled')}`);
905
+ }
906
+ if (body.price_amount !== undefined) {
907
+ if (body.price_amount === null) {
908
+ changes.push(` Pricing: ${brand.green('FREE')}`);
909
+ } else {
910
+ changes.push(` Pricing: ${chalk.blue(`$${body.price_amount} per ${body.price_unit}`)}`);
911
+ }
912
+ }
913
+ if (body.visibility) {
914
+ changes.push(` Visibility: ${body.visibility}`);
915
+ }
916
+ if (body.category) {
917
+ changes.push(` Category: ${body.category}`);
918
+ }
919
+ if (body.tags) {
920
+ changes.push(` Tags: ${(body.tags as string[]).join(', ')}`);
921
+ }
922
+ if (body.description) {
923
+ const desc = body.description as string;
924
+ changes.push(` Description: ${chalk.gray(desc.slice(0, 50))}${desc.length > 50 ? '...' : ''}`);
925
+ }
926
+
927
+ if (changes.length > 0) {
928
+ console.log('');
929
+ console.log(chalk.bold('Changes:'));
930
+ changes.forEach(c => console.log(c));
931
+ console.log('');
932
+ }
933
+ } catch (err) {
934
+ spinner.fail(chalk.red((err as Error).message));
935
+ process.exit(1);
936
+ }
937
+ });
938
+
812
939
  // ========== INIT COMMAND ==========
813
940
 
814
941
  program
@@ -1113,9 +1240,24 @@ ${chalk.bold('Examples:')}
1113
1240
  for (const agent of data.agents) {
1114
1241
  const stars = '★'.repeat(Math.round(agent.avgRating)) + '☆'.repeat(5 - Math.round(agent.avgRating));
1115
1242
  const pricing = agent.pricing === 'free' ? brand.green('FREE') :
1116
- agent.pricing === 'paid' ? chalk.blue('PAID') : chalk.gray('CONTACT');
1243
+ agent.pricing === 'paid' ? chalk.blue('PAID') :
1244
+ agent.pricing === 'freemium' ? chalk.cyan('FREEMIUM') : chalk.gray(agent.pricing?.toUpperCase() || 'FREE');
1117
1245
 
1118
- console.log(` ${chalk.bold(agent.name)} ${chalk.yellow(stars)} (${agent.ratingCount})`);
1246
+ // Access status badge
1247
+ let accessBadge = '';
1248
+ if (agent.accessStatus === 'owner') {
1249
+ accessBadge = chalk.blue('👤YOURS');
1250
+ } else if (agent.accessStatus === 'approved' || agent.accessStatus === 'open') {
1251
+ accessBadge = chalk.green('✓ACCESS');
1252
+ } else if (agent.accessStatus === 'pending') {
1253
+ accessBadge = chalk.yellow('⏳PENDING');
1254
+ } else if (agent.accessStatus === 'denied') {
1255
+ accessBadge = chalk.red('✗DENIED');
1256
+ } else if (agent.autoApprove) {
1257
+ accessBadge = chalk.magenta('⚡INSTANT');
1258
+ }
1259
+
1260
+ console.log(` ${chalk.bold(agent.name)} ${chalk.yellow(stars)} (${agent.ratingCount}) ${accessBadge}`);
1119
1261
  console.log(` ${chalk.gray(agent.description || 'No description')}`);
1120
1262
  console.log(` ${chalk.cyan(agent.id)} | ${pricing} | ${agent.category || 'uncategorized'}`);
1121
1263
  console.log('');
@@ -1174,7 +1316,8 @@ discover
1174
1316
  console.log(chalk.bold('\n⭐ Featured Agents:\n'));
1175
1317
  for (const agent of data.featured) {
1176
1318
  const stars = '★'.repeat(Math.round(agent.avgRating)) + '☆'.repeat(5 - Math.round(agent.avgRating));
1177
- console.log(` ${chalk.bold(agent.name)} ${chalk.yellow(stars)}`);
1319
+ const instant = agent.autoApprove ? chalk.magenta('⚡INSTANT') : '';
1320
+ console.log(` ${chalk.bold(agent.name)} ${chalk.yellow(stars)} ${instant}`);
1178
1321
  console.log(` ${chalk.gray(agent.description || 'No description')}`);
1179
1322
  console.log(` ${chalk.cyan(agent.id)}`);
1180
1323
  console.log('');
@@ -1218,6 +1361,25 @@ ${chalk.bold('Example:')}
1218
1361
  console.log(` ${chalk.bold('Category:')} ${agent.category || 'None'}`);
1219
1362
  console.log(` ${chalk.bold('By:')} ${agent.tenantName}`);
1220
1363
 
1364
+ // Show access status
1365
+ let accessLine = '';
1366
+ if (agent.accessStatus === 'owner') {
1367
+ accessLine = chalk.blue('👤 Your agent');
1368
+ } else if (agent.accessStatus === 'approved') {
1369
+ accessLine = chalk.green('✓ You have access');
1370
+ } else if (agent.accessStatus === 'open') {
1371
+ accessLine = chalk.green('✓ Open access (instant)');
1372
+ } else if (agent.accessStatus === 'pending') {
1373
+ accessLine = chalk.yellow('⏳ Request pending');
1374
+ } else if (agent.accessStatus === 'denied') {
1375
+ accessLine = chalk.red('✗ Access denied');
1376
+ } else if (agent.autoApprove) {
1377
+ accessLine = chalk.magenta('⚡ Instant (no approval needed)');
1378
+ } else {
1379
+ accessLine = chalk.gray('Requires approval - run: gopherhole discover request ' + agentId);
1380
+ }
1381
+ console.log(` ${chalk.bold('Access:')} ${accessLine}`);
1382
+
1221
1383
  if (agent.tags.length > 0) {
1222
1384
  console.log(` ${chalk.bold('Tags:')} ${agent.tags.join(', ')}`);
1223
1385
  }
@@ -1253,6 +1415,50 @@ ${chalk.bold('Example:')}
1253
1415
  }
1254
1416
  });
1255
1417
 
1418
+ discover
1419
+ .command('request <agent-id>')
1420
+ .description(`Request access to an agent
1421
+
1422
+ ${chalk.bold('Example:')}
1423
+ $ gopherhole discover request agent-abc123
1424
+ $ gopherhole discover request agent-abc123 --reason "I want to integrate with my app"
1425
+ `)
1426
+ .option('-r, --reason <reason>', 'Reason for requesting access')
1427
+ .action(async (agentId, options) => {
1428
+ const sessionId = config.get('sessionId') as string;
1429
+ if (!sessionId) {
1430
+ console.log(chalk.red('Not logged in. Run: gopherhole login'));
1431
+ process.exit(1);
1432
+ }
1433
+
1434
+ const spinner = ora('Requesting access...').start();
1435
+
1436
+ try {
1437
+ const res = await fetch(`${API_URL}/discover/agents/${agentId}/request-access`, {
1438
+ method: 'POST',
1439
+ headers: {
1440
+ 'Authorization': `Bearer ${sessionId}`,
1441
+ 'Content-Type': 'application/json',
1442
+ },
1443
+ body: JSON.stringify({ reason: options.reason }),
1444
+ });
1445
+
1446
+ const data = await res.json();
1447
+
1448
+ if (!res.ok) {
1449
+ spinner.fail(chalk.red(data.error || 'Failed to request access'));
1450
+ process.exit(1);
1451
+ }
1452
+
1453
+ spinner.succeed(chalk.green('Access request sent!'));
1454
+ console.log(chalk.gray('\nThe agent owner will review your request.'));
1455
+ console.log(chalk.gray(`Check status: gopherhole discover info ${agentId}`));
1456
+ } catch (err) {
1457
+ spinner.fail(chalk.red((err as Error).message));
1458
+ process.exit(1);
1459
+ }
1460
+ });
1461
+
1256
1462
  discover
1257
1463
  .command('top')
1258
1464
  .description(`Show top-rated agents