@stagewhisper/stagewhisper 0.9.0 → 0.14.0

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/index.ts CHANGED
@@ -1,77 +1,54 @@
1
- import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
- import { stagewhisperPlugin } from "./src/channel.js";
3
- import { setRuntime } from "./src/runtime.js";
4
- import { createRelayService } from "./src/service.js";
5
-
6
- export default definePluginEntry({
7
- id: "stagewhisper",
8
- name: "StageWhisper",
9
- description: "Turn live call moments into assistant tasks via StageWhisper",
10
- register(api) {
11
- api.registerChannel({ plugin: stagewhisperPlugin });
12
-
13
- const service = createRelayService(api);
14
-
15
- api.registerCli(({ program }) => {
16
- const sw = program
17
- .command("stagewhisper")
18
- .description("StageWhisper integration");
19
-
20
- sw.command("pair")
21
- .description("Pair with StageWhisper using a pairing code from the desktop app")
22
- .requiredOption("--code <code>", "Pairing code from Settings → Assistant")
23
- .requiredOption("--api-url <url>", "StageWhisper backend URL (e.g. https://api.stagewhisper.io)")
24
- .option("--label <label>", "Label for this OpenClaw host", "OpenClaw")
25
- .action(
26
- async (opts: { code: string; apiUrl: string; label?: string }) => {
27
- const { StageWhisperClient } = await import("./src/client.js");
28
- const client = new StageWhisperClient(opts.apiUrl, "", "");
29
- try {
30
- const result = await client.completePairing(
31
- opts.code,
32
- opts.label ?? "OpenClaw",
33
- );
34
-
35
- console.log(`\n✓ Paired with StageWhisper (${result.label})\n`);
36
- console.log(" Apply the config:\n");
37
- console.log(` openclaw config set plugins.entries.stagewhisper.config.apiBaseUrl ${JSON.stringify(opts.apiUrl)}`);
38
- console.log(` openclaw config set plugins.entries.stagewhisper.config.integrationId ${JSON.stringify(result.integration_id)}`);
39
- console.log(` openclaw config set plugins.entries.stagewhisper.config.relayToken ${JSON.stringify(result.relay_token)}`);
40
- console.log(` openclaw config set plugins.entries.stagewhisper.config.label ${JSON.stringify(result.label)}`);
41
- console.log("\n Then restart OpenClaw to activate the relay:\n");
42
- console.log(" openclaw gateway restart\n");
43
- } catch (err) {
44
- console.error(`\n✗ Pairing failed: ${err}\n`);
45
- process.exit(1);
46
- }
47
- },
48
- );
49
-
50
- sw.command("status")
51
- .description("Show StageWhisper relay connection status")
52
- .action(() => {
53
- const relayState = service.getState();
54
- const cfg = api.pluginConfig as Record<string, string> | undefined;
55
- const configured = !!(cfg?.["integrationId"] && cfg?.["relayToken"]);
56
-
57
- if (!configured) {
58
- console.log("\nStageWhisper: not paired\n");
59
- console.log(" Run: openclaw stagewhisper pair --code <CODE> --api-url <URL>\n");
60
- console.log(" Get the pairing code from StageWhisper desktop: Settings → Assistant → Generate Pairing Code\n");
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ // OpenClaw loads external plugins via jiti from ~/.openclaw/extensions/.
5
+ // jiti's alias map is built by walking up from the plugin file's directory
6
+ // to find a package.json with name "openclaw" — but external plugins live
7
+ // outside the openclaw package tree, so the walk never finds it and
8
+ // 'openclaw/plugin-sdk/*' imports fail with "Cannot find module".
9
+ //
10
+ // This bootstrap creates a node_modules/openclaw symlink pointing to the
11
+ // actual openclaw package (located via process.argv[1]), then loads the
12
+ // real plugin entry where the openclaw imports live.
13
+
14
+ function ensureOpenClawResolvable(): void {
15
+ const pluginDir =
16
+ typeof __dirname === "string"
17
+ ? __dirname
18
+ : path.dirname(new URL(import.meta.url).pathname);
19
+
20
+ const link = path.join(pluginDir, "node_modules", "openclaw");
21
+ if (fs.existsSync(link)) return;
22
+
23
+ const binPath = process.argv[1];
24
+ if (!binPath) return;
25
+
26
+ try {
27
+ const resolved = fs.realpathSync(binPath);
28
+ let dir = path.dirname(resolved);
29
+ for (let i = 0; i < 20; i++) {
30
+ const pkgPath = path.join(dir, "package.json");
31
+ if (fs.existsSync(pkgPath)) {
32
+ try {
33
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
34
+ if (pkg.name === "openclaw") {
35
+ fs.mkdirSync(path.join(pluginDir, "node_modules"), {
36
+ recursive: true,
37
+ });
38
+ fs.symlinkSync(dir, link, "dir");
61
39
  return;
62
40
  }
63
-
64
- console.log(`\nStageWhisper relay:`);
65
- console.log(` Connected: ${relayState.connected}`);
66
- console.log(` Last heartbeat: ${relayState.lastHeartbeat?.toISOString() ?? "never"}`);
67
- console.log(` Reconnect attempts: ${relayState.reconnectAttempts}`);
68
- console.log(` Backend: ${cfg?.["apiBaseUrl"] ?? "(unset)"}\n`);
69
- });
70
- });
71
-
72
- if (api.registrationMode !== "full") return;
73
-
74
- setRuntime(api.runtime);
75
- api.registerService(service);
76
- },
77
- });
41
+ } catch {}
42
+ }
43
+ const parent = path.dirname(dir);
44
+ if (parent === dir) break;
45
+ dir = parent;
46
+ }
47
+ } catch {}
48
+ }
49
+
50
+ ensureOpenClawResolvable();
51
+
52
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
53
+ const pluginMain = require("./plugin-main");
54
+ export default pluginMain.default ?? pluginMain;
@@ -2,7 +2,7 @@
2
2
  "id": "stagewhisper",
3
3
  "name": "StageWhisper",
4
4
  "description": "Turn live call moments into assistant tasks via StageWhisper",
5
- "version": "0.9.0",
5
+ "version": "0.14.0",
6
6
  "channels": [
7
7
  "stagewhisper"
8
8
  ],
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@stagewhisper/stagewhisper",
3
- "version": "0.9.0",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "description": "OpenClaw channel plugin that connects StageWhisper live calls to your AI assistant",
6
6
  "license": "MIT",
7
7
  "files": [
8
8
  "index.ts",
9
- "setup-entry.ts",
9
+ "plugin-main.ts",
10
10
  "api.ts",
11
11
  "src",
12
12
  "openclaw.plugin.json",
@@ -21,7 +21,6 @@
21
21
  "extensions": [
22
22
  "./index.ts"
23
23
  ],
24
- "setupEntry": "./setup-entry.ts",
25
24
  "channel": {
26
25
  "id": "stagewhisper",
27
26
  "label": "StageWhisper",
package/plugin-main.ts ADDED
@@ -0,0 +1,77 @@
1
+ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
+ import { stagewhisperPlugin } from "./src/channel.js";
3
+ import { setRuntime } from "./src/runtime.js";
4
+ import { createRelayService } from "./src/service.js";
5
+
6
+ export default definePluginEntry({
7
+ id: "stagewhisper",
8
+ name: "StageWhisper",
9
+ description: "Turn live call moments into assistant tasks via StageWhisper",
10
+ register(api) {
11
+ api.registerChannel({ plugin: stagewhisperPlugin });
12
+
13
+ const service = createRelayService(api);
14
+
15
+ api.registerCli(({ program }) => {
16
+ const sw = program
17
+ .command("stagewhisper")
18
+ .description("StageWhisper integration");
19
+
20
+ sw.command("pair")
21
+ .description("Pair with StageWhisper using a pairing code from the desktop app")
22
+ .requiredOption("--code <code>", "Pairing code from Settings → Assistant")
23
+ .requiredOption("--api-url <url>", "StageWhisper backend URL (e.g. https://api.stagewhisper.io)")
24
+ .option("--label <label>", "Label for this OpenClaw host", "OpenClaw")
25
+ .action(
26
+ async (opts: { code: string; apiUrl: string; label?: string }) => {
27
+ const { StageWhisperClient } = await import("./src/client.js");
28
+ const client = new StageWhisperClient(opts.apiUrl, "", "");
29
+ try {
30
+ const result = await client.completePairing(
31
+ opts.code,
32
+ opts.label ?? "OpenClaw",
33
+ );
34
+
35
+ console.log(`\n✓ Paired with StageWhisper (${result.label})\n`);
36
+ console.log(" Apply the config:\n");
37
+ console.log(` openclaw config set plugins.entries.stagewhisper.config.apiBaseUrl ${JSON.stringify(opts.apiUrl)}`);
38
+ console.log(` openclaw config set plugins.entries.stagewhisper.config.integrationId ${JSON.stringify(result.integration_id)}`);
39
+ console.log(` openclaw config set plugins.entries.stagewhisper.config.relayToken ${JSON.stringify(result.relay_token)}`);
40
+ console.log(` openclaw config set plugins.entries.stagewhisper.config.label ${JSON.stringify(result.label)}`);
41
+ console.log("\n Then restart OpenClaw to activate the relay:\n");
42
+ console.log(" openclaw gateway restart\n");
43
+ } catch (err) {
44
+ console.error(`\n✗ Pairing failed: ${err}\n`);
45
+ process.exit(1);
46
+ }
47
+ },
48
+ );
49
+
50
+ sw.command("status")
51
+ .description("Show StageWhisper relay connection status")
52
+ .action(() => {
53
+ const relayState = service.getState();
54
+ const cfg = api.pluginConfig as Record<string, string> | undefined;
55
+ const configured = !!(cfg?.["integrationId"] && cfg?.["relayToken"]);
56
+
57
+ if (!configured) {
58
+ console.log("\nStageWhisper: not paired\n");
59
+ console.log(" Run: openclaw stagewhisper pair --code <CODE> --api-url <URL>\n");
60
+ console.log(" Get the pairing code from StageWhisper desktop: Settings → Assistant → Generate Pairing Code\n");
61
+ return;
62
+ }
63
+
64
+ console.log(`\nStageWhisper relay:`);
65
+ console.log(` Connected: ${relayState.connected}`);
66
+ console.log(` Last heartbeat: ${relayState.lastHeartbeat?.toISOString() ?? "never"}`);
67
+ console.log(` Reconnect attempts: ${relayState.reconnectAttempts}`);
68
+ console.log(` Backend: ${cfg?.["apiBaseUrl"] ?? "(unset)"}\n`);
69
+ });
70
+ });
71
+
72
+ if (api.registrationMode !== "full") return;
73
+
74
+ setRuntime(api.runtime);
75
+ api.registerService(service);
76
+ },
77
+ });
package/setup-entry.ts DELETED
@@ -1,4 +0,0 @@
1
- import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
2
- import { stagewhisperPlugin } from "./src/channel.js";
3
-
4
- export default defineSetupPluginEntry(stagewhisperPlugin);