openclaw-quiubo 2.6.22 → 2.6.25

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/README.md CHANGED
@@ -8,6 +8,12 @@ OpenClaw channel plugin for [Quiubo](https://quiubo.io) — chat with AI assista
8
8
  npm install openclaw-quiubo
9
9
  ```
10
10
 
11
+ ## Updating
12
+
13
+ ```bash
14
+ openclaw plugins update openclaw-quiubo
15
+ ```
16
+
11
17
  ## Setup
12
18
 
13
19
  ```bash
package/dist/index.js CHANGED
@@ -8957,6 +8957,15 @@ import { basename, join as join2 } from "path";
8957
8957
 
8958
8958
  // src/api.ts
8959
8959
  import { randomUUID } from "crypto";
8960
+ var QuiuboApiError = class extends Error {
8961
+ constructor(status, statusText, body) {
8962
+ super(`Quiubo API error: ${status} ${statusText} - ${body}`);
8963
+ this.status = status;
8964
+ this.statusText = statusText;
8965
+ this.body = body;
8966
+ this.name = "QuiuboApiError";
8967
+ }
8968
+ };
8960
8969
  var QuiuboApiClient = class {
8961
8970
  baseUrl;
8962
8971
  apiKey;
@@ -8977,7 +8986,7 @@ var QuiuboApiClient = class {
8977
8986
  });
8978
8987
  if (!response.ok) {
8979
8988
  const errorBody = await response.text();
8980
- throw new Error(`Quiubo API error: ${response.status} ${response.statusText} - ${errorBody}`);
8989
+ throw new QuiuboApiError(response.status, response.statusText, errorBody);
8981
8990
  }
8982
8991
  if (response.status === 204) {
8983
8992
  return void 0;
@@ -13339,7 +13348,7 @@ var quiuboPlugin = {
13339
13348
  },
13340
13349
  capabilities: {
13341
13350
  chatTypes: ["group"],
13342
- supportsMedia: false,
13351
+ supportsMedia: true,
13343
13352
  supportsReactions: false,
13344
13353
  supportsThreads: false
13345
13354
  },
@@ -13645,8 +13654,12 @@ var quiuboPlugin = {
13645
13654
  log?.info?.(`[${accountId}] [outbound:sendText] sent to group ${groupId} (realtime=${apiResp?.realtimeDelivered})`);
13646
13655
  return { ok: true };
13647
13656
  } catch (error) {
13657
+ if (error instanceof QuiuboApiError) {
13658
+ log?.error?.(`[${accountId}] [outbound:sendText] SEND FAILED [${error.status}] group=${groupId} \u2014 ${error.body}`);
13659
+ return { ok: false, error: `${error.status}: ${error.body}` };
13660
+ }
13648
13661
  const msg = error instanceof Error ? error.message : String(error);
13649
- log?.error?.(`[${accountId}] [outbound:sendText] failed: ${msg}`);
13662
+ log?.error?.(`[${accountId}] [outbound:sendText] SEND FAILED [network] group=${groupId} \u2014 ${msg}`);
13650
13663
  return { ok: false, error: msg };
13651
13664
  }
13652
13665
  },
@@ -13697,8 +13710,12 @@ var quiuboPlugin = {
13697
13710
  log?.info?.(`[${accountId}] [outbound:sendMedia] sent to group ${groupId} (realtime=${apiResp?.realtimeDelivered})`);
13698
13711
  return { ok: true };
13699
13712
  } catch (error) {
13713
+ if (error instanceof QuiuboApiError) {
13714
+ log?.error?.(`[${accountId}] [outbound:sendMedia] SEND FAILED [${error.status}] group=${groupId} \u2014 ${error.body}`);
13715
+ return { ok: false, error: `${error.status}: ${error.body}` };
13716
+ }
13700
13717
  const msg = error instanceof Error ? error.message : String(error);
13701
- log?.error?.(`[${accountId}] [outbound:sendMedia] failed: ${msg}`);
13718
+ log?.error?.(`[${accountId}] [outbound:sendMedia] SEND FAILED [network] group=${groupId} \u2014 ${msg}`);
13702
13719
  return { ok: false, error: msg };
13703
13720
  }
13704
13721
  }
