@zhin.js/adapter-lark 1.1.15 → 1.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/agents/lark/messages.js +57 -0
  3. package/agents/lark/messages.ts +57 -0
  4. package/agents/lark/skills/lark/tools/create_chat/index.js +2 -1
  5. package/agents/lark/skills/lark/tools/create_chat/index.ts +2 -1
  6. package/agents/lark/skills/lark/tools/upload_file/index.js +4 -1
  7. package/agents/lark/skills/lark/tools/upload_file/index.ts +3 -1
  8. package/agents/lark/skills/lark-group-admin/tools/add_members/index.js +2 -1
  9. package/agents/lark/skills/lark-group-admin/tools/add_members/index.ts +2 -1
  10. package/agents/lark/skills/lark-group-admin/tools/dissolve_chat/index.js +2 -1
  11. package/agents/lark/skills/lark-group-admin/tools/dissolve_chat/index.ts +2 -1
  12. package/agents/lark/skills/lark-group-admin/tools/remove_managers/index.js +2 -1
  13. package/agents/lark/skills/lark-group-admin/tools/remove_managers/index.ts +2 -1
  14. package/agents/lark/skills/lark-group-admin/tools/set_managers/index.js +2 -1
  15. package/agents/lark/skills/lark-group-admin/tools/set_managers/index.ts +2 -1
  16. package/agents/lark/skills/lark-group-admin/tools/update_chat/index.js +2 -1
  17. package/agents/lark/skills/lark-group-admin/tools/update_chat/index.ts +2 -1
  18. package/commands/lark/endpoint/definition.js +4 -4
  19. package/commands/lark/endpoint/definition.ts +4 -4
  20. package/lib/cards.d.ts +2 -1
  21. package/lib/cards.js +3 -2
  22. package/lib/endpoint.d.ts +1 -1
  23. package/lib/endpoint.js +2 -2
  24. package/lib/i18n.d.ts +1 -0
  25. package/lib/i18n.js +6 -0
  26. package/lib/protocol.d.ts +2 -1
  27. package/lib/protocol.js +2 -2
  28. package/package.json +17 -17
  29. package/schema.json +53 -8
  30. package/src/cards.ts +4 -2
  31. package/src/endpoint.ts +2 -2
  32. package/src/i18n.ts +7 -0
  33. package/src/protocol.ts +3 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @zhin.js/adapter-lark
2
2
 
3
+ ## 1.1.16
4
+
5
+ ### Patch Changes
6
+
7
+ - 53bc6a0: 适配器配置标签、端点命令和工具反馈支持中英文;复用当前操作语言,保持协议值、用户内容、身份、权限与发送链路不变。Sandbox 展示使用项目语言,QQ 绑定与交互状态保留完整会话身份。
8
+ - dcd4982: Upgrade runtime dependencies to clear security advisories: `undici` (6.29.1 / 8.12.2+), `axios` 1.20.0, and `@modelcontextprotocol/sdk` 1.32.0+ (bringing patched `hono`, `body-parser`, `proxy-addr`, `follow-redirects` and `ip-address` through the lockfile).
9
+ - Updated dependencies [334e92d]
10
+ - Updated dependencies [f3b7c9f]
11
+ - Updated dependencies [658a5fb]
12
+ - Updated dependencies [144a17b]
13
+ - Updated dependencies [18296cf]
14
+ - Updated dependencies [08e64de]
15
+ - Updated dependencies [9cade30]
16
+ - Updated dependencies [53bc6a0]
17
+ - Updated dependencies [7595136]
18
+ - Updated dependencies [66b6404]
19
+ - Updated dependencies [adb4af2]
20
+ - Updated dependencies [69f9ef6]
21
+ - Updated dependencies [17d1301]
22
+ - @zhin.js/adapter@1.1.23
23
+ - @zhin.js/host-http@1.1.10
24
+ - @zhin.js/core@1.1.51
25
+ - @zhin.js/tool@1.1.10
26
+ - @zhin.js/skill@1.1.10
27
+ - @zhin.js/im-contract@1.1.7
28
+ - @zhin.js/agent-feature@1.1.10
29
+ - @zhin.js/feature-kit@1.1.9
30
+
3
31
  ## 1.1.15
4
32
 
5
33
  ### Patch Changes
