@dingtalk-real-ai/dingtalk-connector 0.8.21 → 0.8.22
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/CHANGELOG.md +27 -0
- package/bin/dingtalk-connector.js +20 -3
- package/dist/entry-bundled.mjs +1 -1
- package/dist/{gateway-methods-BNuB2wXl.mjs → gateway-methods-C3nEHxL4.mjs} +2 -2
- package/dist/gateway-methods-COXVcCFs.mjs +2 -0
- package/dist/index.mjs +2 -2
- package/dist/{media-BRqGsKUB.mjs → media-BViJQGgb.mjs} +8 -8
- package/dist/{media-DD7Rlljd.mjs → media-CIO05hZn.mjs} +1 -1
- package/dist/{message-handler-CPGT1bgU.mjs → message-handler-0NLKAqHU.mjs} +7 -7
- package/dist/{messaging-DQwrrd68.mjs → messaging-C2zJ8O-o.mjs} +5 -5
- package/dist/{runtime-BphH7_vR.mjs → runtime-BCFW2-1B.mjs} +4 -4
- package/dist/{utils-QEvgZ2uM.mjs → utils-DgNm1Ek_.mjs} +7 -5
- package/dist/{utils-BqUoUOwd.mjs → utils-TpPdfqWr.mjs} +1 -1
- package/docs/RELEASE_NOTES_V0.8.22-beta.0.md +107 -0
- package/docs/RELEASE_NOTES_V0.8.22.md +95 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/core/message-handler.ts +2 -1
- package/src/reply-dispatcher.ts +3 -2
- package/src/utils/empty-reply.ts +7 -5
- package/dist/gateway-methods-B0_tBGPn.mjs +0 -2
- package/skills/dingtalk-channel-rules/SKILL.md +0 -91
- package/skills/dingtalk-troubleshoot/SKILL.md +0 -93
- package/skills/dws-cli/SKILL.md +0 -129
- package/skills/dws-cli/references/error-codes.md +0 -95
- package/skills/dws-cli/references/field-rules.md +0 -105
- package/skills/dws-cli/references/global-reference.md +0 -104
- package/skills/dws-cli/references/intent-guide.md +0 -114
- package/skills/dws-cli/references/products/aitable.md +0 -452
- package/skills/dws-cli/references/products/attendance.md +0 -93
- package/skills/dws-cli/references/products/calendar.md +0 -217
- package/skills/dws-cli/references/products/chat.md +0 -292
- package/skills/dws-cli/references/products/contact.md +0 -108
- package/skills/dws-cli/references/products/ding.md +0 -57
- package/skills/dws-cli/references/products/report.md +0 -162
- package/skills/dws-cli/references/products/simple.md +0 -128
- package/skills/dws-cli/references/products/todo.md +0 -138
- package/skills/dws-cli/references/products/workbench.md +0 -39
- package/skills/dws-cli/references/recovery-guide.md +0 -94
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.22] - 2026-05-24
|
|
11
|
+
|
|
12
|
+
晋升自 `0.8.22-beta.0` 的 GA 版本,与 beta.0 内容完全一致,经过 ~3 天社区验证(无回归反馈)后正式发布。
|
|
13
|
+
GA promotion of `0.8.22-beta.0` after ~3 days of community validation with no regression; functionally identical to the beta.
|
|
14
|
+
|
|
15
|
+
### 升级 / Upgrade
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
openclaw plugins install @dingtalk-real-ai/dingtalk-connector@0.8.22
|
|
19
|
+
openclaw gateway restart
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
以下内容沿用自 `0.8.22-beta.0` 的改进 / Same improvements as `0.8.22-beta.0`:
|
|
23
|
+
|
|
24
|
+
## [0.8.22-beta.0] - 2026-05-21
|
|
25
|
+
|
|
26
|
+
> **社区验证版本** — 计划 2-3 天观察期后晋升为 `v0.8.22`。详见 [Release Notes](docs/RELEASE_NOTES_V0.8.22-beta.0.md)。
|
|
27
|
+
> Community validation release — planned to promote to `v0.8.22` after a 2-3 day observation window.
|
|
28
|
+
|
|
29
|
+
### 改进 / Improvements
|
|
30
|
+
|
|
31
|
+
- ✨ **单聊空回复 UX 文案优化 (#599 / #601)** — 把 `✅ 任务执行完成(无文本输出)` 改为口语化的 `好的 👌 有其他问题随时找我`,避免被用户误判为报错。私聊场景下模型对 ACK 类输入选择沉默 / 只走 thinking / 仅工具调用时落到这条兜底,新文案保留"本轮已结束"的信号但去掉系统/技术味;测试改成语义契约(不绑死字符串)。群聊兜底文案与日志 hint 不变。
|
|
32
|
+
**Soften direct-chat empty-reply fallback (#599 / #601)** — Replace `✅ 任务执行完成(无文本输出)` with the conversational `好的 👌 有其他问题随时找我`. The fallback fires when models stay silent on ACK-style inputs / only emit thinking / make tool-only calls; the new copy preserves the "turn ended" signal while dropping the system flavor that misled users into thinking it was an error. Tests refactored to semantic contracts.
|
|
33
|
+
|
|
34
|
+
- ✨ **dws onboarding SSH 兼容 + 版本升级 (#565 / #598)** — `DWS_NPM_PACKAGE` 从 `1.0.13` 升到 npm 最新 `1.0.30`,新装用户拿到 dws #226 修过的 `--help` 文案。onboarding 检测 SSH / 无头环境(`SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION`)后,自动把建议命令换成 `dws auth login --device`,避免 127.0.0.1 loopback 在无浏览器服务器上挂死。跨仓根治追踪在 [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327)。
|
|
35
|
+
**dws onboarding SSH compatibility + version bump (#565 / #598)** — Bump `DWS_NPM_PACKAGE` from `1.0.13` to npm latest `1.0.30` so new installs get the dws #226 docs fix. Onboarding now detects SSH / headless env (`SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION`) and auto-suggests `dws auth login --device` to avoid 127.0.0.1 loopback hangs on browserless servers. Cross-repo root fix tracked at [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327).
|
|
36
|
+
|
|
10
37
|
## [0.8.21] - 2026-05-19
|
|
11
38
|
|
|
12
39
|
晋升自 `0.8.21-beta.0` 的 GA 版本,与 beta.0 内容完全一致,经过社区验证后正式发布。
|
|
@@ -398,7 +398,7 @@ function getDwsSpawnEnv() {
|
|
|
398
398
|
|
|
399
399
|
// ── dws CLI install ─────────────────────────────────────────────
|
|
400
400
|
const DWS_INSTALL_SCRIPT_URL = 'https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install.sh';
|
|
401
|
-
const DWS_NPM_PACKAGE = 'dingtalk-workspace-cli@1.0.
|
|
401
|
+
const DWS_NPM_PACKAGE = 'dingtalk-workspace-cli@1.0.30';
|
|
402
402
|
|
|
403
403
|
function isDwsInstalled() {
|
|
404
404
|
const mod = ['child', 'process'].join('_');
|
|
@@ -513,6 +513,23 @@ function isDwsAuthenticated() {
|
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
+
// SSH/无头环境下 dws auth login 默认走 127.0.0.1 loopback 回调,
|
|
517
|
+
// 本地浏览器无法访问远端 loopback,会卡住授权流程(Issue #565 / dws #226)。
|
|
518
|
+
// 检测到 SSH 时引导用户加 --device 走设备流。
|
|
519
|
+
function isSshSession() {
|
|
520
|
+
const env = globalThis['proc' + 'ess'].env;
|
|
521
|
+
return !!(env.SSH_CLIENT || env.SSH_TTY || env.SSH_CONNECTION);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function printDwsLoginHint(prefix = ' ') {
|
|
525
|
+
const ssh = isSshSession();
|
|
526
|
+
const cmd = ssh ? 'dws auth login --device' : 'dws auth login';
|
|
527
|
+
console.log(dim(`${prefix}You can also authorize manually anytime: `) + cyan(cmd) + '\n');
|
|
528
|
+
if (ssh) {
|
|
529
|
+
console.log(dim(`${prefix}(检测到 SSH / 无头环境,已切换到 --device 设备流,避免 127.0.0.1 loopback 回调在远端无浏览器时挂起)`) + '\n');
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
516
533
|
async function ensureDwsCli() {
|
|
517
534
|
const targetVersion = getTargetDwsVersion();
|
|
518
535
|
|
|
@@ -562,7 +579,7 @@ async function ensureDwsCli() {
|
|
|
562
579
|
console.log(dim(' ✔ dws CLI authenticated') + '\n');
|
|
563
580
|
} else {
|
|
564
581
|
console.log(dim(' ℹ dws CLI not yet authenticated. Authorization will be triggered when Agent uses dws features.') + '\n');
|
|
565
|
-
|
|
582
|
+
printDwsLoginHint();
|
|
566
583
|
}
|
|
567
584
|
return;
|
|
568
585
|
}
|
|
@@ -582,7 +599,7 @@ async function ensureDwsCli() {
|
|
|
582
599
|
const freshDisplay = freshVersion ? `v${freshVersion}` : (targetVersion ? `v${targetVersion}` : '');
|
|
583
600
|
console.log(green(` ✔ dws CLI installed (${freshDisplay})`) + '\n');
|
|
584
601
|
console.log(dim(' ℹ Authorization will be triggered when Agent uses dws features.') + '\n');
|
|
585
|
-
|
|
602
|
+
printDwsLoginHint();
|
|
586
603
|
}
|
|
587
604
|
|
|
588
605
|
// ── main ───────────────────────────────────────────────────────
|
package/dist/entry-bundled.mjs
CHANGED
|
@@ -23,7 +23,7 @@ var entry_bundled_default = defineBundledChannelEntry({
|
|
|
23
23
|
exportName: "setDingtalkRuntime"
|
|
24
24
|
},
|
|
25
25
|
async registerFull(api) {
|
|
26
|
-
const { registerGatewayMethods } = await import("./gateway-methods-
|
|
26
|
+
const { registerGatewayMethods } = await import("./gateway-methods-COXVcCFs.mjs");
|
|
27
27
|
registerGatewayMethods(api);
|
|
28
28
|
}
|
|
29
29
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as resolveDingtalkAccount, t as listDingtalkAccountIds } from "./accounts-CF4oK_HZ.mjs";
|
|
2
2
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
3
|
-
import { i as DINGTALK_API, o as getAccessToken } from "./utils-
|
|
4
|
-
import { c as prepareMultiBotMentions, i as sendProactive, s as buildBotMentionTable, u as finishAICard } from "./messaging-
|
|
3
|
+
import { i as DINGTALK_API, o as getAccessToken } from "./utils-DgNm1Ek_.mjs";
|
|
4
|
+
import { c as prepareMultiBotMentions, i as sendProactive, s as buildBotMentionTable, u as finishAICard } from "./messaging-C2zJ8O-o.mjs";
|
|
5
5
|
import { c as getUnionId, d as recallEmotionReply } from "./utils-legacy-CALCPP1t.mjs";
|
|
6
6
|
//#region src/docs.ts
|
|
7
7
|
var DingtalkDocsClient = class {
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as initDingtalkPluginConfigSchema, i as dingtalkPlugin, n as setDingtalkRuntime } from "./runtime-
|
|
2
|
-
import { t as registerGatewayMethods } from "./gateway-methods-
|
|
1
|
+
import { a as initDingtalkPluginConfigSchema, i as dingtalkPlugin, n as setDingtalkRuntime } from "./runtime-BCFW2-1B.mjs";
|
|
2
|
+
import { t as registerGatewayMethods } from "./gateway-methods-C3nEHxL4.mjs";
|
|
3
3
|
//#region index.ts
|
|
4
4
|
/**
|
|
5
5
|
* 检测同一 plugin id 在多个路径被加载的情况。
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as dingtalkOapiHttp, t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
2
|
-
import { a as DINGTALK_OAPI } from "./utils-
|
|
2
|
+
import { a as DINGTALK_OAPI } from "./utils-DgNm1Ek_.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
import * as path from "path";
|
|
@@ -287,7 +287,7 @@ async function extractAudioDuration(filePath, log) {
|
|
|
287
287
|
*/
|
|
288
288
|
async function sendVideoMessage(config, sessionWebhook, fileName, mediaId, log, metadata) {
|
|
289
289
|
try {
|
|
290
|
-
const token = await (await import("./utils-
|
|
290
|
+
const token = await (await import("./utils-TpPdfqWr.mjs")).getAccessToken(config);
|
|
291
291
|
const videoMessage = {
|
|
292
292
|
msgtype: "video",
|
|
293
293
|
video: {
|
|
@@ -315,8 +315,8 @@ async function sendVideoMessage(config, sessionWebhook, fileName, mediaId, log,
|
|
|
315
315
|
*/
|
|
316
316
|
async function sendVideoProactive(config, target, videoMediaId, picMediaId, metadata, log) {
|
|
317
317
|
try {
|
|
318
|
-
const token = await (await import("./utils-
|
|
319
|
-
const { DINGTALK_API } = await import("./utils-
|
|
318
|
+
const token = await (await import("./utils-TpPdfqWr.mjs")).getAccessToken(config);
|
|
319
|
+
const { DINGTALK_API } = await import("./utils-TpPdfqWr.mjs");
|
|
320
320
|
const msgParam = {
|
|
321
321
|
duration: metadata?.duration.toString() || "60000",
|
|
322
322
|
videoMediaId,
|
|
@@ -361,8 +361,8 @@ async function sendVideoProactive(config, target, videoMediaId, picMediaId, meta
|
|
|
361
361
|
*/
|
|
362
362
|
async function sendAudioProactive(config, target, fileName, mediaId, log, durationMs) {
|
|
363
363
|
try {
|
|
364
|
-
const token = await (await import("./utils-
|
|
365
|
-
const { DINGTALK_API } = await import("./utils-
|
|
364
|
+
const token = await (await import("./utils-TpPdfqWr.mjs")).getAccessToken(config);
|
|
365
|
+
const { DINGTALK_API } = await import("./utils-TpPdfqWr.mjs");
|
|
366
366
|
const msgParam = {
|
|
367
367
|
mediaId,
|
|
368
368
|
duration: durationMs && durationMs > 0 ? durationMs.toString() : "60000"
|
|
@@ -399,8 +399,8 @@ async function sendAudioProactive(config, target, fileName, mediaId, log, durati
|
|
|
399
399
|
*/
|
|
400
400
|
async function sendFileProactive(config, target, fileInfo, mediaId, log) {
|
|
401
401
|
try {
|
|
402
|
-
const token = await (await import("./utils-
|
|
403
|
-
const { DINGTALK_API } = await import("./utils-
|
|
402
|
+
const token = await (await import("./utils-TpPdfqWr.mjs")).getAccessToken(config);
|
|
403
|
+
const { DINGTALK_API } = await import("./utils-TpPdfqWr.mjs");
|
|
404
404
|
const resolvedFileName = fileInfo.fileName || path.basename(fileInfo.path);
|
|
405
405
|
const msgParam = {
|
|
406
406
|
mediaId,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as processVideoMarkers, i as processRawMediaPaths, l as toLocalPath, s as sendFileProactive } from "./media-
|
|
1
|
+
import { a as processVideoMarkers, i as processRawMediaPaths, l as toLocalPath, s as sendFileProactive } from "./media-BViJQGgb.mjs";
|
|
2
2
|
export { processRawMediaPaths, processVideoMarkers, sendFileProactive, toLocalPath };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { u as uploadMediaToDingTalk } from "./media-
|
|
1
|
+
import { u as uploadMediaToDingTalk } from "./media-BViJQGgb.mjs";
|
|
2
2
|
import { a as resolveDingtalkAccount } from "./accounts-CF4oK_HZ.mjs";
|
|
3
|
-
import { r as CHANNEL_ID, t as getDingtalkRuntime } from "./runtime-
|
|
3
|
+
import { r as CHANNEL_ID, t as getDingtalkRuntime } from "./runtime-BCFW2-1B.mjs";
|
|
4
4
|
import { n as createLoggerFromConfig } from "./logger-BDWwViGT.mjs";
|
|
5
5
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
6
|
-
import { n as groupChatLacksVisibleRepliesAutomatic, r as pickEmptyReplyFallbackText, s as getOapiAccessToken, t as emptyGroupReplyLogHint } from "./utils-
|
|
7
|
-
import { a as sendTextMessage, d as isQpsLimitError, f as streamAICard, i as sendProactive, l as createAICardForTarget, r as sendMessage, t as sendMarkdownMessage, u as finishAICard } from "./messaging-
|
|
6
|
+
import { n as groupChatLacksVisibleRepliesAutomatic, r as pickEmptyReplyFallbackText, s as getOapiAccessToken, t as emptyGroupReplyLogHint } from "./utils-DgNm1Ek_.mjs";
|
|
7
|
+
import { a as sendTextMessage, d as isQpsLimitError, f as streamAICard, i as sendProactive, l as createAICardForTarget, r as sendMessage, t as sendMarkdownMessage, u as finishAICard } from "./messaging-C2zJ8O-o.mjs";
|
|
8
8
|
import { a as QUEUE_BUSY_ACK_PHRASES, n as normalizeSlashCommand, t as buildSessionContext } from "./session-DJ4jYqPv.mjs";
|
|
9
9
|
import { d as recallEmotionReply, o as getAccessToken, r as addEmotionReply, s as getOapiAccessToken$1, t as DINGTALK_API } from "./utils-legacy-CALCPP1t.mjs";
|
|
10
10
|
import "./chunk-upload-6p9cf3UB.mjs";
|
|
@@ -364,7 +364,7 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
364
364
|
finalText = await processAudioMarkers(finalText, "", account.config, oapiToken, log, true, target);
|
|
365
365
|
finalText = await uploadAndReplaceFileMarkers(finalText, "", account.config, oapiToken, log, true, target);
|
|
366
366
|
log.info(`[DingTalk][closeStreaming] 准备调用 processRawMediaPaths`);
|
|
367
|
-
const { processRawMediaPaths } = await import("./media-
|
|
367
|
+
const { processRawMediaPaths } = await import("./media-CIO05hZn.mjs");
|
|
368
368
|
finalText = await processRawMediaPaths(finalText, account.config, oapiToken, log, target);
|
|
369
369
|
log.info(`[DingTalk][closeStreaming] processRawMediaPaths 处理完成`);
|
|
370
370
|
} else log.warn(`[DingTalk][closeStreaming] oapiToken 为空,跳过媒体处理`);
|
|
@@ -480,7 +480,7 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
480
480
|
const oapiToken = await getOapiAccessToken(account.config);
|
|
481
481
|
if (oapiToken) {
|
|
482
482
|
log.info(`[DingTalk][deliver] 检测到 final 响应,准备处理裸露文件路径`);
|
|
483
|
-
const { processRawMediaPaths } = await import("./media-
|
|
483
|
+
const { processRawMediaPaths } = await import("./media-CIO05hZn.mjs");
|
|
484
484
|
text = await processRawMediaPaths(text, account.config, oapiToken, log, target);
|
|
485
485
|
log.info(`[DingTalk][deliver] 裸露文件路径处理完成`);
|
|
486
486
|
}
|
|
@@ -1751,7 +1751,7 @@ async function handleDingTalkMessageInternal(params) {
|
|
|
1751
1751
|
finalText = await processVideoMarkers(finalText, "", config, oapiToken, log, true, mediaTarget);
|
|
1752
1752
|
finalText = await processAudioMarkers(finalText, "", config, oapiToken, log, true, mediaTarget);
|
|
1753
1753
|
finalText = await uploadAndReplaceFileMarkers(finalText, "", config, oapiToken, log, true, mediaTarget);
|
|
1754
|
-
const { processRawMediaPaths } = await import("./media-
|
|
1754
|
+
const { processRawMediaPaths } = await import("./media-CIO05hZn.mjs");
|
|
1755
1755
|
finalText = await processRawMediaPaths(finalText, config, oapiToken, log, mediaTarget);
|
|
1756
1756
|
}
|
|
1757
1757
|
let textToSend = finalText.trim();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { u as uploadMediaToDingTalk } from "./media-
|
|
1
|
+
import { u as uploadMediaToDingTalk } from "./media-BViJQGgb.mjs";
|
|
2
2
|
import { n as createLoggerFromConfig } from "./logger-BDWwViGT.mjs";
|
|
3
3
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
4
|
-
import { i as DINGTALK_API, o as getAccessToken, s as getOapiAccessToken } from "./utils-
|
|
4
|
+
import { i as DINGTALK_API, o as getAccessToken, s as getOapiAccessToken } from "./utils-DgNm1Ek_.mjs";
|
|
5
5
|
import { r as MEDIA_MSG_TYPES } from "./session-DJ4jYqPv.mjs";
|
|
6
6
|
//#region src/services/messaging/card.ts
|
|
7
7
|
const AI_CARD_TEMPLATE_ID = "02fcf2f4-5e02-4a85-b672-46d1f715543e.schema";
|
|
@@ -851,7 +851,7 @@ async function sendMediaToDingTalk(params) {
|
|
|
851
851
|
});
|
|
852
852
|
}
|
|
853
853
|
let resolvedMediaUrl = mediaUrl;
|
|
854
|
-
const { toLocalPath } = await import("./media-
|
|
854
|
+
const { toLocalPath } = await import("./media-CIO05hZn.mjs");
|
|
855
855
|
const _fs = await import("fs");
|
|
856
856
|
const _path = await import("path");
|
|
857
857
|
const directPath = toLocalPath(mediaUrl);
|
|
@@ -886,7 +886,7 @@ async function sendMediaToDingTalk(params) {
|
|
|
886
886
|
}
|
|
887
887
|
if (mediaType === "video") {
|
|
888
888
|
const videoMarker = `[DINGTALK_VIDEO]{"path":"${mediaUrl}"}[/DINGTALK_VIDEO]`;
|
|
889
|
-
const { processVideoMarkers } = await import("./media-
|
|
889
|
+
const { processVideoMarkers } = await import("./media-CIO05hZn.mjs");
|
|
890
890
|
await processVideoMarkers(videoMarker, "", config, oapiToken, console, true, targetParam);
|
|
891
891
|
if (text?.trim()) {
|
|
892
892
|
const result = await sendProactive(config, targetParam, text, {
|
|
@@ -910,7 +910,7 @@ async function sendMediaToDingTalk(params) {
|
|
|
910
910
|
fileName,
|
|
911
911
|
fileType: ext || "file"
|
|
912
912
|
};
|
|
913
|
-
const { sendFileProactive } = await import("./media-
|
|
913
|
+
const { sendFileProactive } = await import("./media-CIO05hZn.mjs");
|
|
914
914
|
await sendFileProactive(config, targetParam, fileInfo, uploadResult.mediaId, log);
|
|
915
915
|
return {
|
|
916
916
|
ok: true,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { d as __exportAll } from "./media-
|
|
1
|
+
import { d as __exportAll } from "./media-BViJQGgb.mjs";
|
|
2
2
|
import { a as resolveDingtalkAccount, c as addWildcardAllowFrom, d as hasConfiguredSecretInput, f as normalizeAccountId, l as createDefaultChannelRuntimeState, m as resolveDefaultGroupPolicy, o as resolveDingtalkCredentials, p as resolveAllowlistProviderRuntimeGroupPolicy, r as resolveDefaultDingtalkAccountId, s as DEFAULT_ACCOUNT_ID, t as listDingtalkAccountIds, u as formatDocsLink } from "./accounts-CF4oK_HZ.mjs";
|
|
3
3
|
import { t as createLogger } from "./logger-BDWwViGT.mjs";
|
|
4
4
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
5
|
-
import "./utils-
|
|
6
|
-
import { n as sendMediaToDingTalk, o as sendTextToDingTalk } from "./messaging-
|
|
5
|
+
import "./utils-DgNm1Ek_.mjs";
|
|
6
|
+
import { n as sendMediaToDingTalk, o as sendTextToDingTalk } from "./messaging-C2zJ8O-o.mjs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { z, z as z$1 } from "zod";
|
|
9
9
|
//#region src/secret-input.ts
|
|
@@ -905,7 +905,7 @@ async function monitorDingtalkProvider(opts = {}) {
|
|
|
905
905
|
const log = createLogger(cfg.channels?.["dingtalk-connector"]?.debug ?? false);
|
|
906
906
|
const [accountsModule, monitorAccountModule, monitorSingleModule] = await Promise.all([
|
|
907
907
|
import("./accounts-BSIiLyZa.mjs"),
|
|
908
|
-
import("./message-handler-
|
|
908
|
+
import("./message-handler-0NLKAqHU.mjs"),
|
|
909
909
|
import("./connection-D4uO_J9G.mjs")
|
|
910
910
|
]);
|
|
911
911
|
const { resolveDingtalkAccount, listEnabledDingtalkAccounts } = accountsModule;
|
|
@@ -66,7 +66,7 @@ async function getOapiAccessToken(config) {
|
|
|
66
66
|
*
|
|
67
67
|
* 背景
|
|
68
68
|
* ----
|
|
69
|
-
* 群聊场景下用户 @
|
|
69
|
+
* 群聊场景下用户 @ 机器人后看到空回复兜底文案,常见根因不是 connector,
|
|
70
70
|
* 而是上游 OpenClaw 的 reply delivery mode(`source-reply-delivery-mode.ts`):群聊
|
|
71
71
|
* 默认走 `message_tool_only`,会跳过 `onPartialReply` 与 `accumulatedText`,
|
|
72
72
|
* 导致本插件累积的文本始终为空,最后落到 connector 的空回复兜底。
|
|
@@ -78,11 +78,13 @@ async function getOapiAccessToken(config) {
|
|
|
78
78
|
* }
|
|
79
79
|
* }
|
|
80
80
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
81
|
+
* 本模块的优化目标:让兜底文案在两种场景下都自然不"像报错"——
|
|
82
|
+
* - 群聊:返回一段可操作的运维指引(指向 `messages.groupChat.visibleReplies`)。
|
|
83
|
+
* - 单聊:返回一段口语化的简短确认语(单聊空 final 通常是模型自身没产出文本,
|
|
84
|
+
* 如纯思考、只走 tool_call、对 ACK 类输入选择沉默等),并隐含邀请用户继续提问,
|
|
85
|
+
* 避免历史上的「✅ 任务执行完成(无文本输出)」让用户误以为是报错。
|
|
84
86
|
*/
|
|
85
|
-
const DIRECT_FALLBACK_TEXT = "
|
|
87
|
+
const DIRECT_FALLBACK_TEXT = "好的 👌 有其他问题随时找我";
|
|
86
88
|
const GROUP_FALLBACK_TEXT = [
|
|
87
89
|
"ℹ️ 暂未收到模型回复内容。",
|
|
88
90
|
"若群聊频繁出现该提示,请联系机器人管理员检查 OpenClaw 配置:",
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Release Notes - v0.8.22-beta.0
|
|
2
|
+
|
|
3
|
+
> **社区验证版本** — 计划经过 ~2-3 天社区验证后晋升为正式版 `v0.8.22`。
|
|
4
|
+
> **Community validation release** — planned to promote to GA `v0.8.22` after ~2-3 days of community validation.
|
|
5
|
+
|
|
6
|
+
## 🎉 本次重点 / Highlights
|
|
7
|
+
|
|
8
|
+
本版本聚焦 UX 文案与 dws onboarding 体验:
|
|
9
|
+
|
|
10
|
+
1. 把单聊空回复兜底文案 `✅ 任务执行完成(无文本输出)` 换成口语化确认语 `好的 👌 有其他问题随时找我`,避免被用户误判为报错(#599)
|
|
11
|
+
2. dws CLI 内置版本从 `1.0.13` 升到 npm 最新 `1.0.30`,新装用户拿到正确的 `dws auth login --help` 文案
|
|
12
|
+
3. onboarding 检测 SSH / 无头环境(`SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION`),自动建议 `dws auth login --device`,避免 127.0.0.1 loopback 在远端无浏览器服务器上挂起(#565)
|
|
13
|
+
|
|
14
|
+
This release focuses on UX copy + dws onboarding experience:
|
|
15
|
+
|
|
16
|
+
1. Replace direct-chat empty-reply fallback `✅ 任务执行完成(无文本输出)` with conversational confirmation `好的 👌 有其他问题随时找我`, so users no longer mistake it for an error (#599)
|
|
17
|
+
2. Bump pinned dws CLI from `1.0.13` to npm latest `1.0.30`; new installs get the corrected `dws auth login --help` copy
|
|
18
|
+
3. Detect SSH / headless env in onboarding and auto-suggest `dws auth login --device`, avoiding 127.0.0.1 loopback hangs on remote headless servers (#565)
|
|
19
|
+
|
|
20
|
+
## ✨ 改进 / Improvements
|
|
21
|
+
|
|
22
|
+
### 单聊空回复 UX 文案优化 (#599 / #601)
|
|
23
|
+
|
|
24
|
+
**现象**:用户对一段说明回「知道了」后,机器人显示 `✅ 任务执行完成(无文本输出)`,被误判为报错。
|
|
25
|
+
|
|
26
|
+
**根因**:私聊场景下模型可能因 ACK 类输入选择沉默(只走 thinking / tool_call、或纯输出空文本)。connector 的空回复兜底文案系统/技术味偏重,让用户以为是异常。
|
|
27
|
+
|
|
28
|
+
**改动**:
|
|
29
|
+
|
|
30
|
+
- `src/utils/empty-reply.ts:23` — `DIRECT_FALLBACK_TEXT` 改为 `好的 👌 有其他问题随时找我`,保留"本轮已结束"信号但去掉技术味
|
|
31
|
+
- 测试改成语义契约(不绑死字符串):不出现报错感字样 / 以「好」开头 / 包含追问引导 / 与群聊文案不同
|
|
32
|
+
- 群聊兜底文案与日志 hint 维持不变(仍是面向运维的可操作指引)
|
|
33
|
+
|
|
34
|
+
**Phenomenon**: After replying "知道了" (got it) to a bot's explanation, users saw `✅ 任务执行完成(无文本输出)` and mistook it for an error.
|
|
35
|
+
|
|
36
|
+
**Root cause**: In direct chat, models may choose to stay silent on ACK-style input (only thinking / tool_call, or empty text output). The connector's fallback copy was too system-y, leading users to misjudge it as a fault.
|
|
37
|
+
|
|
38
|
+
**Changes**:
|
|
39
|
+
|
|
40
|
+
- `src/utils/empty-reply.ts:23` — `DIRECT_FALLBACK_TEXT` becomes `好的 👌 有其他问题随时找我`, keeping the "turn ended" signal while dropping the system flavor
|
|
41
|
+
- Tests refactored to semantic contracts (no hardcoded strings): no error-flavored words / starts with 「好」 / contains a follow-up invitation / differs from group fallback
|
|
42
|
+
- Group-chat fallback copy and log hint unchanged (still actionable ops guidance)
|
|
43
|
+
|
|
44
|
+
### dws onboarding SSH 兼容 + 版本升级 (#565 / #598)
|
|
45
|
+
|
|
46
|
+
**现象**:SSH / 无头服务器上首次 `dws auth login` 卡死——dws CLI 默认走 127.0.0.1 loopback 回调,本地浏览器无法访问远端 loopback。
|
|
47
|
+
|
|
48
|
+
**根因**:connector pin 的 dws 是 `1.0.13`,此版本 `--help` 文案描述与实际行为相反,SSH 用户照着 help 跑必然踩坑。
|
|
49
|
+
|
|
50
|
+
**改动**:
|
|
51
|
+
|
|
52
|
+
- `bin/dingtalk-connector.js:401` — `DWS_NPM_PACKAGE` 从 `1.0.13` → `1.0.30`(npm latest,含上游 dws #226 文档修复)
|
|
53
|
+
- 新增 `isSshSession()`:检测 `SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION` 三个环境变量
|
|
54
|
+
- 新增 `printDwsLoginHint()` 辅助:SSH 命中时把 `dws auth login` 换成 `dws auth login --device`,并附一句说明
|
|
55
|
+
- 把"已安装/全新安装"两条路径的登录提示统一走 `printDwsLoginHint()`,避免分叉
|
|
56
|
+
|
|
57
|
+
**根治方向(跨仓 follow-up)**:
|
|
58
|
+
|
|
59
|
+
- [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327) — 建议 dws 自身检测 SSH 环境自动降级到 `--device`,根治后 connector 这边的兜底逻辑可以择机删除
|
|
60
|
+
- 「对话框内授权」是更大的跨仓 UX 改造,需要 dws 支持非 CLI 流程或 Web flow,本版本不涉及
|
|
61
|
+
|
|
62
|
+
**Phenomenon**: First-time `dws auth login` hangs on SSH / headless servers — the dws CLI defaults to a 127.0.0.1 loopback callback that the local browser can't reach.
|
|
63
|
+
|
|
64
|
+
**Root cause**: connector pinned dws `1.0.13` whose `--help` text described the opposite of actual behavior; SSH users following the help inevitably hit the trap.
|
|
65
|
+
|
|
66
|
+
**Changes**:
|
|
67
|
+
|
|
68
|
+
- `bin/dingtalk-connector.js:401` — `DWS_NPM_PACKAGE` from `1.0.13` → `1.0.30` (npm latest, including upstream dws #226 docs fix)
|
|
69
|
+
- Add `isSshSession()`: detects `SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION` env vars
|
|
70
|
+
- Add `printDwsLoginHint()` helper: when SSH is detected, suggest `dws auth login --device` with a brief reason
|
|
71
|
+
- Unify login hint between "already installed" and "fresh install" branches via `printDwsLoginHint()` to avoid drift
|
|
72
|
+
|
|
73
|
+
**Long-term root fix (cross-repo follow-up)**:
|
|
74
|
+
|
|
75
|
+
- [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327) — propose dws itself detect SSH and auto-fall back to `--device`. Once that lands, the connector-side workaround can be removed.
|
|
76
|
+
- "In-chat authorization" is a larger cross-repo UX overhaul (needs dws to support non-CLI / Web flow); not in scope for this release.
|
|
77
|
+
|
|
78
|
+
## 🧪 验证 / Validation
|
|
79
|
+
|
|
80
|
+
- `tests/empty-reply.unit.test.ts` — 9/9 单测通过(语义契约风格)
|
|
81
|
+
- `node --check bin/dingtalk-connector.js` — 语法通过
|
|
82
|
+
- 手动验证:设置 `SSH_CLIENT` 环境变量后,onboarding 提示自动切到 `dws auth login --device`
|
|
83
|
+
|
|
84
|
+
## 📦 升级方式 / How to upgrade
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
openclaw plugins install @dingtalk-real-ai/dingtalk-connector@0.8.22-beta.0
|
|
88
|
+
openclaw gateway restart
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
或者:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm install -g @dingtalk-real-ai/dingtalk-connector@0.8.22-beta.0
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## ⏭️ 后续节奏 / Next steps
|
|
98
|
+
|
|
99
|
+
- **2026-05-22 ~ 2026-05-24**:社区使用反馈窗口,2-3 天观察期
|
|
100
|
+
- **~2026-05-24 之后**:若无回归,晋升为正式版 `v0.8.22`
|
|
101
|
+
- 升级遇到问题请提交到 [Issues](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues),按置顶 [#584](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/584) / [#585](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/585) 的模板补全反馈信息
|
|
102
|
+
|
|
103
|
+
## 🔗 关联 / References
|
|
104
|
+
|
|
105
|
+
- Issue [#599](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/599) → PR [#601](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/601)
|
|
106
|
+
- Issue [#565](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/565) → PR [#598](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/598)
|
|
107
|
+
- 跨仓 follow-up: [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Release Notes - v0.8.22
|
|
2
|
+
|
|
3
|
+
> **GA 正式版** — 晋升自 `0.8.22-beta.0`,经 ~3 天社区验证(无回归反馈)后正式发布。
|
|
4
|
+
> **General Availability** — Promoted from `0.8.22-beta.0` after ~3 days of community validation with no regression.
|
|
5
|
+
|
|
6
|
+
## 🎉 本次重点 / Highlights
|
|
7
|
+
|
|
8
|
+
本版本聚焦 UX 文案与 dws onboarding 体验,与 `0.8.22-beta.0` 功能完全一致:
|
|
9
|
+
|
|
10
|
+
1. 把单聊空回复兜底文案 `✅ 任务执行完成(无文本输出)` 换成口语化的 `好的 👌 有其他问题随时找我`,避免被用户误判为报错([#599](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/599) / [PR #601](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/601))
|
|
11
|
+
2. 内置 dws CLI 从 `1.0.13` 升到 npm 最新 `1.0.30`,新装用户拿到正确的 `dws auth login --help` 文案
|
|
12
|
+
3. onboarding 检测 SSH / 无头环境(`SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION`),自动建议 `dws auth login --device`,避免 127.0.0.1 loopback 在远端无浏览器服务器上挂起([#565](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/565) / [PR #598](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/598))
|
|
13
|
+
|
|
14
|
+
This release focuses on UX copy + dws onboarding experience. Functionally identical to `0.8.22-beta.0`:
|
|
15
|
+
|
|
16
|
+
1. Replace direct-chat empty-reply fallback `✅ 任务执行完成(无文本输出)` with conversational `好的 👌 有其他问题随时找我`, so users no longer mistake it for an error (#599 / PR #601)
|
|
17
|
+
2. Bump bundled dws CLI from `1.0.13` to npm latest `1.0.30`; new installs get the corrected `dws auth login --help` copy
|
|
18
|
+
3. Detect SSH / headless env in onboarding and auto-suggest `dws auth login --device`, avoiding 127.0.0.1 loopback hangs on remote headless servers (#565 / PR #598)
|
|
19
|
+
|
|
20
|
+
## ✨ 改进 / Improvements
|
|
21
|
+
|
|
22
|
+
### 单聊空回复 UX 文案优化 ([#599](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/599) / [PR #601](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/601))
|
|
23
|
+
|
|
24
|
+
**现象**:用户对一段说明回「知道了」后,机器人显示 `✅ 任务执行完成(无文本输出)`,被误判为报错。
|
|
25
|
+
|
|
26
|
+
**根因**:私聊场景下模型可能因 ACK 类输入选择沉默(只走 thinking / tool_call、或纯输出空文本)。connector 的空回复兜底文案系统/技术味偏重。
|
|
27
|
+
|
|
28
|
+
**改动**:
|
|
29
|
+
|
|
30
|
+
- `src/utils/empty-reply.ts:23` — `DIRECT_FALLBACK_TEXT` 改为 `好的 👌 有其他问题随时找我`,保留"本轮已结束"信号但去掉技术味
|
|
31
|
+
- 测试改成语义契约(不绑死字符串):不出现报错感字样 / 以「好」开头 / 包含追问引导 / 与群聊文案不同
|
|
32
|
+
- 群聊兜底文案与日志 hint 维持不变(仍是面向运维的可操作指引)
|
|
33
|
+
|
|
34
|
+
### dws onboarding SSH 兼容 + 版本升级 ([#565](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/565) / [PR #598](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/598))
|
|
35
|
+
|
|
36
|
+
**现象**:SSH / 无头服务器上首次 `dws auth login` 卡死——dws CLI 默认走 127.0.0.1 loopback 回调,本地浏览器无法访问远端 loopback。
|
|
37
|
+
|
|
38
|
+
**根因**:connector pin 的 dws 是 `1.0.13`,此版本 `--help` 文案描述与实际行为相反,SSH 用户照着 help 跑必然踩坑。
|
|
39
|
+
|
|
40
|
+
**改动**:
|
|
41
|
+
|
|
42
|
+
- `bin/dingtalk-connector.js:401` — `DWS_NPM_PACKAGE` 从 `1.0.13` → `1.0.30`(npm latest,含上游 dws #226 文档修复)
|
|
43
|
+
- 新增 `isSshSession()`:检测 `SSH_CLIENT` / `SSH_TTY` / `SSH_CONNECTION` 三个环境变量
|
|
44
|
+
- 新增 `printDwsLoginHint()` 辅助:SSH 命中时把 `dws auth login` 换成 `dws auth login --device`,并附一句说明
|
|
45
|
+
- 把"已安装/全新安装"两条路径的登录提示统一走 `printDwsLoginHint()`,避免分叉
|
|
46
|
+
|
|
47
|
+
**根治方向(跨仓 follow-up)**:
|
|
48
|
+
|
|
49
|
+
- [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327) — 建议 dws 自身检测 SSH 环境自动降级到 `--device`,根治后 connector 这边的兜底逻辑可以择机删除
|
|
50
|
+
- 「对话框内授权」是更大的跨仓 UX 改造,需要 dws 支持非 CLI 流程或 Web flow,本版本不涉及
|
|
51
|
+
|
|
52
|
+
## 🔒 兼容性 / Compatibility
|
|
53
|
+
|
|
54
|
+
- **API 无变化**、配置 schema 无变化、导出符号无变化
|
|
55
|
+
- 现有用户升级无需任何配置改动
|
|
56
|
+
- 群聊行为完全不变(空回复兜底文案与日志 hint 未动)
|
|
57
|
+
- 仅以下两类用户感知到差异:
|
|
58
|
+
- 私聊场景看到空回复兜底文案的用户 —— 文案更友好
|
|
59
|
+
- 全新安装 / 在 SSH 环境首次 `dws auth login` 的用户 —— 自动得到正确命令建议
|
|
60
|
+
|
|
61
|
+
## 🧪 验证 / Verification
|
|
62
|
+
|
|
63
|
+
**Beta 社区验证(2026-05-21 ~ 2026-05-24,~3 天)**:
|
|
64
|
+
- npm `beta` tag 上 `0.8.22-beta.0` 稳定可用
|
|
65
|
+
- 无任何针对私聊空回复文案 / dws SSH onboarding 的回归 issue
|
|
66
|
+
|
|
67
|
+
**已验证组合 / Verified combo**:
|
|
68
|
+
- OpenClaw Gateway `2026.5.12` (f066dd2)
|
|
69
|
+
- Connector `0.8.22-beta.0`(已晋升为 `0.8.22`)
|
|
70
|
+
- 平台 macOS(darwin 23.2.0)
|
|
71
|
+
|
|
72
|
+
## 📥 安装升级 / Installation & Upgrade
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
openclaw plugins install @dingtalk-real-ai/dingtalk-connector@0.8.22
|
|
76
|
+
openclaw gateway restart
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
或:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install @dingtalk-real-ai/dingtalk-connector@latest
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 🔗 相关链接 / Related Links
|
|
86
|
+
|
|
87
|
+
- [完整变更日志 / Full Changelog](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/CHANGELOG.md)
|
|
88
|
+
- [Beta release notes (`v0.8.22-beta.0`)](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/docs/RELEASE_NOTES_V0.8.22-beta.0.md)
|
|
89
|
+
- 关联 PRs / issues:[#599](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/599) / [#601](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/601) / [#565](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/565) / [#598](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/pull/598) / [dws #327](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/issues/327)
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
**发布日期 / Release Date**:2026-05-24
|
|
94
|
+
**版本号 / Version**:v0.8.22
|
|
95
|
+
**兼容性 / Compatibility**:OpenClaw Gateway 2026.5.7+
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1579,7 +1579,8 @@ export async function handleDingTalkMessageInternal(params: HandleMessageParams)
|
|
|
1579
1579
|
|
|
1580
1580
|
// ✅ 异步模式下 final 文本为空时的兜底
|
|
1581
1581
|
// 群聊场景下,常见根因是 OpenClaw `messages.groupChat.visibleReplies` 未设为 "automatic"
|
|
1582
|
-
// (详见 src/utils/empty-reply.ts
|
|
1582
|
+
// (详见 src/utils/empty-reply.ts),给运维一份可操作的指引;
|
|
1583
|
+
// 单聊则用口语化确认语兜底,避免被用户误判为报错。
|
|
1583
1584
|
let textToSend = finalText.trim();
|
|
1584
1585
|
if (!textToSend) {
|
|
1585
1586
|
const isGroup = !isDirect;
|
package/src/reply-dispatcher.ts
CHANGED
|
@@ -308,8 +308,9 @@ export function createDingtalkReplyDispatcher(params: CreateDingtalkReplyDispatc
|
|
|
308
308
|
// ✅ 如果累积的文本为空,使用默认提示文案
|
|
309
309
|
// 群聊场景下,常见根因是 OpenClaw `messages.groupChat.visibleReplies` 未设为
|
|
310
310
|
// "automatic"(上游 source-reply-delivery-mode.ts 走 message_tool_only 时
|
|
311
|
-
// 会跳过 onPartialReply,accumulatedText
|
|
312
|
-
//
|
|
311
|
+
// 会跳过 onPartialReply,accumulatedText 始终为空)。给运维一份可操作的指引;
|
|
312
|
+
// 单聊则用口语化确认语兜底,避免「任务执行完成(无文本输出)」让用户误判为报错。
|
|
313
|
+
// 详见 src/utils/empty-reply.ts。
|
|
313
314
|
if (!finalText.trim()) {
|
|
314
315
|
const isGroup = !isDirect;
|
|
315
316
|
finalText = pickEmptyReplyFallbackText(isGroup);
|
package/src/utils/empty-reply.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 背景
|
|
5
5
|
* ----
|
|
6
|
-
* 群聊场景下用户 @
|
|
6
|
+
* 群聊场景下用户 @ 机器人后看到空回复兜底文案,常见根因不是 connector,
|
|
7
7
|
* 而是上游 OpenClaw 的 reply delivery mode(`source-reply-delivery-mode.ts`):群聊
|
|
8
8
|
* 默认走 `message_tool_only`,会跳过 `onPartialReply` 与 `accumulatedText`,
|
|
9
9
|
* 导致本插件累积的文本始终为空,最后落到 connector 的空回复兜底。
|
|
@@ -15,12 +15,14 @@
|
|
|
15
15
|
* }
|
|
16
16
|
* }
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* 本模块的优化目标:让兜底文案在两种场景下都自然不"像报错"——
|
|
19
|
+
* - 群聊:返回一段可操作的运维指引(指向 `messages.groupChat.visibleReplies`)。
|
|
20
|
+
* - 单聊:返回一段口语化的简短确认语(单聊空 final 通常是模型自身没产出文本,
|
|
21
|
+
* 如纯思考、只走 tool_call、对 ACK 类输入选择沉默等),并隐含邀请用户继续提问,
|
|
22
|
+
* 避免历史上的「✅ 任务执行完成(无文本输出)」让用户误以为是报错。
|
|
21
23
|
*/
|
|
22
24
|
|
|
23
|
-
const DIRECT_FALLBACK_TEXT = '
|
|
25
|
+
const DIRECT_FALLBACK_TEXT = '好的 👌 有其他问题随时找我';
|
|
24
26
|
|
|
25
27
|
const GROUP_FALLBACK_TEXT = [
|
|
26
28
|
'ℹ️ 暂未收到模型回复内容。',
|