@lanmers/wecom-openclaw-plugin-agents 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +326 -0
  2. package/dist/index.cjs.js +3617 -0
  3. package/dist/index.cjs.js.map +1 -0
  4. package/dist/index.d.ts +12 -0
  5. package/dist/index.esm.js +3591 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/dist/src/channel.d.ts +11 -0
  8. package/dist/src/const.d.ts +74 -0
  9. package/dist/src/dm-policy.d.ts +29 -0
  10. package/dist/src/group-policy.d.ts +29 -0
  11. package/dist/src/interface.d.ts +154 -0
  12. package/dist/src/mcp/index.d.ts +6 -0
  13. package/dist/src/mcp/schema.d.ts +11 -0
  14. package/dist/src/mcp/tool.d.ts +55 -0
  15. package/dist/src/mcp/transport.d.ts +61 -0
  16. package/dist/src/mcp-config.d.ts +29 -0
  17. package/dist/src/media-handler.d.ts +36 -0
  18. package/dist/src/media-uploader.d.ts +131 -0
  19. package/dist/src/message-parser.d.ts +72 -0
  20. package/dist/src/message-sender.d.ts +23 -0
  21. package/dist/src/monitor.d.ts +27 -0
  22. package/dist/src/onboarding.d.ts +5 -0
  23. package/dist/src/openclaw-compat.d.ts +48 -0
  24. package/dist/src/reqid-store.d.ts +31 -0
  25. package/dist/src/runtime.d.ts +3 -0
  26. package/dist/src/state-manager.d.ts +76 -0
  27. package/dist/src/timeout.d.ts +20 -0
  28. package/dist/src/utils.d.ts +80 -0
  29. package/dist/src/version.d.ts +2 -0
  30. package/openclaw.plugin.json +14 -0
  31. package/package.json +73 -0
  32. package/skills/wecom-contact-lookup/SKILL.md +162 -0
  33. package/skills/wecom-doc/SKILL.md +363 -0
  34. package/skills/wecom-doc/references/doc-api.md +224 -0
  35. package/skills/wecom-doc-manager/SKILL.md +64 -0
  36. package/skills/wecom-doc-manager/references/api-create-doc.md +56 -0
  37. package/skills/wecom-doc-manager/references/api-edit-doc-content.md +68 -0
  38. package/skills/wecom-doc-manager/references/api-export-document.md +88 -0
  39. package/skills/wecom-edit-todo/SKILL.md +249 -0
  40. package/skills/wecom-get-todo-detail/SKILL.md +143 -0
  41. package/skills/wecom-get-todo-list/SKILL.md +127 -0
  42. package/skills/wecom-meeting-create/SKILL.md +158 -0
  43. package/skills/wecom-meeting-create/references/example-full.md +30 -0
  44. package/skills/wecom-meeting-create/references/example-reminder.md +46 -0
  45. package/skills/wecom-meeting-create/references/example-security.md +22 -0
  46. package/skills/wecom-meeting-manage/SKILL.md +136 -0
  47. package/skills/wecom-meeting-query/SKILL.md +330 -0
  48. package/skills/wecom-preflight/SKILL.md +141 -0
  49. package/skills/wecom-schedule/SKILL.md +159 -0
  50. package/skills/wecom-schedule/references/api-check-availability.md +56 -0
  51. package/skills/wecom-schedule/references/api-create-schedule.md +38 -0
  52. package/skills/wecom-schedule/references/api-get-schedule-detail.md +81 -0
  53. package/skills/wecom-schedule/references/api-update-schedule.md +30 -0
  54. package/skills/wecom-schedule/references/ref-reminders.md +24 -0
  55. package/skills/wecom-smartsheet-data/SKILL.md +71 -0
  56. package/skills/wecom-smartsheet-data/references/api-get-records.md +61 -0
  57. package/skills/wecom-smartsheet-data/references/cell-value-formats.md +120 -0
  58. package/skills/wecom-smartsheet-schema/SKILL.md +92 -0
  59. package/skills/wecom-smartsheet-schema/references/field-types.md +43 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * 企业微信消息内容解析模块
