@jeik/dingtalk-connector 0.8.32 → 0.8.34
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 +20 -0
- package/dist/card-content-cache-BsFPIwOr.mjs +2 -0
- package/dist/{runtime-CjE4Z9G5.mjs → channel-HfPzJGwO.mjs} +18 -29
- package/dist/chunk-upload-CNlZg1SF.mjs +2 -0
- package/dist/{common-BfIYs1yC.mjs → common-1-GDZ2h3.mjs} +2 -2
- package/dist/{common-C0Oaf0z-.mjs → common-DCVdWMiZ.mjs} +1 -1
- package/dist/{connection-obtrPkj4.mjs → connection-Bh3U9I4x.mjs} +2 -2
- package/dist/dws-delivery-context-DLR1ghNQ.mjs +272 -0
- package/dist/entry-bundled.mjs +1 -1
- package/dist/gateway-methods-CV8y0xGw.mjs +2 -0
- package/dist/{gateway-methods-BdcpfxEZ.mjs → gateway-methods-Ce1FXmCx.mjs} +4 -4
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +3 -2
- package/dist/{message-handler-BeTQQCUe.mjs → message-handler-Dsyk414y.mjs} +43 -14
- package/dist/{messaging-CK0Wz3Ze.mjs → messaging-CwQLykl6.mjs} +1 -1
- package/dist/runtime-DDMzayvA.mjs +26 -0
- package/dist/utils-legacy-Bx5izlVF.mjs +3 -0
- package/openclaw.plugin.json +28 -1
- package/package.json +1 -1
- package/src/config/schema.ts +11 -0
- package/src/core/message-handler.ts +2 -0
- package/src/reply-dispatcher.ts +46 -0
- package/src/services/dws-delivery-context.ts +458 -0
- package/dist/card-content-cache-C7-XHhHw.mjs +0 -2
- package/dist/chunk-upload-BKM1y4Ba.mjs +0 -2
- package/dist/gateway-methods-DQ6TwOAr.mjs +0 -2
- package/dist/utils-legacy-BOqY3zE7.mjs +0 -3
- /package/dist/{background-work-DkaSDqWk.mjs → background-work-874-aK4-.mjs} +0 -0
- /package/dist/{card-content-cache-DT_OYThh.mjs → card-content-cache-CGggfgCg.mjs} +0 -0
- /package/dist/{chunk-upload-CIU5G_ay.mjs → chunk-upload-z185bTqH.mjs} +0 -0
- /package/dist/{game-xiyou-uwsv23AC.mjs → game-xiyou-CKoWJobs.mjs} +0 -0
- /package/dist/{utils-legacy-DQ3HeGHh.mjs → utils-legacy-CGEa8tg2.mjs} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ 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.34] - 2026-07-31
|
|
9
|
+
|
|
10
|
+
### Fixes
|
|
11
|
+
|
|
12
|
+
- **dwsDeliveryContext 在 jeikclaw 上无法注入** — 插件原先只 `import("openclaw/plugin-sdk/outbound-runtime")`,而生产安装包名为 `jeikclaw`,导致模块解析失败、目标会话写不进 outbound_message。现按顺序尝试 `openclaw` / `jeikclaw` / 从 gateway 入口 resolve 包路径;并改为始终 `console` 输出注入结果,便于无 debug 时排障。解析命令时折叠 shell `\` 续行。
|
|
13
|
+
|
|
14
|
+
## [0.8.33] - 2026-07-31
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
- **dws 发消息成功后注入 outbound_message 上下文** — 与 `message` 工具 OC-4 一致:当 agent 通过 `dws chat message send|send-by-bot|reply|send-by-webhook` 发消息成功时,自动向目标会话写入模型可见的出站上下文(来源/调用人/正文/可复制 ID)。
|
|
19
|
+
- 配置项 `channels.dingtalk-connector.dwsDeliveryContext`:`target`(默认)/ `source` / `both` / `off`
|
|
20
|
+
- **仅叠加**:不影响普通回复与 message 工具;解析失败或非发消息命令时 no-op
|
|
21
|
+
- 实现:`src/services/dws-delivery-context.ts` + `onCommandOutput` 钩子;从命令行解析 `--group`/`--user` 后经 `resolveOutboundSessionRoute` 映射 sessionKey
|
|
22
|
+
- 依赖 OpenClaw(≥ 本配套版本)`plugin-sdk/outbound-runtime` 导出 `appendOutboundMessageDeliveryContext`
|
|
23
|
+
|
|
24
|
+
### Docs
|
|
25
|
+
|
|
26
|
+
- **CHANGELOG / schema / openclaw.plugin.json** — 同步 `dwsDeliveryContext` 字段说明与 UI help。
|
|
27
|
+
|
|
8
28
|
## [0.8.32] - 2026-07-29
|
|
9
29
|
|
|
10
30
|
### Features
|
|
@@ -3,7 +3,7 @@ import { a as resolveDingtalkAccount, c as addWildcardAllowFrom, d as hasConfigu
|
|
|
3
3
|
import { t as createLogger } from "./logger-CnBTcwyq.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-CwQLykl6.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
|
|
@@ -111,6 +111,20 @@ const DingtalkSharedConfigShape = {
|
|
|
111
111
|
*/
|
|
112
112
|
messageAnswerCard: z$1.boolean().optional(),
|
|
113
113
|
groupReplyMode: GroupReplyModeSchema,
|
|
114
|
+
/**
|
|
115
|
+
* dws CLI 发消息成功后,是否写入与 message 工具一致的 outbound_message 上下文。
|
|
116
|
+
* - target(默认):写入目标会话(群/好友),对方会话后续能看见「谁让 bot 发了什么」
|
|
117
|
+
* - source:写入发起会话
|
|
118
|
+
* - both:两边都写
|
|
119
|
+
* - off:关闭(完全不改行为)
|
|
120
|
+
* 仅叠加:不影响普通回复 / message 工具;解析失败或 dws 非发消息命令时 no-op。
|
|
121
|
+
*/
|
|
122
|
+
dwsDeliveryContext: z$1.enum([
|
|
123
|
+
"off",
|
|
124
|
+
"target",
|
|
125
|
+
"source",
|
|
126
|
+
"both"
|
|
127
|
+
]).optional(),
|
|
114
128
|
/** AI Card 模板 ID,不填则使用官方默认模板 */
|
|
115
129
|
cardTemplateId: z$1.string().optional(),
|
|
116
130
|
/** AI Card 内容变量名,对应卡片模板中的变量字段,不填默认 content(与默认增强模板一致) */
|
|
@@ -956,8 +970,8 @@ async function monitorDingtalkProvider(opts = {}) {
|
|
|
956
970
|
const log = createLogger(cfg.channels?.["dingtalk-connector"]?.debug ?? false);
|
|
957
971
|
const [accountsModule, monitorAccountModule, monitorSingleModule] = await Promise.all([
|
|
958
972
|
import("./accounts-BQptOmgB.mjs"),
|
|
959
|
-
import("./message-handler-
|
|
960
|
-
import("./connection-
|
|
973
|
+
import("./message-handler-Dsyk414y.mjs"),
|
|
974
|
+
import("./connection-Bh3U9I4x.mjs")
|
|
961
975
|
]);
|
|
962
976
|
const { resolveDingtalkAccount, listEnabledDingtalkAccounts } = accountsModule;
|
|
963
977
|
const { handleDingTalkMessage } = monitorAccountModule;
|
|
@@ -1445,29 +1459,4 @@ function initDingtalkPluginConfigSchema() {
|
|
|
1445
1459
|
dingtalkPlugin.configSchema = buildChannelConfigSchema(DingtalkConfigBaseSchema);
|
|
1446
1460
|
}
|
|
1447
1461
|
//#endregion
|
|
1448
|
-
|
|
1449
|
-
/**
|
|
1450
|
-
* 自实现的运行时存储工厂,避免依赖特定版本 openclaw 是否导出 createPluginRuntimeStore。
|
|
1451
|
-
* 旧版 openclaw 没有导出该函数,直接 import 会导致 TypeError,因此在此处内联实现。
|
|
1452
|
-
*/
|
|
1453
|
-
function createRuntimeStore(errorMessage) {
|
|
1454
|
-
let runtimeValue = null;
|
|
1455
|
-
return {
|
|
1456
|
-
setRuntime: (next) => {
|
|
1457
|
-
runtimeValue = next;
|
|
1458
|
-
},
|
|
1459
|
-
clearRuntime: () => {
|
|
1460
|
-
runtimeValue = null;
|
|
1461
|
-
},
|
|
1462
|
-
tryGetRuntime: () => {
|
|
1463
|
-
return runtimeValue;
|
|
1464
|
-
},
|
|
1465
|
-
getRuntime: () => {
|
|
1466
|
-
if (runtimeValue === null) throw new Error(errorMessage);
|
|
1467
|
-
return runtimeValue;
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
}
|
|
1471
|
-
const { setRuntime: setDingtalkRuntime, getRuntime: getDingtalkRuntime } = createRuntimeStore("DingTalk runtime not initialized");
|
|
1472
|
-
//#endregion
|
|
1473
|
-
export { initDingtalkPluginConfigSchema as a, dingtalkPlugin as i, setDingtalkRuntime as n, CHANNEL_ID as r, getDingtalkRuntime as t };
|
|
1462
|
+
export { dingtalkPlugin as n, initDingtalkPluginConfigSchema as r, CHANNEL_ID as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as createLogger } from "./logger-CnBTcwyq.mjs";
|
|
2
2
|
import { r as dingtalkUploadHttp } from "./http-client-DFWZgO1n.mjs";
|
|
3
|
-
import { t as CHUNK_CONFIG } from "./chunk-upload-
|
|
3
|
+
import { t as CHUNK_CONFIG } from "./chunk-upload-z185bTqH.mjs";
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import FormData from "form-data";
|
|
@@ -48,7 +48,7 @@ async function uploadMediaToDingTalk(filePath, mediaType, oapiToken, maxSize = 2
|
|
|
48
48
|
if ((mediaType === "video" || mediaType === "file") && fileSize > CHUNK_CONFIG.SIZE_THRESHOLD) {
|
|
49
49
|
log?.info?.(`文件超过 20MB,使用分块上传:${absPath} (${fileSizeMB}MB)`);
|
|
50
50
|
try {
|
|
51
|
-
const { uploadLargeFileByChunks } = await import("./chunk-upload-
|
|
51
|
+
const { uploadLargeFileByChunks } = await import("./chunk-upload-CNlZg1SF.mjs");
|
|
52
52
|
const downloadCode = await uploadLargeFileByChunks(absPath, mediaType, oapiToken, debugEnabled);
|
|
53
53
|
if (downloadCode) {
|
|
54
54
|
log?.info?.(`分块上传成功:${absPath}, download_code: ${downloadCode}`);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as VIDEO_MARKER_PATTERN, r as FILE_MARKER_PATTERN, t as AUDIO_MARKER_PATTERN } from "./common-
|
|
1
|
+
import { i as VIDEO_MARKER_PATTERN, r as FILE_MARKER_PATTERN, t as AUDIO_MARKER_PATTERN } from "./common-1-GDZ2h3.mjs";
|
|
2
2
|
export { AUDIO_MARKER_PATTERN, FILE_MARKER_PATTERN, VIDEO_MARKER_PATTERN };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as checkAndMarkDingtalkMessage } from "./utils-legacy-
|
|
2
|
-
import { n as onBackgroundWorkCountChange, t as getActiveBackgroundWorkCount } from "./background-work-
|
|
1
|
+
import { i as checkAndMarkDingtalkMessage } from "./utils-legacy-CGEa8tg2.mjs";
|
|
2
|
+
import { n as onBackgroundWorkCountChange, t as getActiveBackgroundWorkCount } from "./background-work-874-aK4-.mjs";
|
|
3
3
|
import * as fs from "fs";
|
|
4
4
|
//#region src/core/connection.ts
|
|
5
5
|
/**
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { t as CHANNEL_ID } from "./channel-HfPzJGwO.mjs";
|
|
2
|
+
//#region src/services/dws-delivery-context.ts
|
|
3
|
+
/**
|
|
4
|
+
* DWS 发消息成功后注入 outbound_message 上下文(对齐 OpenClaw message 工具 OC-4)。
|
|
5
|
+
*
|
|
6
|
+
* - 不修改 dws 本体:仅解析 OpenClaw exec/shell 回调里看到的命令行
|
|
7
|
+
* - 默认开启(target):只在 dws 发消息成功时追加上下文,不影响普通回复 / message 工具
|
|
8
|
+
* - 可配置 off | target | source | both
|
|
9
|
+
*/
|
|
10
|
+
const SEND_COMMAND_RE = /\bdws\b(?:\s+[^\s]+)*\s+chat\s+message\s+(send-by-bot|send-by-webhook|send|reply)\b/i;
|
|
11
|
+
/** 从命令行提取 --flag value / --flag=value / 布尔 --flag */
|
|
12
|
+
function extractFlag(cmd, name) {
|
|
13
|
+
const eq = new RegExp(`--${name}(?:=|\\s+)(?:"([^"]*)"|'([^']*)'|(\\S+))`, "i");
|
|
14
|
+
const m = cmd.match(eq);
|
|
15
|
+
if (!m) return void 0;
|
|
16
|
+
return (m[1] ?? m[2] ?? m[3] ?? "").trim() || void 0;
|
|
17
|
+
}
|
|
18
|
+
function hasBoolFlag(cmd, name) {
|
|
19
|
+
return new RegExp(`(?:^|\\s)--${name}(?:\\s|=|$)`, "i").test(cmd);
|
|
20
|
+
}
|
|
21
|
+
function splitCsv(raw) {
|
|
22
|
+
if (!raw) return void 0;
|
|
23
|
+
const parts = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
24
|
+
return parts.length ? parts : void 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 判断是否为 dws 发消息类命令,并解析关键参数。
|
|
28
|
+
* 解析失败返回 null(调用方 no-op,不影响现有体验)。
|
|
29
|
+
*/
|
|
30
|
+
/** 折叠 shell 续行 `\` + 换行,便于从 tool title/output 里解析 */
|
|
31
|
+
function normalizeShellCommandText(raw) {
|
|
32
|
+
return String(raw || "").replace(/\\\r?\n/g, " ").replace(/\r?\n/g, " ").replace(/[ \t]+/g, " ").trim();
|
|
33
|
+
}
|
|
34
|
+
function parseDwsSendCommand(commandText) {
|
|
35
|
+
const cmd = normalizeShellCommandText(commandText);
|
|
36
|
+
if (!cmd) return null;
|
|
37
|
+
const m = cmd.match(SEND_COMMAND_RE);
|
|
38
|
+
if (!m) return null;
|
|
39
|
+
const sub = m[1].toLowerCase();
|
|
40
|
+
let kind;
|
|
41
|
+
if (sub === "send-by-bot") kind = "bot-send";
|
|
42
|
+
else if (sub === "send-by-webhook") kind = "webhook-send";
|
|
43
|
+
else if (sub === "reply") kind = "reply";
|
|
44
|
+
else kind = "user-send";
|
|
45
|
+
const group = extractFlag(cmd, "group") || extractFlag(cmd, "conversation-id") || extractFlag(cmd, "id") || extractFlag(cmd, "chat");
|
|
46
|
+
const user = extractFlag(cmd, "user") || extractFlag(cmd, "open-dingtalk-id") || splitCsv(extractFlag(cmd, "users"))?.[0] || splitCsv(extractFlag(cmd, "open-dingtalk-ids"))?.[0];
|
|
47
|
+
const text = extractFlag(cmd, "text") || extractFlag(cmd, "content") || extractFlag(cmd, "body") || extractFlag(cmd, "message") || extractFlag(cmd, "markdown");
|
|
48
|
+
let target;
|
|
49
|
+
let rawTarget;
|
|
50
|
+
let targetChatType;
|
|
51
|
+
if (group) {
|
|
52
|
+
rawTarget = group.replace(/^(group:|channel:)/i, "");
|
|
53
|
+
target = `group:${rawTarget}`;
|
|
54
|
+
targetChatType = "group";
|
|
55
|
+
} else if (user) {
|
|
56
|
+
rawTarget = user.replace(/^(user:|dm:)/i, "");
|
|
57
|
+
target = `user:${rawTarget}`;
|
|
58
|
+
targetChatType = "direct";
|
|
59
|
+
}
|
|
60
|
+
if (kind === "webhook-send" && !target) return {
|
|
61
|
+
kind,
|
|
62
|
+
message: text,
|
|
63
|
+
title: extractFlag(cmd, "title"),
|
|
64
|
+
atAll: hasBoolFlag(cmd, "at-all"),
|
|
65
|
+
atUserIds: splitCsv(extractFlag(cmd, "at-users")),
|
|
66
|
+
atMobiles: splitCsv(extractFlag(cmd, "at-mobiles")),
|
|
67
|
+
command: cmd.slice(0, 2e3)
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
kind,
|
|
71
|
+
target,
|
|
72
|
+
rawTarget,
|
|
73
|
+
targetChatType,
|
|
74
|
+
message: text,
|
|
75
|
+
title: extractFlag(cmd, "title"),
|
|
76
|
+
atAll: hasBoolFlag(cmd, "at-all"),
|
|
77
|
+
atUserIds: splitCsv(extractFlag(cmd, "at-user-ids")) || splitCsv(extractFlag(cmd, "at-users")),
|
|
78
|
+
atOpenDingTalkIds: splitCsv(extractFlag(cmd, "at-open-dingtalk-ids")),
|
|
79
|
+
atMobiles: splitCsv(extractFlag(cmd, "at-mobiles")),
|
|
80
|
+
robotCode: extractFlag(cmd, "robot-code"),
|
|
81
|
+
command: cmd.slice(0, 2e3)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function resolveDwsDeliveryContextMode(config) {
|
|
85
|
+
const raw = config?.dwsDeliveryContext;
|
|
86
|
+
if (raw === "off" || raw === false) return "off";
|
|
87
|
+
if (raw === "source" || raw === "both" || raw === "target") return raw;
|
|
88
|
+
if (raw === true || raw === void 0 || raw === null) return "target";
|
|
89
|
+
return "off";
|
|
90
|
+
}
|
|
91
|
+
let warnedMissingApi = false;
|
|
92
|
+
/** 始终打到 console,不依赖 debug 开关(否则生产无法排障) */
|
|
93
|
+
function alwaysLog(level, msg) {
|
|
94
|
+
const line = `[DingTalk][dwsDeliveryContext] ${msg}`;
|
|
95
|
+
if (level === "error") console.error(line);
|
|
96
|
+
else if (level === "warn") console.warn(line);
|
|
97
|
+
else console.log(line);
|
|
98
|
+
}
|
|
99
|
+
function resolveModeFromConfigs(cfg, accountConfig) {
|
|
100
|
+
if (accountConfig?.dwsDeliveryContext !== void 0) return resolveDwsDeliveryContextMode(accountConfig);
|
|
101
|
+
const channelCfg = cfg?.channels?.[CHANNEL_ID];
|
|
102
|
+
if (channelCfg?.dwsDeliveryContext !== void 0) return resolveDwsDeliveryContextMode(channelCfg);
|
|
103
|
+
return "target";
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 加载 OC-4 append API。
|
|
107
|
+
*
|
|
108
|
+
* 注意:钉钉插件装在 ~/.openclaw/npm/projects/... 下,Node 从插件路径
|
|
109
|
+
* 解析不到名为 openclaw/jeikclaw 的 package(包名还可能是 jeikclaw)。
|
|
110
|
+
* 必须用 gateway 进程入口(process.argv[1])定位 dist/plugin-sdk。
|
|
111
|
+
*/
|
|
112
|
+
async function loadOutboundRuntime() {
|
|
113
|
+
const { pathToFileURL } = await import("node:url");
|
|
114
|
+
const path = await import("node:path");
|
|
115
|
+
const fs = await import("node:fs");
|
|
116
|
+
const { createRequire } = await import("node:module");
|
|
117
|
+
const candidates = [
|
|
118
|
+
"openclaw/plugin-sdk/outbound-runtime",
|
|
119
|
+
"jeikclaw/plugin-sdk/outbound-runtime",
|
|
120
|
+
"jeikclaw/dist/plugin-sdk/outbound-runtime.js",
|
|
121
|
+
"openclaw/dist/plugin-sdk/outbound-runtime.js"
|
|
122
|
+
];
|
|
123
|
+
const pushIfExists = (filePath) => {
|
|
124
|
+
try {
|
|
125
|
+
if (filePath && fs.existsSync(filePath)) candidates.push(pathToFileURL(filePath).href);
|
|
126
|
+
} catch {}
|
|
127
|
+
};
|
|
128
|
+
const entry = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
129
|
+
if (entry) {
|
|
130
|
+
const entryDir = path.dirname(path.resolve(entry));
|
|
131
|
+
pushIfExists(path.join(entryDir, "plugin-sdk", "outbound-runtime.js"));
|
|
132
|
+
pushIfExists(path.join(entryDir, "dist", "plugin-sdk", "outbound-runtime.js"));
|
|
133
|
+
let dir = entryDir;
|
|
134
|
+
for (let i = 0; i < 5; i++) {
|
|
135
|
+
const pkgJson = path.join(dir, "package.json");
|
|
136
|
+
if (fs.existsSync(pkgJson)) {
|
|
137
|
+
pushIfExists(path.join(dir, "dist", "plugin-sdk", "outbound-runtime.js"));
|
|
138
|
+
pushIfExists(path.join(dir, "plugin-sdk", "outbound-runtime.js"));
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
const parent = path.dirname(dir);
|
|
142
|
+
if (parent === dir) break;
|
|
143
|
+
dir = parent;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const req = createRequire(pathToFileURL(path.resolve(entry)).href);
|
|
147
|
+
for (const name of ["jeikclaw", "openclaw"]) try {
|
|
148
|
+
const pkgJson = req.resolve(`${name}/package.json`);
|
|
149
|
+
const root = path.dirname(pkgJson);
|
|
150
|
+
pushIfExists(path.join(root, "dist", "plugin-sdk", "outbound-runtime.js"));
|
|
151
|
+
} catch {}
|
|
152
|
+
} catch {}
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const execDir = path.dirname(process.execPath);
|
|
156
|
+
pushIfExists(path.join(execDir, "..", "lib", "node_modules", "jeikclaw", "dist", "plugin-sdk", "outbound-runtime.js"));
|
|
157
|
+
pushIfExists(path.join(execDir, "..", "lib", "node_modules", "openclaw", "dist", "plugin-sdk", "outbound-runtime.js"));
|
|
158
|
+
} catch {}
|
|
159
|
+
const errors = [];
|
|
160
|
+
const seen = /* @__PURE__ */ new Set();
|
|
161
|
+
for (const id of candidates) {
|
|
162
|
+
if (!id || seen.has(id)) continue;
|
|
163
|
+
seen.add(id);
|
|
164
|
+
try {
|
|
165
|
+
const oc = await import(id);
|
|
166
|
+
if (typeof oc.appendOutboundMessageDeliveryContext === "function") return {
|
|
167
|
+
append: oc.appendOutboundMessageDeliveryContext.bind(oc),
|
|
168
|
+
resolveRoute: typeof oc.resolveOutboundSessionRoute === "function" ? oc.resolveOutboundSessionRoute.bind(oc) : void 0,
|
|
169
|
+
ensureEntry: typeof oc.ensureOutboundSessionEntry === "function" ? oc.ensureOutboundSessionEntry.bind(oc) : void 0,
|
|
170
|
+
via: id
|
|
171
|
+
};
|
|
172
|
+
errors.push(`${id}: no append export`);
|
|
173
|
+
} catch (e) {
|
|
174
|
+
errors.push(`${id}: ${e?.message || e}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (!warnedMissingApi) {
|
|
178
|
+
warnedMissingApi = true;
|
|
179
|
+
alwaysLog("warn", `无法加载 outbound-runtime。argv1=${entry || "-"} tried=${seen.size} err=${errors.slice(0, 4).join(" | ")}`);
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* 在 dws 发消息命令成功结束后,向目标/来源会话写入 outbound_message。
|
|
185
|
+
* 全程 best-effort,失败只打日志。
|
|
186
|
+
*/
|
|
187
|
+
async function maybeInjectDwsOutboundContext(params) {
|
|
188
|
+
const log = params.log;
|
|
189
|
+
const effectiveMode = resolveModeFromConfigs(params.cfg, params.accountConfig);
|
|
190
|
+
if (effectiveMode === "off") return false;
|
|
191
|
+
if (params.phase && params.phase !== "end") return false;
|
|
192
|
+
if (params.exitCode !== void 0 && params.exitCode !== null && params.exitCode !== 0) return false;
|
|
193
|
+
const parsed = parseDwsSendCommand(params.commandText);
|
|
194
|
+
if (!parsed) return false;
|
|
195
|
+
if (!parsed.target && effectiveMode === "target") {
|
|
196
|
+
alwaysLog("warn", `解析到 dws ${parsed.kind} 但无 --group/--user 目标,跳过 target 注入。cmd=${parsed.command.slice(0, 160)}`);
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
const oc = await loadOutboundRuntime();
|
|
201
|
+
if (!oc?.append) return false;
|
|
202
|
+
let targetRoute = null;
|
|
203
|
+
const targetTo = parsed.target;
|
|
204
|
+
if (targetTo && typeof oc.resolveRoute === "function") try {
|
|
205
|
+
targetRoute = await oc.resolveRoute({
|
|
206
|
+
cfg: params.cfg,
|
|
207
|
+
channel: CHANNEL_ID,
|
|
208
|
+
agentId: params.agentId,
|
|
209
|
+
accountId: params.accountId,
|
|
210
|
+
target: targetTo,
|
|
211
|
+
currentSessionKey: params.sourceSessionKey
|
|
212
|
+
});
|
|
213
|
+
if (targetRoute && typeof oc.ensureEntry === "function") await oc.ensureEntry({
|
|
214
|
+
cfg: params.cfg,
|
|
215
|
+
channel: CHANNEL_ID,
|
|
216
|
+
accountId: params.accountId,
|
|
217
|
+
route: targetRoute
|
|
218
|
+
});
|
|
219
|
+
} catch (err) {
|
|
220
|
+
alwaysLog("warn", `resolveOutboundSessionRoute 失败: ${err?.message || err}`);
|
|
221
|
+
log?.warn?.(`[DingTalk][dwsDeliveryContext] resolveOutboundSessionRoute 失败: ${err?.message || err}`);
|
|
222
|
+
}
|
|
223
|
+
if (effectiveMode === "target" && !targetRoute?.sessionKey) {
|
|
224
|
+
alwaysLog("warn", `target 模式但未解析到 sessionKey,无法写入目标会话。targetTo=${targetTo} via=${oc.via}`);
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const action = parsed.kind === "bot-send" ? "dws.chat.message.send-by-bot" : parsed.kind === "webhook-send" ? "dws.chat.message.send-by-webhook" : parsed.kind === "reply" ? "dws.chat.message.reply" : "dws.chat.message.send";
|
|
228
|
+
const actionParams = {
|
|
229
|
+
action: "send",
|
|
230
|
+
via: "dws",
|
|
231
|
+
dwsKind: parsed.kind,
|
|
232
|
+
message: parsed.message ?? "",
|
|
233
|
+
title: parsed.title,
|
|
234
|
+
target: targetTo,
|
|
235
|
+
to: parsed.rawTarget,
|
|
236
|
+
channel: CHANNEL_ID,
|
|
237
|
+
accountId: params.accountId,
|
|
238
|
+
atAll: parsed.atAll || void 0,
|
|
239
|
+
atUserIds: parsed.atUserIds,
|
|
240
|
+
atOpenDingTalkIds: parsed.atOpenDingTalkIds,
|
|
241
|
+
atMobiles: parsed.atMobiles,
|
|
242
|
+
robotCode: parsed.robotCode,
|
|
243
|
+
command: parsed.command
|
|
244
|
+
};
|
|
245
|
+
const idempotencyKey = params.toolCallId?.trim() || `dws:${params.sourceSessionKey}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
|
|
246
|
+
await oc.append({
|
|
247
|
+
cfg: params.cfg,
|
|
248
|
+
mode: effectiveMode,
|
|
249
|
+
agentId: params.agentId,
|
|
250
|
+
sourceSessionKey: params.sourceSessionKey,
|
|
251
|
+
sourceAccountId: params.accountId,
|
|
252
|
+
invokerId: params.invokerId,
|
|
253
|
+
invokerName: params.invokerName,
|
|
254
|
+
targetTo: targetTo || params.sourceSessionKey,
|
|
255
|
+
targetChannel: CHANNEL_ID,
|
|
256
|
+
targetAccountId: params.accountId,
|
|
257
|
+
targetRoute,
|
|
258
|
+
actionParams,
|
|
259
|
+
action,
|
|
260
|
+
idempotencyKey
|
|
261
|
+
});
|
|
262
|
+
alwaysLog("info", `已注入 outbound_message mode=${effectiveMode} kind=${parsed.kind} target=${targetTo || "-"} route=${targetRoute?.sessionKey || "-"} via=${oc.via}`);
|
|
263
|
+
log?.info?.(`[DingTalk][dwsDeliveryContext] 已注入 outbound_message mode=${effectiveMode} kind=${parsed.kind} target=${targetTo || "-"} route=${targetRoute?.sessionKey || "-"}`);
|
|
264
|
+
return true;
|
|
265
|
+
} catch (err) {
|
|
266
|
+
alwaysLog("warn", `注入失败(已忽略,不影响发消息): ${err?.message || err}`);
|
|
267
|
+
log?.warn?.(`[DingTalk][dwsDeliveryContext] 注入失败(已忽略,不影响发消息): ${err?.message || err}`);
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
272
|
+
export { maybeInjectDwsOutboundContext };
|
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-CV8y0xGw.mjs");
|
|
27
27
|
registerGatewayMethods(api);
|
|
28
28
|
}
|
|
29
29
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
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-
|
|
5
|
-
import { d as getUnionId, h as recallEmotionReply } from "./utils-legacy-
|
|
4
|
+
import { c as prepareMultiBotMentions, d as finishAICard, i as sendProactive, s as buildBotMentionTable } from "./messaging-CwQLykl6.mjs";
|
|
5
|
+
import { d as getUnionId, h as recallEmotionReply } from "./utils-legacy-CGEa8tg2.mjs";
|
|
6
6
|
//#region src/docs.ts
|
|
7
7
|
var DingtalkDocsClient = class {
|
|
8
8
|
config;
|
|
@@ -592,7 +592,7 @@ function registerGatewayMethods(api) {
|
|
|
592
592
|
});
|
|
593
593
|
const results = {};
|
|
594
594
|
if (cardInstanceId) try {
|
|
595
|
-
const { getAccessToken } = await import("./utils-legacy-
|
|
595
|
+
const { getAccessToken } = await import("./utils-legacy-Bx5izlVF.mjs");
|
|
596
596
|
const token = await getAccessToken(account.config);
|
|
597
597
|
await finishAICard({
|
|
598
598
|
cardInstanceId: String(cardInstanceId),
|
|
@@ -752,7 +752,7 @@ function registerGatewayMethods(api) {
|
|
|
752
752
|
try {
|
|
753
753
|
const account = resolveDingtalkAccount({ cfg });
|
|
754
754
|
if (!account.config?.clientId || !account.config?.clientSecret) return respond(false, { error: "Not configured" });
|
|
755
|
-
const { getAccessToken } = await import("./utils-legacy-
|
|
755
|
+
const { getAccessToken } = await import("./utils-legacy-Bx5izlVF.mjs");
|
|
756
756
|
await getAccessToken(account.config);
|
|
757
757
|
respond(true, {
|
|
758
758
|
ok: true,
|
package/dist/index.d.mts
CHANGED
|
@@ -76,6 +76,12 @@ declare const DingtalkConfigSchema: z$1.ZodObject<{
|
|
|
76
76
|
text: "text";
|
|
77
77
|
markdown: "markdown";
|
|
78
78
|
}>>;
|
|
79
|
+
dwsDeliveryContext: z$1.ZodOptional<z$1.ZodEnum<{
|
|
80
|
+
source: "source";
|
|
81
|
+
off: "off";
|
|
82
|
+
target: "target";
|
|
83
|
+
both: "both";
|
|
84
|
+
}>>;
|
|
79
85
|
cardTemplateId: z$1.ZodOptional<z$1.ZodString>;
|
|
80
86
|
cardContentVar: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
81
87
|
answerCard: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
@@ -134,6 +140,12 @@ declare const DingtalkConfigSchema: z$1.ZodObject<{
|
|
|
134
140
|
text: "text";
|
|
135
141
|
markdown: "markdown";
|
|
136
142
|
}>>;
|
|
143
|
+
dwsDeliveryContext: z$1.ZodOptional<z$1.ZodEnum<{
|
|
144
|
+
source: "source";
|
|
145
|
+
off: "off";
|
|
146
|
+
target: "target";
|
|
147
|
+
both: "both";
|
|
148
|
+
}>>;
|
|
137
149
|
cardTemplateId: z$1.ZodOptional<z$1.ZodString>;
|
|
138
150
|
cardContentVar: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodString>>;
|
|
139
151
|
answerCard: z$1.ZodOptional<z$1.ZodBoolean>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as dingtalkPlugin, r as initDingtalkPluginConfigSchema } from "./channel-HfPzJGwO.mjs";
|
|
2
|
+
import { n as setDingtalkRuntime } from "./runtime-DDMzayvA.mjs";
|
|
3
|
+
import { t as registerGatewayMethods } from "./gateway-methods-Ce1FXmCx.mjs";
|
|
3
4
|
//#region index.ts
|
|
4
5
|
/**
|
|
5
6
|
* 检测同一 plugin id 在多个路径被加载的情况。
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { a as resolveDingtalkAccount } from "./accounts-BAzdqkAV.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { t as CHANNEL_ID } from "./channel-HfPzJGwO.mjs";
|
|
3
3
|
import { n as createLoggerFromConfig, r as isDingtalkDebug } from "./logger-CnBTcwyq.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-CwQLykl6.mjs";
|
|
7
7
|
import { a as QUEUE_BUSY_ACK_PHRASES, n as normalizeSlashCommand, t as buildSessionContext } from "./session-DJ4jYqPv.mjs";
|
|
8
|
-
import {
|
|
9
|
-
import { r as
|
|
10
|
-
import "./
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
8
|
+
import { t as getDingtalkRuntime } from "./runtime-DDMzayvA.mjs";
|
|
9
|
+
import { c as formatSenderRoles, f as getUserProfile, h as recallEmotionReply, l as getAccessToken, o as formatHiredDateShanghai, r as addEmotionReply, s as formatSenderDisplayLabel, t as DINGTALK_API, u as getOapiAccessToken$1 } from "./utils-legacy-CGEa8tg2.mjs";
|
|
10
|
+
import { r as trackBackgroundWork } from "./background-work-874-aK4-.mjs";
|
|
11
|
+
import "./chunk-upload-z185bTqH.mjs";
|
|
12
|
+
import { a as toLocalPath, i as VIDEO_MARKER_PATTERN, o as uploadMediaToDingTalk, r as FILE_MARKER_PATTERN, t as AUDIO_MARKER_PATTERN } from "./common-1-GDZ2h3.mjs";
|
|
13
|
+
import { n as lookupCardContent, t as collectCardLookupIds } from "./card-content-cache-CGggfgCg.mjs";
|
|
13
14
|
import * as fs from "fs";
|
|
14
15
|
import * as path from "path";
|
|
15
16
|
import * as os from "node:os";
|
|
@@ -250,7 +251,7 @@ function readPayloadRawError(payload) {
|
|
|
250
251
|
}
|
|
251
252
|
function createDingtalkReplyDispatcher(params) {
|
|
252
253
|
const core = getDingtalkRuntime();
|
|
253
|
-
const { cfg, agentId, conversationId, senderId, isDirect, accountId, sessionWebhook, asyncMode = false, preCreatedCard } = params;
|
|
254
|
+
const { cfg, agentId, conversationId, senderId, isDirect, accountId, sessionWebhook, asyncMode = false, preCreatedCard, sessionKey: sourceSessionKey, senderName } = params;
|
|
254
255
|
const account = resolveDingtalkAccount({
|
|
255
256
|
cfg,
|
|
256
257
|
accountId
|
|
@@ -633,7 +634,7 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
633
634
|
}
|
|
634
635
|
} else log.info(`[DingTalk][closeStreaming] 养成系统:onCommandOutput 监听到 ${productsToProcess.size} 个 dws 产品: ${[...productsToProcess].join(", ")}`);
|
|
635
636
|
if (productsToProcess.size > 0) {
|
|
636
|
-
const { GamificationEngine } = await import("./game-xiyou-
|
|
637
|
+
const { GamificationEngine } = await import("./game-xiyou-CKoWJobs.mjs");
|
|
637
638
|
const engine = GamificationEngine.getInstanceForUser(senderId);
|
|
638
639
|
if (engine.isEnabled()) {
|
|
639
640
|
const primaryProduct = [...productsToProcess][0];
|
|
@@ -978,7 +979,7 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
978
979
|
currentToolLine = "";
|
|
979
980
|
await startStreaming();
|
|
980
981
|
if (currentCardTarget) try {
|
|
981
|
-
const { FILE_MARKER_PATTERN, VIDEO_MARKER_PATTERN, AUDIO_MARKER_PATTERN } = await import("./common-
|
|
982
|
+
const { FILE_MARKER_PATTERN, VIDEO_MARKER_PATTERN, AUDIO_MARKER_PATTERN } = await import("./common-DCVdWMiZ.mjs");
|
|
982
983
|
await enqueueCardStream(buildCardContent().replace(FILE_MARKER_PATTERN, "").replace(VIDEO_MARKER_PATTERN, "").replace(AUDIO_MARKER_PATTERN, "").trim(), { force: true });
|
|
983
984
|
} catch (err) {
|
|
984
985
|
if (!isQpsLimitError(err)) log.error(`[DingTalk][onPartialReply] final-marker 刷卡失败:${err.message}`);
|
|
@@ -991,7 +992,7 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
991
992
|
if (payload.text?.trim()) hasModelStreamText = true;
|
|
992
993
|
currentToolLine = "";
|
|
993
994
|
try {
|
|
994
|
-
const { FILE_MARKER_PATTERN, VIDEO_MARKER_PATTERN, AUDIO_MARKER_PATTERN } = await import("./common-
|
|
995
|
+
const { FILE_MARKER_PATTERN, VIDEO_MARKER_PATTERN, AUDIO_MARKER_PATTERN } = await import("./common-DCVdWMiZ.mjs");
|
|
995
996
|
await enqueueCardStream(buildCardContent().replace(FILE_MARKER_PATTERN, "").replace(VIDEO_MARKER_PATTERN, "").replace(AUDIO_MARKER_PATTERN, "").trim());
|
|
996
997
|
} catch (err) {
|
|
997
998
|
if (isQpsLimitError(err)) log.warn(`[DingTalk][onPartialReply] QPS 限流,已排队尾随重试 latestLen=${latestCardContent.length}`);
|
|
@@ -1019,7 +1020,8 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
1019
1020
|
}
|
|
1020
1021
|
},
|
|
1021
1022
|
onCommandOutput: (payload) => {
|
|
1022
|
-
const
|
|
1023
|
+
const commandText = payload.title || payload.name || "";
|
|
1024
|
+
const dwsMatch = commandText.match(DWS_PRODUCT_PATTERN) || payload.output?.match(DWS_PRODUCT_PATTERN);
|
|
1023
1025
|
if (dwsMatch) {
|
|
1024
1026
|
const product = dwsMatch[1];
|
|
1025
1027
|
if (!(payload.phase === "end" && payload.exitCode !== null && payload.exitCode !== 0)) {
|
|
@@ -1027,6 +1029,31 @@ function createDingtalkReplyDispatcher(params) {
|
|
|
1027
1029
|
log.info(`[DingTalk][onCommandOutput] 检测到 dws 产品: ${product},phase=${payload.phase}, exitCode=${payload.exitCode}`);
|
|
1028
1030
|
} else log.info(`[DingTalk][onCommandOutput] dws 命令执行失败,跳过: ${product},exitCode=${payload.exitCode}`);
|
|
1029
1031
|
}
|
|
1032
|
+
if ((payload.phase || (payload.exitCode !== void 0 ? "end" : void 0)) === "end" && sourceSessionKey) {
|
|
1033
|
+
const fullCmd = [
|
|
1034
|
+
payload.title,
|
|
1035
|
+
payload.name,
|
|
1036
|
+
payload.output,
|
|
1037
|
+
commandText
|
|
1038
|
+
].filter(Boolean).join("\n") || "";
|
|
1039
|
+
if (/\bdws\b/i.test(fullCmd)) import("./dws-delivery-context-DLR1ghNQ.mjs").then(({ maybeInjectDwsOutboundContext }) => maybeInjectDwsOutboundContext({
|
|
1040
|
+
cfg,
|
|
1041
|
+
accountConfig: account.config,
|
|
1042
|
+
agentId,
|
|
1043
|
+
accountId,
|
|
1044
|
+
sourceSessionKey,
|
|
1045
|
+
invokerId: senderId,
|
|
1046
|
+
invokerName: senderName,
|
|
1047
|
+
commandText: fullCmd,
|
|
1048
|
+
exitCode: payload.exitCode ?? 0,
|
|
1049
|
+
phase: "end",
|
|
1050
|
+
toolCallId: payload.toolCallId,
|
|
1051
|
+
log
|
|
1052
|
+
})).catch((err) => {
|
|
1053
|
+
console.warn(`[DingTalk][dwsDeliveryContext] onCommandOutput 钩子异常: ${err?.message || err}`);
|
|
1054
|
+
log.warn?.(`[DingTalk][dwsDeliveryContext] onCommandOutput 钩子异常: ${err?.message || err}`);
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1030
1057
|
}
|
|
1031
1058
|
},
|
|
1032
1059
|
markDispatchIdle,
|
|
@@ -2008,7 +2035,7 @@ async function handleDingTalkMessageInternal(params) {
|
|
|
2008
2035
|
const rawText = content.text || "";
|
|
2009
2036
|
let userContent = normalizeSlashCommand(rawText) || (content.imageUrls.length > 0 ? "请描述这张图片" : "");
|
|
2010
2037
|
try {
|
|
2011
|
-
const { GamificationEngine, isGamificationCommand } = await import("./game-xiyou-
|
|
2038
|
+
const { GamificationEngine, isGamificationCommand } = await import("./game-xiyou-CKoWJobs.mjs");
|
|
2012
2039
|
if (isGamificationCommand(rawText)) {
|
|
2013
2040
|
const engine = GamificationEngine.getInstanceForUser(senderId);
|
|
2014
2041
|
if (rawText.trim().startsWith("/西游") || engine.isEnabled()) {
|
|
@@ -2277,7 +2304,9 @@ async function handleDingTalkMessageInternal(params) {
|
|
|
2277
2304
|
messageCreateTimeMs: Date.now(),
|
|
2278
2305
|
sessionWebhook: data.sessionWebhook,
|
|
2279
2306
|
asyncMode,
|
|
2280
|
-
preCreatedCard: earlyCard
|
|
2307
|
+
preCreatedCard: earlyCard,
|
|
2308
|
+
sessionKey,
|
|
2309
|
+
senderName
|
|
2281
2310
|
});
|
|
2282
2311
|
finalizeDispatchError = finalizeErr;
|
|
2283
2312
|
if (config.clientId) {
|
|
@@ -371,7 +371,7 @@ async function finishAICard(card, content, config, log, contentVar, skipInputing
|
|
|
371
371
|
const fixedContent = ensureTableBlankLines(cleanContent);
|
|
372
372
|
log?.info?.(`[DingTalk][AICard] 开始 finish(一次性定稿,无流式回放),最终内容长度=${fixedContent.length}`);
|
|
373
373
|
try {
|
|
374
|
-
const { rememberCardContent } = await import("./card-content-cache-
|
|
374
|
+
const { rememberCardContent } = await import("./card-content-cache-BsFPIwOr.mjs");
|
|
375
375
|
rememberCardContent({
|
|
376
376
|
text: fixedContent,
|
|
377
377
|
outTrackId: card.cardInstanceId,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/runtime.ts
|
|
2
|
+
/**
|
|
3
|
+
* 自实现的运行时存储工厂,避免依赖特定版本 openclaw 是否导出 createPluginRuntimeStore。
|
|
4
|
+
* 旧版 openclaw 没有导出该函数,直接 import 会导致 TypeError,因此在此处内联实现。
|
|
5
|
+
*/
|
|
6
|
+
function createRuntimeStore(errorMessage) {
|
|
7
|
+
let runtimeValue = null;
|
|
8
|
+
return {
|
|
9
|
+
setRuntime: (next) => {
|
|
10
|
+
runtimeValue = next;
|
|
11
|
+
},
|
|
12
|
+
clearRuntime: () => {
|
|
13
|
+
runtimeValue = null;
|
|
14
|
+
},
|
|
15
|
+
tryGetRuntime: () => {
|
|
16
|
+
return runtimeValue;
|
|
17
|
+
},
|
|
18
|
+
getRuntime: () => {
|
|
19
|
+
if (runtimeValue === null) throw new Error(errorMessage);
|
|
20
|
+
return runtimeValue;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const { setRuntime: setDingtalkRuntime, getRuntime: getDingtalkRuntime } = createRuntimeStore("DingTalk runtime not initialized");
|
|
25
|
+
//#endregion
|
|
26
|
+
export { setDingtalkRuntime as n, getDingtalkRuntime as t };
|