@alfe.ai/openclaw-whatsapp 0.0.1 → 0.0.3

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 plugin from "./plugin.js";
2
+ export { plugin as default };
package/dist/index.js CHANGED
@@ -1,111 +1,2 @@
1
- import { Type } from "@sinclair/typebox";
2
- //#region src/plugin.ts
3
- /**
4
- * @alfe/openclaw-whatsapp — OpenClaw native plugin
5
- *
6
- * Registers WhatsApp tools with OpenClaw. Tools call the Twilio service
7
- * API using the agent's API key for authentication.
8
- *
9
- * This plugin provides:
10
- * - whatsapp_send_message — send a WhatsApp message from the agent's phone number
11
- */
12
- function ok(data) {
13
- return {
14
- content: [{
15
- type: "text",
16
- text: JSON.stringify(data)
17
- }],
18
- details: data
19
- };
20
- }
21
- function errResult(message) {
22
- return {
23
- content: [{
24
- type: "text",
25
- text: JSON.stringify({ error: message })
26
- }],
27
- details: { error: message }
28
- };
29
- }
30
- function defineTool(def) {
31
- return {
32
- name: def.name,
33
- description: def.description,
34
- label: def.name,
35
- parameters: def.parameters,
36
- execute: async (_toolCallId, params) => {
37
- try {
38
- return ok(await def.handler(params));
39
- } catch (e) {
40
- return errResult(e.message);
41
- }
42
- }
43
- };
44
- }
45
- let apiUrl = "";
46
- let apiKey = "";
47
- async function whatsappApi(method, path, body) {
48
- const url = `${apiUrl}${path}`;
49
- const headers = {
50
- "Content-Type": "application/json",
51
- Authorization: `Bearer ${apiKey}`
52
- };
53
- const res = await fetch(url, {
54
- method,
55
- headers,
56
- body: body ? JSON.stringify(body) : void 0
57
- });
58
- const json = await res.json();
59
- if (!res.ok) {
60
- const errorMsg = typeof json.error === "string" ? json.error : typeof json.message === "string" ? json.message : `WhatsApp service returned ${String(res.status)}`;
61
- throw new Error(errorMsg);
62
- }
63
- if (json.data && typeof json.data === "object") return json.data;
64
- return json;
65
- }
66
- const whatsappTools = [defineTool({
67
- name: "whatsapp_send_message",
68
- description: "Send a WhatsApp message from your phone number to the specified number. The recipient number must be in E.164 format (e.g., +12025551234). Note: the recipient must have messaged you within the last 24 hours, or the message will fail (WhatsApp session window policy).",
69
- parameters: Type.Object({
70
- to: Type.String({ description: "Recipient phone number in E.164 format (e.g., +12025551234)" }),
71
- body: Type.String({ description: "The message content to send" })
72
- }),
73
- handler: async (params) => {
74
- const { to, body } = params;
75
- return whatsappApi("POST", "/twilio/whatsapp/send", {
76
- to,
77
- body
78
- });
79
- }
80
- })];
81
- const plugin = {
82
- id: "@alfe.ai/openclaw-whatsapp",
83
- name: "Alfe WhatsApp Plugin",
84
- description: "WhatsApp integration — outbound messaging via Twilio",
85
- version: "0.0.1",
86
- activate(api) {
87
- if (globalThis.__whatsappPluginActivated) {
88
- api.logger.debug("Alfe WhatsApp plugin already activated, skipping re-init");
89
- return;
90
- }
91
- globalThis.__whatsappPluginActivated = true;
92
- const log = api.logger;
93
- log.info("Alfe WhatsApp plugin activating...");
94
- apiUrl = ((api.config ?? {}).plugins?.entries?.["@alfe.ai/openclaw-whatsapp"]?.config ?? {}).apiUrl ?? process.env.API_URL ?? "";
95
- apiKey = process.env.ALFE_API_KEY ?? "";
96
- if (!apiUrl) log.warn("No API_URL configured — WhatsApp tools will fail");
97
- if (!apiKey) log.warn("No ALFE_API_KEY configured — WhatsApp tools will fail");
98
- log.info(`WhatsApp API: ${apiUrl}`);
99
- for (const tool of whatsappTools) api.registerTool(tool);
100
- log.info(`Registered ${String(whatsappTools.length)} WhatsApp tools: ${whatsappTools.map((t) => t.name).join(", ")}`);
101
- log.info("Alfe WhatsApp plugin activated");
102
- },
103
- deactivate(api) {
104
- globalThis.__whatsappPluginActivated = false;
105
- api.logger.info("Alfe WhatsApp plugin deactivated");
106
- }
107
- };
108
- //#endregion
1
+ import plugin from "./plugin.js";
109
2
  export { plugin as default };