@@ -0,0 +1,57 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { createMessages } from 'zhin.js/i18n';
3
+ export const messages = createMessages({
4
+ fileUploadFailed: { 'zh-CN': '文件上传失败,未返回文件标识', en: 'File upload failed; no file key was returned.' },
5
+ "createFailed": {
6
+ "zh-CN": "创建失败",
7
+ "en": "Creation failed"
8
+ },
9
+ "chatCreated": {
10
+ "zh-CN": "群聊创建成功: {p0}",
11
+ "en": "Group chat created: {p0}"
12
+ },
13
+ "fileUploaded": {
14
+ "zh-CN": "文件已上传,file_key: {p0}",
15
+ "en": "File uploaded, file_key: {p0}"
16
+ },
17
+ "addFailed": {
18
+ "zh-CN": "添加失败",
19
+ "en": "Could not add members"
20
+ },
21
+ "membersAdded": {
22
+ "zh-CN": "成员添加成功",
23
+ "en": "Members added"
24
+ },
25
+ "dissolveFailed": {
26
+ "zh-CN": "解散失败",
27
+ "en": "Could not dissolve the group chat"
28
+ },
29
+ "chatDissolved": {
30
+ "zh-CN": "群聊已解散",
31
+ "en": "Group chat dissolved"
32
+ },
33
+ "removeFailed": {
34
+ "zh-CN": "移除失败",
35
+ "en": "Removal failed"
36
+ },
37
+ "managersRemoved": {
38
+ "zh-CN": "管理员移除成功",
39
+ "en": "Administrators removed"
40
+ },
41
+ "setFailed": {
42
+ "zh-CN": "设置失败",
43
+ "en": "Update failed"
44
+ },
45
+ "managersSet": {
46
+ "zh-CN": "管理员设置成功",
47
+ "en": "Administrators set"
48
+ },
49
+ "updateFailed": {
50
+ "zh-CN": "更新失败",
51
+ "en": "Update failed"
52
+ },
53
+ "chatInfoUpdated": {
54
+ "zh-CN": "群信息更新成功",
55
+ "en": "Group information updated"
56
+ }
57
+ });
@@ -0,0 +1,57 @@
1
+ import { createMessages } from 'zhin.js/i18n';
2
+
3
+ export const messages = createMessages({
4
+ fileUploadFailed: { 'zh-CN': '文件上传失败,未返回文件标识', en: 'File upload failed; no file key was returned.' },
5
+ "createFailed": {
6
+ "zh-CN": "创建失败",
7
+ "en": "Creation failed"
8
+ },
9
+ "chatCreated": {
10
+ "zh-CN": "群聊创建成功: {p0}",
11
+ "en": "Group chat created: {p0}"
12
+ },
13
+ "fileUploaded": {
14
+ "zh-CN": "文件已上传,file_key: {p0}",
15
+ "en": "File uploaded, file_key: {p0}"
16
+ },
17
+ "addFailed": {
18
+ "zh-CN": "添加失败",
19
+ "en": "Could not add members"
20
+ },
21
+ "membersAdded": {
22
+ "zh-CN": "成员添加成功",
23
+ "en": "Members added"
24
+ },
25
+ "dissolveFailed": {
26
+ "zh-CN": "解散失败",
27
+ "en": "Could not dissolve the group chat"
28
+ },
29
+ "chatDissolved": {
30
+ "zh-CN": "群聊已解散",
31
+ "en": "Group chat dissolved"
32
+ },
33
+ "removeFailed": {
34
+ "zh-CN": "移除失败",
35
+ "en": "Removal failed"
36
+ },
37
+ "managersRemoved": {
38
+ "zh-CN": "管理员移除成功",
39
+ "en": "Administrators removed"
40
+ },
41
+ "setFailed": {
42
+ "zh-CN": "设置失败",
43
+ "en": "Update failed"
44
+ },
45
+ "managersSet": {
46
+ "zh-CN": "管理员设置成功",
47
+ "en": "Administrators set"
48
+ },
49
+ "updateFailed": {
50
+ "zh-CN": "更新失败",
51
+ "en": "Update failed"
52
+ },
53
+ "chatInfoUpdated": {
54
+ "zh-CN": "群信息更新成功",
55
+ "en": "Group information updated"
56
+ }
57
+ });
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  export default defineAgentTool({
@@ -13,6 +14,6 @@ export default defineAgentTool({
13
14
  async execute({ name, members, owner }, context) {
14
15
  const endpoint = context.$client;
15
16
  const chatId = await endpoint.createChat(name, members.split(','), owner);
16
- return { success: !!chatId, chat_id: chatId, message: chatId ? `群聊创建成功: ${chatId}` : '创建失败' };
17
+ return { success: !!chatId, chat_id: chatId, message: chatId ? t(context.locale, 'chatCreated', { p0: chatId }) : t(context.locale, 'createFailed') };
17
18
  },
18
19
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
  export default defineAgentTool<{ name: string; members: string; owner?: string }>({
@@ -12,7 +13,7 @@ export default defineAgentTool<{ name: string; members: string; owner?: string }
12
13
  async execute({ name, members, owner }: { name: string; members: string; owner?: string }, context) {
13
14
  const endpoint = context.$client;
14
15
  const chatId = await endpoint.createChat(name, members.split(','), owner);
15
- return { success: !!chatId, chat_id: chatId, message: chatId ? `群聊创建成功: ${chatId}` : '创建失败' };
16
+ return { success: !!chatId, chat_id: chatId, message: chatId ? t(context.locale, 'chatCreated', { p0: chatId }) : t(context.locale, 'createFailed') };
16
17
  },
17
18
  });
18
19
 
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  export default defineAgentTool({
@@ -12,6 +13,8 @@ export default defineAgentTool({
12
13
  async execute({ file_path, file_type }, context) {
13
14
  const endpoint = context.$client;
14
15
  const result = await endpoint.uploadFile(file_path, file_type);
15
- return { success: true, file_key: result, message: `文件已上传,file_key: ${result}` };
16
+ if (result === null)
17
+ return { success: false, file_key: null, message: t(context.locale, 'fileUploadFailed') };
18
+ return { success: true, file_key: result, message: t(context.locale, 'fileUploaded', { p0: result }) };
16
19
  },
17
20
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
 
@@ -18,6 +19,7 @@ export default defineAgentTool<{
18
19
  }, context) {
19
20
  const endpoint = context.$client;
20
21
  const result = await endpoint.uploadFile(file_path, file_type);
21
- return { success: true, file_key: result, message: `文件已上传,file_key: ${result}` };
22
+ if (result === null) return { success: false, file_key: null, message: t(context.locale, 'fileUploadFailed') };
23
+ return { success: true, file_key: result, message: t(context.locale, 'fileUploaded', { p0: result }) };
22
24
  },
23
25
  });
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { platformPermission } from '@zhin.js/permission';
@@ -15,6 +16,6 @@ export default defineAgentTool({
15
16
  async execute({ chat_id, user_ids }, context) {
16
17
  const endpoint = context.$client;
17
18
  const success = await endpoint.addChatMembers(chat_id, user_ids.split(','));
18
- return { success, message: success ? '成员添加成功' : '添加失败' };
19
+ return { success, message: success ? t(context.locale, 'membersAdded') : t(context.locale, 'addFailed') };
19
20
  },
20
21
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
  import { platformPermission } from '@zhin.js/permission';
@@ -15,6 +16,6 @@ export default defineAgentTool<{ chat_id: string; user_ids: string }>({
15
16
  async execute({ chat_id, user_ids }: { chat_id: string; user_ids: string }, context) {
16
17
  const endpoint = context.$client;
17
18
  const success = await endpoint.addChatMembers(chat_id, user_ids.split(','));
18
- return { success, message: success ? '成员添加成功' : '添加失败' };
19
+ return { success, message: success ? t(context.locale, 'membersAdded') : t(context.locale, 'addFailed') };
19
20
  },
20
21
  });
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  export default defineAgentTool({
@@ -12,6 +13,6 @@ export default defineAgentTool({
12
13
  async execute({ chat_id }, context) {
13
14
  const endpoint = context.$client;
14
15
  const success = await endpoint.dissolveChat(chat_id);
15
- return { success, message: success ? '群聊已解散' : '解散失败' };
16
+ return { success, message: success ? t(context.locale, 'chatDissolved') : t(context.locale, 'dissolveFailed') };
16
17
  },
17
18
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
  export default defineAgentTool<{ chat_id: string }>({
@@ -11,7 +12,7 @@ export default defineAgentTool<{ chat_id: string }>({
11
12
  async execute({ chat_id }: { chat_id: string }, context) {
12
13
  const endpoint = context.$client;
13
14
  const success = await endpoint.dissolveChat(chat_id);
14
- return { success, message: success ? '群聊已解散' : '解散失败' };
15
+ return { success, message: success ? t(context.locale, 'chatDissolved') : t(context.locale, 'dissolveFailed') };
15
16
  },
16
17
  });
17
18
 
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { platformPermission } from '@zhin.js/permission';
@@ -15,6 +16,6 @@ export default defineAgentTool({
15
16
  async execute({ chat_id, user_ids }, context) {
16
17
  const endpoint = context.$client;
17
18
  const success = await endpoint.removeChatManagers(chat_id, user_ids.split(','));
18
- return { success, message: success ? '管理员移除成功' : '移除失败' };
19
+ return { success, message: success ? t(context.locale, 'managersRemoved') : t(context.locale, 'removeFailed') };
19
20
  },
20
21
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
  import { platformPermission } from '@zhin.js/permission';
@@ -15,6 +16,6 @@ export default defineAgentTool<{ chat_id: string; user_ids: string }>({
15
16
  async execute({ chat_id, user_ids }: { chat_id: string; user_ids: string }, context) {
16
17
  const endpoint = context.$client;
17
18
  const success = await endpoint.removeChatManagers(chat_id, user_ids.split(','));
18
- return { success, message: success ? '管理员移除成功' : '移除失败' };
19
+ return { success, message: success ? t(context.locale, 'managersRemoved') : t(context.locale, 'removeFailed') };
19
20
  },
20
21
  });
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { platformPermission } from '@zhin.js/permission';
@@ -15,6 +16,6 @@ export default defineAgentTool({
15
16
  async execute({ chat_id, user_ids }, context) {
16
17
  const endpoint = context.$client;
17
18
  const success = await endpoint.setChatManagers(chat_id, user_ids.split(','));
18
- return { success, message: success ? '管理员设置成功' : '设置失败' };
19
+ return { success, message: success ? t(context.locale, 'managersSet') : t(context.locale, 'setFailed') };
19
20
  },
20
21
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
  import { platformPermission } from '@zhin.js/permission';
@@ -15,6 +16,6 @@ export default defineAgentTool<{ chat_id: string; user_ids: string }>({
15
16
  async execute({ chat_id, user_ids }: { chat_id: string; user_ids: string }, context) {
16
17
  const endpoint = context.$client;
17
18
  const success = await endpoint.setChatManagers(chat_id, user_ids.split(','));
18
- return { success, message: success ? '管理员设置成功' : '设置失败' };
19
+ return { success, message: success ? t(context.locale, 'managersSet') : t(context.locale, 'setFailed') };
19
20
  },
20
21
  });
@@ -1,4 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { messages as t } from "../../../../messages.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  import { platformPermission } from '@zhin.js/permission';
@@ -16,6 +17,6 @@ export default defineAgentTool({
16
17
  async execute({ chat_id, name, description }, context) {
17
18
  const endpoint = context.$client;
18
19
  const success = await endpoint.updateChatInfo(chat_id, { name, description });
19
- return { success, message: success ? '群信息更新成功' : '更新失败' };
20
+ return { success, message: success ? t(context.locale, 'chatInfoUpdated') : t(context.locale, 'updateFailed') };
20
21
  },
21
22
  });
@@ -1,3 +1,4 @@
1
+ import { messages as t } from "../../../../messages.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
  import { platformPermission } from '@zhin.js/permission';
@@ -16,6 +17,6 @@ export default defineAgentTool<{ chat_id: string; name?: string; description?: s
16
17
  async execute({ chat_id, name, description }: { chat_id: string; name?: string; description?: string }, context) {
17
18
  const endpoint = context.$client;
18
19
  const success = await endpoint.updateChatInfo(chat_id, { name, description });
19
- return { success, message: success ? '群信息更新成功' : '更新失败' };
20
+ return { success, message: success ? t(context.locale, 'chatInfoUpdated') : t(context.locale, 'updateFailed') };
20
21
  },
21
22
  });
@@ -10,10 +10,10 @@ export const larkEndpointCommands = createEndpointCommands({
10
10
  adapterKey: 'lark',
11
11
  adapterDisplayName: 'Lark',
12
12
  fields: [
13
- { key: 'appId', required: true, env: true, description: '飞书 App ID' },
14
- { key: 'appSecret', required: true, env: true, description: '飞书 App Secret' },
15
- { key: 'encryptKey', env: true, description: '事件加密 key' },
16
- { key: 'verificationToken', env: true, description: '事件验证 token' },
13
+ { key: 'appId', required: true, env: true, description: '飞书 App ID', descriptionI18n: { en: "Lark app ID" } },
14
+ { key: 'appSecret', required: true, env: true, description: '飞书 App Secret', descriptionI18n: { en: "Lark app secret" } },
15
+ { key: 'encryptKey', env: true, description: '事件加密 key', descriptionI18n: { en: "Event encryption key" } },
16
+ { key: 'verificationToken', env: true, description: '事件验证 token', descriptionI18n: { en: "Event verification token" } },
17
17
  ],
18
18
  running: (use) => use(larkRuntimeStateToken).endpoints.values(),
19
19
  describeEntry: (entry) => `appId: ${String(entry.appId)}`,
@@ -10,10 +10,10 @@ export const larkEndpointCommands = createEndpointCommands({
10
10
  adapterKey: 'lark',
11
11
  adapterDisplayName: 'Lark',
12
12
  fields: [
13
- { key: 'appId', required: true, env: true, description: '飞书 App ID' },
14
- { key: 'appSecret', required: true, env: true, description: '飞书 App Secret' },
15
- { key: 'encryptKey', env: true, description: '事件加密 key' },
16
- { key: 'verificationToken', env: true, description: '事件验证 token' },
13
+ { key: 'appId', required: true, env: true, description: '飞书 App ID', descriptionI18n: { en: "Lark app ID" } },
14
+ { key: 'appSecret', required: true, env: true, description: '飞书 App Secret', descriptionI18n: { en: "Lark app secret" } },
15
+ { key: 'encryptKey', env: true, description: '事件加密 key', descriptionI18n: { en: "Event encryption key" } },
16
+ { key: 'verificationToken', env: true, description: '事件验证 token', descriptionI18n: { en: "Event verification token" } },
17
17
  ],
18
18
  running: (use) => use(larkRuntimeStateToken).endpoints.values(),
19
19
  describeEntry: (entry) => `appId: ${String(entry.appId)}`,
package/lib/cards.d.ts CHANGED
@@ -1,6 +1,7 @@
1
+ import type { Locale } from 'zhin.js/i18n';
1
2
  import type { LarkSendBody, LarkWireSegment } from './protocol.js';
2
3
  /** Feishu JSON card v1: ordered native rich text, link and button components. */
3
- export declare function formatLarkCard(items: Array<string | LarkWireSegment>): LarkSendBody;
4
+ export declare function formatLarkCard(items: Array<string | LarkWireSegment>, locale?: Locale): LarkSendBody;
4
5
  export interface LarkCardAction {
5
6
  readonly token?: string;
6
7
  readonly context?: {
package/lib/cards.js CHANGED
@@ -1,6 +1,7 @@
1
+ import { messages as t } from './i18n.js';
1
2
  import { EndpointDeliveryError } from '@zhin.js/im-contract';
2
3
  /** Feishu JSON card v1: ordered native rich text, link and button components. */
3
- export function formatLarkCard(items) {
4
+ export function formatLarkCard(items, locale) {
4
5
  const elements = [];
5
6
  let replyTo;
6
7
  for (const item of items) {
@@ -33,7 +34,7 @@ export function formatLarkCard(items) {
33
34
  elements.push({ tag: 'div', text: { tag: 'plain_text', content: String(data.title ?? url) } });
34
35
  if (data.description)
35
36
  elements.push({ tag: 'div', text: { tag: 'plain_text', content: String(data.description) } });
36
- elements.push({ tag: 'action', actions: [{ tag: 'button', text: { tag: 'plain_text', content: '打开链接' }, url }] });
37
+ elements.push({ tag: 'action', actions: [{ tag: 'button', text: { tag: 'plain_text', content: t(locale, 'openLink') }, url }] });
37
38
  break;
38
39
  }
39
40
  case 'keyboard': {
package/lib/endpoint.d.ts CHANGED
@@ -79,7 +79,7 @@ export declare class LarkEndpoint extends Endpoint<LarkClient> {
79
79
  open(): void;
80
80
  close(): void;
81
81
  stop(): Promise<void>;
82
- send({ conversation, payload }: EndpointSendRequest): Promise<string>;
82
+ send({ conversation, payload, locale }: EndpointSendRequest): Promise<string>;
83
83
  recallMessage(messageId: string): Promise<void>;
84
84
  /** Upload must succeed before issuing a message; dropped media is never confirmed. */
85
85
  uploadImage(media: Parameters<typeof resolveMediaBinary>[0]): Promise<string>;
package/lib/endpoint.js CHANGED
@@ -189,10 +189,10 @@ export class LarkEndpoint extends Endpoint {
189
189
  this.#started = false;
190
190
  this.#logger.debug(formatCompact({ op: 'disconnect' }));
191
191
  }
192
- async send({ conversation, payload }) {
192
+ async send({ conversation, payload, locale }) {
193
193
  try {
194
194
  const materialized = await this.#materializeOutboundMedia(payload);
195
- const content = formatOutboundBody(materialized);
195
+ const content = formatOutboundBody(materialized, locale);
196
196
  const data = await this.#request(content.replyTo
197
197
  ? `/im/v1/messages/${encodeURIComponent(content.replyTo)}/reply`
198
198
  : '/im/v1/messages', {
package/lib/i18n.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const messages: (locale: import("zhin.js").Locale | undefined, key: "openLink" | "link" | "message", values?: import("zhin.js").MessageValues) => string;
package/lib/i18n.js ADDED
@@ -0,0 +1,6 @@
1
+ import { createMessages } from 'zhin.js/i18n';
2
+ export const messages = createMessages({
3
+ openLink: { 'zh-CN': '打开链接', en: 'Open link' },
4
+ link: { 'zh-CN': '链接', en: 'Link' },
5
+ message: { 'zh-CN': '消息', en: 'Message' }
6
+ });
package/lib/protocol.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Locale } from 'zhin.js/i18n';
1
2
  import type { IncomingMessage } from 'node:http';
2
3
  import { type ConversationRef } from '@zhin.js/im-contract';
3
4
  /** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
@@ -115,7 +116,7 @@ export declare function verifyToken(token: string, expected: string): boolean;
115
116
  * Wire-encode an already-rendered outbound payload into Lark im/v1 message body.
116
117
  * Segment canonicalization is intentionally not done here.
117
118
  */
118
- export declare function formatOutboundBody(payload: unknown): LarkSendBody;
119
+ export declare function formatOutboundBody(payload: unknown, locale?: Locale): LarkSendBody;
119
120
  export declare function headerValue(headers: IncomingMessage['headers'], name: string): string;
120
121
  export declare function readTextBody(request: IncomingMessage, options?: {
121
122
  readonly limit?: number;
package/lib/protocol.js CHANGED
@@ -155,7 +155,7 @@ export function verifyToken(token, expected) {
155
155
  * Wire-encode an already-rendered outbound payload into Lark im/v1 message body.
156
156
  * Segment canonicalization is intentionally not done here.
157
157
  */
158
- export function formatOutboundBody(payload) {
158
+ export function formatOutboundBody(payload, locale) {
159
159
  if (typeof payload === 'string') {
160
160
  return {
161
161
  msg_type: 'text',
@@ -168,7 +168,7 @@ export function formatOutboundBody(payload) {
168
168
  ? [payload]
169
169
  : [];
170
170
  if (items.some(item => typeof item !== 'string' && ['markdown', 'share', 'keyboard'].includes(item.type)))
171
- return formatLarkCard(items);
171
+ return formatLarkCard(items, locale);
172
172
  const hasMarkdown = items.some((item) => typeof item !== 'string' && item.type === 'markdown');
173
173
  if (items.length === 0) {
174
174
  const text = payload == null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-lark",
3
- "version": "1.1.15",
3
+ "version": "1.1.16",
4
4
  "description": "Zhin.js Lark/Feishu adapter (HTTP webhook and WebSocket long connection)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -33,26 +33,26 @@
33
33
  "directory": "plugins/adapters/lark"
34
34
  },
35
35
  "dependencies": {
36
- "undici": "6.28.0",
36
+ "undici": "6.29.1",
37
37
  "@larksuiteoapi/node-sdk": "^1.67.0",
38
- "@zhin.js/adapter": "1.1.22",
39
- "@zhin.js/agent-feature": "1.1.9",
40
- "@zhin.js/core": "1.1.50",
41
- "@zhin.js/feature-kit": "1.1.8",
42
- "@zhin.js/host-http": "1.1.9",
43
- "@zhin.js/im-contract": "1.1.6",
38
+ "@zhin.js/agent-feature": "1.1.10",
39
+ "@zhin.js/adapter": "1.1.23",
40
+ "@zhin.js/core": "1.1.51",
41
+ "@zhin.js/feature-kit": "1.1.9",
42
+ "@zhin.js/host-http": "1.1.10",
43
+ "@zhin.js/im-contract": "1.1.7",
44
44
  "@zhin.js/logger": "1.1.2",
45
- "@zhin.js/skill": "1.1.9",
46
- "@zhin.js/tool": "1.1.9"
45
+ "@zhin.js/skill": "1.1.10",
46
+ "@zhin.js/tool": "1.1.10"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "zod": "^4.0.0",
50
- "@zhin.js/adapter": "^1.1.22",
51
- "@zhin.js/command": "^1.1.10",
52
- "@zhin.js/core": "^1.1.50",
53
- "@zhin.js/host-http": "^1.1.9",
54
- "@zhin.js/permission": "^1.1.8",
55
- "zhin.js": "^1.1.15"
50
+ "@zhin.js/adapter": "^1.1.23",
51
+ "@zhin.js/command": "^1.1.11",
52
+ "@zhin.js/core": "^1.1.51",
53
+ "@zhin.js/permission": "^1.1.9",
54
+ "@zhin.js/host-http": "^1.1.10",
55
+ "zhin.js": "^1.1.16"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "@zhin.js/command": {
@@ -70,7 +70,7 @@
70
70
  "typescript": "^6.0.3",
71
71
  "vitest": "^4.1.10",
72
72
  "zod": "^4.4.3",
73
- "zhin.js": "1.1.15"
73
+ "zhin.js": "1.1.16"
74
74
  },
75
75
  "files": [
76
76
  "adapters",
package/schema.json CHANGED
@@ -19,7 +19,12 @@
19
19
  "string",
20
20
  "number"
21
21
  ],
22
- "description": "框架 master(Lark/Feishu open_id or user_id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
22
+ "description": "框架 master(Lark/Feishu open_id or user_id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖",
23
+ "x-i18n": {
24
+ "en": {
25
+ "description": "Framework masters (Lark/Feishu open_id or user_id; AI/tool permissions and endpoint management). endpoints[i].master can override this value."
26
+ }
27
+ }
23
28
  },
24
29
  "trusted": {
25
30
  "type": "array",
@@ -30,7 +35,12 @@
30
35
  ],
31
36
  "description": "Trusted Lark/Feishu open_id or user_id"
32
37
  },
33
- "description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
38
+ "description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加",
39
+ "x-i18n": {
40
+ "en": {
41
+ "description": "Framework trusted users, below master authority. endpoints[i].trusted can add users."
42
+ }
43
+ }
34
44
  },
35
45
  "endpoints": {
36
46
  "type": "array",
@@ -45,7 +55,12 @@
45
55
  "string",
46
56
  "number"
47
57
  ],
48
- "description": "本 endpoint 的框架 master(Lark/Feishu open_id or user_id);覆盖顶层 master"
58
+ "description": "本 endpoint 的框架 master(Lark/Feishu open_id or user_id);覆盖顶层 master",
59
+ "x-i18n": {
60
+ "en": {
61
+ "description": "Framework masters for this endpoint (Lark/Feishu open_id or user_id), overriding the top-level master list."
62
+ }
63
+ }
49
64
  },
50
65
  "trusted": {
51
66
  "type": "array",
@@ -56,7 +71,12 @@
56
71
  ],
57
72
  "description": "Trusted Lark/Feishu open_id or user_id"
58
73
  },
59
- "description": "本 endpoint 的 trusted 列表"
74
+ "description": "本 endpoint 的 trusted 列表",
75
+ "x-i18n": {
76
+ "en": {
77
+ "description": "Trusted users for this endpoint."
78
+ }
79
+ }
60
80
  },
61
81
  "appId": {
62
82
  "type": "string",
@@ -117,7 +137,12 @@
117
137
  "port",
118
138
  "serverName"
119
139
  ],
120
- "description": "WSS故障验收:仅TCP固定loopback,保留TLS身份"
140
+ "description": "WSS故障验收:仅TCP固定loopback,保留TLS身份",
141
+ "x-i18n": {
142
+ "en": {
143
+ "description": "WSS fault-injection tests: pin only TCP to loopback while preserving TLS identity."
144
+ }
145
+ }
121
146
  },
122
147
  "webApiProxy": {
123
148
  "type": "object",
@@ -132,7 +157,12 @@
132
157
  "maximum": 65535
133
158
  }
134
159
  },
135
- "description": "默认关闭;仅飞书出站API的loopback TLS故障代理,保留官方Host/SNI和证书校验,与streamProxy独立"
160
+ "description": "默认关闭;仅飞书出站API的loopback TLS故障代理,保留官方Host/SNI和证书校验,与streamProxy独立",
161
+ "x-i18n": {
162
+ "en": {
163
+ "description": "Disabled by default. Loopback TLS fault proxy for Feishu outbound APIs only; preserves the official Host, SNI and certificate validation. Independent of streamProxy."
164
+ }
165
+ }
136
166
  }
137
167
  },
138
168
  "required": [
@@ -140,12 +170,22 @@
140
170
  "appId",
141
171
  "appSecret"
142
172
  ]
173
+ },
174
+ "x-i18n": {
175
+ "en": {
176
+ "description": "Multiple accounts: mount multiple endpoints in one plugin instance. Each entry uses the top-level fields; id is required and other fields override defaults."
177
+ }
143
178
  }
144
179
  },
145
180
  "commandPrefix": {
146
181
  "type": "string",
147
182
  "default": "",
148
- "description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖"
183
+ "description": "命令前缀(默认 '' 无前缀,任意文本按命令匹配;如 '/' 要求 / 开头)。endpoints[i] 可逐项覆盖",
184
+ "x-i18n": {
185
+ "en": {
186
+ "description": "Command prefix. The default empty string allows unprefixed commands; '/' requires a leading slash. Each endpoints[i] can override it."
187
+ }
188
+ }
149
189
  },
150
190
  "mode": {
151
191
  "type": "string",
@@ -168,7 +208,12 @@
168
208
  "maximum": 65535
169
209
  }
170
210
  },
171
- "description": "默认关闭;仅飞书出站API的loopback TLS故障代理,保留官方Host/SNI和证书校验,与streamProxy独立"
211
+ "description": "默认关闭;仅飞书出站API的loopback TLS故障代理,保留官方Host/SNI和证书校验,与streamProxy独立",
212
+ "x-i18n": {
213
+ "en": {
214
+ "description": "Disabled by default. Loopback TLS fault proxy for Feishu outbound APIs only; preserves the official Host, SNI and certificate validation. Independent of streamProxy."
215
+ }
216
+ }
172
217
  }
173
218
  },
174
219
  "required": [
package/src/cards.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import type { Locale } from 'zhin.js/i18n';
2
+ import { messages as t } from './i18n.js';
1
3
  import { EndpointDeliveryError } from '@zhin.js/im-contract';
2
4
  import type { LarkSendBody, LarkWireSegment } from './protocol.js';
3
5
 
4
6
  /** Feishu JSON card v1: ordered native rich text, link and button components. */
5
- export function formatLarkCard(items: Array<string | LarkWireSegment>): LarkSendBody {
7
+ export function formatLarkCard(items: Array<string | LarkWireSegment>, locale?: Locale): LarkSendBody {
6
8
  const elements: unknown[] = [];
7
9
  let replyTo: string | undefined;
8
10
  for (const item of items) {
@@ -22,7 +24,7 @@ export function formatLarkCard(items: Array<string | LarkWireSegment>): LarkSend
22
24
  if (!/^https?:\/\//.test(url)) throw unsupported();
23
25
  elements.push({ tag: 'div', text: { tag: 'plain_text', content: String(data.title ?? url) } });
24
26
  if (data.description) elements.push({ tag: 'div', text: { tag: 'plain_text', content: String(data.description) } });
25
- elements.push({ tag: 'action', actions: [{ tag: 'button', text: { tag: 'plain_text', content: '打开链接' }, url }] }); break;
27
+ elements.push({ tag: 'action', actions: [{ tag: 'button', text: { tag: 'plain_text', content: t(locale, 'openLink') }, url }] }); break;
26
28
  }
27
29
  case 'keyboard': {
28
30
  const rows = data.rows as Array<Array<{ id?: string; label?: string; payload?: string; url?: string }>> | undefined;
package/src/endpoint.ts CHANGED
@@ -258,10 +258,10 @@ export class LarkEndpoint extends Endpoint<LarkClient> {
258
258
  this.#logger.debug(formatCompact({ op: 'disconnect' }));
259
259
  }
260
260
 
261
- async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
261
+ async send({ conversation, payload, locale }: EndpointSendRequest): Promise<string> {
262
262
  try {
263
263
  const materialized = await this.#materializeOutboundMedia(payload);
264
- const content = formatOutboundBody(materialized);
264
+ const content = formatOutboundBody(materialized, locale);
265
265
  const data = await this.#request(content.replyTo
266
266
  ? `/im/v1/messages/${encodeURIComponent(content.replyTo)}/reply`
267
267
  : '/im/v1/messages', {
package/src/i18n.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { createMessages } from 'zhin.js/i18n';
2
+
3
+ export const messages = createMessages({
4
+ openLink: { 'zh-CN': '打开链接', en: 'Open link' },
5
+ link: { 'zh-CN': '链接', en: 'Link' },
6
+ message: { 'zh-CN': '消息', en: 'Message' }
7
+ });
package/src/protocol.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Locale } from 'zhin.js/i18n';
1
2
  import { validateLarkWebApiProxy } from './web-api-proxy.js';
2
3
  /**
3
4
  * Lark/Feishu protocol helpers — no legacy Adapter/Endpoint / segment-mapper.
@@ -272,7 +273,7 @@ export function verifyToken(token: string, expected: string): boolean {
272
273
  * Wire-encode an already-rendered outbound payload into Lark im/v1 message body.
273
274
  * Segment canonicalization is intentionally not done here.
274
275
  */
275
- export function formatOutboundBody(payload: unknown): LarkSendBody {
276
+ export function formatOutboundBody(payload: unknown, locale?: Locale): LarkSendBody {
276
277
  if (typeof payload === 'string') {
277
278
  return {
278
279
  msg_type: 'text',
@@ -285,7 +286,7 @@ export function formatOutboundBody(payload: unknown): LarkSendBody {
285
286
  : payload && typeof payload === 'object' && 'type' in (payload as object)
286
287
  ? [payload as LarkWireSegment]
287
288
  : [];
288
- if (items.some(item => typeof item !== 'string' && ['markdown', 'share', 'keyboard'].includes(item.type))) return formatLarkCard(items);
289
+ if (items.some(item => typeof item !== 'string' && ['markdown', 'share', 'keyboard'].includes(item.type))) return formatLarkCard(items, locale);
289
290
  const hasMarkdown = items.some((item) => typeof item !== 'string' && item.type === 'markdown');
290
291
 
291
292
  if (items.length === 0) {