@jeik/dingtalk-connector 0.8.21-fix46 → 0.8.21-fix47
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 +12 -0
- package/README.en.md +8 -5
- package/README.md +9 -6
- package/dist/entry-bundled.mjs +1 -1
- package/dist/gateway-methods-DHMdV0k8.mjs +2 -0
- package/dist/{gateway-methods-CkBI4__L.mjs → gateway-methods-DNvtOYEG.mjs} +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{media-9LvaywGZ.mjs → media-BqpUGCni.mjs} +1 -1
- package/dist/{media-BMNRjseJ.mjs → media-DnQB2BrL.mjs} +10 -2
- package/dist/{message-handler-CytB34ZJ.mjs → message-handler-DVXM5olz.mjs} +7 -7
- package/dist/{messaging-ngF20yqM.mjs → messaging-msXFq5IJ.mjs} +4 -4
- package/dist/{runtime-I36vhOzx.mjs → runtime-f78QdJj5.mjs} +3 -3
- package/docs/RELEASE_NOTES_V0.8.21-fix47.md +32 -0
- package/package.json +1 -1
- package/src/services/media/common.ts +5 -6
- package/src/services/media.ts +18 -4
- package/dist/gateway-methods-BTByJFxo.mjs +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.21-fix47] - 2026-07-20
|
|
9
|
+
|
|
10
|
+
### 修复 / Fixed
|
|
11
|
+
- 🐛 **`file://` 本地图被误判为远程** — `looksLikeRemoteUrl` 对含 `://` 一律当远程,导致 `` / `file:///root/...` 走 `fetch` → `fetch failed`,原样发出灰图。现:`file://` / `MEDIA:` / `attachment://` **优先按本地上传**(`toLocalPath` 后 oapi)。
|
|
12
|
+
日志特征(fix46):`kind=http path=file://...` + `远程图下载异常 | fetch failed` + `localTried=0`。
|
|
13
|
+
|
|
14
|
+
### 安装 / Install
|
|
15
|
+
```bash
|
|
16
|
+
npx -y @jeik/dingtalk-connector install --force
|
|
17
|
+
openclaw gateway restart
|
|
18
|
+
```
|
|
19
|
+
|
|
8
20
|
## [0.8.21-fix46] - 2026-07-20
|
|
9
21
|
|
|
10
22
|
### 诊断 / Diagnostics
|
package/README.en.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<p>Community maintained fork of the official <strong>v0.8.20</strong> release, tracking and fixing bugs the official team hasn't addressed.<br/>
|
|
5
5
|
Identical to the official release in functionality — only community-critical fixes applied.</p>
|
|
6
6
|
|
|
7
|
-
<p><strong>Current published release: <a href="https://www.npmjs.com/package/@jeik/dingtalk-connector">@jeik/dingtalk-connector</a> v0.8.21-
|
|
7
|
+
<p><strong>Current published release: <a href="https://www.npmjs.com/package/@jeik/dingtalk-connector">@jeik/dingtalk-connector</a> v0.8.21-fix47</strong> (production-stable; install: <code>npx -y @jeik/dingtalk-connector install</code>).</p>
|
|
8
8
|
|
|
9
9
|
<p>
|
|
10
10
|
<a href="https://www.npmjs.com/package/@jeik/dingtalk-connector"><img src="https://img.shields.io/npm/v/@jeik/dingtalk-connector.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="npm version" /></a>
|
|
@@ -23,19 +23,22 @@
|
|
|
23
23
|
|
|
24
24
|
## 🔧 Recent Updates
|
|
25
25
|
|
|
26
|
-
### 🚀 v0.8.21-
|
|
26
|
+
### 🚀 v0.8.21-fix47 · 2026-07-20 (current)
|
|
27
27
|
|
|
28
|
-
**Theme:
|
|
28
|
+
**Theme: fix `file://` misclassified as remote URL**
|
|
29
29
|
|
|
30
30
|
| | Change |
|
|
31
31
|
|--|--------|
|
|
32
|
-
|
|
|
33
|
-
| 🔍 **MediaIdTrace** | `mdImgs`, `residualLocal`, API-before preview |
|
|
32
|
+
| 🐛 **`file://` grey images** | Treat `file://` / `MEDIA:` / `attachment://` as local upload, not `fetch` |
|
|
34
33
|
|
|
35
34
|
```bash
|
|
36
35
|
npx -y @jeik/dingtalk-connector install --force && openclaw gateway restart
|
|
37
36
|
```
|
|
38
37
|
|
|
38
|
+
### 📦 v0.8.21-fix46 · 2026-07-20
|
|
39
|
+
|
|
40
|
+
Always-on local MD image diagnostics.
|
|
41
|
+
|
|
39
42
|
### 📦 v0.8.21-fix45 · 2026-07-20
|
|
40
43
|
|
|
41
44
|
Image + download link one bubble · only `![]` · quote cache · residual false-positive fix.
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<p>基于官方 <strong>v0.8.20</strong> 的社区维护版本,由社区持续跟进修复官方无暇处理的 Bug。<br/>
|
|
5
5
|
功能与官方完全一致,拥有最快的修复速度,及时合并官方pr和个人发现的bug和社区急需的 Bug。</p>
|
|
6
6
|
|
|
7
|
-
<p><strong>当前发布版:<a href="https://www.npmjs.com/package/@jeik/dingtalk-connector">@jeik/dingtalk-connector</a> v0.8.21-
|
|
7
|
+
<p><strong>当前发布版:<a href="https://www.npmjs.com/package/@jeik/dingtalk-connector">@jeik/dingtalk-connector</a> v0.8.21-fix47</strong>(稳定生产可用;一键安装:`npx -y @jeik/dingtalk-connector install`;本地 tgz:`openclaw plugins install ./jeik-dingtalk-connector-0.8.21-fix47.tgz --force`)</p>
|
|
8
8
|
|
|
9
9
|
<p>
|
|
10
10
|
<a href="https://www.npmjs.com/package/@jeik/dingtalk-connector"><img src="https://img.shields.io/npm/v/@jeik/dingtalk-connector.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="npm version" /></a>
|
|
@@ -23,19 +23,22 @@
|
|
|
23
23
|
|
|
24
24
|
## 🔧 最近更新
|
|
25
25
|
|
|
26
|
-
### 🚀 v0.8.21-
|
|
26
|
+
### 🚀 v0.8.21-fix47 · 2026-07-20(当前)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
**主题:`file://` 本地图误判远程修复**
|
|
29
29
|
|
|
30
30
|
| | 改动 |
|
|
31
31
|
|--|------|
|
|
32
|
-
|
|
|
33
|
-
| 🔍 **MediaIdTrace** | `mdImgs`、`residualLocal`、API前 preview,方便对灰图 |
|
|
32
|
+
| 🐛 **`file://` 灰图** | `` / `file:///root/...` 按本地上传,不再 `fetch failed` |
|
|
34
33
|
|
|
35
34
|
```bash
|
|
36
35
|
npx -y @jeik/dingtalk-connector install --force && openclaw gateway restart
|
|
37
36
|
```
|
|
38
37
|
|
|
38
|
+
### 📦 v0.8.21-fix46 · 2026-07-20
|
|
39
|
+
|
|
40
|
+
本地 MD 图灰图诊断日志(LocalImage / MediaIdTrace)。
|
|
41
|
+
|
|
39
42
|
### 📦 v0.8.21-fix45 · 2026-07-20
|
|
40
43
|
|
|
41
44
|
图 + 下载链接单气泡 · 只认 `![]` · 引用卡片缓存 · residual 误报修复。
|
|
@@ -66,7 +69,7 @@ message 远程 `media` 下载上传。
|
|
|
66
69
|
| 2026-06-28 | 上线 npm `@jeik/dingtalk-connector`;过程消息提前定稿修复 |
|
|
67
70
|
| 2026-05 | MD 直链/本地图;多轮刷屏;4.29+ 无文本输出;WebSocket 幻影重连 |
|
|
68
71
|
|
|
69
|
-
完整说明:[CHANGELOG.md](CHANGELOG.md) · [FIXES.md](FIXES.md) · [Release
|
|
72
|
+
完整说明:[CHANGELOG.md](CHANGELOG.md) · [FIXES.md](FIXES.md) · [Release fix47](docs/RELEASE_NOTES_V0.8.21-fix47.md)
|
|
70
73
|
|
|
71
74
|
---
|
|
72
75
|
|
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-DHMdV0k8.mjs");
|
|
27
27
|
registerGatewayMethods(api);
|
|
28
28
|
}
|
|
29
29
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as resolveDingtalkAccount, t as listDingtalkAccountIds } from "./accounts-BAzdqkAV.mjs";
|
|
2
2
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
3
3
|
import { r as getAccessToken, t as DINGTALK_API } from "./utils-CIfI_3Jh.mjs";
|
|
4
|
-
import { c as prepareMultiBotMentions, d as finishAICard, i as sendProactive, s as buildBotMentionTable } from "./messaging-
|
|
4
|
+
import { c as prepareMultiBotMentions, d as finishAICard, i as sendProactive, s as buildBotMentionTable } from "./messaging-msXFq5IJ.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-f78QdJj5.mjs";
|
|
2
|
+
import { t as registerGatewayMethods } from "./gateway-methods-DNvtOYEG.mjs";
|
|
3
3
|
//#region index.ts
|
|
4
4
|
/**
|
|
5
5
|
* 检测同一 plugin id 在多个路径被加载的情况。
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as toLocalPath, d as processLocalImages, f as processRawMediaPaths, h as sendFileProactive, o as hasResidualLocalMdImagesOutsideCode, p as processVideoMarkers } from "./media-
|
|
1
|
+
import { _ as toLocalPath, d as processLocalImages, f as processRawMediaPaths, h as sendFileProactive, o as hasResidualLocalMdImagesOutsideCode, p as processVideoMarkers } from "./media-DnQB2BrL.mjs";
|
|
2
2
|
export { hasResidualLocalMdImagesOutsideCode, processLocalImages, processRawMediaPaths, processVideoMarkers, sendFileProactive, toLocalPath };
|
|
@@ -30,10 +30,18 @@ const IMAGE_EXTENSIONS = /\.(png|jpg|jpeg|gif|bmp|webp|tiff|svg)$/i;
|
|
|
30
30
|
* 注意:旧版只匹配 /tmp|/home|/root 等前缀,**漏掉 /mnt 共享盘**,导致 message 工具 MD 灰图。
|
|
31
31
|
*/
|
|
32
32
|
const LOCAL_IMAGE_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
33
|
-
/**
|
|
33
|
+
/** 本地文件 URI / OpenClaw 媒体前缀(不是 http 远程) */
|
|
34
|
+
function isLocalFileScheme(p) {
|
|
35
|
+
return p.startsWith("file://") || p.startsWith("MEDIA:") || p.startsWith("attachment://");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 是否像远程 URL(禁止当本地路径上传)。
|
|
39
|
+
* **不含** file:// / MEDIA: / attachment://(那些是本地引用)。
|
|
40
|
+
*/
|
|
34
41
|
function looksLikeRemoteUrl(raw) {
|
|
35
42
|
const p = (raw || "").trim();
|
|
36
43
|
if (!p) return false;
|
|
44
|
+
if (isLocalFileScheme(p)) return false;
|
|
37
45
|
if (/^https?:\/\//i.test(p)) return true;
|
|
38
46
|
if (/^[a-z]:\/\//i.test(p) && !/^[a-z]:[\\/][^/\\]/i.test(p)) return true;
|
|
39
47
|
if (p.includes("://")) return true;
|
|
@@ -43,9 +51,9 @@ function looksLikeRemoteUrl(raw) {
|
|
|
43
51
|
function isLocalImageRef(rawPath) {
|
|
44
52
|
const p = (rawPath || "").trim();
|
|
45
53
|
if (!p) return false;
|
|
54
|
+
if (isLocalFileScheme(p)) return true;
|
|
46
55
|
if (looksLikeRemoteUrl(p) || /^https?:\/\//i.test(p)) return false;
|
|
47
56
|
if (p.startsWith("@") && !p.includes("/") && !p.includes("\\")) return false;
|
|
48
|
-
if (p.startsWith("file://") || p.startsWith("MEDIA:") || p.startsWith("attachment://")) return true;
|
|
49
57
|
if (p.startsWith("/") || /^[A-Za-z]:[\\/]/.test(p)) {
|
|
50
58
|
if (IMAGE_EXTENSIONS.test(p.split("?")[0] || p)) return true;
|
|
51
59
|
return !p.includes("://");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { a as resolveDingtalkAccount } from "./accounts-BAzdqkAV.mjs";
|
|
2
|
-
import { r as CHANNEL_ID, t as getDingtalkRuntime } from "./runtime-
|
|
2
|
+
import { r as CHANNEL_ID, t as getDingtalkRuntime } from "./runtime-f78QdJj5.mjs";
|
|
3
3
|
import { n as createLoggerFromConfig } from "./logger-mZ9OSbmD.mjs";
|
|
4
4
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
5
5
|
import { i as getOapiAccessToken } from "./utils-CIfI_3Jh.mjs";
|
|
6
|
-
import { S as finalClean, _ as FINAL_TAG, a as sendTextMessage, b as estimateTokens, d as finishAICard, g as unregisterActiveCard, h as streamAICard, i as sendProactive, m as registerActiveCard, p as isQpsLimitError, r as sendMessage, t as sendMarkdownMessage, u as createAICardForTarget, v as PROCESS_TAG, x as extractFinal, y as displayClean } from "./messaging-
|
|
6
|
+
import { S as finalClean, _ as FINAL_TAG, a as sendTextMessage, b as estimateTokens, d as finishAICard, g as unregisterActiveCard, h as streamAICard, i as sendProactive, m as registerActiveCard, p as isQpsLimitError, r as sendMessage, t as sendMarkdownMessage, u as createAICardForTarget, v as PROCESS_TAG, x as extractFinal, y as displayClean } from "./messaging-msXFq5IJ.mjs";
|
|
7
7
|
import { a as QUEUE_BUSY_ACK_PHRASES, n as normalizeSlashCommand, t as buildSessionContext } from "./session-DJ4jYqPv.mjs";
|
|
8
8
|
import { d as recallEmotionReply, o as getAccessToken, r as addEmotionReply, s as getOapiAccessToken$1, t as DINGTALK_API } from "./utils-legacy-CALCPP1t.mjs";
|
|
9
9
|
import "./chunk-upload-BBQgGtcZ.mjs";
|
|
@@ -62,7 +62,7 @@ function resolveAgentWorkspaceDir(cfg, agentId) {
|
|
|
62
62
|
* 直接复用 media.ts 权威实现,避免 reply 路径与 message 路径两套逻辑分叉。
|
|
63
63
|
*/
|
|
64
64
|
async function processLocalImages(content, oapiToken, log) {
|
|
65
|
-
const { processLocalImages: impl } = await import("./media-
|
|
65
|
+
const { processLocalImages: impl } = await import("./media-BqpUGCni.mjs");
|
|
66
66
|
return impl(content, oapiToken, log);
|
|
67
67
|
}
|
|
68
68
|
//#endregion
|
|
@@ -581,14 +581,14 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
581
581
|
finalText = await processLocalImages(finalText, oapiToken, log);
|
|
582
582
|
if (beforeImg !== finalText) console.log(`[DingTalk][LocalImage] closeStreaming 图片处理 | ${beforeImg.length}→${finalText.length}`);
|
|
583
583
|
try {
|
|
584
|
-
const { hasResidualLocalMdImagesOutsideCode } = await import("./media-
|
|
584
|
+
const { hasResidualLocalMdImagesOutsideCode } = await import("./media-BqpUGCni.mjs");
|
|
585
585
|
if (hasResidualLocalMdImagesOutsideCode(finalText)) console.warn(`[DingTalk][LocalImage] closeStreaming 定稿后仍有代码块外的本地 MD 图未上传,钉钉可能灰图`);
|
|
586
586
|
} catch {}
|
|
587
587
|
finalText = await processVideoMarkers(finalText, "", account.config, oapiToken, log, true, target);
|
|
588
588
|
finalText = await processAudioMarkers(finalText, "", account.config, oapiToken, log, true, target);
|
|
589
589
|
finalText = await uploadAndReplaceFileMarkers(finalText, "", account.config, oapiToken, log, true, target);
|
|
590
590
|
log.info(`[DingTalk][closeStreaming] 准备调用 processRawMediaPaths`);
|
|
591
|
-
const { processRawMediaPaths } = await import("./media-
|
|
591
|
+
const { processRawMediaPaths } = await import("./media-BqpUGCni.mjs");
|
|
592
592
|
finalText = await processRawMediaPaths(finalText, account.config, oapiToken, log, target);
|
|
593
593
|
log.info(`[DingTalk][closeStreaming] processRawMediaPaths 处理完成`);
|
|
594
594
|
} else log.warn(`[DingTalk][closeStreaming] oapiToken 为空,跳过媒体处理`);
|
|
@@ -744,7 +744,7 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
744
744
|
const oapiToken = await getOapiAccessToken(account.config);
|
|
745
745
|
if (oapiToken) {
|
|
746
746
|
log.info(`[DingTalk][deliver] 检测到 final 响应,准备处理裸露文件路径`);
|
|
747
|
-
const { processRawMediaPaths } = await import("./media-
|
|
747
|
+
const { processRawMediaPaths } = await import("./media-BqpUGCni.mjs");
|
|
748
748
|
text = await processRawMediaPaths(text, account.config, oapiToken, log, target);
|
|
749
749
|
log.info(`[DingTalk][deliver] 裸露文件路径处理完成`);
|
|
750
750
|
}
|
|
@@ -2184,7 +2184,7 @@ async function handleDingTalkMessageInternal(params) {
|
|
|
2184
2184
|
finalText = await processVideoMarkers(finalText, "", config, oapiToken, log, true, mediaTarget);
|
|
2185
2185
|
finalText = await processAudioMarkers(finalText, "", config, oapiToken, log, true, mediaTarget);
|
|
2186
2186
|
finalText = await uploadAndReplaceFileMarkers(finalText, "", config, oapiToken, log, true, mediaTarget);
|
|
2187
|
-
const { processRawMediaPaths } = await import("./media-
|
|
2187
|
+
const { processRawMediaPaths } = await import("./media-BqpUGCni.mjs");
|
|
2188
2188
|
finalText = await processRawMediaPaths(finalText, config, oapiToken, log, mediaTarget);
|
|
2189
2189
|
}
|
|
2190
2190
|
const textToSend = finalText.trim() || "✅ 任务执行完成(无文本输出)";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as logMediaIdTrace, d as processLocalImages, u as processImagesForOutbound, y as uploadMediaToDingTalk } from "./media-
|
|
1
|
+
import { c as logMediaIdTrace, d as processLocalImages, u as processImagesForOutbound, y as uploadMediaToDingTalk } from "./media-DnQB2BrL.mjs";
|
|
2
2
|
import { n as createLoggerFromConfig } from "./logger-mZ9OSbmD.mjs";
|
|
3
3
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
4
4
|
import { i as getOapiAccessToken, r as getAccessToken, t as DINGTALK_API } from "./utils-CIfI_3Jh.mjs";
|
|
@@ -848,7 +848,7 @@ async function resolveMediaSourceToLocalFile(mediaUrl, mediaLocalRoots, log) {
|
|
|
848
848
|
cleanup: tmp
|
|
849
849
|
};
|
|
850
850
|
}
|
|
851
|
-
const { toLocalPath } = await import("./media-
|
|
851
|
+
const { toLocalPath } = await import("./media-BqpUGCni.mjs");
|
|
852
852
|
const _fs = await import("fs");
|
|
853
853
|
const _path = await import("path");
|
|
854
854
|
let resolved = toLocalPath(mediaUrl);
|
|
@@ -1121,7 +1121,7 @@ async function sendMediaToDingTalk(params) {
|
|
|
1121
1121
|
const fileName = mediaUrl.split("/").filter(Boolean).pop()?.split("?")[0] || "file";
|
|
1122
1122
|
if (mediaType === "video") {
|
|
1123
1123
|
const videoMarker = `[DINGTALK_VIDEO]{"path":"${resolvedMediaUrl}"}[/DINGTALK_VIDEO]`;
|
|
1124
|
-
const { processVideoMarkers } = await import("./media-
|
|
1124
|
+
const { processVideoMarkers } = await import("./media-BqpUGCni.mjs");
|
|
1125
1125
|
await processVideoMarkers(videoMarker, "", config, oapiToken, console, true, targetParam);
|
|
1126
1126
|
return {
|
|
1127
1127
|
ok: true,
|
|
@@ -1140,7 +1140,7 @@ async function sendMediaToDingTalk(params) {
|
|
|
1140
1140
|
fileName,
|
|
1141
1141
|
fileType: ext && ext.length < 12 ? ext : "file"
|
|
1142
1142
|
};
|
|
1143
|
-
const { sendFileProactive } = await import("./media-
|
|
1143
|
+
const { sendFileProactive } = await import("./media-BqpUGCni.mjs");
|
|
1144
1144
|
await sendFileProactive(config, targetParam, fileInfo, uploadResult.mediaId, log);
|
|
1145
1145
|
return {
|
|
1146
1146
|
ok: true,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { b as __exportAll } from "./media-
|
|
1
|
+
import { b as __exportAll } from "./media-DnQB2BrL.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-BAzdqkAV.mjs";
|
|
3
3
|
import { t as createLogger } from "./logger-mZ9OSbmD.mjs";
|
|
4
4
|
import { t as dingtalkHttp } from "./http-client-DFWZgO1n.mjs";
|
|
5
5
|
import "./utils-CIfI_3Jh.mjs";
|
|
6
|
-
import { S as finalClean, f as getActiveCardForConversation, n as sendMediaToDingTalk, o as sendTextToDingTalk } from "./messaging-
|
|
6
|
+
import { S as finalClean, f as getActiveCardForConversation, n as sendMediaToDingTalk, o as sendTextToDingTalk } from "./messaging-msXFq5IJ.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
|
|
@@ -930,7 +930,7 @@ async function monitorDingtalkProvider(opts = {}) {
|
|
|
930
930
|
const log = createLogger(cfg.channels?.["dingtalk-connector"]?.debug ?? false);
|
|
931
931
|
const [accountsModule, monitorAccountModule, monitorSingleModule] = await Promise.all([
|
|
932
932
|
import("./accounts-BQptOmgB.mjs"),
|
|
933
|
-
import("./message-handler-
|
|
933
|
+
import("./message-handler-DVXM5olz.mjs"),
|
|
934
934
|
import("./connection-DHHFFNQJ.mjs")
|
|
935
935
|
]);
|
|
936
936
|
const { resolveDingtalkAccount, listEnabledDingtalkAccounts } = accountsModule;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Release Notes — v0.8.21-fix47(2026-07-20)
|
|
2
|
+
|
|
3
|
+
## 安装 / Install
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx -y @jeik/dingtalk-connector install --force
|
|
7
|
+
openclaw gateway restart
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## 修复 / Fixed
|
|
11
|
+
|
|
12
|
+
### `file://` MD 本地图灰图
|
|
13
|
+
|
|
14
|
+
**现象(fix46 日志):**
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
扫描 ![]() | #2 kind=http path=file:///mnt/smb/...
|
|
18
|
+
processImagesForOutbound 远程图 | file:///mnt/...
|
|
19
|
+
远程图下载异常 | fetch failed
|
|
20
|
+
localTried=0 remoteTried=3
|
|
21
|
+
API前 mdImgs 仍含 http:file:///...
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**原因:** `looksLikeRemoteUrl` 把任意含 `://` 的字符串当远程;`isLocalImageRef` 又先调用它,`file://` 永远进不了本地上传。
|
|
25
|
+
|
|
26
|
+
**修复:** `file://` / `MEDIA:` / `attachment://` 优先判本地 → `toLocalPath` → 上传 mediaId。
|
|
27
|
+
|
|
28
|
+
裸绝对路径 `/mnt/...`、`/tmp/...` 本来就正常;本版修的是 **带 `file://` 前缀** 的写法。
|
|
29
|
+
|
|
30
|
+
## 升级
|
|
31
|
+
|
|
32
|
+
从 fix46 直接 `--force` 安装。
|
package/package.json
CHANGED
|
@@ -28,18 +28,17 @@ export const IMAGE_EXTENSIONS = /\.(png|jpg|jpeg|gif|bmp|webp|tiff|svg)$/i;
|
|
|
28
28
|
*/
|
|
29
29
|
export const LOCAL_IMAGE_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
30
30
|
|
|
31
|
-
/**
|
|
31
|
+
/** 是否为需上传的本地图引用(与 media.ts 权威实现一致:file:// 必须算本地) */
|
|
32
32
|
export function isLocalImageRef(rawPath: string): boolean {
|
|
33
33
|
const p = (rawPath || "").trim();
|
|
34
34
|
if (!p) return false;
|
|
35
|
-
|
|
36
|
-
if (p.includes("://") && !p.startsWith("file://") && !p.startsWith("MEDIA:") && !p.startsWith("attachment://")) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
if (p.startsWith("@") && !p.includes("/") && !p.includes("\\")) return false;
|
|
35
|
+
// file:// 等本地 scheme 优先(勿被 includes("://") 挡掉)
|
|
40
36
|
if (p.startsWith("file://") || p.startsWith("MEDIA:") || p.startsWith("attachment://")) {
|
|
41
37
|
return true;
|
|
42
38
|
}
|
|
39
|
+
if (/^https?:\/\//i.test(p)) return false;
|
|
40
|
+
if (p.includes("://")) return false;
|
|
41
|
+
if (p.startsWith("@") && !p.includes("/") && !p.includes("\\")) return false;
|
|
43
42
|
if (p.startsWith("/") || /^[A-Za-z]:[\\/]/.test(p)) {
|
|
44
43
|
if (IMAGE_EXTENSIONS.test(p.split("?")[0] || p)) return true;
|
|
45
44
|
return !p.includes("://");
|
package/src/services/media.ts
CHANGED
|
@@ -45,11 +45,26 @@ export const IMAGE_EXTENSIONS = /\.(png|jpg|jpeg|gif|bmp|webp|tiff|svg)$/i;
|
|
|
45
45
|
*/
|
|
46
46
|
export const LOCAL_IMAGE_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
47
47
|
|
|
48
|
-
/**
|
|
48
|
+
/** 本地文件 URI / OpenClaw 媒体前缀(不是 http 远程) */
|
|
49
|
+
function isLocalFileScheme(p: string): boolean {
|
|
50
|
+
return (
|
|
51
|
+
p.startsWith("file://") ||
|
|
52
|
+
p.startsWith("MEDIA:") ||
|
|
53
|
+
p.startsWith("attachment://")
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 是否像远程 URL(禁止当本地路径上传)。
|
|
59
|
+
* **不含** file:// / MEDIA: / attachment://(那些是本地引用)。
|
|
60
|
+
*/
|
|
49
61
|
export function looksLikeRemoteUrl(raw: string): boolean {
|
|
50
62
|
const p = (raw || "").trim();
|
|
51
63
|
if (!p) return false;
|
|
64
|
+
// 本地 scheme 优先:否则 file:// 会被 includes("://") 误判成远程 → fetch 失败 → 灰图
|
|
65
|
+
if (isLocalFileScheme(p)) return false;
|
|
52
66
|
if (/^https?:\/\//i.test(p)) return true;
|
|
67
|
+
// 伪协议截断如 p://(Windows 路径被当 URL 的历史坑)
|
|
53
68
|
if (/^[a-z]:\/\//i.test(p) && !/^[a-z]:[\\/][^/\\]/i.test(p)) return true;
|
|
54
69
|
if (p.includes("://")) return true;
|
|
55
70
|
return false;
|
|
@@ -156,12 +171,11 @@ export function protectNonImageOccurrencesOfTargets(
|
|
|
156
171
|
export function isLocalImageRef(rawPath: string): boolean {
|
|
157
172
|
const p = (rawPath || "").trim();
|
|
158
173
|
if (!p) return false;
|
|
174
|
+
// file:// / MEDIA: / attachment:// 一律本地(必须先于 looksLikeRemoteUrl)
|
|
175
|
+
if (isLocalFileScheme(p)) return true;
|
|
159
176
|
// 已是远程 URL 或钉钉 mediaId(@ 开头)→ 不上传
|
|
160
177
|
if (looksLikeRemoteUrl(p) || /^https?:\/\//i.test(p)) return false;
|
|
161
178
|
if (p.startsWith("@") && !p.includes("/") && !p.includes("\\")) return false;
|
|
162
|
-
if (p.startsWith("file://") || p.startsWith("MEDIA:") || p.startsWith("attachment://")) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
179
|
// Unix 绝对路径 / Windows 盘符
|
|
166
180
|
if (p.startsWith("/") || /^[A-Za-z]:[\\/]/.test(p)) {
|
|
167
181
|
// 有图片后缀,或路径中明显是文件(含扩展名)
|