@zhin.js/adapter-telegram 7.0.14 → 8.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,40 @@
1
1
  # Changelog
2
2
 
3
+ ## 8.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
+
25
+ ## 8.0.0
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies [b10d058]
30
+ - Updated dependencies [f2c532f]
31
+ - Updated dependencies [3dbf990]
32
+ - @zhin.js/host-http@1.0.12
33
+ - @zhin.js/adapter@1.2.0
34
+ - @zhin.js/core@1.5.13
35
+ - @zhin.js/agent@1.1.15
36
+ - zhin.js@6.0.13
37
+
3
38
  ## 7.0.14
4
39
 
5
40
  ### Patch Changes
package/README.md CHANGED
@@ -20,7 +20,7 @@ pnpm add @zhin.js/adapter-telegram
20
20
  ## Plugin Runtime
21
21
 
22
22
  - `@zhin.js/adapter` — 约定式 `adapters/telegram.ts`(`defineAdapter`)
23
- - `@zhin.js/core` — `messageGatewayToken` 入站/出站
23
+ - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
24
24
  - `zhin.js` — `plugin.ts`(`definePlugin`)
25
25
  - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
26
26
  - **无需** `@zhin.js/host-http`(polling 路径)
@@ -3,7 +3,6 @@
3
3
  * Convention entry: discover `adapters/telegram.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 { TelegramEndpoint } from "../lib/endpoint.js";
9
8
  import { resolveTelegramConfig, } from "../lib/protocol.js";
@@ -28,8 +27,6 @@ export default defineAdapter({
28
27
  });
29
28
  return new TelegramEndpoint({
30
29
  id: context.id,
31
- gateway: context.use(messageGatewayToken),
32
- sideEvents: context.use(sideEventGatewayToken),
33
30
  config,
34
31
  http: config.mode === 'webhook' ? context.use(httpHostToken) : undefined,
35
32
  });
@@ -2,7 +2,6 @@
2
2
  * Convention entry: discover `adapters/telegram.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 { TelegramEndpoint } from '../src/endpoint.js';
