@gopherhole/cli 0.6.1 → 0.6.3

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 CHANGED
@@ -82,10 +82,39 @@ function makeHubClient(apiKey, transport) {
82
82
  const hubUrl = apiUrl.replace('https://', 'wss://').replace('http://', 'ws://') + '/ws';
83
83
  return new sdk_1.GopherHole({ apiKey, hubUrl, autoReconnect: false, transport: transport || 'http' });
84
84
  }
85
+ /** Load secrets for a target agent from .gopherhole/secrets/{alias}.json */
86
+ async function loadAgentSecrets(agentId) {
87
+ const fs = await import('fs');
88
+ const path = await import('path');
89
+ const filePath = path.join(process.cwd(), '.gopherhole', 'secrets', `${agentId}.json`);
90
+ if (!fs.existsSync(filePath))
91
+ return null;
92
+ try {
93
+ const raw = fs.readFileSync(filePath, 'utf-8');
94
+ const parsed = JSON.parse(raw);
95
+ if (typeof parsed !== 'object' || parsed === null)
96
+ return null;
97
+ const secrets = {};
98
+ for (const [k, v] of Object.entries(parsed)) {
99
+ if (typeof v === 'string')
100
+ secrets[k] = v;
101
+ }
102
+ return Object.keys(secrets).length > 0 ? secrets : null;
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ }
85
108
  /** Send a message and poll until terminal state, return response text.
86
109
  * Matches the MCP client pattern: sendText → poll getTask. */
87
- async function askAgent(client, agentId, text) {
88
- const task = await client.sendText(agentId, text);
110
+ async function askAgent(client, agentId, text, opts) {
111
+ const config = {};
112
+ if (opts?.secrets)
113
+ config['x-gopherhole-secrets'] = opts.secrets;
114
+ if (opts?.ttl !== undefined)
115
+ config['x-ttl'] = opts.ttl;
116
+ const sendConfig = Object.keys(config).length > 0 ? config : undefined;
117
+ const task = await client.sendText(agentId, text, sendConfig);
89
118
  const terminalStates = ['completed', 'failed', 'canceled', 'rejected'];
90
119
  let current = task;
91
120
  const start = Date.now();
@@ -1283,6 +1312,7 @@ ${chalk_1.default.bold('Examples:')}
1283
1312
  console.log(chalk_1.default.gray('Run: gopherhole login'));
1284
1313
  process.exit(1);
1285
1314
  }
1315
+ const secrets = await loadAgentSecrets(agentId);
1286
1316
  const spinner = (0, ora_1.default)(`Sending to ${agentId}...`).start();
1287
1317
  log('POST /a2a SendMessage', { to: agentId, message });
1288
1318
  try {
@@ -1300,6 +1330,7 @@ ${chalk_1.default.bold('Examples:')}
1300
1330
  configuration: {
1301
1331
  agentId,
1302
1332
  ...(cmdOpts.ttl !== undefined ? { 'x-ttl': cmdOpts.ttl } : {}),
1333
+ ...(secrets ? { 'x-gopherhole-secrets': secrets } : {}),
1303
1334
  },
1304
1335
  },
1305
1336
  id: 1,
@@ -2565,10 +2596,11 @@ ${chalk_1.default.bold('Examples:')}
2565
2596
  process.exit(1);
2566
2597
  }
2567
2598
  log(`Transport: http (A2AClient is HTTP-only)`);
2599
+ const secrets = await loadAgentSecrets(agentId);
2568
2600
  const spinner = (0, ora_1.default)(`Messaging ${agentId}...`).start();
2569
2601
  try {
2570
2602
  const client = makeAgentClient(apiKey);
2571
- const response = await askAgent(client, agentId, text);
2603
+ const response = await askAgent(client, agentId, text, secrets ? { secrets } : undefined);
2572
2604
  spinner.stop();
2573
2605
  console.log(response || chalk_1.default.gray('(no response)'));
2574
2606
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gopherhole/cli",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "GopherHole CLI - Connect AI agents to the world",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
  "author": "GopherHole",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@gopherhole/sdk": "^0.7.2",
25
+ "@gopherhole/sdk": "^0.7.5",
26
26
  "chalk": "^5.3.0",
27
27
  "commander": "^12.0.0",
28
28
  "conf": "^12.0.0",
@@ -38,4 +38,4 @@
38
38
  "ts-node": "^10.9.2",
39
39
  "typescript": "^5.3.0"
40
40
  }
41
- }
41
+ }
package/src/index.ts CHANGED
@@ -85,10 +85,34 @@ function makeHubClient(apiKey: string, transport?: TransportMode): GopherHole {
85
85
  return new GopherHole({ apiKey, hubUrl, autoReconnect: false, transport: transport || 'http' });
86
86
  }
