@krischoichoi/channel-dingtalk 0.6.0
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 +139 -0
- package/lib/adapter.d.ts +123 -0
- package/lib/adapter.d.ts.map +1 -0
- package/lib/adapter.js +355 -0
- package/lib/adapter.js.map +1 -0
- package/lib/ai-card.d.ts +64 -0
- package/lib/ai-card.d.ts.map +1 -0
- package/lib/ai-card.js +150 -0
- package/lib/ai-card.js.map +1 -0
- package/lib/auth/device-registration.d.ts +18 -0
- package/lib/auth/device-registration.d.ts.map +1 -0
- package/lib/auth/device-registration.js +147 -0
- package/lib/auth/device-registration.js.map +1 -0
- package/lib/config.d.ts +119 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +75 -0
- package/lib/config.js.map +1 -0
- package/lib/definition.d.ts +53 -0
- package/lib/definition.d.ts.map +1 -0
- package/lib/definition.js +227 -0
- package/lib/definition.js.map +1 -0
- package/lib/image-hydrator.d.ts +213 -0
- package/lib/image-hydrator.d.ts.map +1 -0
- package/lib/image-hydrator.js +244 -0
- package/lib/image-hydrator.js.map +1 -0
- package/lib/inbound.d.ts +38 -0
- package/lib/inbound.d.ts.map +1 -0
- package/lib/inbound.js +158 -0
- package/lib/inbound.js.map +1 -0
- package/lib/index.d.ts +49 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +123 -0
- package/lib/index.js.map +1 -0
- package/lib/manifest.d.ts +23 -0
- package/lib/manifest.d.ts.map +1 -0
- package/lib/manifest.js +34 -0
- package/lib/manifest.js.map +1 -0
- package/lib/mapper.d.ts +36 -0
- package/lib/mapper.d.ts.map +1 -0
- package/lib/mapper.js +175 -0
- package/lib/mapper.js.map +1 -0
- package/lib/media-mime.d.ts +14 -0
- package/lib/media-mime.d.ts.map +1 -0
- package/lib/media-mime.js +32 -0
- package/lib/media-mime.js.map +1 -0
- package/lib/official-upstream.d.ts +143 -0
- package/lib/official-upstream.d.ts.map +1 -0
- package/lib/official-upstream.js +425 -0
- package/lib/official-upstream.js.map +1 -0
- package/lib/openapi-port.d.ts +190 -0
- package/lib/openapi-port.d.ts.map +1 -0
- package/lib/openapi-port.js +2 -0
- package/lib/openapi-port.js.map +1 -0
- package/lib/outbound.d.ts +69 -0
- package/lib/outbound.d.ts.map +1 -0
- package/lib/outbound.js +148 -0
- package/lib/outbound.js.map +1 -0
- package/lib/stream-upstream.d.ts +77 -0
- package/lib/stream-upstream.d.ts.map +1 -0
- package/lib/stream-upstream.js +303 -0
- package/lib/stream-upstream.js.map +1 -0
- package/lib/transport.d.ts +37 -0
- package/lib/transport.d.ts.map +1 -0
- package/lib/transport.js +73 -0
- package/lib/transport.js.map +1 -0
- package/lib/upstream.d.ts +60 -0
- package/lib/upstream.d.ts.map +1 -0
- package/lib/upstream.js +61 -0
- package/lib/upstream.js.map +1 -0
- package/package.json +46 -0
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAgB,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAC9G,OAAO,EAAE,MAAM,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EAAE,eAAe,EAA4B,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,CAAC,MAAM,IAAI,GAAG,kBAAkB,CAAC;AACvC,MAAM,CAAC,MAAM,MAAM,GAAa,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAE5D,OAAO,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EACL,uBAAuB,EACvB,sBAAsB,GAGvB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,eAAe,EAA4B,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAoD,MAAM,cAAc,CAAC;AACnG,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,YAAY,GAOb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,cAAc,GAEf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAgD,MAAM,eAAe,CAAC;AACnG,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,cAAc,GAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAYN,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,YAAY,GAIb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAsB,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,UAAU,EACV,aAAa,EACb,QAAQ,EACR,UAAU,GAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAyB,MAAM,eAAe,CAAC;AAoBhE;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CACnB,GAAY,EACZ,SAA8C,EAC9C,OAA4B,EAAE;IAE9B,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAmB,CAAC;IAClE,gFAAgF;IAChF,sEAAsE;IACtE,wEAAwE;IACxE,MAAM,YAAY,GAAI,MAAM,CAAC,QAAsC,CAAC,YAAY,CAAC;IACjF,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,IAAI,0BAA0B,CAAC;IAC1E,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChE,KAAK,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;QAC3D,wEAAwE;QACxE,oEAAoE;QACpE,uEAAuE;QACvE,uEAAuE;QACvE,MAAM,QAAQ,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,EAA4B,CAAC;QAC3F,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,IAAI,CAAC;YACF,SAA4B,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAmC,CAAC;IAC5E,IAAI,OAAO,EAAE,CAAC;QACZ,2EAA2E;QAC3E,uEAAuE;QACvE,eAAe;QACf,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,CAAC,UAAU,CAA8B,CAAC;QAClE,OAAO,CAAC,WAAW,CAAC,QAAQ,CAC1B,wBAAwB,CAAC;YACvB,MAAM;YACN,IAAI;YACJ,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,mBAAmB,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;YAC1F,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;YACpG,eAAe,EAAE,OAAO,CAAC,OAAO;gBAC9B,CAAC,CAAC,KAAK,IAAI,EAAE;oBACT,IAAI,CAAC;wBACH,MAAM,OAAO,CAAC,OAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;oBAC/D,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,6DAA6D;wBAC7D,6DAA6D;wBAC7D,qDAAqD;wBACrD,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAClC,uDAAuD,EACvD,KAAK,CACN,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACH,CAAC,CAAC,SAAS;SACd,CAAC,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,6EAA6E;IAC7E,0EAA0E;IAC1E,gCAAgC;IAChC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO;IAClD,MAAM,cAAc,GAAG,GAA0D,CAAC;IAClF,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QACpB,sEAAsE;QACtE,IAAI,YAAgC,CAAC;QACrC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9E,YAAY,GAAG,QAAQ,EAAE,KAAK,CAAC;YAC/B,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CACjC,4CAA4C,GAAG,mCAAmC,CACnF,CAAC;gBACF,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,mBAAmB,CACjB,GAAG,EACH,IAAI,eAAe,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAC5E,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CACjF,CAAC;QACF,0EAA0E;QAC1E,2DAA2D;QAC3D,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface DingTalkUpstreamManifest {
|
|
2
|
+
reference: string;
|
|
3
|
+
testedVersion: string;
|
|
4
|
+
versionRange: string;
|
|
5
|
+
strategy: 'sdk' | 'source';
|
|
6
|
+
}
|
|
7
|
+
/** Official SDK consumed by the upstream driver, when one is used. */
|
|
8
|
+
export interface DingTalkSdkManifest {
|
|
9
|
+
/** npm package name of the official SDK. */
|
|
10
|
+
package: string;
|
|
11
|
+
/** Version the adapter was verified against. */
|
|
12
|
+
testedVersion: string;
|
|
13
|
+
}
|
|
14
|
+
export interface DingTalkManifest {
|
|
15
|
+
id: 'dingtalk';
|
|
16
|
+
adapterVersion: string;
|
|
17
|
+
upstream: DingTalkUpstreamManifest;
|
|
18
|
+
sdk: DingTalkSdkManifest | undefined;
|
|
19
|
+
status: 'tested';
|
|
20
|
+
}
|
|
21
|
+
/** Current manifest: inbound via the official dingtalk-stream SDK. */
|
|
22
|
+
export declare const manifest: DingTalkManifest;
|
|
23
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC5B;AAED,sEAAsE;AACtE,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,UAAU,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,GAAG,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACrC,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,sEAAsE;AACtE,eAAO,MAAM,QAAQ,EAAE,gBActB,CAAC"}
|
package/lib/manifest.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DingTalk upstream compatibility manifest (M2 + SDK driver).
|
|
3
|
+
*
|
|
4
|
+
* Records the upstream reference and tested version so `channels doctor` and
|
|
5
|
+
* the upgrade pipeline can govern compatibility without re-verifying by hand.
|
|
6
|
+
*
|
|
7
|
+
* Strategy: 'sdk' — inbound rides the official `dingtalk-stream` SDK
|
|
8
|
+
* (WebSocket stream mode). Outbound (message send / AI Card) is not part of
|
|
9
|
+
* the stream SDK; it uses the message-scoped `sessionWebhook` and DingTalk's
|
|
10
|
+
* official AI Card OpenAPI through the shared HTTP transport.
|
|
11
|
+
*
|
|
12
|
+
* Status 'tested' is justified by the Channel Contract + fixture tests plus
|
|
13
|
+
* the SDK-mode offline tests (fake stream client) passing — fully offline.
|
|
14
|
+
* Live verification against a real DingTalk app (AppKey/AppSecret) is a
|
|
15
|
+
* manual step.
|
|
16
|
+
*/
|
|
17
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
18
|
+
/** Current manifest: inbound via the official dingtalk-stream SDK. */
|
|
19
|
+
export const manifest = {
|
|
20
|
+
id: 'dingtalk',
|
|
21
|
+
adapterVersion: pkg.version,
|
|
22
|
+
upstream: {
|
|
23
|
+
reference: 'open-dingtalk/dingtalk-stream-sdk-nodejs (https://github.com/open-dingtalk/dingtalk-stream-sdk-nodejs)',
|
|
24
|
+
testedVersion: '2.1.5',
|
|
25
|
+
versionRange: '2.1.5',
|
|
26
|
+
strategy: 'sdk',
|
|
27
|
+
},
|
|
28
|
+
sdk: {
|
|
29
|
+
package: 'dingtalk-stream',
|
|
30
|
+
testedVersion: '2.1.5',
|
|
31
|
+
},
|
|
32
|
+
status: 'tested',
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAyBxD,sEAAsE;AACtE,MAAM,CAAC,MAAM,QAAQ,GAAqB;IACxC,EAAE,EAAE,UAAU;IACd,cAAc,EAAE,GAAG,CAAC,OAAO;IAC3B,QAAQ,EAAE;QACR,SAAS,EAAE,wGAAwG;QACnH,aAAa,EAAE,OAAO;QACtB,YAAY,EAAE,OAAO;QACrB,QAAQ,EAAE,KAAK;KAChB;IACD,GAAG,EAAE;QACH,OAAO,EAAE,iBAAiB;QAC1B,aAAa,EAAE,OAAO;KACvB;IACD,MAAM,EAAE,QAAQ;CACjB,CAAC"}
|
package/lib/mapper.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure payload mapping (no I/O): platform raw payloads → Channel Contract,
|
|
3
|
+
* and outbound Channel messages → dingtalk text payloads.
|
|
4
|
+
*
|
|
5
|
+
* Raw payloads only ever ride along in `event.raw` for debugging — core and
|
|
6
|
+
* the harness bridge never depend on their shape (red line 6).
|
|
7
|
+
*
|
|
8
|
+
* DingTalk-ish raw shapes are protocol-level and deliberately simple, e.g.:
|
|
9
|
+
* ```json
|
|
10
|
+
* { "type": "text", "msgId": "msg_1", "senderId": "user_123",
|
|
11
|
+
* "conversationId": "conv_456", "content": "hello" }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import type { AccountId, ChannelId, MessageReceived, InteractionReceived, OutboundMessage } from '@krischoichoi/channel-core';
|
|
15
|
+
export interface DingTalkInboundMeta {
|
|
16
|
+
channel: ChannelId;
|
|
17
|
+
accountId: AccountId;
|
|
18
|
+
}
|
|
19
|
+
/** Stable hash for ids when the gateway omits a msgId. */
|
|
20
|
+
export declare function simpleHash(input: string): string;
|
|
21
|
+
/** Map one raw dingtalk message into the stable channel event shape. */
|
|
22
|
+
export declare function mapInbound(raw: unknown, meta: DingTalkInboundMeta): MessageReceived;
|
|
23
|
+
export declare function mapInteraction(raw: unknown, meta: DingTalkInboundMeta): InteractionReceived;
|
|
24
|
+
/** Outbound dingtalk payload; buffered strategy → single text message. */
|
|
25
|
+
export interface DingTalkTextPayload {
|
|
26
|
+
to: string;
|
|
27
|
+
type: 'text';
|
|
28
|
+
content: string;
|
|
29
|
+
}
|
|
30
|
+
/** Convert an outbound channel message into a dingtalk text payload. */
|
|
31
|
+
export declare function toTextPayload(target: {
|
|
32
|
+
conversationId: string;
|
|
33
|
+
}, message: OutboundMessage): DingTalkTextPayload;
|
|
34
|
+
/** Dedup identity for raw payloads (webhook retries share one msgId/eventId). */
|
|
35
|
+
export declare function dedupKey(raw: unknown): string;
|
|
36
|
+
//# sourceMappingURL=mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../src/mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EAIT,eAAe,EACf,mBAAmB,EACnB,eAAe,EAEhB,MAAM,4BAA4B,CAAC;AAIpC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;CACtB;AAmDD,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMhD;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,GAAG,eAAe,CA4BnF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,CAyB3F;AAiDD,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,EAAE,eAAe,GAAG,mBAAmB,CAkC/G;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAG7C"}
|
package/lib/mapper.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { ChannelError, textParts } from '@krischoichoi/channel-core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
const dingtalkRawSchema = z.object({
|
|
4
|
+
type: z.string().optional(),
|
|
5
|
+
msgId: z.string().optional(),
|
|
6
|
+
eventId: z.string().optional(),
|
|
7
|
+
senderId: z.string().optional(),
|
|
8
|
+
conversationId: z.string().optional(),
|
|
9
|
+
conversationType: z.string().optional(),
|
|
10
|
+
content: z.string().optional(),
|
|
11
|
+
mentionedBot: z.boolean().optional(),
|
|
12
|
+
}).passthrough();
|
|
13
|
+
function parseDingTalkRaw(raw) {
|
|
14
|
+
const parsed = dingtalkRawSchema.safeParse(raw);
|
|
15
|
+
if (!parsed.success) {
|
|
16
|
+
throw new ChannelError('CHANNEL_ERROR', 'dingtalk inbound payload is invalid');
|
|
17
|
+
}
|
|
18
|
+
return parsed.data;
|
|
19
|
+
}
|
|
20
|
+
/** True only for genuine http(s) locators. */
|
|
21
|
+
function isHttpUrl(locator) {
|
|
22
|
+
return typeof locator === 'string' && /^https?:\/\//i.test(locator);
|
|
23
|
+
}
|
|
24
|
+
/** Stable hash for ids when the gateway omits a msgId. */
|
|
25
|
+
export function simpleHash(input) {
|
|
26
|
+
let hash = 0;
|
|
27
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
28
|
+
hash = (hash * 31 + input.charCodeAt(i)) | 0;
|
|
29
|
+
}
|
|
30
|
+
return Math.abs(hash).toString(36);
|
|
31
|
+
}
|
|
32
|
+
/** Map one raw dingtalk message into the stable channel event shape. */
|
|
33
|
+
export function mapInbound(raw, meta) {
|
|
34
|
+
const value = parseDingTalkRaw(raw);
|
|
35
|
+
const sender = (value.senderId ?? 'unknown');
|
|
36
|
+
// DingTalk payloads carry a conversation id; fall back to the sender when
|
|
37
|
+
// the gateway omits it (direct/one-off payloads).
|
|
38
|
+
const conversationId = (value.conversationId ?? sender);
|
|
39
|
+
const messageId = value.msgId
|
|
40
|
+
? value.msgId
|
|
41
|
+
: `dt-${simpleHash(`${sender}:${value.content ?? ''}:${value.type ?? 'unknown'}`)}`;
|
|
42
|
+
return {
|
|
43
|
+
type: 'message.received',
|
|
44
|
+
channel: meta.channel,
|
|
45
|
+
accountId: meta.accountId,
|
|
46
|
+
conversation: {
|
|
47
|
+
id: conversationId,
|
|
48
|
+
type: value.conversationType === '2' ? 'group' : 'dm',
|
|
49
|
+
},
|
|
50
|
+
sender: { id: sender },
|
|
51
|
+
message: {
|
|
52
|
+
id: messageId,
|
|
53
|
+
content: partsFor(value),
|
|
54
|
+
createdAt: Date.now(),
|
|
55
|
+
...(value.mentionedBot !== undefined ? { activation: { mentionedBot: value.mentionedBot } } : {}),
|
|
56
|
+
},
|
|
57
|
+
raw,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function mapInteraction(raw, meta) {
|
|
61
|
+
const parsed = z.object({
|
|
62
|
+
type: z.literal('interaction'),
|
|
63
|
+
senderId: z.string().min(1),
|
|
64
|
+
conversationId: z.string().min(1),
|
|
65
|
+
conversationType: z.string().optional(),
|
|
66
|
+
interactionId: z.string().min(1),
|
|
67
|
+
action: z.string().min(1),
|
|
68
|
+
value: z.unknown().optional(),
|
|
69
|
+
}).passthrough().safeParse(raw);
|
|
70
|
+
if (!parsed.success)
|
|
71
|
+
throw new ChannelError('CHANNEL_ERROR', 'dingtalk interaction payload is invalid');
|
|
72
|
+
return {
|
|
73
|
+
type: 'interaction.received',
|
|
74
|
+
channel: meta.channel,
|
|
75
|
+
accountId: meta.accountId,
|
|
76
|
+
conversation: {
|
|
77
|
+
id: parsed.data.conversationId,
|
|
78
|
+
type: parsed.data.conversationType === '2' ? 'group' : 'dm',
|
|
79
|
+
},
|
|
80
|
+
sender: { id: parsed.data.senderId },
|
|
81
|
+
interactionId: parsed.data.interactionId,
|
|
82
|
+
action: parsed.data.action,
|
|
83
|
+
value: parsed.data.value,
|
|
84
|
+
raw,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function partsFor(raw) {
|
|
88
|
+
switch (raw.type) {
|
|
89
|
+
case 'text':
|
|
90
|
+
return textParts(raw.content ?? '');
|
|
91
|
+
case 'image':
|
|
92
|
+
case 'picture': {
|
|
93
|
+
// Official robot picture messages carry an opaque picMediaId/downloadCode
|
|
94
|
+
// (NOT a URL): resourceRef holds the opaque handle, url only a genuine
|
|
95
|
+
// http(s) URL. Resolving resourceRef is the upstream's job.
|
|
96
|
+
const url = isHttpUrl(raw.picUrl) ? raw.picUrl : undefined;
|
|
97
|
+
const opaque = raw.picMediaId ?? raw.picDownloadCode ?? (raw.picUrl ? raw.picUrl : undefined);
|
|
98
|
+
return [{ type: 'image', ...(url ? { url } : opaque ? { resourceRef: opaque } : {}), alt: raw.title }];
|
|
99
|
+
}
|
|
100
|
+
case 'richText': {
|
|
101
|
+
const parts = textParts(raw.content ?? '');
|
|
102
|
+
for (const image of raw.richTextImages ?? []) {
|
|
103
|
+
const url = isHttpUrl(image.pictureUrl) ? image.pictureUrl : undefined;
|
|
104
|
+
const resourceRef = image.downloadCode ? `downloadCode:${image.downloadCode}` : undefined;
|
|
105
|
+
parts.push({ type: 'image', ...(url ? { url } : resourceRef ? { resourceRef } : {}) });
|
|
106
|
+
}
|
|
107
|
+
return parts.length > 0
|
|
108
|
+
? parts
|
|
109
|
+
: [{ type: 'unsupported', reason: "empty dingtalk richText message" }];
|
|
110
|
+
}
|
|
111
|
+
case 'audio':
|
|
112
|
+
case 'voice': {
|
|
113
|
+
const url = isHttpUrl(raw.mediaUrl) ? raw.mediaUrl : undefined;
|
|
114
|
+
const opaque = raw.downloadCode ?? (raw.mediaUrl ? raw.mediaUrl : undefined);
|
|
115
|
+
return [{ type: 'audio', ...(url ? { url } : opaque ? { resourceRef: opaque } : {}), durationMs: raw.durationMs }];
|
|
116
|
+
}
|
|
117
|
+
case 'video': {
|
|
118
|
+
const url = isHttpUrl(raw.mediaUrl) ? raw.mediaUrl : undefined;
|
|
119
|
+
const opaque = raw.downloadCode ?? (raw.mediaUrl ? raw.mediaUrl : undefined);
|
|
120
|
+
return [{ type: 'video', ...(url ? { url } : opaque ? { resourceRef: opaque } : {}), durationMs: raw.durationMs }];
|
|
121
|
+
}
|
|
122
|
+
case 'file': {
|
|
123
|
+
const url = isHttpUrl(raw.mediaUrl) ? raw.mediaUrl : undefined;
|
|
124
|
+
const opaque = raw.downloadCode ?? (raw.mediaUrl ? raw.mediaUrl : undefined);
|
|
125
|
+
return [{ type: 'file', ...(url ? { url } : opaque ? { resourceRef: opaque } : {}), name: raw.title }];
|
|
126
|
+
}
|
|
127
|
+
case 'link':
|
|
128
|
+
return textParts(raw.title ?? raw.content ?? '');
|
|
129
|
+
default:
|
|
130
|
+
return [{ type: 'unsupported', reason: `unknown dingtalk type '${raw.type ?? 'undefined'}'` }];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Convert an outbound channel message into a dingtalk text payload. */
|
|
134
|
+
export function toTextPayload(target, message) {
|
|
135
|
+
const segments = [];
|
|
136
|
+
if (message.text)
|
|
137
|
+
segments.push(message.text);
|
|
138
|
+
if (message.parts) {
|
|
139
|
+
for (const part of message.parts) {
|
|
140
|
+
switch (part.type) {
|
|
141
|
+
case 'text':
|
|
142
|
+
segments.push(part.text);
|
|
143
|
+
break;
|
|
144
|
+
case 'image':
|
|
145
|
+
segments.push(part.alt ? `[image: ${part.alt}]` : '[image]');
|
|
146
|
+
break;
|
|
147
|
+
case 'audio':
|
|
148
|
+
segments.push('[audio]');
|
|
149
|
+
break;
|
|
150
|
+
case 'video':
|
|
151
|
+
segments.push('[video]');
|
|
152
|
+
break;
|
|
153
|
+
case 'file':
|
|
154
|
+
segments.push(part.name ? `[file: ${part.name}]` : '[file]');
|
|
155
|
+
break;
|
|
156
|
+
case 'location':
|
|
157
|
+
segments.push(`[location: ${part.latitude},${part.longitude}]`);
|
|
158
|
+
break;
|
|
159
|
+
case 'card':
|
|
160
|
+
segments.push(`[card: ${part.kind}]`);
|
|
161
|
+
break;
|
|
162
|
+
case 'unsupported':
|
|
163
|
+
segments.push('[unsupported content]');
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { to: target.conversationId, type: 'text', content: segments.join('') };
|
|
169
|
+
}
|
|
170
|
+
/** Dedup identity for raw payloads (webhook retries share one msgId/eventId). */
|
|
171
|
+
export function dedupKey(raw) {
|
|
172
|
+
const value = parseDingTalkRaw(raw);
|
|
173
|
+
return value.msgId ?? value.eventId ?? `dt-${simpleHash(JSON.stringify(value))}`;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.js","sourceRoot":"","sources":["../src/mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal raster-image MIME sniffing for media bytes downloaded from the
|
|
3
|
+
* DingTalk download API.
|
|
4
|
+
*
|
|
5
|
+
* This is NOT a platform protocol: it is a local content-sniffing helper so
|
|
6
|
+
* the Harness `saveImage()` seam receives a valid raster `ImageMediaType`
|
|
7
|
+
* (the message-converter only commits an image when a raster MIME is known).
|
|
8
|
+
* The official connector does the same thing (ext derives from the response
|
|
9
|
+
* content-type); here we sniff magic bytes because the shared transport
|
|
10
|
+
* returns raw bytes without headers.
|
|
11
|
+
*/
|
|
12
|
+
/** Raster MIME sniffed from the leading magic bytes, if recognized. */
|
|
13
|
+
export declare function sniffImageMime(data: Uint8Array): 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif' | undefined;
|
|
14
|
+
//# sourceMappingURL=media-mime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-mime.d.ts","sourceRoot":"","sources":["../src/media-mime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAgBpH"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal raster-image MIME sniffing for media bytes downloaded from the
|
|
3
|
+
* DingTalk download API.
|
|
4
|
+
*
|
|
5
|
+
* This is NOT a platform protocol: it is a local content-sniffing helper so
|
|
6
|
+
* the Harness `saveImage()` seam receives a valid raster `ImageMediaType`
|
|
7
|
+
* (the message-converter only commits an image when a raster MIME is known).
|
|
8
|
+
* The official connector does the same thing (ext derives from the response
|
|
9
|
+
* content-type); here we sniff magic bytes because the shared transport
|
|
10
|
+
* returns raw bytes without headers.
|
|
11
|
+
*/
|
|
12
|
+
/** Raster MIME sniffed from the leading magic bytes, if recognized. */
|
|
13
|
+
export function sniffImageMime(data) {
|
|
14
|
+
if (data.byteLength < 8)
|
|
15
|
+
return undefined;
|
|
16
|
+
// PNG: 89 50 4E 47 0D 0A 1A 0A
|
|
17
|
+
if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47)
|
|
18
|
+
return 'image/png';
|
|
19
|
+
// JPEG: FF D8 FF
|
|
20
|
+
if (data[0] === 0xff && data[1] === 0xd8 && data[2] === 0xff)
|
|
21
|
+
return 'image/jpeg';
|
|
22
|
+
// GIF: 'GIF8'
|
|
23
|
+
if (data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x38)
|
|
24
|
+
return 'image/gif';
|
|
25
|
+
// WebP: 'RIFF' .... 'WEBP'
|
|
26
|
+
if (data[0] === 0x52 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x46 &&
|
|
27
|
+
data[8] === 0x57 && data[9] === 0x45 && data[10] === 0x42 && data[11] === 0x50) {
|
|
28
|
+
return 'image/webp';
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=media-mime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-mime.js","sourceRoot":"","sources":["../src/media-mime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,IAAgB;IAC7C,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,+BAA+B;IAC/B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,WAAW,CAAC;IACrG,iBAAiB;IACjB,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC;IAClF,cAAc;IACd,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,WAAW,CAAC;IACrG,2BAA2B;IAC3B,IACE,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;QAC5E,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,EAC9E,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Official DingTalk OpenAPI port implementation.
|
|
3
|
+
*
|
|
4
|
+
* Positioned as `DingTalkOpenApiPortImpl`: it is the thin
|
|
5
|
+
* implementation of `DingTalkOpenApiPort`, and it also implements the
|
|
6
|
+
* `DingTalkUpstream` outbound surface so `DingTalkStreamUpstream` can keep
|
|
7
|
+
* delegating to it unchanged. Stream-mode reply messages carry a short-lived
|
|
8
|
+
* sessionWebhook used ONLY for the current inbound reply; AI Cards
|
|
9
|
+
* and proactive sends use the documented DingTalk OpenAPI with an application
|
|
10
|
+
* access token. Neither path requires the legacy local gateway.
|
|
11
|
+
*
|
|
12
|
+
* Behavior oracle / payload contract:
|
|
13
|
+
* `@dingtalk-real-ai/dingtalk-connector@0.8.24`.
|
|
14
|
+
* Every port method records its official-behavior basis in
|
|
15
|
+
* `DingTalkOpenApiPortImpl.OFFICIAL_BASIS` (and its own docblock). Methods with
|
|
16
|
+
* no official-behavior basis are marked `@upstream-gap` / `@deprecated` with a
|
|
17
|
+
* reason (delete any protocol with no official basis).
|
|
18
|
+
*/
|
|
19
|
+
import type { ChannelTarget, OutboundActionRow } from '@krischoichoi/channel-core';
|
|
20
|
+
import type { CardCreateResult, DingTalkUpstream } from './upstream.js';
|
|
21
|
+
import type { HttpTransport } from './transport.js';
|
|
22
|
+
import type { RemoteMediaFetchLike } from './image-hydrator.js';
|
|
23
|
+
import type { DingTalkOpenApiPort, DingTalkOpenApiCredentials, MediaSendInput, MediaUploadInput, MediaUploadResult, ProactiveTextInput, ResolvedMedia, RobotMessageSendResult } from './openapi-port.js';
|
|
24
|
+
export interface DingTalkOfficialUpstreamOptions extends DingTalkOpenApiCredentials {
|
|
25
|
+
transport: HttpTransport;
|
|
26
|
+
/** Shared host safety boundary for short-lived DingTalk download URLs. */
|
|
27
|
+
secureFetch?: RemoteMediaFetchLike;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Official DingTalk OpenAPI port implementation (rename of the former
|
|
31
|
+
* `DingTalkOfficialUpstream`). Implements the small `DingTalkOpenApiPort`
|
|
32
|
+
* plus the `DingTalkUpstream` outbound surface it always had.
|
|
33
|
+
*
|
|
34
|
+
* The legacy name `DingTalkOfficialUpstream` is preserved as an alias below so
|
|
35
|
+
* existing import/call sites and tests keep compiling unchanged.
|
|
36
|
+
*/
|
|
37
|
+
export declare class DingTalkOpenApiPortImpl implements DingTalkOpenApiPort, DingTalkUpstream {
|
|
38
|
+
private readonly options;
|
|
39
|
+
private readonly now;
|
|
40
|
+
private cachedToken?;
|
|
41
|
+
private readonly inputingCards;
|
|
42
|
+
private readonly secureFetch;
|
|
43
|
+
constructor(options: DingTalkOfficialUpstreamOptions);
|
|
44
|
+
receive(): Promise<void>;
|
|
45
|
+
/** Reply path: sessionWebhook is ONLY for the current inbound reply. */
|
|
46
|
+
sendText(target: ChannelTarget, text: string): Promise<unknown>;
|
|
47
|
+
/**
|
|
48
|
+
* Get (and cache) the application access token. Official behavior basis:
|
|
49
|
+
* DingTalk OpenAPI `POST /v1.0/oauth2/accessToken` (the official connector's
|
|
50
|
+
* token acquisition, mirrored here).
|
|
51
|
+
*/
|
|
52
|
+
getAccessToken(): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Proactive plain-text robot send: official proactive API,
|
|
55
|
+
* never sessionWebhook. Official behavior basis: DingTalk robot message send
|
|
56
|
+
* (`POST /v1.0/robot/groupMessages/send` for groups;
|
|
57
|
+
* `POST /v1.0/robot/oToMessages/batchSend` for single chat), msgKey `sampleText`,
|
|
58
|
+
* msgParam `{ "content": ... }` — mirrors the official connector's proactive
|
|
59
|
+
* robot message path. Payload contract from the official connector.
|
|
60
|
+
*/
|
|
61
|
+
sendProactiveText(input: ProactiveTextInput): Promise<RobotMessageSendResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Upload a media file. Official behavior basis:
|
|
64
|
+
* DingTalk media upload `POST /media/upload?access_token=...&type=image|file`
|
|
65
|
+
* as used by the connector. Standard `FormData` delegates multipart framing
|
|
66
|
+
* to fetch instead of reproducing a platform protocol in this package.
|
|
67
|
+
*/
|
|
68
|
+
uploadMedia(input: MediaUploadInput): Promise<MediaUploadResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Send an uploaded mediaId as a robot image/file message.
|
|
71
|
+
* Official behavior basis: DingTalk robot message send with msgKey
|
|
72
|
+
* `sampleImageMsg` with `{ photoURL: mediaId }` for images, and
|
|
73
|
+
* `sampleFile` with `{ mediaId, fileName, fileType }` for files, matching
|
|
74
|
+
* the connector's verified proactive paths.
|
|
75
|
+
*/
|
|
76
|
+
sendMedia(input: MediaSendInput): Promise<RobotMessageSendResult>;
|
|
77
|
+
sendInteractiveCard(input: {
|
|
78
|
+
target: ChannelTarget;
|
|
79
|
+
templateId: string;
|
|
80
|
+
text: string;
|
|
81
|
+
actions: OutboundActionRow[];
|
|
82
|
+
textParam: string;
|
|
83
|
+
actionsParam: string;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
messageId?: string;
|
|
86
|
+
outTrackId: string;
|
|
87
|
+
raw?: unknown;
|
|
88
|
+
}>;
|
|
89
|
+
updateInteractiveCard(input: {
|
|
90
|
+
outTrackId: string;
|
|
91
|
+
text: string;
|
|
92
|
+
actions: OutboundActionRow[];
|
|
93
|
+
textParam: string;
|
|
94
|
+
actionsParam: string;
|
|
95
|
+
}): Promise<unknown>;
|
|
96
|
+
createCard(target: ChannelTarget, _text: string): Promise<CardCreateResult>;
|
|
97
|
+
updateCard(cardId: string, text: string): Promise<unknown>;
|
|
98
|
+
finishCard(cardId: string, text?: string): Promise<unknown>;
|
|
99
|
+
failCard(cardId: string, reason?: string): Promise<unknown>;
|
|
100
|
+
/**
|
|
101
|
+
* Resolve an opaque DingTalk media handle (mediaId / downloadCode) into
|
|
102
|
+
* trusted bytes. Official behavior basis: the connector's
|
|
103
|
+
* `downloadMediaByCode` / `getFileDownloadUrl` — POST
|
|
104
|
+
* `/v1.0/robot/messageFiles/download` with `{ downloadCode, robotCode }`
|
|
105
|
+
* and the application access token returns `{ downloadUrl }`; the URL is
|
|
106
|
+
* then fetched as raw bytes (responseType arraybuffer). A genuine http(s)
|
|
107
|
+
* `ref` is fetched directly. Fails closed with a typed error when an opaque
|
|
108
|
+
* ref lacks the per-message `downloadCode` context.
|
|
109
|
+
*/
|
|
110
|
+
resolveMedia(ref: string, options?: {
|
|
111
|
+
signal?: AbortSignal;
|
|
112
|
+
name?: string;
|
|
113
|
+
downloadCode?: string;
|
|
114
|
+
robotCode?: string;
|
|
115
|
+
}): Promise<ResolvedMedia>;
|
|
116
|
+
/**
|
|
117
|
+
* Resolve an opaque DingTalk media handle into a download URL. Official
|
|
118
|
+
* behavior basis: the connector's `getFileDownloadUrl` — POST
|
|
119
|
+
* `/v1.0/robot/messageFiles/download` with `{ downloadCode, robotCode }`
|
|
120
|
+
* and `x-acs-dingtalk-access-token`. A genuine http(s) ref is returned
|
|
121
|
+
* as-is. Returns `undefined` (fail closed) when an opaque ref lacks the
|
|
122
|
+
* downloadCode context.
|
|
123
|
+
*/
|
|
124
|
+
getMediaDownloadUrl(ref: string, options?: {
|
|
125
|
+
signal?: AbortSignal;
|
|
126
|
+
downloadCode?: string;
|
|
127
|
+
robotCode?: string;
|
|
128
|
+
}): Promise<string | undefined>;
|
|
129
|
+
private ensureCardInputing;
|
|
130
|
+
private targetData;
|
|
131
|
+
private cardDelivery;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Official-behavior basis for every port method: maps a port method
|
|
135
|
+
* name to the corresponding official connector implementation location / behavior
|
|
136
|
+
* oracle, or an explicit `@upstream-gap` / `@deprecated` marker with a reason.
|
|
137
|
+
* The port-inventory test asserts every interface method has a non-empty entry
|
|
138
|
+
* here (shape + marker presence).
|
|
139
|
+
*/
|
|
140
|
+
export declare const OFFICIAL_BASIS: Record<string, string>;
|
|
141
|
+
/** Legacy alias (rename): `DingTalkOfficialUpstream` -> `DingTalkOpenApiPortImpl`. */
|
|
142
|
+
export declare const DingTalkOfficialUpstream: typeof DingTalkOpenApiPortImpl;
|
|
143
|
+
//# sourceMappingURL=official-upstream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"official-upstream.d.ts","sourceRoot":"","sources":["../src/official-upstream.ts"],"names":[],"mappings":"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"}
|