3
+ *
4
+ * 负责从 WsFrame 中提取文本、图片、引用等内容
5
+ */
6
+ export interface MessageBody {
7
+ msgid: string;
8
+ aibotid?: string;
9
+ chatid?: string;
10
+ chattype: "single" | "group";
11
+ from: {
12
+ userid: string;
13
+ };
14
+ response_url?: string;
15
+ msgtype: string;
16
+ text?: {
17
+ content: string;
18
+ };
19
+ image?: {
20
+ url?: string;
21
+ aeskey?: string;
22
+ };
23
+ voice?: {
24
+ content?: string;
25
+ };
26
+ mixed?: {
27
+ msg_item: Array<{
28
+ msgtype: "text" | "image";
29
+ text?: {
30
+ content: string;
31
+ };
32
+ image?: {
33
+ url?: string;
34
+ aeskey?: string;
35
+ };
36
+ }>;
37
+ };
38
+ file?: {
39
+ url?: string;
40
+ aeskey?: string;
41
+ };
42
+ quote?: {
43
+ msgtype: string;
44
+ text?: {
45
+ content: string;
46
+ };
47
+ voice?: {
48
+ content: string;
49
+ };
50
+ image?: {
51
+ url?: string;
52
+ aeskey?: string;
53
+ };
54
+ file?: {
55
+ url?: string;
56
+ aeskey?: string;
57
+ };
58
+ };
59
+ }
60
+ export interface ParsedMessageContent {
61
+ textParts: string[];
62
+ imageUrls: string[];
63
+ imageAesKeys: Map<string, string>;
64
+ fileUrls: string[];
65
+ fileAesKeys: Map<string, string>;
66
+ quoteContent: string | undefined;
67
+ }
68
+ /**
69
+ * 解析消息内容(支持单条消息、图文混排和引用消息)
70
+ * @returns 提取的文本数组、图片URL数组和引用消息内容
71
+ */
72
+ export declare function parseMessageContent(body: MessageBody): ParsedMessageContent;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 企业微信消息发送模块
3
+ *
4
+ * 负责通过 WSClient 发送回复消息,包含超时保护
5
+ */
6
+ import type { RuntimeEnv } from "openclaw/plugin-sdk";
7
+ import { type WSClient, type WsFrame } from "@wecom/aibot-node-sdk";
8
+ /**
9
+ * 发送企业微信回复消息
10
+ * 供 monitor 内部和 channel outbound 使用
11
+ *
12
+ * @returns messageId (streamId)
13
+ */
14
+ export declare function sendWeComReply(params: {
15
+ wsClient: WSClient;
16
+ frame: WsFrame;
17
+ text?: string;
18
+ runtime: RuntimeEnv;
19
+ /** 是否为流式回复的最终消息,默认为 true */
20
+ finish?: boolean;
21
+ /** 指定 streamId,用于流式回复时保持相同的 streamId */
22
+ streamId?: string;
23
+ }): Promise<string>;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 企业微信 WebSocket 监控器主模块
3
+ *
4
+ * 负责:
5
+ * - 建立和管理 WebSocket 连接
6
+ * - 协调消息处理流程(解析→策略检查→下载图片→路由回复)
7
+ * - 资源生命周期管理
8
+ *
9
+ * 子模块:
10
+ * - message-parser.ts : 消息内容解析
11
+ * - message-sender.ts : 消息发送(带超时保护)
12
+ * - media-handler.ts : 图片下载和保存(带超时保护)
13
+ * - group-policy.ts : 群组访问控制
14
+ * - dm-policy.ts : 私聊访问控制
15
+ * - state-manager.ts : 全局状态管理(带 TTL 清理)
16
+ * - timeout.ts : 超时工具
17
+ */
18
+ import type { WeComMonitorOptions } from "./interface.js";
19
+ export type { WeComMonitorOptions } from "./interface.js";
20
+ export { WeComCommand } from "./const.js";
21
+ export { getWeComWebSocket, setReqIdForChat, getReqIdForChatAsync, getReqIdForChat, deleteReqIdForChat, warmupReqIdStore, flushReqIdStore, } from "./state-manager.js";
22
+ export { sendWeComReply } from "./message-sender.js";
23
+ /**
24
+ * 监听企业微信 WebSocket 连接
25
+ * 使用 aibot-node-sdk 简化连接管理
26
+ */
27
+ export declare function monitorWeComProvider(options: WeComMonitorOptions): Promise<void>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 企业微信 onboarding adapter for CLI setup wizard.
3
+ */
4
+ import { type ChannelOnboardingAdapter } from "openclaw/plugin-sdk";
5
+ export declare const wecomOnboardingAdapter: ChannelOnboardingAdapter;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * openclaw plugin-sdk 高版本方法兼容层
3
+ *
4
+ * 部分方法(如 loadOutboundMediaFromUrl、detectMime、getDefaultMediaLocalRoots)
5
+ * 仅在较新版本的 openclaw plugin-sdk 中才导出。
6
+ *
7
+ * 本模块在加载时一次性探测 SDK 导出,存在则直接 re-export SDK 版本,
8
+ * 不存在则导出 fallback 实现。其他模块统一从本文件导入,无需关心底层兼容细节。
9
+ */
10
+ /** 与 openclaw plugin-sdk 中 WebMediaResult 兼容的类型 */
11
+ export type WebMediaResult = {
12
+ buffer: Buffer;
13
+ contentType?: string;
14
+ kind?: string;
15
+ fileName?: string;
16
+ };
17
+ export type OutboundMediaLoadOptions = {
18
+ maxBytes?: number;
19
+ mediaLocalRoots?: readonly string[];
20
+ };
21
+ export type DetectMimeOptions = {
22
+ buffer?: Buffer;
23
+ headerMime?: string | null;
24
+ filePath?: string;
25
+ };
26
+ /**
27
+ * 检测 MIME 类型(兼容入口)
28
+ *
29
+ * 支持两种调用签名以兼容不同使用场景:
30
+ * - detectMime(buffer) → 旧式调用
31
+ * - detectMime({ buffer, headerMime, filePath }) → 完整参数
32
+ *
33
+ * 优先使用 SDK 版本,不可用时使用 fallback。
34
+ */
35
+ export declare function detectMime(bufferOrOpts: Buffer | DetectMimeOptions): Promise<string | undefined>;
36
+ /**
37
+ * 从 URL 或本地路径加载媒体文件(兼容入口)
38
+ *
39
+ * 优先使用 SDK 版本,不可用时使用 fallback。
40
+ * SDK 版本抛出的业务异常(如 LocalMediaAccessError)会直接透传。
41
+ */
42
+ export declare function loadOutboundMediaFromUrl(mediaUrl: string, options?: OutboundMediaLoadOptions): Promise<WebMediaResult>;
43
+ /**
44
+ * 获取默认媒体本地路径白名单(兼容入口)
45
+ *
46
+ * 优先使用 SDK 版本,不可用时手动构建白名单(与 weclaw/src/media/local-roots.ts 逻辑一致)。
47
+ */
48
+ export declare function getDefaultMediaLocalRoots(): Promise<readonly string[]>;
@@ -0,0 +1,31 @@
1
+ /** Store 配置 */
2
+ interface ReqIdStoreOptions {
3
+ /** TTL 毫秒数,超时的 reqId 视为过期(默认 24 小时) */
4
+ ttlMs?: number;
5
+ /** 内存最大条目数(默认 200) */
6
+ memoryMaxSize?: number;
7
+ /** 磁盘最大条目数(默认 500) */
8
+ fileMaxEntries?: number;
9
+ /** 磁盘写入防抖时间(毫秒),默认 1000ms */
10
+ flushDebounceMs?: number;
11
+ }
12
+ export interface PersistentReqIdStore {
13
+ /** 设置 chatId 对应的 reqId(写入内存 + 防抖写磁盘) */
14
+ set(chatId: string, reqId: string): void;
15
+ /** 获取 chatId 对应的 reqId(异步:优先内存,miss 时查磁盘并回填内存) */
16
+ get(chatId: string): Promise<string | undefined>;
17
+ /** 同步获取 chatId 对应的 reqId(仅内存) */
18
+ getSync(chatId: string): string | undefined;
19
+ /** 删除 chatId 对应的 reqId */
20
+ delete(chatId: string): void;
21
+ /** 启动时从磁盘预热内存,返回加载条目数 */
22
+ warmup(onError?: (error: unknown) => void): Promise<number>;
23
+ /** 立即将内存数据刷写到磁盘(用于优雅退出) */
24
+ flush(): Promise<void>;
25
+ /** 清空内存缓存 */
26
+ clearMemory(): void;
27
+ /** 返回内存中的条目数 */
28
+ memorySize(): number;
29
+ }
30
+ export declare function createPersistentReqIdStore(accountId: string, options?: ReqIdStoreOptions): PersistentReqIdStore;
31
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { PluginRuntime } from "openclaw/plugin-sdk";
2
+ export declare function setWeComRuntime(r: PluginRuntime): void;
3
+ export declare function getWeComRuntime(): PluginRuntime;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 企业微信全局状态管理模块
3
+ *
4
+ * 负责管理 WSClient 实例、消息状态(带 TTL 清理)、ReqId 存储
5
+ * 解决全局 Map 的内存泄漏问题
6
+ */
7
+ import type { WSClient } from "@wecom/aibot-node-sdk";
8
+ import type { MessageState } from "./interface.js";
9
+ /**
10
+ * 获取指定账户的 WSClient 实例
11
+ */
12
+ export declare function getWeComWebSocket(accountId: string): WSClient | null;
13
+ /**
14
+ * 设置指定账户的 WSClient 实例
15
+ */
16
+ export declare function setWeComWebSocket(accountId: string, client: WSClient): void;
17
+ /**
18
+ * 删除指定账户的 WSClient 实例
19
+ */
20
+ export declare function deleteWeComWebSocket(accountId: string): void;
21
+ /**
22
+ * 启动消息状态定期清理(自动 TTL 清理 + 容量限制)
23
+ */
24
+ export declare function startMessageStateCleanup(): void;
25
+ /**
26
+ * 停止消息状态定期清理
27
+ */
28
+ export declare function stopMessageStateCleanup(): void;
29
+ /**
30
+ * 设置消息状态
31
+ */
32
+ export declare function setMessageState(messageId: string, state: MessageState): void;
33
+ /**
34
+ * 获取消息状态
35
+ */
36
+ export declare function getMessageState(messageId: string): MessageState | undefined;
37
+ /**
38
+ * 删除消息状态
39
+ */
40
+ export declare function deleteMessageState(messageId: string): void;
41
+ /**
42
+ * 清空所有消息状态
43
+ */
44
+ export declare function clearAllMessageStates(): void;
45
+ /**
46
+ * 设置 chatId 对应的 reqId(写入内存 + 防抖写磁盘)
47
+ */
48
+ export declare function setReqIdForChat(chatId: string, reqId: string, accountId?: string): void;
49
+ /**
50
+ * 获取 chatId 对应的 reqId(异步:优先内存,miss 时查磁盘并回填内存)
51
+ */
52
+ export declare function getReqIdForChatAsync(chatId: string, accountId?: string): Promise<string | undefined>;
53
+ /**
54
+ * 获取 chatId 对应的 reqId(同步:仅内存,保留向后兼容)
55
+ */
56
+ export declare function getReqIdForChat(chatId: string, accountId?: string): string | undefined;
57
+ /**
58
+ * 删除 chatId 对应的 reqId
59
+ */
60
+ export declare function deleteReqIdForChat(chatId: string, accountId?: string): void;
61
+ /**
62
+ * 启动时预热 reqId 缓存(从磁盘加载到内存)
63
+ */
64
+ export declare function warmupReqIdStore(accountId?: string, log?: (...args: unknown[]) => void): Promise<number>;
65
+ /**
66
+ * 立即将 reqId 数据刷写到磁盘(用于优雅退出)
67
+ */
68
+ export declare function flushReqIdStore(accountId?: string): Promise<void>;
69
+ /**
70
+ * 清理指定账户的所有资源
71
+ */
72
+ export declare function cleanupAccount(accountId: string): Promise<void>;
73
+ /**
74
+ * 清理所有资源(用于进程退出)
75
+ */
76
+ export declare function cleanupAll(): Promise<void>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 超时控制工具模块
3
+ *
4
+ * 为异步操作提供统一的超时保护机制
5
+ */
6
+ /**
7
+ * 为 Promise 添加超时保护
8
+ *
9
+ * @param promise - 原始 Promise
10
+ * @param timeoutMs - 超时时间(毫秒)
11
+ * @param message - 超时错误消息
12
+ * @returns 带超时保护的 Promise
13
+ */
14
+ export declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message?: string): Promise<T>;
15
+ /**
16
+ * 超时错误类型
17
+ */
18
+ export declare class TimeoutError extends Error {
19
+ constructor(message: string);
20
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * 企业微信公共工具函数
3
+ */
4
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
5
+ /**
6
+ * 企业微信群组配置
7
+ */
8
+ export interface WeComGroupConfig {
9
+ /** 群组内发送者白名单(仅列表中的成员消息会被处理) */
10
+ allowFrom?: Array<string | number>;
11
+ }
12
+ /**
13
+ * 企业微信配置类型
14
+ */
15
+ export interface WeComConfig {
16
+ enabled?: boolean;
17
+ websocketUrl?: string;
18
+ botId?: string;
19
+ secret?: string;
20
+ name?: string;
21
+ allowFrom?: Array<string | number>;
22
+ dmPolicy?: "open" | "allowlist" | "pairing" | "disabled";
23
+ /** 群组访问策略:"open" = 允许所有群组(默认),"allowlist" = 仅允许 groupAllowFrom 中的群组,"disabled" = 禁用群组消息 */
24
+ groupPolicy?: "open" | "allowlist" | "disabled";
25
+ /** 群组白名单(仅 groupPolicy="allowlist" 时生效) */
26
+ groupAllowFrom?: Array<string | number>;
27
+ /** 每个群组的详细配置(如群组内发送者白名单) */
28
+ groups?: Record<string, WeComGroupConfig>;
29
+ /** 是否发送"思考中"消息,默认为 true */
30
+ sendThinkingMessage?: boolean;
31
+ /** 额外允许访问的本地媒体路径白名单(支持 ~ 表示 home 目录),如 ["~/Downloads", "~/Documents"] */
32
+ mediaLocalRoots?: string[];
33
+ }
34
+ export declare const DefaultWsUrl = "wss://openws.work.weixin.qq.com";
35
+ export interface ResolvedWeComAccount {
36
+ accountId: string;
37
+ name: string;
38
+ enabled: boolean;
39
+ websocketUrl: string;
40
+ botId: string;
41
+ secret: string;
42
+ /** 是否发送"思考中"消息,默认为 true */
43
+ sendThinkingMessage: boolean;
44
+ config: WeComConfig;
45
+ }
46
+ /**
47
+ * 从 Channel ID 解析对应的 WeCom 配置
48
+ *
49
+ * 支持两种配置方式:
50
+ * 1. 多 Agent 模式:channels.wecom-bot1, channels.wecom-bot2(推荐)
51
+ * 2. 单 Agent 模式:channels.wecom(兼容旧版)
52
+ *
53
+ * @param cfg - OpenClaw 配置
54
+ * @param channelId - Channel ID(如 wecom-bot1 或 wecom)
55
+ * @returns 解析后的账户配置
56
+ */
57
+ export declare function resolveWeComAccountByChannelId(cfg: OpenClawConfig, channelId: string): ResolvedWeComAccount | null;
58
+ /**
59
+ * 解析企业微信账户配置(兼容旧版,返回 wecom 频道配置)
60
+ * @deprecated 请使用 resolveWeComAccountByChannelId
61
+ */
62
+ export declare function resolveWeComAccount(cfg: OpenClawConfig): ResolvedWeComAccount;
63
+ /**
64
+ * 列出所有已配置的 WeCom Channel ID
65
+ *
66
+ * 扫描所有 channels 键,找出以 wecom 或 wecom- 开头的配置
67
+ */
68
+ export declare function listWeComChannelIds(cfg: OpenClawConfig): string[];
69
+ /**
70
+ * 设置企业微信账户配置
71
+ */
72
+ export declare function setWeComAccount(cfg: OpenClawConfig, channelId: string, account: Partial<WeComConfig>): OpenClawConfig;
73
+ /**
74
+ * 删除指定 Channel 的配置
75
+ */
76
+ export declare function deleteWeComAccount(cfg: OpenClawConfig, channelId: string): OpenClawConfig;
77
+ /**
78
+ * 设置账户启用状态
79
+ */
80
+ export declare function setWeComAccountEnabled(cfg: OpenClawConfig, channelId: string, enabled: boolean): OpenClawConfig;
@@ -0,0 +1,2 @@
1
+ /** 插件版本号,来源于 package.json */
2
+ export declare const PLUGIN_VERSION: string;
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "wecom-openclaw-plugin-agents",
3
+ "channels": [
4
+ "wecom"
5
+ ],
6
+ "skills": [
7
+ "./skills"
8
+ ],
9
+ "configSchema": {
10
+ "type": "object",
11
+ "additionalProperties": false,
12
+ "properties": {}
13
+ }
14
+ }
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@lanmers/wecom-openclaw-plugin-agents",
3
+ "version": "3.0.0",
4
+ "type": "module",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "skills",
11
+ "openclaw.plugin.json",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "rollup -c",
16
+ "dev": "rollup -c -w",
17
+ "clean": "rm -rf dist",
18
+ "prebuild": "npm run clean",
19
+ "release": "node scripts/publish-all.mjs",
20
+ "release:dry": "node scripts/publish-all.mjs --dry-run"
21
+ },
22
+ "keywords": [
23
+ "wecom",
24
+ "openclaw",
25
+ "wecom-openclaw-plugin-agents"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/lanmers/wecom-openclaw-plugin-agents.git"
32
+ },
33
+ "homepage": "https://github.com/lanmers/wecom-openclaw-plugin-agents#readme",
34
+ "bugs": {
35
+ "url": "https://github.com/lanmers/wecom-openclaw-plugin-agents/issues"
36
+ },
37
+ "description": "OpenClaw WeCom (企业微信) channel plugin (official by Tencent WeCom team)",
38
+ "openclaw": {
39
+ "extensions": [
40
+ "./dist/index.esm.js"
41
+ ],
42
+ "channel": {
43
+ "id": "wecom",
44
+ "label": "企业微信",
45
+ "selectionLabel": "企业微信 (WeCom)",
46
+ "docsPath": "/channels/wecom",
47
+ "docsLabel": "wecom-openclaw-plugin-agents",
48
+ "blurb": "企业微信机器人接入插件",
49
+ "order": 80,
50
+ "quickstartAllowFrom": true
51
+ },
52
+ "install": {
53
+ "npmSpec": "@wecom/wecom-openclaw-plugin-agents",
54
+ "localPath": "extensions/wecom-openclaw-plugin-agents",
55
+ "defaultChoice": "npm"
56
+ }
57
+ },
58
+ "dependencies": {
59
+ "@wecom/aibot-node-sdk": "^1.0.2",
60
+ "file-type": "^21.3.0"
61
+ },
62
+ "devDependencies": {
63
+ "@rollup/plugin-commonjs": "^25.0.7",
64
+ "@rollup/plugin-json": "^6.1.0",
65
+ "@rollup/plugin-node-resolve": "^15.2.3",
66
+ "@rollup/plugin-typescript": "^11.1.6",
67
+ "openclaw": "^2026.3.13",
68
+ "rollup": "^4.9.6",
69
+ "rollup-plugin-dts": "^6.1.0",
70
+ "tslib": "^2.6.2",
71
+ "typescript": "^5.3.3"
72
+ }
73
+ }
@@ -0,0 +1,162 @@
1
+ ---
2
+ name: wecom-contact-lookup
3
+ description: 通讯录成员查询技能,基于 MCP tool 协议封装的 `get_userlist` 接口,获取当前用户可见范围内的通讯录成员,支持按姓名/别名本地筛选匹配。返回 userid、姓名和别名。⚠️ 仅返回当前用户有权限查看的成员,非全量成员。
4
+ ---
5
+
6
+ # 通讯录成员查询技能
7
+
8
+ > `wecom_mcp` 是一个 MCP tool,所有操作通过调用该 tool 完成。
9
+
10
+ > ⚠️ **前置条件**:首次调用 `wecom_mcp` 前,必须按 `wecom-preflight` 技能执行前置条件检查,确保工具已加入白名单。
11
+
12
+ 通过 MCP tool 协议封装的 `get_userlist` 接口,获取当前用户可见范围内的通讯录成员,并在本地按姓名/别名进行筛选匹配。
13
+
14
+ ## 操作
15
+
16
+ ### 1. 获取全量通讯录成员
17
+
18
+ 获取当前用户可见范围内的所有企业成员信息:
19
+
20
+ **调用示例:**
21
+
22
+ 使用 `wecom_mcp` tool 调用 `wecom_mcp call contact get_userlist '{}'`
23
+
24
+ **返回格式:**
25
+
26
+ ```json
27
+ {
28
+ "errcode": 0,
29
+ "errmsg": "ok",
30
+ "userlist": [
31
+ {
32
+ "userid": "zhangsan",
33
+ "name": "张三",
34
+ "alias": "Sam"
35
+ },
36
+ {
37
+ "userid": "lisi",
38
+ "name": "李四",
39
+ "alias": ""
40
+ }
41
+ ]
42
+ }
43
+ ```
44
+
45
+ **返回字段说明:**
46
+
47
+ | 字段 | 类型 | 说明 |
48
+ |------|------|------|
49
+ | `errcode` | integer | 返回码,`0` 表示成功 |
50
+ | `errmsg` | string | 错误信息 |
51
+ | `userlist` | array | 用户列表 |
52
+ | `userlist[].userid` | string | 用户唯一 ID |
53
+ | `userlist[].name` | string | 用户姓名 |
54
+ | `userlist[].alias` | string | 用户别名,可能为空 |
55
+
56
+ ---
57
+
58
+ ### 2. 按姓名/别名搜索人员
59
+
60
+ `get_userlist` 返回全量成员后,在本地对结果进行筛选匹配:
61
+
62
+ - **精确匹配**:`name` 或 `alias` 与关键词完全一致,直接使用
63
+ - **模糊匹配**:`name` 或 `alias` 包含关键词,返回所有匹配结果
64
+ - **无结果**:告知用户未找到对应人员
65
+
66
+ **搜索示例:**
67
+
68
+ 用户问:"帮我找一下张三是谁?"
69
+
70
+ 1. 调用 `get_userlist` 获取全量成员
71
+ 2. 在 `userlist` 中筛选 `name` 或 `alias` 包含"张三"的成员
72
+ 3. 返回匹配结果
73
+
74
+ ---
75
+
76
+ ## 注意事项
77
+
78
+ - `get_userlist` 返回的是当前用户**可见范围内**的成员,需经过可见性规则过滤,不一定是全公司所有人员;返回字段仅包含 `userid`、`name`(姓名)和 `alias`(别名)
79
+ - ⚠️ **超过 10 人时接口将报错**:若 `userlist` 返回成员数量超过 10 人,视为异常,应立即停止处理并向用户说明:
80
+
81
+ > 当前通讯录可见成员数量超过了本技能支持的上限(10 人)。
82
+ > 本技能仅适用于可见范围较小的场景,无法在大范围通讯录中使用。
83
+ > 建议缩小可见范围后重试,或通过其他方式查询目标人员。
84
+
85
+ - `userid` 是用户的唯一标识,在需要传递用户 ID 给其他接口时使用此字段
86
+ - `alias` 字段可能为空字符串,搜索时需做空值判断
87
+ - 若搜索结果有多个同名人员,需将所有候选人展示给用户选择,不得自行决定
88
+ - 若 `errcode` 不为 `0`,说明接口调用失败,需告知用户错误信息(`errmsg`)
89
+
90
+ ---
91
+
92
+ ## 典型工作流
93
+
94
+ ### 工作流 1:查询人员信息
95
+
96
+ 用户问:"帮我查一下 Sam 是谁?"
97
+
98
+ 1. 使用 `wecom_mcp` tool 调用 `wecom_mcp call contact get_userlist '{}'` 获取全量成员列表
99
+
100
+ 2. 在结果中筛选 `alias` 为 `Sam` 或 `name` 包含 `Sam` 的成员
101
+ 3. 若找到唯一匹配,直接展示结果:
102
+
103
+ ```
104
+ 📇 找到成员:
105
+ - 姓名:张三
106
+ - 别名:Sam
107
+ - 用户ID:zhangsan
108
+ ```
109
+
110
+ 4. 若找到多个匹配,展示候选列表请用户确认:
111
+
112
+ ```
113
+ 🔍 找到多个匹配成员,请确认您要查询的是哪位:
114
+
115
+ 1. 张三(别名:Sam,ID:zhangsan)
116
+ 2. 张三丰(别名:Sam2,ID:zhangsan2)
117
+
118
+ 请问您要查询的是哪一位?
119
+ ```
120
+
121
+ ---
122
+
123
+ ### 工作流 2:为其他功能提供 userid 转换
124
+
125
+ 用户问:"帮我发消息给张三"
126
+
127
+ 1. 使用 `wecom_mcp` tool 调用 `wecom_mcp call contact get_userlist '{}'` 获取全量成员
128
+
129
+ 2. 筛选 `name` 为"张三"的成员,确认 `userid`
130
+ 3. 将 `userid` 传递给消息发送接口
131
+
132
+ ---
133
+
134
+ ### 工作流 3:批量查询多个人员
135
+
136
+ 用户问:"帮我查一下张三和李四分别是谁?"
137
+
138
+ 1. 使用 `wecom_mcp` tool 调用 `wecom_mcp call contact get_userlist '{}'` 获取全量成员列表
139
+
140
+ 2. 分别筛选"张三"和"李四"的匹配结果
141
+ 3. 汇总后一并展示
142
+
143
+ > 注意:只需调用一次 `get_userlist`,在本地对结果进行多次筛选,避免重复调用接口。
144
+
145
+ ---
146
+
147
+ ## 快速参考
148
+
149
+ ### 接口说明
150
+
151
+ | 接口 | 用途 | 输入 | 返回 |
152
+ |------|------|------|------|
153
+ | `get_userlist` | 获取可见范围内全量通讯录成员 | 无 | 用户列表(userid、name、alias) |
154
+
155
+ ### 本地筛选策略
156
+
157
+ | 场景 | 策略 |
158
+ |------|------|
159
+ | 精确匹配(name 或 alias 完全一致) | 直接使用,无需用户确认 |
160
+ | 模糊匹配(name 或 alias 包含关键词),唯一结果 | 直接使用,向用户展示结果 |
161
+ | 模糊匹配,多个结果 | 展示候选列表,请用户选择 |
162
+ | 无匹配结果 | 告知用户未找到对应人员 |