openclaw-quiubo 2.6.38 → 2.6.40

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
@@ -199,6 +199,20 @@ If an agent is registered, the gateway sends a heartbeat every 60s to report `co
199
199
 
200
200
  A typing indicator is sent immediately when processing begins, then repeated every 4s until the response is delivered.
201
201
 
202
+ ### Scheduled messages / Cron delivery
203
+
204
+ Cron jobs that deliver to Quiubo groups **must** include `--to <groupId>`:
205
+
206
+ ```bash
207
+ openclaw cron add --every 30m --channel quiubo --to 7868cc21-... "Check in with the team"
208
+ ```
209
+
210
+ Without `--to`, the extension cannot determine which group to deliver to. Unlike 1:1 sessions (which have a single bound chat), group sessions are multi-tenant — the target must be explicit.
211
+
212
+ > **Note:** The `--to` value is the Quiubo group UUID, visible in the group detail screen or conversation URL.
213
+
214
+ See [#84](https://github.com/bitlabs-com/quiubo/issues/84) for a planned improvement to auto-resolve the target from the session bound group.
215
+
202
216
  ## Managing Accounts
203
217
 
204
218
  ```bash
package/dist/index.js CHANGED
@@ -14333,10 +14333,10 @@ function resolveOutboundGroupId(ctx) {
14333
14333
  if (targetGroupId) return targetGroupId;
14334
14334
  const toField = ctx.to;
14335
14335
  if (toField) {
14336
- const str = String(toField);
14337
- if (!str.match(/^quiubo:/i)) {
14338
- const cleaned = str.trim();
14339
- if (cleaned) return cleaned;
14336
+ const str = String(toField).trim();
14337
+ const stripped = str.replace(/^quiubo:/i, "").trim();
14338
+ if (stripped.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)) {
14339
+ return stripped;
14340
14340
  }
14341
14341
  }
14342
14342
  return void 0;
@@ -14350,16 +14350,24 @@ async function resolveAnnounceGroupId(accountId, log) {
14350
14350
  const raw = await readFile4(cronPath, "utf-8");
14351
14351
  const parsed = JSON.parse(raw);
14352
14352
  const jobs = parsed?.jobs ?? [];
14353
+ let fallback;
14353
14354
  for (const job of jobs) {
14354
14355
  if (job.enabled === false) continue;
14355
14356
  const delivery = job.delivery;
14356
14357
  if (!delivery) continue;
14357
14358
  if (delivery.channel !== "quiubo") continue;
14358
14359
  if (delivery.to) {
14359
- log?.info?.(`[${accountId}] [resolveAnnounceGroupId] found cron job ${job.id} \u2192 delivery.to=${delivery.to}`);
14360
- return delivery.to;
14360
+ if (job.agentId === accountId) {
14361
+ log?.info?.(`[${accountId}] [resolveAnnounceGroupId] found matching cron job ${job.id} \u2192 delivery.to=${delivery.to}`);
14362
+ return delivery.to;
14363
+ }
14364
+ if (!fallback) fallback = delivery.to;
14361
14365
  }
14362
14366
  }
14367
+ if (fallback) {
14368
+ log?.info?.(`[${accountId}] [resolveAnnounceGroupId] using fallback cron delivery.to=${fallback}`);
14369
+ return fallback;
14370
+ }
14363
14371
  } catch (err) {
14364
14372
  log?.warn?.(`[${accountId}] [resolveAnnounceGroupId] failed to read cron jobs: ${err}`);
14365
14373
  }