@clowder-ai/connector-dingtalk 0.0.0-stage → 0.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +54 -0
- package/README.md +24 -2
- package/assets/icon.svg +4 -0
- package/dist/DingTalkAdapter.d.ts +251 -0
- package/dist/DingTalkAdapter.d.ts.map +1 -0
- package/dist/DingTalkAdapter.js +821 -0
- package/dist/DingTalkAdapter.js.map +1 -0
- package/dist/command-ingress.d.ts +10 -0
- package/dist/command-ingress.d.ts.map +1 -0
- package/dist/command-ingress.js +15 -0
- package/dist/command-ingress.js.map +1 -0
- package/dist/execution-status.d.ts +27 -0
- package/dist/execution-status.d.ts.map +1 -0
- package/dist/execution-status.js +48 -0
- package/dist/execution-status.js.map +1 -0
- package/dist/inbound-download.d.ts +13 -0
- package/dist/inbound-download.d.ts.map +1 -0
- package/dist/inbound-download.js +70 -0
- package/dist/inbound-download.js.map +1 -0
- package/dist/inbound-media-source.d.ts +25 -0
- package/dist/inbound-media-source.d.ts.map +1 -0
- package/dist/inbound-media-source.js +115 -0
- package/dist/inbound-media-source.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle-action.d.ts +30 -0
- package/dist/lifecycle-action.d.ts.map +1 -0
- package/dist/lifecycle-action.js +457 -0
- package/dist/lifecycle-action.js.map +1 -0
- package/dist/materialize-media.d.ts +7 -0
- package/dist/materialize-media.d.ts.map +1 -0
- package/dist/materialize-media.js +35 -0
- package/dist/materialize-media.js.map +1 -0
- package/dist/media-notice.d.ts +6 -0
- package/dist/media-notice.d.ts.map +1 -0
- package/dist/media-notice.js +50 -0
- package/dist/media-notice.js.map +1 -0
- package/dist/plugin-entrypoint.d.ts +7 -0
- package/dist/plugin-entrypoint.d.ts.map +1 -0
- package/dist/plugin-entrypoint.js +282 -0
- package/dist/plugin-entrypoint.js.map +1 -0
- package/dist/reply-sender-map.d.ts +10 -0
- package/dist/reply-sender-map.d.ts.map +1 -0
- package/dist/reply-sender-map.js +123 -0
- package/dist/reply-sender-map.js.map +1 -0
- package/dist/runtime.d.ts +68 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +167 -0
- package/dist/runtime.js.map +1 -0
- package/dist/thread-mappings.d.ts +46 -0
- package/dist/thread-mappings.d.ts.map +1 -0
- package/dist/thread-mappings.js +62 -0
- package/dist/thread-mappings.js.map +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/npm-shrinkwrap.json +485 -0
- package/package.json +55 -4
- package/plugin.yaml +63 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { isPluginDeliveryInput } from '@clowder-ai/plugin-contract';
|
|
2
|
+
import { definePluginModule } from '@clowder-ai/plugin-sdk';
|
|
3
|
+
import { threadMappings } from './thread-mappings.js';
|
|
4
|
+
import { createConnectorCommandBridge } from '@clowder-ai/plugin-sdk';
|
|
5
|
+
import { definePlugin, defineDeliveryAction, requireConnectorOutboundDelivery, } from '@clowder-ai/plugin-sdk';
|
|
6
|
+
import { createDingTalkConnectorRuntime, } from './runtime.js';
|
|
7
|
+
import { renderTypedMediaNotice } from './media-notice.js';
|
|
8
|
+
import { createInboundMediaSource, releaseInboundMedia, retainInboundMedia } from './inbound-media-source.js';
|
|
9
|
+
import { createConnectorLifecycleAction } from './lifecycle-action.js';
|
|
10
|
+
import { createReplySenderMap } from './reply-sender-map.js';
|
|
11
|
+
import { connectorCommandFacts } from './command-ingress.js';
|
|
12
|
+
const CONNECTOR_ID = 'dingtalk';
|
|
13
|
+
const IDENTITY_ID = 'dingtalk-bot';
|
|
14
|
+
function object(value) {
|
|
15
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
function requireDelivery(candidate) {
|
|
18
|
+
if (!isPluginDeliveryInput(candidate) || candidate.kind !== 'message')
|
|
19
|
+
throw new TypeError('dingtalk requires a message delivery');
|
|
20
|
+
return structuredClone(candidate);
|
|
21
|
+
}
|
|
22
|
+
function title(value) {
|
|
23
|
+
const normalized = value.trim();
|
|
24
|
+
const candidate = normalized.length > 0 ? normalized : 'DingTalk conversation';
|
|
25
|
+
return candidate.length <= 200 ? candidate : candidate.slice(0, 200);
|
|
26
|
+
}
|
|
27
|
+
async function draft(context, message) {
|
|
28
|
+
const retained = await retainInboundMedia(context, CONNECTOR_ID, 'dingtalk-media', message.providerMessageId, (message.attachments ?? []).map(attachment => ({
|
|
29
|
+
type: attachment.type, platformKey: attachment.platformKey,
|
|
30
|
+
...(attachment.fileName === undefined ? {} : { fileName: attachment.fileName }),
|
|
31
|
+
...(attachment.duration === undefined ? {} : { duration: attachment.duration }),
|
|
32
|
+
})));
|
|
33
|
+
const messageDraft = {
|
|
34
|
+
idempotencyKey: message.providerMessageId,
|
|
35
|
+
sourceEventId: message.providerMessageId,
|
|
36
|
+
identity: IDENTITY_ID,
|
|
37
|
+
...(message.sender === undefined ? {} : { sender: message.sender }),
|
|
38
|
+
payload: {
|
|
39
|
+
provenance: {
|
|
40
|
+
origin: {
|
|
41
|
+
kind: 'external',
|
|
42
|
+
connectorId: CONNECTOR_ID,
|
|
43
|
+
sourceAddress: {
|
|
44
|
+
connectorId: CONNECTOR_ID,
|
|
45
|
+
chatId: message.externalConversationId,
|
|
46
|
+
messageId: message.providerMessageId,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
epistemicStatus: 'observation',
|
|
50
|
+
},
|
|
51
|
+
elements: [
|
|
52
|
+
{ elementId: 'text-1', kind: 'text', payload: { text: message.text } },
|
|
53
|
+
...retained.elements,
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
return { messageDraft, ownership: retained.ownership };
|
|
58
|
+
}
|
|
59
|
+
async function createMessageBridge(context, reply) {
|
|
60
|
+
const replySenders = createReplySenderMap(context);
|
|
61
|
+
const subscriptions = new Map();
|
|
62
|
+
const subscribe = (threadId) => {
|
|
63
|
+
const current = subscriptions.get(threadId);
|
|
64
|
+
if (current !== undefined)
|
|
65
|
+
return current;
|
|
66
|
+
let pending;
|
|
67
|
+
pending = context.messaging.subscribe(threadId, { contributionId: CONNECTOR_ID })
|
|
68
|
+
.catch((error) => {
|
|
69
|
+
if (subscriptions.get(threadId) === pending)
|
|
70
|
+
subscriptions.delete(threadId);
|
|
71
|
+
throw error;
|
|
72
|
+
});
|
|
73
|
+
subscriptions.set(threadId, pending);
|
|
74
|
+
return pending;
|
|
75
|
+
};
|
|
76
|
+
for (const binding of await threadMappings(context).listBindings())
|
|
77
|
+
await subscribe(binding.threadId);
|
|
78
|
+
const routeCommand = createConnectorCommandBridge(context, {
|
|
79
|
+
connectorId: CONNECTOR_ID, identityId: IDENTITY_ID, reply,
|
|
80
|
+
settle: async () => { },
|
|
81
|
+
async bindingChanged(change) {
|
|
82
|
+
if (change.threadId !== undefined)
|
|
83
|
+
await subscribe(change.threadId);
|
|
84
|
+
if (change.previousThreadId !== undefined && change.previousThreadId !== change.threadId &&
|
|
85
|
+
!(await threadMappings(context).listBindings()).some(binding => binding.threadId === change.previousThreadId)) {
|
|
86
|
+
await context.messaging.unsubscribe(change.previousThreadId);
|
|
87
|
+
subscriptions.delete(change.previousThreadId);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
async deliver(message) {
|
|
93
|
+
await routeCommand(connectorCommandFacts(message), async () => {
|
|
94
|
+
const thread = await threadMappings(context).ensureByKey(message.externalConversationId, {
|
|
95
|
+
title: title(message.chatName ?? `DingTalk ${message.externalConversationId}`),
|
|
96
|
+
});
|
|
97
|
+
await subscribe(thread.id);
|
|
98
|
+
const prepared = await draft(context, message);
|
|
99
|
+
try {
|
|
100
|
+
const sent = await context.messaging.send(thread.id, prepared.messageDraft);
|
|
101
|
+
if (prepared.messageDraft.sender !== undefined) {
|
|
102
|
+
try {
|
|
103
|
+
await replySenders.record(sent.messageId, prepared.messageDraft.sender);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
context.log('warn', 'DingTalk reply-sender mapping record failed', {
|
|
107
|
+
errorName: error instanceof Error ? error.name : 'unknown',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
await releaseInboundMedia(context, prepared.ownership, error);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
async outbound(candidate) {
|
|
119
|
+
const input = requireDelivery(candidate);
|
|
120
|
+
const bindings = (await threadMappings(context).listBindings()).filter(item => item.threadId === input.threadId);
|
|
121
|
+
if (bindings.length === 0)
|
|
122
|
+
throw new TypeError(`dingtalk thread ${input.threadId} has no provider binding`);
|
|
123
|
+
const text = input.envelope.payload.elements.flatMap((element) => {
|
|
124
|
+
if (element.kind === 'text')
|
|
125
|
+
return [element.payload.text];
|
|
126
|
+
const notice = renderTypedMediaNotice(element, {
|
|
127
|
+
elements: input.envelope.payload.elements,
|
|
128
|
+
warnInvalid: elementId => context.log('warn', 'Invalid typed media notice ignored', { elementId }),
|
|
129
|
+
});
|
|
130
|
+
return notice === undefined ? [] : [notice];
|
|
131
|
+
}).join('\n\n');
|
|
132
|
+
const richBlocks = input.envelope.payload.elements
|
|
133
|
+
.filter(element => element.kind === 'rich_block')
|
|
134
|
+
.map(element => element.payload);
|
|
135
|
+
const media = input.envelope.payload.elements.flatMap((element) => {
|
|
136
|
+
if (element.kind !== 'media_ref' || !object(element.payload))
|
|
137
|
+
return [];
|
|
138
|
+
const type = element.payload.type;
|
|
139
|
+
const reference = element.payload.reference;
|
|
140
|
+
if (!['image', 'file', 'audio', 'video'].includes(String(type)) || typeof reference !== 'string')
|
|
141
|
+
return [];
|
|
142
|
+
return [{ type, reference, ...(typeof element.payload.fileName === 'string' ? { fileName: element.payload.fileName } : {}) }];
|
|
143
|
+
});
|
|
144
|
+
const displayName = input.presentation?.actor.displayName || input.envelope.actor.id;
|
|
145
|
+
const replyPrefix = input.envelope.actor.kind === 'cat' ? `【${displayName}🐱】\n` : '';
|
|
146
|
+
const replyToSender = await replySenders.resolve(input.envelope.replyTo);
|
|
147
|
+
// One thread can carry several provider bindings (the Host allows
|
|
148
|
+
// rebinding different external chats onto the same thread), so the
|
|
149
|
+
// same Host delivery fans out to every binding.
|
|
150
|
+
return {
|
|
151
|
+
replyPrefix,
|
|
152
|
+
inputs: bindings.map(binding => requireConnectorOutboundDelivery({
|
|
153
|
+
deliveryId: input.deliveryId,
|
|
154
|
+
externalConversationId: binding.key,
|
|
155
|
+
presentation: {
|
|
156
|
+
header: displayName,
|
|
157
|
+
body: text,
|
|
158
|
+
origin: input.envelope.actor.kind === 'cat' ? 'agent' : input.envelope.actor.kind === 'system' ? 'system' : 'direct',
|
|
159
|
+
},
|
|
160
|
+
...(replyToSender === undefined ? {} : { metadata: { replyToSender } }),
|
|
161
|
+
...(richBlocks.length === 0 ? {} : { richBlocks }),
|
|
162
|
+
...(media.length === 0 ? {} : { media }),
|
|
163
|
+
})),
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function deliverOutbound(outbound, input, context, replyPrefix) {
|
|
169
|
+
const blocks = [...(input.richBlocks ?? [])];
|
|
170
|
+
if (blocks.length > 0) {
|
|
171
|
+
await outbound.sendRichMessage(input.externalConversationId, input.presentation.body, blocks, input.presentation.header, input.metadata);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
await outbound.sendFormattedReply(input.externalConversationId, {
|
|
175
|
+
...input.presentation,
|
|
176
|
+
origin: input.presentation.origin === 'callback' ? 'callback' : 'direct',
|
|
177
|
+
}, input.metadata);
|
|
178
|
+
}
|
|
179
|
+
for (const media of input.media ?? []) {
|
|
180
|
+
if (media.type === 'video') {
|
|
181
|
+
await outbound.sendReply(input.externalConversationId, `${replyPrefix}⚠️ 视频附件暂不支持发送`, input.metadata);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (!media.reference.startsWith('hmr_')) {
|
|
185
|
+
await outbound.sendReply(input.externalConversationId, `${replyPrefix}⚠️ 媒体不可用(旧引用无法读取)`, input.metadata);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
await outbound.sendMedia(input.externalConversationId, {
|
|
190
|
+
type: media.type,
|
|
191
|
+
content: context.streams.read(media.reference),
|
|
192
|
+
...(media.fileName === undefined ? {} : { fileName: media.fileName }),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
context.log('warn', 'DingTalk outbound media delivery failed', {
|
|
197
|
+
mediaType: media.type,
|
|
198
|
+
errorName: error instanceof Error ? error.name : 'unknown',
|
|
199
|
+
});
|
|
200
|
+
await outbound.sendReply(input.externalConversationId, `${replyPrefix}${error instanceof RangeError ? '⚠️ 媒体过大,超过钉钉发送上限' : '⚠️ 媒体不可用(读取或上传失败)'}`, input.metadata);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export function createDingTalkPluginModule(createRuntime = createDingTalkConnectorRuntime) {
|
|
205
|
+
return definePluginModule((manifest) => definePlugin({
|
|
206
|
+
manifest,
|
|
207
|
+
activate: {
|
|
208
|
+
'dingtalk-messaging': async (context) => {
|
|
209
|
+
let runtime;
|
|
210
|
+
const bridge = await createMessageBridge(context, (input, result) => runtime.outbound.sendFormattedReply(input.chatId, { header: 'Clowder AI', body: result.response, origin: 'callback' }, { chatType: input.group ? 'group' : 'p2p', ...(input.group && input.senderId !== undefined ? { replyToSender: { id: input.senderId } } : {}) }));
|
|
211
|
+
const configure = async () => {
|
|
212
|
+
await runtime?.stop();
|
|
213
|
+
const appKey = await context.config.get('appKey');
|
|
214
|
+
const appSecret = await context.secrets.get('appSecret');
|
|
215
|
+
if (typeof appKey !== 'string')
|
|
216
|
+
throw new TypeError('appKey must be a declared string');
|
|
217
|
+
if (typeof appSecret !== 'string')
|
|
218
|
+
throw new TypeError('appSecret must be a declared secret');
|
|
219
|
+
runtime = createRuntime({
|
|
220
|
+
config: { appKey, appSecret },
|
|
221
|
+
host: { deliver: bridge.deliver },
|
|
222
|
+
logger: { debug: (...args) => context.log('debug', String(args[0]), { args }), info: (...args) => context.log('info', String(args[0]), { args }), warn: (...args) => context.log('warn', String(args[0]), { args }), error: (...args) => context.log('error', String(args[0]), { args }) },
|
|
223
|
+
});
|
|
224
|
+
await runtime.start();
|
|
225
|
+
};
|
|
226
|
+
await configure();
|
|
227
|
+
const mediaSource = createInboundMediaSource(context, locator => runtime.outbound.downloadInboundMedia(locator));
|
|
228
|
+
const lifecycle = createConnectorLifecycleAction(context, {
|
|
229
|
+
sendPlaceholder: (externalConversationId, text) => runtime.outbound.sendPlaceholder(externalConversationId, text),
|
|
230
|
+
editPlaceholder: (externalConversationId, platformMessageId, text, phase) => runtime.outbound.editMessage(externalConversationId, platformMessageId, text, { bypassThrottle: phase === 'blocked' }),
|
|
231
|
+
sendRecovery: (externalConversationId, text) => runtime.outbound.sendReply(externalConversationId, text),
|
|
232
|
+
settle: async ({ platformMessageId, recoveryText }) => {
|
|
233
|
+
if (platformMessageId !== undefined)
|
|
234
|
+
await runtime.outbound.deleteMessage(platformMessageId, recoveryText);
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
return {
|
|
238
|
+
configRefresh: configure,
|
|
239
|
+
streams: mediaSource,
|
|
240
|
+
actions: {
|
|
241
|
+
'dingtalk.outbound': defineDeliveryAction(async (candidate) => {
|
|
242
|
+
if (candidate.kind === 'execution_status') {
|
|
243
|
+
return lifecycle(candidate);
|
|
244
|
+
}
|
|
245
|
+
const { inputs, replyPrefix } = await bridge.outbound(candidate);
|
|
246
|
+
// Per-binding isolation: one thread can fan out to several
|
|
247
|
+
// provider bindings, and a failure on one chat must not block
|
|
248
|
+
// or fail the others. A single binding keeps the old fail-fast
|
|
249
|
+
// behavior so the Host redelivers; with several bindings the
|
|
250
|
+
// action only rejects when every binding failed.
|
|
251
|
+
let firstFailure;
|
|
252
|
+
let delivered = 0;
|
|
253
|
+
for (const input of inputs) {
|
|
254
|
+
try {
|
|
255
|
+
await deliverOutbound(runtime.outbound, input, context, replyPrefix);
|
|
256
|
+
delivered += 1;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
if (firstFailure === undefined)
|
|
260
|
+
firstFailure = error;
|
|
261
|
+
context.log('warn', 'DingTalk outbound delivery to one binding failed', {
|
|
262
|
+
externalConversationId: input.externalConversationId,
|
|
263
|
+
errorName: error instanceof Error ? error.name : 'unknown',
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (delivered === 0) {
|
|
268
|
+
if (firstFailure !== undefined)
|
|
269
|
+
throw firstFailure;
|
|
270
|
+
throw new Error('DingTalk outbound delivery failed for all bindings (provider did not report an error)');
|
|
271
|
+
}
|
|
272
|
+
return { deliveryId: candidate.deliveryId };
|
|
273
|
+
}),
|
|
274
|
+
},
|
|
275
|
+
dispose: () => runtime.stop(),
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
export default createDingTalkPluginModule();
|
|
282
|
+
//# sourceMappingURL=plugin-entrypoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-entrypoint.js","sourceRoot":"","sources":["../src/plugin-entrypoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FeatureContext } from '@clowder-ai/plugin-sdk';
|
|
2
|
+
export interface ReplySender {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function createReplySenderMap(context: FeatureContext): {
|
|
7
|
+
record(hostMessageId: string, replySender: ReplySender): Promise<void>;
|
|
8
|
+
resolve(hostMessageId: string | undefined): Promise<ReplySender | undefined>;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=reply-sender-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply-sender-map.d.ts","sourceRoot":"","sources":["../src/reply-sender-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AA0CD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc;0BAkD5B,MAAM,eAAe,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;2BAgB/C,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;EAmBrF"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const KEY_PREFIX = 'reply-sender:';
|
|
2
|
+
const ENTRY_TTL_MS = 24 * 60 * 60 * 1000;
|
|
3
|
+
const SWEEP_EVERY_RECORDS = 50;
|
|
4
|
+
const ENTRY_CAP = 2000;
|
|
5
|
+
function object(value) {
|
|
6
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function errorName(error) {
|
|
9
|
+
return error instanceof Error ? error.name : 'unknown';
|
|
10
|
+
}
|
|
11
|
+
function parseEntry(value) {
|
|
12
|
+
if (typeof value !== 'string')
|
|
13
|
+
return undefined;
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(value);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
if (!object(parsed) || parsed.version !== 1 || typeof parsed.storedAt !== 'number')
|
|
22
|
+
return undefined;
|
|
23
|
+
const candidate = parsed.sender;
|
|
24
|
+
if (!object(candidate) || typeof candidate.id !== 'string' || candidate.id.length === 0)
|
|
25
|
+
return undefined;
|
|
26
|
+
return {
|
|
27
|
+
version: 1,
|
|
28
|
+
storedAt: parsed.storedAt,
|
|
29
|
+
sender: {
|
|
30
|
+
id: candidate.id,
|
|
31
|
+
...(typeof candidate.name === 'string' ? { name: candidate.name } : {}),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function createReplySenderMap(context) {
|
|
36
|
+
let recordedSinceSweep = 0;
|
|
37
|
+
let sweepInFlight = false;
|
|
38
|
+
const sweep = async () => {
|
|
39
|
+
let listed;
|
|
40
|
+
try {
|
|
41
|
+
listed = await context.storage.list();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
context.log('warn', 'Connector reply-sender mapping sweep failed', { errorName: errorName(error) });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
const live = [];
|
|
49
|
+
for (const [key, item] of Object.entries(listed)) {
|
|
50
|
+
if (!key.startsWith(KEY_PREFIX))
|
|
51
|
+
continue;
|
|
52
|
+
const entry = parseEntry(item?.value);
|
|
53
|
+
if (entry === undefined || entry.storedAt + ENTRY_TTL_MS < now) {
|
|
54
|
+
await context.storage.delete(key).catch(() => undefined);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
live.push({ key, storedAt: entry.storedAt });
|
|
58
|
+
}
|
|
59
|
+
live.sort((a, b) => a.storedAt - b.storedAt);
|
|
60
|
+
let overflow = live.length - (ENTRY_CAP - 1);
|
|
61
|
+
for (let index = 0; overflow > 0 && index < live.length; index += 1, overflow -= 1) {
|
|
62
|
+
await context.storage.delete(live[index].key).catch(() => undefined);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
// Sweep single-flight in the background: recording stays on the inbound
|
|
66
|
+
// hot path and overlapping bursts never stack sweeps. sweep() already
|
|
67
|
+
// swallows and logs its own storage failures. context.log is intentionally
|
|
68
|
+
// NOT used here: log() runs assertActive() and throws
|
|
69
|
+
// FeatureContextRevokedError after stop/revoke, so a sweep racing feature
|
|
70
|
+
// shutdown would turn into an unhandled rejection; console.warn is the
|
|
71
|
+
// reviewer-sanctioned exception that stays callable past revocation.
|
|
72
|
+
const sweepInBackground = () => {
|
|
73
|
+
if (sweepInFlight)
|
|
74
|
+
return;
|
|
75
|
+
sweepInFlight = true;
|
|
76
|
+
void sweep()
|
|
77
|
+
.catch((error) => {
|
|
78
|
+
console.warn('Connector reply-sender mapping sweep failed', { errorName: errorName(error) });
|
|
79
|
+
})
|
|
80
|
+
.finally(() => {
|
|
81
|
+
sweepInFlight = false;
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
async record(hostMessageId, replySender) {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
try {
|
|
88
|
+
await context.storage.set(`${KEY_PREFIX}${hostMessageId}`, JSON.stringify({ version: 1, sender: replySender, storedAt: now }));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
context.log('warn', 'Connector reply-sender mapping record failed', { errorName: errorName(error) });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
recordedSinceSweep += 1;
|
|
95
|
+
if (recordedSinceSweep < SWEEP_EVERY_RECORDS)
|
|
96
|
+
return;
|
|
97
|
+
recordedSinceSweep = 0;
|
|
98
|
+
sweepInBackground();
|
|
99
|
+
},
|
|
100
|
+
async resolve(hostMessageId) {
|
|
101
|
+
if (hostMessageId === undefined)
|
|
102
|
+
return undefined;
|
|
103
|
+
const key = `${KEY_PREFIX}${hostMessageId}`;
|
|
104
|
+
let stored;
|
|
105
|
+
try {
|
|
106
|
+
stored = await context.storage.get(key);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
context.log('warn', 'Connector reply-sender mapping lookup failed', { errorName: errorName(error) });
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const entry = parseEntry(stored?.value);
|
|
113
|
+
if (entry === undefined)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (entry.storedAt + ENTRY_TTL_MS < Date.now()) {
|
|
116
|
+
await context.storage.delete(key).catch(() => undefined);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
return entry.sender;
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=reply-sender-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply-sender-map.js","sourceRoot":"","sources":["../src/reply-sender-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DingTalkAdapter, type DingTalkAdapterOptions, type DingTalkInboundMessage } from './DingTalkAdapter.js';
|
|
2
|
+
import type { ConnectorLogger } from './types.js';
|
|
3
|
+
export interface DingTalkRuntimeConfig {
|
|
4
|
+
readonly appKey: string;
|
|
5
|
+
readonly appSecret: string;
|
|
6
|
+
readonly robotCode?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DingTalkInboundAttachment {
|
|
9
|
+
readonly type: 'image' | 'file' | 'audio';
|
|
10
|
+
readonly platformKey: string;
|
|
11
|
+
readonly fileName?: string;
|
|
12
|
+
readonly duration?: number;
|
|
13
|
+
}
|
|
14
|
+
/** Provider facts only; the Host resolves the authenticated connector binding. */
|
|
15
|
+
export interface DingTalkHostInboundMessage {
|
|
16
|
+
readonly externalConversationId: string;
|
|
17
|
+
readonly providerConversationId: string;
|
|
18
|
+
readonly providerMessageId: string;
|
|
19
|
+
/** Provider sender identity for admission; independent of group reply attribution. */
|
|
20
|
+
readonly externalSenderId?: string;
|
|
21
|
+
readonly text: string;
|
|
22
|
+
readonly attachments?: readonly DingTalkInboundAttachment[];
|
|
23
|
+
readonly sender?: {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly name?: string;
|
|
26
|
+
};
|
|
27
|
+
readonly chatType: 'p2p' | 'group';
|
|
28
|
+
readonly chatName?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface DingTalkRuntimeHost {
|
|
31
|
+
deliver(message: DingTalkHostInboundMessage): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export interface DingTalkOutbound {
|
|
34
|
+
readonly connectorId: string;
|
|
35
|
+
sendReply(externalChatId: string, content: string, metadata?: Record<string, unknown>): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export interface DingTalkRuntimeAdapter extends DingTalkOutbound {
|
|
38
|
+
startStream(handler: (message: DingTalkInboundMessage) => Promise<void>): Promise<void>;
|
|
39
|
+
stopStream(): Promise<void>;
|
|
40
|
+
isStreamLive(): boolean;
|
|
41
|
+
resolveSenderName(senderId: string): string | undefined;
|
|
42
|
+
resolveConversationTitle(chatId: string): string | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface DingTalkConnectorRuntime<Adapter extends DingTalkRuntimeAdapter = DingTalkAdapter> {
|
|
45
|
+
readonly outbound: Adapter;
|
|
46
|
+
start(): Promise<void>;
|
|
47
|
+
stop(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
export interface DingTalkConnectorRuntimeOptions<Adapter extends DingTalkRuntimeAdapter = DingTalkAdapter> {
|
|
50
|
+
readonly config: DingTalkRuntimeConfig;
|
|
51
|
+
readonly host: DingTalkRuntimeHost;
|
|
52
|
+
readonly logger: ConnectorLogger;
|
|
53
|
+
readonly createAdapter?: (config: DingTalkAdapterOptions, logger: ConnectorLogger) => Adapter;
|
|
54
|
+
/** Watchdog poll interval for provider stream liveness (default 15s). */
|
|
55
|
+
readonly streamWatchdogIntervalMs?: number;
|
|
56
|
+
/** Backoff base delay before reconnecting a stream the watchdog found dead (default 5s). */
|
|
57
|
+
readonly reconnectDelayMs?: number;
|
|
58
|
+
/** Backoff delay ceiling (default 60s). Exponential backoff doubles from the
|
|
59
|
+
* base delay with ±20% jitter until this cap. */
|
|
60
|
+
readonly reconnectMaxDelayMs?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Composes DingTalk provider I/O from explicit manifest-declared values.
|
|
64
|
+
* Binding lookup, admission, wake policy, retry, and settlement remain Host
|
|
65
|
+
* responsibilities and are intentionally absent from the delivered payload.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createDingTalkConnectorRuntime<Adapter extends DingTalkRuntimeAdapter = DingTalkAdapter>(options: DingTalkConnectorRuntimeOptions<Adapter>): DingTalkConnectorRuntime<Adapter>;
|
|
68
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|