@alfe.ai/openclaw-metrics 0.0.2

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,29 @@
1
+ //#region src/plugin.d.ts
2
+ /**
3
+ * @alfe.ai/openclaw-metrics — OpenClaw metrics plugin for Alfe.
4
+ *
5
+ * Hooks into the global `message` event to track per-user activity
6
+ * across all channels (Alfe chat, Discord, Slack, etc.).
7
+ *
8
+ * On each message, fires a fire-and-forget POST to the Alfe API
9
+ * via the AgentApiClient. The backend resolves agentId + tenantId
10
+ * from the agent's API key — the plugin never needs to know or send
11
+ * the Alfe agentId.
12
+ */
13
+ interface PluginLogger {
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 PluginApi {
20
+ logger: PluginLogger;
21
+ on(event: string, handler: (...args: unknown[]) => void | Promise<void>): void;
22
+ }
23
+ declare const plugin: {
24
+ id: string;
25
+ activate(api: PluginApi): void;
26
+ deactivate(api: PluginApi): void;
27
+ };
28
+ //#endregion
29
+ export { plugin as default };
package/dist/plugin.js ADDED
@@ -0,0 +1,92 @@
1
+ import { resolveConfig } from "@alfe.ai/config";
2
+ import { AgentApiClient } from "@alfe.ai/agent-api-client";
3
+ //#region src/session-keys.ts
4
+ /** Known channel segments in canonical session keys. */
5
+ const KNOWN_CHANNELS = new Set([
6
+ "alfe",
7
+ "discord",
8
+ "slack",
9
+ "telegram",
10
+ "whatsapp",
11
+ "signal",
12
+ "irc",
13
+ "googlechat",
14
+ "msteams",
15
+ "imessage",
16
+ "feishu"
17
+ ]);
18
+ /**
19
+ * Parse a session key for userId and channel.
20
+ *
21
+ * Returns empty strings for fields that cannot be determined.
22
+ */
23
+ function parseSessionKey(key) {
24
+ const canonicalMatch = /^agent:[^:]+:([^:]+):(?:default:)?direct:([^:]+)/.exec(key);
25
+ if (canonicalMatch) {
26
+ const [, channel, userId] = canonicalMatch;
27
+ return {
28
+ userId,
29
+ channel: KNOWN_CHANNELS.has(channel) ? channel : "unknown"
30
+ };
31
+ }
32
+ if (key.includes("chat-")) return {
33
+ userId: "",
34
+ channel: "alfe"
35
+ };
36
+ return {
37
+ userId: "",
38
+ channel: "unknown"
39
+ };
40
+ }
41
+ //#endregion
42
+ //#region src/plugin.ts
43
+ /**
44
+ * @alfe.ai/openclaw-metrics — OpenClaw metrics plugin for Alfe.
45
+ *
46
+ * Hooks into the global `message` event to track per-user activity
47
+ * across all channels (Alfe chat, Discord, Slack, etc.).
48
+ *
49
+ * On each message, fires a fire-and-forget POST to the Alfe API
50
+ * via the AgentApiClient. The backend resolves agentId + tenantId
51
+ * from the agent's API key — the plugin never needs to know or send
52
+ * the Alfe agentId.
53
+ */
54
+ let client = null;
55
+ const plugin = {
56
+ id: "@alfe.ai/openclaw-metrics",
57
+ activate(api) {
58
+ const log = api.logger;
59
+ log.info("Alfe Metrics plugin activating...");
60
+ resolveConfig().then((cfg) => {
61
+ client = new AgentApiClient({
62
+ apiKey: cfg.apiKey,
63
+ apiUrl: cfg.apiUrl
64
+ });
65
+ log.info("Alfe Metrics plugin ready — API client initialized");
66
+ }).catch((err) => {
67
+ log.warn(`Failed to resolve Alfe config — metrics will not be reported: ${err instanceof Error ? err.message : String(err)}`);
68
+ });
69
+ api.on("message", (...eventArgs) => {
70
+ if (!client) return;
71
+ const { sessionKey, role } = eventArgs[0];
72
+ if (!sessionKey) return;
73
+ const parsed = parseSessionKey(sessionKey);
74
+ if (!parsed.userId) return;
75
+ client.recordActivity({
76
+ userId: parsed.userId,
77
+ channel: parsed.channel,
78
+ role
79
+ }).catch((err) => {
80
+ log.debug(`Metrics report failed: ${err instanceof Error ? err.message : String(err)}`);
81
+ });
82
+ });
83
+ log.info("Alfe Metrics plugin registered");
84
+ },
85
+ deactivate(api) {
86
+ const log = api.logger;
87
+ client = null;
88
+ log.info("Alfe Metrics plugin deactivated");
89
+ }
90
+ };
91
+ //#endregion
92
+ export { plugin as default };
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "@alfe.ai/openclaw-metrics",
3
+ "configSchema": {
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "properties": {}
7
+ }
8
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@alfe.ai/openclaw-metrics",
3
+ "version": "0.0.2",
4
+ "description": "OpenClaw metrics plugin for Alfe — per-user activity tracking",
5
+ "type": "module",
6
+ "main": "./dist/plugin.js",
7
+ "types": "./dist/plugin.d.ts",
8
+ "exports": {
9
+ "./plugin": {
10
+ "import": "./dist/plugin.js",
11
+ "types": "./dist/plugin.d.ts"
12
+ }
13
+ },
14
+ "openclaw": {
15
+ "extensions": [
16
+ "./dist/plugin.js"
17
+ ]
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "openclaw.plugin.json"
22
+ ],
23
+ "dependencies": {
24
+ "@alfe.ai/config": "^0.0.5",
25
+ "@alfe.ai/agent-api-client": "^0.0.3"
26
+ },
27
+ "peerDependencies": {
28
+ "openclaw": ">=2026.3.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "openclaw": {
32
+ "optional": true
33
+ }
34
+ },
35
+ "license": "UNLICENSED",
36
+ "scripts": {
37
+ "build": "tsdown",
38
+ "dev": "tsdown --watch",
39
+ "test": "vitest run --passWithNoTests",
40
+ "test:watch": "vitest",
41
+ "typecheck": "tsc --noEmit",
42
+ "lint": "eslint ."
43
+ }
44
+ }