@made-by-moonlight/athene-plugin-notifier-openclaw 0.9.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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Composio, Inc.
4
+ Copyright (c) 2026 slievr (Athene fork)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # notifier-openclaw
2
+
3
+ OpenClaw notifier plugin for AO escalation events.
4
+
5
+ ## Quick setup
6
+
7
+ ```bash
8
+ athene setup openclaw
9
+ ```
10
+
11
+ This interactive wizard auto-detects your OpenClaw gateway, lets you reuse or change the URL, OpenClaw config path, and routing values, then writes the AO config. For non-interactive use (e.g., in CI/CD pipelines or automation scripts):
12
+
13
+ ```bash
14
+ athene setup openclaw --url http://127.0.0.1:18789/hooks/agent --non-interactive
15
+ ```
16
+
17
+ AO does not generate the token or write shell-profile exports. Local setup reads `hooks.token` from your OpenClaw config. For a remote OpenClaw gateway, you can pass `--token` and AO will store that token in `agent-orchestrator.yaml`.
18
+
19
+ Useful follow-up commands:
20
+
21
+ ```bash
22
+ athene setup openclaw --refresh
23
+ athene setup openclaw --status
24
+ ```
25
+
26
+ Interactive setup asks which notification priorities OpenClaw should receive.
27
+ For scriptable setup, pass `--routing-preset urgent-only`, `urgent-action`, or
28
+ `all`.
29
+
30
+ ## Required OpenClaw config (`openclaw.json`)
31
+
32
+ ```json
33
+ {
34
+ "hooks": {
35
+ "enabled": true,
36
+ "token": "<your-hooks-token>",
37
+ "allowRequestSessionKey": true,
38
+ "allowedSessionKeyPrefixes": ["hook:"]
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## AO config (`agent-orchestrator.yaml`)
44
+
45
+ ```yaml
46
+ notifiers:
47
+ openclaw:
48
+ plugin: openclaw
49
+ url: http://127.0.0.1:18789/hooks/agent
50
+ openclawConfigPath: ~/.openclaw/openclaw.json
51
+ ```
52
+
53
+ ## Behavior
54
+
55
+ - Sends `POST /hooks/agent` payloads with per-session key `hook:ao:<sessionId>`.
56
+ - Defaults `wakeMode: now` and `deliver: true`.
57
+ - Retries on `429` and `5xx` responses with exponential backoff.
58
+
59
+ ## Token rotation
60
+
61
+ 1. Rotate `hooks.token` in OpenClaw.
62
+ 2. Restart OpenClaw so it picks up the new config.
63
+ 3. Run `athene setup openclaw --status` to verify the new token.
64
+
65
+ ## Known limitation (Phase 0)
66
+
67
+ - OpenClaw hook ingest is not idempotent by default. Replayed webhook payloads are processed as separate runs.
68
+ - Owner: AO integration.
69
+ - Follow-up: add stable event id/idempotency key support.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Regression tests for plugin-internal activity events (issue #1659).
3
+ *
4
+ * Covers notifier.auth_failed (MUST) and notifier.unreachable (SHOULD) —
5
+ * the two failure shapes RCA needs to distinguish.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=activity-events.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-events.test.d.ts","sourceRoot":"","sources":["../src/activity-events.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Regression tests for plugin-internal activity events (issue #1659).
3
+ *
4
+ * Covers notifier.auth_failed (MUST) and notifier.unreachable (SHOULD) —
5
+ * the two failure shapes RCA needs to distinguish.
6
+ */
7
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
8
+ const { recordActivityEventMock } = vi.hoisted(() => ({
9
+ recordActivityEventMock: vi.fn(),
10
+ }));
11
+ vi.mock("@made-by-moonlight/athene-core", async () => {
12
+ const actual = (await vi.importActual("@made-by-moonlight/athene-core"));
13
+ return {
14
+ ...actual,
15
+ recordActivityEvent: recordActivityEventMock,
16
+ };
17
+ });
18
+ import { create } from "./index.js";
19
+ function makeEvent(overrides = {}) {
20
+ return {
21
+ id: "evt-1",
22
+ type: "reaction.escalated",
23
+ priority: "urgent",
24
+ sessionId: "ao-5",
25
+ projectId: "ao",
26
+ timestamp: new Date("2026-03-08T12:00:00Z"),
27
+ message: "Reaction escalated",
28
+ data: {},
29
+ ...overrides,
30
+ };
31
+ }
32
+ beforeEach(() => {
33
+ vi.clearAllMocks();
34
+ vi.restoreAllMocks();
35
+ delete process.env.OPENCLAW_HOOKS_TOKEN;
36
+ });
37
+ afterEach(() => {
38
+ vi.unstubAllGlobals();
39
+ });
40
+ describe("notifier.auth_failed (MUST emit)", () => {
41
+ it("emits on 401 (distinct from notifier.unreachable on ECONNREFUSED)", async () => {
42
+ const fetchMock = vi
43
+ .fn()
44
+ .mockResolvedValue({ ok: false, status: 401, text: () => Promise.resolve("unauthorized") });
45
+ vi.stubGlobal("fetch", fetchMock);
46
+ const notifier = create({ token: "tok", retries: 0 });
47
+ await expect(notifier.notify(makeEvent())).rejects.toThrow(/OpenClaw rejected the auth token/);
48
+ expect(recordActivityEventMock).toHaveBeenCalledWith(expect.objectContaining({
49
+ source: "notifier",
50
+ kind: "notifier.auth_failed",
51
+ level: "error",
52
+ sessionId: "ao-5",
53
+ data: expect.objectContaining({
54
+ plugin: "notifier-openclaw",
55
+ status: 401,
56
+ }),
57
+ }));
58
+ });
59
+ it("emits on 403", async () => {
60
+ const fetchMock = vi
61
+ .fn()
62
+ .mockResolvedValue({ ok: false, status: 403, text: () => Promise.resolve("forbidden") });
63
+ vi.stubGlobal("fetch", fetchMock);
64
+ const notifier = create({ token: "tok", retries: 0 });
65
+ await expect(notifier.notify(makeEvent())).rejects.toThrow();
66
+ expect(recordActivityEventMock).toHaveBeenCalledWith(expect.objectContaining({
67
+ kind: "notifier.auth_failed",
68
+ data: expect.objectContaining({ status: 403 }),
69
+ }));
70
+ });
71
+ });
72
+ describe("notifier.unreachable (SHOULD emit)", () => {
73
+ it.each(["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND", "ENETUNREACH"])("emits on %s (distinct from notifier.auth_failed)", async (code) => {
74
+ const fetchMock = vi.fn().mockRejectedValue(new Error(`fetch failed: ${code}`));
75
+ vi.stubGlobal("fetch", fetchMock);
76
+ const notifier = create({ token: "tok", retries: 0 });
77
+ await expect(notifier.notify(makeEvent())).rejects.toThrow(/Can't reach OpenClaw gateway/);
78
+ expect(recordActivityEventMock).toHaveBeenCalledWith(expect.objectContaining({
79
+ source: "notifier",
80
+ kind: "notifier.unreachable",
81
+ level: "warn",
82
+ sessionId: "ao-5",
83
+ data: expect.objectContaining({
84
+ plugin: "notifier-openclaw",
85
+ errorMessage: expect.stringContaining(code),
86
+ }),
87
+ }));
88
+ // Critically: should NOT also fire auth_failed — distinct shapes.
89
+ const authFailedCalls = recordActivityEventMock.mock.calls.filter(([event]) => event.kind === "notifier.auth_failed");
90
+ expect(authFailedCalls).toHaveLength(0);
91
+ });
92
+ it.each(["ETIMEDOUT", "ENOTFOUND", "ENETUNREACH"])("does not emit on transient %s when a retry succeeds", async (code) => {
93
+ const fetchMock = vi
94
+ .fn()
95
+ .mockRejectedValueOnce(new Error(`fetch failed: ${code}`))
96
+ .mockResolvedValueOnce({ ok: true });
97
+ vi.stubGlobal("fetch", fetchMock);
98
+ const notifier = create({ token: "tok", retries: 1, retryDelayMs: 0 });
99
+ await notifier.notify(makeEvent());
100
+ expect(fetchMock).toHaveBeenCalledTimes(2);
101
+ const unreachableCalls = recordActivityEventMock.mock.calls.filter(([event]) => event.kind === "notifier.unreachable");
102
+ expect(unreachableCalls).toHaveLength(0);
103
+ });
104
+ it.each(["ETIMEDOUT", "ENOTFOUND", "ENETUNREACH"])("emits on transient %s only after retry budget is exhausted", async (code) => {
105
+ const fetchMock = vi.fn().mockRejectedValue(new Error(`fetch failed: ${code}`));
106
+ vi.stubGlobal("fetch", fetchMock);
107
+ const notifier = create({ token: "tok", retries: 1, retryDelayMs: 0 });
108
+ await expect(notifier.notify(makeEvent())).rejects.toThrow(/Can't reach OpenClaw gateway/);
109
+ expect(fetchMock).toHaveBeenCalledTimes(2);
110
+ const unreachableCalls = recordActivityEventMock.mock.calls.filter(([event]) => event.kind === "notifier.unreachable");
111
+ expect(unreachableCalls).toHaveLength(1);
112
+ expect(unreachableCalls[0]?.[0].data).toMatchObject({
113
+ errorMessage: expect.stringContaining(code),
114
+ });
115
+ });
116
+ it("does not emit unreachable for unrelated network errors", async () => {
117
+ const fetchMock = vi.fn().mockRejectedValue(new Error("fetch failed: certificate expired"));
118
+ vi.stubGlobal("fetch", fetchMock);
119
+ const notifier = create({ token: "tok", retries: 0 });
120
+ await expect(notifier.notify(makeEvent())).rejects.toThrow(/fetch failed: certificate expired/);
121
+ const unreachableCalls = recordActivityEventMock.mock.calls.filter(([event]) => event.kind === "notifier.unreachable");
122
+ expect(unreachableCalls).toHaveLength(0);
123
+ });
124
+ });
125
+ //# sourceMappingURL=activity-events.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-events.test.js","sourceRoot":"","sources":["../src/activity-events.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type Notifier } from "@made-by-moonlight/athene-core";
2
+ export declare const manifest: {
3
+ name: string;
4
+ slot: "notifier";
5
+ description: string;
6
+ version: string;
7
+ };
8
+ export declare function create(config?: Record<string, unknown>): Notifier;
9
+ declare const _default: {
10
+ manifest: {
11
+ name: string;
12
+ slot: "notifier";
13
+ description: string;
14
+ version: string;
15
+ };
16
+ create: typeof create;
17
+ };
18
+ export default _default;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAKL,KAAK,QAAQ,EAOd,MAAM,gCAAgC,CAAC;AA4BxC,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC;AAoYF,wBAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAwFjE;;;;;;;;;;AAED,wBAAqE"}
package/dist/index.js ADDED
@@ -0,0 +1,441 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { getNotificationDataV3, getObservabilityBaseDir, recordActivityEvent, } from "@made-by-moonlight/athene-core";
5
+ import { isRetryableHttpStatus, normalizeRetryConfig, validateUrl } from "@made-by-moonlight/athene-core/utils";
6
+ /**
7
+ * Read the hooks token from OpenClaw's config. AO treats OpenClaw as the
8
+ * owner of hooks.token; setup only points the notifier at this file.
9
+ */
10
+ function expandHomePath(path) {
11
+ if (path === "~")
12
+ return homedir();
13
+ if (path.startsWith("~/"))
14
+ return join(homedir(), path.slice(2));
15
+ return path;
16
+ }
17
+ function readTokenFromOpenClawConfig(configPath) {
18
+ try {
19
+ const resolvedPath = expandHomePath(configPath ?? join(homedir(), ".openclaw", "openclaw.json"));
20
+ if (!existsSync(resolvedPath))
21
+ return undefined;
22
+ const raw = readFileSync(resolvedPath, "utf-8");
23
+ const config = JSON.parse(raw);
24
+ const token = config.hooks?.token;
25
+ return typeof token === "string" && token ? token : undefined;
26
+ }
27
+ catch {
28
+ return undefined;
29
+ }
30
+ }
31
+ export const manifest = {
32
+ name: "openclaw",
33
+ slot: "notifier",
34
+ description: "Notifier plugin: OpenClaw webhook notifications",
35
+ version: "0.1.0",
36
+ };
37
+ const DEFAULT_TIMEOUT_MS = 10_000;
38
+ const UNREACHABLE_NETWORK_ERROR_CODES = [
39
+ "ECONNREFUSED",
40
+ "ETIMEDOUT",
41
+ "ENOTFOUND",
42
+ "ENETUNREACH",
43
+ ];
44
+ const DEFAULT_HEALTH_SUMMARY = {
45
+ lastSuccessAt: null,
46
+ lastFailureAt: null,
47
+ lastFailureError: null,
48
+ totalSent: 0,
49
+ totalFailed: 0,
50
+ };
51
+ function readHealthSummary(path) {
52
+ try {
53
+ if (!existsSync(path))
54
+ return { ...DEFAULT_HEALTH_SUMMARY };
55
+ const raw = readFileSync(path, "utf-8");
56
+ return {
57
+ ...DEFAULT_HEALTH_SUMMARY,
58
+ ...JSON.parse(raw),
59
+ };
60
+ }
61
+ catch {
62
+ return { ...DEFAULT_HEALTH_SUMMARY };
63
+ }
64
+ }
65
+ function writeHealthSummary(path, summary) {
66
+ try {
67
+ mkdirSync(dirname(path), { recursive: true });
68
+ const tempPath = `${path}.tmp.${process.pid}`;
69
+ writeFileSync(tempPath, JSON.stringify(summary, null, 2) + "\n");
70
+ renameSync(tempPath, path);
71
+ }
72
+ catch {
73
+ // Health telemetry is best-effort and must never block notifications.
74
+ }
75
+ }
76
+ function getHealthSummaryPath(config) {
77
+ const explicitPath = typeof config?.healthSummaryPath === "string" ? config.healthSummaryPath : undefined;
78
+ if (explicitPath)
79
+ return explicitPath;
80
+ const configPath = typeof config?.configPath === "string" ? config.configPath : undefined;
81
+ if (!configPath)
82
+ return null;
83
+ return join(getObservabilityBaseDir(configPath), "openclaw-health.json");
84
+ }
85
+ function recordHealthSuccess(path) {
86
+ if (!path)
87
+ return;
88
+ const summary = readHealthSummary(path);
89
+ summary.lastSuccessAt = new Date().toISOString();
90
+ summary.totalSent += 1;
91
+ writeHealthSummary(path, summary);
92
+ }
93
+ function recordHealthFailure(path, error) {
94
+ if (!path)
95
+ return;
96
+ const summary = readHealthSummary(path);
97
+ summary.lastFailureAt = new Date().toISOString();
98
+ summary.lastFailureError = error instanceof Error ? error.message : String(error);
99
+ summary.totalFailed += 1;
100
+ writeHealthSummary(path, summary);
101
+ }
102
+ function getUnreachableNetworkErrorCode(error) {
103
+ return UNREACHABLE_NETWORK_ERROR_CODES.find((code) => error.message.includes(code));
104
+ }
105
+ async function postWithRetry(url, payload, headers, retries, retryDelayMs, context) {
106
+ let lastError;
107
+ for (let attempt = 0; attempt <= retries; attempt++) {
108
+ const controller = new AbortController();
109
+ const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
110
+ let shouldRethrowResponseError = false;
111
+ try {
112
+ const response = await fetch(url, {
113
+ method: "POST",
114
+ headers,
115
+ body: JSON.stringify(payload),
116
+ signal: controller.signal,
117
+ });
118
+ if (response.ok)
119
+ return;
120
+ const body = await response.text();
121
+ if (response.status === 401 || response.status === 403) {
122
+ // User-actionable: distinct from generic 5xx — token expired or wrong.
123
+ recordActivityEvent({
124
+ sessionId: context.sessionId,
125
+ source: "notifier",
126
+ kind: "notifier.auth_failed",
127
+ level: "error",
128
+ summary: `OpenClaw rejected auth token (HTTP ${response.status})`,
129
+ data: {
130
+ plugin: "notifier-openclaw",
131
+ status: response.status,
132
+ url,
133
+ fixHint: "athene setup openclaw",
134
+ },
135
+ });
136
+ lastError = new Error(`OpenClaw rejected the auth token (HTTP ${response.status}).\n` +
137
+ ` Check that hooks.token in your OpenClaw config matches the token configured for AO.\n` +
138
+ ` Reconfigure: athene setup openclaw`);
139
+ shouldRethrowResponseError = true;
140
+ throw lastError;
141
+ }
142
+ lastError = new Error(`OpenClaw webhook failed (${response.status}): ${body}`);
143
+ if (!isRetryableHttpStatus(response.status)) {
144
+ shouldRethrowResponseError = true;
145
+ throw lastError;
146
+ }
147
+ if (attempt < retries) {
148
+ console.warn(`[notifier-openclaw] Retry ${attempt + 1}/${retries} for session=${context.sessionId} after HTTP ${response.status}`);
149
+ }
150
+ }
151
+ catch (err) {
152
+ if (shouldRethrowResponseError && err === lastError)
153
+ throw err;
154
+ lastError = err instanceof Error ? err : new Error(String(err));
155
+ const unreachableCode = getUnreachableNetworkErrorCode(lastError);
156
+ if (unreachableCode && (unreachableCode === "ECONNREFUSED" || attempt >= retries)) {
157
+ recordActivityEvent({
158
+ sessionId: context.sessionId,
159
+ source: "notifier",
160
+ kind: "notifier.unreachable",
161
+ level: "warn",
162
+ summary: `OpenClaw gateway unreachable at ${url}`,
163
+ data: {
164
+ plugin: "notifier-openclaw",
165
+ url,
166
+ errorMessage: lastError.message,
167
+ fixHint: "openclaw status",
168
+ },
169
+ });
170
+ throw new Error(`Can't reach OpenClaw gateway at ${url}.\n` +
171
+ ` Is OpenClaw running? Check: openclaw status\n` +
172
+ ` Wrong URL? Run: athene setup openclaw`, { cause: err });
173
+ }
174
+ if (attempt < retries) {
175
+ console.warn(`[notifier-openclaw] Retry ${attempt + 1}/${retries} for session=${context.sessionId} after network error: ${lastError.message}`);
176
+ }
177
+ }
178
+ finally {
179
+ clearTimeout(timer);
180
+ }
181
+ if (attempt < retries) {
182
+ const delay = retryDelayMs * 2 ** attempt;
183
+ await new Promise((resolve) => setTimeout(resolve, delay));
184
+ }
185
+ }
186
+ throw lastError;
187
+ }
188
+ function sanitizeSessionId(id) {
189
+ return id.replace(/[^a-zA-Z0-9:_-]/g, "-");
190
+ }
191
+ function eventHeadline(event) {
192
+ const priorityTag = {
193
+ urgent: "URGENT",
194
+ action: "ACTION",
195
+ warning: "WARNING",
196
+ info: "INFO",
197
+ };
198
+ return `**AO ${priorityTag[event.priority]}** \`${event.type}\``;
199
+ }
200
+ function isPrimitive(value) {
201
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
202
+ }
203
+ function compactValue(value) {
204
+ if (value === null || value === undefined)
205
+ return undefined;
206
+ if (isPrimitive(value))
207
+ return String(value);
208
+ if (value instanceof Date)
209
+ return value.toISOString();
210
+ return undefined;
211
+ }
212
+ function truncate(value, maxLength = 140) {
213
+ return value.length > maxLength ? `${value.slice(0, maxLength - 3)}...` : value;
214
+ }
215
+ function escapeMarkdownLinkLabel(value) {
216
+ return value
217
+ .replace(/\\/g, "\\\\")
218
+ .replace(/\[/g, "\\[")
219
+ .replace(/\]/g, "\\]")
220
+ .replace(/\(/g, "\\(")
221
+ .replace(/\)/g, "\\)")
222
+ .replace(/\*/g, "\\*")
223
+ .replace(/_/g, "\\_")
224
+ .replace(/~/g, "\\~")
225
+ .replace(/`/g, "\\`");
226
+ }
227
+ function escapeMarkdownLinkUrl(value) {
228
+ return value.replace(/[()\\\s<>]/g, (char) => {
229
+ const code = char.codePointAt(0) ?? 0;
230
+ return `%${code.toString(16).toUpperCase().padStart(2, "0")}`;
231
+ });
232
+ }
233
+ function formatLink(label, url) {
234
+ return `[${escapeMarkdownLinkLabel(label)}](${escapeMarkdownLinkUrl(url)})`;
235
+ }
236
+ function pushSection(lines, title, items) {
237
+ const filtered = items.filter(Boolean);
238
+ if (filtered.length === 0)
239
+ return;
240
+ lines.push("", `**${title}**`, ...filtered);
241
+ }
242
+ function formatSubjectLines(data) {
243
+ const subject = data.subject;
244
+ const lines = [
245
+ `- Project: \`${subject.session.projectId}\``,
246
+ `- Session: \`${subject.session.id}\``,
247
+ ];
248
+ if (subject.issue) {
249
+ const label = subject.issue.title
250
+ ? `${subject.issue.id} - ${subject.issue.title}`
251
+ : subject.issue.id;
252
+ lines.push(`- Issue: ${label}`);
253
+ }
254
+ return lines;
255
+ }
256
+ function formatPrLines(data) {
257
+ const pr = data.subject.pr;
258
+ if (!pr)
259
+ return [];
260
+ const title = pr.title ? ` - ${pr.title}` : "";
261
+ const lines = [`- PR: ${formatLink(`#${pr.number}${title}`, pr.url)}`];
262
+ if (pr.branch)
263
+ lines.push(`- Branch: \`${pr.branch}\``);
264
+ if (pr.baseBranch)
265
+ lines.push(`- Base: \`${pr.baseBranch}\``);
266
+ if (typeof pr.isDraft === "boolean")
267
+ lines.push(`- Draft: ${pr.isDraft ? "yes" : "no"}`);
268
+ return lines;
269
+ }
270
+ function formatStatusLines(data) {
271
+ const lines = [];
272
+ if (data.transition) {
273
+ lines.push(`- Transition: \`${data.transition.from}\` -> \`${data.transition.to}\``);
274
+ }
275
+ if (data.ci?.status)
276
+ lines.push(`- CI: \`${data.ci.status}\``);
277
+ if (data.review?.decision)
278
+ lines.push(`- Review: \`${data.review.decision}\``);
279
+ if (typeof data.review?.unresolvedThreads === "number") {
280
+ lines.push(`- Unresolved threads: ${data.review.unresolvedThreads}`);
281
+ }
282
+ if (typeof data.merge?.ready === "boolean") {
283
+ lines.push(`- Merge ready: ${data.merge.ready ? "yes" : "no"}`);
284
+ }
285
+ if (typeof data.merge?.conflicts === "boolean") {
286
+ lines.push(`- Conflicts: ${data.merge.conflicts ? "yes" : "no"}`);
287
+ }
288
+ if (typeof data.merge?.isBehind === "boolean") {
289
+ lines.push(`- Behind base: ${data.merge.isBehind ? "yes" : "no"}`);
290
+ }
291
+ if (data.reaction) {
292
+ lines.push(`- Reaction: \`${data.reaction.key}\` -> \`${data.reaction.action}\``);
293
+ }
294
+ if (data.escalation) {
295
+ lines.push(`- Escalation: ${data.escalation.attempts} attempts (${data.escalation.cause})`);
296
+ }
297
+ return lines;
298
+ }
299
+ function formatCheckLine(check) {
300
+ const status = check.conclusion ? `${check.status}/${check.conclusion}` : check.status;
301
+ const name = check.url ? formatLink(check.name, check.url) : check.name;
302
+ return `- ${name}: \`${status}\``;
303
+ }
304
+ function formatCheckLines(data) {
305
+ const checks = data.ci?.failedChecks ?? [];
306
+ return checks.slice(0, 8).map(formatCheckLine);
307
+ }
308
+ function formatBlockerLines(data) {
309
+ const blockers = data.merge?.blockers ?? [];
310
+ return blockers.slice(0, 8).map((blocker) => `- ${blocker}`);
311
+ }
312
+ function formatLinkLines(data) {
313
+ const links = [];
314
+ if (data.subject.pr?.url)
315
+ links.push(`- ${formatLink("Pull request", data.subject.pr.url)}`);
316
+ if (data.review?.url)
317
+ links.push(`- ${formatLink("Review", data.review.url)}`);
318
+ return links;
319
+ }
320
+ function formatLegacyContext(data) {
321
+ return Object.entries(data)
322
+ .filter(([, value]) => compactValue(value) !== undefined)
323
+ .slice(0, 8)
324
+ .map(([key, value]) => `- ${key}: ${truncate(compactValue(value) ?? "")}`);
325
+ }
326
+ function formatEscalationMessage(event) {
327
+ const lines = [eventHeadline(event), "", event.message];
328
+ const data = getNotificationDataV3(event.data);
329
+ if (!data) {
330
+ pushSection(lines, "Session", [
331
+ `- Project: \`${event.projectId}\``,
332
+ `- Session: \`${event.sessionId}\``,
333
+ ]);
334
+ pushSection(lines, "Context", formatLegacyContext(event.data));
335
+ return lines.join("\n");
336
+ }
337
+ pushSection(lines, "Session", formatSubjectLines(data));
338
+ pushSection(lines, "Pull Request", formatPrLines(data));
339
+ pushSection(lines, "Status", formatStatusLines(data));
340
+ pushSection(lines, "Checks", formatCheckLines(data));
341
+ pushSection(lines, "Blockers", formatBlockerLines(data));
342
+ pushSection(lines, "Links", formatLinkLines(data));
343
+ return lines.join("\n");
344
+ }
345
+ function formatActionsLine(actions) {
346
+ if (actions.length === 0)
347
+ return "";
348
+ const lines = actions.map((action) => {
349
+ const target = action.url ?? action.callbackEndpoint;
350
+ return target ? `- ${formatLink(action.label, target)}` : `- ${action.label}`;
351
+ });
352
+ return ["", "**Actions**", ...lines].join("\n");
353
+ }
354
+ /**
355
+ * Resolve a token value that may be a `${ENV_VAR}` placeholder (as written
356
+ * into agent-orchestrator.yaml by `athene setup openclaw`) or a literal string.
357
+ * Returns undefined for empty/unresolvable values so callers can chain `??`.
358
+ */
359
+ function resolveEnvVarToken(raw) {
360
+ if (typeof raw !== "string" || !raw)
361
+ return undefined;
362
+ const match = raw.match(/^\$\{([^}]+)\}$/);
363
+ if (match)
364
+ return process.env[match[1]] || undefined;
365
+ return raw;
366
+ }
367
+ export function create(config) {
368
+ const url = (typeof config?.url === "string" ? config.url : undefined) ??
369
+ "http://127.0.0.1:18789/hooks/agent";
370
+ const openclawConfigPath = typeof config?.openclawConfigPath === "string" ? config.openclawConfigPath : undefined;
371
+ const token = resolveEnvVarToken(config?.token) ??
372
+ readTokenFromOpenClawConfig(openclawConfigPath) ??
373
+ process.env.OPENCLAW_HOOKS_TOKEN;
374
+ const senderName = typeof config?.name === "string" ? config.name : "AO";
375
+ const sessionKeyPrefix = typeof config?.sessionKeyPrefix === "string" ? config.sessionKeyPrefix : "hook:ao:";
376
+ const wakeMode = config?.wakeMode === "next-heartbeat" ? "next-heartbeat" : "now";
377
+ const deliver = typeof config?.deliver === "boolean" ? config.deliver : true;
378
+ const healthSummaryPath = getHealthSummaryPath(config);
379
+ const { retries, retryDelayMs } = normalizeRetryConfig(config);
380
+ validateUrl(url, "notifier-openclaw");
381
+ if (!token) {
382
+ console.warn("[notifier-openclaw] No token configured.\n" +
383
+ " Add hooks.token to your OpenClaw config, or set notifiers.openclaw.openclawConfigPath.\n" +
384
+ " Run: athene setup openclaw");
385
+ }
386
+ async function sendPayload(payload) {
387
+ const headers = {
388
+ "Content-Type": "application/json",
389
+ };
390
+ if (token)
391
+ headers["Authorization"] = `Bearer ${token}`;
392
+ const sessionId = payload.sessionKey?.slice(sessionKeyPrefix.length) ?? "default";
393
+ try {
394
+ await postWithRetry(url, payload, headers, retries, retryDelayMs, { sessionId });
395
+ recordHealthSuccess(healthSummaryPath);
396
+ }
397
+ catch (err) {
398
+ recordHealthFailure(healthSummaryPath, err);
399
+ throw err;
400
+ }
401
+ }
402
+ return {
403
+ name: "openclaw",
404
+ async notify(event) {
405
+ const sessionKey = `${sessionKeyPrefix}${sanitizeSessionId(event.sessionId)}`;
406
+ await sendPayload({
407
+ message: formatEscalationMessage(event),
408
+ name: senderName,
409
+ sessionKey,
410
+ wakeMode,
411
+ deliver,
412
+ });
413
+ },
414
+ async notifyWithActions(event, actions) {
415
+ const sessionKey = `${sessionKeyPrefix}${sanitizeSessionId(event.sessionId)}`;
416
+ const actionsLine = formatActionsLine(actions);
417
+ const message = [formatEscalationMessage(event), actionsLine].filter(Boolean).join("\n");
418
+ await sendPayload({
419
+ message,
420
+ name: senderName,
421
+ sessionKey,
422
+ wakeMode,
423
+ deliver,
424
+ });
425
+ },
426
+ async post(message, context) {
427
+ const sessionId = context?.sessionId ? sanitizeSessionId(context.sessionId) : "default";
428
+ const sessionKey = `${sessionKeyPrefix}${sessionId}`;
429
+ await sendPayload({
430
+ message,
431
+ name: senderName,
432
+ sessionKey,
433
+ wakeMode,
434
+ deliver,
435
+ });
436
+ return null;
437
+ },
438
+ };
439
+ }
440
+ export default { manifest, create };
441
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,309 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { buildCIFailureNotificationData, buildSessionTransitionNotificationData, } from "@made-by-moonlight/athene-core";
6
+ import { create, manifest } from "./index.js";
7
+ function makeEvent(overrides = {}) {
8
+ return {
9
+ id: "evt-1",
10
+ type: "reaction.escalated",
11
+ priority: "urgent",
12
+ sessionId: "ao-5",
13
+ projectId: "ao",
14
+ timestamp: new Date("2026-03-08T12:00:00Z"),
15
+ message: "Reaction escalated after retries",
16
+ data: { attempts: 5, reason: "ci_failed" },
17
+ ...overrides,
18
+ };
19
+ }
20
+ const prContext = {
21
+ pr: {
22
+ number: 1579,
23
+ url: "https://github.com/slievr/Athene/pull/1579",
24
+ title: "Normalize AO notifier payloads",
25
+ branch: "ao/demo-notifier-harness",
26
+ baseBranch: "main",
27
+ owner: "slievr",
28
+ repo: "agent-orchestrator",
29
+ isDraft: false,
30
+ },
31
+ prs: [
32
+ {
33
+ number: 1579,
34
+ url: "https://github.com/slievr/Athene/pull/1579",
35
+ title: "Normalize AO notifier payloads",
36
+ branch: "ao/demo-notifier-harness",
37
+ baseBranch: "main",
38
+ owner: "slievr",
39
+ repo: "agent-orchestrator",
40
+ isDraft: false,
41
+ },
42
+ ],
43
+ issueId: "AO-1579",
44
+ issueTitle: "Make AO notification payloads API-grade",
45
+ summary: "Normalize AO notifier payloads",
46
+ branch: "ao/demo-notifier-harness",
47
+ };
48
+ describe("notifier-openclaw", () => {
49
+ let tempConfigDir;
50
+ let tempConfigPath;
51
+ let tempHealthPath;
52
+ beforeEach(() => {
53
+ vi.restoreAllMocks();
54
+ delete process.env.OPENCLAW_HOOKS_TOKEN;
55
+ tempConfigDir = mkdtempSync(join(tmpdir(), "openclaw-notifier-test-"));
56
+ tempConfigPath = join(tempConfigDir, "agent-orchestrator.yaml");
57
+ tempHealthPath = join(tempConfigDir, "openclaw-health.json");
58
+ writeFileSync(tempConfigPath, "projects: {}\n");
59
+ });
60
+ afterEach(() => {
61
+ vi.unstubAllGlobals();
62
+ vi.useRealTimers();
63
+ rmSync(tempConfigDir, { recursive: true, force: true });
64
+ });
65
+ it("has correct manifest", () => {
66
+ expect(manifest.name).toBe("openclaw");
67
+ expect(manifest.slot).toBe("notifier");
68
+ });
69
+ it("uses default OpenClaw hooks endpoint", async () => {
70
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
71
+ vi.stubGlobal("fetch", fetchMock);
72
+ const notifier = create({ token: "tok" });
73
+ await notifier.notify(makeEvent());
74
+ expect(fetchMock).toHaveBeenCalledOnce();
75
+ expect(fetchMock.mock.calls[0][0]).toBe("http://127.0.0.1:18789/hooks/agent");
76
+ });
77
+ it("uses token from OPENCLAW_HOOKS_TOKEN env", async () => {
78
+ process.env.OPENCLAW_HOOKS_TOKEN = "env-token";
79
+ const missingOpenClawConfigPath = join(tempConfigDir, "missing-openclaw.json");
80
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
81
+ vi.stubGlobal("fetch", fetchMock);
82
+ const notifier = create({ openclawConfigPath: missingOpenClawConfigPath });
83
+ await notifier.notify(makeEvent());
84
+ const headers = fetchMock.mock.calls[0][1].headers;
85
+ expect(headers["Authorization"]).toBe("Bearer env-token");
86
+ });
87
+ it("uses hooks token from configured OpenClaw config path", async () => {
88
+ const openclawConfigPath = join(tempConfigDir, "openclaw.json");
89
+ writeFileSync(openclawConfigPath, JSON.stringify({ hooks: { token: "config-token" } }));
90
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
91
+ vi.stubGlobal("fetch", fetchMock);
92
+ const notifier = create({ openclawConfigPath });
93
+ await notifier.notify(makeEvent());
94
+ const headers = fetchMock.mock.calls[0][1].headers;
95
+ expect(headers["Authorization"]).toBe("Bearer config-token");
96
+ });
97
+ it("warns and sends without Authorization when token missing", async () => {
98
+ const missingOpenClawConfigPath = join(tempConfigDir, "missing-openclaw.json");
99
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
100
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
101
+ vi.stubGlobal("fetch", fetchMock);
102
+ const notifier = create({ openclawConfigPath: missingOpenClawConfigPath });
103
+ await notifier.notify(makeEvent());
104
+ const headers = fetchMock.mock.calls[0][1].headers;
105
+ expect(headers["Authorization"]).toBeUndefined();
106
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("No token configured"));
107
+ });
108
+ it("builds per-session OpenClaw session key", async () => {
109
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
110
+ vi.stubGlobal("fetch", fetchMock);
111
+ const notifier = create({ token: "tok", sessionKeyPrefix: "hook:ao:" });
112
+ await notifier.notify(makeEvent({ sessionId: "ao-12" }));
113
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
114
+ expect(body.sessionKey).toBe("hook:ao:ao-12");
115
+ });
116
+ it("sanitizes invalid characters in session id", async () => {
117
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
118
+ vi.stubGlobal("fetch", fetchMock);
119
+ const notifier = create({ token: "tok" });
120
+ await notifier.notify(makeEvent({ sessionId: "ao/12?x" }));
121
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
122
+ expect(body.sessionKey).toBe("hook:ao:ao-12-x");
123
+ });
124
+ it("notifyWithActions appends action links", async () => {
125
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
126
+ vi.stubGlobal("fetch", fetchMock);
127
+ const notifier = create({ token: "tok" });
128
+ const actions = [
129
+ { label: "Open dashboard", url: "http://localhost:3000" },
130
+ { label: "Acknowledge", callbackEndpoint: "http://localhost:3000/api/ack" },
131
+ ];
132
+ await notifier.notifyWithActions(makeEvent(), actions);
133
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
134
+ expect(body.message).toContain("**Actions**");
135
+ expect(body.message).toContain("- [Open dashboard](http://localhost:3000)");
136
+ expect(body.message).toContain("- [Acknowledge](http://localhost:3000/api/ack)");
137
+ });
138
+ it("escapes markdown-sensitive labels and URLs in links", async () => {
139
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
140
+ vi.stubGlobal("fetch", fetchMock);
141
+ const notifier = create({ token: "tok" });
142
+ const actions = [
143
+ {
144
+ label: "Open [prod] (now) *please*",
145
+ url: "https://github.com/org/repo/pull/1?a=(test)",
146
+ },
147
+ ];
148
+ await notifier.notifyWithActions(makeEvent(), actions);
149
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
150
+ expect(body.message).toContain("- [Open \\[prod\\] \\(now\\) \\*please\\*](https://github.com/org/repo/pull/1?a=%28test%29)");
151
+ });
152
+ it("formats v3 CI notifications as a compact OpenClaw brief", async () => {
153
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
154
+ vi.stubGlobal("fetch", fetchMock);
155
+ const notifier = create({ token: "tok" });
156
+ await notifier.notify(makeEvent({
157
+ type: "ci.failing",
158
+ priority: "action",
159
+ sessionId: "demo-agent-19",
160
+ projectId: "demo",
161
+ message: "CI is failing on PR #1579",
162
+ data: buildCIFailureNotificationData({
163
+ sessionId: "demo-agent-19",
164
+ projectId: "demo",
165
+ context: prContext,
166
+ failedChecks: [
167
+ {
168
+ name: "typecheck",
169
+ status: "failed",
170
+ conclusion: "FAILURE",
171
+ url: "https://github.com/slievr/Athene/pull/1579/checks",
172
+ },
173
+ ],
174
+ }),
175
+ }));
176
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
177
+ expect(body.message).toContain("**AO ACTION** `ci.failing`");
178
+ expect(body.message).toContain("**Pull Request**");
179
+ expect(body.message).toContain("[#1579 - Normalize AO notifier payloads](https://github.com/slievr/Athene/pull/1579)");
180
+ expect(body.message).toContain("**Checks**");
181
+ expect(body.message).toContain("- [typecheck](https://github.com/slievr/Athene/pull/1579/checks): `failed/FAILURE`");
182
+ expect(body.message).not.toContain("Context: {");
183
+ });
184
+ it("formats v3 merge notifications with status and links", async () => {
185
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
186
+ vi.stubGlobal("fetch", fetchMock);
187
+ const notifier = create({ token: "tok" });
188
+ await notifier.notify(makeEvent({
189
+ type: "merge.ready",
190
+ priority: "action",
191
+ sessionId: "demo-agent-29",
192
+ projectId: "demo",
193
+ message: "PR #1579 is ready to merge",
194
+ data: buildSessionTransitionNotificationData({
195
+ eventType: "merge.ready",
196
+ sessionId: "demo-agent-29",
197
+ projectId: "demo",
198
+ context: prContext,
199
+ oldStatus: "approved",
200
+ newStatus: "mergeable",
201
+ enrichment: {
202
+ state: "open",
203
+ ciStatus: "passing",
204
+ reviewDecision: "approved",
205
+ mergeable: true,
206
+ title: "Normalize AO notifier payloads",
207
+ hasConflicts: false,
208
+ isBehind: false,
209
+ },
210
+ }),
211
+ }));
212
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
213
+ expect(body.message).toContain("- Transition: `approved` -> `mergeable`");
214
+ expect(body.message).toContain("- CI: `passing`");
215
+ expect(body.message).toContain("- Review: `approved`");
216
+ expect(body.message).toContain("- Merge ready: yes");
217
+ expect(body.message).toContain("- [Pull request](https://github.com/slievr/Athene/pull/1579)");
218
+ });
219
+ it("post uses context sessionId when provided", async () => {
220
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
221
+ vi.stubGlobal("fetch", fetchMock);
222
+ const notifier = create({ token: "tok" });
223
+ await notifier.post("ready", { sessionId: "ao-77" });
224
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
225
+ expect(body.sessionKey).toBe("hook:ao:ao-77");
226
+ expect(body.message).toBe("ready");
227
+ });
228
+ it("defaults wakeMode=now and deliver=true", async () => {
229
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
230
+ vi.stubGlobal("fetch", fetchMock);
231
+ const notifier = create({ token: "tok" });
232
+ await notifier.notify(makeEvent());
233
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
234
+ expect(body.wakeMode).toBe("now");
235
+ expect(body.deliver).toBe(true);
236
+ });
237
+ it("supports wakeMode=next-heartbeat when configured", async () => {
238
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
239
+ vi.stubGlobal("fetch", fetchMock);
240
+ const notifier = create({ token: "tok", wakeMode: "next-heartbeat" });
241
+ await notifier.notify(makeEvent());
242
+ const body = JSON.parse(fetchMock.mock.calls[0][1].body);
243
+ expect(body.wakeMode).toBe("next-heartbeat");
244
+ });
245
+ it("retries on 5xx response", async () => {
246
+ vi.useFakeTimers();
247
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => { });
248
+ const fetchMock = vi
249
+ .fn()
250
+ .mockResolvedValueOnce({ ok: false, status: 503, text: () => Promise.resolve("down") })
251
+ .mockResolvedValueOnce({ ok: true });
252
+ vi.stubGlobal("fetch", fetchMock);
253
+ const notifier = create({ token: "tok", retries: 1, retryDelayMs: 50 });
254
+ const promise = notifier.notify(makeEvent());
255
+ await vi.advanceTimersByTimeAsync(0);
256
+ expect(fetchMock).toHaveBeenCalledTimes(1);
257
+ await vi.advanceTimersByTimeAsync(50);
258
+ expect(fetchMock).toHaveBeenCalledTimes(2);
259
+ await promise;
260
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("Retry 1/1 for session=ao-5 after HTTP 503"));
261
+ });
262
+ it("does not retry on 4xx response", async () => {
263
+ const fetchMock = vi
264
+ .fn()
265
+ .mockResolvedValue({ ok: false, status: 401, text: () => Promise.resolve("unauthorized") });
266
+ vi.stubGlobal("fetch", fetchMock);
267
+ const notifier = create({ token: "tok", retries: 2, retryDelayMs: 1 });
268
+ await expect(notifier.notify(makeEvent())).rejects.toThrow("OpenClaw rejected the auth token");
269
+ expect(fetchMock).toHaveBeenCalledTimes(1);
270
+ });
271
+ it("throws actionable error on ECONNREFUSED", async () => {
272
+ const fetchMock = vi.fn().mockRejectedValue(new Error("fetch failed: ECONNREFUSED"));
273
+ vi.stubGlobal("fetch", fetchMock);
274
+ const notifier = create({ token: "tok", retries: 0 });
275
+ await expect(notifier.notify(makeEvent())).rejects.toThrow("Can't reach OpenClaw gateway");
276
+ });
277
+ it("records success telemetry when a notification is sent", async () => {
278
+ const fetchMock = vi.fn().mockResolvedValue({ ok: true });
279
+ vi.stubGlobal("fetch", fetchMock);
280
+ const notifier = create({
281
+ token: "tok",
282
+ configPath: tempConfigPath,
283
+ healthSummaryPath: tempHealthPath,
284
+ });
285
+ await notifier.notify(makeEvent());
286
+ expect(existsSync(tempHealthPath)).toBe(true);
287
+ const summary = JSON.parse(readFileSync(tempHealthPath, "utf-8"));
288
+ expect(summary.lastSuccessAt).toBeTruthy();
289
+ expect(summary.totalSent).toBe(1);
290
+ expect(summary.totalFailed).toBe(0);
291
+ });
292
+ it("records failure telemetry when notification delivery fails", async () => {
293
+ const fetchMock = vi.fn().mockRejectedValue(new Error("fetch failed: ECONNREFUSED"));
294
+ vi.stubGlobal("fetch", fetchMock);
295
+ const notifier = create({
296
+ token: "tok",
297
+ retries: 0,
298
+ configPath: tempConfigPath,
299
+ healthSummaryPath: tempHealthPath,
300
+ });
301
+ await expect(notifier.notify(makeEvent())).rejects.toThrow();
302
+ const summary = JSON.parse(readFileSync(tempHealthPath, "utf-8"));
303
+ expect(summary.lastFailureAt).toBeTruthy();
304
+ expect(summary.lastFailureError).toContain("Can't reach OpenClaw gateway");
305
+ expect(summary.totalSent).toBe(0);
306
+ expect(summary.totalFailed).toBe(1);
307
+ });
308
+ });
309
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@made-by-moonlight/athene-plugin-notifier-openclaw",
3
+ "version": "0.9.1",
4
+ "description": "Notifier plugin: OpenClaw webhook notifications",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/slievr/Athene.git",
21
+ "directory": "packages/plugins/notifier-openclaw"
22
+ },
23
+ "homepage": "https://github.com/slievr/Athene",
24
+ "bugs": {
25
+ "url": "https://github.com/slievr/Athene/issues"
26
+ },
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "dependencies": {
31
+ "@made-by-moonlight/athene-core": "0.9.1"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.2.3",
35
+ "typescript": "^5.7.0",
36
+ "vitest": "^3.0.0"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "typecheck": "tsc --noEmit",
44
+ "test": "vitest run",
45
+ "clean": "rm -rf dist"
46
+ }
47
+ }