gopherhole_openclaw_a2a 0.2.8 → 0.3.0
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/src/channel.d.ts +1 -1
- package/dist/src/channel.js +12 -25
- package/dist/src/connection.js +6 -7
- package/dist/src/types.d.ts +17 -21
- package/package.json +1 -1
- package/src/channel.ts +32 -53
- package/src/connection.ts +6 -7
- package/src/types.ts +21 -21
package/dist/src/channel.d.ts
CHANGED
package/dist/src/channel.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A2A Channel Plugin for
|
|
2
|
+
* A2A Channel Plugin for OpenClaw
|
|
3
3
|
* Enables communication with other AI agents via A2A protocol
|
|
4
4
|
*/
|
|
5
5
|
// Use minimal type imports - mostly self-contained
|
|
@@ -25,10 +25,9 @@ function resolveA2AAccount(opts) {
|
|
|
25
25
|
accountId,
|
|
26
26
|
name: config.agentName ?? 'A2A',
|
|
27
27
|
enabled: config.enabled ?? false,
|
|
28
|
-
configured: !!(config.bridgeUrl
|
|
29
|
-
agentId: config.agentId ?? '
|
|
28
|
+
configured: !!(config.bridgeUrl && config.apiKey),
|
|
29
|
+
agentId: config.agentId ?? 'openclaw',
|
|
30
30
|
bridgeUrl: config.bridgeUrl ?? null,
|
|
31
|
-
agents: config.agents ?? [],
|
|
32
31
|
config,
|
|
33
32
|
};
|
|
34
33
|
}
|
|
@@ -39,9 +38,9 @@ const meta = {
|
|
|
39
38
|
detailLabel: 'A2A Protocol',
|
|
40
39
|
docsPath: '/channels/a2a',
|
|
41
40
|
docsLabel: 'a2a',
|
|
42
|
-
blurb: 'Communicate with other AI agents via A2A protocol.',
|
|
41
|
+
blurb: 'Communicate with other AI agents via GopherHole A2A protocol.',
|
|
43
42
|
systemImage: 'bubble.left.and.bubble.right',
|
|
44
|
-
aliases: ['agent2agent'],
|
|
43
|
+
aliases: ['agent2agent', 'gopherhole'],
|
|
45
44
|
order: 200,
|
|
46
45
|
};
|
|
47
46
|
export const a2aPlugin = {
|
|
@@ -98,8 +97,8 @@ export const a2aPlugin = {
|
|
|
98
97
|
messaging: {
|
|
99
98
|
normalizeTarget: (target) => target?.trim() ?? '',
|
|
100
99
|
targetResolver: {
|
|
101
|
-
looksLikeId: (id) => /^[a-z0-9_
|
|
102
|
-
hint: '<agentId>',
|
|
100
|
+
looksLikeId: (id) => /^[a-z0-9_@-]+$/i.test(id),
|
|
101
|
+
hint: '<agentId> (e.g. @memory, @echo)',
|
|
103
102
|
},
|
|
104
103
|
formatTargetDisplay: ({ target }) => target ?? '',
|
|
105
104
|
},
|
|
@@ -108,7 +107,7 @@ export const a2aPlugin = {
|
|
|
108
107
|
applyAccountName: ({ cfg }) => cfg,
|
|
109
108
|
validateInput: ({ input }) => {
|
|
110
109
|
if (!input.httpUrl && !input.customArgs) {
|
|
111
|
-
return 'A2A requires --http-url (bridge URL) or
|
|
110
|
+
return 'A2A requires --http-url (bridge URL) or bridgeUrl + apiKey in config.';
|
|
112
111
|
}
|
|
113
112
|
return null;
|
|
114
113
|
},
|
|
@@ -211,7 +210,7 @@ export const a2aPlugin = {
|
|
|
211
210
|
.join('\n') ?? '';
|
|
212
211
|
if (!text)
|
|
213
212
|
return;
|
|
214
|
-
// Route to
|
|
213
|
+
// Route to OpenClaw's reply pipeline via gateway JSON-RPC
|
|
215
214
|
try {
|
|
216
215
|
ctx.log?.info(`[a2a] Routing message from ${message.from}: "${text.slice(0, 100)}..."`);
|
|
217
216
|
// Use chat.send to route the message through the agent
|
|
@@ -219,26 +218,14 @@ export const a2aPlugin = {
|
|
|
219
218
|
const sessionKey = `agent:main:a2a:${message.from}`;
|
|
220
219
|
const response = await sendChatMessage(sessionKey, text);
|
|
221
220
|
ctx.log?.info(`[a2a] chat.send returned: ${response ? `text=${response.text?.slice(0, 50)}...` : 'null'}`);
|
|
222
|
-
// Send response back to the agent
|
|
221
|
+
// Send response back to the agent via GopherHole
|
|
223
222
|
if (response?.text) {
|
|
224
|
-
|
|
225
|
-
if (agentId === 'gopherhole' && message.from) {
|
|
226
|
-
connectionManager?.sendResponseViaGopherHole(message.from, message.taskId, response.text, message.contextId);
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
connectionManager?.sendResponse(agentId, message.taskId, response.text, message.contextId);
|
|
230
|
-
}
|
|
223
|
+
connectionManager?.sendResponseViaGopherHole(message.from, message.taskId, response.text, message.contextId);
|
|
231
224
|
}
|
|
232
225
|
}
|
|
233
226
|
catch (err) {
|
|
234
227
|
ctx.log?.error(`[a2a] Error handling message:`, err);
|
|
235
|
-
|
|
236
|
-
if (agentId === 'gopherhole' && message.from) {
|
|
237
|
-
connectionManager?.sendResponseViaGopherHole(message.from, message.taskId, `Error: ${err.message}`, message.contextId);
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
connectionManager?.sendResponse(agentId, message.taskId, `Error: ${err.message}`, message.contextId);
|
|
241
|
-
}
|
|
228
|
+
connectionManager?.sendResponseViaGopherHole(message.from, message.taskId, `Error: ${err.message}`, message.contextId);
|
|
242
229
|
}
|
|
243
230
|
}
|
|
244
231
|
});
|
package/dist/src/connection.js
CHANGED
|
@@ -11,30 +11,29 @@ export class A2AConnectionManager {
|
|
|
11
11
|
connected = false;
|
|
12
12
|
constructor(config) {
|
|
13
13
|
this.config = config;
|
|
14
|
-
this.agentId = config.agentId ?? '
|
|
14
|
+
this.agentId = config.agentId ?? 'openclaw';
|
|
15
15
|
}
|
|
16
16
|
setMessageHandler(handler) {
|
|
17
17
|
this.messageHandler = handler;
|
|
18
18
|
}
|
|
19
19
|
async start() {
|
|
20
|
-
// Connect to GopherHole if configured
|
|
21
|
-
if (this.config.
|
|
20
|
+
// Connect to GopherHole if configured (flat config: enabled + apiKey)
|
|
21
|
+
if (this.config.enabled && this.config.apiKey) {
|
|
22
22
|
await this.connectToGopherHole();
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
async connectToGopherHole() {
|
|
26
|
-
const
|
|
27
|
-
const hubUrl = gphConfig.hubUrl || 'wss://gopherhole.ai/ws';
|
|
26
|
+
const hubUrl = this.config.bridgeUrl || 'wss://gopherhole.ai/ws';
|
|
28
27
|
const timeoutMs = this.config.requestTimeoutMs ?? 180000;
|
|
29
28
|
this.gopherhole = new GopherHole({
|
|
30
|
-
apiKey:
|
|
29
|
+
apiKey: this.config.apiKey,
|
|
31
30
|
hubUrl,
|
|
32
31
|
autoReconnect: true,
|
|
33
32
|
reconnectDelay: this.config.reconnectIntervalMs ?? 5000,
|
|
34
33
|
maxReconnectAttempts: 20,
|
|
35
34
|
requestTimeout: timeoutMs,
|
|
36
35
|
messageTimeout: timeoutMs,
|
|
37
|
-
agentCard:
|
|
36
|
+
agentCard: this.config.agentCard ?? {
|
|
38
37
|
name: this.config.agentName ?? 'OpenClaw',
|
|
39
38
|
description: 'Personal AI assistant with tools, web search, browser control, and various skills',
|
|
40
39
|
version: '0.1.0',
|
package/dist/src/types.d.ts
CHANGED
|
@@ -39,26 +39,27 @@ export interface A2AResponse {
|
|
|
39
39
|
status: string;
|
|
40
40
|
from?: string;
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* A2A Channel Config (flat structure)
|
|
44
|
+
*
|
|
45
|
+
* Example:
|
|
46
|
+
* {
|
|
47
|
+
* "channels": {
|
|
48
|
+
* "a2a": {
|
|
49
|
+
* "enabled": true,
|
|
50
|
+
* "bridgeUrl": "wss://gopherhole.ai/ws",
|
|
51
|
+
* "apiKey": "gph_your_api_key"
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
*/
|
|
42
56
|
export interface A2AChannelConfig {
|
|
43
57
|
enabled?: boolean;
|
|
58
|
+
bridgeUrl?: string;
|
|
59
|
+
apiKey?: string;
|
|
44
60
|
agentId?: string;
|
|
45
61
|
agentName?: string;
|
|
46
|
-
|
|
47
|
-
agents?: Array<{
|
|
48
|
-
id: string;
|
|
49
|
-
url: string;
|
|
50
|
-
name?: string;
|
|
51
|
-
}>;
|
|
52
|
-
gopherhole?: {
|
|
53
|
-
enabled?: boolean;
|
|
54
|
-
apiKey: string;
|
|
55
|
-
hubUrl?: string;
|
|
56
|
-
requestTimeoutMs?: number;
|
|
57
|
-
agentCard?: A2AAgentCard;
|
|
58
|
-
};
|
|
59
|
-
auth?: {
|
|
60
|
-
token?: string;
|
|
61
|
-
};
|
|
62
|
+
agentCard?: A2AAgentCard;
|
|
62
63
|
reconnectIntervalMs?: number;
|
|
63
64
|
requestTimeoutMs?: number;
|
|
64
65
|
}
|
|
@@ -69,10 +70,5 @@ export interface ResolvedA2AAccount {
|
|
|
69
70
|
configured: boolean;
|
|
70
71
|
agentId: string;
|
|
71
72
|
bridgeUrl: string | null;
|
|
72
|
-
agents: Array<{
|
|
73
|
-
id: string;
|
|
74
|
-
url: string;
|
|
75
|
-
name?: string;
|
|
76
|
-
}>;
|
|
77
73
|
config: A2AChannelConfig;
|
|
78
74
|
}
|
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A2A Channel Plugin for
|
|
2
|
+
* A2A Channel Plugin for OpenClaw
|
|
3
3
|
* Enables communication with other AI agents via A2A protocol
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
} from './types.js';
|
|
19
19
|
|
|
20
20
|
// Minimal runtime interface - what we actually need
|
|
21
|
-
interface
|
|
21
|
+
interface OpenClawRuntime {
|
|
22
22
|
handleInbound(params: {
|
|
23
23
|
channel: string;
|
|
24
24
|
chatId: string;
|
|
@@ -32,14 +32,14 @@ interface ClawdbotRuntime {
|
|
|
32
32
|
|
|
33
33
|
// Runtime state
|
|
34
34
|
let connectionManager: A2AConnectionManager | null = null;
|
|
35
|
-
let currentRuntime:
|
|
35
|
+
let currentRuntime: OpenClawRuntime | null = null;
|
|
36
36
|
|
|
37
37
|
export function setA2ARuntime(runtime: unknown): void {
|
|
38
|
-
currentRuntime = runtime as
|
|
38
|
+
currentRuntime = runtime as OpenClawRuntime;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
-
type
|
|
42
|
+
type OpenClawConfig = any;
|
|
43
43
|
|
|
44
44
|
// Minimal channel plugin interfaces (self-contained)
|
|
45
45
|
interface ChannelAccountSnapshot {
|
|
@@ -85,12 +85,12 @@ type ChannelPlugin<T = any> = {
|
|
|
85
85
|
};
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
-
function resolveA2AConfig(cfg:
|
|
88
|
+
function resolveA2AConfig(cfg: OpenClawConfig): A2AChannelConfig {
|
|
89
89
|
return cfg?.channels?.a2a ?? {};
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function resolveA2AAccount(opts: {
|
|
93
|
-
cfg:
|
|
93
|
+
cfg: OpenClawConfig;
|
|
94
94
|
accountId?: string;
|
|
95
95
|
}): ResolvedA2AAccount {
|
|
96
96
|
const config = resolveA2AConfig(opts.cfg);
|
|
@@ -100,10 +100,9 @@ function resolveA2AAccount(opts: {
|
|
|
100
100
|
accountId,
|
|
101
101
|
name: config.agentName ?? 'A2A',
|
|
102
102
|
enabled: config.enabled ?? false,
|
|
103
|
-
configured: !!(config.bridgeUrl
|
|
104
|
-
agentId: config.agentId ?? '
|
|
103
|
+
configured: !!(config.bridgeUrl && config.apiKey),
|
|
104
|
+
agentId: config.agentId ?? 'openclaw',
|
|
105
105
|
bridgeUrl: config.bridgeUrl ?? null,
|
|
106
|
-
agents: config.agents ?? [],
|
|
107
106
|
config,
|
|
108
107
|
};
|
|
109
108
|
}
|
|
@@ -115,9 +114,9 @@ const meta = {
|
|
|
115
114
|
detailLabel: 'A2A Protocol',
|
|
116
115
|
docsPath: '/channels/a2a',
|
|
117
116
|
docsLabel: 'a2a',
|
|
118
|
-
blurb: 'Communicate with other AI agents via A2A protocol.',
|
|
117
|
+
blurb: 'Communicate with other AI agents via GopherHole A2A protocol.',
|
|
119
118
|
systemImage: 'bubble.left.and.bubble.right',
|
|
120
|
-
aliases: ['agent2agent'],
|
|
119
|
+
aliases: ['agent2agent', 'gopherhole'],
|
|
121
120
|
order: 200,
|
|
122
121
|
};
|
|
123
122
|
|
|
@@ -136,10 +135,10 @@ export const a2aPlugin: ChannelPlugin<ResolvedA2AAccount> = {
|
|
|
136
135
|
config: {
|
|
137
136
|
listAccountIds: () => [DEFAULT_ACCOUNT_ID],
|
|
138
137
|
resolveAccount: (cfg, accountId) =>
|
|
139
|
-
resolveA2AAccount({ cfg: cfg as
|
|
138
|
+
resolveA2AAccount({ cfg: cfg as OpenClawConfig, accountId }),
|
|
140
139
|
defaultAccountId: () => DEFAULT_ACCOUNT_ID,
|
|
141
140
|
setAccountEnabled: ({ cfg, enabled }) => {
|
|
142
|
-
const next = cfg as
|
|
141
|
+
const next = cfg as OpenClawConfig;
|
|
143
142
|
return {
|
|
144
143
|
...next,
|
|
145
144
|
channels: {
|
|
@@ -149,9 +148,9 @@ export const a2aPlugin: ChannelPlugin<ResolvedA2AAccount> = {
|
|
|
149
148
|
enabled,
|
|
150
149
|
},
|
|
151
150
|
},
|
|
152
|
-
} as
|
|
151
|
+
} as OpenClawConfig;
|
|
153
152
|
},
|
|
154
|
-
deleteAccount: ({ cfg }) => cfg as
|
|
153
|
+
deleteAccount: ({ cfg }) => cfg as OpenClawConfig,
|
|
155
154
|
isConfigured: (account) => account.configured,
|
|
156
155
|
describeAccount: (account): ChannelAccountSnapshot => ({
|
|
157
156
|
accountId: account.accountId,
|
|
@@ -176,22 +175,22 @@ export const a2aPlugin: ChannelPlugin<ResolvedA2AAccount> = {
|
|
|
176
175
|
messaging: {
|
|
177
176
|
normalizeTarget: (target) => target?.trim() ?? '',
|
|
178
177
|
targetResolver: {
|
|
179
|
-
looksLikeId: (id) => /^[a-z0-9_
|
|
180
|
-
hint: '<agentId>',
|
|
178
|
+
looksLikeId: (id) => /^[a-z0-9_@-]+$/i.test(id),
|
|
179
|
+
hint: '<agentId> (e.g. @memory, @echo)',
|
|
181
180
|
},
|
|
182
181
|
formatTargetDisplay: ({ target }) => target ?? '',
|
|
183
182
|
},
|
|
184
183
|
setup: {
|
|
185
184
|
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
|
186
|
-
applyAccountName: ({ cfg }) => cfg as
|
|
185
|
+
applyAccountName: ({ cfg }) => cfg as OpenClawConfig,
|
|
187
186
|
validateInput: ({ input }) => {
|
|
188
187
|
if (!input.httpUrl && !input.customArgs) {
|
|
189
|
-
return 'A2A requires --http-url (bridge URL) or
|
|
188
|
+
return 'A2A requires --http-url (bridge URL) or bridgeUrl + apiKey in config.';
|
|
190
189
|
}
|
|
191
190
|
return null;
|
|
192
191
|
},
|
|
193
192
|
applyAccountConfig: ({ cfg, input }) => {
|
|
194
|
-
const next = cfg as
|
|
193
|
+
const next = cfg as OpenClawConfig;
|
|
195
194
|
return {
|
|
196
195
|
...next,
|
|
197
196
|
channels: {
|
|
@@ -202,7 +201,7 @@ export const a2aPlugin: ChannelPlugin<ResolvedA2AAccount> = {
|
|
|
202
201
|
...(input.httpUrl ? { bridgeUrl: input.httpUrl } : {}),
|
|
203
202
|
},
|
|
204
203
|
},
|
|
205
|
-
} as
|
|
204
|
+
} as OpenClawConfig;
|
|
206
205
|
},
|
|
207
206
|
},
|
|
208
207
|
outbound: {
|
|
@@ -292,7 +291,7 @@ export const a2aPlugin: ChannelPlugin<ResolvedA2AAccount> = {
|
|
|
292
291
|
|
|
293
292
|
if (!text) return;
|
|
294
293
|
|
|
295
|
-
// Route to
|
|
294
|
+
// Route to OpenClaw's reply pipeline via gateway JSON-RPC
|
|
296
295
|
try {
|
|
297
296
|
ctx.log?.info(`[a2a] Routing message from ${message.from}: "${text.slice(0, 100)}..."`);
|
|
298
297
|
|
|
@@ -303,43 +302,23 @@ export const a2aPlugin: ChannelPlugin<ResolvedA2AAccount> = {
|
|
|
303
302
|
|
|
304
303
|
ctx.log?.info(`[a2a] chat.send returned: ${response ? `text=${response.text?.slice(0, 50)}...` : 'null'}`);
|
|
305
304
|
|
|
306
|
-
// Send response back to the agent
|
|
305
|
+
// Send response back to the agent via GopherHole
|
|
307
306
|
if (response?.text) {
|
|
308
|
-
// If message came via GopherHole, route response back through it
|
|
309
|
-
if (agentId === 'gopherhole' && message.from) {
|
|
310
|
-
connectionManager?.sendResponseViaGopherHole(
|
|
311
|
-
message.from,
|
|
312
|
-
message.taskId,
|
|
313
|
-
response.text,
|
|
314
|
-
message.contextId
|
|
315
|
-
);
|
|
316
|
-
} else {
|
|
317
|
-
connectionManager?.sendResponse(
|
|
318
|
-
agentId,
|
|
319
|
-
message.taskId,
|
|
320
|
-
response.text,
|
|
321
|
-
message.contextId
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
} catch (err) {
|
|
326
|
-
ctx.log?.error(`[a2a] Error handling message:`, err);
|
|
327
|
-
// If message came via GopherHole, route error back through it
|
|
328
|
-
if (agentId === 'gopherhole' && message.from) {
|
|
329
307
|
connectionManager?.sendResponseViaGopherHole(
|
|
330
308
|
message.from,
|
|
331
309
|
message.taskId,
|
|
332
|
-
|
|
333
|
-
message.contextId
|
|
334
|
-
);
|
|
335
|
-
} else {
|
|
336
|
-
connectionManager?.sendResponse(
|
|
337
|
-
agentId,
|
|
338
|
-
message.taskId,
|
|
339
|
-
`Error: ${(err as Error).message}`,
|
|
310
|
+
response.text,
|
|
340
311
|
message.contextId
|
|
341
312
|
);
|
|
342
313
|
}
|
|
314
|
+
} catch (err) {
|
|
315
|
+
ctx.log?.error(`[a2a] Error handling message:`, err);
|
|
316
|
+
connectionManager?.sendResponseViaGopherHole(
|
|
317
|
+
message.from,
|
|
318
|
+
message.taskId,
|
|
319
|
+
`Error: ${(err as Error).message}`,
|
|
320
|
+
message.contextId
|
|
321
|
+
);
|
|
343
322
|
}
|
|
344
323
|
}
|
|
345
324
|
});
|
package/src/connection.ts
CHANGED
|
@@ -22,7 +22,7 @@ export class A2AConnectionManager {
|
|
|
22
22
|
|
|
23
23
|
constructor(config: A2AChannelConfig) {
|
|
24
24
|
this.config = config;
|
|
25
|
-
this.agentId = config.agentId ?? '
|
|
25
|
+
this.agentId = config.agentId ?? 'openclaw';
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
setMessageHandler(handler: MessageHandler): void {
|
|
@@ -30,26 +30,25 @@ export class A2AConnectionManager {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async start(): Promise<void> {
|
|
33
|
-
// Connect to GopherHole if configured
|
|
34
|
-
if (this.config.
|
|
33
|
+
// Connect to GopherHole if configured (flat config: enabled + apiKey)
|
|
34
|
+
if (this.config.enabled && this.config.apiKey) {
|
|
35
35
|
await this.connectToGopherHole();
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
private async connectToGopherHole(): Promise<void> {
|
|
40
|
-
const
|
|
41
|
-
const hubUrl = gphConfig.hubUrl || 'wss://gopherhole.ai/ws';
|
|
40
|
+
const hubUrl = this.config.bridgeUrl || 'wss://gopherhole.ai/ws';
|
|
42
41
|
const timeoutMs = this.config.requestTimeoutMs ?? 180000;
|
|
43
42
|
|
|
44
43
|
this.gopherhole = new GopherHole({
|
|
45
|
-
apiKey:
|
|
44
|
+
apiKey: this.config.apiKey!,
|
|
46
45
|
hubUrl,
|
|
47
46
|
autoReconnect: true,
|
|
48
47
|
reconnectDelay: this.config.reconnectIntervalMs ?? 5000,
|
|
49
48
|
maxReconnectAttempts: 20,
|
|
50
49
|
requestTimeout: timeoutMs,
|
|
51
50
|
messageTimeout: timeoutMs,
|
|
52
|
-
agentCard:
|
|
51
|
+
agentCard: this.config.agentCard ?? {
|
|
53
52
|
name: this.config.agentName ?? 'OpenClaw',
|
|
54
53
|
description: 'Personal AI assistant with tools, web search, browser control, and various skills',
|
|
55
54
|
version: '0.1.0',
|
package/src/types.ts
CHANGED
|
@@ -39,28 +39,29 @@ export interface A2AResponse {
|
|
|
39
39
|
from?: string;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* A2A Channel Config (flat structure)
|
|
44
|
+
*
|
|
45
|
+
* Example:
|
|
46
|
+
* {
|
|
47
|
+
* "channels": {
|
|
48
|
+
* "a2a": {
|
|
49
|
+
* "enabled": true,
|
|
50
|
+
* "bridgeUrl": "wss://gopherhole.ai/ws",
|
|
51
|
+
* "apiKey": "gph_your_api_key"
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
*/
|
|
42
56
|
export interface A2AChannelConfig {
|
|
43
57
|
enabled?: boolean;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}>;
|
|
52
|
-
gopherhole?: { // GopherHole Agent Hub connection
|
|
53
|
-
enabled?: boolean;
|
|
54
|
-
apiKey: string;
|
|
55
|
-
hubUrl?: string; // Default: wss://gopherhole.ai/ws
|
|
56
|
-
requestTimeoutMs?: number;
|
|
57
|
-
agentCard?: A2AAgentCard; // Custom agent card (overrides defaults)
|
|
58
|
-
};
|
|
59
|
-
auth?: {
|
|
60
|
-
token?: string;
|
|
61
|
-
};
|
|
62
|
-
reconnectIntervalMs?: number;
|
|
63
|
-
requestTimeoutMs?: number;
|
|
58
|
+
bridgeUrl?: string; // WebSocket URL (default: wss://gopherhole.ai/ws)
|
|
59
|
+
apiKey?: string; // GopherHole API key (gph_...)
|
|
60
|
+
agentId?: string; // Our agent ID (default: "openclaw")
|
|
61
|
+
agentName?: string; // Display name for agent card
|
|
62
|
+
agentCard?: A2AAgentCard; // Custom agent card (overrides defaults)
|
|
63
|
+
reconnectIntervalMs?: number; // Reconnect delay (default: 5000)
|
|
64
|
+
requestTimeoutMs?: number; // Request timeout (default: 180000)
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export interface ResolvedA2AAccount {
|
|
@@ -70,6 +71,5 @@ export interface ResolvedA2AAccount {
|
|
|
70
71
|
configured: boolean;
|
|
71
72
|
agentId: string;
|
|
72
73
|
bridgeUrl: string | null;
|
|
73
|
-
agents: Array<{ id: string; url: string; name?: string }>;
|
|
74
74
|
config: A2AChannelConfig;
|
|
75
75
|
}
|