twindex-openclaw-plugin 0.5.1 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twindex-openclaw-plugin",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Music intelligence for AI agents. Tours, merch drops, releases, presales.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -94,12 +94,23 @@ export default function register(api: any) {
94
94
  description:
95
95
  "How often to deliver updates. realtime = every 5 min, periodic = every hour, daily = once per day.",
96
96
  },
97
+ chat_target: {
98
+ type: "string",
99
+ description:
100
+ "Delivery target. For Telegram, this is the chat ID. For Slack, the channel ID.",
101
+ },
102
+ chat_channel: {
103
+ type: "string",
104
+ enum: ["telegram", "slack"],
105
+ description:
106
+ "Delivery channel. Defaults to telegram.",
107
+ },
97
108
  },
98
- required: ["artists", "frequency"],
109
+ required: ["artists", "frequency", "chat_target"],
99
110
  },
100
111
  async execute(
101
112
  _id: string,
102
- params: { artists: string[]; frequency: string },
113
+ params: { artists: string[]; frequency: string; chat_target: string; chat_channel?: string },
103
114
  ) {
104
115
  try {
105
116
  const config = cfg();
@@ -118,6 +129,8 @@ export default function register(api: any) {
118
129
  apiKey,
119
130
  artists: params.artists,
120
131
  frequency: params.frequency,
132
+ chatTarget: params.chat_target,
133
+ chatChannel: params.chat_channel ?? "telegram",
121
134
  });
122
135
 
123
136
  const results: string[] = [];
@@ -1,7 +1,7 @@
1
1
  // Polling notification service — replaces SSE for frameworks that can't hold
2
2
  // persistent connections (like OpenClaw plugins).
3
3
  // Polls GET /api/v1/notifications at configurable intervals, delivers via
4
- // `openclaw agent` CLI, marks read after confirmed delivery.
4
+ // `openclaw message send` CLI, marks read after confirmed delivery.
5
5
 
6
6
  import { execFile } from "child_process";
7
7
  import * as twindex from "./client.js";
@@ -12,21 +12,16 @@ const FREQUENCY_MS: Record<string, number> = {
12
12
  daily: 24 * 60 * 60 * 1000, // 24 hours
13
13
  };
14
14
 
15
- function runAgent(message: string): Promise<boolean> {
15
+ function sendMessage(
16
+ message: string,
17
+ channel: string,
18
+ target: string,
19
+ ): Promise<boolean> {
16
20
  return new Promise((resolve) => {
17
21
  execFile(
18
22
  "openclaw",
19
- [
20
- "agent",
21
- "--session-id",
22
- "twindex-push",
23
- "--deliver",
24
- "--channel",
25
- "last",
26
- "-m",
27
- message,
28
- ],
29
- { timeout: 120_000 },
23
+ ["message", "send", "--channel", channel, "--target", target, "-m", message],
24
+ { timeout: 30_000 },
30
25
  (err) => resolve(!err),
31
26
  );
32
27
  });
@@ -45,6 +40,14 @@ export function createNotificationService(api: any) {
45
40
  return api.config?.plugins?.entries?.twindex?.config?.frequency ?? "periodic";
46
41
  }
47
42
 
43
+ function getChatTarget(): string | undefined {
44
+ return api.config?.plugins?.entries?.twindex?.config?.chatTarget;
45
+ }
46
+
47
+ function getChatChannel(): string {
48
+ return api.config?.plugins?.entries?.twindex?.config?.chatChannel ?? "telegram";
49
+ }
50
+
48
51
  const logger = api.logger;
49
52
 
50
53
  async function poll() {
@@ -55,6 +58,13 @@ export function createNotificationService(api: any) {
55
58
  const apiKey = getApiKey();
56
59
  if (!apiKey) return;
57
60
 
61
+ const target = getChatTarget();
62
+ if (!target) {
63
+ logger?.warn?.("Twindex: no chatTarget configured — skipping delivery");
64
+ return;
65
+ }
66
+ const channel = getChatChannel();
67
+
58
68
  const notifications = await twindex.getNotifications(apiKey);
59
69
  if (!notifications || notifications.length === 0) return;
60
70
 
@@ -69,7 +79,7 @@ export function createNotificationService(api: any) {
69
79
  `New Twindex update for ${notif.brand} (${notif.event_type}): ${notif.summary}\n` +
70
80
  "Share this with the user naturally. If they seem busy, keep it brief.";
71
81
 
72
- const delivered = await runAgent(message);
82
+ const delivered = await sendMessage(message, channel, target);
73
83
  if (delivered) {
74
84
  try {
75
85
  await twindex.markRead(apiKey, [notif.id]);
@@ -77,7 +87,7 @@ export function createNotificationService(api: any) {
77
87
  // Non-fatal — delivered but read status will catch up
78
88
  }
79
89
  } else {
80
- logger?.warn?.("Twindex: agent delivery failed, will retry next poll");
90
+ logger?.warn?.("Twindex: message delivery failed, will retry next poll");
81
91
  break; // Don't pile up failed deliveries
82
92
  }
83
93
  }
@@ -92,7 +102,12 @@ export function createNotificationService(api: any) {
92
102
  id: "twindex-notifications",
93
103
 
94
104
  start() {
95
- if (running) return;
105
+ // Clear any stale timer from a previous gateway reload
106
+ if (timer) {
107
+ clearInterval(timer);
108
+ timer = null;
109
+ }
110
+
96
111
  const apiKey = getApiKey();
97
112
  if (!apiKey) {
98
113
  logger?.info?.("Twindex: no API key — poll service waiting for setup");