@gopherhole/cli 0.6.0 → 0.6.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/dist/index.js +60 -1
- package/package.json +1 -1
- package/src/index.ts +65 -1
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ const brand = {
|
|
|
20
20
|
greenDark: chalk_1.default.hex('#16a34a'), // gopher-600 - emphasis
|
|
21
21
|
};
|
|
22
22
|
// Version
|
|
23
|
-
const VERSION = '0.6.
|
|
23
|
+
const VERSION = '0.6.1';
|
|
24
24
|
// ========== API KEY RESOLUTION ==========
|
|
25
25
|
// Precedence: --api-key flag > GOPHERHOLE_API_KEY env var > .env file in cwd
|
|
26
26
|
async function resolveApiKey(flagValue) {
|
|
@@ -2577,6 +2577,65 @@ ${chalk_1.default.bold('Examples:')}
|
|
|
2577
2577
|
process.exit(1);
|
|
2578
2578
|
}
|
|
2579
2579
|
});
|
|
2580
|
+
// ========== REQUEST ACCESS (agent-to-agent via API key) ==========
|
|
2581
|
+
program
|
|
2582
|
+
.command('request-access <agentId>')
|
|
2583
|
+
.description(`Request access to another agent (agent-to-agent, uses API key)
|
|
2584
|
+
|
|
2585
|
+
If the target has auto-approve enabled, access is granted immediately.
|
|
2586
|
+
Otherwise it's queued for manual approval by the target tenant.
|
|
2587
|
+
|
|
2588
|
+
${chalk_1.default.bold('Examples:')}
|
|
2589
|
+
$ gopherhole request-access agent-abc123
|
|
2590
|
+
$ gopherhole request-access agent-abc123 --reason "Need data feed"
|
|
2591
|
+
$ gopherhole request-access agent-abc123 --scopes "messages:send,memory:read"
|
|
2592
|
+
`)
|
|
2593
|
+
.option('--api-key <key>', 'API key (overrides env / .env)')
|
|
2594
|
+
.option('--scopes <scopes>', 'Comma-separated scopes to request (default: messages:send)')
|
|
2595
|
+
.option('--reason <text>', 'Reason for the request (shown to target tenant)')
|
|
2596
|
+
.action(async (agentId, options) => {
|
|
2597
|
+
const apiKey = await resolveApiKey(options.apiKey);
|
|
2598
|
+
if (!apiKey) {
|
|
2599
|
+
console.error(chalk_1.default.red('No API key found.'));
|
|
2600
|
+
console.error(chalk_1.default.gray('Set GOPHERHOLE_API_KEY, pass --api-key, or run gopherhole init'));
|
|
2601
|
+
process.exit(1);
|
|
2602
|
+
}
|
|
2603
|
+
const scopes = options.scopes
|
|
2604
|
+
? options.scopes.split(',').map((s) => s.trim())
|
|
2605
|
+
: ['messages:send'];
|
|
2606
|
+
const spinner = (0, ora_1.default)(`Requesting access to ${agentId}...`).start();
|
|
2607
|
+
try {
|
|
2608
|
+
const res = await fetch(`${API_URL}/access/request`, {
|
|
2609
|
+
method: 'POST',
|
|
2610
|
+
headers: {
|
|
2611
|
+
'Content-Type': 'application/json',
|
|
2612
|
+
Authorization: `Bearer ${apiKey}`,
|
|
2613
|
+
},
|
|
2614
|
+
body: JSON.stringify({
|
|
2615
|
+
targetAgentId: agentId,
|
|
2616
|
+
scopes,
|
|
2617
|
+
reason: options.reason,
|
|
2618
|
+
}),
|
|
2619
|
+
});
|
|
2620
|
+
if (!res.ok) {
|
|
2621
|
+
const err = await res.json().catch(() => ({}));
|
|
2622
|
+
throw new Error(err.error || `HTTP ${res.status}`);
|
|
2623
|
+
}
|
|
2624
|
+
const data = await res.json();
|
|
2625
|
+
if (data.grant.status === 'approved') {
|
|
2626
|
+
spinner.succeed(`Access granted immediately (auto-approved). You can now message ${chalk_1.default.cyan(agentId)}.`);
|
|
2627
|
+
}
|
|
2628
|
+
else {
|
|
2629
|
+
spinner.succeed(`Access request submitted (pending approval).`);
|
|
2630
|
+
}
|
|
2631
|
+
console.log(` Grant ID: ${chalk_1.default.cyan(data.grant.id)}`);
|
|
2632
|
+
console.log(` Status: ${data.grant.status}`);
|
|
2633
|
+
}
|
|
2634
|
+
catch (err) {
|
|
2635
|
+
spinner.fail(chalk_1.default.red(err.message));
|
|
2636
|
+
process.exit(1);
|
|
2637
|
+
}
|
|
2638
|
+
});
|
|
2580
2639
|
// ========== MEMORY COMMANDS (agent-to-agent via memory agent) ==========
|
|
2581
2640
|
const MEMORY_AGENT = process.env.GOPHERHOLE_MEMORY_AGENT || 'agent-memory-official';
|
|
2582
2641
|
const memory = program
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ const brand = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
// Version
|
|
23
|
-
const VERSION = '0.6.
|
|
23
|
+
const VERSION = '0.6.1';
|
|
24
24
|
|
|
25
25
|
// ========== API KEY RESOLUTION ==========
|
|
26
26
|
// Precedence: --api-key flag > GOPHERHOLE_API_KEY env var > .env file in cwd
|
|
@@ -2807,6 +2807,70 @@ ${chalk.bold('Examples:')}
|
|
|
2807
2807
|
}
|
|
2808
2808
|
});
|
|
2809
2809
|
|
|
2810
|
+
// ========== REQUEST ACCESS (agent-to-agent via API key) ==========
|
|
2811
|
+
|
|
2812
|
+
program
|
|
2813
|
+
.command('request-access <agentId>')
|
|
2814
|
+
.description(`Request access to another agent (agent-to-agent, uses API key)
|
|
2815
|
+
|
|
2816
|
+
If the target has auto-approve enabled, access is granted immediately.
|
|
2817
|
+
Otherwise it's queued for manual approval by the target tenant.
|
|
2818
|
+
|
|
2819
|
+
${chalk.bold('Examples:')}
|
|
2820
|
+
$ gopherhole request-access agent-abc123
|
|
2821
|
+
$ gopherhole request-access agent-abc123 --reason "Need data feed"
|
|
2822
|
+
$ gopherhole request-access agent-abc123 --scopes "messages:send,memory:read"
|
|
2823
|
+
`)
|
|
2824
|
+
.option('--api-key <key>', 'API key (overrides env / .env)')
|
|
2825
|
+
.option('--scopes <scopes>', 'Comma-separated scopes to request (default: messages:send)')
|
|
2826
|
+
.option('--reason <text>', 'Reason for the request (shown to target tenant)')
|
|
2827
|
+
.action(async (agentId, options) => {
|
|
2828
|
+
const apiKey = await resolveApiKey(options.apiKey);
|
|
2829
|
+
if (!apiKey) {
|
|
2830
|
+
console.error(chalk.red('No API key found.'));
|
|
2831
|
+
console.error(chalk.gray('Set GOPHERHOLE_API_KEY, pass --api-key, or run gopherhole init'));
|
|
2832
|
+
process.exit(1);
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
const scopes = options.scopes
|
|
2836
|
+
? options.scopes.split(',').map((s: string) => s.trim())
|
|
2837
|
+
: ['messages:send'];
|
|
2838
|
+
|
|
2839
|
+
const spinner = ora(`Requesting access to ${agentId}...`).start();
|
|
2840
|
+
try {
|
|
2841
|
+
const res = await fetch(`${API_URL}/access/request`, {
|
|
2842
|
+
method: 'POST',
|
|
2843
|
+
headers: {
|
|
2844
|
+
'Content-Type': 'application/json',
|
|
2845
|
+
Authorization: `Bearer ${apiKey}`,
|
|
2846
|
+
},
|
|
2847
|
+
body: JSON.stringify({
|
|
2848
|
+
targetAgentId: agentId,
|
|
2849
|
+
scopes,
|
|
2850
|
+
reason: options.reason,
|
|
2851
|
+
}),
|
|
2852
|
+
});
|
|
2853
|
+
|
|
2854
|
+
if (!res.ok) {
|
|
2855
|
+
const err = await res.json().catch(() => ({}));
|
|
2856
|
+
throw new Error((err as any).error || `HTTP ${res.status}`);
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
const data = await res.json() as { grant: { id: string; status: string } };
|
|
2860
|
+
|
|
2861
|
+
if (data.grant.status === 'approved') {
|
|
2862
|
+
spinner.succeed(`Access granted immediately (auto-approved). You can now message ${chalk.cyan(agentId)}.`);
|
|
2863
|
+
} else {
|
|
2864
|
+
spinner.succeed(`Access request submitted (pending approval).`);
|
|
2865
|
+
}
|
|
2866
|
+
console.log(` Grant ID: ${chalk.cyan(data.grant.id)}`);
|
|
2867
|
+
console.log(` Status: ${data.grant.status}`);
|
|
2868
|
+
} catch (err) {
|
|
2869
|
+
spinner.fail(chalk.red((err as Error).message));
|
|
2870
|
+
process.exit(1);
|
|
2871
|
+
}
|
|
2872
|
+
});
|
|
2873
|
+
|
|
2810
2874
|
// ========== MEMORY COMMANDS (agent-to-agent via memory agent) ==========
|
|
2811
2875
|
|
|
2812
2876
|
const MEMORY_AGENT = process.env.GOPHERHOLE_MEMORY_AGENT || 'agent-memory-official';
|