@zhin.js/adapter-dingtalk 7.0.0 → 7.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @zhin.js/adapter-dingtalk
2
2
 
3
+ ## 7.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 1fc78bc: Unify native platform Client access behind the literal `adapter` discriminant. Handlers infer both native events and Clients, while command, inbound/outbound middleware, and both Agent tool authoring surfaces expose the exact operation-scoped Client through a lazy `$client` getter. Definitions without `adapter` keep `$client` typed as `unknown`, and runtime dispatch rejects adapter mismatches before resolving the Client. Bundled platform tools now use this single path instead of model-provided endpoint ids and adapter-specific dependency wrappers. Every adapter registers one Client/EventMap contract, and protocol adapters including NapCat, Milky, OneBot and Satori now produce transport-independent Client objects rather than letting Endpoint instances impersonate Clients.
8
+ - Updated dependencies [e9c6a73]
9
+ - Updated dependencies [4e8117c]
10
+ - Updated dependencies [902fa35]
11
+ - Updated dependencies [54bfd6b]
12
+ - Updated dependencies [12025ee]
13
+ - Updated dependencies [09b14d6]
14
+ - Updated dependencies [1fc78bc]
15
+ - @zhin.js/agent@1.1.16
16
+ - @zhin.js/adapter@1.2.1
17
+ - @zhin.js/core@1.5.14
18
+ - @zhin.js/host-http@1.0.13
19
+ - @zhin.js/command@1.0.16
20
+ - @zhin.js/logger@1.0.77
21
+ - zhin.js@6.0.14
22
+ - @zhin.js/feature-kit@1.0.13
23
+ - @zhin.js/permission@1.0.4
24
+
3
25
  ## 7.0.0
4
26
 
5
27
  ### Patch Changes
package/README.md CHANGED
@@ -20,7 +20,7 @@ pnpm add @zhin.js/adapter-dingtalk
20
20
 
21
21
  - `@zhin.js/adapter` — 约定式薄入口 `adapters/dingtalk.ts`(`defineAdapter`)
22
22
  - 实现:`src/endpoint.ts`(生命周期/出站/OpenAPI)、`src/webhook.ts`(验签入站)、`src/protocol.ts`
23
- - `@zhin.js/core` — `messageGatewayToken` 入站/出站
23
+ - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
24
24
  - `@zhin.js/host-http` — `httpHostToken` 注册 Webhook 路由(**非** legacy host-router/Koa)
25
25
  - `zhin.js` — `plugin.ts`(`definePlugin`)
26
26
  - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
@@ -75,7 +75,7 @@ plugins:
75
75
 
76
76
  ## Agent 工具
77
77
 
78
- `agent/` 目录保留(get_user、部门、群聊、工作通知等)。Endpoint `start` 时自注册到 `dingtalk-agent-deps`。
78
+ `agent/` 目录保留(get_user、部门、群聊、工作通知等)。工具声明 `adapter: 'dingtalk'` 后,通过惰性的 `context.$client` 自动取得当前操作的 `DingTalkClient`;无需把 Endpoint id 暴露给模型。
79
79
 
80
80
  ## 平台权限(platform permit)
81
81
 
@@ -87,3 +87,12 @@ plugins:
87
87
  pnpm --filter @zhin.js/adapter-dingtalk build
88
88
  pnpm --filter @zhin.js/adapter-dingtalk test