@@ -13714,8 +13731,15 @@ var quiuboPlugin = {
13714
13731
  startAccount: async (ctx) => {
13715
13732
  const { cfg, accountId, abortSignal, log } = ctx;
13716
13733
  const quiuboConfig = getChannelConfig(cfg)?.accounts?.[accountId];
13717
- if (!quiuboConfig?.apiKey || !quiuboConfig?.botIdentityId) {
13718
- log?.warn?.(`[${accountId}] Quiubo: missing apiKey or botIdentityId, skipping`);
13734
+ if (!quiuboConfig) {
13735
+ log?.error?.(`[${accountId}] Quiubo: [FATAL] STARTUP FAILED \u2014 no config found for account "${accountId}". Check channels.quiubo.accounts.${accountId} in your OpenClaw config.`);
13736
+ return;
13737
+ }
13738
+ const missing = [];
13739
+ if (!quiuboConfig.apiKey) missing.push("apiKey");
13740
+ if (!quiuboConfig.botIdentityId) missing.push("botIdentityId");
13741
+ if (missing.length > 0) {
13742
+ log?.error?.(`[${accountId}] Quiubo: [FATAL] STARTUP FAILED \u2014 missing required config: ${missing.join(", ")}. Run "openclaw accounts configure quiubo" to set them.`);
13719
13743
  return;
13720
13744
  }
13721
13745
  if (quiuboConfig.enabled === false) {
@@ -13747,7 +13771,17 @@ var quiuboPlugin = {
13747
13771
  log?.info?.(`[${accountId}] Quiubo: Pusher not configured \u2014 using polling`);
13748
13772
  }
13749
13773
  } catch (error) {
13750
- log?.error?.(`[${accountId}] Quiubo: authentication failed: ${error}`);
13774
+ if (error instanceof QuiuboApiError) {
13775
+ if (error.status === 401) {
13776
+ log?.error?.(`[${accountId}] Quiubo: [FATAL] STARTUP FAILED \u2014 API key is invalid or expired (401). Regenerate your SDK API key in the Quiubo dashboard.`);
13777
+ } else if (error.status === 403) {
13778
+ log?.error?.(`[${accountId}] Quiubo: [FATAL] STARTUP FAILED \u2014 API key lacks permissions (403). Check your SDK app tier and permissions.`);
13779
+ } else {
13780
+ log?.error?.(`[${accountId}] Quiubo: [FATAL] STARTUP FAILED \u2014 authentication error (${error.status}): ${error.body}`);
13781
+ }
13782
+ } else {
13783
+ log?.error?.(`[${accountId}] Quiubo: [FATAL] STARTUP FAILED \u2014 cannot reach API at ${apiUrl}: ${error instanceof Error ? error.message : error}`);
13784
+ }
13751
13785
  return;
13752
13786
  }
13753
13787
  try {
@@ -14058,7 +14092,7 @@ var quiuboPlugin = {
14058
14092
  }
14059
14093
  await gateway.loadCursors();
14060
14094
  await gateway.start();
14061
- log?.info?.(`[${accountId}] Quiubo: gateway started`);
14095
+ log?.info?.(`[${accountId}] Quiubo: [OK] STARTUP COMPLETE \u2014 realtime=${pusherConfig ? "pusher" : "polling"}, agent=${resolvedAgentId ? resolvedAgentName : "none"}, e2ee=${keyManager ? "ready" : "off"}`);
14062
14096
  return new Promise((resolve) => {
14063
14097
  const cleanup = () => {
14064
14098
  log?.info?.(`[${accountId}] Quiubo: gateway stopping`);
@@ -14191,8 +14225,14 @@ async function routeInboundMessage(opts) {
14191
14225
  const senderId = msg.senderIdentityId;
14192
14226
  const groupId = msg.groupId;
14193
14227
  let text = msg.plaintext ?? "";
14228
+ const imageAttachments = (msg.attachments ?? []).filter(
14229
+ (att) => att.storageUrl && att.mimeType?.startsWith("image/")
14230
+ );
14231
+ const mediaUrls = imageAttachments.map((att) => att.storageUrl);
14232
+ const mediaTypes = imageAttachments.map((att) => att.mimeType);
14194
14233
  if (msg.attachments?.length) {
14195
14234
  for (const att of msg.attachments) {
14235
+ if (att.storageUrl && att.mimeType?.startsWith("image/")) continue;
14196
14236
  const sizeKb = att.sizeBytes ? `${(att.sizeBytes / 1024).toFixed(1)} KB` : "";
14197
14237
  text += `
14198
14238
 
@@ -14229,7 +14269,11 @@ async function routeInboundMessage(opts) {
14229
14269
  Provider: CHANNEL_ID,
14230
14270
  Surface: CHANNEL_ID,
14231
14271
  MessageSid: `quiubo-${msg.messageId}`,
14232
- Timestamp: msg.createdAt ? new Date(msg.createdAt).getTime() : Date.now()
14272
+ Timestamp: msg.createdAt ? new Date(msg.createdAt).getTime() : Date.now(),
14273
+ ...mediaUrls.length > 0 && {
14274
+ MediaUrls: mediaUrls,
14275
+ MediaTypes: mediaTypes
14276
+ }
14233
14277
  });
14234
14278
  try {
14235
14279
  await runtime2.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
@@ -14311,7 +14355,11 @@ async function routeInboundMessage(opts) {
14311
14355
  log?.info?.(`[${accountId}] Quiubo: reply sent to group ${groupId} (realtime=${apiResp?.realtimeDelivered})`);
14312
14356
  }
14313
14357
  } catch (error) {
14314
- log?.error?.(`[${accountId}] Quiubo: failed to send reply: ${error}`);
14358
+ if (error instanceof QuiuboApiError) {
14359
+ log?.error?.(`[${accountId}] Quiubo: SEND FAILED [${error.status}] group=${groupId} \u2014 ${error.body}`);
14360
+ } else {
14361
+ log?.error?.(`[${accountId}] Quiubo: SEND FAILED [network] group=${groupId} \u2014 ${error instanceof Error ? error.message : error}`);
14362
+ }
14315
14363
  }
14316
14364
  },
14317
14365
  // eslint-disable-next-line @typescript-eslint/no-explicit-any