@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.
Files changed (70) hide show
  1. package/README.md +139 -0
  2. package/lib/adapter.d.ts +123 -0
  3. package/lib/adapter.d.ts.map +1 -0
  4. package/lib/adapter.js +355 -0
  5. package/lib/adapter.js.map +1 -0
  6. package/lib/ai-card.d.ts +64 -0
  7. package/lib/ai-card.d.ts.map +1 -0
  8. package/lib/ai-card.js +150 -0
  9. package/lib/ai-card.js.map +1 -0
  10. package/lib/auth/device-registration.d.ts +18 -0
  11. package/lib/auth/device-registration.d.ts.map +1 -0
  12. package/lib/auth/device-registration.js +147 -0
  13. package/lib/auth/device-registration.js.map +1 -0
  14. package/lib/config.d.ts +119 -0
  15. package/lib/config.d.ts.map +1 -0
  16. package/lib/config.js +75 -0
  17. package/lib/config.js.map +1 -0
  18. package/lib/definition.d.ts +53 -0
  19. package/lib/definition.d.ts.map +1 -0
  20. package/lib/definition.js +227 -0
  21. package/lib/definition.js.map +1 -0
  22. package/lib/image-hydrator.d.ts +213 -0
  23. package/lib/image-hydrator.d.ts.map +1 -0
  24. package/lib/image-hydrator.js +244 -0
  25. package/lib/image-hydrator.js.map +1 -0
  26. package/lib/inbound.d.ts +38 -0
  27. package/lib/inbound.d.ts.map +1 -0
  28. package/lib/inbound.js +158 -0
  29. package/lib/inbound.js.map +1 -0
  30. package/lib/index.d.ts +49 -0
  31. package/lib/index.d.ts.map +1 -0
  32. package/lib/index.js +123 -0
  33. package/lib/index.js.map +1 -0
  34. package/lib/manifest.d.ts +23 -0
  35. package/lib/manifest.d.ts.map +1 -0
  36. package/lib/manifest.js +34 -0
  37. package/lib/manifest.js.map +1 -0
  38. package/lib/mapper.d.ts +36 -0
  39. package/lib/mapper.d.ts.map +1 -0
  40. package/lib/mapper.js +175 -0
  41. package/lib/mapper.js.map +1 -0
  42. package/lib/media-mime.d.ts +14 -0
  43. package/lib/media-mime.d.ts.map +1 -0
  44. package/lib/media-mime.js +32 -0
  45. package/lib/media-mime.js.map +1 -0
  46. package/lib/official-upstream.d.ts +143 -0
  47. package/lib/official-upstream.d.ts.map +1 -0
  48. package/lib/official-upstream.js +425 -0
  49. package/lib/official-upstream.js.map +1 -0
  50. package/lib/openapi-port.d.ts +190 -0
  51. package/lib/openapi-port.d.ts.map +1 -0
  52. package/lib/openapi-port.js +2 -0
  53. package/lib/openapi-port.js.map +1 -0
  54. package/lib/outbound.d.ts +69 -0
  55. package/lib/outbound.d.ts.map +1 -0
  56. package/lib/outbound.js +148 -0
  57. package/lib/outbound.js.map +1 -0
  58. package/lib/stream-upstream.d.ts +77 -0
  59. package/lib/stream-upstream.d.ts.map +1 -0
  60. package/lib/stream-upstream.js +303 -0
  61. package/lib/stream-upstream.js.map +1 -0
  62. package/lib/transport.d.ts +37 -0
  63. package/lib/transport.d.ts.map +1 -0
  64. package/lib/transport.js +73 -0
  65. package/lib/transport.js.map +1 -0
  66. package/lib/upstream.d.ts +60 -0
  67. package/lib/upstream.d.ts.map +1 -0
  68. package/lib/upstream.js +61 -0
  69. package/lib/upstream.js.map +1 -0
  70. package/package.json +46 -0