89
89
  ```
90
+
91
+ ## 故障排查
92
+
93
+ | 现象 | 排查 |
94
+ | --- | --- |
95
+ | 平台校验 URL 失败 | 确认公网 HTTPS 可达,HTTP Host 已监听,路径与 `webhookPath` 一致 |
96
+ | Webhook 返回 401/403 | 检查 `appSecret`、签名时间戳与服务器时钟 |
97
+ | 能收到但无法回复 | 检查 `robotCode`、应用权限与 session webhook 是否有效 |
98
+ | Endpoint 未出现 | 在日志查 Schema 或凭据错误,再到运行时能力核对 Endpoint |
@@ -3,7 +3,6 @@
3
3
  * Convention entry: discover `adapters/dingtalk.ts` → defineAdapter.
4
4
  */
5
5
  import { defineAdapter } from 'zhin.js/adapter';
6
- import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
7
6
  import { httpHostToken } from '@zhin.js/host-http';
8
7
  import { DingTalkEndpoint } from "../lib/endpoint.js";
9
8
  import { resolveDingTalkConfig, } from "../lib/protocol.js";
@@ -27,8 +26,6 @@ export default defineAdapter({
27
26
  });
28
27
  return new DingTalkEndpoint({
29
28
  id: context.id,
30
- gateway: context.use(messageGatewayToken),
31
- sideEvents: context.use(sideEventGatewayToken),
32
29
  http: context.use(httpHostToken),
33
30
  config,
34
31
  });
@@ -2,7 +2,6 @@
2
2
  * Convention entry: discover `adapters/dingtalk.ts` → defineAdapter.
3
3
  */
4
4
  import { defineAdapter } from 'zhin.js/adapter';
5
- import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
6
5
  import { httpHostToken } from '@zhin.js/host-http';
7
6
  import { DingTalkEndpoint } from '../src/endpoint.js';
8
7
  import {
@@ -32,8 +31,6 @@ export default defineAdapter<DingTalkAdapterConfig>({
32
31
  });
33
32
  return new DingTalkEndpoint({
34
33
  id: context.id,
35
- gateway: context.use(messageGatewayToken),
36
- sideEvents: context.use(sideEventGatewayToken),
37
34
  http: context.use(httpHostToken),
38
35
  config,
39
36
  });
@@ -1,20 +1,18 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
3
  import { platformPermit } from '../../src/platform-permit.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; user_ids: string }>({
5
+ export default defineAgentTool<{ chat_id: string; user_ids: string }>({
7
6
  description: '向钉钉群聊添加成员',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  chat_id: z.string().describe('群聊 ID'),
11
9
  user_ids: z.string().describe('要添加的用户 ID 列表,逗号分隔'),
12
10
  }),
13
- platforms: ['dingtalk'],
11
+ adapter: 'dingtalk',
14
12
  tags: ['dingtalk'],
15
13
  permissions: [platformPermit('chat_admin')],
16
- async execute({ endpoint_id, chat_id, user_ids }: { endpoint_id: string; chat_id: string; user_ids: string }) {
17
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
14
+ async execute({ chat_id, user_ids }: { chat_id: string; user_ids: string }, context) {
15
+ const endpoint = context.$client;
18
16
  const success = await endpoint.updateChat(chat_id, { add_useridlist: user_ids.split(',') });
19
17
  return { success, message: success ? '成员添加成功' : '添加失败' };
20
18
  },
@@ -1,21 +1,19 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
3
  import { platformPermit } from '../../src/platform-permit.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; name: string; owner: string; members: string }>({
5
+ export default defineAgentTool<{ name: string; owner: string; members: string }>({
7
6
  description: '创建钉钉群聊',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  name: z.string().describe('群名'),
11
9
  owner: z.string().describe('群主用户 ID'),
12
10
  members: z.string().describe('成员用户 ID 列表,逗号分隔'),
13
11
  }),
14
- platforms: ['dingtalk'],
12
+ adapter: 'dingtalk',
15
13
  tags: ['dingtalk'],
16
14
  permissions: [platformPermit('chat_owner')],
17
- async execute({ endpoint_id, name, owner, members }: { endpoint_id: string; name: string; owner: string; members: string }) {
18
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
15
+ async execute({ name, owner, members }: { name: string; owner: string; members: string }, context) {
16
+ const endpoint = context.$client;
19
17
  const chatId = await endpoint.createChat(name, owner, members.split(','));
20
18
  return { success: !!chatId, chat_id: chatId, message: chatId ? `群聊创建成功: ${chatId}` : '创建失败' };
21
19
  },
@@ -1,16 +1,14 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
- export default defineAgentTool<{ endpoint_id: string; dept_id: string }>({
3
+ export default defineAgentTool<{ dept_id: string }>({
5
4
  description: '获取钉钉部门详细信息',
6
5
  inputSchema: z.object({
7
- endpoint_id: z.string().describe('Endpoint 名称'),
8
6
  dept_id: z.string().describe('部门 ID'),
9
7
  }),
10
- platforms: ['dingtalk'],
8
+ adapter: 'dingtalk',
11
9
  tags: ['dingtalk'],
12
- async execute({ endpoint_id, dept_id }: { endpoint_id: string; dept_id: string }) {
13
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
10
+ async execute({ dept_id }: { dept_id: string }, context) {
11
+ const endpoint = context.$client;
14
12
  return await endpoint.getDepartmentInfo(Number(dept_id));
15
13
  },
16
14
  });
@@ -1,16 +1,14 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
- export default defineAgentTool<{ endpoint_id: string; dept_id: string }>({
3
+ export default defineAgentTool<{ dept_id: string }>({
5
4
  description: '获取钉钉部门用户列表',
6
5
  inputSchema: z.object({
7
- endpoint_id: z.string().describe('Endpoint 名称'),
8
6
  dept_id: z.string().describe('部门 ID'),
9
7
  }),
10
- platforms: ['dingtalk'],
8
+ adapter: 'dingtalk',
11
9
  tags: ['dingtalk'],
12
- async execute({ endpoint_id, dept_id }: { endpoint_id: string; dept_id: string }) {
13
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
10
+ async execute({ dept_id }: { dept_id: string }, context) {
11
+ const endpoint = context.$client;
14
12
  const users = await endpoint.getDepartmentUsers(Number(dept_id));
15
13
  return { users, count: users.length };
16
14
  },
@@ -1,16 +1,14 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
- export default defineAgentTool<{ endpoint_id: string; user_id: string }>({
3
+ export default defineAgentTool<{ user_id: string }>({
5
4
  description: '获取钉钉用户信息',
6
5
  inputSchema: z.object({
7
- endpoint_id: z.string().describe('Endpoint 名称'),
8
6
  user_id: z.string().describe('用户 ID'),
9
7
  }),
10
- platforms: ['dingtalk'],
8
+ adapter: 'dingtalk',
11
9
  tags: ['dingtalk'],
12
- async execute({ endpoint_id, user_id }: { endpoint_id: string; user_id: string }) {
13
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
10
+ async execute({ user_id }: { user_id: string }, context) {
11
+ const endpoint = context.$client;
14
12
  return await endpoint.getUserInfo(user_id);
15
13
  },
16
14
  });
@@ -1,16 +1,14 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
- export default defineAgentTool<{ endpoint_id: string; dept_id?: string }>({
3
+ export default defineAgentTool<{ dept_id?: string }>({
5
4
  description: '获取钉钉部门列表',
6
5
  inputSchema: z.object({
7
- endpoint_id: z.string().describe('Endpoint 名称'),
8
6
  dept_id: z.string().optional().describe('父部门 ID,默认 1(根部门)'),
9
7
  }),
10
- platforms: ['dingtalk'],
8
+ adapter: 'dingtalk',
11
9
  tags: ['dingtalk'],
12
- async execute({ endpoint_id, dept_id }: { endpoint_id: string; dept_id?: string }) {
13
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
10
+ async execute({ dept_id }: { dept_id?: string }, context) {
11
+ const endpoint = context.$client;
14
12
  const departments = await endpoint.getDepartmentList(Number(dept_id || '1'));
15
13
  return { departments, count: departments.length };
16
14
  },
@@ -1,17 +1,15 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
- export default defineAgentTool<{ endpoint_id: string; user_ids: string; content: string }>({
3
+ export default defineAgentTool<{ user_ids: string; content: string }>({
5
4
  description: '向指定用户发送钉钉工作通知',
6
5
  inputSchema: z.object({
7
- endpoint_id: z.string().describe('Endpoint 名称'),
8
6
  user_ids: z.string().describe('用户 ID 列表,逗号分隔'),
9
7
  content: z.string().describe('通知内容'),
10
8
  }),
11
- platforms: ['dingtalk'],
9
+ adapter: 'dingtalk',
12
10
  tags: ['dingtalk'],
13
- async execute({ endpoint_id, user_ids, content }: { endpoint_id: string; user_ids: string; content: string }) {
14
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
11
+ async execute({ user_ids, content }: { user_ids: string; content: string }, context) {
12
+ const endpoint = context.$client;
15
13
  const msgContent = { msgtype: 'text', text: { content } };
16
14
  const success = await endpoint.sendWorkNotice(user_ids.split(','), msgContent);
17
15
  return { success, message: success ? '工作通知已发送' : '发送失败' };
@@ -1,20 +1,18 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getDingtalkAgentDeps } from '../../src/dingtalk-agent-deps.js';
4
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }>({
3
+ export default defineAgentTool<{ chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }>({
5
4
  description: '更新钉钉群聊设置(改名、换群主、增减成员)',
6
5
  inputSchema: z.object({
7
- endpoint_id: z.string().describe('Endpoint 名称'),
8
6
  chat_id: z.string().describe('群聊 ID'),
9
7
  name: z.string().optional().describe('新群名(可选)'),
10
8
  owner: z.string().optional().describe('新群主 userId(可选)'),
11
9
  add_members: z.string().optional().describe('要添加的成员 userId,逗号分隔(可选)'),
12
10
  remove_members: z.string().optional().describe('要移除的成员 userId,逗号分隔(可选)'),
13
11
  }),
14
- platforms: ['dingtalk'],
12
+ adapter: 'dingtalk',
15
13
  tags: ['dingtalk'],
16
- async execute({ endpoint_id, chat_id, name, owner, add_members, remove_members }: { endpoint_id: string; chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }) {
17
- const endpoint = getDingtalkAgentDeps().getEndpoint(endpoint_id);
14
+ async execute({ chat_id, name, owner, add_members, remove_members }: { chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }, context) {
15
+ const endpoint = context.$client;
18
16
  const options: Record<string, unknown> = {};
19
17
  if (name) options.name = name;
20
18
  if (owner) options.owner = owner;
@@ -0,0 +1,12 @@
1
+ import type { DingTalkClient } from './endpoint.js';
2
+ import type { DingTalkEvent } from './protocol.js';
3
+ export type DingtalkClientEventMap = Record<string, DingTalkEvent>;
4
+ declare module '@zhin.js/feature-kit' {
5
+ interface AdapterClientRegistry {
6
+ readonly dingtalk: {
7
+ readonly client: DingTalkClient;
8
+ readonly events: DingtalkClientEventMap;
9
+ };
10
+ }
11
+ }
12
+ export declare const dingtalkClient: import("@zhin.js/adapter").EndpointClientToken<DingTalkClient, DingtalkClientEventMap>;
package/lib/client.js ADDED
@@ -0,0 +1,2 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ export const dingtalkClient = defineEndpointClient('dingtalk');
@@ -1 +1 @@
1
- export declare const dingtalkEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage>>>;
1
+ export declare const dingtalkEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
package/lib/endpoint.d.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  /**
2
3
  * DingTalkEndpoint — lifecycle, outbound, admit, OpenAPI helpers for agent tools.
3
4
  */
4
- import type { EndpointInstance, EndpointSendRequest } from 'zhin.js/adapter';
5
- import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
5
+ import { type EndpointSendRequest } from 'zhin.js/adapter';
6
6
  import type { HttpHost } from '@zhin.js/host-http';
7
7
  import type { CapabilityId } from 'zhin.js';
8
8
  import { type DingTalkEvent, type DingTalkMessage, type ResolvedDingTalkConfig } from './protocol.js';
@@ -18,19 +18,46 @@ export type DingTalkFetch = (url: string, init?: {
18
18
  }>;
19
19
  export interface DingTalkEndpointOptions {
20
20
  readonly id: CapabilityId;
21
- readonly gateway: MessageGateway;
22
- readonly sideEvents?: SideEventGateway;
23
21
  readonly http: HttpHost;
24
22
  readonly config: ResolvedDingTalkConfig;
25
23
  readonly fetch?: DingTalkFetch;
26
24
  }
25
+ export interface DingTalkClientApi {
26
+ getUserInfo(userId: string): Promise<unknown>;
27
+ getDepartmentUsers(deptId: number): Promise<unknown[]>;
28
+ sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean>;
29
+ getDepartmentList(deptId?: number): Promise<unknown[]>;
30
+ getDepartmentInfo(deptId: number): Promise<unknown>;
31
+ createChat(name: string, ownerUserId: string, userIdList: string[]): Promise<string | null>;
32
+ getChatInfo(chatId: string): Promise<unknown>;
33
+ updateChat(chatId: string, options: {
34
+ name?: string;
35
+ owner?: string;
36
+ add_useridlist?: string[];
37
+ del_useridlist?: string[];
38
+ }): Promise<boolean>;
39
+ }
40
+ /** SDK-like DingTalk OpenAPI surface available on every Endpoint event. */
41
+ export declare class DingTalkClient implements DingTalkClientApi {
42
+ readonly api: DingTalkClientApi;
43
+ constructor(api: DingTalkClientApi);
44
+ getUserInfo: (userId: string) => Promise<unknown>;
45
+ getDepartmentUsers: (deptId: number) => Promise<unknown[]>;
46
+ sendWorkNotice: (userIds: string[], content: unknown) => Promise<boolean>;
47
+ getDepartmentList: (deptId?: number) => Promise<unknown[]>;
48
+ getDepartmentInfo: (deptId: number) => Promise<unknown>;
49
+ createChat: (name: string, owner: string, users: string[]) => Promise<string | null>;
50
+ getChatInfo: (chatId: string) => Promise<unknown>;
51
+ updateChat: (chatId: string, options: Parameters<DingTalkClientApi["updateChat"]>[1]) => Promise<boolean>;
52
+ }
27
53
  /**
28
54
  * 钉钉机器人(webhook/stream 模式)无常规群列表 API——机器人不持有
29
55
  * 「我所在的群」枚举面,仅能收发消息;
30
56
  * 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
31
57
  */
32
- export declare class DingTalkEndpoint implements EndpointInstance {
58
+ export declare class DingTalkEndpoint extends Endpoint<DingTalkClient> {
33
59
  #private;
60
+ readonly client: DingTalkClient;
34
61
  constructor(options: DingTalkEndpointOptions);
35
62
  /** Used by webhook handler. */
36
63
  get isOpen(): boolean;
@@ -42,17 +69,4 @@ export declare class DingTalkEndpoint implements EndpointInstance {
42
69
  send({ conversation, payload }: EndpointSendRequest): Promise<string>;
43
70
  /** Test / internal: admit a parsed event when open (non-webhook path). */
44
71
  admit(event: DingTalkEvent | DingTalkMessage): void;
45
- getUserInfo(userId: string): Promise<unknown>;
46
- getDepartmentUsers(deptId: number): Promise<unknown[]>;
47
- sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean>;
48
- getDepartmentList(deptId?: number): Promise<unknown[]>;
49
- getDepartmentInfo(deptId: number): Promise<unknown>;
50
- createChat(name: string, ownerUserId: string, userIdList: string[]): Promise<string | null>;
51
- getChatInfo(chatId: string): Promise<unknown>;
52
- updateChat(chatId: string, options: {
53
- name?: string;
54
- owner?: string;
55
- add_useridlist?: string[];
56
- del_useridlist?: string[];
57
- }): Promise<boolean>;
58
72
  }
package/lib/endpoint.js CHANGED
@@ -1,14 +1,39 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
2
- import { registerDingtalkAgentEndpoint } from './dingtalk-agent-deps.js';
3
3
  import { normalizeDingtalkSenderForPermit } from './platform-permit.js';
4
4
  import { dingtalkInboundConversation, formatInboundContent, formatOutboundBody, generateMessageId, isDingtalkBotMentioned, resolveChatType, resolveSender, } from './protocol.js';
5
5
  import { registerDingTalkWebhookRoutes } from './webhook.js';
6
+ /** SDK-like DingTalk OpenAPI surface available on every Endpoint event. */
7
+ export class DingTalkClient {
8
+ api;
9
+ constructor(api) {
10
+ this.api = api;
11
+ }
12
+ getUserInfo = (userId) => this.api.getUserInfo(userId);
13
+ getDepartmentUsers = (deptId) => this.api.getDepartmentUsers(deptId);
14
+ sendWorkNotice = (userIds, content) => this.api.sendWorkNotice(userIds, content);
15
+ getDepartmentList = (deptId) => this.api.getDepartmentList(deptId);
16
+ getDepartmentInfo = (deptId) => this.api.getDepartmentInfo(deptId);
17
+ createChat = (name, owner, users) => this.api.createChat(name, owner, users);
18
+ getChatInfo = (chatId) => this.api.getChatInfo(chatId);
19
+ updateChat = (chatId, options) => this.api.updateChat(chatId, options);
20
+ }
6
21
  /**
7
22
  * 钉钉机器人(webhook/stream 模式)无常规群列表 API——机器人不持有
8
23
  * 「我所在的群」枚举面,仅能收发消息;
9
24
  * 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
10
25
  */
11
- export class DingTalkEndpoint {
26
+ export class DingTalkEndpoint extends Endpoint {
27
+ client = new DingTalkClient({
28
+ getUserInfo: (userId) => this.#getUserInfo(userId),
29
+ getDepartmentUsers: (deptId) => this.#getDepartmentUsers(deptId),
30
+ sendWorkNotice: (userIds, content) => this.#sendWorkNotice(userIds, content),
31
+ getDepartmentList: (deptId) => this.#getDepartmentList(deptId),
32
+ getDepartmentInfo: (deptId) => this.#getDepartmentInfo(deptId),
33
+ createChat: (name, owner, users) => this.#createChat(name, owner, users),
34
+ getChatInfo: (chatId) => this.#getChatInfo(chatId),
35
+ updateChat: (chatId, options) => this.#updateChat(chatId, options),
36
+ });
12
37
  #logger;
13
38
  #options;
14
39
  #fetch;
@@ -18,8 +43,8 @@ export class DingTalkEndpoint {
18
43
  #sessionWebhooks = new Map();
19
44
  #open = false;
20
45
  #started = false;
21
- #unregisterAgent;
22
46
  constructor(options) {
47
+ super();
23
48
  this.#logger = getAdapterLogger('dingtalk', options.config.id);
24
49
  this.#options = options;
25
50
  this.#fetch = options.fetch ?? globalThis.fetch;
@@ -37,7 +62,6 @@ export class DingTalkEndpoint {
37
62
  this.#started = true;
38
63
  try {
39
64
  await this.#refreshAccessToken();
40
- this.#unregisterAgent = registerDingtalkAgentEndpoint(this.#options.config.id, this);
41
65
  this.#routeReleases.push(...registerDingTalkWebhookRoutes(this.#options.http, this));
42
66
  this.#logger.debug(formatCompact({
43
67
  endpoint: this.#options.config.id,
@@ -62,8 +86,6 @@ export class DingTalkEndpoint {
62
86
  this.#sessionWebhooks.clear();
63
87
  for (const release of this.#routeReleases.splice(0))
64
88
  release();
65
- this.#unregisterAgent?.();
66
- this.#unregisterAgent = undefined;
67
89
  this.#started = false;
68
90
  this.#logger.debug(formatCompact({ op: 'disconnect' }));
69
91
  }
@@ -108,13 +130,14 @@ export class DingTalkEndpoint {
108
130
  admit(event) {
109
131
  if (!this.#open)
110
132
  return;
133
+ this.#emitPlatformEvent(event.msgtype || 'event', event);
111
134
  if (event.sessionWebhook && event.conversationId) {
112
135
  this.#sessionWebhooks.set(event.conversationId, event.sessionWebhook);
113
136
  }
114
137
  const conversation = dingtalkInboundConversation(String(this.#options.id), event);
115
138
  const chatType = resolveChatType(event.conversationType);
116
139
  const permit = normalizeDingtalkSenderForPermit({ isAdmin: event.isAdmin === true });
117
- void this.#options.gateway.receive({
140
+ void this.emit('message.receive', {
118
141
  conversation,
119
142
  message: { conversation, id: generateMessageId(event) },
120
143
  content: formatInboundContent(event),
@@ -141,7 +164,16 @@ export class DingTalkEndpoint {
141
164
  }));
142
165
  });
143
166
  }
144
- async getUserInfo(userId) {
167
+ #emitPlatformEvent(name, event) {
168
+ void this.emitPlatform(name, event).catch((error) => {
169
+ this.#logger.warn(formatCompact({
170
+ op: 'dingtalk_platform_event_failed',
171
+ event: name,
172
+ error: error instanceof Error ? error.message : String(error),
173
+ }));
174
+ });
175
+ }
176
+ async #getUserInfo(userId) {
145
177
  try {
146
178
  const data = await this.#request('/topapi/v2/user/get', {
147
179
  method: 'POST',
@@ -156,7 +188,7 @@ export class DingTalkEndpoint {
156
188
  return null;
157
189
  }
158
190
  }
159
- async getDepartmentUsers(deptId) {
191
+ async #getDepartmentUsers(deptId) {
160
192
  try {
161
193
  const data = await this.#request('/topapi/user/listid', {
162
194
  method: 'POST',
@@ -173,7 +205,7 @@ export class DingTalkEndpoint {
173
205
  return [];
174
206
  }
175
207
  }
176
- async sendWorkNotice(userIdList, content) {
208
+ async #sendWorkNotice(userIdList, content) {
177
209
  try {
178
210
  const data = await this.#request('/topapi/message/corpconversation/asyncsend_v2', {
179
211
  method: 'POST',
@@ -192,7 +224,7 @@ export class DingTalkEndpoint {
192
224
  return false;
193
225
  }
194
226
  }
195
- async getDepartmentList(deptId = 1) {
227
+ async #getDepartmentList(deptId = 1) {
196
228
  try {
197
229
  const data = await this.#request('/topapi/v2/department/listsub', {
198
230
  method: 'POST',
@@ -207,7 +239,7 @@ export class DingTalkEndpoint {
207
239
  return [];
208
240
  }
209
241
  }
210
- async getDepartmentInfo(deptId) {
242
+ async #getDepartmentInfo(deptId) {
211
243
  try {
212
244
  const data = await this.#request('/topapi/v2/department/get', {
213
245
  method: 'POST',
@@ -222,7 +254,7 @@ export class DingTalkEndpoint {
222
254
  return null;
223
255
  }
224
256
  }
225
- async createChat(name, ownerUserId, userIdList) {
257
+ async #createChat(name, ownerUserId, userIdList) {
226
258
  try {
227
259
  const data = await this.#request('/topapi/chat/create', {
228
260
  method: 'POST',
@@ -237,7 +269,7 @@ export class DingTalkEndpoint {
237
269
  return null;
238
270
  }
239
271
  }
240
- async getChatInfo(chatId) {
272
+ async #getChatInfo(chatId) {
241
273
  try {
242
274
  const data = await this.#request('/topapi/chat/get', {
243
275
  method: 'POST',
@@ -252,7 +284,7 @@ export class DingTalkEndpoint {
252
284
  return null;
253
285
  }
254
286
  }
255
- async updateChat(chatId, options) {
287
+ async #updateChat(chatId, options) {
256
288
  try {
257
289
  const data = await this.#request('/topapi/chat/update', {
258
290
  method: 'POST',
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { dingtalkInboundConversation, formatInboundContent, formatOutboundBody, generateMessageId, headerValue, normalizeWebhookPath, readTextBody, resolveChatType, resolveDingTalkConfig, resolveSender, verifySignature, type AccessToken, type DingTalkAdapterConfig, type DingTalkApiResponse, type DingTalkEvent, type DingTalkMessage, type DingTalkSendBody, type DingTalkWireSegment, type ResolvedDingTalkConfig, } from './protocol.js';
2
- export { DingTalkEndpoint, type DingTalkEndpointOptions, type DingTalkFetch, } from './endpoint.js';
2
+ export { DingTalkClient, DingTalkEndpoint, type DingTalkClientApi, type DingTalkEndpointOptions, type DingTalkFetch, } from './endpoint.js';
3
3
  export { registerDingTalkWebhookRoutes, handleDingTalkWebhookRequest, type DingTalkWebhookHandler, } from './webhook.js';
4
- export { getDingtalkAgentDeps, registerDingtalkAgentEndpoint, setDingtalkAgentDeps, type DingtalkAgentDeps, type DingtalkAgentEndpoint, } from './dingtalk-agent-deps.js';
4
+ export { dingtalkClient, type DingtalkClientEventMap } from './client.js';
5
5
  export { checkDingtalkPlatformPermit, dingtalkGroupPermitResolver, normalizeDingtalkSenderForPermit, platformPermit, } from './platform-permit.js';
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { dingtalkInboundConversation, formatInboundContent, formatOutboundBody, generateMessageId, headerValue, normalizeWebhookPath, readTextBody, resolveChatType, resolveDingTalkConfig, resolveSender, verifySignature, } from './protocol.js';
2
- export { DingTalkEndpoint, } from './endpoint.js';
2
+ export { DingTalkClient, DingTalkEndpoint, } from './endpoint.js';
3
3
  export { registerDingTalkWebhookRoutes, handleDingTalkWebhookRequest, } from './webhook.js';
4
- export { getDingtalkAgentDeps, registerDingtalkAgentEndpoint, setDingtalkAgentDeps, } from './dingtalk-agent-deps.js';
4
+ export { dingtalkClient } from './client.js';
5
5
  export { checkDingtalkPlatformPermit, dingtalkGroupPermitResolver, normalizeDingtalkSenderForPermit, platformPermit, } from './platform-permit.js';
package/lib/protocol.d.ts CHANGED
@@ -113,7 +113,7 @@ export declare function resolveChatType(conversationType?: string): 'group' | 'p
113
113
  export declare function dingtalkInboundConversation(endpointKey: string, msg: DingTalkMessage): ConversationRef;
114
114
  export declare function resolveSender(msg: DingTalkMessage): string;
115
115
  export declare function generateMessageId(msg: DingTalkMessage): string;
116
- /** Build inbound text for MessageGateway.receive. */
116
+ /** Build inbound text for OutboundMessageService.receive. */
117
117
  export declare function formatInboundContent(msg: DingTalkMessage): string;
118
118
  /** DingTalk timestamps are epoch milliseconds; reject replays outside ±1 hour. */
119
119
  export declare const MAX_TIMESTAMP_DRIFT_MS: number;
package/lib/protocol.js CHANGED
@@ -71,7 +71,7 @@ export function resolveSender(msg) {
71
71
  export function generateMessageId(msg) {
72
72
  return msg.msgId || `${msg.createAt ?? Date.now()}`;
73
73
  }
74
- /** Build inbound text for MessageGateway.receive. */
74
+ /** Build inbound text for OutboundMessageService.receive. */
75
75
  export function formatInboundContent(msg) {
76
76
  if (!msg.msgtype)
77
77
  return '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-dingtalk",
3
- "version": "7.0.0",
3
+ "version": "7.0.1",
4
4
  "description": "Zhin.js DingTalk (钉钉) adapter for Plugin Runtime (HTTP webhook)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -33,21 +33,22 @@
33
33
  "directory": "plugins/adapters/dingtalk"
34
34
  },
35
35
  "dependencies": {
36
- "@zhin.js/adapter": "1.2.0",
37
- "@zhin.js/core": "1.5.13",
38
- "@zhin.js/host-http": "1.0.12",
36
+ "@zhin.js/adapter": "1.2.1",
37
+ "@zhin.js/core": "1.5.14",
38
+ "@zhin.js/feature-kit": "1.0.13",
39
+ "@zhin.js/host-http": "1.0.13",
39
40
  "@zhin.js/im-contract": "1.0.4",
40
- "@zhin.js/logger": "1.0.76"
41
+ "@zhin.js/logger": "1.0.77"
41
42
  },
42
43
  "peerDependencies": {
43
44
  "zod": "^4.0.0",
44
- "@zhin.js/adapter": "1.2.0",
45
- "@zhin.js/agent": "1.1.15",
46
- "@zhin.js/command": "1.0.15",
47
- "@zhin.js/core": "1.5.13",
48
- "@zhin.js/host-http": "1.0.12",
49
- "@zhin.js/permission": "1.0.3",
50
- "zhin.js": "6.0.13"
45
+ "@zhin.js/adapter": "1.2.1",
46
+ "@zhin.js/agent": "1.1.16",
47
+ "@zhin.js/command": "1.0.16",
48
+ "@zhin.js/core": "1.5.14",
49
+ "@zhin.js/host-http": "1.0.13",
50
+ "@zhin.js/permission": "1.0.4",
51
+ "zhin.js": "6.0.14"
51
52
  },
52
53
  "peerDependenciesMeta": {
53
54
  "@zhin.js/agent": {
@@ -68,8 +69,8 @@
68
69
  "typescript": "^6.0.3",
69
70
  "vitest": "^4.1.10",
70
71
  "zod": "^4.4.3",
71
- "@zhin.js/agent": "1.1.15",
72
- "zhin.js": "6.0.13"
72
+ "@zhin.js/agent": "1.1.16",
73
+ "zhin.js": "6.0.14"
73
74
  },
74
75
  "files": [
75
76
  "adapters",
package/src/client.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ import type { DingTalkClient } from './endpoint.js';
3
+ import type { DingTalkEvent } from './protocol.js';
4
+
5
+ export type DingtalkClientEventMap = Record<string, DingTalkEvent>;
6
+
7
+ declare module '@zhin.js/feature-kit' {
8
+ interface AdapterClientRegistry {
9
+ readonly dingtalk: {
10
+ readonly client: DingTalkClient;
11
+ readonly events: DingtalkClientEventMap;
12
+ };
13
+ }
14
+ }
15
+
16
+ export const dingtalkClient = defineEndpointClient<DingTalkClient, DingtalkClientEventMap>('dingtalk');
package/src/endpoint.ts CHANGED
@@ -1,12 +1,11 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  /**
2
3
  * DingTalkEndpoint — lifecycle, outbound, admit, OpenAPI helpers for agent tools.
3
4
  */
4
- import type { EndpointInstance, EndpointSendRequest } from 'zhin.js/adapter';
5
- import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
5
+ import { type EndpointSendRequest } from 'zhin.js/adapter';
6
6
  import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
7
7
  import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
8
8
  import type { CapabilityId } from 'zhin.js';
9
- import { registerDingtalkAgentEndpoint } from './dingtalk-agent-deps.js';
10
9
  import { normalizeDingtalkSenderForPermit } from './platform-permit.js';
11
10
  import {
12
11
  dingtalkInboundConversation,
@@ -41,19 +40,59 @@ export type DingTalkFetch = (
41
40
 
42
41
  export interface DingTalkEndpointOptions {
43
42
  readonly id: CapabilityId;
44
- readonly gateway: MessageGateway;
45
- readonly sideEvents?: SideEventGateway;
46
43
  readonly http: HttpHost;
47
44
  readonly config: ResolvedDingTalkConfig;
48
45
  readonly fetch?: DingTalkFetch;
49
46
  }
50
47
 
48
+ export interface DingTalkClientApi {
49
+ getUserInfo(userId: string): Promise<unknown>;
50
+ getDepartmentUsers(deptId: number): Promise<unknown[]>;
51
+ sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean>;
52
+ getDepartmentList(deptId?: number): Promise<unknown[]>;
53
+ getDepartmentInfo(deptId: number): Promise<unknown>;
54
+ createChat(name: string, ownerUserId: string, userIdList: string[]): Promise<string | null>;
55
+ getChatInfo(chatId: string): Promise<unknown>;
56
+ updateChat(chatId: string, options: {
57
+ name?: string;
58
+ owner?: string;
59
+ add_useridlist?: string[];
60
+ del_useridlist?: string[];
61
+ }): Promise<boolean>;
62
+ }
63
+
64
+ /** SDK-like DingTalk OpenAPI surface available on every Endpoint event. */
65
+ export class DingTalkClient implements DingTalkClientApi {
66
+ constructor(readonly api: DingTalkClientApi) {}
67
+ getUserInfo = (userId: string) => this.api.getUserInfo(userId);
68
+ getDepartmentUsers = (deptId: number) => this.api.getDepartmentUsers(deptId);
69
+ sendWorkNotice = (userIds: string[], content: unknown) =>
70
+ this.api.sendWorkNotice(userIds, content);
71
+ getDepartmentList = (deptId?: number) => this.api.getDepartmentList(deptId);
72
+ getDepartmentInfo = (deptId: number) => this.api.getDepartmentInfo(deptId);
73
+ createChat = (name: string, owner: string, users: string[]) =>
74
+ this.api.createChat(name, owner, users);
75
+ getChatInfo = (chatId: string) => this.api.getChatInfo(chatId);
76
+ updateChat = (chatId: string, options: Parameters<DingTalkClientApi['updateChat']>[1]) =>
77
+ this.api.updateChat(chatId, options);
78
+ }
79
+
51
80
  /**
52
81
  * 钉钉机器人(webhook/stream 模式)无常规群列表 API——机器人不持有
53
82
  * 「我所在的群」枚举面,仅能收发消息;
54
83
  * 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
55
84
  */
56
- export class DingTalkEndpoint implements EndpointInstance {
85
+ export class DingTalkEndpoint extends Endpoint<DingTalkClient> {
86
+ readonly client = new DingTalkClient({
87
+ getUserInfo: (userId) => this.#getUserInfo(userId),
88
+ getDepartmentUsers: (deptId) => this.#getDepartmentUsers(deptId),
89
+ sendWorkNotice: (userIds, content) => this.#sendWorkNotice(userIds, content),
90
+ getDepartmentList: (deptId) => this.#getDepartmentList(deptId),
91
+ getDepartmentInfo: (deptId) => this.#getDepartmentInfo(deptId),
92
+ createChat: (name, owner, users) => this.#createChat(name, owner, users),
93
+ getChatInfo: (chatId) => this.#getChatInfo(chatId),
94
+ updateChat: (chatId, options) => this.#updateChat(chatId, options),
95
+ });
57
96
  readonly #logger!: ReturnType<typeof getAdapterLogger>;
58
97
 
59
98
  readonly #options: DingTalkEndpointOptions;
@@ -64,9 +103,9 @@ export class DingTalkEndpoint implements EndpointInstance {
64
103
  #sessionWebhooks = new Map<string, string>();
65
104
  #open = false;
66
105
  #started = false;
67
- #unregisterAgent?: () => void;
68
106
 
69
107
  constructor(options: DingTalkEndpointOptions) {
108
+ super();
70
109
  this.#logger = getAdapterLogger('dingtalk', options.config.id);
71
110
  this.#options = options;
72
111
  this.#fetch = options.fetch ?? globalThis.fetch;
@@ -86,7 +125,6 @@ export class DingTalkEndpoint implements EndpointInstance {
86
125
  this.#started = true;
87
126
  try {
88
127
  await this.#refreshAccessToken();
89
- this.#unregisterAgent = registerDingtalkAgentEndpoint(this.#options.config.id, this);
90
128
  this.#routeReleases.push(...registerDingTalkWebhookRoutes(this.#options.http, this));
91
129
  this.#logger.debug(formatCompact({
92
130
  endpoint: this.#options.config.id,
@@ -112,8 +150,6 @@ export class DingTalkEndpoint implements EndpointInstance {
112
150
  this.#open = false;
113
151
  this.#sessionWebhooks.clear();
114
152
  for (const release of this.#routeReleases.splice(0)) release();
115
- this.#unregisterAgent?.();
116
- this.#unregisterAgent = undefined;
117
153
  this.#started = false;
118
154
  this.#logger.debug(formatCompact({ op: 'disconnect' }));
119
155
  }
@@ -160,13 +196,14 @@ export class DingTalkEndpoint implements EndpointInstance {
160
196
  /** Test / internal: admit a parsed event when open (non-webhook path). */
161
197
  admit(event: DingTalkEvent | DingTalkMessage): void {
162
198
  if (!this.#open) return;
199
+ this.#emitPlatformEvent(event.msgtype || 'event', event);
163
200
  if (event.sessionWebhook && event.conversationId) {
164
201
  this.#sessionWebhooks.set(event.conversationId, event.sessionWebhook);
165
202
  }
166
203
  const conversation = dingtalkInboundConversation(String(this.#options.id), event);
167
204
  const chatType = resolveChatType(event.conversationType);
168
205
  const permit = normalizeDingtalkSenderForPermit({ isAdmin: event.isAdmin === true });
169
- void this.#options.gateway.receive({
206
+ void this.emit('message.receive', {
170
207
  conversation,
171
208
  message: { conversation, id: generateMessageId(event) },
172
209
  content: formatInboundContent(event),
@@ -194,7 +231,17 @@ export class DingTalkEndpoint implements EndpointInstance {
194
231
  });
195
232
  }
196
233
 
197
- async getUserInfo(userId: string): Promise<unknown> {
234
+ #emitPlatformEvent(name: string, event: unknown): void {
235
+ void this.emitPlatform(name, event).catch((error) => {
236
+ this.#logger.warn(formatCompact({
237
+ op: 'dingtalk_platform_event_failed',
238
+ event: name,
239
+ error: error instanceof Error ? error.message : String(error),
240
+ }));
241
+ });
242
+ }
243
+
244
+ async #getUserInfo(userId: string): Promise<unknown> {
198
245
  try {
199
246
  const data = await this.#request('/topapi/v2/user/get', {
200
247
  method: 'POST',
@@ -208,7 +255,7 @@ export class DingTalkEndpoint implements EndpointInstance {
208
255
  }
209
256
  }
210
257
 
211
- async getDepartmentUsers(deptId: number): Promise<unknown[]> {
258
+ async #getDepartmentUsers(deptId: number): Promise<unknown[]> {
212
259
  try {
213
260
  const data = await this.#request('/topapi/user/listid', {
214
261
  method: 'POST',
@@ -225,7 +272,7 @@ export class DingTalkEndpoint implements EndpointInstance {
225
272
  }
226
273
  }
227
274
 
228
- async sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean> {
275
+ async #sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean> {
229
276
  try {
230
277
  const data = await this.#request('/topapi/message/corpconversation/asyncsend_v2', {
231
278
  method: 'POST',
@@ -243,7 +290,7 @@ export class DingTalkEndpoint implements EndpointInstance {
243
290
  }
244
291
  }
245
292
 
246
- async getDepartmentList(deptId: number = 1): Promise<unknown[]> {
293
+ async #getDepartmentList(deptId: number = 1): Promise<unknown[]> {
247
294
  try {
248
295
  const data = await this.#request('/topapi/v2/department/listsub', {
249
296
  method: 'POST',
@@ -257,7 +304,7 @@ export class DingTalkEndpoint implements EndpointInstance {
257
304
  }
258
305
  }
259
306
 
260
- async getDepartmentInfo(deptId: number): Promise<unknown> {
307
+ async #getDepartmentInfo(deptId: number): Promise<unknown> {
261
308
  try {
262
309
  const data = await this.#request('/topapi/v2/department/get', {
263
310
  method: 'POST',
@@ -271,7 +318,7 @@ export class DingTalkEndpoint implements EndpointInstance {
271
318
  }
272
319
  }
273
320
 
274
- async createChat(
321
+ async #createChat(
275
322
  name: string,
276
323
  ownerUserId: string,
277
324
  userIdList: string[],
@@ -289,7 +336,7 @@ export class DingTalkEndpoint implements EndpointInstance {
289
336
  }
290
337
  }
291
338
 
292
- async getChatInfo(chatId: string): Promise<unknown> {
339
+ async #getChatInfo(chatId: string): Promise<unknown> {
293
340
  try {
294
341
  const data = await this.#request('/topapi/chat/get', {
295
342
  method: 'POST',
@@ -303,7 +350,7 @@ export class DingTalkEndpoint implements EndpointInstance {
303
350
  }
304
351
  }
305
352
 
306
- async updateChat(
353
+ async #updateChat(
307
354
  chatId: string,
308
355
  options: {
309
356
  name?: string;
package/src/index.ts CHANGED
@@ -21,7 +21,9 @@ export {
21
21
  } from './protocol.js';
22
22
 
23
23
  export {
24
+ DingTalkClient,
24
25
  DingTalkEndpoint,
26
+ type DingTalkClientApi,
25
27
  type DingTalkEndpointOptions,
26
28
  type DingTalkFetch,
27
29
  } from './endpoint.js';
@@ -32,13 +34,7 @@ export {
32
34
  type DingTalkWebhookHandler,
33
35
  } from './webhook.js';
34
36
 
35
- export {
36
- getDingtalkAgentDeps,
37
- registerDingtalkAgentEndpoint,
38
- setDingtalkAgentDeps,
39
- type DingtalkAgentDeps,
40
- type DingtalkAgentEndpoint,
41
- } from './dingtalk-agent-deps.js';
37
+ export { dingtalkClient, type DingtalkClientEventMap } from './client.js';
42
38
 
43
39
  export {
44
40
  checkDingtalkPlatformPermit,
package/src/protocol.ts CHANGED
@@ -176,7 +176,7 @@ export function generateMessageId(msg: DingTalkMessage): string {
176
176
  return msg.msgId || `${msg.createAt ?? Date.now()}`;
177
177
  }
178
178
 
179
- /** Build inbound text for MessageGateway.receive. */
179
+ /** Build inbound text for OutboundMessageService.receive. */
180
180
  export function formatInboundContent(msg: DingTalkMessage): string {
181
181
  if (!msg.msgtype) return '';
182
182
  switch (msg.msgtype) {
@@ -1,26 +0,0 @@
1
- /**
2
- * Agent tool deps for dingtalk (user / dept / chat / work notice).
3
- * Endpoints register themselves on start; tools look up by endpoint id.
4
- */
5
- export interface DingtalkAgentEndpoint {
6
- getUserInfo(userId: string): Promise<unknown>;
7
- getDepartmentUsers(deptId: number): Promise<unknown[]>;
8
- sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean>;
9
- getDepartmentList(deptId?: number): Promise<unknown[]>;
10
- getDepartmentInfo(deptId: number): Promise<unknown>;
11
- createChat(name: string, ownerUserId: string, userIdList: string[]): Promise<string | null>;
12
- getChatInfo(chatId: string): Promise<unknown>;
13
- updateChat(chatId: string, options: {
14
- name?: string;
15
- owner?: string;
16
- add_useridlist?: string[];
17
- del_useridlist?: string[];
18
- }): Promise<boolean>;
19
- }
20
- export interface DingtalkAgentDeps {
21
- getEndpoint: (endpointKey: string) => DingtalkAgentEndpoint;
22
- }
23
- export declare function registerDingtalkAgentEndpoint(endpointKey: string, endpoint: DingtalkAgentEndpoint): () => void;
24
- /** Optional override used by tests / transitional callers. Pass `null` to clear. */
25
- export declare function setDingtalkAgentDeps(deps: DingtalkAgentDeps | null): void;
26
- export declare function getDingtalkAgentDeps(): DingtalkAgentDeps;
@@ -1,30 +0,0 @@
1
- /**
2
- * Agent tool deps for dingtalk (user / dept / chat / work notice).
3
- * Endpoints register themselves on start; tools look up by endpoint id.
4
- */
5
- const endpoints = new Map();
6
- let override = null;
7
- export function registerDingtalkAgentEndpoint(endpointKey, endpoint) {
8
- endpoints.set(endpointKey, endpoint);
9
- return () => {
10
- if (endpoints.get(endpointKey) === endpoint) {
11
- endpoints.delete(endpointKey);
12
- }
13
- };
14
- }
15
- /** Optional override used by tests / transitional callers. Pass `null` to clear. */
16
- export function setDingtalkAgentDeps(deps) {
17
- override = deps;
18
- }
19
- export function getDingtalkAgentDeps() {
20
- if (override)
21
- return override;
22
- return {
23
- getEndpoint(endpointKey) {
24
- const endpoint = endpoints.get(endpointKey);
25
- if (!endpoint)
26
- throw new Error(`Endpoint ${endpointKey} 不存在`);
27
- return endpoint;
28
- },
29
- };
30
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * Agent tool deps for dingtalk (user / dept / chat / work notice).
3
- * Endpoints register themselves on start; tools look up by endpoint id.
4
- */
5
-
6
- export interface DingtalkAgentEndpoint {
7
- getUserInfo(userId: string): Promise<unknown>;
8
- getDepartmentUsers(deptId: number): Promise<unknown[]>;
9
- sendWorkNotice(userIdList: string[], content: unknown): Promise<boolean>;
10
- getDepartmentList(deptId?: number): Promise<unknown[]>;
11
- getDepartmentInfo(deptId: number): Promise<unknown>;
12
- createChat(name: string, ownerUserId: string, userIdList: string[]): Promise<string | null>;
13
- getChatInfo(chatId: string): Promise<unknown>;
14
- updateChat(
15
- chatId: string,
16
- options: {
17
- name?: string;
18
- owner?: string;
19
- add_useridlist?: string[];
20
- del_useridlist?: string[];
21
- },
22
- ): Promise<boolean>;
23
- }
24
-
25
- export interface DingtalkAgentDeps {
26
- getEndpoint: (endpointKey: string) => DingtalkAgentEndpoint;
27
- }
28
-
29
- const endpoints = new Map<string, DingtalkAgentEndpoint>();
30
- let override: DingtalkAgentDeps | null = null;
31
-
32
- export function registerDingtalkAgentEndpoint(
33
- endpointKey: string,
34
- endpoint: DingtalkAgentEndpoint,
35
- ): () => void {
36
- endpoints.set(endpointKey, endpoint);
37
- return () => {
38
- if (endpoints.get(endpointKey) === endpoint) {
39
- endpoints.delete(endpointKey);
40
- }
41
- };
42
- }
43
-
44
- /** Optional override used by tests / transitional callers. Pass `null` to clear. */
45
- export function setDingtalkAgentDeps(deps: DingtalkAgentDeps | null): void {
46
- override = deps;
47
- }
48
-
49
- export function getDingtalkAgentDeps(): DingtalkAgentDeps {
50
- if (override) return override;
51
- return {
52
- getEndpoint(endpointKey) {
53
- const endpoint = endpoints.get(endpointKey);
54
- if (!endpoint) throw new Error(`Endpoint ${endpointKey} 不存在`);
55
- return endpoint;
56
- },
57
- };
58
- }