@alfe.ai/openclaw-webhooks 0.0.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.
@@ -0,0 +1,2 @@
1
+ import { i as WebhooksPluginConfig, n as Logger, r as OpenClawPluginApi, t as plugin } from "./plugin.js";
2
+ export { type Logger, type OpenClawPluginApi, type WebhooksPluginConfig, plugin };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import plugin from "./plugin.js";
2
+ export { plugin };
@@ -0,0 +1,48 @@
1
+ //#region src/types.d.ts
2
+ /**
3
+ * Types for the Alfe webhooks plugin.
4
+ */
5
+ interface WebhooksPluginConfig {
6
+ /** Alfe daemon IPC socket path override. */
7
+ daemonSocket?: string;
8
+ /** Webhooks service WebSocket URL (e.g. wss://webhooks.dev.alfe.ai/ws) */
9
+ webhooksWsUrl?: string;
10
+ /** API key for webhooks service auth */
11
+ apiKey?: string;
12
+ }
13
+ interface Logger {
14
+ info(msg: string, ...args: unknown[]): void;
15
+ warn(msg: string, ...args: unknown[]): void;
16
+ error(msg: string, ...args: unknown[]): void;
17
+ debug(msg: string, ...args: unknown[]): void;
18
+ }
19
+ interface OpenClawConfig {
20
+ plugins?: {
21
+ entries?: Record<string, {
22
+ config?: WebhooksPluginConfig;
23
+ [key: string]: unknown;
24
+ }>;
25
+ [key: string]: unknown;
26
+ };
27
+ [key: string]: unknown;
28
+ }
29
+ interface OpenClawPluginApi {
30
+ logger: Logger;
31
+ config?: OpenClawConfig;
32
+ registerGatewayMethod?(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
33
+ on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: {
34
+ priority?: number;
35
+ }): void;
36
+ }
37
+ //#endregion
38
+ //#region src/plugin.d.ts
39
+ declare const plugin: {
40
+ id: string;
41
+ name: string;
42
+ description: string;
43
+ version: string;
44
+ activate(api: OpenClawPluginApi): Promise<void>;
45
+ deactivate(api: OpenClawPluginApi): void;
46
+ };
47
+ //#endregion
48
+ export { WebhooksPluginConfig as i, Logger as n, OpenClawPluginApi as r, plugin as t };
package/dist/plugin.js ADDED
@@ -0,0 +1,175 @@
1
+ import { join } from "node:path";
2
+ import { homedir } from "node:os";
3
+ import { WebhooksServiceClient } from "@alfe.ai/webhooks";
4
+ //#region src/plugin.ts
5
+ /**
6
+ * @alfe.ai/openclaw-webhooks — OpenClaw webhooks plugin.
7
+ *
8
+ * Receives webhook deliveries from the Alfe webhooks service and
9
+ * exposes tools for the agent to manage its own webhooks.
10
+ *
11
+ * Follows the same pattern as @alfe.ai/openclaw-chat:
12
+ * - Connects to Alfe daemon IPC for capability registration
13
+ * - Connects to webhooks service WS for real-time delivery
14
+ * - Registers gateway RPC methods for webhook management
15
+ * - Exposes agent-callable tools for self-service CRUD
16
+ */
17
+ const DEFAULT_SOCKET_PATH = join(homedir(), ".alfe", "gateway.sock");
18
+ const WEBHOOKS_CAPABILITIES = ["webhooks.receive", "webhooks.manage"];
19
+ let daemonIpcClient = null;
20
+ let webhooksClient = null;
21
+ /**
22
+ * Attempt to connect to the Alfe daemon IPC socket.
23
+ */
24
+ async function connectToDaemon(socketPath, log) {
25
+ try {
26
+ const IPCClientCtor = (await import("@alfe.ai/openclaw")).IPCClient;
27
+ const client = new IPCClientCtor(socketPath, log);
28
+ client.on("connected", async () => {
29
+ log.info("Connected to Alfe daemon — registering webhooks capabilities...");
30
+ const response = await client.request("capability.register", {
31
+ plugin: "@alfe.ai/openclaw-webhooks",
32
+ capabilities: [...WEBHOOKS_CAPABILITIES]
33
+ });
34
+ if (response.ok) log.info("Webhooks capabilities registered with daemon");
35
+ else log.warn(`Failed to register webhooks capabilities: ${response.error?.message ?? "unknown"}`);
36
+ });
37
+ client.on("disconnected", (reason) => {
38
+ log.warn(`Disconnected from Alfe daemon: ${String(reason)}`);
39
+ });
40
+ client.on("error", (err) => {
41
+ log.debug(`Daemon IPC error: ${err.message}`);
42
+ });
43
+ client.start();
44
+ return client;
45
+ } catch {
46
+ log.info("Alfe daemon not available — webhooks plugin running standalone");
47
+ return null;
48
+ }
49
+ }
50
+ const plugin = {
51
+ id: "@alfe.ai/openclaw-webhooks",
52
+ name: "Alfe Webhooks Plugin",
53
+ description: "Receive and manage HTTP webhooks from external services",
54
+ version: "0.1.0",
55
+ async activate(api) {
56
+ if (globalThis.__alfeWebhooksPluginActivated) {
57
+ api.logger.debug("Alfe Webhooks plugin already activated, skipping re-init");
58
+ return;
59
+ }
60
+ globalThis.__alfeWebhooksPluginActivated = true;
61
+ const log = api.logger;
62
+ log.info("Alfe Webhooks plugin activating...");
63
+ const pluginConfig = (api.config ?? {}).plugins?.entries?.["@alfe.ai/openclaw-webhooks"]?.config ?? {};
64
+ daemonIpcClient = await connectToDaemon(pluginConfig.daemonSocket ?? process.env.ALFE_GATEWAY_SOCKET ?? DEFAULT_SOCKET_PATH, log);
65
+ const webhooksWsUrl = pluginConfig.webhooksWsUrl ?? process.env.ALFE_WEBHOOKS_WS_URL;
66
+ const apiKey = pluginConfig.apiKey ?? process.env.ALFE_API_KEY;
67
+ if (webhooksWsUrl && apiKey) {
68
+ log.info(`Connecting to webhooks service: ${webhooksWsUrl}`);
69
+ webhooksClient = new WebhooksServiceClient({
70
+ wsUrl: webhooksWsUrl,
71
+ apiKey,
72
+ onWebhook: (delivery) => {
73
+ log.info(`Webhook received: ${delivery.name} (${delivery.webhookId}) provider=${delivery.provider}`);
74
+ if (daemonIpcClient) daemonIpcClient.request("event.emit", {
75
+ event: "webhook.received",
76
+ payload: delivery
77
+ }).catch((err) => {
78
+ log.debug(`Failed to emit webhook event to daemon: ${err.message}`);
79
+ });
80
+ },
81
+ onConnectionChange: (connected) => {
82
+ log.info(`Webhooks service connection: ${connected ? "connected" : "disconnected"}`);
83
+ },
84
+ logger: log
85
+ });
86
+ webhooksClient.start();
87
+ log.info("Webhooks service client started");
88
+ } else log.info("Webhooks service URL not configured — running without webhooks relay");
89
+ if (typeof api.registerGatewayMethod === "function") {
90
+ api.registerGatewayMethod("webhooks.create", async (...args) => {
91
+ const params = args[0];
92
+ if (!daemonIpcClient) return {
93
+ ok: false,
94
+ error: "Daemon not connected"
95
+ };
96
+ const response = await daemonIpcClient.request("webhooks.create", params);
97
+ return response.ok ? response.payload : {
98
+ ok: false,
99
+ error: response.error?.message
100
+ };
101
+ });
102
+ api.registerGatewayMethod("webhooks.list", async () => {
103
+ if (!daemonIpcClient) return {
104
+ ok: false,
105
+ error: "Daemon not connected"
106
+ };
107
+ const response = await daemonIpcClient.request("webhooks.list", {});
108
+ return response.ok ? response.payload : {
109
+ ok: false,
110
+ error: response.error?.message
111
+ };
112
+ });
113
+ api.registerGatewayMethod("webhooks.delete", async (...args) => {
114
+ const params = args[0];
115
+ if (!daemonIpcClient) return {
116
+ ok: false,
117
+ error: "Daemon not connected"
118
+ };
119
+ const response = await daemonIpcClient.request("webhooks.delete", params);
120
+ return response.ok ? response.payload : {
121
+ ok: false,
122
+ error: response.error?.message
123
+ };
124
+ });
125
+ api.registerGatewayMethod("webhooks.rotate", async (...args) => {
126
+ const params = args[0];
127
+ if (!daemonIpcClient) return {
128
+ ok: false,
129
+ error: "Daemon not connected"
130
+ };
131
+ const response = await daemonIpcClient.request("webhooks.rotate", params);
132
+ return response.ok ? response.payload : {
133
+ ok: false,
134
+ error: response.error?.message
135
+ };
136
+ });
137
+ api.registerGatewayMethod("webhooks.deliveries", async (...args) => {
138
+ const params = args[0];
139
+ if (!daemonIpcClient) return {
140
+ ok: false,
141
+ error: "Daemon not connected"
142
+ };
143
+ const response = await daemonIpcClient.request("webhooks.deliveries", params);
144
+ return response.ok ? response.payload : {
145
+ ok: false,
146
+ error: response.error?.message
147
+ };
148
+ });
149
+ log.info("Registered gateway RPC methods: webhooks.create, webhooks.list, webhooks.delete, webhooks.rotate, webhooks.deliveries");
150
+ }
151
+ log.info("Alfe Webhooks plugin activated");
152
+ },
153
+ deactivate(api) {
154
+ globalThis.__alfeWebhooksPluginActivated = false;
155
+ const log = api.logger;
156
+ log.info("Alfe Webhooks plugin deactivating...");
157
+ if (webhooksClient) {
158
+ webhooksClient.stop();
159
+ webhooksClient = null;
160
+ log.info("Webhooks service client stopped");
161
+ }
162
+ if (daemonIpcClient) {
163
+ try {
164
+ daemonIpcClient.stop();
165
+ log.info("Disconnected from Alfe daemon");
166
+ } catch (err) {
167
+ log.debug(`Error disconnecting from daemon: ${err.message}`);
168
+ }
169
+ daemonIpcClient = null;
170
+ }
171
+ log.info("Alfe Webhooks plugin deactivated");
172
+ }
173
+ };
174
+ //#endregion
175
+ export { plugin as default };
@@ -0,0 +1,2 @@
1
+ import { t as plugin } from "./plugin.js";
2
+ export { plugin as default };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@alfe.ai/openclaw-webhooks",
3
+ "version": "0.0.1",
4
+ "description": "OpenClaw webhooks plugin for Alfe — receive and manage external webhooks",
5
+ "type": "module",
6
+ "main": "./dist/plugin.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./plugin": {
14
+ "import": "./dist/plugin.js",
15
+ "types": "./dist/plugin.d.ts"
16
+ }
17
+ },
18
+ "openclaw": {
19
+ "extensions": [
20
+ "./dist/plugin.js"
21
+ ]
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "dependencies": {
27
+ "ws": "^8.18.0",
28
+ "@alfe.ai/webhooks": "^0.0.1"
29
+ },
30
+ "devDependencies": {
31
+ "@types/ws": "^8.5.13"
32
+ },
33
+ "license": "UNLICENSED",
34
+ "scripts": {
35
+ "build": "tsdown",
36
+ "dev": "tsdown --watch",
37
+ "test": "vitest run --passWithNoTests",
38
+ "typecheck": "tsc --noEmit",
39
+ "lint": "eslint ."
40
+ }
41
+ }