110
-
111
- //# sourceMappingURL=index.js.map
@@ -2,20 +2,6 @@ import { TSchema } from "@sinclair/typebox";
2
2
 
3
3
  //#region src/plugin.d.ts
4
4
 
5
- interface WhatsAppPluginConfig {
6
- apiUrl?: string;
7
- [key: string]: unknown;
8
- }
9
- interface OpenClawConfig {
10
- plugins?: {
11
- entries?: Record<string, {
12
- config?: WhatsAppPluginConfig;
13
- [key: string]: unknown;
14
- }>;
15
- [key: string]: unknown;
16
- };
17
- [key: string]: unknown;
18
- }
19
5
  interface Logger {
20
6
  info(msg: string, ...args: unknown[]): void;
21
7
  warn(msg: string, ...args: unknown[]): void;
@@ -24,7 +10,6 @@ interface Logger {
24
10
  }
25
11
  interface OpenClawPluginApi {
26
12
  logger: Logger;
27
- config?: OpenClawConfig;
28
13
  registerTool(tool: ToolDef): void;
29
14
  registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
30
15
  on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: {
@@ -49,9 +34,9 @@ declare const plugin: {
49
34
  name: string;
50
35
  description: string;
51
36
  version: string;
52
- activate(api: OpenClawPluginApi): void;
37
+ activate(api: OpenClawPluginApi): Promise<void>;
53
38
  deactivate(api: OpenClawPluginApi): void;
54
39
  };
55
40
  //#endregion
56
41
  export { plugin as default };
57
- //# sourceMappingURL=index-CRcEAuLY.d.ts.map
42
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;UAaU,MAAA,CAWyD;EAKzD,IAAA,CAAA,GAAA,EAAO,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;EAAA,IAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAIH,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAC0B,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;;UAd9B,iBAAA,CAciE;EAkGrE,MAAA,EA/GI,MAwJT;EAAA,YAAA,CAAA,IAAA,EAvJoB,OAuJpB,CAAA,EAAA,IAAA;uBAnCqB,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAnHiD,OAmHjD,CAAA,OAAA,CAAA,CAAA,EAAA,IAAA;KAAiB,KAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA,GAlHqB,OAkHrB,CAAA,IAAA,CAAA,EAAA,OA+BJ,CA/BI,EAAA;IA+BrB,QAAA,CAAA,EAAA,MAAA;EAAiB,CAAA,CAAA,EAAA,IAAA;;UA5IzB,OAAA;;;;cAII;wCAC0B,4BAA4B;;;;;;;;cAkG9D;;;;;gBAMgB,oBAAiB;kBA+BrB"}
package/dist/plugin.js ADDED
@@ -0,0 +1,116 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { resolveConfig } from "@alfe.ai/config";
3
+ //#region src/plugin.ts
4
+ /**
5
+ * @alfe/openclaw-whatsapp — OpenClaw native plugin
6
+ *
7
+ * Registers WhatsApp tools with OpenClaw. Tools call the Twilio service
8
+ * API using the agent's API key for authentication.
9
+ *
10
+ * This plugin provides:
11
+ * - whatsapp_send_message — send a WhatsApp message from the agent's phone number
12
+ */
13
+ function ok(data) {
14
+ return {
15
+ content: [{
16
+ type: "text",
17
+ text: JSON.stringify(data)
18
+ }],
19
+ details: data
20
+ };
21
+ }
22
+ function errResult(message) {
23
+ return {
24
+ content: [{
25
+ type: "text",
26
+ text: JSON.stringify({ error: message })
27
+ }],
28
+ details: { error: message }
29
+ };
30
+ }
31
+ function defineTool(def) {
32
+ return {
33
+ name: def.name,
34
+ description: def.description,
35
+ label: def.name,
36
+ parameters: def.parameters,
37
+ execute: async (_toolCallId, params) => {
38
+ try {
39
+ return ok(await def.handler(params));
40
+ } catch (e) {
41
+ return errResult(e.message);
42
+ }
43
+ }
44
+ };
45
+ }
46
+ let apiUrl = "";
47
+ let apiKey = "";
48
+ async function whatsappApi(method, path, body) {
49
+ const url = `${apiUrl}${path}`;
50
+ const headers = {
51
+ "Content-Type": "application/json",
52
+ Authorization: `Bearer ${apiKey}`
53
+ };
54
+ const res = await fetch(url, {
55
+ method,
56
+ headers,
57
+ body: body ? JSON.stringify(body) : void 0
58
+ });
59
+ const json = await res.json();
60
+ if (!res.ok) {
61
+ const errorMsg = typeof json.error === "string" ? json.error : typeof json.message === "string" ? json.message : `WhatsApp service returned ${String(res.status)}`;
62
+ throw new Error(errorMsg);
63
+ }
64
+ if (json.data && typeof json.data === "object") return json.data;
65
+ return json;
66
+ }
67
+ const whatsappTools = [defineTool({
68
+ name: "whatsapp_send_message",
69
+ description: "Send a WhatsApp message from your phone number to the specified number. The recipient number must be in E.164 format (e.g., +12025551234). Note: the recipient must have messaged you within the last 24 hours, or the message will fail (WhatsApp session window policy).",
70
+ parameters: Type.Object({
71
+ to: Type.String({ description: "Recipient phone number in E.164 format (e.g., +12025551234)" }),
72
+ body: Type.String({ description: "The message content to send" })
73
+ }),
74
+ handler: async (params) => {
75
+ const { to, body } = params;
76
+ return whatsappApi("POST", "/twilio/whatsapp/send", {
77
+ to,
78
+ body
79
+ });
80
+ }
81
+ })];
82
+ const plugin = {
83
+ id: "@alfe.ai/openclaw-whatsapp",
84
+ name: "Alfe WhatsApp Plugin",
85
+ description: "WhatsApp integration — outbound messaging via Twilio",
86
+ version: "0.0.1",
87
+ async activate(api) {
88
+ if (globalThis.__whatsappPluginActivated) {
89
+ api.logger.debug("Alfe WhatsApp plugin already activated, skipping re-init");
90
+ return;
91
+ }
92
+ globalThis.__whatsappPluginActivated = true;
93
+ const log = api.logger;
94
+ log.info("Alfe WhatsApp plugin activating...");
95
+ try {
96
+ const config = await resolveConfig();
97
+ apiUrl = config.apiUrl;
98
+ apiKey = config.apiKey;
99
+ } catch (err) {
100
+ log.error(`Failed to resolve config: ${err instanceof Error ? err.message : String(err)}`);
101
+ log.warn("WhatsApp tools will fail — no API config available");
102
+ }
103
+ log.info(`WhatsApp API: ${apiUrl}`);
104
+ for (const tool of whatsappTools) api.registerTool(tool);
105
+ log.info(`Registered ${String(whatsappTools.length)} WhatsApp tools: ${whatsappTools.map((t) => t.name).join(", ")}`);
106
+ log.info("Alfe WhatsApp plugin activated");
107
+ },
108
+ deactivate(api) {
109
+ globalThis.__whatsappPluginActivated = false;
110
+ api.logger.info("Alfe WhatsApp plugin deactivated");
111
+ }
112
+ };
113
+ //#endregion
114
+ export { plugin as default };
115
+
116
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["/**\n * @alfe/openclaw-whatsapp — OpenClaw native plugin\n *\n * Registers WhatsApp tools with OpenClaw. Tools call the Twilio service\n * API using the agent's API key for authentication.\n *\n * This plugin provides:\n * - whatsapp_send_message — send a WhatsApp message from the agent's phone number\n */\n\nimport { Type, type TSchema } from \"@sinclair/typebox\";\nimport { resolveConfig } from \"@alfe.ai/config\";\n\ninterface Logger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug(msg: string, ...args: unknown[]): void;\n}\n\ninterface OpenClawPluginApi {\n logger: Logger;\n registerTool(tool: ToolDef): void;\n registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: { priority?: number }): void;\n}\n\n// ── Tool types ───────────────────────────────────────────────\n\ninterface ToolDef {\n name: string;\n description: string;\n label: string;\n parameters: TSchema;\n execute: (toolCallId: string, params: Record<string, unknown>) => Promise<{\n content: { type: \"text\"; text: string }[];\n details: unknown;\n }>;\n}\n\nfunction ok(data: unknown) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(data) }], details: data };\n}\n\nfunction errResult(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], details: { error: message } };\n}\n\nfunction defineTool(def: {\n name: string;\n description: string;\n parameters: TSchema;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n}): ToolDef {\n return {\n name: def.name,\n description: def.description,\n label: def.name,\n parameters: def.parameters,\n execute: async (_toolCallId: string, params: Record<string, unknown>) => {\n try {\n const result = await def.handler(params);\n return ok(result);\n } catch (e) {\n return errResult((e as Error).message);\n }\n },\n };\n}\n\n// ── API client ───────────────────────────────────────────────\n\nlet apiUrl = \"\";\nlet apiKey = \"\";\n\nasync function whatsappApi(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const url = `${apiUrl}${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n };\n\n const res = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n const json = (await res.json()) as Record<string, unknown>;\n if (!res.ok) {\n const errorMsg = typeof json.error === \"string\"\n ? json.error\n : typeof json.message === \"string\"\n ? json.message\n : `WhatsApp service returned ${String(res.status)}`;\n throw new Error(errorMsg);\n }\n\n // unwrap { data: ... } envelope if present\n if (json.data && typeof json.data === \"object\") {\n return json.data as Record<string, unknown>;\n }\n return json;\n}\n\n// ── Tool definitions ─────────────────────────────────────────\n\nconst whatsappTools: ToolDef[] = [\n defineTool({\n name: \"whatsapp_send_message\",\n description:\n \"Send a WhatsApp message from your phone number to the specified number. \" +\n \"The recipient number must be in E.164 format (e.g., +12025551234). \" +\n \"Note: the recipient must have messaged you within the last 24 hours, \" +\n \"or the message will fail (WhatsApp session window policy).\",\n parameters: Type.Object({\n to: Type.String({ description: \"Recipient phone number in E.164 format (e.g., +12025551234)\" }),\n body: Type.String({ description: \"The message content to send\" }),\n }),\n handler: async (params) => {\n const { to, body } = params as { to: string; body: string };\n return whatsappApi(\"POST\", \"/twilio/whatsapp/send\", { to, body });\n },\n }),\n];\n\n// ── Plugin definition ────────────────────────────────────────\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-whatsapp\",\n name: \"Alfe WhatsApp Plugin\",\n description: \"WhatsApp integration — outbound messaging via Twilio\",\n version: \"0.0.1\",\n\n async activate(api: OpenClawPluginApi) {\n if ((globalThis as Record<string, unknown>).__whatsappPluginActivated) {\n api.logger.debug(\"Alfe WhatsApp plugin already activated, skipping re-init\");\n return;\n }\n (globalThis as Record<string, unknown>).__whatsappPluginActivated = true;\n\n const log = api.logger;\n log.info(\"Alfe WhatsApp plugin activating...\");\n\n // Resolve API URL and key from centralized config (~/.alfe/config.toml)\n try {\n const config = await resolveConfig();\n apiUrl = config.apiUrl;\n apiKey = config.apiKey;\n } catch (err) {\n log.error(`Failed to resolve config: ${err instanceof Error ? err.message : String(err)}`);\n log.warn(\"WhatsApp tools will fail — no API config available\");\n }\n\n log.info(`WhatsApp API: ${apiUrl}`);\n\n // Register tools\n for (const tool of whatsappTools) {\n api.registerTool(tool);\n }\n log.info(`Registered ${String(whatsappTools.length)} WhatsApp tools: ${whatsappTools.map((t) => t.name).join(\", \")}`);\n\n log.info(\"Alfe WhatsApp plugin activated\");\n },\n\n deactivate(api: OpenClawPluginApi) {\n (globalThis as Record<string, unknown>).__whatsappPluginActivated = false;\n api.logger.info(\"Alfe WhatsApp plugin deactivated\");\n },\n};\n\nexport default plugin;\n"],"mappings":";;;;;;;;;;;;AAwCA,SAAS,GAAG,MAAe;AACzB,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,KAAK;GAAE,CAAC;EAAE,SAAS;EAAM;;AAG5F,SAAS,UAAU,SAAiB;AAClC,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;GAAE,CAAC;EAAE,SAAS,EAAE,OAAO,SAAS;EAAE;;AAGxH,SAAS,WAAW,KAKR;AACV,QAAO;EACL,MAAM,IAAI;EACV,aAAa,IAAI;EACjB,OAAO,IAAI;EACX,YAAY,IAAI;EAChB,SAAS,OAAO,aAAqB,WAAoC;AACvE,OAAI;AAEF,WAAO,GADQ,MAAM,IAAI,QAAQ,OAAO,CACvB;YACV,GAAG;AACV,WAAO,UAAW,EAAY,QAAQ;;;EAG3C;;AAKH,IAAI,SAAS;AACb,IAAI,SAAS;AAEb,eAAe,YACb,QACA,MACA,MACkC;CAClC,MAAM,MAAM,GAAG,SAAS;CACxB,MAAM,UAAkC;EACtC,gBAAgB;EAChB,eAAe,UAAU;EAC1B;CAED,MAAM,MAAM,MAAM,MAAM,KAAK;EAC3B;EACA;EACA,MAAM,OAAO,KAAK,UAAU,KAAK,GAAG,KAAA;EACrC,CAAC;CAEF,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,KAAI,CAAC,IAAI,IAAI;EACX,MAAM,WAAW,OAAO,KAAK,UAAU,WACnC,KAAK,QACL,OAAO,KAAK,YAAY,WACtB,KAAK,UACL,6BAA6B,OAAO,IAAI,OAAO;AACrD,QAAM,IAAI,MAAM,SAAS;;AAI3B,KAAI,KAAK,QAAQ,OAAO,KAAK,SAAS,SACpC,QAAO,KAAK;AAEd,QAAO;;AAKT,MAAM,gBAA2B,CAC/B,WAAW;CACT,MAAM;CACN,aACE;CAIF,YAAY,KAAK,OAAO;EACtB,IAAI,KAAK,OAAO,EAAE,aAAa,+DAA+D,CAAC;EAC/F,MAAM,KAAK,OAAO,EAAE,aAAa,+BAA+B,CAAC;EAClE,CAAC;CACF,SAAS,OAAO,WAAW;EACzB,MAAM,EAAE,IAAI,SAAS;AACrB,SAAO,YAAY,QAAQ,yBAAyB;GAAE;GAAI;GAAM,CAAC;;CAEpE,CAAC,CACH;AAID,MAAM,SAAS;CACb,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CAET,MAAM,SAAS,KAAwB;AACrC,MAAK,WAAuC,2BAA2B;AACrE,OAAI,OAAO,MAAM,2DAA2D;AAC5E;;AAED,aAAuC,4BAA4B;EAEpE,MAAM,MAAM,IAAI;AAChB,MAAI,KAAK,qCAAqC;AAG9C,MAAI;GACF,MAAM,SAAS,MAAM,eAAe;AACpC,YAAS,OAAO;AAChB,YAAS,OAAO;WACT,KAAK;AACZ,OAAI,MAAM,6BAA6B,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC1F,OAAI,KAAK,qDAAqD;;AAGhE,MAAI,KAAK,iBAAiB,SAAS;AAGnC,OAAK,MAAM,QAAQ,cACjB,KAAI,aAAa,KAAK;AAExB,MAAI,KAAK,cAAc,OAAO,cAAc,OAAO,CAAC,mBAAmB,cAAc,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,GAAG;AAErH,MAAI,KAAK,iCAAiC;;CAG5C,WAAW,KAAwB;AAChC,aAAuC,4BAA4B;AACpE,MAAI,OAAO,KAAK,mCAAmC;;CAEtD"}
@@ -0,0 +1,7 @@
1
+ {
2
+ "id": "@alfe.ai/openclaw-whatsapp",
3
+ "name": "WhatsApp",
4
+ "version": "0.0.2",
5
+ "description": "Outbound WhatsApp messaging via Twilio",
6
+ "entry": "./dist/plugin.js"
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/openclaw-whatsapp",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "OpenClaw WhatsApp plugin for Alfe — outbound WhatsApp messaging via Twilio",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,6 +9,10 @@
9
9
  ".": {
10
10
  "import": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts"
12
+ },
13
+ "./plugin": {
14
+ "import": "./dist/plugin.js",
15
+ "types": "./dist/plugin.d.ts"
12
16
  }
13
17
  },
14
18
  "openclaw": {
@@ -17,10 +21,12 @@
17
21
  ]
18
22
  },
19
23
  "files": [
20
- "dist"
24
+ "dist",
25
+ "openclaw.plugin.json"
21
26
  ],
22
27
  "dependencies": {
23
- "@sinclair/typebox": "^0.34.48"
28
+ "@sinclair/typebox": "^0.34.48",
29
+ "@alfe.ai/config": "0.0.5"
24
30
  },
25
31
  "scripts": {
26
32
  "build": "tsdown",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-CRcEAuLY.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;AA2BgB,UAbN,oBAAA,CAoBiB;EAAA,MAAA,CAAA,EAAA,MAAA;MACjB,EAAA,MAAA,CAAA,EAAA,OAAA;;UAhBA,cAAA,CAkBW;SACkD,CAAA,EAAA;IACX,OAAA,CAAA,EAlB9C,MAkB8C,CAAA,MAAA,EAAA;MAAO,MAAA,CAAA,EAlB3B,oBAkB2B;MAKzD,CAAA,GAAO,EAAA,MAAA,CAAA,EAAA,OAAA;IAAA,CAAA,CAAA;IAIH,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;MACsD,EAAA,MAAA,CAAA,EAAA,OAAA;;AAAO,UAtBjE,MAAA,CAyKT;EAAA,IAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;MA3Ce,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;OAuCE,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;EAAiB,KAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;;UA9JzB,iBAAA;UACA;WACC;qBACU;uEACkD;4DACX;;;;UAKlD,OAAA;;;;cAII;wCAC0B,4BAA4B;;;;;;;;cAkG9D;;;;;gBAMU;kBAuCE"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["/**\n * @alfe/openclaw-whatsapp — OpenClaw native plugin\n *\n * Registers WhatsApp tools with OpenClaw. Tools call the Twilio service\n * API using the agent's API key for authentication.\n *\n * This plugin provides:\n * - whatsapp_send_message — send a WhatsApp message from the agent's phone number\n */\n\nimport { Type, type TSchema } from \"@sinclair/typebox\";\n\n// ── Plugin config ────────────────────────────────────────────\n\ninterface WhatsAppPluginConfig {\n apiUrl?: string;\n [key: string]: unknown;\n}\n\ninterface OpenClawConfig {\n plugins?: {\n entries?: Record<string, { config?: WhatsAppPluginConfig; [key: string]: unknown }>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\ninterface Logger {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug(msg: string, ...args: unknown[]): void;\n}\n\ninterface OpenClawPluginApi {\n logger: Logger;\n config?: OpenClawConfig;\n registerTool(tool: ToolDef): void;\n registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;\n on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: { priority?: number }): void;\n}\n\n// ── Tool types ───────────────────────────────────────────────\n\ninterface ToolDef {\n name: string;\n description: string;\n label: string;\n parameters: TSchema;\n execute: (toolCallId: string, params: Record<string, unknown>) => Promise<{\n content: { type: \"text\"; text: string }[];\n details: unknown;\n }>;\n}\n\nfunction ok(data: unknown) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(data) }], details: data };\n}\n\nfunction errResult(message: string) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }], details: { error: message } };\n}\n\nfunction defineTool(def: {\n name: string;\n description: string;\n parameters: TSchema;\n handler: (params: Record<string, unknown>) => Promise<unknown>;\n}): ToolDef {\n return {\n name: def.name,\n description: def.description,\n label: def.name,\n parameters: def.parameters,\n execute: async (_toolCallId: string, params: Record<string, unknown>) => {\n try {\n const result = await def.handler(params);\n return ok(result);\n } catch (e) {\n return errResult((e as Error).message);\n }\n },\n };\n}\n\n// ── API client ───────────────────────────────────────────────\n\nlet apiUrl = \"\";\nlet apiKey = \"\";\n\nasync function whatsappApi(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const url = `${apiUrl}${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n };\n\n const res = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n const json = (await res.json()) as Record<string, unknown>;\n if (!res.ok) {\n const errorMsg = typeof json.error === \"string\"\n ? json.error\n : typeof json.message === \"string\"\n ? json.message\n : `WhatsApp service returned ${String(res.status)}`;\n throw new Error(errorMsg);\n }\n\n // unwrap { data: ... } envelope if present\n if (json.data && typeof json.data === \"object\") {\n return json.data as Record<string, unknown>;\n }\n return json;\n}\n\n// ── Tool definitions ─────────────────────────────────────────\n\nconst whatsappTools: ToolDef[] = [\n defineTool({\n name: \"whatsapp_send_message\",\n description:\n \"Send a WhatsApp message from your phone number to the specified number. \" +\n \"The recipient number must be in E.164 format (e.g., +12025551234). \" +\n \"Note: the recipient must have messaged you within the last 24 hours, \" +\n \"or the message will fail (WhatsApp session window policy).\",\n parameters: Type.Object({\n to: Type.String({ description: \"Recipient phone number in E.164 format (e.g., +12025551234)\" }),\n body: Type.String({ description: \"The message content to send\" }),\n }),\n handler: async (params) => {\n const { to, body } = params as { to: string; body: string };\n return whatsappApi(\"POST\", \"/twilio/whatsapp/send\", { to, body });\n },\n }),\n];\n\n// ── Plugin definition ────────────────────────────────────────\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-whatsapp\",\n name: \"Alfe WhatsApp Plugin\",\n description: \"WhatsApp integration — outbound messaging via Twilio\",\n version: \"0.0.1\",\n\n activate(api: OpenClawPluginApi) {\n if ((globalThis as Record<string, unknown>).__whatsappPluginActivated) {\n api.logger.debug(\"Alfe WhatsApp plugin already activated, skipping re-init\");\n return;\n }\n (globalThis as Record<string, unknown>).__whatsappPluginActivated = true;\n\n const log = api.logger;\n log.info(\"Alfe WhatsApp plugin activating...\");\n\n // Resolve API URL from plugin config or environment\n const fullConfig = api.config ?? {};\n const pluginConfig: WhatsAppPluginConfig =\n fullConfig.plugins?.entries?.[\"@alfe.ai/openclaw-whatsapp\"]?.config ?? {};\n\n apiUrl = pluginConfig.apiUrl\n ?? process.env.API_URL\n ?? \"\";\n\n apiKey = process.env.ALFE_API_KEY ?? \"\";\n\n if (!apiUrl) {\n log.warn(\"No API_URL configured — WhatsApp tools will fail\");\n }\n if (!apiKey) {\n log.warn(\"No ALFE_API_KEY configured — WhatsApp tools will fail\");\n }\n\n log.info(`WhatsApp API: ${apiUrl}`);\n\n // Register tools\n for (const tool of whatsappTools) {\n api.registerTool(tool);\n }\n log.info(`Registered ${String(whatsappTools.length)} WhatsApp tools: ${whatsappTools.map((t) => t.name).join(\", \")}`);\n\n log.info(\"Alfe WhatsApp plugin activated\");\n },\n\n deactivate(api: OpenClawPluginApi) {\n (globalThis as Record<string, unknown>).__whatsappPluginActivated = false;\n api.logger.info(\"Alfe WhatsApp plugin deactivated\");\n },\n};\n\nexport default plugin;\n"],"mappings":";;;;;;;;;;;AAuDA,SAAS,GAAG,MAAe;AACzB,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,KAAK;GAAE,CAAC;EAAE,SAAS;EAAM;;AAG5F,SAAS,UAAU,SAAiB;AAClC,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;GAAE,CAAC;EAAE,SAAS,EAAE,OAAO,SAAS;EAAE;;AAGxH,SAAS,WAAW,KAKR;AACV,QAAO;EACL,MAAM,IAAI;EACV,aAAa,IAAI;EACjB,OAAO,IAAI;EACX,YAAY,IAAI;EAChB,SAAS,OAAO,aAAqB,WAAoC;AACvE,OAAI;AAEF,WAAO,GADQ,MAAM,IAAI,QAAQ,OAAO,CACvB;YACV,GAAG;AACV,WAAO,UAAW,EAAY,QAAQ;;;EAG3C;;AAKH,IAAI,SAAS;AACb,IAAI,SAAS;AAEb,eAAe,YACb,QACA,MACA,MACkC;CAClC,MAAM,MAAM,GAAG,SAAS;CACxB,MAAM,UAAkC;EACtC,gBAAgB;EAChB,eAAe,UAAU;EAC1B;CAED,MAAM,MAAM,MAAM,MAAM,KAAK;EAC3B;EACA;EACA,MAAM,OAAO,KAAK,UAAU,KAAK,GAAG,KAAA;EACrC,CAAC;CAEF,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,KAAI,CAAC,IAAI,IAAI;EACX,MAAM,WAAW,OAAO,KAAK,UAAU,WACnC,KAAK,QACL,OAAO,KAAK,YAAY,WACtB,KAAK,UACL,6BAA6B,OAAO,IAAI,OAAO;AACrD,QAAM,IAAI,MAAM,SAAS;;AAI3B,KAAI,KAAK,QAAQ,OAAO,KAAK,SAAS,SACpC,QAAO,KAAK;AAEd,QAAO;;AAKT,MAAM,gBAA2B,CAC/B,WAAW;CACT,MAAM;CACN,aACE;CAIF,YAAY,KAAK,OAAO;EACtB,IAAI,KAAK,OAAO,EAAE,aAAa,+DAA+D,CAAC;EAC/F,MAAM,KAAK,OAAO,EAAE,aAAa,+BAA+B,CAAC;EAClE,CAAC;CACF,SAAS,OAAO,WAAW;EACzB,MAAM,EAAE,IAAI,SAAS;AACrB,SAAO,YAAY,QAAQ,yBAAyB;GAAE;GAAI;GAAM,CAAC;;CAEpE,CAAC,CACH;AAID,MAAM,SAAS;CACb,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CAET,SAAS,KAAwB;AAC/B,MAAK,WAAuC,2BAA2B;AACrE,OAAI,OAAO,MAAM,2DAA2D;AAC5E;;AAED,aAAuC,4BAA4B;EAEpE,MAAM,MAAM,IAAI;AAChB,MAAI,KAAK,qCAAqC;AAO9C,aAJmB,IAAI,UAAU,EAAE,EAEtB,SAAS,UAAU,+BAA+B,UAAU,EAAE,EAErD,UACjB,QAAQ,IAAI,WACZ;AAEL,WAAS,QAAQ,IAAI,gBAAgB;AAErC,MAAI,CAAC,OACH,KAAI,KAAK,mDAAmD;AAE9D,MAAI,CAAC,OACH,KAAI,KAAK,wDAAwD;AAGnE,MAAI,KAAK,iBAAiB,SAAS;AAGnC,OAAK,MAAM,QAAQ,cACjB,KAAI,aAAa,KAAK;AAExB,MAAI,KAAK,cAAc,OAAO,cAAc,OAAO,CAAC,mBAAmB,cAAc,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,GAAG;AAErH,MAAI,KAAK,iCAAiC;;CAG5C,WAAW,KAAwB;AAChC,aAAuC,4BAA4B;AACpE,MAAI,OAAO,KAAK,mCAAmC;;CAEtD"}