@dp-pcs/ogp 0.2.31 → 0.3.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/README.md +11 -0
- package/dist/daemon/notify.d.ts +20 -0
- package/dist/daemon/notify.d.ts.map +1 -1
- package/dist/daemon/notify.js +168 -48
- package/dist/daemon/notify.js.map +1 -1
- package/dist/shared/config.d.ts +3 -0
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js.map +1 -1
- package/docs/TESTING-HERMES-BACKEND.md +278 -0
- package/docs/extending-to-hermes.md +462 -0
- package/docs/hermes-implementation-checklist.md +448 -0
- package/docs/hermes-local-testing.md +478 -0
- package/docs/hermes-tunnel-setup.md +214 -0
- package/docs/platform-agnostic-architecture.md +472 -0
- package/package.json +3 -2
- package/scripts/install-skills.js +142 -20
- package/skills/ogp-project/SKILL.md +321 -226
package/README.md
CHANGED
|
@@ -1015,6 +1015,17 @@ skills/
|
|
|
1015
1015
|
|
|
1016
1016
|
MIT
|
|
1017
1017
|
|
|
1018
|
+
## macOS Menu Bar App
|
|
1019
|
+
|
|
1020
|
+
A lightweight native macOS app for monitoring OGP status at a glance:
|
|
1021
|
+
|
|
1022
|
+
- **Status Indicator**: Color-coded dot in menu bar (🟢/🟡/🔴)
|
|
1023
|
+
- **Quick View**: Daemon, tunnel, and peer status
|
|
1024
|
+
- **Quick Actions**: Start/stop services with one click
|
|
1025
|
+
- **Peer List**: See federated peers, intents, and last activity
|
|
1026
|
+
|
|
1027
|
+
See [macos-menubar-app/QUICKSTART.md](./macos-menubar-app/QUICKSTART.md) for setup instructions.
|
|
1028
|
+
|
|
1018
1029
|
## Links
|
|
1019
1030
|
|
|
1020
1031
|
- **GitHub Repository**: https://github.com/dp-pcs/ogp
|
package/dist/daemon/notify.d.ts
CHANGED
|
@@ -19,6 +19,26 @@ export interface NotificationPayload {
|
|
|
19
19
|
* Topic for agent-comms notifications (for hook payload)
|
|
20
20
|
*/
|
|
21
21
|
topic?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Display name of the peer (for Hermes integration)
|
|
24
|
+
*/
|
|
25
|
+
peerDisplayName?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Priority level (for Hermes integration)
|
|
28
|
+
*/
|
|
29
|
+
priority?: 'low' | 'normal' | 'high';
|
|
30
|
+
/**
|
|
31
|
+
* Conversation ID for threading (for Hermes integration)
|
|
32
|
+
*/
|
|
33
|
+
conversationId?: string;
|
|
22
34
|
}
|
|
23
35
|
export declare function notifyOpenClaw(payload: NotificationPayload): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Send notification to the local AI agent using the configured platform backend.
|
|
38
|
+
* This is the recommended function for new code.
|
|
39
|
+
*
|
|
40
|
+
* @param payload Notification data including message, peer info, and metadata
|
|
41
|
+
* @returns Promise<boolean> indicating success
|
|
42
|
+
*/
|
|
43
|
+
export declare function notifyLocalAgent(payload: NotificationPayload): Promise<boolean>;
|
|
24
44
|
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/daemon/notify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/daemon/notify.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA8ND,wBAAsB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAInF;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAIrF"}
|
package/dist/daemon/notify.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { requireConfig } from '../shared/config.js';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
2
3
|
/**
|
|
3
4
|
* Resolve the notification target for a given agent.
|
|
4
5
|
* Priority:
|
|
@@ -14,38 +15,131 @@ function resolveNotifyTarget(config, agent) {
|
|
|
14
15
|
// Fall back to legacy notifyTarget
|
|
15
16
|
return config.notifyTarget;
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
18
|
+
/**
|
|
19
|
+
* OpenClaw notification backend.
|
|
20
|
+
* Uses the existing OpenClaw webhook and CLI integration.
|
|
21
|
+
*/
|
|
22
|
+
class OpenClawBackend {
|
|
23
|
+
name = 'openclaw';
|
|
24
|
+
async notify(payload, config) {
|
|
25
|
+
// Method 1: POST /hooks/agent
|
|
26
|
+
const hooksToken = config.openclawHooksToken;
|
|
27
|
+
if (hooksToken && config.openclawUrl) {
|
|
28
|
+
const openclawUrl = config.openclawUrl.replace(/\/$/, '');
|
|
29
|
+
try {
|
|
30
|
+
const result = await new Promise((resolve) => {
|
|
31
|
+
import('node:https').then(({ request: httpsRequest }) => {
|
|
32
|
+
import('node:http').then(({ request: httpRequest }) => {
|
|
33
|
+
import('node:url').then(({ URL }) => {
|
|
34
|
+
const url = new URL(`${openclawUrl}/hooks/agent`);
|
|
35
|
+
const isHttps = url.protocol === 'https:';
|
|
36
|
+
const target = resolveNotifyTarget(config, payload.agent);
|
|
37
|
+
const hookPayload = {
|
|
38
|
+
agentId: payload.agent || config.agentId || 'default',
|
|
39
|
+
peerId: payload.peerId || payload.metadata?.ogp?.from || 'unknown',
|
|
40
|
+
intent: payload.intent || payload.metadata?.ogp?.intent || 'unknown',
|
|
41
|
+
topic: payload.topic || payload.metadata?.ogp?.topic || 'general',
|
|
42
|
+
message: payload.text,
|
|
43
|
+
notifyTarget: target || config.notifyTarget || null,
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
45
|
+
// Legacy fields for backward compatibility
|
|
46
|
+
name: 'OGP',
|
|
47
|
+
deliver: true,
|
|
48
|
+
channel: config.notifyChannel || 'last',
|
|
49
|
+
...(target ? { to: target } : {}),
|
|
50
|
+
};
|
|
51
|
+
const body = JSON.stringify(hookPayload);
|
|
52
|
+
const reqFn = isHttps ? httpsRequest : httpRequest;
|
|
53
|
+
const req = reqFn({
|
|
54
|
+
hostname: url.hostname,
|
|
55
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
56
|
+
path: url.pathname,
|
|
57
|
+
method: 'POST',
|
|
58
|
+
rejectUnauthorized: false,
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
'Authorization': `Bearer ${hooksToken}`,
|
|
62
|
+
'Content-Length': Buffer.byteLength(body),
|
|
63
|
+
},
|
|
64
|
+
}, (res) => {
|
|
65
|
+
resolve(res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 300);
|
|
66
|
+
});
|
|
67
|
+
req.on('error', () => resolve(false));
|
|
68
|
+
req.setTimeout(5000, () => { req.destroy(); resolve(false); });
|
|
69
|
+
req.write(body);
|
|
70
|
+
req.end();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
if (result) {
|
|
76
|
+
console.log('[OGP] Notified OpenClaw via /hooks/agent:', payload.text);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
console.warn('[OGP] /hooks/agent call failed (non-2xx or error), falling back');
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error('[OGP] /hooks/agent failed:', error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Method 2: openclaw system event --mode now (CLI fallback)
|
|
86
|
+
try {
|
|
87
|
+
const { execSync } = await import('node:child_process');
|
|
88
|
+
const escaped = payload.text.replace(/'/g, "'\\''");
|
|
89
|
+
execSync(`openclaw system event --text '${escaped}' --mode now 2>/dev/null`, {
|
|
90
|
+
timeout: 5000,
|
|
91
|
+
env: { ...process.env }
|
|
92
|
+
});
|
|
93
|
+
console.log('[OGP] Notified OpenClaw via system event CLI:', payload.text);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.error('[OGP] System event CLI failed:', err);
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Hermes notification backend.
|
|
104
|
+
* Uses Hermes's webhook platform adapter for OGP integration.
|
|
105
|
+
*/
|
|
106
|
+
class HermesBackend {
|
|
107
|
+
name = 'hermes';
|
|
108
|
+
async notify(payload, config) {
|
|
109
|
+
const webhookUrl = config.hermesWebhookUrl || 'http://localhost:8644/webhooks/ogp_federation';
|
|
110
|
+
const secret = config.hermesWebhookSecret;
|
|
111
|
+
if (!secret) {
|
|
112
|
+
console.error('[OGP] Hermes webhook secret not configured. Set hermesWebhookSecret in config.json');
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
// Build webhook payload
|
|
116
|
+
// Note: event_type is required by Hermes webhook event filter ("events" subscription list)
|
|
117
|
+
const intentStr = payload.intent || 'message';
|
|
118
|
+
const body = {
|
|
119
|
+
event_type: intentStr, // required for Hermes event filter ("*" is not a wildcard there)
|
|
120
|
+
peer_id: payload.peerId || 'unknown',
|
|
121
|
+
peer_display_name: payload.peerDisplayName || payload.peerId || 'Unknown Peer',
|
|
122
|
+
intent: intentStr,
|
|
123
|
+
topic: payload.topic || 'general',
|
|
124
|
+
message: payload.text,
|
|
125
|
+
priority: payload.priority || 'normal',
|
|
126
|
+
conversation_id: payload.conversationId,
|
|
127
|
+
timestamp: new Date().toISOString(),
|
|
128
|
+
payload: payload.metadata || {}
|
|
129
|
+
};
|
|
130
|
+
const bodyStr = JSON.stringify(body);
|
|
131
|
+
// Compute HMAC signature
|
|
132
|
+
const signature = crypto
|
|
133
|
+
.createHmac('sha256', secret)
|
|
134
|
+
.update(bodyStr)
|
|
135
|
+
.digest('hex');
|
|
26
136
|
try {
|
|
27
137
|
const result = await new Promise((resolve) => {
|
|
28
138
|
import('node:https').then(({ request: httpsRequest }) => {
|
|
29
139
|
import('node:http').then(({ request: httpRequest }) => {
|
|
30
140
|
import('node:url').then(({ URL }) => {
|
|
31
|
-
const url = new URL(
|
|
141
|
+
const url = new URL(webhookUrl);
|
|
32
142
|
const isHttps = url.protocol === 'https:';
|
|
33
|
-
const target = resolveNotifyTarget(config, payload.agent);
|
|
34
|
-
const hookPayload = {
|
|
35
|
-
agentId: payload.agent || config.agentId || 'default',
|
|
36
|
-
peerId: payload.peerId || payload.metadata?.ogp?.from || 'unknown',
|
|
37
|
-
intent: payload.intent || payload.metadata?.ogp?.intent || 'unknown',
|
|
38
|
-
topic: payload.topic || payload.metadata?.ogp?.topic || 'general',
|
|
39
|
-
message: payload.text,
|
|
40
|
-
notifyTarget: target || config.notifyTarget || null,
|
|
41
|
-
timestamp: new Date().toISOString(),
|
|
42
|
-
// Legacy fields for backward compatibility
|
|
43
|
-
name: 'OGP',
|
|
44
|
-
deliver: true,
|
|
45
|
-
channel: config.notifyChannel || 'last',
|
|
46
|
-
...(target ? { to: target } : {}),
|
|
47
|
-
};
|
|
48
|
-
const body = JSON.stringify(hookPayload);
|
|
49
143
|
const reqFn = isHttps ? httpsRequest : httpRequest;
|
|
50
144
|
const req = reqFn({
|
|
51
145
|
hostname: url.hostname,
|
|
@@ -55,44 +149,70 @@ export async function notifyOpenClaw(payload) {
|
|
|
55
149
|
rejectUnauthorized: false,
|
|
56
150
|
headers: {
|
|
57
151
|
'Content-Type': 'application/json',
|
|
58
|
-
'
|
|
59
|
-
'Content-Length': Buffer.byteLength(
|
|
152
|
+
'X-Hub-Signature-256': `sha256=${signature}`,
|
|
153
|
+
'Content-Length': Buffer.byteLength(bodyStr),
|
|
60
154
|
},
|
|
61
155
|
}, (res) => {
|
|
62
156
|
resolve(res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 300);
|
|
63
157
|
});
|
|
64
|
-
req.on('error', () =>
|
|
65
|
-
|
|
66
|
-
|
|
158
|
+
req.on('error', (error) => {
|
|
159
|
+
console.error('[OGP] Hermes webhook request error:', error);
|
|
160
|
+
resolve(false);
|
|
161
|
+
});
|
|
162
|
+
req.setTimeout(5000, () => {
|
|
163
|
+
req.destroy();
|
|
164
|
+
resolve(false);
|
|
165
|
+
});
|
|
166
|
+
req.write(bodyStr);
|
|
67
167
|
req.end();
|
|
68
168
|
});
|
|
69
169
|
});
|
|
70
170
|
});
|
|
71
171
|
});
|
|
72
172
|
if (result) {
|
|
73
|
-
console.log('[OGP] Notified
|
|
173
|
+
console.log('[OGP] Notified Hermes via webhook:', payload.text);
|
|
74
174
|
return true;
|
|
75
175
|
}
|
|
76
|
-
|
|
176
|
+
else {
|
|
177
|
+
console.error('[OGP] Hermes webhook call failed (non-2xx response)');
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
77
180
|
}
|
|
78
181
|
catch (error) {
|
|
79
|
-
console.error('[OGP]
|
|
182
|
+
console.error('[OGP] Hermes webhook failed:', error);
|
|
183
|
+
return false;
|
|
80
184
|
}
|
|
81
185
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the appropriate notification backend based on platform config.
|
|
189
|
+
* Defaults to OpenClaw for backward compatibility.
|
|
190
|
+
*/
|
|
191
|
+
function getNotificationBackend(config) {
|
|
192
|
+
const platform = config.platform || 'openclaw';
|
|
193
|
+
switch (platform) {
|
|
194
|
+
case 'hermes':
|
|
195
|
+
return new HermesBackend();
|
|
196
|
+
case 'openclaw':
|
|
197
|
+
default:
|
|
198
|
+
return new OpenClawBackend();
|
|
95
199
|
}
|
|
96
|
-
|
|
200
|
+
}
|
|
201
|
+
export async function notifyOpenClaw(payload) {
|
|
202
|
+
const config = requireConfig();
|
|
203
|
+
const backend = getNotificationBackend(config);
|
|
204
|
+
return backend.notify(payload, config);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Send notification to the local AI agent using the configured platform backend.
|
|
208
|
+
* This is the recommended function for new code.
|
|
209
|
+
*
|
|
210
|
+
* @param payload Notification data including message, peer info, and metadata
|
|
211
|
+
* @returns Promise<boolean> indicating success
|
|
212
|
+
*/
|
|
213
|
+
export async function notifyLocalAgent(payload) {
|
|
214
|
+
const config = requireConfig();
|
|
215
|
+
const backend = getNotificationBackend(config);
|
|
216
|
+
return backend.notify(payload, config);
|
|
97
217
|
}
|
|
98
218
|
//# sourceMappingURL=notify.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/daemon/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/daemon/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,qBAAqB,CAAC;AACpE,OAAO,MAAM,MAAM,aAAa,CAAC;AA8CjC;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,MAAiB,EAAE,KAAc;IAC5D,sDAAsD;IACtD,IAAI,KAAK,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IACD,mCAAmC;IACnC,OAAO,MAAM,CAAC,YAAY,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,eAAe;IACV,IAAI,GAAG,UAAU,CAAC;IAE3B,KAAK,CAAC,MAAM,CAAC,OAA4B,EAAE,MAAiB;QAC1D,8BAA8B;QAC9B,MAAM,UAAU,GAAI,MAAc,CAAC,kBAAkB,CAAC;QACtD,IAAI,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC1D,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;oBACpD,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE;wBACtD,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE;4BACpD,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;gCAClC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,WAAW,cAAc,CAAC,CAAC;gCAClD,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;gCAC1C,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gCAC1D,MAAM,WAAW,GAAG;oCAClB,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,IAAI,SAAS;oCACrD,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,IAAI,SAAS;oCAClE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,IAAI,SAAS;oCACpE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,IAAI,SAAS;oCACjE,OAAO,EAAE,OAAO,CAAC,IAAI;oCACrB,YAAY,EAAE,MAAM,IAAI,MAAM,CAAC,YAAY,IAAI,IAAI;oCACnD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oCACnC,2CAA2C;oCAC3C,IAAI,EAAE,KAAK;oCACX,OAAO,EAAE,IAAI;oCACb,OAAO,EAAG,MAAc,CAAC,aAAa,IAAI,MAAM;oCAChD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iCAClC,CAAC;gCACF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;gCACzC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;gCACnD,MAAM,GAAG,GAAI,KAA6B,CAAC;oCACzC,QAAQ,EAAE,GAAG,CAAC,QAAQ;oCACtB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oCACtC,IAAI,EAAE,GAAG,CAAC,QAAQ;oCAClB,MAAM,EAAE,MAAM;oCACd,kBAAkB,EAAE,KAAK;oCACzB,OAAO,EAAE;wCACP,cAAc,EAAE,kBAAkB;wCAClC,eAAe,EAAE,UAAU,UAAU,EAAE;wCACvC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;qCAC1C;iCACF,EAAE,CAAC,GAAG,EAAE,EAAE;oCACT,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;gCACzF,CAAC,CAAC,CAAC;gCACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;gCACtC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gCAC/D,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gCAChB,GAAG,CAAC,GAAG,EAAE,CAAC;4BACZ,CAAC,CAAC,CAAC;wBACL,CAAC,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;gBACH,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,CAAC,GAAG,CAAC,2CAA2C,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;oBACvE,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAClF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAED,4DAA4D;QAC5D,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACxD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACpD,QAAQ,CAAC,iCAAiC,OAAO,0BAA0B,EAAE;gBAC3E,OAAO,EAAE,IAAI;gBACb,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;aACxB,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,aAAa;IACR,IAAI,GAAG,QAAQ,CAAC;IAEzB,KAAK,CAAC,MAAM,CAAC,OAA4B,EAAE,MAAiB;QAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,IAAI,+CAA+C,CAAC;QAC9F,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC;QAE1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,oFAAoF,CAAC,CAAC;YACpG,OAAO,KAAK,CAAC;QACf,CAAC;QAED,wBAAwB;QACxB,2FAA2F;QAC3F,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,SAAS,CAAC;QAC9C,MAAM,IAAI,GAAG;YACX,UAAU,EAAE,SAAS,EAAG,iEAAiE;YACzF,OAAO,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;YACpC,iBAAiB,EAAE,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,MAAM,IAAI,cAAc;YAC9E,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;YACjC,OAAO,EAAE,OAAO,CAAC,IAAI;YACrB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,QAAQ;YACtC,eAAe,EAAE,OAAO,CAAC,cAAc;YACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;SAChC,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAErC,yBAAyB;QACzB,MAAM,SAAS,GAAG,MAAM;aACrB,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;aAC5B,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;gBACpD,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE;oBACtD,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE;wBACpD,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;4BAClC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;4BAChC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;4BAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;4BAEnD,MAAM,GAAG,GAAI,KAA6B,CAAC;gCACzC,QAAQ,EAAE,GAAG,CAAC,QAAQ;gCACtB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gCACtC,IAAI,EAAE,GAAG,CAAC,QAAQ;gCAClB,MAAM,EAAE,MAAM;gCACd,kBAAkB,EAAE,KAAK;gCACzB,OAAO,EAAE;oCACP,cAAc,EAAE,kBAAkB;oCAClC,qBAAqB,EAAE,UAAU,SAAS,EAAE;oCAC5C,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;iCAC7C;6BACF,EAAE,CAAC,GAAG,EAAE,EAAE;gCACT,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;4BACzF,CAAC,CAAC,CAAC;4BAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gCACxB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;gCAC5D,OAAO,CAAC,KAAK,CAAC,CAAC;4BACjB,CAAC,CAAC,CAAC;4BACH,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE;gCACxB,GAAG,CAAC,OAAO,EAAE,CAAC;gCACd,OAAO,CAAC,KAAK,CAAC,CAAC;4BACjB,CAAC,CAAC,CAAC;4BACH,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;4BACnB,GAAG,CAAC,GAAG,EAAE,CAAC;wBACZ,CAAC,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,oCAAoC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChE,OAAO,IAAI,CAAC;YACd,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;gBACrE,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAAC,MAAiB;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,UAAU,CAAC;IAE/C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,EAAE,CAAC;QAC7B,KAAK,UAAU,CAAC;QAChB;YACE,OAAO,IAAI,eAAe,EAAE,CAAC;IACjC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA4B;IAC/D,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA4B;IACjE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC"}
|
package/dist/shared/config.d.ts
CHANGED
|
@@ -41,6 +41,9 @@ export interface OGPConfig {
|
|
|
41
41
|
notifyTarget?: string;
|
|
42
42
|
notifyTargets?: Record<string, string>;
|
|
43
43
|
agentId?: string;
|
|
44
|
+
platform?: 'openclaw' | 'hermes';
|
|
45
|
+
hermesWebhookUrl?: string;
|
|
46
|
+
hermesWebhookSecret?: string;
|
|
44
47
|
}
|
|
45
48
|
export declare function getConfigPath(): string;
|
|
46
49
|
export declare function getConfigDir(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,cAAc,CAAC;IAC7B,YAAY,EAAE,aAAa,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEvC,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,cAAc,CAAC;IAC7B,YAAY,EAAE,aAAa,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEvC,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,QAAQ,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAGjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,SAAS,GAAG,IAAI,CAW7C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAGlD;AAED,wBAAgB,aAAa,IAAI,SAAS,CAOzC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAgEzB,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AACnF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;AAEjE,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACvC,EAAE,CAAC,SAAS,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAc,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,eAAe,EAAE,CAAC;IAClB,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# Testing the Hermes Backend Implementation
|
|
2
|
+
|
|
3
|
+
> Verification guide for the platform-agnostic notification backend
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
The notification system now supports multiple AI platforms via a backend abstraction layer:
|
|
8
|
+
|
|
9
|
+
**Files Modified:**
|
|
10
|
+
- `src/shared/config.ts` - Added optional `platform`, `hermesWebhookUrl`, `hermesWebhookSecret` fields
|
|
11
|
+
- `src/daemon/notify.ts` - Implemented backend system with OpenClaw and Hermes backends
|
|
12
|
+
|
|
13
|
+
**Backward Compatibility:**
|
|
14
|
+
- ✅ All existing OpenClaw installations work unchanged
|
|
15
|
+
- ✅ Config without `platform` field defaults to `'openclaw'`
|
|
16
|
+
- ✅ All existing code paths preserved
|
|
17
|
+
- ✅ No breaking changes
|
|
18
|
+
|
|
19
|
+
## Test Plan
|
|
20
|
+
|
|
21
|
+
### Phase 1: Regression Testing (OpenClaw)
|
|
22
|
+
|
|
23
|
+
**Goal:** Verify existing OpenClaw integration still works perfectly.
|
|
24
|
+
|
|
25
|
+
1. **Verify OGP is currently working:**
|
|
26
|
+
```bash
|
|
27
|
+
ogp status
|
|
28
|
+
# Should show your existing OpenClaw configuration
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
2. **Check your config has no 'platform' field:**
|
|
32
|
+
```bash
|
|
33
|
+
cat ~/.ogp/config.json | grep platform
|
|
34
|
+
# Should return nothing (field doesn't exist)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. **Send a test message to an existing peer:**
|
|
38
|
+
```bash
|
|
39
|
+
ogp federation list
|
|
40
|
+
# Pick a peer you've already federated with
|
|
41
|
+
|
|
42
|
+
ogp federation send <peer-alias> message '{"text":"Test from feature/hermes-support branch"}'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
4. **Verify notification arrives in OpenClaw:**
|
|
46
|
+
- Check your Telegram/notification channel
|
|
47
|
+
- Should see the test message as before
|
|
48
|
+
- No changes in behavior
|
|
49
|
+
|
|
50
|
+
**Expected Result:** Everything works exactly as before. ✅
|
|
51
|
+
|
|
52
|
+
### Phase 2: Hermes Setup (If You Want to Test It)
|
|
53
|
+
|
|
54
|
+
**Goal:** Set up a second OGP instance for Hermes and test federation.
|
|
55
|
+
|
|
56
|
+
**Prerequisites:**
|
|
57
|
+
- Hermes installed and gateway running
|
|
58
|
+
- Ready to configure webhook
|
|
59
|
+
|
|
60
|
+
#### Step 1: Configure Hermes Webhook
|
|
61
|
+
|
|
62
|
+
Edit `~/.hermes/config.yaml`:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
platforms:
|
|
66
|
+
webhook:
|
|
67
|
+
enabled: true
|
|
68
|
+
port: 8644
|
|
69
|
+
host: "127.0.0.1"
|
|
70
|
+
routes:
|
|
71
|
+
ogp_federation:
|
|
72
|
+
secret: "test-secret-change-me" # Pick a secret
|
|
73
|
+
events: ["*"]
|
|
74
|
+
prompt: |
|
|
75
|
+
📡 **OGP Federation Test**
|
|
76
|
+
|
|
77
|
+
From: {{peer_display_name}} ({{peer_id}})
|
|
78
|
+
Intent: {{intent}}
|
|
79
|
+
Topic: {{topic}}
|
|
80
|
+
|
|
81
|
+
{{message}}
|
|
82
|
+
deliver: "telegram" # Or your preferred channel
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Restart Hermes gateway:**
|
|
86
|
+
```bash
|
|
87
|
+
hermes gateway restart
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Verify webhook is running:**
|
|
91
|
+
```bash
|
|
92
|
+
curl http://localhost:8644/health
|
|
93
|
+
# Should return: {"status":"ok"}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Step 2: Create OGP Instance for Hermes
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Create state directory
|
|
100
|
+
mkdir -p ~/.ogp-hermes
|
|
101
|
+
|
|
102
|
+
# Create config
|
|
103
|
+
cat > ~/.ogp-hermes/config.json <<'EOF'
|
|
104
|
+
{
|
|
105
|
+
"daemonPort": 18791,
|
|
106
|
+
"platform": "hermes",
|
|
107
|
+
"gatewayUrl": "http://localhost:18791",
|
|
108
|
+
"displayName": "David (Hermes)",
|
|
109
|
+
"email": "your-email@example.com",
|
|
110
|
+
"stateDir": "~/.ogp-hermes",
|
|
111
|
+
|
|
112
|
+
"hermesWebhookUrl": "http://localhost:8644/webhooks/ogp_federation",
|
|
113
|
+
"hermesWebhookSecret": "test-secret-change-me",
|
|
114
|
+
|
|
115
|
+
"openclawUrl": "",
|
|
116
|
+
"openclawToken": "",
|
|
117
|
+
|
|
118
|
+
"rendezvous": {
|
|
119
|
+
"enabled": false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
EOF
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Note the differences:**
|
|
126
|
+
- `platform: "hermes"` (this activates the Hermes backend)
|
|
127
|
+
- `hermesWebhookUrl` and `hermesWebhookSecret` (for webhook POST)
|
|
128
|
+
- `openclawUrl` and `openclawToken` are empty (not used)
|
|
129
|
+
|
|
130
|
+
#### Step 3: Start Hermes OGP Instance
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Method 1: Direct daemon start
|
|
134
|
+
OGP_HOME=~/.ogp-hermes node dist/daemon/server.js &
|
|
135
|
+
|
|
136
|
+
# Save PID for later
|
|
137
|
+
echo $! > ~/.ogp-hermes/daemon.pid
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Verify it's running:**
|
|
141
|
+
```bash
|
|
142
|
+
curl http://localhost:18791/.well-known/ogp
|
|
143
|
+
# Should return OGP metadata
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Step 4: Test Local Federation
|
|
147
|
+
|
|
148
|
+
**From OpenClaw OGP to Hermes OGP:**
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Request federation
|
|
152
|
+
ogp federation request http://localhost:18791 --alias hermes-test
|
|
153
|
+
|
|
154
|
+
# Check pending (on Hermes side)
|
|
155
|
+
OGP_HOME=~/.ogp-hermes ogp federation list --status pending
|
|
156
|
+
|
|
157
|
+
# Note the peer ID and approve
|
|
158
|
+
OGP_HOME=~/.ogp-hermes ogp federation approve <peer-id> \
|
|
159
|
+
--intents message,agent-comms
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Send test message:**
|
|
163
|
+
```bash
|
|
164
|
+
ogp federation send hermes-test message '{"text":"Hello Hermes from OpenClaw!"}'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**What should happen:**
|
|
168
|
+
1. Message leaves OpenClaw OGP (port 18790)
|
|
169
|
+
2. Arrives at Hermes OGP (port 18791)
|
|
170
|
+
3. Doorman validates signature
|
|
171
|
+
4. OGP POSTs to Hermes webhook (port 8644)
|
|
172
|
+
5. You see message in Hermes delivery channel (Telegram/etc.)
|
|
173
|
+
|
|
174
|
+
**Check logs:**
|
|
175
|
+
```bash
|
|
176
|
+
# Hermes logs
|
|
177
|
+
tail -f ~/.hermes/logs/gateway.log
|
|
178
|
+
|
|
179
|
+
# Look for:
|
|
180
|
+
# [webhook] Received POST on route ogp_federation
|
|
181
|
+
# [webhook] Signature verified
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Phase 3: Cleanup (If You Tested Hermes)
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Stop Hermes OGP
|
|
188
|
+
kill $(cat ~/.ogp-hermes/daemon.pid)
|
|
189
|
+
|
|
190
|
+
# Remove test state (optional)
|
|
191
|
+
# rm -rf ~/.ogp-hermes
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Verification Checklist
|
|
195
|
+
|
|
196
|
+
### OpenClaw (Must Pass)
|
|
197
|
+
- [ ] Existing OpenClaw OGP still runs
|
|
198
|
+
- [ ] Can send messages to existing peers
|
|
199
|
+
- [ ] Notifications arrive in OpenClaw
|
|
200
|
+
- [ ] `ogp status` shows correct info
|
|
201
|
+
- [ ] No errors in logs
|
|
202
|
+
|
|
203
|
+
### Hermes (Optional Testing)
|
|
204
|
+
- [ ] Hermes webhook receives POST
|
|
205
|
+
- [ ] Signature verification passes
|
|
206
|
+
- [ ] Message arrives in Hermes delivery channel
|
|
207
|
+
- [ ] Logs show successful notification
|
|
208
|
+
- [ ] Can federate with OpenClaw instance
|
|
209
|
+
|
|
210
|
+
## Troubleshooting
|
|
211
|
+
|
|
212
|
+
### Build Issues
|
|
213
|
+
|
|
214
|
+
**If TypeScript compilation fails:**
|
|
215
|
+
```bash
|
|
216
|
+
npm run build
|
|
217
|
+
# Check for errors, fix them, rebuild
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Runtime Issues
|
|
221
|
+
|
|
222
|
+
**OpenClaw notifications not working:**
|
|
223
|
+
1. Check config has no `platform` field (should default to 'openclaw')
|
|
224
|
+
2. Verify `openclawUrl` and `openclawHooksToken` still set
|
|
225
|
+
3. Check logs for errors
|
|
226
|
+
4. Try sending to a known-working peer
|
|
227
|
+
|
|
228
|
+
**Hermes webhook not receiving:**
|
|
229
|
+
1. Verify webhook secret matches in both configs
|
|
230
|
+
2. Check Hermes gateway is running: `curl http://localhost:8644/health`
|
|
231
|
+
3. Check Hermes OGP is running: `curl http://localhost:18791/.well-known/ogp`
|
|
232
|
+
4. Check Hermes logs: `tail -f ~/.hermes/logs/gateway.log`
|
|
233
|
+
|
|
234
|
+
**Signature verification fails:**
|
|
235
|
+
1. Secrets must match exactly:
|
|
236
|
+
- `hermesWebhookSecret` in `~/.ogp-hermes/config.json`
|
|
237
|
+
- `secret` in `~/.hermes/config.yaml` under `routes.ogp_federation`
|
|
238
|
+
2. No extra whitespace in secret values
|
|
239
|
+
3. Case sensitive
|
|
240
|
+
|
|
241
|
+
## Success Criteria
|
|
242
|
+
|
|
243
|
+
### Minimum (Must Pass)
|
|
244
|
+
- ✅ OpenClaw integration works unchanged
|
|
245
|
+
- ✅ No regression in existing functionality
|
|
246
|
+
- ✅ Code compiles without errors
|
|
247
|
+
|
|
248
|
+
### Full (Nice to Have)
|
|
249
|
+
- ✅ Hermes webhook receives messages
|
|
250
|
+
- ✅ Local OpenClaw ↔ Hermes federation works
|
|
251
|
+
- ✅ Both platforms can send/receive simultaneously
|
|
252
|
+
|
|
253
|
+
## Next Steps
|
|
254
|
+
|
|
255
|
+
After verification:
|
|
256
|
+
|
|
257
|
+
1. **If all tests pass:**
|
|
258
|
+
- Ready to merge feature branch
|
|
259
|
+
- Update CHANGELOG
|
|
260
|
+
- Version bump to 0.3.0
|
|
261
|
+
- Publish to npm
|
|
262
|
+
|
|
263
|
+
2. **If issues found:**
|
|
264
|
+
- Document them
|
|
265
|
+
- Fix on feature branch
|
|
266
|
+
- Re-test
|
|
267
|
+
|
|
268
|
+
3. **Future work:**
|
|
269
|
+
- Update CLI setup wizard for platform selection
|
|
270
|
+
- Add platform selection to `ogp setup`
|
|
271
|
+
- Documentation updates for Hermes users
|
|
272
|
+
- Integration tests for both platforms
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
**Branch:** `feature/hermes-support`
|
|
277
|
+
**Last Updated:** 2026-04-04
|
|
278
|
+
**Status:** Ready for Testing
|