@shenhh/popo 0.1.19 → 0.1.20
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 +1 -1
- package/skills/popo-msg/SKILL.md +5 -35
- package/src/channel.ts +74 -47
package/package.json
CHANGED
package/skills/popo-msg/SKILL.md
CHANGED
|
@@ -237,16 +237,6 @@ Common errors:
|
|
|
237
237
|
|
|
238
238
|
Recall (retract) a sent message within the allowed time window.
|
|
239
239
|
|
|
240
|
-
```json
|
|
241
|
-
{
|
|
242
|
-
"action": "recall",
|
|
243
|
-
"msgId": "794076f2-68b1-4d0e-94eb-c15946580b56",
|
|
244
|
-
"target": "user@corp.netease.com"
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
Or using POPO-specific parameters:
|
|
249
|
-
|
|
250
240
|
```json
|
|
251
241
|
{
|
|
252
242
|
"action": "recall",
|
|
@@ -258,11 +248,8 @@ Or using POPO-specific parameters:
|
|
|
258
248
|
|
|
259
249
|
**Parameters:**
|
|
260
250
|
- `msgId` (required): Message ID to recall
|
|
261
|
-
- `
|
|
262
|
-
- `
|
|
263
|
-
- `sessionType` (optional): `1` for P2P, `3` for group (auto-detected from target if not provided)
|
|
264
|
-
|
|
265
|
-
\* Either `target` or `sessionId` must be provided.
|
|
251
|
+
- `sessionId` (required): Session ID (user email for P2P, group ID for group)
|
|
252
|
+
- `sessionType` (required): `1` for P2P, `3` for group
|
|
266
253
|
|
|
267
254
|
**Note:** Messages can only be recalled within a limited time (typically 2 minutes).
|
|
268
255
|
|
|
@@ -270,20 +257,6 @@ Or using POPO-specific parameters:
|
|
|
270
257
|
|
|
271
258
|
Query read/unread status for group messages.
|
|
272
259
|
|
|
273
|
-
```json
|
|
274
|
-
{
|
|
275
|
-
"action": "read-ack",
|
|
276
|
-
"msgId": "1000016836-0000000004",
|
|
277
|
-
"target": "group:1234567",
|
|
278
|
-
"type": 1,
|
|
279
|
-
"st": 1672221224000,
|
|
280
|
-
"page": 1,
|
|
281
|
-
"size": 30
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
Or using POPO-specific parameters:
|
|
286
|
-
|
|
287
260
|
```json
|
|
288
261
|
{
|
|
289
262
|
"action": "read-ack",
|
|
@@ -298,15 +271,12 @@ Or using POPO-specific parameters:
|
|
|
298
271
|
|
|
299
272
|
**Parameters:**
|
|
300
273
|
- `msgId` (required): Message ID
|
|
301
|
-
- `
|
|
302
|
-
- `
|
|
303
|
-
- `
|
|
304
|
-
- `st` (optional): Query end timestamp (milliseconds), default is current time
|
|
274
|
+
- `sessionType` (required): Must be `3` (group)
|
|
275
|
+
- `type` (required): `1` for read list, `2` for unread list
|
|
276
|
+
- `st` (required): Query end timestamp (milliseconds)
|
|
305
277
|
- `page` (optional): Page number, default 1
|
|
306
278
|
- `size` (optional): Page size, default 30
|
|
307
279
|
|
|
308
|
-
**Note:** Read-ack only works for group messages, not P2P.
|
|
309
|
-
|
|
310
280
|
**Response:**
|
|
311
281
|
```json
|
|
312
282
|
{
|
package/src/channel.ts
CHANGED
|
@@ -60,6 +60,7 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
60
60
|
agentPrompt: {
|
|
61
61
|
messageToolHints: () => [
|
|
62
62
|
"- POPO targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:email@example.com` or `group:groupId`.",
|
|
63
|
+
"- POPO actions: send, card, unsend (target=to), addParticipant (target=tid), channel-info/channel-edit/channel-delete (channelId=tid), channel-create (no target), member-info (tid param). Custom actions without target: read-ack (msgId), download-file (fileId), update-team-mgmt, view-scope, modify-view-scope, publish-robot, update-instruction-options, configure-card-callback.",
|
|
63
64
|
],
|
|
64
65
|
},
|
|
65
66
|
groups: {
|
|
@@ -171,18 +172,22 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
171
172
|
const enabled = cfg.channels?.popo?.enabled !== false;
|
|
172
173
|
if (!enabled) return [];
|
|
173
174
|
// Return all supported actions
|
|
175
|
+
// Use built-in action names to work with OpenClaw's target mode system:
|
|
176
|
+
// - unsend (recall), channel-create (create-team), addParticipant (invite-team)
|
|
177
|
+
// - channel-delete (drop-team), member-info (team-members), channel-info (team-info)
|
|
178
|
+
// - channel-edit (update-team-info)
|
|
174
179
|
return [
|
|
175
180
|
"send",
|
|
176
181
|
"card",
|
|
177
|
-
"
|
|
182
|
+
"unsend",
|
|
183
|
+
"channel-create",
|
|
184
|
+
"addParticipant",
|
|
185
|
+
"channel-delete",
|
|
186
|
+
"member-info",
|
|
187
|
+
"channel-info",
|
|
188
|
+
"channel-edit",
|
|
178
189
|
"read-ack",
|
|
179
190
|
"download-file",
|
|
180
|
-
"create-team",
|
|
181
|
-
"invite-team",
|
|
182
|
-
"drop-team",
|
|
183
|
-
"team-members",
|
|
184
|
-
"team-info",
|
|
185
|
-
"update-team-info",
|
|
186
191
|
"update-team-mgmt",
|
|
187
192
|
"view-scope",
|
|
188
193
|
"modify-view-scope",
|
|
@@ -310,17 +315,22 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
310
315
|
};
|
|
311
316
|
}
|
|
312
317
|
|
|
313
|
-
// Handle recall
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const sessionId =
|
|
319
|
-
|
|
318
|
+
// Handle unsend action (recall message) - uses built-in "unsend" which has proper target mode
|
|
319
|
+
// Accepts: target (to), messageId, sessionId, sessionType
|
|
320
|
+
if (action === "unsend") {
|
|
321
|
+
const msgId = typeof params.messageId === "string" ? params.messageId : typeof params.msgId === "string" ? params.msgId : "";
|
|
322
|
+
// For unsend, sessionId can come from "to" (target) or explicit sessionId
|
|
323
|
+
const sessionId =
|
|
324
|
+
typeof params.sessionId === "string"
|
|
325
|
+
? params.sessionId
|
|
326
|
+
: typeof params.to === "string"
|
|
327
|
+
? params.to.trim()
|
|
328
|
+
: "";
|
|
329
|
+
const sessionType = typeof params.sessionType === "number" ? params.sessionType : 1;
|
|
320
330
|
if (!msgId || !sessionId) {
|
|
321
331
|
return {
|
|
322
332
|
isError: true,
|
|
323
|
-
content: [{ type: "text", text: "
|
|
333
|
+
content: [{ type: "text", text: "Unsend requires messageId and target (or sessionId)." }],
|
|
324
334
|
};
|
|
325
335
|
}
|
|
326
336
|
const result = await recallMessagePopo({ cfg, msgId, sessionId, sessionType: sessionType as 1 | 3 });
|
|
@@ -341,8 +351,6 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
341
351
|
// Handle read-ack action
|
|
342
352
|
if (action === "read-ack") {
|
|
343
353
|
const msgId = typeof params.msgId === "string" ? params.msgId : "";
|
|
344
|
-
// Support target (OpenClaw standard) for group identification
|
|
345
|
-
const target = typeof params.target === "string" ? params.target : "";
|
|
346
354
|
const type = typeof params.type === "number" ? params.type : 1;
|
|
347
355
|
const st = typeof params.st === "number" ? params.st : Date.now();
|
|
348
356
|
const page = typeof params.page === "number" ? params.page : 1;
|
|
@@ -353,13 +361,6 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
353
361
|
content: [{ type: "text", text: "Read-ack requires msgId." }],
|
|
354
362
|
};
|
|
355
363
|
}
|
|
356
|
-
// If target is provided, validate it's a group (read-ack only works for groups)
|
|
357
|
-
if (target && target.includes("@")) {
|
|
358
|
-
return {
|
|
359
|
-
isError: true,
|
|
360
|
-
content: [{ type: "text", text: "Read-ack only works for group messages, not P2P." }],
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
364
|
const result = await getMessageReadAckPopo({
|
|
364
365
|
cfg,
|
|
365
366
|
msgId,
|
|
@@ -413,8 +414,9 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
413
414
|
|
|
414
415
|
// ==================== Team Management Actions ====================
|
|
415
416
|
|
|
416
|
-
// Handle create
|
|
417
|
-
|
|
417
|
+
// Handle channel-create action (create team)
|
|
418
|
+
// Built-in action with targetMode: none
|
|
419
|
+
if (action === "channel-create") {
|
|
418
420
|
const uid = typeof params.uid === "string" ? params.uid : "";
|
|
419
421
|
const name = typeof params.name === "string" ? params.name : undefined;
|
|
420
422
|
const uidList = Array.isArray(params.uidList) ? params.uidList : [];
|
|
@@ -422,7 +424,7 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
422
424
|
if (!uid || uidList.length === 0) {
|
|
423
425
|
return {
|
|
424
426
|
isError: true,
|
|
425
|
-
content: [{ type: "text", text: "
|
|
427
|
+
content: [{ type: "text", text: "channel-create requires uid (owner) and uidList (members)." }],
|
|
426
428
|
};
|
|
427
429
|
}
|
|
428
430
|
const result = await createTeam({ cfg, uid, name, uidList, photoUrl });
|
|
@@ -443,16 +445,22 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
443
445
|
};
|
|
444
446
|
}
|
|
445
447
|
|
|
446
|
-
// Handle invite
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const
|
|
448
|
+
// Handle addParticipant action (invite to team)
|
|
449
|
+
// Built-in action with targetMode: to (tid comes from target/to)
|
|
450
|
+
if (action === "addParticipant") {
|
|
451
|
+
const tid =
|
|
452
|
+
typeof params.tid === "string"
|
|
453
|
+
? params.tid
|
|
454
|
+
: typeof params.to === "string"
|
|
455
|
+
? params.to.trim()
|
|
456
|
+
: "";
|
|
457
|
+
const inviteList = Array.isArray(params.inviteList) ? params.inviteList : Array.isArray(params.participant) ? params.participant : [];
|
|
450
458
|
const type = typeof params.type === "string" ? (params.type as "1" | "2") : "1";
|
|
451
459
|
const text = typeof params.text === "string" ? params.text : undefined;
|
|
452
460
|
if (!tid || inviteList.length === 0) {
|
|
453
461
|
return {
|
|
454
462
|
isError: true,
|
|
455
|
-
content: [{ type: "text", text: "
|
|
463
|
+
content: [{ type: "text", text: "addParticipant requires target (tid) and inviteList/participant." }],
|
|
456
464
|
};
|
|
457
465
|
}
|
|
458
466
|
const result = await inviteToTeam({ cfg, tid, inviteList, type, text });
|
|
@@ -472,13 +480,19 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
472
480
|
};
|
|
473
481
|
}
|
|
474
482
|
|
|
475
|
-
// Handle
|
|
476
|
-
|
|
477
|
-
|
|
483
|
+
// Handle channel-delete action (drop/disband team)
|
|
484
|
+
// Built-in action with targetMode: channelId
|
|
485
|
+
if (action === "channel-delete") {
|
|
486
|
+
const tid =
|
|
487
|
+
typeof params.tid === "string"
|
|
488
|
+
? params.tid
|
|
489
|
+
: typeof params.channelId === "string"
|
|
490
|
+
? params.channelId.trim()
|
|
491
|
+
: "";
|
|
478
492
|
if (!tid) {
|
|
479
493
|
return {
|
|
480
494
|
isError: true,
|
|
481
|
-
content: [{ type: "text", text: "
|
|
495
|
+
content: [{ type: "text", text: "channel-delete requires channelId (team ID)." }],
|
|
482
496
|
};
|
|
483
497
|
}
|
|
484
498
|
const result = await dropTeam({ cfg, tid });
|
|
@@ -496,15 +510,16 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
496
510
|
};
|
|
497
511
|
}
|
|
498
512
|
|
|
499
|
-
// Handle
|
|
500
|
-
|
|
513
|
+
// Handle member-info action (get team members)
|
|
514
|
+
// Built-in action with targetMode: none
|
|
515
|
+
if (action === "member-info") {
|
|
501
516
|
const tid = typeof params.tid === "string" ? params.tid : "";
|
|
502
517
|
const page = typeof params.page === "number" ? params.page : 1;
|
|
503
518
|
const limit = typeof params.limit === "number" ? params.limit : 20;
|
|
504
519
|
if (!tid) {
|
|
505
520
|
return {
|
|
506
521
|
isError: true,
|
|
507
|
-
content: [{ type: "text", text: "
|
|
522
|
+
content: [{ type: "text", text: "member-info requires tid (team ID)." }],
|
|
508
523
|
};
|
|
509
524
|
}
|
|
510
525
|
const result = await getTeamMembers({ cfg, tid, page, limit });
|
|
@@ -526,14 +541,20 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
526
541
|
};
|
|
527
542
|
}
|
|
528
543
|
|
|
529
|
-
// Handle
|
|
530
|
-
|
|
531
|
-
|
|
544
|
+
// Handle channel-info action (get team info)
|
|
545
|
+
// Built-in action with targetMode: channelId
|
|
546
|
+
if (action === "channel-info") {
|
|
547
|
+
const tid =
|
|
548
|
+
typeof params.tid === "string"
|
|
549
|
+
? params.tid
|
|
550
|
+
: typeof params.channelId === "string"
|
|
551
|
+
? params.channelId.trim()
|
|
552
|
+
: "";
|
|
532
553
|
const scopes = Array.isArray(params.scopes) ? params.scopes : undefined;
|
|
533
554
|
if (!tid) {
|
|
534
555
|
return {
|
|
535
556
|
isError: true,
|
|
536
|
-
content: [{ type: "text", text: "
|
|
557
|
+
content: [{ type: "text", text: "channel-info requires channelId (team ID)." }],
|
|
537
558
|
};
|
|
538
559
|
}
|
|
539
560
|
const result = await getTeamInfo({ cfg, tid, scopes });
|
|
@@ -552,16 +573,22 @@ export const popoPlugin: ChannelPlugin<ResolvedPopoAccount> = {
|
|
|
552
573
|
};
|
|
553
574
|
}
|
|
554
575
|
|
|
555
|
-
// Handle update
|
|
556
|
-
|
|
557
|
-
|
|
576
|
+
// Handle channel-edit action (update team info)
|
|
577
|
+
// Built-in action with targetMode: channelId
|
|
578
|
+
if (action === "channel-edit") {
|
|
579
|
+
const tid =
|
|
580
|
+
typeof params.tid === "string"
|
|
581
|
+
? params.tid
|
|
582
|
+
: typeof params.channelId === "string"
|
|
583
|
+
? params.channelId.trim()
|
|
584
|
+
: "";
|
|
558
585
|
const name = typeof params.name === "string" ? params.name : "";
|
|
559
586
|
const board = typeof params.board === "string" ? params.board : "";
|
|
560
587
|
const type = typeof params.type === "number" ? params.type : undefined;
|
|
561
588
|
if (!tid || !name || !board) {
|
|
562
589
|
return {
|
|
563
590
|
isError: true,
|
|
564
|
-
content: [{ type: "text", text: "
|
|
591
|
+
content: [{ type: "text", text: "channel-edit requires channelId (tid), name, and board." }],
|
|
565
592
|
};
|
|
566
593
|
}
|
|
567
594
|
const result = await updateTeamInfo({ cfg, tid, name, board, type });
|