@@ -0,0 +1,37 @@
1
+ export interface HttpRequestInit {
2
+ method?: string;
3
+ body?: unknown;
4
+ headers?: Record<string, string>;
5
+ timeoutMs?: number;
6
+ /**
7
+ * Raw binary body (media upload). When set, `body` is ignored and `raw` is
8
+ * sent verbatim with `contentType` (default `application/octet-stream`).
9
+ */
10
+ raw?: Uint8Array | string;
11
+ /** Content-Type to send alongside a `raw` binary body. */
12
+ contentType?: string;
13
+ /**
14
+ * Response decoding. `'json'` (default) parses the response body as JSON;
15
+ * `'arraybuffer'` returns the raw bytes as a `Uint8Array` (media download,
16
+ * where the body is binary and not JSON).
17
+ */
18
+ responseType?: 'json' | 'arraybuffer';
19
+ }
20
+ export interface HttpTransport {
21
+ request(path: string, init?: HttpRequestInit, signal?: AbortSignal): Promise<unknown>;
22
+ }
23
+ export interface FetchTransportOptions {
24
+ /** Request timeout; overridden per-request by `init.timeoutMs`. */
25
+ timeoutMs: number;
26
+ /** Injectable fetch (tests). */
27
+ fetchImpl?: typeof fetch;
28
+ }
29
+ /** Default transport backed by the standard `fetch`. */
30
+ export declare class FetchTransport implements HttpTransport {
31
+ private readonly timeoutMs;
32
+ private readonly fetchImpl;
33
+ constructor(baseUrl: string, options: FetchTransportOptions);
34
+ private readonly baseUrl;
35
+ request(path: string, init?: HttpRequestInit, signal?: AbortSignal): Promise<unknown>;
36
+ }
37
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,GAAG,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvF;AAED,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,wDAAwD;AACxD,qBAAa,cAAe,YAAW,aAAa;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB;IAM3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAE3B,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;CAwDhG"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * HTTP transport boundary.
3
+ *
4
+ * The transport is the single injection point for tests: the adapter is built
5
+ * against `HttpTransport`, and a fake transport replaces the network without
6
+ * touching driver logic. Timeouts abort the underlying fetch; an external
7
+ * `signal` is combined with the request timeout.
8
+ */
9
+ import { ChannelError } from '@krischoichoi/channel-core';
10
+ /** Default transport backed by the standard `fetch`. */
11
+ export class FetchTransport {
12
+ timeoutMs;
13
+ fetchImpl;
14
+ constructor(baseUrl, options) {
15
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
16
+ this.timeoutMs = options.timeoutMs;
17
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch;
18
+ }
19
+ baseUrl;
20
+ async request(path, init = {}, signal) {
21
+ const controller = new AbortController();
22
+ const timeoutMs = init.timeoutMs ?? this.timeoutMs;
23
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
24
+ const onOuterAbort = () => controller.abort();
25
+ signal?.addEventListener('abort', onOuterAbort, { once: true });
26
+ try {
27
+ const url = /^https?:\/\//i.test(path) ? path : `${this.baseUrl}${path}`;
28
+ const headers = { ...init.headers };
29
+ // `FormData` is passed through untouched so fetch creates the multipart
30
+ // boundary. JSON and legacy raw bytes retain their existing paths.
31
+ const body = init.raw !== undefined
32
+ ? (typeof init.raw === 'string' ? init.raw : new Uint8Array(init.raw.buffer, init.raw.byteOffset, init.raw.byteLength))
33
+ : init.body instanceof FormData
34
+ ? init.body
35
+ : init.body !== undefined
36
+ ? JSON.stringify(init.body)
37
+ : undefined;
38
+ if (init.raw !== undefined) {
39
+ headers['content-type'] = init.contentType ?? 'application/octet-stream';
40
+ }
41
+ else if (init.body !== undefined && !(init.body instanceof FormData)) {
42
+ headers['content-type'] = headers['content-type'] ?? 'application/json';
43
+ }
44
+ const response = await this.fetchImpl(url, {
45
+ method: init.method ?? 'GET',
46
+ headers,
47
+ body,
48
+ signal: controller.signal,
49
+ });
50
+ if (!response.ok) {
51
+ const detail = (await response.text()).replace(/\s+/g, ' ').slice(0, 500);
52
+ throw new ChannelError('CHANNEL_ERROR', `dingtalk http ${response.status} on ${path}${detail ? `: ${detail}` : ''}`);
53
+ }
54
+ if (init.responseType === 'arraybuffer') {
55
+ const buffer = await response.arrayBuffer();
56
+ return new Uint8Array(buffer);
57
+ }
58
+ const text = await response.text();
59
+ return text ? JSON.parse(text) : undefined;
60
+ }
61
+ catch (error) {
62
+ if (error instanceof ChannelError)
63
+ throw error;
64
+ const aborted = error?.name === 'AbortError' || controller.signal.aborted;
65
+ throw new ChannelError('CHANNEL_ERROR', aborted ? `dingtalk http aborted on ${path}` : `dingtalk http failed on ${path}`, { cause: error });
66
+ }
67
+ finally {
68
+ clearTimeout(timer);
69
+ signal?.removeEventListener('abort', onOuterAbort);
70
+ }
71
+ }
72
+ }
73
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * DingTalk HTTP upstream driver — the only module that knows the HTTP
3
+ * endpoints (self-hosted gateway protocol).
4
+ *
5
+ * Two drivers implement the shared `DingTalkUpstream` interface:
6
+ * - `HttpDingTalkUpstream` (this file) — long-poll inbound + HTTP outbound
7
+ * against the self-hosted gateway. The gateway owns platform credentials;
8
+ * the adapter never sees or logs them (architecture §21 / red line 3).
9
+ * - `DingTalkStreamUpstream` (stream-upstream.ts) — inbound via the official
10
+ * `dingtalk-stream` SDK; outbound delegates to a separately injected driver.
11
+ * - `DingTalkOpenApiPortImpl` (official-upstream.ts) — SDK-mode outbound via
12
+ * the message-scoped webhook, AI Card OpenAPI, and proactive/media OAPI.
13
+ *
14
+ * Endpoints (protocol-level, self-hosted gateway):
15
+ * - GET /stream — long-poll for inbound payloads
16
+ * - POST /message/send — plain text message (non-streaming fallback)
17
+ * - POST /card/create — create an AI Card with initial content
18
+ * - POST /card/update — update the card body (status 'update')
19
+ * - POST /card/finish — finalize the card (status 'finished')
20
+ * - POST /card/fail — mark the card failed (status 'failed')
21
+ */
22
+ import type { ChannelTarget } from '@krischoichoi/channel-core';
23
+ import type { HttpTransport } from './transport.js';
24
+ /** Card create response: the gateway-issued card id. */
25
+ export interface CardCreateResult {
26
+ cardId: string;
27
+ }
28
+ export interface DingTalkUpstream {
29
+ /**
30
+ * Long-poll for inbound messages until `signal` aborts. Each raw message is
31
+ * passed to `onMessage` as received (unstructured — the mapper owns shape).
32
+ */
33
+ receive(signal: AbortSignal, onMessage: (raw: unknown) => void): Promise<void>;
34
+ /** Send a plain text message (buffered fallback). */
35
+ sendText(target: ChannelTarget, text: string): Promise<unknown>;
36
+ /** Create an AI Card in the given conversation with initial content. */
37
+ createCard(target: ChannelTarget, text: string): Promise<CardCreateResult>;
38
+ /** Update an AI Card's body text. */
39
+ updateCard(cardId: string, text: string): Promise<unknown>;
40
+ /** Finalize an AI Card. */
41
+ finishCard(cardId: string, text?: string): Promise<unknown>;
42
+ /** Mark an AI Card as failed, optionally with a reason. */
43
+ failCard(cardId: string, reason?: string): Promise<unknown>;
44
+ }
45
+ export interface HttpDingTalkUpstreamOptions {
46
+ transport: HttpTransport;
47
+ longPollTimeoutMs: number;
48
+ }
49
+ /** HTTP implementation over a self-hosted dingtalk gateway. */
50
+ export declare class HttpDingTalkUpstream implements DingTalkUpstream {
51
+ private readonly options;
52
+ constructor(options: HttpDingTalkUpstreamOptions);
53
+ receive(signal: AbortSignal, onMessage: (raw: unknown) => void): Promise<void>;
54
+ sendText(target: ChannelTarget, text: string): Promise<unknown>;
55
+ createCard(target: ChannelTarget, text: string): Promise<CardCreateResult>;
56
+ updateCard(cardId: string, text: string): Promise<unknown>;
57
+ finishCard(cardId: string): Promise<unknown>;
58
+ failCard(cardId: string, reason?: string): Promise<unknown>;
59
+ }
60
+ //# sourceMappingURL=upstream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.d.ts","sourceRoot":"","sources":["../src/upstream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,OAAO,CACL,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAChC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhE,wEAAwE;IACxE,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE3E,qCAAqC;IACrC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3D,2BAA2B;IAC3B,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5D,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,aAAa,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,+DAA+D;AAC/D,qBAAa,oBAAqB,YAAW,gBAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,2BAA2B;IAE3D,OAAO,CACX,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAChC,OAAO,CAAC,IAAI,CAAC;IAqBhB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO/D,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAY1E,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO1D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAO5C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAM5D"}
@@ -0,0 +1,61 @@
1
+ /** HTTP implementation over a self-hosted dingtalk gateway. */
2
+ export class HttpDingTalkUpstream {
3
+ options;
4
+ constructor(options) {
5
+ this.options = options;
6
+ }
7
+ async receive(signal, onMessage) {
8
+ while (!signal.aborted) {
9
+ let raw;
10
+ try {
11
+ raw = await this.options.transport.request('/stream', { timeoutMs: this.options.longPollTimeoutMs }, signal);
12
+ }
13
+ catch (error) {
14
+ // Abort-driven teardown exits gracefully; other failures propagate to
15
+ // the adapter, which owns reconnect/backoff.
16
+ if (signal.aborted)
17
+ return;
18
+ throw error;
19
+ }
20
+ if (raw && typeof raw === 'object' && !signal.aborted) {
21
+ onMessage(raw);
22
+ }
23
+ }
24
+ }
25
+ sendText(target, text) {
26
+ return this.options.transport.request('/message/send', {
27
+ method: 'POST',
28
+ body: { to: target.conversationId, type: 'text', content: text },
29
+ });
30
+ }
31
+ createCard(target, text) {
32
+ return this.options.transport
33
+ .request('/card/create', {
34
+ method: 'POST',
35
+ body: { conversationId: target.conversationId, text },
36
+ })
37
+ .then((raw) => {
38
+ const payload = raw;
39
+ return { cardId: payload.cardId ?? '' };
40
+ });
41
+ }
42
+ updateCard(cardId, text) {
43
+ return this.options.transport.request('/card/update', {
44
+ method: 'POST',
45
+ body: { cardId, text },
46
+ });
47
+ }
48
+ finishCard(cardId) {
49
+ return this.options.transport.request('/card/finish', {
50
+ method: 'POST',
51
+ body: { cardId },
52
+ });
53
+ }
54
+ failCard(cardId, reason) {
55
+ return this.options.transport.request('/card/fail', {
56
+ method: 'POST',
57
+ body: { cardId, reason },
58
+ });
59
+ }
60
+ }
61
+ //# sourceMappingURL=upstream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.js","sourceRoot":"","sources":["../src/upstream.ts"],"names":[],"mappings":"AA4DA,+DAA+D;AAC/D,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;IAAG,CAAC;IAErE,KAAK,CAAC,OAAO,CACX,MAAmB,EACnB,SAAiC;QAEjC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,GAAY,CAAC;YACjB,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CACxC,SAAS,EACT,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAC7C,MAAM,CACP,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,sEAAsE;gBACtE,6CAA6C;gBAC7C,IAAI,MAAM,CAAC,OAAO;oBAAE,OAAO;gBAC3B,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACtD,SAAS,CAAC,GAAG,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,MAAqB,EAAE,IAAY;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,eAAe,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;SACjE,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,MAAqB,EAAE,IAAY;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS;aAC1B,OAAO,CAAC,cAAc,EAAE;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE;SACtD,CAAC;aACD,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,MAAM,OAAO,GAAG,GAAgC,CAAC;YACjD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC;IACP,CAAC;IAED,UAAU,CAAC,MAAc,EAAE,IAAY;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;SACvB,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,MAAM,EAAE;SACjB,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,MAAc,EAAE,MAAe;QACtC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE;YAClD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;SACzB,CAAC,CAAC;IACL,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@krischoichoi/channel-dingtalk",
3
+ "version": "0.6.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/krischoichoi/dsh-channels.git"
7
+ },
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "description": "DingTalk channel adapter for DeepSeek Harness (AI Card streaming, edit strategy)",
12
+ "type": "module",
13
+ "main": "./lib/index.js",
14
+ "types": "./lib/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./lib/index.d.ts",
18
+ "default": "./lib/index.js"
19
+ },
20
+ "./package.json": "./package.json"
21
+ },
22
+ "files": [
23
+ "lib"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc -p tsconfig.json",
27
+ "typecheck": "tsc -p tsconfig.json --noEmit",
28
+ "test": "vitest run --passWithNoTests",
29
+ "clean": "rimraf lib"
30
+ },
31
+ "dependencies": {
32
+ "@deepseek-ai/cordis": "^4.0.4",
33
+ "@deepseek-ai/dsh-credentials": "0.2.0-rc.2",
34
+ "@deepseek-ai/dsh-settings": "0.2.0-rc.2",
35
+ "@deepseek-ai/schemastery": "~3.18.4",
36
+ "@krischoichoi/channel-control": "workspace:*",
37
+ "@krischoichoi/channel-core": "workspace:*",
38
+ "dingtalk-stream": "2.1.5",
39
+ "zod": "^4.4.3"
40
+ },
41
+ "devDependencies": {
42
+ "@krischoichoi/channel-testkit": "workspace:*",
43
+ "rimraf": "^6.0.0"
44
+ },
45
+ "license": "MIT"
46
+ }