8
7
  import {
@@ -33,8 +32,6 @@ export default defineAdapter<TelegramAdapterConfig>({
33
32
  });
34
33
  return new TelegramEndpoint({
35
34
  id: context.id,
36
- gateway: context.use(messageGatewayToken),
37
- sideEvents: context.use(sideEventGatewayToken),
38
35
  config,
39
36
  http: config.mode === 'webhook' ? context.use(httpHostToken) : undefined,
40
37
  });
@@ -1,19 +1,17 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; chat_id: string }>({
5
+ export default defineAgentTool<{ chat_id: string }>({
7
6
  description: '创建 Telegram 群组邀请链接',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  chat_id: z.string().describe('聊天 ID'),
11
9
  }),
12
- platforms: ['telegram'],
10
+ adapter: 'telegram',
13
11
  tags: ['telegram'],
14
12
  permissions: [platformPermit('chat_administrator')],
15
- async execute({ endpoint_id, chat_id }: { endpoint_id: string; chat_id: string }) {
16
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
13
+ async execute({ chat_id }: { chat_id: string }, context) {
14
+ const endpoint = context.$client;
17
15
  const link = await endpoint.createInviteLink(Number(chat_id));
18
16
  return { invite_link: link, message: `邀请链接: ${link}` };
19
17
  },
@@ -1,17 +1,15 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; chat_id: string }>({
4
+ export default defineAgentTool<{ chat_id: string }>({
6
5
  description: '获取 Telegram 群组管理员列表',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  chat_id: z.string().describe('聊天 ID'),
10
8
  }),
11
- platforms: ['telegram'],
9
+ adapter: 'telegram',
12
10
  tags: ['telegram'],
13
- async execute({ endpoint_id, chat_id }: { endpoint_id: string; chat_id: string }) {
14
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
11
+ async execute({ chat_id }: { chat_id: string }, context) {
12
+ const endpoint = context.$client;
15
13
  const admins = await endpoint.getChatAdmins(Number(chat_id));
16
14
  return {
17
15
  admins: admins.map((a: { user: { id: number; username?: string; first_name?: string }; status: string }) => ({
@@ -1,17 +1,15 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; chat_id: string }>({
4
+ export default defineAgentTool<{ chat_id: string }>({
6
5
  description: '获取 Telegram 群组成员数量',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  chat_id: z.string().describe('聊天 ID'),
10
8
  }),
11
- platforms: ['telegram'],
9
+ adapter: 'telegram',
12
10
  tags: ['telegram'],
13
- async execute({ endpoint_id, chat_id }: { endpoint_id: string; chat_id: string }) {
14
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
11
+ async execute({ chat_id }: { chat_id: string }, context) {
12
+ const endpoint = context.$client;
15
13
  const count = await endpoint.getChatMemberCount(Number(chat_id));
16
14
  return { count, message: `群组共有 ${count} 名成员` };
17
15
  },
@@ -1,20 +1,18 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; message_id: string }>({
5
+ export default defineAgentTool<{ chat_id: string; message_id: string }>({
7
6
  description: '置顶 Telegram 群组消息',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  chat_id: z.string().describe('聊天 ID'),
11
9
  message_id: z.string().describe('消息 ID'),
12
10
  }),
13
- platforms: ['telegram'],
11
+ adapter: 'telegram',
14
12
  tags: ['telegram'],
15
13
  permissions: [platformPermit('pin_messages')],
16
- async execute({ endpoint_id, chat_id, message_id }: { endpoint_id: string; chat_id: string; message_id: string }) {
17
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
14
+ async execute({ chat_id, message_id }: { chat_id: string; message_id: string }, context) {
15
+ const endpoint = context.$client;
18
16
  const success = await endpoint.pinMessage(Number(chat_id), Number(message_id));
19
17
  return { success, message: success ? '消息已置顶' : '操作失败' };
20
18
  },
@@ -1,19 +1,17 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; message_id: string; reaction: string }>({
4
+ export default defineAgentTool<{ chat_id: string; message_id: string; reaction: string }>({
6
5
  description: '对 Telegram 消息添加表情反应',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  chat_id: z.string().describe('聊天 ID'),
10
8
  message_id: z.string().describe('消息 ID'),
11
9
  reaction: z.string().describe('反应表情(如 👍、❤️、🔥)'),
12
10
  }),
13
- platforms: ['telegram'],
11
+ adapter: 'telegram',
14
12
  tags: ['telegram'],
15
- async execute({ endpoint_id, chat_id, message_id, reaction }: { endpoint_id: string; chat_id: string; message_id: string; reaction: string }) {
16
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
13
+ async execute({ chat_id, message_id, reaction }: { chat_id: string; message_id: string; reaction: string }, context) {
14
+ const endpoint = context.$client;
17
15
  const success = await endpoint.setMessageReaction(Number(chat_id), Number(message_id), reaction);
18
16
  return { success, message: success ? `已添加反应 ${reaction}` : '操作失败' };
19
17
  },
@@ -1,21 +1,19 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; question: string; options: string; is_anonymous?: boolean; allows_multiple?: boolean }>({
4
+ export default defineAgentTool<{ chat_id: string; question: string; options: string; is_anonymous?: boolean; allows_multiple?: boolean }>({
6
5
  description: '在 Telegram 群组中发起投票',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  chat_id: z.string().describe('聊天 ID'),
10
8
  question: z.string().describe('投票问题'),
11
9
  options: z.string().describe('选项 JSON 数组,如 ["A","B","C"]'),
12
10
  is_anonymous: z.boolean().optional().describe('是否匿名投票,默认 true'),
13
11
  allows_multiple: z.boolean().optional().describe('是否允许多选,默认 false'),
14
12
  }),
15
- platforms: ['telegram'],
13
+ adapter: 'telegram',
16
14
  tags: ['telegram'],
17
- async execute({ endpoint_id, chat_id, question, options, is_anonymous, allows_multiple }: { endpoint_id: string; chat_id: string; question: string; options: string; is_anonymous?: boolean; allows_multiple?: boolean }) {
18
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
15
+ async execute({ chat_id, question, options, is_anonymous, allows_multiple }: { chat_id: string; question: string; options: string; is_anonymous?: boolean; allows_multiple?: boolean }, context) {
16
+ const endpoint = context.$client;
19
17
  let optList: string[];
20
18
  try {
21
19
  optList = JSON.parse(options);
@@ -1,18 +1,16 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; sticker: string }>({
4
+ export default defineAgentTool<{ chat_id: string; sticker: string }>({
6
5
  description: '发送 Telegram 贴纸',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  chat_id: z.string().describe('聊天 ID'),
10
8
  sticker: z.string().describe('贴纸 file_id 或 URL'),
11
9
  }),
12
- platforms: ['telegram'],
10
+ adapter: 'telegram',
13
11
  tags: ['telegram'],
14
- async execute({ endpoint_id, chat_id, sticker }: { endpoint_id: string; chat_id: string; sticker: string }) {
15
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
12
+ async execute({ chat_id, sticker }: { chat_id: string; sticker: string }, context) {
13
+ const endpoint = context.$client;
16
14
  const result = await endpoint.sendStickerMessage(Number(chat_id), sticker);
17
15
  return { success: true, message_id: result.message_id, message: '贴纸已发送' };
18
16
  },
@@ -1,18 +1,16 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; description: string }>({
4
+ export default defineAgentTool<{ chat_id: string; description: string }>({
6
5
  description: '设置 Telegram 群组描述',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  chat_id: z.string().describe('聊天 ID'),
10
8
  description: z.string().describe('群描述文字'),
11
9
  }),
12
- platforms: ['telegram'],
10
+ adapter: 'telegram',
13
11
  tags: ['telegram'],
14
- async execute({ endpoint_id, chat_id, description }: { endpoint_id: string; chat_id: string; description: string }) {
15
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
12
+ async execute({ chat_id, description }: { chat_id: string; description: string }, context) {
13
+ const endpoint = context.$client;
16
14
  const success = await endpoint.setChatDescription(Number(chat_id), description);
17
15
  return { success, message: success ? '群描述已更新' : '操作失败' };
18
16
  },
@@ -1,12 +1,10 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; can_send_messages?: boolean; can_send_photos?: boolean; can_send_videos?: boolean; can_send_polls?: boolean; can_send_other_messages?: boolean; can_add_web_page_previews?: boolean; can_change_info?: boolean; can_invite_users?: boolean; can_pin_messages?: boolean }>({
5
+ export default defineAgentTool<{ chat_id: string; can_send_messages?: boolean; can_send_photos?: boolean; can_send_videos?: boolean; can_send_polls?: boolean; can_send_other_messages?: boolean; can_add_web_page_previews?: boolean; can_change_info?: boolean; can_invite_users?: boolean; can_pin_messages?: boolean }>({
7
6
  description: '设置 Telegram 群组的默认成员权限',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  chat_id: z.string().describe('聊天 ID'),
11
9
  can_send_messages: z.boolean().optional().describe('是否可以发消息'),
12
10
  can_send_photos: z.boolean().optional().describe('是否可以发图片'),
@@ -18,11 +16,11 @@ export default defineAgentTool<{ endpoint_id: string; chat_id: string; can_send_
18
16
  can_invite_users: z.boolean().optional().describe('是否可以邀请用户'),
19
17
  can_pin_messages: z.boolean().optional().describe('是否可以置顶消息'),
20
18
  }),
21
- platforms: ['telegram'],
19
+ adapter: 'telegram',
22
20
  tags: ['telegram'],
23
21
  permissions: [platformPermit('manage_chat')],
24
- async execute({ endpoint_id, chat_id, ...perms }: { endpoint_id: string; chat_id: string; can_send_messages?: boolean; can_send_photos?: boolean; can_send_videos?: boolean; can_send_polls?: boolean; can_send_other_messages?: boolean; can_add_web_page_previews?: boolean; can_change_info?: boolean; can_invite_users?: boolean; can_pin_messages?: boolean }) {
25
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
22
+ async execute({ chat_id, ...perms }: { chat_id: string; can_send_messages?: boolean; can_send_photos?: boolean; can_send_videos?: boolean; can_send_polls?: boolean; can_send_other_messages?: boolean; can_add_web_page_previews?: boolean; can_change_info?: boolean; can_invite_users?: boolean; can_pin_messages?: boolean }, context) {
23
+ const endpoint = context.$client;
26
24
  const permissions: Record<string, boolean> = {};
27
25
  for (const [k, v] of Object.entries(perms)) {
28
26
  if (typeof v === 'boolean') permissions[k] = v;
@@ -1,20 +1,18 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getTelegramAgentDeps } from '../../src/telegram-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; chat_id: string; message_id?: string }>({
5
+ export default defineAgentTool<{ chat_id: string; message_id?: string }>({
7
6
  description: '取消置顶 Telegram 群组消息',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  chat_id: z.string().describe('聊天 ID'),
11
9
  message_id: z.string().optional().describe('消息 ID(可选,不提供则取消所有置顶)'),
12
10
  }),
13
- platforms: ['telegram'],
11
+ adapter: 'telegram',
14
12
  tags: ['telegram'],
15
13
  permissions: [platformPermit('pin_messages')],
16
- async execute({ endpoint_id, chat_id, message_id }: { endpoint_id: string; chat_id: string; message_id?: string }) {
17
- const endpoint = getTelegramAgentDeps().getEndpoint(endpoint_id);
14
+ async execute({ chat_id, message_id }: { chat_id: string; message_id?: string }, context) {
15
+ const endpoint = context.$client;
18
16
  const success = await endpoint.unpinMessage(Number(chat_id), message_id ? Number(message_id) : undefined);
19
17
  return { success, message: success ? '已取消置顶' : '操作失败' };
20
18
  },
@@ -0,0 +1,12 @@
1
+ import type { TelegramClient } from './endpoint.js';
2
+ import type { TelegramUpdate } from './protocol.js';
3
+ export type TelegramClientEventMap = Record<string, TelegramUpdate>;
4
+ declare module '@zhin.js/feature-kit' {
5
+ interface AdapterClientRegistry {
6
+ readonly telegram: {
7
+ readonly client: TelegramClient;
8
+ readonly events: TelegramClientEventMap;
9
+ };
10
+ }
11
+ }
12
+ export declare const telegramClient: import("@zhin.js/adapter").EndpointClientToken<TelegramClient, TelegramClientEventMap>;
package/lib/client.js ADDED
@@ -0,0 +1,2 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ export const telegramClient = defineEndpointClient('telegram');
package/lib/endpoint.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { EndpointContentPort, EndpointControl, EndpointInstance, EndpointSendRequest } from 'zhin.js/adapter';
2
- import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
1
+ import { Endpoint } from 'zhin.js/adapter';
2
+ import type { EndpointContentPort, EndpointControl, EndpointSendRequest } from 'zhin.js/adapter';
3
3
  import type { HttpHost } from '@zhin.js/host-http';
4
4
  import { type MessageRef } from '@zhin.js/im-contract';
5
5
  import type { CapabilityId } from 'zhin.js';
@@ -21,19 +21,57 @@ export type TelegramFetch = (url: string, init?: {
21
21
  }>;
22
22
  export interface TelegramEndpointOptions {
23
23
  readonly id: CapabilityId;
24
- readonly gateway: MessageGateway;
25
- readonly sideEvents?: SideEventGateway;
26
24
  readonly config: ResolvedTelegramConfig;
27
25
  readonly http?: HttpHost;
28
26
  readonly fetch?: TelegramFetch;
29
27
  }
28
+ export interface TelegramClientApi {
29
+ callApi<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
30
+ callApiForm<T = unknown>(method: string, form: FormData): Promise<T>;
31
+ pinMessage(chatId: number, messageId: number): Promise<boolean>;
32
+ unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
33
+ setChatDescription(chatId: number, description: string): Promise<boolean>;
34
+ setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
35
+ getChatMemberCount(chatId: number): Promise<number>;
36
+ getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
37
+ sendStickerMessage(chatId: number, sticker: string): Promise<{
38
+ message_id: number;
39
+ }>;
40
+ setChatPermissionsAll(chatId: number, permissions: Record<string, boolean | undefined>): Promise<boolean>;
41
+ createInviteLink(chatId: number): Promise<string>;
42
+ sendPoll(chatId: number, question: string, options: string[], isAnonymous?: boolean, allowsMultipleAnswers?: boolean): Promise<{
43
+ message_id: number;
44
+ }>;
45
+ }
46
+ /** Telegram Bot API client carried by message, update and lifecycle events. */
47
+ export declare class TelegramClient implements TelegramClientApi {
48
+ readonly api: TelegramClientApi;
49
+ constructor(api: TelegramClientApi);
50
+ callApi: <T = unknown>(method: string, params?: Record<string, unknown>) => Promise<T>;
51
+ callApiForm: <T = unknown>(method: string, form: FormData) => Promise<T>;
52
+ pinMessage: (chatId: number, messageId: number) => Promise<boolean>;
53
+ unpinMessage: (chatId: number, messageId?: number) => Promise<boolean>;
54
+ setChatDescription: (chatId: number, description: string) => Promise<boolean>;
55
+ setMessageReaction: (chatId: number, messageId: number, reaction: string) => Promise<boolean>;
56
+ getChatMemberCount: (chatId: number) => Promise<number>;
57
+ getChatAdmins: (chatId: number) => Promise<TelegramChatMember[]>;
58
+ sendStickerMessage: (chatId: number, sticker: string) => Promise<{
59
+ message_id: number;
60
+ }>;
61
+ setChatPermissionsAll: (chatId: number, permissions: Record<string, boolean | undefined>) => Promise<boolean>;
62
+ createInviteLink: (chatId: number) => Promise<string>;
63
+ sendPoll: (chatId: number, question: string, options: string[], anonymous?: boolean, multiple?: boolean) => Promise<{
64
+ message_id: number;
65
+ }>;
66
+ }
30
67
  /**
31
68
  * Telegram Bot API 无列表类接口(无 getMyChats/getChatMembers),
32
69
  * 仅 getChat/getChatMember 按已知 id 单查,不构成列表能力;
33
70
  * 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
34
71
  */
35
- export declare class TelegramEndpoint implements EndpointInstance {
72
+ export declare class TelegramEndpoint extends Endpoint<TelegramClient> {
36
73
  #private;
74
+ readonly client: TelegramClient;
37
75
  readonly control: EndpointControl;
38
76
  readonly content: EndpointContentPort;
39
77
  constructor(options: TelegramEndpointOptions);
package/lib/endpoint.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  /**
2
3
  * TelegramEndpoint — lifecycle, outbound, admit, Bot API helpers for agent tools.
3
4
  */
@@ -6,16 +7,48 @@ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
6
7
  import { runTelegramPollLoop } from './polling.js';
7
8
  import { normalizeTelegramChatMember } from './platform-permit.js';
8
9
  import { botApiUrl, buildWebhookUrl, formatCallbackContent, formatCallbackSegments, formatInboundContent, formatInboundSegments, formatOutboundPlan, resolveTelegramChannelType, senderDisplayName, telegramInboundConversation, } from './protocol.js';
9
- import { registerTelegramAgentEndpoint } from './telegram-agent-deps.js';
10
10
  import { registerTelegramWebhookRoutes } from './webhook.js';
11
11
  const CHAT_MEMBER_CACHE_TTL_MS = 60_000;
12
12
  const CHAT_MEMBER_CACHE_MAX = 2_000;
13
+ /** Telegram Bot API client carried by message, update and lifecycle events. */
14
+ export class TelegramClient {
15
+ api;
16
+ constructor(api) {
17
+ this.api = api;
18
+ }
19
+ callApi = (method, params = {}) => this.api.callApi(method, params);
20
+ callApiForm = (method, form) => this.api.callApiForm(method, form);
21
+ pinMessage = (chatId, messageId) => this.api.pinMessage(chatId, messageId);
22
+ unpinMessage = (chatId, messageId) => this.api.unpinMessage(chatId, messageId);
23
+ setChatDescription = (chatId, description) => this.api.setChatDescription(chatId, description);
24
+ setMessageReaction = (chatId, messageId, reaction) => this.api.setMessageReaction(chatId, messageId, reaction);
25
+ getChatMemberCount = (chatId) => this.api.getChatMemberCount(chatId);
26
+ getChatAdmins = (chatId) => this.api.getChatAdmins(chatId);
27
+ sendStickerMessage = (chatId, sticker) => this.api.sendStickerMessage(chatId, sticker);
28
+ setChatPermissionsAll = (chatId, permissions) => this.api.setChatPermissionsAll(chatId, permissions);
29
+ createInviteLink = (chatId) => this.api.createInviteLink(chatId);
30
+ sendPoll = (chatId, question, options, anonymous, multiple) => this.api.sendPoll(chatId, question, options, anonymous, multiple);
31
+ }
13
32
  /**
14
33
  * Telegram Bot API 无列表类接口(无 getMyChats/getChatMembers),
15
34
  * 仅 getChat/getChatMember 按已知 id 单查,不构成列表能力;
16
35
  * 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
17
36
  */
18
- export class TelegramEndpoint {
37
+ export class TelegramEndpoint extends Endpoint {
38
+ client = new TelegramClient({
39
+ callApi: (method, params) => this.callApi(method, params),
40
+ callApiForm: (method, form) => this.callApiForm(method, form),
41
+ pinMessage: (chatId, messageId) => this.pinMessage(chatId, messageId),
42
+ unpinMessage: (chatId, messageId) => this.unpinMessage(chatId, messageId),
43
+ setChatDescription: (chatId, description) => this.setChatDescription(chatId, description),
44
+ setMessageReaction: (chatId, messageId, reaction) => this.setMessageReaction(chatId, messageId, reaction),
45
+ getChatMemberCount: (chatId) => this.getChatMemberCount(chatId),
46
+ getChatAdmins: (chatId) => this.getChatAdmins(chatId),
47
+ sendStickerMessage: (chatId, sticker) => this.sendStickerMessage(chatId, sticker),
48
+ setChatPermissionsAll: (chatId, permissions) => this.setChatPermissionsAll(chatId, permissions),
49
+ createInviteLink: (chatId) => this.createInviteLink(chatId),
50
+ sendPoll: (chatId, question, options, anonymous, multiple) => this.sendPoll(chatId, question, options, anonymous, multiple),
51
+ });
19
52
  #logger;
20
53
  #options;
21
54
  #fetch;
@@ -24,7 +57,6 @@ export class TelegramEndpoint {
24
57
  #routeReleases = [];
25
58
  #open = false;
26
59
  #started = false;
27
- #unregisterAgent;
28
60
  #updateOffset = 0;
29
61
  #botUserId;
30
62
  #botUsername;
@@ -36,6 +68,7 @@ export class TelegramEndpoint {
36
68
  resolve: (reference, context) => this.#resolveContent(reference, context.signal),
37
69
  });
38
70
  constructor(options) {
71
+ super();
39
72
  this.#logger = getAdapterLogger('telegram', options.config.id);
40
73
  this.#options = options;
41
74
  this.#fetch = options.fetch ?? globalThis.fetch;
@@ -61,7 +94,6 @@ export class TelegramEndpoint {
61
94
  return;
62
95
  this.#started = true;
63
96
  try {
64
- this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.id, this);
65
97
  const me = await this.callApi('getMe');
66
98
  this.#botUserId = me.id;
67
99
  this.#botUsername = me.username;
@@ -128,8 +160,6 @@ export class TelegramEndpoint {
128
160
  }
129
161
  for (const release of this.#routeReleases.splice(0))
130
162
  release();
131
- this.#unregisterAgent?.();
132
- this.#unregisterAgent = undefined;
133
163
  this.#chatMemberCache.clear();
134
164
  this.#started = false;
135
165
  this.#logger.debug(formatCompact({ op: 'disconnect' }));
@@ -243,7 +273,7 @@ export class TelegramEndpoint {
243
273
  const permit = await this.#resolveGroupSenderPermit(msg);
244
274
  // 新 Runtime Message.content 为纯文本:@ 本机只能经 metadata 传递
245
275
  const mentioned = this.#isBotMentioned(msg);
246
- await this.#options.gateway.receive({
276
+ await this.emit('message.receive', {
247
277
  conversation,
248
278
  message: { conversation, id: String(msg.message_id) },
249
279
  content: formatInboundContent(msg),
@@ -336,7 +366,7 @@ export class TelegramEndpoint {
336
366
  const conversation = msg
337
367
  ? telegramInboundConversation(endpointKey, msg.chat)
338
368
  : telegramInboundConversation(endpointKey, { id: query.from.id, type: 'private' });
339
- void this.#options.gateway.receive({
369
+ void this.emit('message.receive', {
340
370
  conversation,
341
371
  message: { conversation, id: query.id },
342
372
  content: formatCallbackContent(query),
@@ -358,6 +388,18 @@ export class TelegramEndpoint {
358
388
  }
359
389
  /** Used by webhook / polling handlers. */
360
390
  handleUpdate(update) {
391
+ const eventName = update.message
392
+ ? 'message'
393
+ : update.callback_query
394
+ ? 'callback_query'
395
+ : 'update';
396
+ void this.emitPlatform(eventName, update).catch((error) => {
397
+ this.#logger.warn(formatCompact({
398
+ op: 'telegram_platform_event_failed',
399
+ event: eventName,
400
+ error: error instanceof Error ? error.message : String(error),
401
+ }));
402
+ });
361
403
  if (update.message) {
362
404
  this.admit(update.message);
363
405
  return;
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { TelegramEndpoint, type TelegramEndpointOptions, type TelegramFetch, } from './endpoint.js';
1
+ export { TelegramClient, TelegramEndpoint, type TelegramClientApi, type TelegramEndpointOptions, type TelegramFetch, } from './endpoint.js';
2
2
  export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath, resolveTelegramConfig, senderDisplayName, type ResolvedTelegramConfig, type TelegramAdapterConfig, type TelegramCallbackQuery, type TelegramChat, type TelegramChatMember, type TelegramMessage, type TelegramOutboundAction, type TelegramOutboundPlan, type TelegramOutboundUpload, type TelegramUpdate, type TelegramUser, type TelegramWireSegment, } from './protocol.js';
3
- export { getTelegramAgentDeps, registerTelegramAgentEndpoint, setTelegramAgentDeps, type TelegramAgentDeps, type TelegramAgentEndpoint, } from './telegram-agent-deps.js';
3
+ export { telegramClient, type TelegramClientEventMap } from './client.js';
4
4
  export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, telegramGroupPermitResolver, } from './platform-permit.js';
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { TelegramEndpoint, } from './endpoint.js';
1
+ export { TelegramClient, TelegramEndpoint, } from './endpoint.js';
2
2
  export { botApiUrl, formatCallbackContent, formatInboundContent, formatOutboundActions, formatOutboundPlan, normalizeWebhookPath, resolveTelegramConfig, senderDisplayName, } from './protocol.js';
3
- export { getTelegramAgentDeps, registerTelegramAgentEndpoint, setTelegramAgentDeps, } from './telegram-agent-deps.js';
3
+ export { telegramClient } from './client.js';
4
4
  export { checkTelegramPlatformPermit, normalizeTelegramChatMember, platformPermit, telegramGroupPermitResolver, } from './platform-permit.js';
package/lib/protocol.d.ts CHANGED
@@ -251,7 +251,7 @@ export declare function resolveTelegramChannelType(chatType: TelegramChat['type'
251
251
  */
252
252
  export declare function telegramInboundConversation(endpointKey: string, chat: Pick<TelegramChat, 'id' | 'type'>): ConversationRef;
253
253
  export declare function senderDisplayName(user?: TelegramUser): string;
254
- /** Build inbound text for MessageGateway.receive. */
254
+ /** Build inbound text for OutboundMessageService.receive. */
255
255
  export declare function formatInboundContent(msg: TelegramMessage): string;
256
256
  export declare function formatCallbackContent(query: TelegramCallbackQuery): string;
257
257
  /**
package/lib/protocol.js CHANGED
@@ -101,7 +101,7 @@ export function senderDisplayName(user) {
101
101
  return 'Unknown';
102
102
  return user.username || user.first_name || String(user.id);
103
103
  }
104
- /** Build inbound text for MessageGateway.receive. */
104
+ /** Build inbound text for OutboundMessageService.receive. */
105
105
  export function formatInboundContent(msg) {
106
106
  if (msg.text)
107
107
  return msg.text;
@@ -1 +1 @@
1
- export declare const telegramEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage>>>;
1
+ export declare const telegramEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-telegram",
3
- "version": "7.0.14",
3
+ "version": "8.0.1",
4
4
  "description": "Zhin.js Telegram Bot API adapter for Plugin Runtime (long-poll getUpdates)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -32,20 +32,21 @@
32
32
  "directory": "plugins/adapters/telegram"
33
33
  },
34
34
  "dependencies": {
35
- "@zhin.js/adapter": "1.1.11",
36
- "@zhin.js/core": "1.5.12",
37
- "@zhin.js/host-http": "1.0.11",
35
+ "@zhin.js/adapter": "1.2.1",
36
+ "@zhin.js/core": "1.5.14",
37
+ "@zhin.js/feature-kit": "1.0.13",
38
+ "@zhin.js/host-http": "1.0.13",
38
39
  "@zhin.js/im-contract": "1.0.4",
39
- "@zhin.js/logger": "1.0.76"
40
+ "@zhin.js/logger": "1.0.77"
40
41
  },
41
42
  "peerDependencies": {
42
43
  "zod": "^4.0.0",
43
- "@zhin.js/adapter": "1.1.11",
44
- "@zhin.js/agent": "1.1.14",
45
- "@zhin.js/command": "1.0.15",
46
- "@zhin.js/core": "1.5.12",
47
- "@zhin.js/permission": "1.0.3",
48
- "zhin.js": "6.0.12"
44
+ "@zhin.js/adapter": "1.2.1",
45
+ "@zhin.js/agent": "1.1.16",
46
+ "@zhin.js/command": "1.0.16",
47
+ "@zhin.js/core": "1.5.14",
48
+ "@zhin.js/permission": "1.0.4",
49
+ "zhin.js": "6.0.14"
49
50
  },
50
51
  "peerDependenciesMeta": {
51
52
  "@zhin.js/agent": {
@@ -66,9 +67,9 @@
66
67
  "typescript": "^6.0.3",
67
68
  "vitest": "^4.1.10",
68
69
  "zod": "^4.4.3",
69
- "@zhin.js/agent": "1.1.14",
70
- "@zhin.js/host-http": "1.0.11",
71
- "zhin.js": "6.0.12"
70
+ "@zhin.js/agent": "1.1.16",
71
+ "@zhin.js/host-http": "1.0.13",
72
+ "zhin.js": "6.0.14"
72
73
  },
73
74
  "files": [
74
75
  "adapters",
package/src/client.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ import type { TelegramClient } from './endpoint.js';
3
+ import type { TelegramUpdate } from './protocol.js';
4
+
5
+ export type TelegramClientEventMap = Record<string, TelegramUpdate>;
6
+
7
+ declare module '@zhin.js/feature-kit' {
8
+ interface AdapterClientRegistry {
9
+ readonly telegram: {
10
+ readonly client: TelegramClient;
11
+ readonly events: TelegramClientEventMap;
12
+ };
13
+ }
14
+ }
15
+
16
+ export const telegramClient = defineEndpointClient<TelegramClient, TelegramClientEventMap>('telegram');
package/src/endpoint.ts CHANGED
@@ -1,9 +1,9 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  /**
2
3
  * TelegramEndpoint — lifecycle, outbound, admit, Bot API helpers for agent tools.
3
4
  */
4
5
  import { readFile } from 'node:fs/promises';
5
- import type { EndpointContentPort, EndpointContentResolveContext, EndpointControl, EndpointInstance, EndpointSendRequest } from 'zhin.js/adapter';
6
- import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
6
+ import type { EndpointContentPort, EndpointContentResolveContext, EndpointControl, EndpointSendRequest } from 'zhin.js/adapter';
7
7
  import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
8
8
  import {
9
9
  type ConversationRef,
@@ -33,7 +33,6 @@ import {
33
33
  type TelegramOutboundUpload,
34
34
  type TelegramUpdate,
35
35
  } from './protocol.js';
36
- import { registerTelegramAgentEndpoint } from './telegram-agent-deps.js';
37
36
  import { registerTelegramWebhookRoutes } from './webhook.js';
38
37
 
39
38
  const CHAT_MEMBER_CACHE_TTL_MS = 60_000;
@@ -64,13 +63,61 @@ export type TelegramFetch = (
64
63
 
65
64
  export interface TelegramEndpointOptions {
66
65
  readonly id: CapabilityId;
67
- readonly gateway: MessageGateway;
68
- readonly sideEvents?: SideEventGateway;
69
66
  readonly config: ResolvedTelegramConfig;
70
67
  readonly http?: HttpHost;
71
68
  readonly fetch?: TelegramFetch;
72
69
  }
73
70
 
71
+ export interface TelegramClientApi {
72
+ callApi<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
73
+ callApiForm<T = unknown>(method: string, form: FormData): Promise<T>;
74
+ pinMessage(chatId: number, messageId: number): Promise<boolean>;
75
+ unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
76
+ setChatDescription(chatId: number, description: string): Promise<boolean>;
77
+ setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
78
+ getChatMemberCount(chatId: number): Promise<number>;
79
+ getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
80
+ sendStickerMessage(chatId: number, sticker: string): Promise<{ message_id: number }>;
81
+ setChatPermissionsAll(chatId: number, permissions: Record<string, boolean | undefined>): Promise<boolean>;
82
+ createInviteLink(chatId: number): Promise<string>;
83
+ sendPoll(
84
+ chatId: number,
85
+ question: string,
86
+ options: string[],
87
+ isAnonymous?: boolean,
88
+ allowsMultipleAnswers?: boolean,
89
+ ): Promise<{ message_id: number }>;
90
+ }
91
+
92
+ /** Telegram Bot API client carried by message, update and lifecycle events. */
93
+ export class TelegramClient implements TelegramClientApi {
94
+ constructor(readonly api: TelegramClientApi) {}
95
+ callApi = <T = unknown>(method: string, params: Record<string, unknown> = {}) =>
96
+ this.api.callApi<T>(method, params);
97
+ callApiForm = <T = unknown>(method: string, form: FormData) =>
98
+ this.api.callApiForm<T>(method, form);
99
+ pinMessage = (chatId: number, messageId: number) => this.api.pinMessage(chatId, messageId);
100
+ unpinMessage = (chatId: number, messageId?: number) => this.api.unpinMessage(chatId, messageId);
101
+ setChatDescription = (chatId: number, description: string) =>
102
+ this.api.setChatDescription(chatId, description);
103
+ setMessageReaction = (chatId: number, messageId: number, reaction: string) =>
104
+ this.api.setMessageReaction(chatId, messageId, reaction);
105
+ getChatMemberCount = (chatId: number) => this.api.getChatMemberCount(chatId);
106
+ getChatAdmins = (chatId: number) => this.api.getChatAdmins(chatId);
107
+ sendStickerMessage = (chatId: number, sticker: string) =>
108
+ this.api.sendStickerMessage(chatId, sticker);
109
+ setChatPermissionsAll = (chatId: number, permissions: Record<string, boolean | undefined>) =>
110
+ this.api.setChatPermissionsAll(chatId, permissions);
111
+ createInviteLink = (chatId: number) => this.api.createInviteLink(chatId);
112
+ sendPoll = (
113
+ chatId: number,
114
+ question: string,
115
+ options: string[],
116
+ anonymous?: boolean,
117
+ multiple?: boolean,
118
+ ) => this.api.sendPoll(chatId, question, options, anonymous, multiple);
119
+ }
120
+
74
121
  interface TelegramApiOk<T> {
75
122
  readonly ok: true;
76
123
  readonly result: T;
@@ -87,7 +134,24 @@ interface TelegramApiErr {
87
134
  * 仅 getChat/getChatMember 按已知 id 单查,不构成列表能力;
88
135
  * 因此本 endpoint 不暴露 EndpointManagement(Console 社交面 RPC 对该平台保持未接线)。
89
136
  */
90
- export class TelegramEndpoint implements EndpointInstance {
137
+ export class TelegramEndpoint extends Endpoint<TelegramClient> {
138
+ readonly client = new TelegramClient({
139
+ callApi: (method, params) => this.callApi(method, params),
140
+ callApiForm: (method, form) => this.callApiForm(method, form),
141
+ pinMessage: (chatId, messageId) => this.pinMessage(chatId, messageId),
142
+ unpinMessage: (chatId, messageId) => this.unpinMessage(chatId, messageId),
143
+ setChatDescription: (chatId, description) => this.setChatDescription(chatId, description),
144
+ setMessageReaction: (chatId, messageId, reaction) =>
145
+ this.setMessageReaction(chatId, messageId, reaction),
146
+ getChatMemberCount: (chatId) => this.getChatMemberCount(chatId),
147
+ getChatAdmins: (chatId) => this.getChatAdmins(chatId),
148
+ sendStickerMessage: (chatId, sticker) => this.sendStickerMessage(chatId, sticker),
149
+ setChatPermissionsAll: (chatId, permissions) =>
150
+ this.setChatPermissionsAll(chatId, permissions),
151
+ createInviteLink: (chatId) => this.createInviteLink(chatId),
152
+ sendPoll: (chatId, question, options, anonymous, multiple) =>
153
+ this.sendPoll(chatId, question, options, anonymous, multiple),
154
+ });
91
155
  readonly #logger!: ReturnType<typeof getAdapterLogger>;
92
156
 
93
157
  readonly #options: TelegramEndpointOptions;
@@ -97,7 +161,6 @@ export class TelegramEndpoint implements EndpointInstance {
97
161
  #routeReleases: HttpRouteRegistration[] = [];
98
162
  #open = false;
99
163
  #started = false;
100
- #unregisterAgent?: () => void;
101
164
  #updateOffset = 0;
102
165
  #botUserId?: number;
103
166
  #botUsername?: string;
@@ -110,6 +173,7 @@ export class TelegramEndpoint implements EndpointInstance {
110
173
  });
111
174
 
112
175
  constructor(options: TelegramEndpointOptions) {
176
+ super();
113
177
  this.#logger = getAdapterLogger('telegram', options.config.id);
114
178
  this.#options = options;
115
179
  this.#fetch = options.fetch ?? globalThis.fetch;
@@ -140,7 +204,6 @@ export class TelegramEndpoint implements EndpointInstance {
140
204
  if (this.#started) return;
141
205
  this.#started = true;
142
206
  try {
143
- this.#unregisterAgent = registerTelegramAgentEndpoint(this.#options.config.id, this);
144
207
  const me = await this.callApi<{ id?: number; username?: string; first_name?: string }>('getMe');
145
208
  this.#botUserId = me.id;
146
209
  this.#botUsername = me.username;
@@ -209,8 +272,6 @@ export class TelegramEndpoint implements EndpointInstance {
209
272
  /* poll loop exit */
210
273
  }
211
274
  for (const release of this.#routeReleases.splice(0)) release();
212
- this.#unregisterAgent?.();
213
- this.#unregisterAgent = undefined;
214
275
  this.#chatMemberCache.clear();
215
276
  this.#started = false;
216
277
  this.#logger.debug(formatCompact({ op: 'disconnect' }));
@@ -330,7 +391,7 @@ export class TelegramEndpoint implements EndpointInstance {
330
391
  const permit = await this.#resolveGroupSenderPermit(msg);
331
392
  // 新 Runtime Message.content 为纯文本:@ 本机只能经 metadata 传递
332
393
  const mentioned = this.#isBotMentioned(msg);
333
- await this.#options.gateway.receive({
394
+ await this.emit('message.receive', {
334
395
  conversation,
335
396
  message: { conversation, id: String(msg.message_id) },
336
397
  content: formatInboundContent(msg),
@@ -417,7 +478,7 @@ export class TelegramEndpoint implements EndpointInstance {
417
478
  const conversation = msg
418
479
  ? telegramInboundConversation(endpointKey, msg.chat)
419
480
  : telegramInboundConversation(endpointKey, { id: query.from.id, type: 'private' });
420
- void this.#options.gateway.receive({
481
+ void this.emit('message.receive', {
421
482
  conversation,
422
483
  message: { conversation, id: query.id },
423
484
  content: formatCallbackContent(query),
@@ -440,6 +501,18 @@ export class TelegramEndpoint implements EndpointInstance {
440
501
 
441
502
  /** Used by webhook / polling handlers. */
442
503
  handleUpdate(update: TelegramUpdate): void {
504
+ const eventName = update.message
505
+ ? 'message'
506
+ : update.callback_query
507
+ ? 'callback_query'
508
+ : 'update';
509
+ void this.emitPlatform(eventName, update).catch((error) => {
510
+ this.#logger.warn(formatCompact({
511
+ op: 'telegram_platform_event_failed',
512
+ event: eventName,
513
+ error: error instanceof Error ? error.message : String(error),
514
+ }));
515
+ });
443
516
  if (update.message) {
444
517
  this.admit(update.message);
445
518
  return;
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export {
2
+ TelegramClient,
2
3
  TelegramEndpoint,
4
+ type TelegramClientApi,
3
5
  type TelegramEndpointOptions,
4
6
  type TelegramFetch,
5
7
  } from './endpoint.js';
@@ -27,13 +29,7 @@ export {
27
29
  type TelegramWireSegment,
28
30
  } from './protocol.js';
29
31
 
30
- export {
31
- getTelegramAgentDeps,
32
- registerTelegramAgentEndpoint,
33
- setTelegramAgentDeps,
34
- type TelegramAgentDeps,
35
- type TelegramAgentEndpoint,
36
- } from './telegram-agent-deps.js';
32
+ export { telegramClient, type TelegramClientEventMap } from './client.js';
37
33
 
38
34
  export {
39
35
  checkTelegramPlatformPermit,
package/src/protocol.ts CHANGED
@@ -358,7 +358,7 @@ export function senderDisplayName(user?: TelegramUser): string {
358
358
  return user.username || user.first_name || String(user.id);
359
359
  }
360
360
 
361
- /** Build inbound text for MessageGateway.receive. */
361
+ /** Build inbound text for OutboundMessageService.receive. */
362
362
  export function formatInboundContent(msg: TelegramMessage): string {
363
363
  if (msg.text) return msg.text;
364
364
  if (msg.caption) return msg.caption;
@@ -1,28 +0,0 @@
1
- /**
2
- * Agent tool deps for telegram.
3
- * Endpoints register themselves on start; tools look up by config name / endpoint id.
4
- */
5
- import type { TelegramChatMember } from './protocol.js';
6
- export interface TelegramAgentEndpoint {
7
- pinMessage(chatId: number, messageId: number): Promise<boolean>;
8
- unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
9
- setChatDescription(chatId: number, description: string): Promise<boolean>;
10
- setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
11
- getChatMemberCount(chatId: number): Promise<number>;
12
- getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
13
- sendStickerMessage(chatId: number, sticker: string): Promise<{
14
- message_id: number;
15
- }>;
16
- setChatPermissionsAll(chatId: number, permissions: Record<string, boolean | undefined>): Promise<boolean>;
17
- createInviteLink(chatId: number): Promise<string>;
18
- sendPoll(chatId: number, question: string, options: string[], isAnonymous?: boolean, allowsMultipleAnswers?: boolean): Promise<{
19
- message_id: number;
20
- }>;
21
- }
22
- export interface TelegramAgentDeps {
23
- getEndpoint: (endpointKey: string) => TelegramAgentEndpoint;
24
- }
25
- export declare function registerTelegramAgentEndpoint(endpointKey: string, endpoint: TelegramAgentEndpoint): () => void;
26
- /** Optional override used by tests / transitional callers. Pass `null` to clear. */
27
- export declare function setTelegramAgentDeps(deps: TelegramAgentDeps | null): void;
28
- export declare function getTelegramAgentDeps(): TelegramAgentDeps;
@@ -1,30 +0,0 @@
1
- /**
2
- * Agent tool deps for telegram.
3
- * Endpoints register themselves on start; tools look up by config name / endpoint id.
4
- */
5
- const endpoints = new Map();
6
- let override = null;
7
- export function registerTelegramAgentEndpoint(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 setTelegramAgentDeps(deps) {
17
- override = deps;
18
- }
19
- export function getTelegramAgentDeps() {
20
- if (override)
21
- return override;
22
- return {
23
- getEndpoint(endpointKey) {
24
- const registered = endpoints.get(endpointKey);
25
- if (!registered)
26
- throw new Error(`Endpoint ${endpointKey} 不存在`);
27
- return registered;
28
- },
29
- };
30
- }
@@ -1,63 +0,0 @@
1
- /**
2
- * Agent tool deps for telegram.
3
- * Endpoints register themselves on start; tools look up by config name / endpoint id.
4
- */
5
-
6
- import type { TelegramChatMember } from './protocol.js';
7
-
8
- export interface TelegramAgentEndpoint {
9
- pinMessage(chatId: number, messageId: number): Promise<boolean>;
10
- unpinMessage(chatId: number, messageId?: number): Promise<boolean>;
11
- setChatDescription(chatId: number, description: string): Promise<boolean>;
12
- setMessageReaction(chatId: number, messageId: number, reaction: string): Promise<boolean>;
13
- getChatMemberCount(chatId: number): Promise<number>;
14
- getChatAdmins(chatId: number): Promise<TelegramChatMember[]>;
15
- sendStickerMessage(chatId: number, sticker: string): Promise<{ message_id: number }>;
16
- setChatPermissionsAll(
17
- chatId: number,
18
- permissions: Record<string, boolean | undefined>,
19
- ): Promise<boolean>;
20
- createInviteLink(chatId: number): Promise<string>;
21
- sendPoll(
22
- chatId: number,
23
- question: string,
24
- options: string[],
25
- isAnonymous?: boolean,
26
- allowsMultipleAnswers?: boolean,
27
- ): Promise<{ message_id: number }>;
28
- }
29
-
30
- export interface TelegramAgentDeps {
31
- getEndpoint: (endpointKey: string) => TelegramAgentEndpoint;
32
- }
33
-
34
- const endpoints = new Map<string, TelegramAgentEndpoint>();
35
- let override: TelegramAgentDeps | null = null;
36
-
37
- export function registerTelegramAgentEndpoint(
38
- endpointKey: string,
39
- endpoint: TelegramAgentEndpoint,
40
- ): () => void {
41
- endpoints.set(endpointKey, endpoint);
42
- return () => {
43
- if (endpoints.get(endpointKey) === endpoint) {
44
- endpoints.delete(endpointKey);
45
- }
46
- };
47
- }
48
-
49
- /** Optional override used by tests / transitional callers. Pass `null` to clear. */
50
- export function setTelegramAgentDeps(deps: TelegramAgentDeps | null): void {
51
- override = deps;
52
- }
53
-
54
- export function getTelegramAgentDeps(): TelegramAgentDeps {
55
- if (override) return override;
56
- return {
57
- getEndpoint(endpointKey: string): TelegramAgentEndpoint {
58
- const registered = endpoints.get(endpointKey);
59
- if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
60
- return registered;
61
- },
62
- };
63
- }