@alfe.ai/openclaw-mobile 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.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -119
- package/dist/{index-c8Vhfjeg.d.ts → plugin.d.ts} +2 -17
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +125 -0
- package/dist/plugin.js.map +1 -0
- package/openclaw.plugin.json +7 -0
- package/package.json +9 -3
- package/dist/index-c8Vhfjeg.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.d.ts
ADDED
package/dist/index.js
CHANGED
|
@@ -1,120 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
//#region src/plugin.ts
|
|
3
|
-
/**
|
|
4
|
-
* @alfe/openclaw-mobile — OpenClaw native plugin
|
|
5
|
-
*
|
|
6
|
-
* Registers mobile tools (SMS, calls) with OpenClaw. Tools call the
|
|
7
|
-
* mobile service API using the agent's API key for authentication.
|
|
8
|
-
*
|
|
9
|
-
* This plugin provides:
|
|
10
|
-
* - mobile_send_sms — send an SMS message from the agent's phone number
|
|
11
|
-
* - mobile_call — initiate an outbound phone call
|
|
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 mobileApi(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 : `Mobile 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 mobileTools = [defineTool({
|
|
68
|
-
name: "mobile_send_sms",
|
|
69
|
-
description: "Send an SMS text message from your phone number to the specified number. The recipient number must be in E.164 format (e.g., +12025551234).",
|
|
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 text message content to send" })
|
|
73
|
-
}),
|
|
74
|
-
handler: async (params) => {
|
|
75
|
-
const { to, body } = params;
|
|
76
|
-
return mobileApi("POST", "/mobile/sms/send", {
|
|
77
|
-
to,
|
|
78
|
-
body
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}), defineTool({
|
|
82
|
-
name: "mobile_call",
|
|
83
|
-
description: "Make an outbound phone call to the specified number. When the recipient answers, they will be connected to your voice pipeline. The number must be in E.164 format (e.g., +12025551234).",
|
|
84
|
-
parameters: Type.Object({ to: Type.String({ description: "Phone number to call in E.164 format (e.g., +12025551234)" }) }),
|
|
85
|
-
handler: async (params) => {
|
|
86
|
-
const { to } = params;
|
|
87
|
-
return mobileApi("POST", "/mobile/calls/outbound", { to });
|
|
88
|
-
}
|
|
89
|
-
})];
|
|
90
|
-
const plugin = {
|
|
91
|
-
id: "@alfe.ai/openclaw-mobile",
|
|
92
|
-
name: "Alfe Mobile Plugin",
|
|
93
|
-
description: "Mobile integration — outbound SMS and phone calls via Twilio",
|
|
94
|
-
version: "0.0.1",
|
|
95
|
-
activate(api) {
|
|
96
|
-
if (globalThis.__mobilePluginActivated) {
|
|
97
|
-
api.logger.debug("Alfe Mobile plugin already activated, skipping re-init");
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
globalThis.__mobilePluginActivated = true;
|
|
101
|
-
const log = api.logger;
|
|
102
|
-
log.info("Alfe Mobile plugin activating...");
|
|
103
|
-
apiUrl = ((api.config ?? {}).plugins?.entries?.["@alfe.ai/openclaw-mobile"]?.config ?? {}).apiUrl ?? process.env.API_URL ?? "";
|
|
104
|
-
apiKey = process.env.ALFE_API_KEY ?? "";
|
|
105
|
-
if (!apiUrl) log.warn("No API_URL configured — mobile tools will fail");
|
|
106
|
-
if (!apiKey) log.warn("No ALFE_API_KEY configured — mobile tools will fail");
|
|
107
|
-
log.info(`Mobile API: ${apiUrl}`);
|
|
108
|
-
for (const tool of mobileTools) api.registerTool(tool);
|
|
109
|
-
log.info(`Registered ${String(mobileTools.length)} mobile tools: ${mobileTools.map((t) => t.name).join(", ")}`);
|
|
110
|
-
log.info("Alfe Mobile plugin activated");
|
|
111
|
-
},
|
|
112
|
-
deactivate(api) {
|
|
113
|
-
globalThis.__mobilePluginActivated = false;
|
|
114
|
-
api.logger.info("Alfe Mobile plugin deactivated");
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
//#endregion
|
|
1
|
+
import plugin from "./plugin.js";
|
|
118
2
|
export { plugin as default };
|
|
119
|
-
|
|
120
|
-
//# 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 MobilePluginConfig {
|
|
6
|
-
apiUrl?: string;
|
|
7
|
-
[key: string]: unknown;
|
|
8
|
-
}
|
|
9
|
-
interface OpenClawConfig {
|
|
10
|
-
plugins?: {
|
|
11
|
-
entries?: Record<string, {
|
|
12
|
-
config?: MobilePluginConfig;
|
|
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=
|
|
42
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;AAyBmE,UAXzD,MAAA,CAgBO;EAAA,IAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;MAIH,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;OAA4B,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;;AAAO,UAdjE,iBAAA,CAsKT;EAAA,MAAA,EArKS,MAqKT;cAnCqB,CAAA,IAAA,EAjID,OAiIC,CAAA,EAAA,IAAA;uBAAiB,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAhIgC,OAgIhC,CAAA,OAAA,CAAA,CAAA,EAAA,IAAA;KA+BrB,KAAA,EAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA,GA9J0C,OA8J1C,CAAA,IAAA,CAAA,EAAA,QAAA,EAAA;IAAiB,QAAA,CAAA,EAAA,MAAA;;;UAzJzB,OAAA;;;;cAII;wCAC0B,4BAA4B;;;;;;;;cA+G9D;;;;;gBAMgB,oBAAiB;kBA+BrB"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { resolveConfig } from "@alfe.ai/config";
|
|
3
|
+
//#region src/plugin.ts
|
|
4
|
+
/**
|
|
5
|
+
* @alfe/openclaw-mobile — OpenClaw native plugin
|
|
6
|
+
*
|
|
7
|
+
* Registers mobile tools (SMS, calls) with OpenClaw. Tools call the
|
|
8
|
+
* mobile service API using the agent's API key for authentication.
|
|
9
|
+
*
|
|
10
|
+
* This plugin provides:
|
|
11
|
+
* - mobile_send_sms — send an SMS message from the agent's phone number
|
|
12
|
+
* - mobile_call — initiate an outbound phone call
|
|
13
|
+
*/
|
|
14
|
+
function ok(data) {
|
|
15
|
+
return {
|
|
16
|
+
content: [{
|
|
17
|
+
type: "text",
|
|
18
|
+
text: JSON.stringify(data)
|
|
19
|
+
}],
|
|
20
|
+
details: data
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function errResult(message) {
|
|
24
|
+
return {
|
|
25
|
+
content: [{
|
|
26
|
+
type: "text",
|
|
27
|
+
text: JSON.stringify({ error: message })
|
|
28
|
+
}],
|
|
29
|
+
details: { error: message }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function defineTool(def) {
|
|
33
|
+
return {
|
|
34
|
+
name: def.name,
|
|
35
|
+
description: def.description,
|
|
36
|
+
label: def.name,
|
|
37
|
+
parameters: def.parameters,
|
|
38
|
+
execute: async (_toolCallId, params) => {
|
|
39
|
+
try {
|
|
40
|
+
return ok(await def.handler(params));
|
|
41
|
+
} catch (e) {
|
|
42
|
+
return errResult(e.message);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
let apiUrl = "";
|
|
48
|
+
let apiKey = "";
|
|
49
|
+
async function mobileApi(method, path, body) {
|
|
50
|
+
const url = `${apiUrl}${path}`;
|
|
51
|
+
const headers = {
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
Authorization: `Bearer ${apiKey}`
|
|
54
|
+
};
|
|
55
|
+
const res = await fetch(url, {
|
|
56
|
+
method,
|
|
57
|
+
headers,
|
|
58
|
+
body: body ? JSON.stringify(body) : void 0
|
|
59
|
+
});
|
|
60
|
+
const json = await res.json();
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
const errorMsg = typeof json.error === "string" ? json.error : typeof json.message === "string" ? json.message : `Mobile service returned ${String(res.status)}`;
|
|
63
|
+
throw new Error(errorMsg);
|
|
64
|
+
}
|
|
65
|
+
if (json.data && typeof json.data === "object") return json.data;
|
|
66
|
+
return json;
|
|
67
|
+
}
|
|
68
|
+
const mobileTools = [defineTool({
|
|
69
|
+
name: "mobile_send_sms",
|
|
70
|
+
description: "Send an SMS text message from your phone number to the specified number. The recipient number must be in E.164 format (e.g., +12025551234).",
|
|
71
|
+
parameters: Type.Object({
|
|
72
|
+
to: Type.String({ description: "Recipient phone number in E.164 format (e.g., +12025551234)" }),
|
|
73
|
+
body: Type.String({ description: "The text message content to send" })
|
|
74
|
+
}),
|
|
75
|
+
handler: async (params) => {
|
|
76
|
+
const { to, body } = params;
|
|
77
|
+
return mobileApi("POST", "/twilio/sms/send", {
|
|
78
|
+
to,
|
|
79
|
+
body
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}), defineTool({
|
|
83
|
+
name: "mobile_call",
|
|
84
|
+
description: "Make an outbound phone call to the specified number. When the recipient answers, they will be connected to your voice pipeline. The number must be in E.164 format (e.g., +12025551234).",
|
|
85
|
+
parameters: Type.Object({ to: Type.String({ description: "Phone number to call in E.164 format (e.g., +12025551234)" }) }),
|
|
86
|
+
handler: async (params) => {
|
|
87
|
+
const { to } = params;
|
|
88
|
+
return mobileApi("POST", "/twilio/calls/outbound", { to });
|
|
89
|
+
}
|
|
90
|
+
})];
|
|
91
|
+
const plugin = {
|
|
92
|
+
id: "@alfe.ai/openclaw-mobile",
|
|
93
|
+
name: "Alfe Mobile Plugin",
|
|
94
|
+
description: "Mobile integration — outbound SMS and phone calls via Twilio",
|
|
95
|
+
version: "0.0.1",
|
|
96
|
+
async activate(api) {
|
|
97
|
+
if (globalThis.__mobilePluginActivated) {
|
|
98
|
+
api.logger.debug("Alfe Mobile plugin already activated, skipping re-init");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
globalThis.__mobilePluginActivated = true;
|
|
102
|
+
const log = api.logger;
|
|
103
|
+
log.info("Alfe Mobile plugin activating...");
|
|
104
|
+
try {
|
|
105
|
+
const config = await resolveConfig();
|
|
106
|
+
apiUrl = config.apiUrl;
|
|
107
|
+
apiKey = config.apiKey;
|
|
108
|
+
} catch (err) {
|
|
109
|
+
log.error(`Failed to resolve config: ${err instanceof Error ? err.message : String(err)}`);
|
|
110
|
+
log.warn("Mobile tools will fail — no API config available");
|
|
111
|
+
}
|
|
112
|
+
log.info(`Mobile API: ${apiUrl}`);
|
|
113
|
+
for (const tool of mobileTools) api.registerTool(tool);
|
|
114
|
+
log.info(`Registered ${String(mobileTools.length)} mobile tools: ${mobileTools.map((t) => t.name).join(", ")}`);
|
|
115
|
+
log.info("Alfe Mobile plugin activated");
|
|
116
|
+
},
|
|
117
|
+
deactivate(api) {
|
|
118
|
+
globalThis.__mobilePluginActivated = false;
|
|
119
|
+
api.logger.info("Alfe Mobile plugin deactivated");
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
//#endregion
|
|
123
|
+
export { plugin as default };
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["/**\n * @alfe/openclaw-mobile — OpenClaw native plugin\n *\n * Registers mobile tools (SMS, calls) with OpenClaw. Tools call the\n * mobile service API using the agent's API key for authentication.\n *\n * This plugin provides:\n * - mobile_send_sms — send an SMS message from the agent's phone number\n * - mobile_call — initiate an outbound phone call\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 mobileApi(\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 : `Mobile 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 mobileTools: ToolDef[] = [\n defineTool({\n name: \"mobile_send_sms\",\n description:\n \"Send an SMS text message from your phone number to the specified number. \" +\n \"The recipient number must be in E.164 format (e.g., +12025551234).\",\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 text message content to send\" }),\n }),\n handler: async (params) => {\n const { to, body } = params as { to: string; body: string };\n return mobileApi(\"POST\", \"/twilio/sms/send\", { to, body });\n },\n }),\n\n defineTool({\n name: \"mobile_call\",\n description:\n \"Make an outbound phone call to the specified number. \" +\n \"When the recipient answers, they will be connected to your voice pipeline. \" +\n \"The number must be in E.164 format (e.g., +12025551234).\",\n parameters: Type.Object({\n to: Type.String({ description: \"Phone number to call in E.164 format (e.g., +12025551234)\" }),\n }),\n handler: async (params) => {\n const { to } = params as { to: string };\n return mobileApi(\"POST\", \"/twilio/calls/outbound\", { to });\n },\n }),\n];\n\n// ── Plugin definition ────────────────────────────────────────\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-mobile\",\n name: \"Alfe Mobile Plugin\",\n description: \"Mobile integration — outbound SMS and phone calls via Twilio\",\n version: \"0.0.1\",\n\n async activate(api: OpenClawPluginApi) {\n if ((globalThis as Record<string, unknown>).__mobilePluginActivated) {\n api.logger.debug(\"Alfe Mobile plugin already activated, skipping re-init\");\n return;\n }\n (globalThis as Record<string, unknown>).__mobilePluginActivated = true;\n\n const log = api.logger;\n log.info(\"Alfe Mobile 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(\"Mobile tools will fail — no API config available\");\n }\n\n log.info(`Mobile API: ${apiUrl}`);\n\n // Register tools\n for (const tool of mobileTools) {\n api.registerTool(tool);\n }\n log.info(`Registered ${String(mobileTools.length)} mobile tools: ${mobileTools.map((t) => t.name).join(\", \")}`);\n\n log.info(\"Alfe Mobile plugin activated\");\n },\n\n deactivate(api: OpenClawPluginApi) {\n (globalThis as Record<string, unknown>).__mobilePluginActivated = false;\n api.logger.info(\"Alfe Mobile plugin deactivated\");\n },\n};\n\nexport default plugin;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/openclaw-mobile",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "OpenClaw mobile plugin for Alfe — outbound SMS and phone calls 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-c8Vhfjeg.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";;;;UAeU,kBAAA,CAoBiB;QACjB,CAAA,EAAA,MAAA;MACC,EAAA,MAAA,CAAA,EAAA,OAAA;;UAjBD,cAAA,CAmB6D;SACX,CAAA,EAAA;IAAO,OAAA,CAAA,EAlBrD,MAkBqD,CAAA,MAAA,EAAA;MAKzD,MAAO,CAAA,EAvBuB,kBAuBvB;MAAA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IAIH,CAAA,CAAA;IAC0B,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;EAAmC,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;AAAA;UAtBjE,MAAA,CAsLT;MA3Ce,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA;MAuCE,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;;;UA3KzB,iBAAA;UACA;WACC;qBACU;uEACkD;4DACX;;;;UAKlD,OAAA;;;;cAII;wCAC0B,4BAA4B;;;;;;;;cA+G9D;;;;;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-mobile — OpenClaw native plugin\n *\n * Registers mobile tools (SMS, calls) with OpenClaw. Tools call the\n * mobile service API using the agent's API key for authentication.\n *\n * This plugin provides:\n * - mobile_send_sms — send an SMS message from the agent's phone number\n * - mobile_call — initiate an outbound phone call\n */\n\nimport { Type, type TSchema } from \"@sinclair/typebox\";\n\n// ── Plugin config ────────────────────────────────────────────\n\ninterface MobilePluginConfig {\n apiUrl?: string;\n [key: string]: unknown;\n}\n\ninterface OpenClawConfig {\n plugins?: {\n entries?: Record<string, { config?: MobilePluginConfig; [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 mobileApi(\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 : `Mobile 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 mobileTools: ToolDef[] = [\n defineTool({\n name: \"mobile_send_sms\",\n description:\n \"Send an SMS text message from your phone number to the specified number. \" +\n \"The recipient number must be in E.164 format (e.g., +12025551234).\",\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 text message content to send\" }),\n }),\n handler: async (params) => {\n const { to, body } = params as { to: string; body: string };\n return mobileApi(\"POST\", \"/mobile/sms/send\", { to, body });\n },\n }),\n\n defineTool({\n name: \"mobile_call\",\n description:\n \"Make an outbound phone call to the specified number. \" +\n \"When the recipient answers, they will be connected to your voice pipeline. \" +\n \"The number must be in E.164 format (e.g., +12025551234).\",\n parameters: Type.Object({\n to: Type.String({ description: \"Phone number to call in E.164 format (e.g., +12025551234)\" }),\n }),\n handler: async (params) => {\n const { to } = params as { to: string };\n return mobileApi(\"POST\", \"/mobile/calls/outbound\", { to });\n },\n }),\n];\n\n// ── Plugin definition ────────────────────────────────────────\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-mobile\",\n name: \"Alfe Mobile Plugin\",\n description: \"Mobile integration — outbound SMS and phone calls via Twilio\",\n version: \"0.0.1\",\n\n activate(api: OpenClawPluginApi) {\n if ((globalThis as Record<string, unknown>).__mobilePluginActivated) {\n api.logger.debug(\"Alfe Mobile plugin already activated, skipping re-init\");\n return;\n }\n (globalThis as Record<string, unknown>).__mobilePluginActivated = true;\n\n const log = api.logger;\n log.info(\"Alfe Mobile plugin activating...\");\n\n // Resolve API URL from plugin config or environment\n const fullConfig = api.config ?? {};\n const pluginConfig: MobilePluginConfig =\n fullConfig.plugins?.entries?.[\"@alfe.ai/openclaw-mobile\"]?.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 — mobile tools will fail\");\n }\n if (!apiKey) {\n log.warn(\"No ALFE_API_KEY configured — mobile tools will fail\");\n }\n\n log.info(`Mobile API: ${apiUrl}`);\n\n // Register tools\n for (const tool of mobileTools) {\n api.registerTool(tool);\n }\n log.info(`Registered ${String(mobileTools.length)} mobile tools: ${mobileTools.map((t) => t.name).join(\", \")}`);\n\n log.info(\"Alfe Mobile plugin activated\");\n },\n\n deactivate(api: OpenClawPluginApi) {\n (globalThis as Record<string, unknown>).__mobilePluginActivated = false;\n api.logger.info(\"Alfe Mobile plugin deactivated\");\n },\n};\n\nexport default plugin;\n"],"mappings":"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"}
|