openclaw-plugin-yuanbao 2.15.0 → 2.16.0
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 +1 -1
- package/dist/src/business/actions/handler.js +9 -2
- package/dist/src/business/pipeline/middlewares/dispatch-reply.js +6 -1
- package/dist/src/business/tools/remind.js +4 -4
- package/dist/src/business/trace/context.d.ts +9 -0
- package/dist/src/business/trace/context.js +7 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ through direct messages and group chats.
|
|
|
18
18
|
|
|
19
19
|
## Quick start
|
|
20
20
|
|
|
21
|
-
> **Requires OpenClaw 2026.
|
|
21
|
+
> **Requires OpenClaw 2026.5.7 or above.** Run `openclaw --version` to check. Upgrade with `openclaw update`.
|
|
22
22
|
|
|
23
23
|
### 1. Add the Yuanbao channel with your credentials
|
|
24
24
|
|
|
@@ -15,6 +15,7 @@ import { resolveYuanbaoAccount } from "../../accounts.js";
|
|
|
15
15
|
import { createLog } from "../../logger.js";
|
|
16
16
|
import { getYuanbaoRuntime } from "../../runtime.js";
|
|
17
17
|
import { createMessageSender } from "../outbound/create-sender.js";
|
|
18
|
+
import { getActiveTraceContext } from "../trace/context.js";
|
|
18
19
|
import { resolveActionTarget } from "./resolve-target.js";
|
|
19
20
|
import { searchSticker } from "./sticker/send.js";
|
|
20
21
|
/**
|
|
@@ -135,8 +136,14 @@ export async function handleAction(input) {
|
|
|
135
136
|
}
|
|
136
137
|
log.error(`${item.type} send failed: ${result.error}`);
|
|
137
138
|
}
|
|
138
|
-
else
|
|
139
|
-
|
|
139
|
+
else {
|
|
140
|
+
// Mark outbound delivered on the active agent-run trace context so
|
|
141
|
+
// dispatch-reply won't mistake an action-only reply (e.g. a sticker
|
|
142
|
+
// with no text) for an empty reply and send the fallback text.
|
|
143
|
+
getActiveTraceContext()?.markActionDelivered();
|
|
144
|
+
if (result.messageId) {
|
|
145
|
+
lastMessageId = result.messageId;
|
|
146
|
+
}
|
|
140
147
|
}
|
|
141
148
|
}
|
|
142
149
|
return { channel: "yuanbao", ok: true, messageId: lastMessageId };
|
|
@@ -202,7 +202,12 @@ export const dispatchReply = {
|
|
|
202
202
|
}
|
|
203
203
|
// ⭐ Flush outbound queue
|
|
204
204
|
const flushed = await queueSession.flush();
|
|
205
|
-
|
|
205
|
+
// The model may reply purely through a message action (e.g. sticker/react)
|
|
206
|
+
// which is delivered via handleAction and bypasses queueSession entirely.
|
|
207
|
+
// Such deliveries mark the agent-run trace context, so treat them as real
|
|
208
|
+
// outbound content and skip the fallback reply.
|
|
209
|
+
const deliveredViaAction = ctx.traceContext?.hasActionDelivered() ?? false;
|
|
210
|
+
if (!flushed && !hasSentContent && !deliveredViaAction && !ctx.abortSignal?.aborted) {
|
|
206
211
|
const { fallbackReply } = account;
|
|
207
212
|
if (fallbackReply) {
|
|
208
213
|
ctx.log.warn("[dispatch-reply] AI returned no reply content, using fallback reply");
|
|
@@ -222,10 +222,10 @@ function resolveCronBase(params, intent) {
|
|
|
222
222
|
// ============================================================================
|
|
223
223
|
/** Builds a Gateway job config for a one-time job. */
|
|
224
224
|
function buildOnceJob(params, time, to, accountId, intent) {
|
|
225
|
-
const { name,
|
|
225
|
+
const { name, atStr: at, message } = resolveOnceBase(params, time, intent);
|
|
226
226
|
return {
|
|
227
227
|
name,
|
|
228
|
-
schedule: { kind: 'at',
|
|
228
|
+
schedule: { kind: 'at', at },
|
|
229
229
|
sessionTarget: 'isolated',
|
|
230
230
|
wakeMode: 'now',
|
|
231
231
|
deleteAfterRun: true,
|
|
@@ -411,7 +411,7 @@ async function executeGateway(gatewayTool, p, resolvedTo, accountId) {
|
|
|
411
411
|
if (isCronExpression(p.time)) {
|
|
412
412
|
const job = buildCronJob({ ...p, content: p.content.trim() }, resolvedTo, accountId, intent);
|
|
413
413
|
try {
|
|
414
|
-
const cronResult = await gatewayTool('cron.add', { timeoutMs: DEFAULT_GATEWAY_TIMEOUT_MS },
|
|
414
|
+
const cronResult = await gatewayTool('cron.add', { timeoutMs: DEFAULT_GATEWAY_TIMEOUT_MS }, job);
|
|
415
415
|
const typeLabel = intent === 'task' ? '循环任务' : '周期提醒';
|
|
416
416
|
return json({
|
|
417
417
|
status: 'ok',
|
|
@@ -430,7 +430,7 @@ async function executeGateway(gatewayTool, p, resolvedTo, accountId) {
|
|
|
430
430
|
return json(timeResult);
|
|
431
431
|
const job = buildOnceJob({ ...p, content: p.content.trim() }, timeResult.timeSpec, resolvedTo, accountId, intent);
|
|
432
432
|
try {
|
|
433
|
-
const cronResult = await gatewayTool('cron.add', { timeoutMs: DEFAULT_GATEWAY_TIMEOUT_MS },
|
|
433
|
+
const cronResult = await gatewayTool('cron.add', { timeoutMs: DEFAULT_GATEWAY_TIMEOUT_MS }, job);
|
|
434
434
|
return json({
|
|
435
435
|
status: 'ok',
|
|
436
436
|
action: 'add',
|
|
@@ -4,6 +4,15 @@ export type YuanbaoTraceContext = {
|
|
|
4
4
|
seqId?: string;
|
|
5
5
|
/** Auto-incremented based on inbound seqId */
|
|
6
6
|
nextMsgSeq: () => number | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Mark that an outbound message was successfully delivered via a message
|
|
9
|
+
* action (e.g. sticker/react/send) during this agent run. Used by
|
|
10
|
+
* dispatch-reply to avoid sending the fallback reply when the model already
|
|
11
|
+
* replied through an action rather than the deliver callback.
|
|
12
|
+
*/
|
|
13
|
+
markActionDelivered: () => void;
|
|
14
|
+
/** Whether any action-driven outbound succeeded within this agent run. */
|
|
15
|
+
hasActionDelivered: () => boolean;
|
|
7
16
|
};
|
|
8
17
|
/**
|
|
9
18
|
* Generate a random trace ID (32-char hex string).
|
|
@@ -59,6 +59,11 @@ export function resolveTraceContext(params) {
|
|
|
59
59
|
seqCounter++;
|
|
60
60
|
return baseSeq + seqCounter;
|
|
61
61
|
};
|
|
62
|
+
let actionDelivered = false;
|
|
63
|
+
const markActionDelivered = () => {
|
|
64
|
+
actionDelivered = true;
|
|
65
|
+
};
|
|
66
|
+
const hasActionDelivered = () => actionDelivered;
|
|
62
67
|
const log = createLog("trace");
|
|
63
68
|
log.debug("[msg-trace] resolve context", {
|
|
64
69
|
traceId,
|
|
@@ -69,6 +74,8 @@ export function resolveTraceContext(params) {
|
|
|
69
74
|
traceId,
|
|
70
75
|
traceparent: buildTraceparent(traceId),
|
|
71
76
|
nextMsgSeq,
|
|
77
|
+
markActionDelivered,
|
|
78
|
+
hasActionDelivered,
|
|
72
79
|
...(seqId ? { seqId } : {}),
|
|
73
80
|
};
|
|
74
81
|
}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-plugin-yuanbao",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Tencent YuanBao intelligent bot channel plugin",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@types/ws": "^8.18.1",
|
|
31
31
|
"c8": "^11.0.0",
|
|
32
32
|
"eslint": "^9.0.0",
|
|
33
|
-
"openclaw": ">=2026.
|
|
33
|
+
"openclaw": ">=2026.5.7",
|
|
34
34
|
"tsx": "^4.19.0",
|
|
35
35
|
"typescript": "^5.7.0",
|
|
36
36
|
"typescript-eslint": "^8.0.0"
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"npmSpec": "openclaw-plugin-yuanbao",
|
|
65
65
|
"localPath": "extensions/yuanbao",
|
|
66
66
|
"defaultChoice": "npm",
|
|
67
|
-
"minHostVersion": ">=2026.
|
|
67
|
+
"minHostVersion": ">=2026.5.7"
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
70
|
"scripts": {
|