@soimy/dingtalk 3.6.0 → 3.6.2-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14443 -0
- package/dist/index.js.map +7 -0
- package/dist/src/access-control.d.ts +43 -0
- package/dist/src/access-control.d.ts.map +1 -0
- package/dist/src/ack-reaction/dynamic-ack-reaction-controller.d.ts +22 -0
- package/dist/src/ack-reaction/dynamic-ack-reaction-controller.d.ts.map +1 -0
- package/dist/src/ack-reaction/dynamic-ack-reaction-events.d.ts +36 -0
- package/dist/src/ack-reaction/dynamic-ack-reaction-events.d.ts.map +1 -0
- package/dist/src/ack-reaction/dynamic-ack-reaction-progress.d.ts +7 -0
- package/dist/src/ack-reaction/dynamic-ack-reaction-progress.d.ts.map +1 -0
- package/dist/src/ack-reaction-classifier.d.ts +8 -0
- package/dist/src/ack-reaction-classifier.d.ts.map +1 -0
- package/dist/src/ack-reaction-service.d.ts +15 -0
- package/dist/src/ack-reaction-service.d.ts.map +1 -0
- package/dist/src/auth.d.ts +7 -0
- package/dist/src/auth.d.ts.map +1 -0
- package/dist/src/card/card-action-handler.d.ts +14 -0
- package/dist/src/card/card-action-handler.d.ts.map +1 -0
- package/dist/src/card/card-markdown-image-reroute.d.ts +16 -0
- package/dist/src/card/card-markdown-image-reroute.d.ts.map +1 -0
- package/dist/src/card/card-run-registry.d.ts +60 -0
- package/dist/src/card/card-run-registry.d.ts.map +1 -0
- package/dist/src/card/card-stop-handler.d.ts +18 -0
- package/dist/src/card/card-stop-handler.d.ts.map +1 -0
- package/dist/src/card/card-streaming-mode.d.ts +8 -0
- package/dist/src/card/card-streaming-mode.d.ts.map +1 -0
- package/dist/src/card/card-template.d.ts +21 -0
- package/dist/src/card/card-template.d.ts.map +1 -0
- package/dist/src/card/reasoning-answer-split.d.ts +6 -0
- package/dist/src/card/reasoning-answer-split.d.ts.map +1 -0
- package/dist/src/card/reasoning-block-assembler.d.ts +7 -0
- package/dist/src/card/reasoning-block-assembler.d.ts.map +1 -0
- package/dist/src/card/statusline-renderer.d.ts +24 -0
- package/dist/src/card/statusline-renderer.d.ts.map +1 -0
- package/dist/src/card-callback-service.d.ts +23 -0
- package/dist/src/card-callback-service.d.ts.map +1 -0
- package/dist/src/card-draft-controller.d.ts +75 -0
- package/dist/src/card-draft-controller.d.ts.map +1 -0
- package/dist/src/card-service.d.ts +99 -0
- package/dist/src/card-service.d.ts.map +1 -0
- package/dist/src/channel.d.ts +10 -0
- package/dist/src/channel.d.ts.map +1 -0
- package/dist/src/command/card-stop-command.d.ts +30 -0
- package/dist/src/command/card-stop-command.d.ts.map +1 -0
- package/dist/src/command/inbound-command-dispatch-service.d.ts +40 -0
- package/dist/src/command/inbound-command-dispatch-service.d.ts.map +1 -0
- package/dist/src/config-schema.d.ts +8 -0
- package/dist/src/config-schema.d.ts.map +1 -0
- package/dist/src/config.d.ts +60 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/connection-manager.d.ts +148 -0
- package/dist/src/connection-manager.d.ts.map +1 -0
- package/dist/src/dedup.d.ts +4 -0
- package/dist/src/dedup.d.ts.map +1 -0
- package/dist/src/device-registration.d.ts +16 -0
- package/dist/src/device-registration.d.ts.map +1 -0
- package/dist/src/docs-service.d.ts +12 -0
- package/dist/src/docs-service.d.ts.map +1 -0
- package/dist/src/draft-stream-loop.d.ts +28 -0
- package/dist/src/draft-stream-loop.d.ts.map +1 -0
- package/dist/src/feedback-learning-service.d.ts +123 -0
- package/dist/src/feedback-learning-service.d.ts.map +1 -0
- package/dist/src/feedback-learning-store.d.ts +181 -0
- package/dist/src/feedback-learning-store.d.ts.map +1 -0
- package/dist/src/gateway/channel-gateway.d.ts +4 -0
- package/dist/src/gateway/channel-gateway.d.ts.map +1 -0
- package/dist/src/http-client.d.ts +9 -0
- package/dist/src/http-client.d.ts.map +1 -0
- package/dist/src/inbound-handler.d.ts +9 -0
- package/dist/src/inbound-handler.d.ts.map +1 -0
- package/dist/src/learning-command-service.d.ts +64 -0
- package/dist/src/learning-command-service.d.ts.map +1 -0
- package/dist/src/logger-context.d.ts +10 -0
- package/dist/src/logger-context.d.ts.map +1 -0
- package/dist/src/media-utils.d.ts +63 -0
- package/dist/src/media-utils.d.ts.map +1 -0
- package/dist/src/message-context-store.d.ts +126 -0
- package/dist/src/message-context-store.d.ts.map +1 -0
- package/dist/src/message-utils.d.ts +12 -0
- package/dist/src/message-utils.d.ts.map +1 -0
- package/dist/src/messaging/attachment-text-extractor.d.ts +13 -0
- package/dist/src/messaging/attachment-text-extractor.d.ts.map +1 -0
- package/dist/src/messaging/btw-deliver.d.ts +42 -0
- package/dist/src/messaging/btw-deliver.d.ts.map +1 -0
- package/dist/src/messaging/channel-actions.d.ts +3 -0
- package/dist/src/messaging/channel-actions.d.ts.map +1 -0
- package/dist/src/messaging/channel-outbound.d.ts +3 -0
- package/dist/src/messaging/channel-outbound.d.ts.map +1 -0
- package/dist/src/messaging/quoted-context.d.ts +36 -0
- package/dist/src/messaging/quoted-context.d.ts.map +1 -0
- package/dist/src/messaging/quoted-file-service.d.ts +25 -0
- package/dist/src/messaging/quoted-file-service.d.ts.map +1 -0
- package/dist/src/messaging/quoted-ref.d.ts +12 -0
- package/dist/src/messaging/quoted-ref.d.ts.map +1 -0
- package/dist/src/onboarding.d.ts +4 -0
- package/dist/src/onboarding.d.ts.map +1 -0
- package/dist/src/path-utils.d.ts +3 -0
- package/dist/src/path-utils.d.ts.map +1 -0
- package/dist/src/peer-id-registry.d.ts +35 -0
- package/dist/src/peer-id-registry.d.ts.map +1 -0
- package/dist/src/persistence-store.d.ts +27 -0
- package/dist/src/persistence-store.d.ts.map +1 -0
- package/dist/src/platform/channel-status.d.ts +3 -0
- package/dist/src/platform/channel-status.d.ts.map +1 -0
- package/dist/src/plugin-sdk-channel-actions-augment.d.ts +7 -0
- package/dist/src/plugin-sdk-channel-actions-augment.d.ts.map +1 -0
- package/dist/src/proactive-risk-registry.d.ts +22 -0
- package/dist/src/proactive-risk-registry.d.ts.map +1 -0
- package/dist/src/reply-strategy-card.d.ts +14 -0
- package/dist/src/reply-strategy-card.d.ts.map +1 -0
- package/dist/src/reply-strategy-markdown.d.ts +10 -0
- package/dist/src/reply-strategy-markdown.d.ts.map +1 -0
- package/dist/src/reply-strategy-types.d.ts +85 -0
- package/dist/src/reply-strategy-types.d.ts.map +1 -0
- package/dist/src/reply-strategy-with-reaction.d.ts +47 -0
- package/dist/src/reply-strategy-with-reaction.d.ts.map +1 -0
- package/dist/src/reply-strategy.d.ts +14 -0
- package/dist/src/reply-strategy.d.ts.map +1 -0
- package/dist/src/run-usage-store.d.ts +15 -0
- package/dist/src/run-usage-store.d.ts.map +1 -0
- package/dist/src/runtime.d.ts +4 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/secret-input.d.ts +42 -0
- package/dist/src/secret-input.d.ts.map +1 -0
- package/dist/src/send-service.d.ts +46 -0
- package/dist/src/send-service.d.ts.map +1 -0
- package/dist/src/session-command-service.d.ts +35 -0
- package/dist/src/session-command-service.d.ts.map +1 -0
- package/dist/src/session-lock.d.ts +11 -0
- package/dist/src/session-lock.d.ts.map +1 -0
- package/dist/src/session-peer-store.d.ts +21 -0
- package/dist/src/session-peer-store.d.ts.map +1 -0
- package/dist/src/session-routing.d.ts +14 -0
- package/dist/src/session-routing.d.ts.map +1 -0
- package/dist/src/session-state.d.ts +13 -0
- package/dist/src/session-state.d.ts.map +1 -0
- package/dist/src/signature.d.ts +6 -0
- package/dist/src/signature.d.ts.map +1 -0
- package/dist/src/targeting/agent-name-matcher.d.ts +63 -0
- package/dist/src/targeting/agent-name-matcher.d.ts.map +1 -0
- package/dist/src/targeting/agent-routing.d.ts +72 -0
- package/dist/src/targeting/agent-routing.d.ts.map +1 -0
- package/dist/src/targeting/group-members-store.d.ts +3 -0
- package/dist/src/targeting/group-members-store.d.ts.map +1 -0
- package/dist/src/targeting/target-directory-adapter.d.ts +13 -0
- package/dist/src/targeting/target-directory-adapter.d.ts.map +1 -0
- package/dist/src/targeting/target-directory-store.d.ts +45 -0
- package/dist/src/targeting/target-directory-store.d.ts.map +1 -0
- package/dist/src/targeting/target-input.d.ts +3 -0
- package/dist/src/targeting/target-input.d.ts.map +1 -0
- package/dist/src/types.d.ts +730 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +54 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/openclaw.plugin.json +49 -5
- package/package.json +26 -5
- package/src/auth.ts +5 -2
- package/src/card-service.ts +41 -16
- package/src/channel.ts +5 -2
- package/src/config-schema.ts +2 -1
- package/src/config.ts +24 -67
- package/src/device-registration.ts +0 -32
- package/src/gateway/channel-gateway.ts +9 -8
- package/src/inbound-handler.ts +1239 -1061
- package/src/message-context-store.ts +183 -85
- package/src/messaging/channel-actions.ts +2 -1
- package/src/onboarding.ts +18 -13
- package/src/path-utils.ts +49 -0
- package/src/secret-input.ts +182 -0
- package/src/targeting/agent-routing.ts +30 -5
- package/src/types.ts +25 -10
|
@@ -11,8 +11,17 @@ export const DEFAULT_CREATED_AT_MATCH_WINDOW_MS = 2000;
|
|
|
11
11
|
const MAX_RECORDS_PER_SCOPE = 1000;
|
|
12
12
|
|
|
13
13
|
export type MessageContextDirection = "inbound" | "outbound";
|
|
14
|
-
export type MessageAliasKind =
|
|
15
|
-
|
|
14
|
+
export type MessageAliasKind =
|
|
15
|
+
| "inboundMsgId"
|
|
16
|
+
| "messageId"
|
|
17
|
+
| "processQueryKey"
|
|
18
|
+
| "outTrackId"
|
|
19
|
+
| "cardInstanceId";
|
|
20
|
+
export type MessageDeliveryKind =
|
|
21
|
+
| "session"
|
|
22
|
+
| "proactive-text"
|
|
23
|
+
| "proactive-card"
|
|
24
|
+
| "proactive-media";
|
|
16
25
|
export const DEFAULT_OUTBOUND_SENDER = {
|
|
17
26
|
senderId: "bot",
|
|
18
27
|
senderName: "OpenClaw",
|
|
@@ -47,6 +56,7 @@ export interface MessageRecord {
|
|
|
47
56
|
quotedMessageId?: string;
|
|
48
57
|
media?: {
|
|
49
58
|
downloadCode?: string;
|
|
59
|
+
downloadCodes?: string[];
|
|
50
60
|
spaceId?: string;
|
|
51
61
|
fileId?: string;
|
|
52
62
|
};
|
|
@@ -96,6 +106,7 @@ interface BaseUpsertParams {
|
|
|
96
106
|
quotedMessageId?: string;
|
|
97
107
|
media?: {
|
|
98
108
|
downloadCode?: string;
|
|
109
|
+
downloadCodes?: string[];
|
|
99
110
|
spaceId?: string;
|
|
100
111
|
fileId?: string;
|
|
101
112
|
};
|
|
@@ -120,7 +131,11 @@ interface ScopeParams {
|
|
|
120
131
|
const stateCache = new Map<string, MessageContextState>();
|
|
121
132
|
|
|
122
133
|
function getScopeKey(params: ScopeParams): string {
|
|
123
|
-
return JSON.stringify([
|
|
134
|
+
return JSON.stringify([
|
|
135
|
+
params.storePath || "__memory__",
|
|
136
|
+
params.accountId,
|
|
137
|
+
params.conversationId || null,
|
|
138
|
+
]);
|
|
124
139
|
}
|
|
125
140
|
|
|
126
141
|
function fallbackState(): MessageContextState {
|
|
@@ -145,19 +160,26 @@ function normalizeMedia(value: unknown): MessageRecord["media"] | undefined {
|
|
|
145
160
|
if (!candidate) {
|
|
146
161
|
return undefined;
|
|
147
162
|
}
|
|
148
|
-
const downloadCode =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
163
|
+
const downloadCode =
|
|
164
|
+
typeof candidate.downloadCode === "string" && candidate.downloadCode.trim()
|
|
165
|
+
? candidate.downloadCode.trim()
|
|
166
|
+
: undefined;
|
|
167
|
+
const downloadCodes =
|
|
168
|
+
Array.isArray(candidate.downloadCodes) && candidate.downloadCodes.length > 0
|
|
169
|
+
? candidate.downloadCodes.filter((c: unknown) => typeof c === "string" && c.trim())
|
|
170
|
+
: undefined;
|
|
171
|
+
const spaceId =
|
|
172
|
+
typeof candidate.spaceId === "string" && candidate.spaceId.trim()
|
|
173
|
+
? candidate.spaceId.trim()
|
|
174
|
+
: undefined;
|
|
175
|
+
const fileId =
|
|
176
|
+
typeof candidate.fileId === "string" && candidate.fileId.trim()
|
|
177
|
+
? candidate.fileId.trim()
|
|
178
|
+
: undefined;
|
|
179
|
+
if (!downloadCode && (!downloadCodes || downloadCodes.length === 0) && !spaceId && !fileId) {
|
|
158
180
|
return undefined;
|
|
159
181
|
}
|
|
160
|
-
return { downloadCode, spaceId, fileId };
|
|
182
|
+
return { downloadCode, downloadCodes, spaceId, fileId };
|
|
161
183
|
}
|
|
162
184
|
|
|
163
185
|
function normalizeQuotedRef(value: unknown): QuotedRef | undefined {
|
|
@@ -180,7 +202,9 @@ function normalizeQuotedRef(value: unknown): QuotedRef | undefined {
|
|
|
180
202
|
? candidate.key
|
|
181
203
|
: undefined;
|
|
182
204
|
const valueString =
|
|
183
|
-
typeof candidate.value === "string" && candidate.value.trim()
|
|
205
|
+
typeof candidate.value === "string" && candidate.value.trim()
|
|
206
|
+
? candidate.value.trim()
|
|
207
|
+
: undefined;
|
|
184
208
|
const fallbackCreatedAt =
|
|
185
209
|
typeof candidate.fallbackCreatedAt === "number" && Number.isFinite(candidate.fallbackCreatedAt)
|
|
186
210
|
? candidate.fallbackCreatedAt
|
|
@@ -213,21 +237,26 @@ function normalizeDelivery(value: unknown): MessageRecord["delivery"] | undefine
|
|
|
213
237
|
if (!candidate) {
|
|
214
238
|
return undefined;
|
|
215
239
|
}
|
|
216
|
-
const messageId =
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
240
|
+
const messageId =
|
|
241
|
+
typeof candidate.messageId === "string" && candidate.messageId.trim()
|
|
242
|
+
? candidate.messageId.trim()
|
|
243
|
+
: undefined;
|
|
244
|
+
const processQueryKey =
|
|
245
|
+
typeof candidate.processQueryKey === "string" && candidate.processQueryKey.trim()
|
|
246
|
+
? candidate.processQueryKey.trim()
|
|
247
|
+
: undefined;
|
|
248
|
+
const outTrackId =
|
|
249
|
+
typeof candidate.outTrackId === "string" && candidate.outTrackId.trim()
|
|
250
|
+
? candidate.outTrackId.trim()
|
|
251
|
+
: undefined;
|
|
252
|
+
const cardInstanceId =
|
|
253
|
+
typeof candidate.cardInstanceId === "string" && candidate.cardInstanceId.trim()
|
|
254
|
+
? candidate.cardInstanceId.trim()
|
|
255
|
+
: undefined;
|
|
256
|
+
const kind =
|
|
257
|
+
typeof candidate.kind === "string" && candidate.kind.trim()
|
|
258
|
+
? (candidate.kind.trim() as MessageDeliveryKind)
|
|
259
|
+
: undefined;
|
|
231
260
|
if (!messageId && !processQueryKey && !outTrackId && !cardInstanceId && !kind) {
|
|
232
261
|
return undefined;
|
|
233
262
|
}
|
|
@@ -248,30 +277,46 @@ function normalizeMessageRecord(value: unknown): MessageRecord | null {
|
|
|
248
277
|
if (!candidate) {
|
|
249
278
|
return null;
|
|
250
279
|
}
|
|
251
|
-
const msgId =
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
280
|
+
const msgId =
|
|
281
|
+
typeof candidate.msgId === "string" && candidate.msgId.trim() ? candidate.msgId.trim() : "";
|
|
282
|
+
const direction =
|
|
283
|
+
candidate.direction === "outbound"
|
|
284
|
+
? "outbound"
|
|
285
|
+
: candidate.direction === "inbound"
|
|
286
|
+
? "inbound"
|
|
287
|
+
: null;
|
|
288
|
+
const accountId =
|
|
289
|
+
typeof candidate.accountId === "string" && candidate.accountId.trim()
|
|
290
|
+
? candidate.accountId.trim()
|
|
291
|
+
: "";
|
|
292
|
+
const conversationId =
|
|
293
|
+
typeof candidate.conversationId === "string" && candidate.conversationId.trim()
|
|
294
|
+
? candidate.conversationId.trim()
|
|
295
|
+
: null;
|
|
296
|
+
const createdAt =
|
|
297
|
+
typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt)
|
|
298
|
+
? candidate.createdAt
|
|
299
|
+
: NaN;
|
|
300
|
+
const updatedAt =
|
|
301
|
+
typeof candidate.updatedAt === "number" && Number.isFinite(candidate.updatedAt)
|
|
302
|
+
? candidate.updatedAt
|
|
303
|
+
: Date.now();
|
|
265
304
|
if (!msgId || !direction || !accountId || !Number.isFinite(createdAt)) {
|
|
266
305
|
return null;
|
|
267
306
|
}
|
|
268
|
-
const expiresAt =
|
|
269
|
-
|
|
270
|
-
|
|
307
|
+
const expiresAt =
|
|
308
|
+
typeof candidate.expiresAt === "number" && Number.isFinite(candidate.expiresAt)
|
|
309
|
+
? candidate.expiresAt
|
|
310
|
+
: undefined;
|
|
271
311
|
return {
|
|
272
312
|
msgId,
|
|
273
313
|
direction,
|
|
274
|
-
topic:
|
|
314
|
+
topic:
|
|
315
|
+
candidate.topic === null
|
|
316
|
+
? null
|
|
317
|
+
: typeof candidate.topic === "string"
|
|
318
|
+
? candidate.topic
|
|
319
|
+
: null,
|
|
275
320
|
accountId,
|
|
276
321
|
conversationId,
|
|
277
322
|
createdAt,
|
|
@@ -279,16 +324,26 @@ function normalizeMessageRecord(value: unknown): MessageRecord | null {
|
|
|
279
324
|
expiresAt,
|
|
280
325
|
messageType: typeof candidate.messageType === "string" ? candidate.messageType : undefined,
|
|
281
326
|
text: typeof candidate.text === "string" ? candidate.text : undefined,
|
|
282
|
-
attachmentText:
|
|
327
|
+
attachmentText:
|
|
328
|
+
typeof candidate.attachmentText === "string" ? candidate.attachmentText : undefined,
|
|
283
329
|
attachmentTextSource: normalizeAttachmentTextSource(candidate.attachmentTextSource),
|
|
284
330
|
attachmentTextTruncated: candidate.attachmentTextTruncated === true ? true : undefined,
|
|
285
331
|
attachmentFileName:
|
|
286
332
|
typeof candidate.attachmentFileName === "string" ? candidate.attachmentFileName : undefined,
|
|
287
333
|
quotedRef: normalizeQuotedRef(candidate.quotedRef),
|
|
288
|
-
senderId:
|
|
289
|
-
|
|
334
|
+
senderId:
|
|
335
|
+
typeof candidate.senderId === "string" && candidate.senderId.trim()
|
|
336
|
+
? candidate.senderId.trim()
|
|
337
|
+
: undefined,
|
|
338
|
+
senderName:
|
|
339
|
+
typeof candidate.senderName === "string" && candidate.senderName.trim()
|
|
340
|
+
? candidate.senderName.trim()
|
|
341
|
+
: undefined,
|
|
290
342
|
mentions: normalizeMentions(candidate.mentions),
|
|
291
|
-
chatType:
|
|
343
|
+
chatType:
|
|
344
|
+
candidate.chatType === "direct" || candidate.chatType === "group"
|
|
345
|
+
? candidate.chatType
|
|
346
|
+
: undefined,
|
|
292
347
|
quotedMessageId:
|
|
293
348
|
typeof candidate.quotedMessageId === "string" && candidate.quotedMessageId.trim()
|
|
294
349
|
? candidate.quotedMessageId.trim()
|
|
@@ -327,10 +382,17 @@ function buildAliasEntries(record: MessageRecord): Array<[string, string]> {
|
|
|
327
382
|
}
|
|
328
383
|
|
|
329
384
|
function isRecordExpired(record: MessageRecord, nowMs: number): boolean {
|
|
330
|
-
return
|
|
385
|
+
return (
|
|
386
|
+
typeof record.expiresAt === "number" &&
|
|
387
|
+
Number.isFinite(record.expiresAt) &&
|
|
388
|
+
nowMs >= record.expiresAt
|
|
389
|
+
);
|
|
331
390
|
}
|
|
332
391
|
|
|
333
|
-
function normalizeState(
|
|
392
|
+
function normalizeState(
|
|
393
|
+
state: MessageContextState,
|
|
394
|
+
nowMs: number,
|
|
395
|
+
): { state: MessageContextState; removed: number } {
|
|
334
396
|
const normalizedRecords: Record<string, MessageRecord> = {};
|
|
335
397
|
const sortedRecords = Object.values(state.records)
|
|
336
398
|
.map((record) => normalizeMessageRecord(record))
|
|
@@ -363,12 +425,15 @@ function hydrateState(params: ScopeParams, nowMs: number): MessageContextState {
|
|
|
363
425
|
if (!params.storePath) {
|
|
364
426
|
return fallbackState();
|
|
365
427
|
}
|
|
366
|
-
const persisted = readNamespaceJson<Partial<PersistedMessageContextState>>(
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
428
|
+
const persisted = readNamespaceJson<Partial<PersistedMessageContextState>>(
|
|
429
|
+
MESSAGE_CONTEXT_NAMESPACE,
|
|
430
|
+
{
|
|
431
|
+
storePath: params.storePath,
|
|
432
|
+
scope: { accountId: params.accountId, conversationId: params.conversationId || undefined },
|
|
433
|
+
format: "json",
|
|
434
|
+
fallback: { version: MESSAGE_CONTEXT_VERSION, updatedAt: Date.now(), records: {} },
|
|
435
|
+
},
|
|
436
|
+
);
|
|
372
437
|
const parsedRecords = asRecord(persisted.records) || {};
|
|
373
438
|
const hydrated = fallbackState();
|
|
374
439
|
hydrated.updatedAt = typeof persisted.updatedAt === "number" ? persisted.updatedAt : Date.now();
|
|
@@ -426,14 +491,20 @@ function mergeText(existing: string | undefined, next: string | undefined): stri
|
|
|
426
491
|
return next;
|
|
427
492
|
}
|
|
428
493
|
|
|
429
|
-
function mergeAttachmentText(
|
|
494
|
+
function mergeAttachmentText(
|
|
495
|
+
existing: string | undefined,
|
|
496
|
+
next: string | undefined,
|
|
497
|
+
): string | undefined {
|
|
430
498
|
if (typeof next !== "string") {
|
|
431
499
|
return existing;
|
|
432
500
|
}
|
|
433
501
|
return next;
|
|
434
502
|
}
|
|
435
503
|
|
|
436
|
-
function mergeQuotedRef(
|
|
504
|
+
function mergeQuotedRef(
|
|
505
|
+
existing: QuotedRef | undefined,
|
|
506
|
+
next: QuotedRef | undefined,
|
|
507
|
+
): QuotedRef | undefined {
|
|
437
508
|
if (!existing) {
|
|
438
509
|
return next;
|
|
439
510
|
}
|
|
@@ -448,14 +519,20 @@ function mergeQuotedRef(existing: QuotedRef | undefined, next: QuotedRef | undef
|
|
|
448
519
|
};
|
|
449
520
|
}
|
|
450
521
|
|
|
451
|
-
function mergeStringField(
|
|
522
|
+
function mergeStringField(
|
|
523
|
+
existing: string | undefined,
|
|
524
|
+
next: string | undefined,
|
|
525
|
+
): string | undefined {
|
|
452
526
|
if (typeof next !== "string" || !next.trim()) {
|
|
453
527
|
return existing;
|
|
454
528
|
}
|
|
455
529
|
return next.trim();
|
|
456
530
|
}
|
|
457
531
|
|
|
458
|
-
function mergeMentions(
|
|
532
|
+
function mergeMentions(
|
|
533
|
+
existing: string[] | undefined,
|
|
534
|
+
next: string[] | undefined,
|
|
535
|
+
): string[] | undefined {
|
|
459
536
|
if (!next) {
|
|
460
537
|
return existing;
|
|
461
538
|
}
|
|
@@ -474,6 +551,7 @@ function mergeMedia(
|
|
|
474
551
|
}
|
|
475
552
|
return {
|
|
476
553
|
downloadCode: next.downloadCode || existing.downloadCode,
|
|
554
|
+
downloadCodes: next.downloadCodes || existing.downloadCodes,
|
|
477
555
|
spaceId: next.spaceId || existing.spaceId,
|
|
478
556
|
fileId: next.fileId || existing.fileId,
|
|
479
557
|
};
|
|
@@ -512,7 +590,10 @@ function mergeAttachmentTextTruncated(
|
|
|
512
590
|
return next === undefined ? existing : next;
|
|
513
591
|
}
|
|
514
592
|
|
|
515
|
-
function mergeAttachmentFileName(
|
|
593
|
+
function mergeAttachmentFileName(
|
|
594
|
+
existing: string | undefined,
|
|
595
|
+
next: string | undefined,
|
|
596
|
+
): string | undefined {
|
|
516
597
|
if (typeof next !== "string") {
|
|
517
598
|
return existing;
|
|
518
599
|
}
|
|
@@ -521,7 +602,11 @@ function mergeAttachmentFileName(existing: string | undefined, next: string | un
|
|
|
521
602
|
|
|
522
603
|
function resolveExistingMsgId(
|
|
523
604
|
state: MessageContextState,
|
|
524
|
-
params: {
|
|
605
|
+
params: {
|
|
606
|
+
direction: MessageContextDirection;
|
|
607
|
+
msgId?: string;
|
|
608
|
+
delivery?: MessageRecord["delivery"];
|
|
609
|
+
},
|
|
525
610
|
nowMs: number,
|
|
526
611
|
): string | undefined {
|
|
527
612
|
if (params.direction === "inbound" && params.msgId) {
|
|
@@ -556,11 +641,19 @@ function resolveExistingMsgId(
|
|
|
556
641
|
return undefined;
|
|
557
642
|
}
|
|
558
643
|
|
|
559
|
-
function computeExpiresAt(
|
|
644
|
+
function computeExpiresAt(
|
|
645
|
+
nowMs: number,
|
|
646
|
+
ttlMs?: number,
|
|
647
|
+
ttlReferenceMs?: number,
|
|
648
|
+
): number | undefined {
|
|
560
649
|
if (typeof ttlMs !== "number" || !Number.isFinite(ttlMs) || ttlMs <= 0) {
|
|
561
650
|
return undefined;
|
|
562
651
|
}
|
|
563
|
-
return (
|
|
652
|
+
return (
|
|
653
|
+
(typeof ttlReferenceMs === "number" && Number.isFinite(ttlReferenceMs)
|
|
654
|
+
? ttlReferenceMs
|
|
655
|
+
: nowMs) + ttlMs
|
|
656
|
+
);
|
|
564
657
|
}
|
|
565
658
|
|
|
566
659
|
function pruneStateByCreatedAt(
|
|
@@ -622,11 +715,15 @@ function upsertRecord(
|
|
|
622
715
|
if (params.cleanupCreatedAtTtlDays && params.cleanupCreatedAtTtlDays > 0) {
|
|
623
716
|
state = pruneStateByCreatedAt(state, params.cleanupCreatedAtTtlDays, nowMs).state;
|
|
624
717
|
}
|
|
625
|
-
const existingMsgId = resolveExistingMsgId(
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
718
|
+
const existingMsgId = resolveExistingMsgId(
|
|
719
|
+
state,
|
|
720
|
+
{
|
|
721
|
+
direction: params.direction,
|
|
722
|
+
msgId: params.msgId,
|
|
723
|
+
delivery: params.delivery,
|
|
724
|
+
},
|
|
725
|
+
nowMs,
|
|
726
|
+
);
|
|
630
727
|
const canonicalMsgId =
|
|
631
728
|
existingMsgId ||
|
|
632
729
|
params.msgId ||
|
|
@@ -648,9 +745,7 @@ function upsertRecord(
|
|
|
648
745
|
createdAt: existing?.createdAt ?? params.createdAt,
|
|
649
746
|
updatedAt: nowMs,
|
|
650
747
|
expiresAt:
|
|
651
|
-
expiresAt === undefined
|
|
652
|
-
? existing?.expiresAt
|
|
653
|
-
: Math.max(expiresAt, existing?.expiresAt ?? 0),
|
|
748
|
+
expiresAt === undefined ? existing?.expiresAt : Math.max(expiresAt, existing?.expiresAt ?? 0),
|
|
654
749
|
messageType: params.messageType || existing?.messageType,
|
|
655
750
|
text: mergeText(existing?.text, params.text),
|
|
656
751
|
attachmentText: mergeAttachmentText(existing?.attachmentText, params.attachmentText),
|
|
@@ -692,7 +787,9 @@ export function upsertInboundMessageContext(params: UpsertInboundMessageContextP
|
|
|
692
787
|
);
|
|
693
788
|
}
|
|
694
789
|
|
|
695
|
-
export function upsertOutboundMessageContext(
|
|
790
|
+
export function upsertOutboundMessageContext(
|
|
791
|
+
params: UpsertOutboundMessageContextParams,
|
|
792
|
+
): string | undefined {
|
|
696
793
|
return upsertRecord({
|
|
697
794
|
...params,
|
|
698
795
|
direction: "outbound",
|
|
@@ -780,7 +877,10 @@ export function resolveByQuotedRef(
|
|
|
780
877
|
`[DingTalk][QuotedRef] Resolve outbound by ${quotedRef.key}=${quotedRef.value} hit=no accountId=${params.accountId} conversationId=${params.conversationId || "(none)"}`,
|
|
781
878
|
);
|
|
782
879
|
}
|
|
783
|
-
if (
|
|
880
|
+
if (
|
|
881
|
+
typeof quotedRef.fallbackCreatedAt === "number" &&
|
|
882
|
+
Number.isFinite(quotedRef.fallbackCreatedAt)
|
|
883
|
+
) {
|
|
784
884
|
const record = resolveByCreatedAtWindow({
|
|
785
885
|
...params,
|
|
786
886
|
createdAt: quotedRef.fallbackCreatedAt,
|
|
@@ -828,9 +928,7 @@ export function resolveByCreatedAtWindow(
|
|
|
828
928
|
return bestRecord;
|
|
829
929
|
}
|
|
830
930
|
|
|
831
|
-
export function cleanupExpiredMessageContexts(
|
|
832
|
-
params: ScopeParams & { nowMs?: number },
|
|
833
|
-
): number {
|
|
931
|
+
export function cleanupExpiredMessageContexts(params: ScopeParams & { nowMs?: number }): number {
|
|
834
932
|
const nowMs = params.nowMs ?? Date.now();
|
|
835
933
|
const state = loadState(params, nowMs);
|
|
836
934
|
const beforeCount = Object.keys(state.records).length;
|
|
@@ -850,12 +948,12 @@ export function clearMessageContextCacheForTest(): void {
|
|
|
850
948
|
/**
|
|
851
949
|
* Lists non-expired message-context records for one account/conversation scope in createdAt ascending order.
|
|
852
950
|
*/
|
|
853
|
-
export function listMessageContexts(
|
|
854
|
-
params: ScopeParams & { nowMs?: number },
|
|
855
|
-
): MessageRecord[] {
|
|
951
|
+
export function listMessageContexts(params: ScopeParams & { nowMs?: number }): MessageRecord[] {
|
|
856
952
|
const nowMs = params.nowMs ?? Date.now();
|
|
857
953
|
const state = loadState(params, nowMs);
|
|
858
954
|
return state.recentByCreatedAt
|
|
859
955
|
.map((msgId) => state.records[msgId])
|
|
860
|
-
.filter(
|
|
956
|
+
.filter(
|
|
957
|
+
(record): record is MessageRecord => Boolean(record) && !isRecordExpired(record, nowMs),
|
|
958
|
+
);
|
|
861
959
|
}
|
|
@@ -6,6 +6,7 @@ import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
|
|
|
6
6
|
import { getConfig, stripTargetPrefix } from "../config";
|
|
7
7
|
import { getLogger } from "../logger-context";
|
|
8
8
|
import { resolveOriginalPeerId } from "../peer-id-registry";
|
|
9
|
+
import { hasConfiguredSecretInput } from "../secret-input";
|
|
9
10
|
import { sendMedia, sendMessage } from "../send-service";
|
|
10
11
|
import { parseBooleanLike } from "../utils";
|
|
11
12
|
|
|
@@ -50,7 +51,7 @@ function inferCardOwnerIdFromTarget(target: string): string | undefined {
|
|
|
50
51
|
|
|
51
52
|
function describeDingTalkMessageTool(cfg: OpenClawConfig) {
|
|
52
53
|
const config = getConfig(cfg);
|
|
53
|
-
const configured = Boolean(config.clientId && config.clientSecret);
|
|
54
|
+
const configured = Boolean(config.clientId && hasConfiguredSecretInput(config.clientSecret));
|
|
54
55
|
if (!configured && !(config.accounts && Object.keys(config.accounts).length > 0)) {
|
|
55
56
|
return { actions: [], capabilities: [], schema: null };
|
|
56
57
|
}
|
package/src/onboarding.ts
CHANGED
|
@@ -9,15 +9,19 @@ import { DEFAULT_ACCOUNT_ID, formatDocsLink, normalizeAccountId } from "openclaw
|
|
|
9
9
|
import { listDingTalkAccountIds, resolveDingTalkAccount } from "./config.js";
|
|
10
10
|
import {
|
|
11
11
|
beginDeviceRegistration,
|
|
12
|
-
openUrlInBrowser,
|
|
13
12
|
RegistrationError,
|
|
14
13
|
} from "./device-registration.js";
|
|
14
|
+
import {
|
|
15
|
+
hasConfiguredSecretInput,
|
|
16
|
+
normalizeSecretInputString,
|
|
17
|
+
parseSecretInputString,
|
|
18
|
+
} from "./secret-input.js";
|
|
15
19
|
import type { DingTalkConfig, DingTalkChannelConfig } from "./types.js";
|
|
16
20
|
|
|
17
21
|
const channel = "dingtalk" as const;
|
|
18
22
|
|
|
19
23
|
function isConfigured(account: DingTalkConfig): boolean {
|
|
20
|
-
return Boolean(account.clientId && account.clientSecret);
|
|
24
|
+
return Boolean(account.clientId && hasConfiguredSecretInput(account.clientSecret));
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
function applyAccountNameToChannelSection(params: {
|
|
@@ -354,7 +358,9 @@ function applyGenericSetupInput(params: {
|
|
|
354
358
|
name: params.input.name,
|
|
355
359
|
clientId: typeof params.input.token === "string" ? params.input.token.trim() : undefined,
|
|
356
360
|
clientSecret:
|
|
357
|
-
typeof params.input.password === "string"
|
|
361
|
+
typeof params.input.password === "string"
|
|
362
|
+
? parseSecretInputString(params.input.password)
|
|
363
|
+
: undefined,
|
|
358
364
|
},
|
|
359
365
|
});
|
|
360
366
|
}
|
|
@@ -368,7 +374,9 @@ async function configureDingTalkAccount(params: {
|
|
|
368
374
|
const resolved = resolveDingTalkAccount(cfg, accountId);
|
|
369
375
|
|
|
370
376
|
// ── Credential acquisition: auto-register or manual ────────────────────
|
|
371
|
-
const hasExistingCredentials = Boolean(
|
|
377
|
+
const hasExistingCredentials = Boolean(
|
|
378
|
+
resolved.clientId && hasConfiguredSecretInput(resolved.clientSecret),
|
|
379
|
+
);
|
|
372
380
|
const credentialMethod = await prompter.select({
|
|
373
381
|
message: "How do you want to get DingTalk bot credentials?",
|
|
374
382
|
options: [
|
|
@@ -385,15 +393,12 @@ async function configureDingTalkAccount(params: {
|
|
|
385
393
|
try {
|
|
386
394
|
const session = await beginDeviceRegistration();
|
|
387
395
|
|
|
388
|
-
openUrlInBrowser(session.verificationUrl);
|
|
389
|
-
|
|
390
396
|
await prompter.note(
|
|
391
397
|
[
|
|
392
|
-
"
|
|
393
|
-
"Scan the authorization code in DingTalk to finish registration.",
|
|
394
|
-
"",
|
|
395
|
-
"If the browser did not open automatically, visit this link manually:",
|
|
398
|
+
"Open this authorization page in your browser:",
|
|
396
399
|
session.verificationUrl,
|
|
400
|
+
"",
|
|
401
|
+
"Scan the authorization code in DingTalk to finish registration.",
|
|
397
402
|
].join("\n"),
|
|
398
403
|
"DingTalk bot auto-registration",
|
|
399
404
|
);
|
|
@@ -441,7 +446,7 @@ async function configureDingTalkAccount(params: {
|
|
|
441
446
|
await prompter.text({
|
|
442
447
|
message: "Client Secret (AppSecret)",
|
|
443
448
|
placeholder: "xxx-xxx-xxx-xxx",
|
|
444
|
-
initialValue: resolved.clientSecret
|
|
449
|
+
initialValue: normalizeSecretInputString(resolved.clientSecret),
|
|
445
450
|
validate: (value: string) => (String(value ?? "").trim() ? undefined : "Required"),
|
|
446
451
|
}),
|
|
447
452
|
).trim();
|
|
@@ -461,7 +466,7 @@ async function configureDingTalkAccount(params: {
|
|
|
461
466
|
await prompter.text({
|
|
462
467
|
message: "Client Secret (AppSecret)",
|
|
463
468
|
placeholder: "xxx-xxx-xxx-xxx",
|
|
464
|
-
initialValue: resolved.clientSecret
|
|
469
|
+
initialValue: normalizeSecretInputString(resolved.clientSecret),
|
|
465
470
|
validate: (value: string) => (String(value ?? "").trim() ? undefined : "Required"),
|
|
466
471
|
}),
|
|
467
472
|
).trim();
|
|
@@ -523,7 +528,7 @@ async function configureDingTalkAccount(params: {
|
|
|
523
528
|
accountId,
|
|
524
529
|
input: {
|
|
525
530
|
clientId: String(clientId).trim(),
|
|
526
|
-
clientSecret:
|
|
531
|
+
clientSecret: parseSecretInputString(clientSecret),
|
|
527
532
|
dmPolicy: dmPolicyValue,
|
|
528
533
|
groupPolicy: groupPolicyValue,
|
|
529
534
|
messageType,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
const WINDOWS_ROOT_DIRECTORIES = new Set([
|
|
5
|
+
"Users",
|
|
6
|
+
"Program Files",
|
|
7
|
+
"Program Files (x86)",
|
|
8
|
+
"ProgramData",
|
|
9
|
+
"Windows",
|
|
10
|
+
"Documents and Settings",
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
export function resolveRelativePath(input: string): string {
|
|
14
|
+
const trimmed = input.trim();
|
|
15
|
+
if (!trimmed) {
|
|
16
|
+
return trimmed;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const segments = (value: string): string[] => value.split(/[\\/]+/).filter(Boolean);
|
|
20
|
+
const pathSegments = segments(trimmed);
|
|
21
|
+
const firstSegment = pathSegments[0];
|
|
22
|
+
|
|
23
|
+
if (trimmed === "~") {
|
|
24
|
+
return path.resolve(os.homedir());
|
|
25
|
+
}
|
|
26
|
+
if (trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
27
|
+
return path.resolve(os.homedir(), ...segments(trimmed.slice(2)));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (process.platform === "win32") {
|
|
31
|
+
if (/^[a-zA-Z]:[\\/]/.test(trimmed)) {
|
|
32
|
+
return path.win32.normalize(trimmed);
|
|
33
|
+
}
|
|
34
|
+
if (firstSegment && /^[a-zA-Z]:$/.test(firstSegment)) {
|
|
35
|
+
return path.win32.resolve(`${firstSegment}\\`, ...pathSegments.slice(1));
|
|
36
|
+
}
|
|
37
|
+
if (firstSegment && WINDOWS_ROOT_DIRECTORIES.has(firstSegment)) {
|
|
38
|
+
return path.win32.resolve("\\", ...pathSegments);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (/^[\\/]/.test(trimmed)) {
|
|
43
|
+
return path.resolve(path.sep, ...pathSegments);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return path.resolve(process.cwd(), ...pathSegments);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const resolveUserPath = resolveRelativePath;
|