openclaw-quiubo 2.6.39 → 2.6.41
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 +14 -0
- package/dist/index.js +51 -6
- package/dist/index.js.map +2 -2
- package/dist/src/channel.d.ts.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
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
|
@@ -13531,6 +13531,43 @@ var quiuboPlugin = {
|
|
|
13531
13531
|
const accts = { ...channel.accounts };
|
|
13532
13532
|
delete accts[id];
|
|
13533
13533
|
return setChannelConfig(cfg, { ...channel, accounts: accts });
|
|
13534
|
+
},
|
|
13535
|
+
/**
|
|
13536
|
+
* Resolve a default delivery target for cron/announce when no --to is provided.
|
|
13537
|
+
* Scans the agent's session store for quiubo group sessions and returns the
|
|
13538
|
+
* group ID if there's exactly one. With multiple groups, returns undefined
|
|
13539
|
+
* (user must specify --to).
|
|
13540
|
+
*/
|
|
13541
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13542
|
+
resolveDefaultTo({ cfg, accountId }) {
|
|
13543
|
+
try {
|
|
13544
|
+
const fs = __require("node:fs");
|
|
13545
|
+
const path = __require("node:path");
|
|
13546
|
+
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
13547
|
+
const agentId = accountId ?? "main";
|
|
13548
|
+
const possiblePaths = [
|
|
13549
|
+
path.join(homeDir, ".openclaw", "agents", agentId, "sessions", "sessions.json"),
|
|
13550
|
+
path.join(homeDir, ".openclaw", "sessions", "sessions.json")
|
|
13551
|
+
];
|
|
13552
|
+
for (const storePath of possiblePaths) {
|
|
13553
|
+
if (!fs.existsSync(storePath)) continue;
|
|
13554
|
+
const raw = fs.readFileSync(storePath, "utf-8");
|
|
13555
|
+
const store = JSON.parse(raw);
|
|
13556
|
+
const groupIds = /* @__PURE__ */ new Set();
|
|
13557
|
+
for (const key of Object.keys(store)) {
|
|
13558
|
+
const match = key.match(/quiubo:([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i);
|
|
13559
|
+
if (match && !key.includes(":group:")) {
|
|
13560
|
+
groupIds.add(match[1]);
|
|
13561
|
+
}
|
|
13562
|
+
}
|
|
13563
|
+
if (groupIds.size === 1) {
|
|
13564
|
+
return [...groupIds][0];
|
|
13565
|
+
}
|
|
13566
|
+
if (groupIds.size > 1) return void 0;
|
|
13567
|
+
}
|
|
13568
|
+
} catch {
|
|
13569
|
+
}
|
|
13570
|
+
return void 0;
|
|
13534
13571
|
}
|
|
13535
13572
|
},
|
|
13536
13573
|
// ── setup adapter (for `channels add` CLI) ──────────────────────
|
|
@@ -14333,10 +14370,10 @@ function resolveOutboundGroupId(ctx) {
|
|
|
14333
14370
|
if (targetGroupId) return targetGroupId;
|
|
14334
14371
|
const toField = ctx.to;
|
|
14335
14372
|
if (toField) {
|
|
14336
|
-
const str = String(toField);
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14373
|
+
const str = String(toField).trim();
|
|
14374
|
+
const stripped = str.replace(/^quiubo:/i, "").trim();
|
|
14375
|
+
if (stripped.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)) {
|
|
14376
|
+
return stripped;
|
|
14340
14377
|
}
|
|
14341
14378
|
}
|
|
14342
14379
|
return void 0;
|
|
@@ -14350,16 +14387,24 @@ async function resolveAnnounceGroupId(accountId, log) {
|
|
|
14350
14387
|
const raw = await readFile4(cronPath, "utf-8");
|
|
14351
14388
|
const parsed = JSON.parse(raw);
|
|
14352
14389
|
const jobs = parsed?.jobs ?? [];
|
|
14390
|
+
let fallback;
|
|
14353
14391
|
for (const job of jobs) {
|
|
14354
14392
|
if (job.enabled === false) continue;
|
|
14355
14393
|
const delivery = job.delivery;
|
|
14356
14394
|
if (!delivery) continue;
|
|
14357
14395
|
if (delivery.channel !== "quiubo") continue;
|
|
14358
14396
|
if (delivery.to) {
|
|
14359
|
-
|
|
14360
|
-
|
|
14397
|
+
if (job.agentId === accountId) {
|
|
14398
|
+
log?.info?.(`[${accountId}] [resolveAnnounceGroupId] found matching cron job ${job.id} \u2192 delivery.to=${delivery.to}`);
|
|
14399
|
+
return delivery.to;
|
|
14400
|
+
}
|
|
14401
|
+
if (!fallback) fallback = delivery.to;
|
|
14361
14402
|
}
|
|
14362
14403
|
}
|
|
14404
|
+
if (fallback) {
|
|
14405
|
+
log?.info?.(`[${accountId}] [resolveAnnounceGroupId] using fallback cron delivery.to=${fallback}`);
|
|
14406
|
+
return fallback;
|
|
14407
|
+
}
|
|
14363
14408
|
} catch (err) {
|
|
14364
14409
|
log?.warn?.(`[${accountId}] [resolveAnnounceGroupId] failed to read cron jobs: ${err}`);
|
|
14365
14410
|
}
|