@openclaw-china/dingtalk 2026.3.5 → 2026.3.7
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/dist/index.d.ts +13 -0
- package/dist/index.js +273 -175
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +5 -4
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { z } from 'zod';
|
|
|
14
14
|
* - groupAllowFrom: 群聊白名单会话 ID 列表
|
|
15
15
|
* - historyLimit: 历史消息数量限制
|
|
16
16
|
* - textChunkLimit: 文本分块大小限制
|
|
17
|
+
* - longTaskNoticeDelayMs: 长任务提醒延迟(毫秒,0 表示关闭)
|
|
17
18
|
* - enableAICard: 是否启用 AI Card 流式响应
|
|
18
19
|
* - maxFileSizeMB: 媒体文件大小限制 (MB)
|
|
19
20
|
* - inboundMedia: 入站媒体归档与保留策略
|
|
@@ -39,6 +40,8 @@ declare const DingtalkConfigSchema: z.ZodObject<{
|
|
|
39
40
|
historyLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
40
41
|
/** 文本分块大小限制 (钉钉单条消息最大 4000 字符) */
|
|
41
42
|
textChunkLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
43
|
+
/** 长任务提醒延迟(毫秒),0 表示关闭 */
|
|
44
|
+
longTaskNoticeDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
42
45
|
/** 是否启用 AI Card 流式响应 */
|
|
43
46
|
enableAICard: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
44
47
|
/** Gateway auth token(Bearer) */
|
|
@@ -65,6 +68,7 @@ declare const DingtalkConfigSchema: z.ZodObject<{
|
|
|
65
68
|
requireMention: boolean;
|
|
66
69
|
historyLimit: number;
|
|
67
70
|
textChunkLimit: number;
|
|
71
|
+
longTaskNoticeDelayMs: number;
|
|
68
72
|
enableAICard: boolean;
|
|
69
73
|
maxFileSizeMB: number;
|
|
70
74
|
clientId?: string | undefined;
|
|
@@ -88,6 +92,7 @@ declare const DingtalkConfigSchema: z.ZodObject<{
|
|
|
88
92
|
groupAllowFrom?: string[] | undefined;
|
|
89
93
|
historyLimit?: number | undefined;
|
|
90
94
|
textChunkLimit?: number | undefined;
|
|
95
|
+
longTaskNoticeDelayMs?: number | undefined;
|
|
91
96
|
enableAICard?: boolean | undefined;
|
|
92
97
|
gatewayToken?: string | undefined;
|
|
93
98
|
gatewayPassword?: string | undefined;
|
|
@@ -293,6 +298,10 @@ declare const dingtalkPlugin: {
|
|
|
293
298
|
type: string;
|
|
294
299
|
minimum: number;
|
|
295
300
|
};
|
|
301
|
+
longTaskNoticeDelayMs: {
|
|
302
|
+
type: string;
|
|
303
|
+
minimum: number;
|
|
304
|
+
};
|
|
296
305
|
enableAICard: {
|
|
297
306
|
type: string;
|
|
298
307
|
};
|
|
@@ -751,6 +760,10 @@ declare const plugin: {
|
|
|
751
760
|
type: string;
|
|
752
761
|
minimum: number;
|
|
753
762
|
};
|
|
763
|
+
longTaskNoticeDelayMs: {
|
|
764
|
+
type: string;
|
|
765
|
+
minimum: number;
|
|
766
|
+
};
|
|
754
767
|
};
|
|
755
768
|
};
|
|
756
769
|
/**
|
package/dist/index.js
CHANGED
|
@@ -4236,6 +4236,8 @@ var DingtalkConfigSchema = external_exports.object({
|
|
|
4236
4236
|
historyLimit: external_exports.number().int().min(0).optional().default(10),
|
|
4237
4237
|
/** 文本分块大小限制 (钉钉单条消息最大 4000 字符) */
|
|
4238
4238
|
textChunkLimit: external_exports.number().int().positive().optional().default(4e3),
|
|
4239
|
+
/** 长任务提醒延迟(毫秒),0 表示关闭 */
|
|
4240
|
+
longTaskNoticeDelayMs: external_exports.number().int().min(0).optional().default(3e4),
|
|
4239
4241
|
/** 是否启用 AI Card 流式响应 */
|
|
4240
4242
|
enableAICard: external_exports.boolean().optional().default(true),
|
|
4241
4243
|
/** Gateway auth token(Bearer) */
|
|
@@ -7910,6 +7912,76 @@ async function finishAICard(card, content, log) {
|
|
|
7910
7912
|
}
|
|
7911
7913
|
|
|
7912
7914
|
// src/bot-handler.ts
|
|
7915
|
+
var LONG_TASK_NOTICE_TEXT = "\u4EFB\u52A1\u5904\u7406\u65F6\u95F4\u8F83\u957F\uFF0C\u8BF7\u7A0D\u7B49\uFF0C\u6211\u8FD8\u5728\u7EE7\u7EED\u5904\u7406\u3002";
|
|
7916
|
+
var DEFAULT_LONG_TASK_NOTICE_DELAY_MS = 3e4;
|
|
7917
|
+
function startLongTaskNoticeTimer(params) {
|
|
7918
|
+
const { delayMs, logger, sendNotice } = params;
|
|
7919
|
+
let completed = false;
|
|
7920
|
+
let timer = null;
|
|
7921
|
+
const clear = () => {
|
|
7922
|
+
if (!timer) return;
|
|
7923
|
+
clearTimeout(timer);
|
|
7924
|
+
timer = null;
|
|
7925
|
+
};
|
|
7926
|
+
if (delayMs > 0) {
|
|
7927
|
+
timer = setTimeout(() => {
|
|
7928
|
+
if (completed) return;
|
|
7929
|
+
completed = true;
|
|
7930
|
+
timer = null;
|
|
7931
|
+
void sendNotice().catch((err) => {
|
|
7932
|
+
logger.warn(`send long-task notice failed: ${String(err)}`);
|
|
7933
|
+
});
|
|
7934
|
+
}, delayMs);
|
|
7935
|
+
timer.unref?.();
|
|
7936
|
+
} else {
|
|
7937
|
+
completed = true;
|
|
7938
|
+
}
|
|
7939
|
+
return {
|
|
7940
|
+
markReplyDelivered: () => {
|
|
7941
|
+
if (completed) return;
|
|
7942
|
+
completed = true;
|
|
7943
|
+
clear();
|
|
7944
|
+
},
|
|
7945
|
+
dispose: () => {
|
|
7946
|
+
completed = true;
|
|
7947
|
+
clear();
|
|
7948
|
+
}
|
|
7949
|
+
};
|
|
7950
|
+
}
|
|
7951
|
+
var pendingLongTaskNotices = /* @__PURE__ */ new Map();
|
|
7952
|
+
function armLongTaskNoticeForSession(params) {
|
|
7953
|
+
const { sessionKey, delayMs, logger, sendNotice } = params;
|
|
7954
|
+
pendingLongTaskNotices.get(sessionKey)?.dispose();
|
|
7955
|
+
logger.debug?.(`[long-task] armed sessionKey=${sessionKey} delayMs=${delayMs}`);
|
|
7956
|
+
const controller = startLongTaskNoticeTimer({
|
|
7957
|
+
delayMs,
|
|
7958
|
+
logger,
|
|
7959
|
+
sendNotice: async () => {
|
|
7960
|
+
pendingLongTaskNotices.delete(sessionKey);
|
|
7961
|
+
logger.debug?.(`[long-task] firing sessionKey=${sessionKey}`);
|
|
7962
|
+
await sendNotice();
|
|
7963
|
+
}
|
|
7964
|
+
});
|
|
7965
|
+
const wrapped = {
|
|
7966
|
+
markReplyDelivered: () => {
|
|
7967
|
+
const active = pendingLongTaskNotices.get(sessionKey);
|
|
7968
|
+
if (active !== wrapped) return;
|
|
7969
|
+
pendingLongTaskNotices.delete(sessionKey);
|
|
7970
|
+
logger.debug?.(`[long-task] cleared sessionKey=${sessionKey} reason=reply-delivered`);
|
|
7971
|
+
controller.markReplyDelivered();
|
|
7972
|
+
},
|
|
7973
|
+
dispose: () => {
|
|
7974
|
+
const active = pendingLongTaskNotices.get(sessionKey);
|
|
7975
|
+
if (active === wrapped) {
|
|
7976
|
+
pendingLongTaskNotices.delete(sessionKey);
|
|
7977
|
+
logger.debug?.(`[long-task] cleared sessionKey=${sessionKey} reason=disposed`);
|
|
7978
|
+
}
|
|
7979
|
+
controller.dispose();
|
|
7980
|
+
}
|
|
7981
|
+
};
|
|
7982
|
+
pendingLongTaskNotices.set(sessionKey, wrapped);
|
|
7983
|
+
return wrapped;
|
|
7984
|
+
}
|
|
7913
7985
|
function buildGatewayUserContent(inboundCtx, logger) {
|
|
7914
7986
|
const base = inboundCtx.CommandBody ?? inboundCtx.Body ?? "";
|
|
7915
7987
|
const { base: baseText, prompt } = splitCronHiddenPrompt(base);
|
|
@@ -8653,202 +8725,226 @@ async function handleDingtalkMessage(params) {
|
|
|
8653
8725
|
logger.warn("AI Card creation failed, falling back to normal message");
|
|
8654
8726
|
}
|
|
8655
8727
|
}
|
|
8656
|
-
const
|
|
8657
|
-
const
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8728
|
+
const targetId = isGroup ? ctx.conversationId : ctx.senderId;
|
|
8729
|
+
const chatType = isGroup ? "group" : "direct";
|
|
8730
|
+
const routeSessionKeyRaw = route.sessionKey;
|
|
8731
|
+
const routeSessionKey = typeof routeSessionKeyRaw === "string" && routeSessionKeyRaw.trim() ? routeSessionKeyRaw : `dingtalk:${chatType}:${targetId}`;
|
|
8732
|
+
const longTaskNotice = armLongTaskNoticeForSession({
|
|
8733
|
+
sessionKey: routeSessionKey,
|
|
8734
|
+
delayMs: dingtalkCfgResolved.longTaskNoticeDelayMs ?? DEFAULT_LONG_TASK_NOTICE_DELAY_MS,
|
|
8735
|
+
logger,
|
|
8736
|
+
sendNotice: async () => {
|
|
8737
|
+
await sendMessageDingtalk({
|
|
8738
|
+
cfg: dingtalkCfgResolved,
|
|
8739
|
+
to: targetId,
|
|
8740
|
+
text: LONG_TASK_NOTICE_TEXT,
|
|
8741
|
+
chatType
|
|
8742
|
+
});
|
|
8662
8743
|
}
|
|
8663
|
-
)
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
hasText: typeof payload.text === "string",
|
|
8672
|
-
mediaCount: Array.isArray(payload.mediaUrls) ? payload.mediaUrls.length : payload.mediaUrl ? 1 : 0
|
|
8673
|
-
})}`
|
|
8674
|
-
);
|
|
8675
|
-
const targetId = isGroup ? ctx.conversationId : ctx.senderId;
|
|
8676
|
-
const chatType = isGroup ? "group" : "direct";
|
|
8677
|
-
let sent = false;
|
|
8678
|
-
const sendMediaWithFallback = async (mediaUrl) => {
|
|
8679
|
-
try {
|
|
8680
|
-
await sendMediaDingtalk({
|
|
8681
|
-
cfg: dingtalkCfgResolved,
|
|
8682
|
-
to: targetId,
|
|
8683
|
-
mediaUrl,
|
|
8684
|
-
chatType
|
|
8685
|
-
});
|
|
8686
|
-
sent = true;
|
|
8687
|
-
} catch (err) {
|
|
8688
|
-
logger.error(
|
|
8689
|
-
`[reply] sendMediaDingtalk failed (target=${JSON.stringify(resolvedTargetMeta)}): ${String(err)}`
|
|
8690
|
-
);
|
|
8691
|
-
const fallbackText = `\u{1F4CE} ${mediaUrl}`;
|
|
8692
|
-
await sendMessageDingtalk({
|
|
8693
|
-
cfg: dingtalkCfgResolved,
|
|
8694
|
-
to: targetId,
|
|
8695
|
-
text: fallbackText,
|
|
8696
|
-
chatType
|
|
8697
|
-
});
|
|
8698
|
-
sent = true;
|
|
8744
|
+
});
|
|
8745
|
+
try {
|
|
8746
|
+
const textApi = coreChannel?.text;
|
|
8747
|
+
const textChunkLimitResolved = textApi?.resolveTextChunkLimit?.(
|
|
8748
|
+
{
|
|
8749
|
+
cfg,
|
|
8750
|
+
channel: "dingtalk",
|
|
8751
|
+
defaultLimit: dingtalkCfgResolved.textChunkLimit ?? 4e3
|
|
8699
8752
|
}
|
|
8753
|
+
) ?? (dingtalkCfgResolved.textChunkLimit ?? 4e3);
|
|
8754
|
+
const chunkMode = textApi?.resolveChunkMode?.(cfg, "dingtalk");
|
|
8755
|
+
const tableMode = "bullets";
|
|
8756
|
+
const deliver = async (payload, info) => {
|
|
8757
|
+
logger.debug(
|
|
8758
|
+
`[reply] meta=${JSON.stringify({
|
|
8759
|
+
...resolvedTargetMeta,
|
|
8760
|
+
kind: info?.kind ?? "unknown",
|
|
8761
|
+
hasText: typeof payload.text === "string",
|
|
8762
|
+
mediaCount: Array.isArray(payload.mediaUrls) ? payload.mediaUrls.length : payload.mediaUrl ? 1 : 0
|
|
8763
|
+
})}`
|
|
8764
|
+
);
|
|
8765
|
+
let sent = false;
|
|
8766
|
+
const sendMediaWithFallback = async (mediaUrl) => {
|
|
8767
|
+
try {
|
|
8768
|
+
await sendMediaDingtalk({
|
|
8769
|
+
cfg: dingtalkCfgResolved,
|
|
8770
|
+
to: targetId,
|
|
8771
|
+
mediaUrl,
|
|
8772
|
+
chatType
|
|
8773
|
+
});
|
|
8774
|
+
sent = true;
|
|
8775
|
+
longTaskNotice.markReplyDelivered();
|
|
8776
|
+
} catch (err) {
|
|
8777
|
+
logger.error(
|
|
8778
|
+
`[reply] sendMediaDingtalk failed (target=${JSON.stringify(resolvedTargetMeta)}): ${String(err)}`
|
|
8779
|
+
);
|
|
8780
|
+
const fallbackText = `\u{1F4CE} ${mediaUrl}`;
|
|
8781
|
+
await sendMessageDingtalk({
|
|
8782
|
+
cfg: dingtalkCfgResolved,
|
|
8783
|
+
to: targetId,
|
|
8784
|
+
text: fallbackText,
|
|
8785
|
+
chatType
|
|
8786
|
+
});
|
|
8787
|
+
sent = true;
|
|
8788
|
+
longTaskNotice.markReplyDelivered();
|
|
8789
|
+
}
|
|
8790
|
+
};
|
|
8791
|
+
const payloadMediaUrls = payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : []);
|
|
8792
|
+
const rawText = payload.text ?? "";
|
|
8793
|
+
const { mediaUrls: mediaFromLines } = extractMediaLinesFromText({
|
|
8794
|
+
text: rawText,
|
|
8795
|
+
logger
|
|
8796
|
+
});
|
|
8797
|
+
const { mediaUrls: localMediaFromText } = extractLocalMediaFromText({
|
|
8798
|
+
text: rawText,
|
|
8799
|
+
logger
|
|
8800
|
+
});
|
|
8801
|
+
const mediaQueue = [];
|
|
8802
|
+
const seenMedia = /* @__PURE__ */ new Set();
|
|
8803
|
+
const addMedia = (value) => {
|
|
8804
|
+
const trimmed = value?.trim();
|
|
8805
|
+
if (!trimmed) return;
|
|
8806
|
+
if (seenMedia.has(trimmed)) return;
|
|
8807
|
+
seenMedia.add(trimmed);
|
|
8808
|
+
mediaQueue.push(trimmed);
|
|
8809
|
+
};
|
|
8810
|
+
for (const url of payloadMediaUrls) addMedia(url);
|
|
8811
|
+
for (const url of mediaFromLines) addMedia(url);
|
|
8812
|
+
for (const url of localMediaFromText) addMedia(url);
|
|
8813
|
+
const converted = textApi?.convertMarkdownTables?.(
|
|
8814
|
+
rawText,
|
|
8815
|
+
tableMode
|
|
8816
|
+
) ?? rawText;
|
|
8817
|
+
const hasText = converted.trim().length > 0;
|
|
8818
|
+
if (hasText) {
|
|
8819
|
+
const chunks = textApi?.chunkTextWithMode && typeof textChunkLimitResolved === "number" && textChunkLimitResolved > 0 ? textApi.chunkTextWithMode(converted, textChunkLimitResolved, chunkMode) : [converted];
|
|
8820
|
+
for (const chunk of chunks) {
|
|
8821
|
+
await sendMessageDingtalk({
|
|
8822
|
+
cfg: dingtalkCfgResolved,
|
|
8823
|
+
to: targetId,
|
|
8824
|
+
text: chunk,
|
|
8825
|
+
chatType
|
|
8826
|
+
});
|
|
8827
|
+
sent = true;
|
|
8828
|
+
longTaskNotice.markReplyDelivered();
|
|
8829
|
+
}
|
|
8830
|
+
}
|
|
8831
|
+
for (const mediaUrl of mediaQueue) {
|
|
8832
|
+
await sendMediaWithFallback(mediaUrl);
|
|
8833
|
+
}
|
|
8834
|
+
if (!hasText && mediaQueue.length === 0) {
|
|
8835
|
+
return false;
|
|
8836
|
+
}
|
|
8837
|
+
return sent;
|
|
8700
8838
|
};
|
|
8701
|
-
const
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
const
|
|
8708
|
-
|
|
8709
|
-
logger
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8839
|
+
const humanDelay = replyApi?.resolveHumanDelayConfig?.(
|
|
8840
|
+
cfg,
|
|
8841
|
+
route?.agentId
|
|
8842
|
+
);
|
|
8843
|
+
const createDispatcherWithTyping = replyApi?.createReplyDispatcherWithTyping;
|
|
8844
|
+
const createDispatcher = replyApi?.createReplyDispatcher;
|
|
8845
|
+
const dispatchReplyWithDispatcher = replyApi?.dispatchReplyWithDispatcher;
|
|
8846
|
+
if (dispatchReplyWithDispatcher) {
|
|
8847
|
+
logger.debug(
|
|
8848
|
+
`[dispatch] direct=${JSON.stringify({
|
|
8849
|
+
sessionKey: route?.sessionKey,
|
|
8850
|
+
...resolvedTargetMeta
|
|
8851
|
+
})}`
|
|
8852
|
+
);
|
|
8853
|
+
const deliveryState = { delivered: false, skippedNonSilent: 0 };
|
|
8854
|
+
const result2 = await dispatchReplyWithDispatcher({
|
|
8855
|
+
ctx: finalCtx,
|
|
8856
|
+
cfg,
|
|
8857
|
+
dispatcherOptions: {
|
|
8858
|
+
deliver: async (payload, info) => {
|
|
8859
|
+
const didSend = await deliver(
|
|
8860
|
+
payload,
|
|
8861
|
+
info
|
|
8862
|
+
);
|
|
8863
|
+
if (didSend) {
|
|
8864
|
+
deliveryState.delivered = true;
|
|
8865
|
+
}
|
|
8866
|
+
},
|
|
8867
|
+
humanDelay,
|
|
8868
|
+
onSkip: (_payload, info) => {
|
|
8869
|
+
if (info.reason !== "silent") {
|
|
8870
|
+
deliveryState.skippedNonSilent += 1;
|
|
8871
|
+
}
|
|
8872
|
+
},
|
|
8873
|
+
onError: (err, info) => {
|
|
8874
|
+
logger.error(`${info.kind} reply failed: ${String(err)}`);
|
|
8875
|
+
}
|
|
8876
|
+
}
|
|
8877
|
+
});
|
|
8878
|
+
if (!deliveryState.delivered && deliveryState.skippedNonSilent > 0) {
|
|
8731
8879
|
await sendMessageDingtalk({
|
|
8732
8880
|
cfg: dingtalkCfgResolved,
|
|
8733
8881
|
to: targetId,
|
|
8734
|
-
text:
|
|
8882
|
+
text: "No response generated. Please try again.",
|
|
8735
8883
|
chatType
|
|
8736
8884
|
});
|
|
8737
|
-
|
|
8885
|
+
longTaskNotice.markReplyDelivered();
|
|
8738
8886
|
}
|
|
8887
|
+
const counts2 = result2?.counts;
|
|
8888
|
+
const queuedFinal2 = result2?.queuedFinal;
|
|
8889
|
+
logger.debug(
|
|
8890
|
+
`dispatch complete (queuedFinal=${typeof queuedFinal2 === "boolean" ? queuedFinal2 : "unknown"}, replies=${counts2?.final ?? 0})`
|
|
8891
|
+
);
|
|
8892
|
+
return;
|
|
8739
8893
|
}
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8894
|
+
const dispatcherResult = createDispatcherWithTyping ? createDispatcherWithTyping({
|
|
8895
|
+
deliver: async (payload, info) => {
|
|
8896
|
+
await deliver(payload, info);
|
|
8897
|
+
},
|
|
8898
|
+
humanDelay,
|
|
8899
|
+
onError: (err, info) => {
|
|
8900
|
+
logger.error(`${info.kind} reply failed: ${String(err)}`);
|
|
8901
|
+
}
|
|
8902
|
+
}) : {
|
|
8903
|
+
dispatcher: createDispatcher?.({
|
|
8904
|
+
deliver: async (payload, info) => {
|
|
8905
|
+
await deliver(payload, info);
|
|
8906
|
+
},
|
|
8907
|
+
humanDelay,
|
|
8908
|
+
onError: (err, info) => {
|
|
8909
|
+
logger.error(`${info.kind} reply failed: ${String(err)}`);
|
|
8910
|
+
}
|
|
8911
|
+
}),
|
|
8912
|
+
replyOptions: {},
|
|
8913
|
+
markDispatchIdle: () => void 0
|
|
8914
|
+
};
|
|
8915
|
+
const dispatcher = dispatcherResult?.dispatcher;
|
|
8916
|
+
if (!dispatcher) {
|
|
8917
|
+
logger.debug("dispatcher not available, skipping dispatch");
|
|
8918
|
+
return;
|
|
8745
8919
|
}
|
|
8746
|
-
return sent;
|
|
8747
|
-
};
|
|
8748
|
-
const humanDelay = replyApi?.resolveHumanDelayConfig?.(
|
|
8749
|
-
cfg,
|
|
8750
|
-
route?.agentId
|
|
8751
|
-
);
|
|
8752
|
-
const createDispatcherWithTyping = replyApi?.createReplyDispatcherWithTyping;
|
|
8753
|
-
const createDispatcher = replyApi?.createReplyDispatcher;
|
|
8754
|
-
const dispatchReplyWithBufferedBlockDispatcher = replyApi?.dispatchReplyWithBufferedBlockDispatcher;
|
|
8755
|
-
if (dispatchReplyWithBufferedBlockDispatcher) {
|
|
8756
8920
|
logger.debug(
|
|
8757
|
-
`[dispatch]
|
|
8921
|
+
`[dispatch] legacy=${JSON.stringify({
|
|
8758
8922
|
sessionKey: route?.sessionKey,
|
|
8759
8923
|
...resolvedTargetMeta
|
|
8760
8924
|
})}`
|
|
8761
8925
|
);
|
|
8762
|
-
const
|
|
8763
|
-
|
|
8926
|
+
const dispatchReplyFromConfig = replyApi?.dispatchReplyFromConfig;
|
|
8927
|
+
if (!dispatchReplyFromConfig) {
|
|
8928
|
+
logger.debug("dispatchReplyFromConfig not available");
|
|
8929
|
+
return;
|
|
8930
|
+
}
|
|
8931
|
+
const result = await dispatchReplyFromConfig({
|
|
8764
8932
|
ctx: finalCtx,
|
|
8765
8933
|
cfg,
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
const didSend = await deliver(
|
|
8769
|
-
payload,
|
|
8770
|
-
info
|
|
8771
|
-
);
|
|
8772
|
-
if (didSend) {
|
|
8773
|
-
deliveryState.delivered = true;
|
|
8774
|
-
}
|
|
8775
|
-
},
|
|
8776
|
-
humanDelay,
|
|
8777
|
-
onSkip: (_payload, info) => {
|
|
8778
|
-
if (info.reason !== "silent") {
|
|
8779
|
-
deliveryState.skippedNonSilent += 1;
|
|
8780
|
-
}
|
|
8781
|
-
},
|
|
8782
|
-
onError: (err, info) => {
|
|
8783
|
-
logger.error(`${info.kind} reply failed: ${String(err)}`);
|
|
8784
|
-
}
|
|
8785
|
-
}
|
|
8934
|
+
dispatcher,
|
|
8935
|
+
replyOptions: dispatcherResult?.replyOptions ?? {}
|
|
8786
8936
|
});
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
|
|
8790
|
-
|
|
8791
|
-
text: "No response generated. Please try again.",
|
|
8792
|
-
chatType: isGroup ? "group" : "direct"
|
|
8793
|
-
});
|
|
8794
|
-
}
|
|
8795
|
-
const counts2 = result2?.counts;
|
|
8796
|
-
const queuedFinal2 = result2?.queuedFinal;
|
|
8937
|
+
const markDispatchIdle = dispatcherResult?.markDispatchIdle;
|
|
8938
|
+
markDispatchIdle?.();
|
|
8939
|
+
const counts = result?.counts;
|
|
8940
|
+
const queuedFinal = result?.queuedFinal;
|
|
8797
8941
|
logger.debug(
|
|
8798
|
-
`dispatch complete (queuedFinal=${typeof
|
|
8942
|
+
`dispatch complete (queuedFinal=${typeof queuedFinal === "boolean" ? queuedFinal : "unknown"}, replies=${counts?.final ?? 0})`
|
|
8799
8943
|
);
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
deliver: async (payload, info) => {
|
|
8804
|
-
await deliver(payload, info);
|
|
8805
|
-
},
|
|
8806
|
-
humanDelay,
|
|
8807
|
-
onError: (err, info) => {
|
|
8808
|
-
logger.error(`${info.kind} reply failed: ${String(err)}`);
|
|
8809
|
-
}
|
|
8810
|
-
}) : {
|
|
8811
|
-
dispatcher: createDispatcher?.({
|
|
8812
|
-
deliver: async (payload, info) => {
|
|
8813
|
-
await deliver(payload, info);
|
|
8814
|
-
},
|
|
8815
|
-
humanDelay,
|
|
8816
|
-
onError: (err, info) => {
|
|
8817
|
-
logger.error(`${info.kind} reply failed: ${String(err)}`);
|
|
8818
|
-
}
|
|
8819
|
-
}),
|
|
8820
|
-
replyOptions: {},
|
|
8821
|
-
markDispatchIdle: () => void 0
|
|
8822
|
-
};
|
|
8823
|
-
const dispatcher = dispatcherResult?.dispatcher;
|
|
8824
|
-
if (!dispatcher) {
|
|
8825
|
-
logger.debug("dispatcher not available, skipping dispatch");
|
|
8826
|
-
return;
|
|
8827
|
-
}
|
|
8828
|
-
logger.debug(
|
|
8829
|
-
`[dispatch] standard=${JSON.stringify({
|
|
8830
|
-
sessionKey: route?.sessionKey,
|
|
8831
|
-
...resolvedTargetMeta
|
|
8832
|
-
})}`
|
|
8833
|
-
);
|
|
8834
|
-
const dispatchReplyFromConfig = replyApi?.dispatchReplyFromConfig;
|
|
8835
|
-
if (!dispatchReplyFromConfig) {
|
|
8836
|
-
logger.debug("dispatchReplyFromConfig not available");
|
|
8837
|
-
return;
|
|
8944
|
+
} catch (err) {
|
|
8945
|
+
longTaskNotice.dispose();
|
|
8946
|
+
throw err;
|
|
8838
8947
|
}
|
|
8839
|
-
const result = await dispatchReplyFromConfig({
|
|
8840
|
-
ctx: finalCtx,
|
|
8841
|
-
cfg,
|
|
8842
|
-
dispatcher,
|
|
8843
|
-
replyOptions: dispatcherResult?.replyOptions ?? {}
|
|
8844
|
-
});
|
|
8845
|
-
const markDispatchIdle = dispatcherResult?.markDispatchIdle;
|
|
8846
|
-
markDispatchIdle?.();
|
|
8847
|
-
const counts = result?.counts;
|
|
8848
|
-
const queuedFinal = result?.queuedFinal;
|
|
8849
|
-
logger.debug(
|
|
8850
|
-
`dispatch complete (queuedFinal=${typeof queuedFinal === "boolean" ? queuedFinal : "unknown"}, replies=${counts?.final ?? 0})`
|
|
8851
|
-
);
|
|
8852
8948
|
} catch (err) {
|
|
8853
8949
|
logger.error(
|
|
8854
8950
|
`failed to dispatch message (target=${JSON.stringify(inboundTargetMeta)}): ${String(err)}`
|
|
@@ -9681,6 +9777,7 @@ var dingtalkPlugin = {
|
|
|
9681
9777
|
groupAllowFrom: { type: "array", items: { type: "string" } },
|
|
9682
9778
|
historyLimit: { type: "integer", minimum: 0 },
|
|
9683
9779
|
textChunkLimit: { type: "integer", minimum: 1 },
|
|
9780
|
+
longTaskNoticeDelayMs: { type: "integer", minimum: 0 },
|
|
9684
9781
|
enableAICard: { type: "boolean" },
|
|
9685
9782
|
gatewayToken: { type: "string" },
|
|
9686
9783
|
gatewayPassword: { type: "string" },
|
|
@@ -9861,7 +9958,8 @@ var plugin = {
|
|
|
9861
9958
|
allowFrom: { type: "array", items: { type: "string" } },
|
|
9862
9959
|
groupAllowFrom: { type: "array", items: { type: "string" } },
|
|
9863
9960
|
historyLimit: { type: "integer", minimum: 0 },
|
|
9864
|
-
textChunkLimit: { type: "integer", minimum: 1 }
|
|
9961
|
+
textChunkLimit: { type: "integer", minimum: 1 },
|
|
9962
|
+
longTaskNoticeDelayMs: { type: "integer", minimum: 0 }
|
|
9865
9963
|
}
|
|
9866
9964
|
},
|
|
9867
9965
|
/**
|