@alfe.ai/openclaw-voice 0.0.11 → 0.0.13

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/plugin.cjs CHANGED
@@ -17,6 +17,7 @@ let _alfe_ai_config = require("@alfe.ai/config");
17
17
  * - voice_transfer tool — placeholder (requires Twilio service)
18
18
  * - voice_dtmf tool �� placeholder (requires Twilio service)
19
19
  */
20
+ const pkg = (0, require("node:module").createRequire)(require("url").pathToFileURL(__filename).href)("../package.json");
20
21
  const VOICE_CAPABILITIES = [
21
22
  "voice.call",
22
23
  "voice.answer",
@@ -137,17 +138,20 @@ const plugin = {
137
138
  id: "@alfe.ai/openclaw-voice",
138
139
  name: "Alfe Voice Plugin",
139
140
  description: "Voice integration — TTS/STT via the voice service, channel-specific operations via channel services",
140
- version: "0.2.0",
141
+ version: pkg.version,
141
142
  activate(api) {
142
143
  const log = api.logger;
143
- if (api.registrationMode && api.registrationMode !== "full") return;
144
144
  for (const tool of voiceTools) api.registerTool(tool);
145
145
  log.info(`Registered ${String(voiceTools.length)} voice tools: ${voiceTools.map((t) => t.name).join(", ")}`);
146
- if (!globalThis.__voiceGatewayActivated) {
146
+ const fullConfig = api.config ?? {};
147
+ const pluginConfig = fullConfig.plugins?.entries?.["@alfe.ai/openclaw-voice"]?.config ?? fullConfig.plugins?.entries?.["voice-gateway"]?.config ?? {};
148
+ const startVoiceService = () => {
149
+ if (globalThis.__voiceGatewayActivated === true) {
150
+ log.debug("Alfe Voice plugin already activated — skipping duplicate");
151
+ return;
152
+ }
147
153
  globalThis.__voiceGatewayActivated = true;
148
154
  log.info("Alfe Voice plugin activating...");
149
- const fullConfig = api.config ?? {};
150
- const pluginConfig = fullConfig.plugins?.entries?.["@alfe.ai/openclaw-voice"]?.config ?? fullConfig.plugins?.entries?.["voice-gateway"]?.config ?? {};
151
155
  voiceServiceUrl = pluginConfig.voiceServiceUrl ?? `http://localhost:${String(pluginConfig.voiceServicePort ?? "3100")}`;
152
156
  voiceServiceApiKey = pluginConfig.voiceServiceApiKey ?? "";
153
157
  log.info(`Voice service: ${voiceServiceUrl}`);
@@ -160,7 +164,20 @@ const plugin = {
160
164
  }).catch((err) => {
161
165
  log.debug(`Daemon connect failed: ${err.message}`);
162
166
  });
163
- }
167
+ };
168
+ const stopVoiceService = () => {
169
+ globalThis.__voiceGatewayActivated = false;
170
+ if (daemonIpcClient) {
171
+ try {
172
+ daemonIpcClient.stop();
173
+ log.info("Disconnected from Alfe daemon");
174
+ } catch (err) {
175
+ log.debug(`Error disconnecting from daemon: ${err.message}`);
176
+ }
177
+ daemonIpcClient = null;
178
+ }
179
+ log.info("Alfe Voice plugin deactivated");
180
+ };
164
181
  api.registerGatewayMethod("voice.speak", async (...args) => {
165
182
  const { text } = args[0];
166
183
  log.info(`voice.speak RPC → text=${text?.slice(0, 50) ?? "(none)"}...`);
@@ -172,6 +189,16 @@ const plugin = {
172
189
  const event = eventArgs[0];
173
190
  if (eventArgs[1].channelId.includes("voice")) log.debug(`Voice-related message from ${event.from}: ${event.content.slice(0, 100)}`);
174
191
  });
192
+ if (api.registerService) api.registerService({
193
+ id: "alfe-voice-daemon",
194
+ start: () => {
195
+ startVoiceService();
196
+ },
197
+ stop: () => {
198
+ stopVoiceService();
199
+ }
200
+ });
201
+ else if (!globalThis.__voiceGatewayActivated) startVoiceService();
175
202
  log.info("Alfe Voice plugin activated");
176
203
  },
177
204
  deactivate(api) {
package/dist/plugin.d.cts CHANGED
@@ -25,12 +25,23 @@ interface OpenClawConfig {
25
25
  };
26
26
  [key: string]: unknown;
27
27
  }
28
+ interface PluginServiceContext {
29
+ config: Record<string, unknown>;
30
+ workspaceDir?: string;
31
+ stateDir: string;
32
+ logger: Logger;
33
+ }
28
34
  interface OpenClawPluginApi {
29
35
  logger: Logger;
30
36
  registrationMode?: 'full' | 'setup-only' | 'setup-runtime' | 'cli-metadata';
31
37
  config?: OpenClawConfig;
32
38
  registerTool(tool: ToolDef): void;
33
39
  registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
40
+ registerService?(service: {
41
+ id: string;
42
+ start: (ctx: PluginServiceContext) => void | Promise<void>;
43
+ stop?: (ctx: PluginServiceContext) => void | Promise<void>;
44
+ }): void;
34
45
  on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: {
35
46
  priority?: number;
36
47
  }): void;
package/dist/plugin.d.ts CHANGED
@@ -25,12 +25,23 @@ interface OpenClawConfig {
25
25
  };
26
26
  [key: string]: unknown;
27
27
  }
28
+ interface PluginServiceContext {
29
+ config: Record<string, unknown>;
30
+ workspaceDir?: string;
31
+ stateDir: string;
32
+ logger: Logger;
33
+ }
28
34
  interface OpenClawPluginApi {
29
35
  logger: Logger;
30
36
  registrationMode?: 'full' | 'setup-only' | 'setup-runtime' | 'cli-metadata';
31
37
  config?: OpenClawConfig;
32
38
  registerTool(tool: ToolDef): void;
33
39
  registerGatewayMethod(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
40
+ registerService?(service: {
41
+ id: string;
42
+ start: (ctx: PluginServiceContext) => void | Promise<void>;
43
+ stop?: (ctx: PluginServiceContext) => void | Promise<void>;
44
+ }): void;
34
45
  on(event: string, handler: (...args: unknown[]) => void | Promise<void>, options?: {
35
46
  priority?: number;
36
47
  }): void;
package/dist/plugin.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createRequire } from "node:module";
1
2
  import { Type } from "@sinclair/typebox";
2
3
  import { DEFAULT_SOCKET_PATH, resolveConfig } from "@alfe.ai/config";
3
4
  //#region src/plugin.ts
@@ -17,6 +18,7 @@ import { DEFAULT_SOCKET_PATH, resolveConfig } from "@alfe.ai/config";
17
18
  * - voice_transfer tool — placeholder (requires Twilio service)
18
19
  * - voice_dtmf tool �� placeholder (requires Twilio service)
19
20
  */
21
+ const pkg = createRequire(import.meta.url)("../package.json");
20
22
  const VOICE_CAPABILITIES = [
21
23
  "voice.call",
22
24
  "voice.answer",
@@ -137,17 +139,20 @@ const plugin = {
137
139
  id: "@alfe.ai/openclaw-voice",
138
140
  name: "Alfe Voice Plugin",
139
141
  description: "Voice integration — TTS/STT via the voice service, channel-specific operations via channel services",
140
- version: "0.2.0",
142
+ version: pkg.version,
141
143
  activate(api) {
142
144
  const log = api.logger;
143
- if (api.registrationMode && api.registrationMode !== "full") return;
144
145
  for (const tool of voiceTools) api.registerTool(tool);
145
146
  log.info(`Registered ${String(voiceTools.length)} voice tools: ${voiceTools.map((t) => t.name).join(", ")}`);
146
- if (!globalThis.__voiceGatewayActivated) {
147
+ const fullConfig = api.config ?? {};
148
+ const pluginConfig = fullConfig.plugins?.entries?.["@alfe.ai/openclaw-voice"]?.config ?? fullConfig.plugins?.entries?.["voice-gateway"]?.config ?? {};
149
+ const startVoiceService = () => {
150
+ if (globalThis.__voiceGatewayActivated === true) {
151
+ log.debug("Alfe Voice plugin already activated — skipping duplicate");
152
+ return;
153
+ }
147
154
  globalThis.__voiceGatewayActivated = true;
148
155
  log.info("Alfe Voice plugin activating...");
149
- const fullConfig = api.config ?? {};
150
- const pluginConfig = fullConfig.plugins?.entries?.["@alfe.ai/openclaw-voice"]?.config ?? fullConfig.plugins?.entries?.["voice-gateway"]?.config ?? {};
151
156
  voiceServiceUrl = pluginConfig.voiceServiceUrl ?? `http://localhost:${String(pluginConfig.voiceServicePort ?? "3100")}`;
152
157
  voiceServiceApiKey = pluginConfig.voiceServiceApiKey ?? "";
153
158
  log.info(`Voice service: ${voiceServiceUrl}`);
@@ -160,7 +165,20 @@ const plugin = {
160
165
  }).catch((err) => {
161
166
  log.debug(`Daemon connect failed: ${err.message}`);
162
167
  });
163
- }
168
+ };
169
+ const stopVoiceService = () => {
170
+ globalThis.__voiceGatewayActivated = false;
171
+ if (daemonIpcClient) {
172
+ try {
173
+ daemonIpcClient.stop();
174
+ log.info("Disconnected from Alfe daemon");
175
+ } catch (err) {
176
+ log.debug(`Error disconnecting from daemon: ${err.message}`);
177
+ }
178
+ daemonIpcClient = null;
179
+ }
180
+ log.info("Alfe Voice plugin deactivated");
181
+ };
164
182
  api.registerGatewayMethod("voice.speak", async (...args) => {
165
183
  const { text } = args[0];
166
184
  log.info(`voice.speak RPC → text=${text?.slice(0, 50) ?? "(none)"}...`);
@@ -172,6 +190,16 @@ const plugin = {
172
190
  const event = eventArgs[0];
173
191
  if (eventArgs[1].channelId.includes("voice")) log.debug(`Voice-related message from ${event.from}: ${event.content.slice(0, 100)}`);
174
192
  });
193
+ if (api.registerService) api.registerService({
194
+ id: "alfe-voice-daemon",
195
+ start: () => {
196
+ startVoiceService();
197
+ },
198
+ stop: () => {
199
+ stopVoiceService();
200
+ }
201
+ });
202
+ else if (!globalThis.__voiceGatewayActivated) startVoiceService();
175
203
  log.info("Alfe Voice plugin activated");
176
204
  },
177
205
  deactivate(api) {
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "id": "@alfe.ai/openclaw-voice",
3
3
  "name": "Alfe Voice Plugin",
4
- "version": "0.1.0",
5
4
  "description": "Pure relay plugin — connects to Fly voice server via WebSocket. All audio processing (STT, TTS, ack) runs on Fly.",
6
5
  "entry": "./dist/plugin.js",
7
6
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/openclaw-voice",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "OpenClaw voice plugin for Alfe — Discord audio, Twilio, Recall.ai",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",