twindex-openclaw-plugin 0.8.3 → 0.8.5

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.
@@ -2,7 +2,7 @@
2
2
  "id": "twindex",
3
3
  "name": "New Lore",
4
4
  "description": "Music intelligence for AI agents. Get notified about tours, merch drops, releases, and presales for your favorite artists.",
5
- "version": "0.8.3",
5
+ "version": "0.8.5",
6
6
  "skills": ["./skills"],
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "twindex-openclaw-plugin",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Music intelligence for AI agents. Tours, merch drops, releases, presales.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -13,23 +13,37 @@ const FREQUENCY_MS: Record<string, number> = {
13
13
  daily: 24 * 60 * 60 * 1000, // 24 hours
14
14
  };
15
15
 
16
+ const INITIAL_POLL_DELAY_MS = 15 * 1000;
17
+ const MESSAGE_SEND_TIMEOUT_MS = 30 * 1000;
18
+
16
19
  function sendMessage(
17
20
  message: string,
18
21
  channel: string,
19
22
  target: string,
20
- ): Promise<boolean> {
23
+ ): Promise<{ ok: boolean; reason?: string }> {
21
24
  return new Promise((resolve) => {
22
25
  execFile(
23
26
  "openclaw",
24
27
  ["message", "send", "--channel", channel, "--target", target, "-m", message],
25
- { timeout: 30_000 },
26
- (err) => resolve(!err),
28
+ { timeout: MESSAGE_SEND_TIMEOUT_MS },
29
+ (err, stdout, stderr) => {
30
+ if (!err) {
31
+ resolve({ ok: true });
32
+ return;
33
+ }
34
+
35
+ const details = [err.message, stderr?.trim(), stdout?.trim()]
36
+ .filter(Boolean)
37
+ .join(" | ");
38
+ resolve({ ok: false, reason: details || "unknown delivery error" });
39
+ },
27
40
  );
28
41
  });
29
42
  }
30
43
 
31
44
  export function createNotificationService(api: any) {
32
45
  let timer: ReturnType<typeof setInterval> | null = null;
46
+ let startupPoll: ReturnType<typeof setTimeout> | null = null;
33
47
  let running = false;
34
48
  let polling = false; // guard against overlapping polls
35
49
 
@@ -143,15 +157,17 @@ export function createNotificationService(api: any) {
143
157
  message += `\n\nWant to see how it looks on you? Send me a selfie and I'll show you.`;
144
158
  }
145
159
 
146
- const delivered = await sendMessage(message, channel, target);
147
- if (delivered) {
160
+ const delivery = await sendMessage(message, channel, target);
161
+ if (delivery.ok) {
148
162
  try {
149
163
  await twindex.markRead(apiKey, [notif.id]);
150
164
  } catch {
151
165
  // Non-fatal — delivered but read status will catch up
152
166
  }
153
167
  } else {
154
- logger?.warn?.("Twindex: message delivery failed, will retry next poll");
168
+ logger?.warn?.(
169
+ `Twindex: message delivery failed, will retry next poll (${delivery.reason})`,
170
+ );
155
171
  break; // Don't pile up failed deliveries
156
172
  }
157
173
  }
@@ -171,6 +187,10 @@ export function createNotificationService(api: any) {
171
187
  clearInterval(timer);
172
188
  timer = null;
173
189
  }
190
+ if (startupPoll) {
191
+ clearTimeout(startupPoll);
192
+ startupPoll = null;
193
+ }
174
194
 
175
195
  const apiKey = getApiKey();
176
196
  if (!apiKey) {
@@ -182,11 +202,15 @@ export function createNotificationService(api: any) {
182
202
  const freq = getFrequency();
183
203
  const intervalMs = FREQUENCY_MS[freq] ?? FREQUENCY_MS.periodic;
184
204
 
185
- // Immediate first poll
186
- poll();
187
-
188
205
  timer = setInterval(poll, intervalMs);
189
- logger?.info?.(`Twindex: poll service started (${freq}, every ${intervalMs / 1000}s)`);
206
+ const initialDelay = Math.min(INITIAL_POLL_DELAY_MS, intervalMs);
207
+ startupPoll = setTimeout(() => {
208
+ startupPoll = null;
209
+ poll();
210
+ }, initialDelay);
211
+ logger?.info?.(
212
+ `Twindex: poll service started (${freq}, every ${intervalMs / 1000}s, initial delay ${initialDelay / 1000}s)`,
213
+ );
190
214
  },
191
215
 
192
216
  stop() {
@@ -195,6 +219,10 @@ export function createNotificationService(api: any) {
195
219
  clearInterval(timer);
196
220
  timer = null;
197
221
  }
222
+ if (startupPoll) {
223
+ clearTimeout(startupPoll);
224
+ startupPoll = null;
225
+ }
198
226
  logger?.info?.("Twindex: poll service stopped");
199
227
  },
200
228
  };