@wps365/openclaw-wpsxiezuo 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/README_ZH-CN.md +318 -0
- package/bin/cli.mjs +677 -0
- package/dist/channel/event-crypto.d.ts +19 -0
- package/dist/channel/event-handlers.d.ts +61 -0
- package/dist/channel/event-types.d.ts +88 -0
- package/dist/channel/index.d.ts +8 -0
- package/dist/channel/plugin.d.ts +11 -0
- package/dist/channel/register-tool-bridge.d.ts +14 -0
- package/dist/channel/sdk-client-options.d.ts +24 -0
- package/dist/channel/sdk-helpers.d.ts +12 -0
- package/dist/channel/sdk-provider.d.ts +23 -0
- package/dist/channel/types.d.ts +324 -0
- package/dist/core/config.d.ts +267 -0
- package/dist/core/errors.d.ts +36 -0
- package/dist/core/index.d.ts +18 -0
- package/dist/core/lazy-client-store.d.ts +28 -0
- package/dist/core/media-utils.d.ts +27 -0
- package/dist/core/reaction.d.ts +29 -0
- package/dist/core/token-store.d.ts +34 -0
- package/dist/core/user-token-store.d.ts +35 -0
- package/dist/core/wps-client.d.ts +42 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +33 -0
- package/dist/messaging/handler.d.ts +73 -0
- package/dist/messaging/inbound/content-parser.d.ts +17 -0
- package/dist/messaging/inbound/handler.d.ts +44 -0
- package/dist/messaging/inbound/index.d.ts +5 -0
- package/dist/messaging/inbound/media-prefetch.d.ts +43 -0
- package/dist/messaging/inbound/pairing-allow-store.d.ts +11 -0
- package/dist/messaging/index.d.ts +3 -0
- package/dist/messaging/outbound.d.ts +15 -0
- package/dist/session/idempotency.d.ts +8 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/resolver.d.ts +17 -0
- package/dist/session/types.d.ts +37 -0
- package/dist/tools/oapi/calendar.d.ts +106 -0
- package/dist/tools/oapi/chat.d.ts +10 -0
- package/dist/tools/oapi/delegated-auth.d.ts +14 -0
- package/dist/tools/oapi/drive.d.ts +112 -0
- package/dist/tools/oapi/index.d.ts +24 -0
- package/dist/tools/oapi/media.d.ts +32 -0
- package/dist/tools/oapi/messaging.d.ts +10 -0
- package/dist/tools/oapi/todo.d.ts +96 -0
- package/dist/tools/oapi/user.d.ts +10 -0
- package/dist/tools/oauth/index.d.ts +65 -0
- package/openclaw.plugin.json +154 -0
- package/package.json +91 -0
- package/scripts/upgrade.sh +37 -0
- package/skills/wps-auth-provider.md +63 -0
- package/skills/wps-calendar/SKILL.md +147 -0
- package/skills/wps-channel-rules/SKILL.md +50 -0
- package/skills/wps-chat/SKILL.md +106 -0
- package/skills/wps-drive/SKILL.md +79 -0
- package/skills/wps-im-read/SKILL.md +88 -0
- package/skills/wps-im-send/SKILL.md +183 -0
- package/skills/wps-media/SKILL.md +101 -0
- package/skills/wps-message-handler.md +48 -0
- package/skills/wps-todo/SKILL.md +65 -0
- package/skills/wps-user/SKILL.md +105 -0
- package/skills/wps-xiezuo-session-mapper.md +62 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "wps-xiezuo",
|
|
3
|
+
"name": "WPS Xiezuo",
|
|
4
|
+
"version": "1.5.1",
|
|
5
|
+
"description": "WPS Xiezuo Openclaw Plugin - 对接 WPS 开放平台应用机器人",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"author": "WPS Xiezuo Team",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=22.0.0",
|
|
11
|
+
"openclaw": ">=2026.3.28"
|
|
12
|
+
},
|
|
13
|
+
"channels": ["wps-xiezuo"],
|
|
14
|
+
"configSchema": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": true,
|
|
17
|
+
"properties": {}
|
|
18
|
+
},
|
|
19
|
+
"channelConfigs": {
|
|
20
|
+
"wps-xiezuo": {
|
|
21
|
+
"label": "WPS Xiezuo",
|
|
22
|
+
"description": "WPS 开放平台企业机器人,支持群聊和私聊消息处理",
|
|
23
|
+
"schema": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"additionalProperties": false,
|
|
26
|
+
"properties": {
|
|
27
|
+
"name": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "账号显示名称(可选)"
|
|
30
|
+
},
|
|
31
|
+
"enabled": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"default": true,
|
|
34
|
+
"description": "启用或禁用此 WPS 账号配置"
|
|
35
|
+
},
|
|
36
|
+
"appId": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "WPS 开放平台应用 ID (Client ID)"
|
|
39
|
+
},
|
|
40
|
+
"appSecret": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "WPS 开放平台应用密钥 (Client Secret)"
|
|
43
|
+
},
|
|
44
|
+
"companyId": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "WPS 企业 ID(可选)"
|
|
47
|
+
},
|
|
48
|
+
"baseUrl": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"default": "https://openapi.wps.cn",
|
|
51
|
+
"description": "WPS 开放平台 API 端点"
|
|
52
|
+
},
|
|
53
|
+
"enableEncryption": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"default": true,
|
|
56
|
+
"description": "启用消息加密"
|
|
57
|
+
},
|
|
58
|
+
"webhookPath": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"default": "/wps/webhook",
|
|
61
|
+
"description": "Webhook 接收路径"
|
|
62
|
+
},
|
|
63
|
+
"webhookPort": {
|
|
64
|
+
"type": "number",
|
|
65
|
+
"default": 3000,
|
|
66
|
+
"minimum": 1,
|
|
67
|
+
"maximum": 65535,
|
|
68
|
+
"description": "Webhook 服务端口"
|
|
69
|
+
},
|
|
70
|
+
"dmPolicy": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"enum": ["open", "pairing", "allowlist"],
|
|
73
|
+
"default": "pairing",
|
|
74
|
+
"description": "私聊访问策略:open 允许所有私聊,pairing 需要配对,allowlist 仅允许白名单用户"
|
|
75
|
+
},
|
|
76
|
+
"allowFrom": {
|
|
77
|
+
"type": "array",
|
|
78
|
+
"items": { "type": "string" },
|
|
79
|
+
"description": "当 dmPolicy 为 allowlist 时,允许的用户 ID 列表"
|
|
80
|
+
},
|
|
81
|
+
"groupPolicy": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"enum": ["open", "allowlist"],
|
|
84
|
+
"default": "open",
|
|
85
|
+
"description": "群聊访问策略:open 允许所有群聊,allowlist 仅允许白名单群组"
|
|
86
|
+
},
|
|
87
|
+
"groupAllowFrom": {
|
|
88
|
+
"type": "array",
|
|
89
|
+
"items": { "type": "string" },
|
|
90
|
+
"description": "当 groupPolicy 为 allowlist 时,允许的群组 ID 列表"
|
|
91
|
+
},
|
|
92
|
+
"requireMention": {
|
|
93
|
+
"type": "boolean",
|
|
94
|
+
"default": true,
|
|
95
|
+
"description": "群聊中是否需要 @机器人 才响应"
|
|
96
|
+
},
|
|
97
|
+
"instantAck": {
|
|
98
|
+
"type": "object",
|
|
99
|
+
"properties": {
|
|
100
|
+
"enabled": {
|
|
101
|
+
"type": "boolean",
|
|
102
|
+
"default": true,
|
|
103
|
+
"description": "启用即时确认消息"
|
|
104
|
+
},
|
|
105
|
+
"text": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"default": "内容处理中,请稍候...",
|
|
108
|
+
"description": "即时确认消息文本"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"debug": {
|
|
113
|
+
"type": "boolean",
|
|
114
|
+
"default": false,
|
|
115
|
+
"description": "启用调试日志"
|
|
116
|
+
},
|
|
117
|
+
"sdk": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"additionalProperties": false,
|
|
120
|
+
"properties": {
|
|
121
|
+
"enabled": { "type": "boolean", "default": false },
|
|
122
|
+
"logLevel": {
|
|
123
|
+
"type": "string",
|
|
124
|
+
"enum": ["debug", "info", "warn", "error"],
|
|
125
|
+
"default": "info"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"mcp": {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"additionalProperties": false,
|
|
132
|
+
"properties": {
|
|
133
|
+
"enabled": { "type": "boolean", "default": false },
|
|
134
|
+
"mode": { "type": "string", "enum": ["app"], "default": "app" },
|
|
135
|
+
"toolAllowlist": {
|
|
136
|
+
"type": "array",
|
|
137
|
+
"items": { "type": "string" }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"capabilities": ["session", "auth", "skills"],
|
|
146
|
+
"hooks": {
|
|
147
|
+
"onInstall": "scripts/install.sh",
|
|
148
|
+
"onUninstall": "scripts/uninstall.sh",
|
|
149
|
+
"onUpgrade": "scripts/upgrade.sh"
|
|
150
|
+
},
|
|
151
|
+
"skills": {
|
|
152
|
+
"directory": "skills"
|
|
153
|
+
}
|
|
154
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wps365/openclaw-wpsxiezuo",
|
|
3
|
+
"version": "1.6.0",
|
|
4
|
+
"description": "WPS Xiezuo OpenClaw plugin - connect OpenClaw Agent to the WPS Open Platform enterprise robot",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"openclaw",
|
|
7
|
+
"openclaw-plugin"
|
|
8
|
+
],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "WPS Xiezuo Team",
|
|
11
|
+
"packageManager": "pnpm@10.33.0",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"bin": {
|
|
16
|
+
"openclaw-wps-xiezuo": "./bin/cli.mjs"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin/",
|
|
20
|
+
"dist/index.js",
|
|
21
|
+
"dist/**/*.d.ts",
|
|
22
|
+
"skills/",
|
|
23
|
+
"scripts/install.sh",
|
|
24
|
+
"scripts/uninstall.sh",
|
|
25
|
+
"scripts/upgrade.sh",
|
|
26
|
+
"openclaw.plugin.json",
|
|
27
|
+
"README.md",
|
|
28
|
+
"README_ZH-CN.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=22.0.0"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -p tsconfig.json",
|
|
36
|
+
"build:release": "rm -rf dist && tsc -p tsconfig.json && node scripts/minify.mjs",
|
|
37
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
38
|
+
"pack:bundle": "node scripts/build-bundle.mjs",
|
|
39
|
+
"release:bundle": "node scripts/release-bundle.mjs",
|
|
40
|
+
"release:patch": "node scripts/release-bundle.mjs patch",
|
|
41
|
+
"release:minor": "node scripts/release-bundle.mjs minor",
|
|
42
|
+
"release:major": "node scripts/release-bundle.mjs major",
|
|
43
|
+
"prepublishOnly": "pnpm run build:release",
|
|
44
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
45
|
+
"test": "echo \"Tests not yet implemented\""
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"esbuild": "^0.24.0",
|
|
50
|
+
"typescript": "^5.7.3"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"openclaw": ">=2026.3.28"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"openclaw": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"express": "^5.2.1",
|
|
62
|
+
"image-size": "^2.0.2",
|
|
63
|
+
"open-event-sdk": "^1.0.1",
|
|
64
|
+
"zod": "^4.3.6"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public",
|
|
68
|
+
"registry": "https://registry.npmjs.org/"
|
|
69
|
+
},
|
|
70
|
+
"openclaw": {
|
|
71
|
+
"extensions": [
|
|
72
|
+
"./dist/index.js"
|
|
73
|
+
],
|
|
74
|
+
"channel": {
|
|
75
|
+
"id": "wps-xiezuo",
|
|
76
|
+
"label": "WPS Xiezuo",
|
|
77
|
+
"selectionLabel": "WPS Kingsoft Docs / WPS Xiezuo",
|
|
78
|
+
"aliases": [
|
|
79
|
+
"wps"
|
|
80
|
+
],
|
|
81
|
+
"blurb": "WPS Open Platform enterprise robot (Kingsoft Docs / WPS Xiezuo) with support for group and direct message conversations.",
|
|
82
|
+
"order": 50,
|
|
83
|
+
"quickstartAllowFrom": true
|
|
84
|
+
},
|
|
85
|
+
"install": {
|
|
86
|
+
"npmSpec": "@wps365/openclaw-wpsxiezuo",
|
|
87
|
+
"localPath": "extensions/wps-xiezuo",
|
|
88
|
+
"defaultChoice": "npm"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "⬆️ 开始升级 WPS Xiezuo Openclaw 插件..."
|
|
5
|
+
|
|
6
|
+
if ! command -v openclaw >/dev/null 2>&1; then
|
|
7
|
+
echo "❌ 错误: 未检测到 openclaw 命令"
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
if ! command -v pnpm >/dev/null 2>&1; then
|
|
12
|
+
echo "❌ 错误: 未检测到 pnpm 命令"
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "📦 更新依赖..."
|
|
17
|
+
pnpm install
|
|
18
|
+
|
|
19
|
+
echo "🔨 重新构建项目..."
|
|
20
|
+
pnpm run build
|
|
21
|
+
|
|
22
|
+
echo "🔌 重新安装插件..."
|
|
23
|
+
if openclaw plugins --help >/dev/null 2>&1; then
|
|
24
|
+
openclaw plugins install .
|
|
25
|
+
else
|
|
26
|
+
openclaw plugin install .
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
echo "🔄 尝试重载插件..."
|
|
30
|
+
if openclaw plugin reload wps-xiezuo >/dev/null 2>&1; then
|
|
31
|
+
echo "✅ 插件重载完成"
|
|
32
|
+
else
|
|
33
|
+
echo "ℹ️ 当前环境不支持 plugin reload,请手动重启 gateway"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
echo "✅ 升级完成"
|
|
37
|
+
echo "💡 如从旧单账号配置升级,建议检查 channels.wps-xiezuo.accounts 是否已按预期配置"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wps-auth-provider
|
|
3
|
+
description: WPS OAuth 认证提供者
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# WPS Xiezuo 认证 Skill
|
|
8
|
+
|
|
9
|
+
## 功能说明
|
|
10
|
+
|
|
11
|
+
本 Skill 实现 WPS OAuth 认证流程,支持:
|
|
12
|
+
|
|
13
|
+
- OAuth 2.0 授权码模式
|
|
14
|
+
- Access Token 管理
|
|
15
|
+
- Token 自动刷新
|
|
16
|
+
- 用户身份验证
|
|
17
|
+
|
|
18
|
+
## 认证流程
|
|
19
|
+
|
|
20
|
+
1. **授权请求**: 引导用户到 WPS 授权页面
|
|
21
|
+
2. **授权回调**: 接收授权码
|
|
22
|
+
3. **Token 交换**: 使用授权码换取 access token
|
|
23
|
+
4. **Token 存储**: 安全存储 token
|
|
24
|
+
5. **Token 刷新**: 自动刷新过期 token
|
|
25
|
+
|
|
26
|
+
## 权限范围
|
|
27
|
+
|
|
28
|
+
- `bot.message.read`: 读取消息
|
|
29
|
+
- `bot.message.write`: 发送消息
|
|
30
|
+
- `bot.user.info`: 获取用户信息
|
|
31
|
+
|
|
32
|
+
## 配置参数
|
|
33
|
+
|
|
34
|
+
- `clientId`: WPS 应用 ID
|
|
35
|
+
- `clientSecret`: WPS 应用密钥
|
|
36
|
+
- 用户 OAuth 回调 URL 由插件内置,无独立 channel 配置项(见 `docs/user-oauth.md`)
|
|
37
|
+
- `scopes`: 权限范围列表
|
|
38
|
+
|
|
39
|
+
## 安全建议
|
|
40
|
+
|
|
41
|
+
1. 使用环境变量存储敏感信息
|
|
42
|
+
2. 启用 HTTPS 传输
|
|
43
|
+
3. 验证 state 参数防止 CSRF
|
|
44
|
+
4. 定期轮换密钥
|
|
45
|
+
|
|
46
|
+
## 使用示例
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// 生成授权 URL
|
|
50
|
+
const authUrl = authProvider.getAuthorizationUrl({
|
|
51
|
+
state: 'random_state',
|
|
52
|
+
scopes: ['bot.message.read', 'bot.message.write']
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// 处理回调
|
|
56
|
+
const tokens = await authProvider.handleCallback({
|
|
57
|
+
code: 'auth_code',
|
|
58
|
+
state: 'random_state'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// 刷新 token
|
|
62
|
+
const newTokens = await authProvider.refreshToken(tokens.refreshToken);
|
|
63
|
+
```
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wps-calendar
|
|
3
|
+
description: |
|
|
4
|
+
WPS365 日程与日历事件。用户要创建、列举主日历日程或「日程实例」(重复规则展开)时须走开放平台用户日历 API。
|
|
5
|
+
必须调用 wps_calendar_create / wps_calendar_list_events / wps_calendar_get_event / wps_calendar_list_event_attendees / wps_calendar_respond_invitation / wps_calendar_list_calendar_event_instances / wps_calendar_list_event_instances,禁止生成本地 .ics / 脚本替代。安装本插件后随 skills 目录一并加载。
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# WPS365 日程:创建与查询主日历事件
|
|
9
|
+
|
|
10
|
+
## 执行前必读
|
|
11
|
+
|
|
12
|
+
- **`wps_calendar_create`**:在用户已完成 **用户 OAuth** 且具备 `kso.calendar_events.readwrite`(或开放平台文档所列等价 delegated 权限)时,调用 `POST /v7/calendars/primary/events/create` 在 **主日历** 创建事件。
|
|
13
|
+
- **`wps_calendar_list_events`**:同一 delegated token 下调用 **`GET /v7/calendars/primary/events`**(即文档中的 `GET /v7/calendars/{calendar_id}/events`,`calendar_id=primary`)。官方说明:[查询日程列表](https://365.kdocs.cn/3rd/open/documents/app-integration-dev/wps365/server/calendar/calendar-event/get-calendar-event-list)。**HTTP 鉴权与创建日程相同**(用户 `access_token` + `Authorization: Bearer`,插件内共用同一 `WpsClient` 用户态路径,不另走 KSO-1)。
|
|
14
|
+
- **`wps_calendar_get_event`**:开放平台「**查询日程**」—— **`GET /v7/calendars/{calendar_id}/events/{event_id}`**(默认 `primary`)。**必填 `event_id`**(通常来自 `wps_calendar_list_events` 的 `id`)。返回体中 **`data` 为单个日程对象**(含 `recurrence`、`original_start_time`、`online_meeting` 等),不是列表。可选请求头:参数 **`x_kso_id_type`** 为 `internal` / `external` 时映射为 **`X-Kso-Id-Type`**(与文档一致)。
|
|
15
|
+
- **`wps_calendar_list_event_attendees`**:开放平台「**获取日程参与者列表**」—— **`GET /v7/calendars/{calendar_id}/events/{event_id}/attendees`**(默认 `primary`)。**必填 `event_id`**。响应 **`data`** 通常含 **`items[]`**(参与者)与可选 **`next_page_token`**。Query:可选 **`page_size`**(默认 30,文档最大 **100**)、**`page_token`**(上一页 `data.next_page_token`)。可选 **`x_kso_id_type`** → **`X-Kso-Id-Type`**。
|
|
16
|
+
- **`wps_calendar_list_calendar_event_instances`**:调用 **`GET /v7/calendars/{calendar_id}/event_instances`**(默认 `calendar_id=primary`)。在时间窗内返回**主日历上多条日程**展开后的实例(日历级扫描)。Query:`start_time` / `end_time` 为 **RFC3339**、时间窗 **≤31 天**;可选 `page_size`(默认 30)、`page_token`。**鉴权与创建相同**(Bearer)。适合「这周所有会议 occurrence」等**不指定某条 event** 的场景。
|
|
17
|
+
- **`wps_calendar_list_event_instances`**:开放平台「**查询日程实例**」—— **`GET /v7/calendars/{calendar_id}/events/{event_id}/event_instances`**(默认 `primary`)。**必填 `event_id`**(从 `wps_calendar_list_events` 返回的 `id` 取得)。Query 仅文档所列:`start_time` / `end_time`(**RFC3339**,**≤31 天**);无 `page_size` / `page_token`。用于**单条重复日程**在指定时间窗内的展开实例。只看逻辑事件用 `wps_calendar_list_events`。
|
|
18
|
+
- **`wps_calendar_respond_invitation`**:开放平台「**答复日程邀请**」—— **`POST /v7/calendars/{calendar_id}/events/{event_id}/respond`**(默认 `primary`)。**必填**:`event_id`、`mod_type`(`normal` / `one` / `all`)、`response_status`(`accepted` / `declined` / `tentative`)、`which_day_time`(日程开始时刻的 **毫秒时间戳**,与文档一致)。用于接受/拒绝/暂定会议邀请。
|
|
19
|
+
- **与「通讯录」工具链的关系**:找人、发消息用 `wps_user_search` / `wps_message_send`;**日程不要**为解析 `wps_user_id` 去调 `wps_user_search` —— **`wps_user_id` = 入站 `SenderId`**。
|
|
20
|
+
- **授权**:首次无用户 token 时,工具会 **自动发送授权卡片**;返回 `needsAuth: true` 后,提示用户点击「前往授权」,完成后再重试。
|
|
21
|
+
- **部署**:用户 OAuth 回调地址由插件内置;须在开放平台「用户授权回调地址」登记**同一 URL**(见 `docs/user-oauth.md`)。
|
|
22
|
+
|
|
23
|
+
## 查询接口要点(与官方一致)
|
|
24
|
+
|
|
25
|
+
| 文档要求 | 插件行为 |
|
|
26
|
+
|----------|----------|
|
|
27
|
+
| `start_time` / `end_time` 为 **RFC3339** 字符串、URL 编码 | 工具参数传 **ISO8601/RFC3339** 字符串(如 `2026-04-22T14:00:00+08:00`),由 HTTP 客户端编码 |
|
|
28
|
+
| 时间窗 **0~31 天** | 超出则 **截断**到 31 天 |
|
|
29
|
+
| `page_size` 默认 **30** | 未传时使用 30 |
|
|
30
|
+
| 增量:`sync_token`、`anchor_time`、`with_cancelled` | 工具支持同名可选参数;若传 **`sync_token`**,不再自动补时间窗(与文档「增量同步」一致) |
|
|
31
|
+
|
|
32
|
+
## 快速索引:意图→工具
|
|
33
|
+
|
|
34
|
+
| 意图 | 工具 | 必填参数 |
|
|
35
|
+
|------|------|----------|
|
|
36
|
+
| 创建日程 / 会议 / 提醒 / 写入日历 | `wps_calendar_create` | `summary`, `start_time`(ISO) |
|
|
37
|
+
| 指定结束时间(可选) | 同上 | `end_time`(ISO;省略则默认 start + 1h) |
|
|
38
|
+
| 查看 / 列举主日历日程(逻辑事件) | `wps_calendar_list_events` | `wps_user_id` |
|
|
39
|
+
| **单条**日程完整详情(含重复规则 `recurrence`) | `wps_calendar_get_event` | `wps_user_id`, **`event_id`** |
|
|
40
|
+
| **单条**日程的参与者列表 | `wps_calendar_list_event_attendees` | `wps_user_id`, **`event_id`**(可选 `page_size`、`page_token`) |
|
|
41
|
+
| 主日历时间窗内**所有**日程的展开实例(日历级) | `wps_calendar_list_calendar_event_instances` | `wps_user_id` |
|
|
42
|
+
| **某一条**重复日程的展开实例(须已知 `event_id`) | `wps_calendar_list_event_instances` | `wps_user_id`, **`event_id`** |
|
|
43
|
+
| 接受 / 拒绝 / 暂定**日程邀请** | `wps_calendar_respond_invitation` | `wps_user_id`, **`event_id`**, **`mod_type`**, **`response_status`**, **`which_day_time`**(**毫秒**) |
|
|
44
|
+
| 指定列表时间窗(可选) | 上述列表工具 | `start_time`, `end_time`(**RFC3339**) |
|
|
45
|
+
|
|
46
|
+
## 核心约束
|
|
47
|
+
|
|
48
|
+
1. **创建**用 **`wps_calendar_create`**;**逻辑事件列表**用 **`wps_calendar_list_events`**;**单条日程详情**(官方「查询日程」)用 **`wps_calendar_get_event`**(必须 **`event_id`**);**参与者列表**(官方「获取日程参与者列表」)用 **`wps_calendar_list_event_attendees`**(必须 **`event_id`**);**答复邀请**用 **`wps_calendar_respond_invitation`**;**日历级实例扫描**用 **`wps_calendar_list_calendar_event_instances`**;**单条 event 的实例**(官方「查询日程实例」路径)用 **`wps_calendar_list_event_instances`**(必须 **`event_id`**)。禁止用本地文件或臆造列表冒充 API。
|
|
49
|
+
2. **禁止**生成 .ics、提醒脚本、txt、MEMORY.md 等替代方案。
|
|
50
|
+
3. **`wps_user_id`**:当前对话 **SenderId**。
|
|
51
|
+
4. **创建**的 `start_time` / `end_time`:事件体用 ISO。**事件列表 / 实例列表** 的 query `start_time` / `end_time`:须为 **RFC3339**。**答复邀请**的 `which_day_time` 为 **毫秒时间戳**(与文档一致);与 **`wps_message_list` 的 Unix 秒** 不同,勿混用。
|
|
52
|
+
5. 若 **`needsAuth: true`**:引导用户完成授权后再试。
|
|
53
|
+
|
|
54
|
+
## 调用示例
|
|
55
|
+
|
|
56
|
+
**创建**(省略 `end_time` 时默认 +1h):
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"summary": "站立会",
|
|
61
|
+
"start_time": "2026-04-23T10:00:00+08:00",
|
|
62
|
+
"wps_user_id": "<SenderId>"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**列举**(省略时间窗时插件默认约「过去 24h~未来 14d」,且不超过 31 天):
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"wps_user_id": "<SenderId>"
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**列举**(显式时间窗):
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"wps_user_id": "<SenderId>",
|
|
79
|
+
"start_time": "2026-04-01T00:00:00+08:00",
|
|
80
|
+
"end_time": "2026-04-07T23:59:59+08:00",
|
|
81
|
+
"page_size": 30
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**单条日程详情**(含 `recurrence`、会议链接等):
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"wps_user_id": "<SenderId>",
|
|
90
|
+
"event_id": "<来自列表的 id>"
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**参与者列表**(分页:`page_token` 填上一页返回的 `data.next_page_token`):
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"wps_user_id": "<SenderId>",
|
|
99
|
+
"event_id": "<来自列表的 id>",
|
|
100
|
+
"page_size": 30
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**答复日程邀请**(`which_day_time` 为该日程开始时间的 **毫秒时间戳**,可从 `wps_calendar_get_event` / 列表返回的 `start_time` 换算):
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"wps_user_id": "<SenderId>",
|
|
109
|
+
"event_id": "<来自列表的 id>",
|
|
110
|
+
"mod_type": "normal",
|
|
111
|
+
"response_status": "accepted",
|
|
112
|
+
"which_day_time": 1714233600000
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**单条重复日程的实例**(先用 `wps_calendar_list_events` 取 `id` 作为 `event_id`):
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"wps_user_id": "<SenderId>",
|
|
121
|
+
"event_id": "<来自列表的 id>",
|
|
122
|
+
"start_time": "2026-04-01T00:00:00+08:00",
|
|
123
|
+
"end_time": "2026-04-07T23:59:59+08:00"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 常见错误与排查
|
|
128
|
+
|
|
129
|
+
| 现象 | 可能原因 | 处理 |
|
|
130
|
+
|------|----------|------|
|
|
131
|
+
| `needsAuth: true` | 用户未授权 | 完成 OAuth 卡片后再试 |
|
|
132
|
+
| 403 / 无权限 | 应用未申请日历 delegated 权限 | 在开放平台补齐 `kso.calendar_events.read` / `readwrite` 等文档要求项 |
|
|
133
|
+
| 列表为空 | 时间窗与日程实际时间无交集 | 扩大 `start_time`~`end_time`(≤31 天) |
|
|
134
|
+
|
|
135
|
+
## 工具覆盖
|
|
136
|
+
|
|
137
|
+
- `wps_calendar_create` — 创建(`POST .../events/create`)
|
|
138
|
+
- `wps_calendar_list_events` — 逻辑事件列表(`GET /v7/calendars/primary/events`)
|
|
139
|
+
- `wps_calendar_get_event` — 查询单条日程(`GET /v7/calendars/primary/events/{event_id}`)
|
|
140
|
+
- `wps_calendar_list_event_attendees` — 参与者列表(`GET /v7/calendars/primary/events/{event_id}/attendees`)
|
|
141
|
+
- `wps_calendar_list_calendar_event_instances` — 日历级实例列表(`GET /v7/calendars/primary/event_instances`)
|
|
142
|
+
- `wps_calendar_list_event_instances` — 单条日程实例(`GET /v7/calendars/primary/events/{event_id}/event_instances`)
|
|
143
|
+
- `wps_calendar_respond_invitation` — 答复邀请(`POST /v7/calendars/primary/events/{event_id}/respond`)
|
|
144
|
+
|
|
145
|
+
## 安装说明
|
|
146
|
+
|
|
147
|
+
- 随插件 **`skills.directory`** 安装;**`tools.allow`** 须包含上述七工具;**`mcp.toolAllowlist`** 默认已含(见 `src/core/config.ts`)。
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wps-channel-rules
|
|
3
|
+
description: |
|
|
4
|
+
WPS 协作渠道输出规则。在 WPS 会话中始终生效。
|
|
5
|
+
alwaysActive: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# WPS 输出规则
|
|
9
|
+
|
|
10
|
+
## 写作风格
|
|
11
|
+
|
|
12
|
+
- 简短、对话式、低仪式感 — 像同事聊天,不像说明书
|
|
13
|
+
- 简短回答用普通句子,不必每次都用列表
|
|
14
|
+
- 直入正题,说完就停 — 不需要每次都加总结段落
|
|
15
|
+
|
|
16
|
+
## 注意事项
|
|
17
|
+
|
|
18
|
+
- WPS 消息支持 @人:使用 `<at id="N">名字</at>` 语法,N 从 1 开始递增
|
|
19
|
+
- WPS 消息最长 5000 字符
|
|
20
|
+
- 回复消息支持 text / rich_text / image 三种类型
|
|
21
|
+
|
|
22
|
+
## 用户发来的图片 / 文件
|
|
23
|
+
|
|
24
|
+
- 插件已自动将用户附件下载到本地临时文件(路径在 Body 中标注,如 `/tmp/openclaw-media/xxx.png`)。
|
|
25
|
+
- 用 **`read(<本地路径>)`** 读取已下载的临时文件 — 这是正确做法。
|
|
26
|
+
- **禁止**对附件「显示文件名」(如 `xiezuo....png`)直接调用 `read` —— 会 ENOENT。
|
|
27
|
+
- **禁止**用 `exec(curl ...)` 下载或上传媒体 — 直接用内置工具。
|
|
28
|
+
- **禁止**引导用户手工执行 `openclaw gateway start/pair`、`curl` 等命令。
|
|
29
|
+
|
|
30
|
+
## 发送图片 / 文件
|
|
31
|
+
|
|
32
|
+
- **推荐方式**:用 `message` 工具,`media` 参数传入本地路径;若运行环境支持省略 `to` 则自动回当前会话:`message(action="send", message="为您发回图片", media="<已下载路径>")`。否则必须显式:`to="user:<SenderId>"` 或 `to="chat:<chatId>"`(与 `src/index.ts` 注入的 `to` 必填规则一致)。插件会自动完成上传和发送。
|
|
33
|
+
- **备选方式**(需要精细控制时):先用 `wps_media_upload_base64` 上传得到 `storage_key`,再用 `wps_message_send(msg_type="image", content={"image":{"storage_key":"..."}})` 发送。
|
|
34
|
+
- 回当前会话:`receiver_id` / `to` 取自入站 **RawBody** 的 `chatId`(群)或 **SenderId**(单聊);**禁止**把 `SessionKey` 里 `:bot:` 后的 `AK…` 等当作聊天 id。
|
|
35
|
+
- **禁止**把文件路径当纯文本回复给用户。
|
|
36
|
+
|
|
37
|
+
## 日程 / 日历(WPS365)
|
|
38
|
+
|
|
39
|
+
- 用户要**创建日程、会议、日历提醒、写入日历**时:必须使用 **`wps_calendar_create`**;要**查看主日历逻辑事件列表**时:**`wps_calendar_list_events`**;要**查询单条日程详情**(官方「查询日程」,须 `event_id`)时:**`wps_calendar_get_event`**;要**查看某条日程的参与者列表**(须 `event_id`)时:**`wps_calendar_list_event_attendees`**;要**答复日程邀请**(接受/拒绝/暂定)时:**`wps_calendar_respond_invitation`**;要**日历级**查看时间窗内多条日程展开后的实例时:**`wps_calendar_list_calendar_event_instances`**;要按文档「查询日程实例」查看**单条 event** 的展开实例时:**`wps_calendar_list_event_instances`**(详见 **`wps-calendar`** skill)。**禁止**用 .ics、本地脚本或纯文字假装已创建/已查询。
|
|
40
|
+
- 用户要**创建 / 列举 / 查看 / 更新 / 更新状态 WPS 个人待办**时:创建 **`wps_todo_create_personal_task`**,列举 **`wps_todo_list_personal_tasks`**,详情 **`wps_todo_get_personal_task`**,更新 **`wps_todo_update_personal_task`**,状态更新 **`wps_todo_update_personal_task_status`**(详见 **`wps-todo`** skill)。**禁止**仅用本地备忘冒充已同步待办。
|
|
41
|
+
- 用户要**获取云文档盘列表**时:必须使用 **`wps_drive_list_drives`**(详见 **`wps-drive`** skill),按文档传 `allotee_type`(`user` / `group` / `app`),可选 `allotee_id`。用户要**新建文件(夹)**时:必须使用 **`wps_drive_create_file`**,按文档传 `drive_id`、`parent_id`、`file_type`、`name`。用户要**文档内容抽取**时:必须使用 **`wps_drive_extract_file_content`**,按文档传 `drive_id`、`file_id` 与可选 `format/include_elements/mode/task_id`。用户要**获取文件信息**时:必须使用 **`wps_drive_get_file_meta`**,按文档传 `file_id` 与可选 `with_permission/with_ext_attrs/with_drive`。用户要**文件搜索**时:必须使用 **`wps_drive_search_files`**,按文档传 `type`(`file_name`/`content`/`all`)和可选筛选条件。**禁止**离线拼接或复用旧缓存冒充实时查询结果。
|
|
42
|
+
- **`wps_user_id`** 使用入站 **SenderId**;不要为日程或待办去调用 `wps_user_search`。
|
|
43
|
+
|
|
44
|
+
## 云文件(cloud file)
|
|
45
|
+
|
|
46
|
+
- WPS 云文件只有 `link_url`,没有 `storage_key`,不能下载到本地。
|
|
47
|
+
- 转发云文件时,使用 `wps_message_send`,msg_type=`file`,content 使用 cloud 结构:
|
|
48
|
+
`wps_message_send(receiver_type="user", receiver_id="<id>", msg_type="file", content='{"file":{"type":"cloud","cloud":{"id":"...","link_id":"...","link_url":"..."}}}')`
|
|
49
|
+
- Body 中会提供完整的调用命令,直接复制即可。
|
|
50
|
+
- **禁止**对云文件使用 `message` 工具的 `media` 参数(没有本地路径)。
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wps-chat
|
|
3
|
+
description: |
|
|
4
|
+
WPS 会话与群管理。在需要创建单聊/群聊、列举会话、查会话详情、拉成员或确认应用是否在群内时使用。
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# WPS 会话:创建、查询与成员
|
|
8
|
+
|
|
9
|
+
## 执行前必读
|
|
10
|
+
|
|
11
|
+
- **P2P**:`type` 为 `p2p`,需提供**恰好 2 个用户的 user_id**。App Token 场景下应用没有 user_id,不能作为 P2P 一方——P2P 创建通常需要用户身份授权场景。
|
|
12
|
+
- **群聊**:`type` 为 `group`,当前操作者自动加入并成为**群主**;`member_ids` 只需传其他成员。
|
|
13
|
+
- **发群消息**:使用 `wps_message_send` 的 `receiver_type=chat`,`receiver_id` 传 `chat_id`。
|
|
14
|
+
- **发消息前建议**:用 `wps_chat_is_member` 确认应用在群内,避免权限错误。
|
|
15
|
+
|
|
16
|
+
## 快速索引:意图→工具
|
|
17
|
+
|
|
18
|
+
| 意图 | 工具 | 必填参数 |
|
|
19
|
+
|------|------|----------|
|
|
20
|
+
| 创建 P2P 或群 | `wps_chat_create` | `type`, `member_ids` |
|
|
21
|
+
| 分页列会话 | `wps_chat_list` | 无(可选分页) |
|
|
22
|
+
| 查看单个会话元数据 | `wps_chat_get` | `chat_id` |
|
|
23
|
+
| 列会话成员 | `wps_chat_members` | `chat_id` |
|
|
24
|
+
| 确认应用是否在群 | `wps_chat_is_member` | `chat_id` |
|
|
25
|
+
|
|
26
|
+
## 核心约束
|
|
27
|
+
|
|
28
|
+
- **`wps_chat_create`**
|
|
29
|
+
- `type`:`p2p` 或 `group`
|
|
30
|
+
- `member_ids`:用户 ID **数组**
|
|
31
|
+
- P2P:提供**恰好 2 个** user_id(无自动注入,两个都需要是真实用户)
|
|
32
|
+
- 群聊:传其他成员的 user_id(操作者自动加入并成为群主)
|
|
33
|
+
- `name`:可选,群名(仅 group 有效)
|
|
34
|
+
- 需要 `kso.chat.readwrite` 权限
|
|
35
|
+
- **`wps_chat_list`**
|
|
36
|
+
- `page_size`:默认 50,最大 100(WPS API 要求必传,已内置兜底)
|
|
37
|
+
- 支持 `page_token` 翻页
|
|
38
|
+
- **`wps_chat_get`**
|
|
39
|
+
- 通过 `chat_id` 查会话是否存在、类型、群名等
|
|
40
|
+
- **`wps_chat_members`**
|
|
41
|
+
- `page_size`:默认 50,最大 100(WPS API 要求必传,已内置兜底)
|
|
42
|
+
- 支持 `page_token` 翻页
|
|
43
|
+
- **`wps_chat_is_member`**
|
|
44
|
+
- 返回 `{ is_in_chat: true/false }`,用于发消息前的前置校验
|
|
45
|
+
|
|
46
|
+
## 使用场景示例
|
|
47
|
+
|
|
48
|
+
**1)创建 P2P**(提供两个用户 ID)
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"type": "p2p",
|
|
53
|
+
"member_ids": ["USER_ID_A", "USER_ID_B"]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**2)创建群聊**(操作者自动加入并为群主)
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"type": "group",
|
|
62
|
+
"member_ids": ["USER_ID_A", "USER_ID_B"],
|
|
63
|
+
"name": "项目协作群"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**3)列举最近会话**
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"page_size": 20
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**4)会话详情**
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"chat_id": "CHAT_ID"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**5)确认应用在群内**
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"chat_id": "CHAT_ID"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 常见错误与排查
|
|
92
|
+
|
|
93
|
+
| 现象 | 可能原因 | 处理 |
|
|
94
|
+
|------|----------|------|
|
|
95
|
+
| 建群失败 | 成员 ID 无效或成员数不足 | 确认 member_ids 均为有效用户 ID |
|
|
96
|
+
| P2P 创建失败 | 成员数不为 2(去重后)或已存在同对会话 | 确认提供恰好 2 个不同的 user_id |
|
|
97
|
+
| 发群消息无反应 | 应用未入群 | 用 `wps_chat_is_member` 确认 |
|
|
98
|
+
| chat_id 不存在 | 会话已解散 | 用 `wps_chat_get` 检查会话状态 |
|
|
99
|
+
|
|
100
|
+
## 工具覆盖
|
|
101
|
+
|
|
102
|
+
- `wps_chat_create` — 创建会话
|
|
103
|
+
- `wps_chat_list` — 列举会话
|
|
104
|
+
- `wps_chat_get` — 查看会话详情
|
|
105
|
+
- `wps_chat_members` — 列举会话成员
|
|
106
|
+
- `wps_chat_is_member` — 判断是否在群
|