87
87
 
88
+ /** Load secrets for a target agent from .gopherhole/secrets/{alias}.json */
89
+ async function loadAgentSecrets(agentId: string): Promise<Record<string, string> | null> {
90
+ const fs = await import('fs');
91
+ const path = await import('path');
92
+ const filePath = path.join(process.cwd(), '.gopherhole', 'secrets', `${agentId}.json`);
93
+ if (!fs.existsSync(filePath)) return null;
94
+ try {
95
+ const raw = fs.readFileSync(filePath, 'utf-8');
96
+ const parsed = JSON.parse(raw);
97
+ if (typeof parsed !== 'object' || parsed === null) return null;
98
+ const secrets: Record<string, string> = {};
99
+ for (const [k, v] of Object.entries(parsed)) {
100
+ if (typeof v === 'string') secrets[k] = v;
101
+ }
102
+ return Object.keys(secrets).length > 0 ? secrets : null;
103
+ } catch {
104
+ return null;
105
+ }
106
+ }
107
+
88
108
  /** Send a message and poll until terminal state, return response text.
89
109
  * Matches the MCP client pattern: sendText → poll getTask. */
90
- async function askAgent(client: A2AClient, agentId: string, text: string): Promise<string> {
91
- const task = await client.sendText(agentId, text);
110
+ async function askAgent(client: A2AClient, agentId: string, text: string, opts?: { secrets?: Record<string, string>; ttl?: number }): Promise<string> {
111
+ const config: Record<string, unknown> = {};
112
+ if (opts?.secrets) config['x-gopherhole-secrets'] = opts.secrets;
113
+ if (opts?.ttl !== undefined) config['x-ttl'] = opts.ttl;
114
+ const sendConfig = Object.keys(config).length > 0 ? config : undefined;
115
+ const task = await client.sendText(agentId, text, sendConfig as any);
92
116
 
93
117
  const terminalStates = ['completed', 'failed', 'canceled', 'rejected'];
94
118
  let current = task;
@@ -1418,6 +1442,7 @@ ${chalk.bold('Examples:')}
1418
1442
  process.exit(1);
1419
1443
  }
1420
1444
 
1445
+ const secrets = await loadAgentSecrets(agentId);
1421
1446
  const spinner = ora(`Sending to ${agentId}...`).start();
1422
1447
  log('POST /a2a SendMessage', { to: agentId, message });
1423
1448
 
@@ -1436,6 +1461,7 @@ ${chalk.bold('Examples:')}
1436
1461
  configuration: {
1437
1462
  agentId,
1438
1463
  ...(cmdOpts.ttl !== undefined ? { 'x-ttl': cmdOpts.ttl } : {}),
1464
+ ...(secrets ? { 'x-gopherhole-secrets': secrets } : {}),
1439
1465
  },
1440
1466
  },
1441
1467
  id: 1,
@@ -2795,10 +2821,11 @@ ${chalk.bold('Examples:')}
2795
2821
  }
2796
2822
 
2797
2823
  log(`Transport: http (A2AClient is HTTP-only)`);
2824
+ const secrets = await loadAgentSecrets(agentId);
2798
2825
  const spinner = ora(`Messaging ${agentId}...`).start();
2799
2826
  try {
2800
2827
  const client = makeAgentClient(apiKey);
2801
- const response = await askAgent(client, agentId, text);
2828
+ const response = await askAgent(client, agentId, text, secrets ? { secrets } : undefined);
2802
2829
  spinner.stop();
2803
2830
  console.log(response || chalk.gray('(no response)'));
2804
2831
  } catch (err) {