@gopherhole/cli 0.1.5 ā 0.1.6
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/dist/index.js +108 -17
- package/package.json +1 -1
- package/src/index.ts +111 -18
package/dist/index.js
CHANGED
|
@@ -1236,7 +1236,11 @@ ${chalk_1.default.bold('Examples:')}
|
|
|
1236
1236
|
access
|
|
1237
1237
|
.command('list')
|
|
1238
1238
|
.description('List access requests to your agents')
|
|
1239
|
-
.option('--
|
|
1239
|
+
.option('--agent <agentId>', 'Filter by agent ID')
|
|
1240
|
+
.option('--status <status>', 'Filter by status (pending, approved, rejected, all)', 'pending')
|
|
1241
|
+
.option('--search <query>', 'Search by requester name or ID')
|
|
1242
|
+
.option('--limit <n>', 'Max results (default 50)', '50')
|
|
1243
|
+
.option('--offset <n>', 'Skip first N results', '0')
|
|
1240
1244
|
.option('--json', 'Output as JSON')
|
|
1241
1245
|
.action(async (options) => {
|
|
1242
1246
|
const sessionId = config.get('sessionId');
|
|
@@ -1246,9 +1250,19 @@ access
|
|
|
1246
1250
|
process.exit(1);
|
|
1247
1251
|
}
|
|
1248
1252
|
const spinner = (0, ora_1.default)('Fetching access requests...').start();
|
|
1249
|
-
|
|
1253
|
+
// Build query params
|
|
1254
|
+
const params = new URLSearchParams();
|
|
1255
|
+
if (options.agent)
|
|
1256
|
+
params.set('agent', options.agent);
|
|
1257
|
+
if (options.status && options.status !== 'all')
|
|
1258
|
+
params.set('status', options.status);
|
|
1259
|
+
if (options.search)
|
|
1260
|
+
params.set('search', options.search);
|
|
1261
|
+
params.set('limit', options.limit);
|
|
1262
|
+
params.set('offset', options.offset);
|
|
1263
|
+
log('GET /access/inbound?' + params.toString());
|
|
1250
1264
|
try {
|
|
1251
|
-
const res = await fetch(`${API_URL}/access/inbound`, {
|
|
1265
|
+
const res = await fetch(`${API_URL}/access/inbound?${params}`, {
|
|
1252
1266
|
headers: { 'X-Session-ID': sessionId },
|
|
1253
1267
|
});
|
|
1254
1268
|
if (!res.ok) {
|
|
@@ -1256,34 +1270,44 @@ access
|
|
|
1256
1270
|
}
|
|
1257
1271
|
const data = await res.json();
|
|
1258
1272
|
spinner.stop();
|
|
1259
|
-
// Filter by status
|
|
1260
|
-
const filtered = options.status === 'all'
|
|
1261
|
-
? data.grants
|
|
1262
|
-
: data.grants.filter((g) => g.status === options.status);
|
|
1263
1273
|
if (options.json) {
|
|
1264
|
-
console.log(JSON.stringify(
|
|
1274
|
+
console.log(JSON.stringify(data.grants, null, 2));
|
|
1265
1275
|
return;
|
|
1266
1276
|
}
|
|
1267
|
-
if (
|
|
1268
|
-
console.log(chalk_1.default.gray(`\nNo ${options.status}
|
|
1277
|
+
if (data.grants.length === 0) {
|
|
1278
|
+
console.log(chalk_1.default.gray(`\nNo ${options.status === 'all' ? '' : options.status + ' '}access requests found.`));
|
|
1279
|
+
if (options.agent)
|
|
1280
|
+
console.log(chalk_1.default.gray(` Agent filter: ${options.agent}`));
|
|
1281
|
+
if (options.search)
|
|
1282
|
+
console.log(chalk_1.default.gray(` Search: "${options.search}"`));
|
|
1269
1283
|
return;
|
|
1270
1284
|
}
|
|
1271
|
-
console.log(chalk_1.default.bold(`\nš ${options.
|
|
1272
|
-
for (const grant of
|
|
1285
|
+
console.log(chalk_1.default.bold(`\nš Access Requests${options.agent ? ` for ${options.agent}` : ''}:\n`));
|
|
1286
|
+
for (const grant of data.grants) {
|
|
1273
1287
|
const statusColor = grant.status === 'pending' ? chalk_1.default.yellow :
|
|
1274
1288
|
grant.status === 'approved' ? chalk_1.default.green : chalk_1.default.red;
|
|
1275
1289
|
console.log(` ${chalk_1.default.cyan(grant.id)}`);
|
|
1276
1290
|
console.log(` From: ${grant.requester_agent_name || grant.requester_agent_id || 'Unknown'}`);
|
|
1277
1291
|
console.log(` To: ${grant.target_agent_name || grant.target_agent_id}`);
|
|
1278
1292
|
console.log(` Status: ${statusColor(grant.status)}`);
|
|
1293
|
+
if (grant.price_amount != null) {
|
|
1294
|
+
console.log(` Price: ${grant.price_amount} ${grant.price_currency}/${grant.price_unit}`);
|
|
1295
|
+
}
|
|
1296
|
+
if (grant.discount_percent != null) {
|
|
1297
|
+
console.log(` Discount: ${grant.discount_percent}%`);
|
|
1298
|
+
}
|
|
1279
1299
|
if (grant.requested_reason) {
|
|
1280
1300
|
console.log(` Reason: ${chalk_1.default.gray(grant.requested_reason)}`);
|
|
1281
1301
|
}
|
|
1282
1302
|
console.log(` Requested: ${new Date(grant.requested_at).toLocaleString()}`);
|
|
1283
1303
|
console.log('');
|
|
1284
1304
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1305
|
+
// Pagination info
|
|
1306
|
+
if (data.grants.length >= parseInt(options.limit)) {
|
|
1307
|
+
console.log(chalk_1.default.gray(`Showing ${data.grants.length} results. Use --offset ${parseInt(options.offset) + parseInt(options.limit)} for next page.`));
|
|
1308
|
+
}
|
|
1309
|
+
if (options.status === 'pending' && data.grants.length > 0) {
|
|
1310
|
+
console.log(chalk_1.default.gray(`\nApprove: gopherhole access approve <id>`));
|
|
1287
1311
|
console.log(chalk_1.default.gray(`Reject: gopherhole access reject <id>`));
|
|
1288
1312
|
}
|
|
1289
1313
|
}
|
|
@@ -1295,10 +1319,11 @@ access
|
|
|
1295
1319
|
access
|
|
1296
1320
|
.command('approve <grantId>')
|
|
1297
1321
|
.description('Approve an access request')
|
|
1298
|
-
.option('--price <amount>', 'Set custom price
|
|
1322
|
+
.option('--price <amount>', 'Set custom price (e.g., 0.01)')
|
|
1299
1323
|
.option('--currency <code>', 'Currency code (default: USD)', 'USD')
|
|
1300
1324
|
.option('--unit <unit>', 'Price unit (request, message, task, month)', 'request')
|
|
1301
|
-
.option('--
|
|
1325
|
+
.option('--discount <percent>', 'Discount off default price (e.g., 20 for 20% off)')
|
|
1326
|
+
.option('--skill-pricing <json>', 'Per-skill pricing as JSON (e.g., \'{"translate":{"amount":0.05,"currency":"USD","unit":"request"}}\')')
|
|
1302
1327
|
.action(async (grantId, options) => {
|
|
1303
1328
|
const sessionId = config.get('sessionId');
|
|
1304
1329
|
if (!sessionId) {
|
|
@@ -1315,6 +1340,12 @@ access
|
|
|
1315
1340
|
body.price_currency = options.currency;
|
|
1316
1341
|
body.price_unit = options.unit;
|
|
1317
1342
|
}
|
|
1343
|
+
if (options.discount) {
|
|
1344
|
+
body.discount_percent = parseFloat(options.discount);
|
|
1345
|
+
}
|
|
1346
|
+
if (options.skillPricing) {
|
|
1347
|
+
body.skill_pricing = JSON.parse(options.skillPricing);
|
|
1348
|
+
}
|
|
1318
1349
|
const res = await fetch(`${API_URL}/access/${grantId}/approve`, {
|
|
1319
1350
|
method: 'PUT',
|
|
1320
1351
|
headers: {
|
|
@@ -1329,8 +1360,68 @@ access
|
|
|
1329
1360
|
}
|
|
1330
1361
|
spinner.succeed('Access request approved');
|
|
1331
1362
|
if (options.price) {
|
|
1332
|
-
console.log(chalk_1.default.gray(` Custom
|
|
1363
|
+
console.log(chalk_1.default.gray(` Custom price: ${options.price} ${options.currency}/${options.unit}`));
|
|
1364
|
+
}
|
|
1365
|
+
if (options.discount) {
|
|
1366
|
+
console.log(chalk_1.default.gray(` Discount: ${options.discount}% off`));
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
catch (err) {
|
|
1370
|
+
spinner.fail(chalk_1.default.red(err.message));
|
|
1371
|
+
process.exit(1);
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
access
|
|
1375
|
+
.command('edit <grantId>')
|
|
1376
|
+
.description('Edit pricing on an existing access grant')
|
|
1377
|
+
.option('--price <amount>', 'Set custom price (e.g., 0.01)')
|
|
1378
|
+
.option('--currency <code>', 'Currency code', 'USD')
|
|
1379
|
+
.option('--unit <unit>', 'Price unit (request, message, task, month)')
|
|
1380
|
+
.option('--discount <percent>', 'Discount off default price (e.g., 20 for 20% off)')
|
|
1381
|
+
.option('--clear-discount', 'Remove discount')
|
|
1382
|
+
.option('--skill-pricing <json>', 'Per-skill pricing as JSON')
|
|
1383
|
+
.option('--clear-skill-pricing', 'Remove per-skill pricing')
|
|
1384
|
+
.action(async (grantId, options) => {
|
|
1385
|
+
const sessionId = config.get('sessionId');
|
|
1386
|
+
if (!sessionId) {
|
|
1387
|
+
console.log(chalk_1.default.yellow('Not logged in.'));
|
|
1388
|
+
console.log(chalk_1.default.gray('Run: gopherhole login'));
|
|
1389
|
+
process.exit(1);
|
|
1390
|
+
}
|
|
1391
|
+
const spinner = (0, ora_1.default)('Updating access grant...').start();
|
|
1392
|
+
log('PATCH /access/' + grantId);
|
|
1393
|
+
try {
|
|
1394
|
+
const body = {};
|
|
1395
|
+
if (options.price) {
|
|
1396
|
+
body.price_amount = parseFloat(options.price);
|
|
1397
|
+
body.price_currency = options.currency;
|
|
1398
|
+
body.price_unit = options.unit;
|
|
1399
|
+
}
|
|
1400
|
+
if (options.discount) {
|
|
1401
|
+
body.discount_percent = parseFloat(options.discount);
|
|
1402
|
+
}
|
|
1403
|
+
if (options.clearDiscount) {
|
|
1404
|
+
body.discount_percent = null;
|
|
1405
|
+
}
|
|
1406
|
+
if (options.skillPricing) {
|
|
1407
|
+
body.skill_pricing = JSON.parse(options.skillPricing);
|
|
1408
|
+
}
|
|
1409
|
+
if (options.clearSkillPricing) {
|
|
1410
|
+
body.skill_pricing = null;
|
|
1411
|
+
}
|
|
1412
|
+
const res = await fetch(`${API_URL}/access/${grantId}`, {
|
|
1413
|
+
method: 'PATCH',
|
|
1414
|
+
headers: {
|
|
1415
|
+
'Content-Type': 'application/json',
|
|
1416
|
+
'X-Session-ID': sessionId,
|
|
1417
|
+
},
|
|
1418
|
+
body: JSON.stringify(body),
|
|
1419
|
+
});
|
|
1420
|
+
if (!res.ok) {
|
|
1421
|
+
const err = await res.json();
|
|
1422
|
+
throw new Error(err.error || 'Failed to update grant');
|
|
1333
1423
|
}
|
|
1424
|
+
spinner.succeed('Access grant updated');
|
|
1334
1425
|
}
|
|
1335
1426
|
catch (err) {
|
|
1336
1427
|
spinner.fail(chalk_1.default.red(err.message));
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1375,7 +1375,11 @@ ${chalk.bold('Examples:')}
|
|
|
1375
1375
|
access
|
|
1376
1376
|
.command('list')
|
|
1377
1377
|
.description('List access requests to your agents')
|
|
1378
|
-
.option('--
|
|
1378
|
+
.option('--agent <agentId>', 'Filter by agent ID')
|
|
1379
|
+
.option('--status <status>', 'Filter by status (pending, approved, rejected, all)', 'pending')
|
|
1380
|
+
.option('--search <query>', 'Search by requester name or ID')
|
|
1381
|
+
.option('--limit <n>', 'Max results (default 50)', '50')
|
|
1382
|
+
.option('--offset <n>', 'Skip first N results', '0')
|
|
1379
1383
|
.option('--json', 'Output as JSON')
|
|
1380
1384
|
.action(async (options) => {
|
|
1381
1385
|
const sessionId = config.get('sessionId') as string;
|
|
@@ -1386,10 +1390,19 @@ access
|
|
|
1386
1390
|
}
|
|
1387
1391
|
|
|
1388
1392
|
const spinner = ora('Fetching access requests...').start();
|
|
1389
|
-
|
|
1393
|
+
|
|
1394
|
+
// Build query params
|
|
1395
|
+
const params = new URLSearchParams();
|
|
1396
|
+
if (options.agent) params.set('agent', options.agent);
|
|
1397
|
+
if (options.status && options.status !== 'all') params.set('status', options.status);
|
|
1398
|
+
if (options.search) params.set('search', options.search);
|
|
1399
|
+
params.set('limit', options.limit);
|
|
1400
|
+
params.set('offset', options.offset);
|
|
1401
|
+
|
|
1402
|
+
log('GET /access/inbound?' + params.toString());
|
|
1390
1403
|
|
|
1391
1404
|
try {
|
|
1392
|
-
const res = await fetch(`${API_URL}/access/inbound`, {
|
|
1405
|
+
const res = await fetch(`${API_URL}/access/inbound?${params}`, {
|
|
1393
1406
|
headers: { 'X-Session-ID': sessionId },
|
|
1394
1407
|
});
|
|
1395
1408
|
|
|
@@ -1400,30 +1413,33 @@ access
|
|
|
1400
1413
|
const data = await res.json();
|
|
1401
1414
|
spinner.stop();
|
|
1402
1415
|
|
|
1403
|
-
// Filter by status
|
|
1404
|
-
const filtered = options.status === 'all'
|
|
1405
|
-
? data.grants
|
|
1406
|
-
: data.grants.filter((g: any) => g.status === options.status);
|
|
1407
|
-
|
|
1408
1416
|
if (options.json) {
|
|
1409
|
-
console.log(JSON.stringify(
|
|
1417
|
+
console.log(JSON.stringify(data.grants, null, 2));
|
|
1410
1418
|
return;
|
|
1411
1419
|
}
|
|
1412
1420
|
|
|
1413
|
-
if (
|
|
1414
|
-
console.log(chalk.gray(`\nNo ${options.status}
|
|
1421
|
+
if (data.grants.length === 0) {
|
|
1422
|
+
console.log(chalk.gray(`\nNo ${options.status === 'all' ? '' : options.status + ' '}access requests found.`));
|
|
1423
|
+
if (options.agent) console.log(chalk.gray(` Agent filter: ${options.agent}`));
|
|
1424
|
+
if (options.search) console.log(chalk.gray(` Search: "${options.search}"`));
|
|
1415
1425
|
return;
|
|
1416
1426
|
}
|
|
1417
1427
|
|
|
1418
|
-
console.log(chalk.bold(`\nš ${options.
|
|
1428
|
+
console.log(chalk.bold(`\nš Access Requests${options.agent ? ` for ${options.agent}` : ''}:\n`));
|
|
1419
1429
|
|
|
1420
|
-
for (const grant of
|
|
1430
|
+
for (const grant of data.grants) {
|
|
1421
1431
|
const statusColor = grant.status === 'pending' ? chalk.yellow :
|
|
1422
1432
|
grant.status === 'approved' ? chalk.green : chalk.red;
|
|
1423
1433
|
console.log(` ${chalk.cyan(grant.id)}`);
|
|
1424
1434
|
console.log(` From: ${grant.requester_agent_name || grant.requester_agent_id || 'Unknown'}`);
|
|
1425
1435
|
console.log(` To: ${grant.target_agent_name || grant.target_agent_id}`);
|
|
1426
1436
|
console.log(` Status: ${statusColor(grant.status)}`);
|
|
1437
|
+
if (grant.price_amount != null) {
|
|
1438
|
+
console.log(` Price: ${grant.price_amount} ${grant.price_currency}/${grant.price_unit}`);
|
|
1439
|
+
}
|
|
1440
|
+
if (grant.discount_percent != null) {
|
|
1441
|
+
console.log(` Discount: ${grant.discount_percent}%`);
|
|
1442
|
+
}
|
|
1427
1443
|
if (grant.requested_reason) {
|
|
1428
1444
|
console.log(` Reason: ${chalk.gray(grant.requested_reason)}`);
|
|
1429
1445
|
}
|
|
@@ -1431,8 +1447,13 @@ access
|
|
|
1431
1447
|
console.log('');
|
|
1432
1448
|
}
|
|
1433
1449
|
|
|
1434
|
-
|
|
1435
|
-
|
|
1450
|
+
// Pagination info
|
|
1451
|
+
if (data.grants.length >= parseInt(options.limit)) {
|
|
1452
|
+
console.log(chalk.gray(`Showing ${data.grants.length} results. Use --offset ${parseInt(options.offset) + parseInt(options.limit)} for next page.`));
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
if (options.status === 'pending' && data.grants.length > 0) {
|
|
1456
|
+
console.log(chalk.gray(`\nApprove: gopherhole access approve <id>`));
|
|
1436
1457
|
console.log(chalk.gray(`Reject: gopherhole access reject <id>`));
|
|
1437
1458
|
}
|
|
1438
1459
|
} catch (err) {
|
|
@@ -1444,10 +1465,11 @@ access
|
|
|
1444
1465
|
access
|
|
1445
1466
|
.command('approve <grantId>')
|
|
1446
1467
|
.description('Approve an access request')
|
|
1447
|
-
.option('--price <amount>', 'Set custom price
|
|
1468
|
+
.option('--price <amount>', 'Set custom price (e.g., 0.01)')
|
|
1448
1469
|
.option('--currency <code>', 'Currency code (default: USD)', 'USD')
|
|
1449
1470
|
.option('--unit <unit>', 'Price unit (request, message, task, month)', 'request')
|
|
1450
|
-
.option('--
|
|
1471
|
+
.option('--discount <percent>', 'Discount off default price (e.g., 20 for 20% off)')
|
|
1472
|
+
.option('--skill-pricing <json>', 'Per-skill pricing as JSON (e.g., \'{"translate":{"amount":0.05,"currency":"USD","unit":"request"}}\')')
|
|
1451
1473
|
.action(async (grantId, options) => {
|
|
1452
1474
|
const sessionId = config.get('sessionId') as string;
|
|
1453
1475
|
if (!sessionId) {
|
|
@@ -1466,6 +1488,12 @@ access
|
|
|
1466
1488
|
body.price_currency = options.currency;
|
|
1467
1489
|
body.price_unit = options.unit;
|
|
1468
1490
|
}
|
|
1491
|
+
if (options.discount) {
|
|
1492
|
+
body.discount_percent = parseFloat(options.discount);
|
|
1493
|
+
}
|
|
1494
|
+
if (options.skillPricing) {
|
|
1495
|
+
body.skill_pricing = JSON.parse(options.skillPricing);
|
|
1496
|
+
}
|
|
1469
1497
|
|
|
1470
1498
|
const res = await fetch(`${API_URL}/access/${grantId}/approve`, {
|
|
1471
1499
|
method: 'PUT',
|
|
@@ -1484,8 +1512,73 @@ access
|
|
|
1484
1512
|
spinner.succeed('Access request approved');
|
|
1485
1513
|
|
|
1486
1514
|
if (options.price) {
|
|
1487
|
-
console.log(chalk.gray(` Custom
|
|
1515
|
+
console.log(chalk.gray(` Custom price: ${options.price} ${options.currency}/${options.unit}`));
|
|
1488
1516
|
}
|
|
1517
|
+
if (options.discount) {
|
|
1518
|
+
console.log(chalk.gray(` Discount: ${options.discount}% off`));
|
|
1519
|
+
}
|
|
1520
|
+
} catch (err) {
|
|
1521
|
+
spinner.fail(chalk.red((err as Error).message));
|
|
1522
|
+
process.exit(1);
|
|
1523
|
+
}
|
|
1524
|
+
});
|
|
1525
|
+
|
|
1526
|
+
access
|
|
1527
|
+
.command('edit <grantId>')
|
|
1528
|
+
.description('Edit pricing on an existing access grant')
|
|
1529
|
+
.option('--price <amount>', 'Set custom price (e.g., 0.01)')
|
|
1530
|
+
.option('--currency <code>', 'Currency code', 'USD')
|
|
1531
|
+
.option('--unit <unit>', 'Price unit (request, message, task, month)')
|
|
1532
|
+
.option('--discount <percent>', 'Discount off default price (e.g., 20 for 20% off)')
|
|
1533
|
+
.option('--clear-discount', 'Remove discount')
|
|
1534
|
+
.option('--skill-pricing <json>', 'Per-skill pricing as JSON')
|
|
1535
|
+
.option('--clear-skill-pricing', 'Remove per-skill pricing')
|
|
1536
|
+
.action(async (grantId, options) => {
|
|
1537
|
+
const sessionId = config.get('sessionId') as string;
|
|
1538
|
+
if (!sessionId) {
|
|
1539
|
+
console.log(chalk.yellow('Not logged in.'));
|
|
1540
|
+
console.log(chalk.gray('Run: gopherhole login'));
|
|
1541
|
+
process.exit(1);
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
const spinner = ora('Updating access grant...').start();
|
|
1545
|
+
log('PATCH /access/' + grantId);
|
|
1546
|
+
|
|
1547
|
+
try {
|
|
1548
|
+
const body: any = {};
|
|
1549
|
+
if (options.price) {
|
|
1550
|
+
body.price_amount = parseFloat(options.price);
|
|
1551
|
+
body.price_currency = options.currency;
|
|
1552
|
+
body.price_unit = options.unit;
|
|
1553
|
+
}
|
|
1554
|
+
if (options.discount) {
|
|
1555
|
+
body.discount_percent = parseFloat(options.discount);
|
|
1556
|
+
}
|
|
1557
|
+
if (options.clearDiscount) {
|
|
1558
|
+
body.discount_percent = null;
|
|
1559
|
+
}
|
|
1560
|
+
if (options.skillPricing) {
|
|
1561
|
+
body.skill_pricing = JSON.parse(options.skillPricing);
|
|
1562
|
+
}
|
|
1563
|
+
if (options.clearSkillPricing) {
|
|
1564
|
+
body.skill_pricing = null;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
const res = await fetch(`${API_URL}/access/${grantId}`, {
|
|
1568
|
+
method: 'PATCH',
|
|
1569
|
+
headers: {
|
|
1570
|
+
'Content-Type': 'application/json',
|
|
1571
|
+
'X-Session-ID': sessionId,
|
|
1572
|
+
},
|
|
1573
|
+
body: JSON.stringify(body),
|
|
1574
|
+
});
|
|
1575
|
+
|
|
1576
|
+
if (!res.ok) {
|
|
1577
|
+
const err = await res.json();
|
|
1578
|
+
throw new Error(err.error || 'Failed to update grant');
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
spinner.succeed('Access grant updated');
|
|
1489
1582
|
} catch (err) {
|
|
1490
1583
|
spinner.fail(chalk.red((err as Error).message));
|
|
1491
1584
|
process.exit(1);
|