@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.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/plugin.d.ts +48 -0
- package/dist/plugin.js +175 -0
- package/dist/plugin2.d.ts +2 -0
- package/package.json +41 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/plugin.d.ts
ADDED
|
@@ -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 };
|
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
|
+
}
|