weaver-work-cli 0.1.5 → 0.1.7
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/README.md +14 -9
- package/dist/cmd/skills/index.js +60 -0
- package/dist/internal/e10/auth/commands.js +48 -32
- package/dist/internal/e10/auth/session.js +44 -3
- package/dist/internal/e10/auth/xiaoe.js +363 -11
- package/dist/internal/e10/context.js +4 -2
- package/dist/internal/skills/detector.js +42 -0
- package/dist/internal/skills/install.js +50 -3
- package/dist/shortcuts/archive/render/search-format.js +12 -3
- package/dist/shortcuts/ebuilder-form/continuation.js +70 -0
- package/dist/shortcuts/ebuilder-form/errors.js +54 -0
- package/dist/shortcuts/ebuilder-form/host.js +1238 -0
- package/dist/shortcuts/ebuilder-form/index.js +108 -0
- package/dist/shortcuts/ebuilder-form/manifest.js +347 -0
- package/dist/shortcuts/ebuilder-form/operations/read.js +157 -0
- package/dist/shortcuts/ebuilder-form/operations/registry.js +56 -0
- package/dist/shortcuts/ebuilder-form/operations/shared.js +132 -0
- package/dist/shortcuts/ebuilder-form/operations/types.js +19 -0
- package/dist/shortcuts/ebuilder-form/operations/write.js +277 -0
- package/dist/shortcuts/ebuilder-form/operations.js +8 -0
- package/dist/shortcuts/ehr/operations/salary.js +2 -140
- package/dist/shortcuts/im/continuation.js +70 -0
- package/dist/shortcuts/{yimiaoban → im}/errors.js +14 -14
- package/dist/shortcuts/{yimiaoban → im}/host.js +26 -26
- package/dist/shortcuts/{yimiaoban → im}/index.js +42 -42
- package/dist/shortcuts/{yimiaoban → im}/manifest.js +7 -6
- package/dist/shortcuts/{yimiaoban → im}/operations/file-user.js +54 -41
- package/dist/shortcuts/{yimiaoban → im}/operations/group-read.js +46 -44
- package/dist/shortcuts/{yimiaoban → im}/operations/group-write.js +113 -66
- package/dist/shortcuts/{yimiaoban → im}/operations/msg-sync.js +164 -141
- package/dist/shortcuts/{yimiaoban → im}/operations/msg-write.js +47 -47
- package/dist/shortcuts/{yimiaoban → im}/operations/person.js +10 -10
- package/dist/shortcuts/{yimiaoban → im}/operations/registry.js +10 -8
- package/dist/shortcuts/{yimiaoban → im}/operations/session.js +82 -83
- package/dist/shortcuts/im/operations/shared.js +442 -0
- package/dist/shortcuts/{yimiaoban → im}/operations/types.js +1 -1
- package/dist/shortcuts/im/operations/user-remind.js +201 -0
- package/dist/shortcuts/{yimiaoban → im}/operations/write-util.js +7 -7
- package/dist/shortcuts/{yimiaoban → im}/operations.js +3 -3
- package/dist/shortcuts/index.js +10 -2
- package/dist/shortcuts/invoice/manifest.js +113 -10
- package/dist/shortcuts/invoice/operations/import.js +39 -14
- package/dist/shortcuts/invoice/operations/reim.js +38 -18
- package/dist/shortcuts/invoice/operations/shared.js +35 -6
- package/dist/shortcuts/jiuchuanhui/manifest.js +3 -3
- package/dist/shortcuts/jiuchuanhui/operations/registry.js +2 -2
- package/dist/shortcuts/{yimiaoban → okr}/continuation.js +10 -10
- package/dist/shortcuts/okr/errors.js +70 -0
- package/dist/shortcuts/okr/host.js +169 -0
- package/dist/shortcuts/okr/index.js +155 -0
- package/dist/shortcuts/okr/manifest.js +70 -0
- package/dist/shortcuts/okr/operations/link.js +305 -0
- package/dist/shortcuts/okr/operations/read.js +481 -0
- package/dist/shortcuts/okr/operations/registry.js +31 -0
- package/dist/shortcuts/okr/operations/shared.js +381 -0
- package/dist/shortcuts/okr/operations/types.js +88 -0
- package/dist/shortcuts/okr/operations/write.js +838 -0
- package/dist/shortcuts/okr/operations.js +8 -0
- package/dist/shortcuts/project/continuation.js +70 -0
- package/dist/shortcuts/project/errors.js +53 -0
- package/dist/shortcuts/project/host.js +160 -0
- package/dist/shortcuts/project/index.js +106 -0
- package/dist/shortcuts/project/manifest.js +36 -0
- package/dist/shortcuts/project/operations/read.js +551 -0
- package/dist/shortcuts/project/operations/registry.js +31 -0
- package/dist/shortcuts/project/operations/shared.js +68 -0
- package/dist/shortcuts/project/operations/types.js +39 -0
- package/dist/shortcuts/project/operations/write.js +266 -0
- package/dist/shortcuts/project/operations.js +8 -0
- package/dist/shortcuts/workflow/continuation.js +508 -0
- package/dist/shortcuts/workflow/endpoints.js +149 -0
- package/dist/shortcuts/workflow/errors.js +112 -0
- package/dist/shortcuts/workflow/host.js +224 -0
- package/dist/shortcuts/workflow/index.js +116 -0
- package/dist/shortcuts/workflow/manifest.js +30 -0
- package/dist/shortcuts/workflow/operations/form.js +4159 -0
- package/dist/shortcuts/workflow/operations/read.js +3778 -0
- package/dist/shortcuts/workflow/operations/registry.js +33 -0
- package/dist/shortcuts/workflow/operations/shared.js +167 -0
- package/dist/shortcuts/workflow/operations/types.js +44 -0
- package/dist/shortcuts/workflow/operations/write.js +1991 -0
- package/dist/shortcuts/workflow/operations.js +119 -0
- package/dist/shortcuts/workflow/state.js +182 -0
- package/docs/SKILL.md +5 -3
- package/docs/_catalog.md +10 -1
- package/docs/agent-invoice.md +2 -2
- package/docs/agent-skill-install.md +2 -2
- package/docs/e10-auth.md +3 -1
- package/docs/ebuilder-form.md +38 -0
- package/docs/im.md +104 -0
- package/docs/invoice.md +5 -5
- package/docs/okr.md +122 -0
- package/docs/operation-manual.md +10 -7
- package/docs/project.md +69 -0
- package/docs/skill-review-2026-09-19.md +68 -0
- package/package.json +3 -2
- package/scripts/package-skill.mjs +38 -11
- package/scripts/sync-connector-skills.mjs +172 -0
- package/skill-template/business-info.json +357 -16
- package/skill-template/domains/ebuilder-form.md +5 -0
- package/skill-template/domains/okr.md +18 -0
- package/skill-template/domains/shijingran.md +3 -0
- package/skill-template/domains/skill-maker.md +4 -4
- package/skill-template/domains/workflow.md +22 -0
- package/skill-template/domains/yepiaotong.md +4 -2
- package/skill-template/domains/yimiaoban.md +13 -10
- package/skill-template/product.json +5 -0
- package/skill-template/skill-template.md +1 -0
- package/skills/weaver-e10-calendar/SKILL.md +5 -1
- package/skills/weaver-e10-calendar/references/calendar-query.md +7 -0
- package/skills/weaver-e10-calendar/references/source-manifest.json +314 -32
- package/skills/weaver-e10-ebuilder-form/SKILL.md +123 -0
- package/skills/weaver-e10-ebuilder-form/references/context-routing.md +90 -0
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +86 -0
- package/skills/weaver-e10-ebuilder-form/references/disabled-capabilities.md +50 -0
- package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +100 -0
- package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +91 -0
- package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +74 -0
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +86 -0
- package/skills/weaver-e10-ebuilder-form/references/source-manifest.json +107 -0
- package/skills/weaver-e10-esb/SKILL.md +1 -1
- package/skills/weaver-e10-esb/references/source-manifest.json +15 -14
- package/skills/weaver-e10-hrm/SKILL.md +1 -1
- package/skills/weaver-e10-hrm/references/source-manifest.json +357 -38
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +22 -4
- package/skills/weaver-e10-jiuchuanhui/references/clue.md +4 -2
- package/skills/weaver-e10-jiuchuanhui/references/contact.md +1 -1
- package/skills/weaver-e10-jiuchuanhui/references/customer.md +3 -3
- package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +1 -1
- package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +10 -10
- package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +3 -3
- package/skills/weaver-e10-jiuchuanhui/references/sale.md +7 -7
- package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +3 -3
- package/skills/weaver-e10-jucailin/SKILL.md +2 -2
- package/skills/weaver-e10-mail/SKILL.md +22 -6
- package/skills/weaver-e10-meeting/SKILL.md +22 -1
- package/skills/weaver-e10-okr/SKILL.md +139 -0
- package/skills/weaver-e10-okr/references/okr-align.md +59 -0
- package/skills/weaver-e10-okr/references/okr-keyresult.md +68 -0
- package/skills/weaver-e10-okr/references/okr-link-routing.md +67 -0
- package/skills/weaver-e10-okr/references/okr-query.md +105 -0
- package/skills/weaver-e10-okr/references/okr-write.md +94 -0
- package/skills/weaver-e10-okr/references/source-manifest.json +672 -0
- package/skills/weaver-e10-plan/SKILL.md +3 -3
- package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
- package/skills/weaver-e10-qiyecheng/SKILL.md +21 -1
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +17 -17
- package/skills/weaver-e10-shared/SKILL.md +79 -11
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +41 -8
- package/skills/weaver-e10-shared/references/non-interactive-environment.md +78 -0
- package/skills/weaver-e10-shared/references/weaver-e10-installation.md +39 -0
- package/skills/weaver-e10-shijingran/SKILL.md +83 -0
- package/skills/weaver-e10-shijingran/references/field-resolution.md +105 -0
- package/skills/weaver-e10-shijingran/references/operations.md +154 -0
- package/skills/weaver-e10-shijingran/references/source-manifest.json +1380 -0
- package/skills/weaver-e10-shijingran/references/write-operations.md +90 -0
- package/skills/weaver-e10-skill-maker/SKILL.md +26 -9
- package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +39 -8
- package/skills/weaver-e10-skill-maker/references/detector-validation.md +25 -8
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +66 -5
- package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +86 -0
- package/skills/weaver-e10-skill-maker/references/source-update-detection.md +59 -5
- package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +16 -8
- package/skills/weaver-e10-wenshuding/SKILL.md +28 -4
- package/skills/weaver-e10-wenshuding/references/archive-search.md +14 -0
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +27 -26
- package/skills/weaver-e10-workflow/SKILL.md +250 -0
- package/skills/weaver-e10-workflow/references/source-manifest.json +1062 -0
- package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +96 -0
- package/skills/weaver-e10-workflow/references/workflow-batch.md +275 -0
- package/skills/weaver-e10-workflow/references/workflow-create.md +182 -0
- package/skills/weaver-e10-workflow/references/workflow-edit.md +106 -0
- package/skills/weaver-e10-workflow/references/workflow-memory.md +165 -0
- package/skills/weaver-e10-workflow/references/workflow-operate.md +153 -0
- package/skills/weaver-e10-workflow/references/workflow-query.md +821 -0
- package/skills/weaver-e10-workflow/references/workflow-share.md +117 -0
- package/skills/weaver-e10-workflow/references/workflow-view.md +189 -0
- package/skills/weaver-e10-yepiaotong/SKILL.md +28 -28
- package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +11 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-import.md +14 -8
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +9 -43
- package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +8 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +13 -17
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +6 -7
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +2 -2
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1155 -553
- package/skills/weaver-e10-yimiaoban/SKILL.md +56 -38
- package/skills/weaver-e10-yimiaoban/references/ding-write.md +8 -8
- package/skills/weaver-e10-yimiaoban/references/error-codes.md +16 -0
- package/skills/weaver-e10-yimiaoban/references/field-resolution.md +10 -10
- package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +12 -12
- package/skills/weaver-e10-yimiaoban/references/group-read.md +16 -16
- package/skills/weaver-e10-yimiaoban/references/group-write.md +17 -15
- package/skills/weaver-e10-yimiaoban/references/msg-read.md +21 -17
- package/skills/weaver-e10-yimiaoban/references/msg-write.md +10 -10
- package/skills/weaver-e10-yimiaoban/references/person.md +6 -6
- package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +15 -11
- package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +11 -10
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +2164 -154
- package/skills/weaver-e10-yimiaoban/references/user-remind.md +75 -0
- package/skills/weaver-e10-ziguanjia/SKILL.md +4 -2
- package/skills/weaver-e10-ziguanjia/references/source-manifest.json +99 -29
- package/tools/weaver-skill-detector-1.0.13/SKILL.md +253 -0
- package/tools/weaver-skill-detector-1.0.13/_meta.json +6 -0
- package/tools/weaver-skill-detector-1.0.13/references/checklist.md +298 -0
- package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +4190 -0
- package/dist/shortcuts/yimiaoban/operations/shared.js +0 -236
- package/docs/yimiaoban.md +0 -86
- package/skills/weaver-e10-calendar/product.json +0 -8
- package/skills/weaver-e10-esb/product.json +0 -8
- package/skills/weaver-e10-hrm/product.json +0 -8
- package/skills/weaver-e10-jiuchuanhui/product.json +0 -8
- package/skills/weaver-e10-jucailin/product.json +0 -8
- package/skills/weaver-e10-mail/product.json +0 -8
- package/skills/weaver-e10-meeting/product.json +0 -8
- package/skills/weaver-e10-plan/product.json +0 -8
- package/skills/weaver-e10-qiyecheng/product.json +0 -8
- package/skills/weaver-e10-skill-maker/product.json +0 -8
- package/skills/weaver-e10-wenshuding/product.json +0 -8
- package/skills/weaver-e10-yepiaotong/product.json +0 -8
- package/skills/weaver-e10-yepiaotong/references/invoice-red.md +0 -261
- package/skills/weaver-e10-yimiaoban/product.json +0 -8
- package/skills/weaver-e10-ziguanjia/product.json +0 -8
- /package/dist/shortcuts/{yimiaoban → im}/operations/msg-parse.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { imValidationError } from '../errors.js';
|
|
4
4
|
import { schemaOf, } from './types.js';
|
|
5
5
|
import { assertImOk, compact, extractGroupMembers, str } from './shared.js';
|
|
6
6
|
import { fileObjToFile, fileObjToImg, makeWritePair } from './write-util.js';
|
|
@@ -8,7 +8,7 @@ import { fileObjToFile, fileObjToImg, makeWritePair } from './write-util.js';
|
|
|
8
8
|
function assertLocalFile(pathValue, field) {
|
|
9
9
|
const abs = resolve(String(pathValue ?? ''));
|
|
10
10
|
if (!existsSync(abs))
|
|
11
|
-
throw
|
|
11
|
+
throw imValidationError('file_not_found', `${field} 文件不存在: ${abs}`);
|
|
12
12
|
return abs;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
@@ -21,21 +21,21 @@ function normalizeContent(args) {
|
|
|
21
21
|
const imgPath = args.img || args.imgPath ? String(args.img || args.imgPath) : undefined;
|
|
22
22
|
const filePath = args.file || args.filePath ? String(args.file || args.filePath) : undefined;
|
|
23
23
|
if (!txt && !imgPath && !filePath) {
|
|
24
|
-
throw
|
|
24
|
+
throw imValidationError('content_required', 'txt / img / file 至少提供一种(空白文本不算内容,禁止发送空白消息)');
|
|
25
25
|
}
|
|
26
26
|
if (imgPath && filePath) {
|
|
27
|
-
throw
|
|
27
|
+
throw imValidationError('content_conflict', 'img 与 file 不能同时提供(一次发一种媒体)');
|
|
28
28
|
}
|
|
29
29
|
return { txt, imgPath, filePath };
|
|
30
30
|
}
|
|
31
31
|
// ── 发单聊 ──
|
|
32
32
|
const sendSinglePair = makeWritePair({
|
|
33
|
-
action: '
|
|
33
|
+
action: 'im.msg.send.single',
|
|
34
34
|
async plan(args, env) {
|
|
35
35
|
const toUid = str(args.toUid);
|
|
36
36
|
const toCid = str(args.toCid);
|
|
37
37
|
if (!toUid || !toCid || toUid === '0' || toCid === '0') {
|
|
38
|
-
throw
|
|
38
|
+
throw imValidationError('id_invalid', 'toUid/toCid 必须非 0');
|
|
39
39
|
}
|
|
40
40
|
const content = normalizeContent(args);
|
|
41
41
|
const summary = {
|
|
@@ -79,7 +79,7 @@ const sendSinglePair = makeWritePair({
|
|
|
79
79
|
method: 'POST',
|
|
80
80
|
path: '/api/em/msg/executeIm/send/sendSingleMsg',
|
|
81
81
|
body,
|
|
82
|
-
operation: '
|
|
82
|
+
operation: 'im.msg.send.single',
|
|
83
83
|
});
|
|
84
84
|
assertImOk(res, '发送单聊消息');
|
|
85
85
|
return { toUid: plan.toUid, toCid: plan.toCid, sent: true };
|
|
@@ -87,11 +87,11 @@ const sendSinglePair = makeWritePair({
|
|
|
87
87
|
});
|
|
88
88
|
// ── 发群聊 ──
|
|
89
89
|
const sendGroupPair = makeWritePair({
|
|
90
|
-
action: '
|
|
90
|
+
action: 'im.msg.send.group',
|
|
91
91
|
async plan(args, env) {
|
|
92
92
|
const groupId = str(args.groupId);
|
|
93
93
|
if (!groupId || groupId === '0')
|
|
94
|
-
throw
|
|
94
|
+
throw imValidationError('id_invalid', 'groupId 必须非 0');
|
|
95
95
|
const content = normalizeContent(args);
|
|
96
96
|
const summary = { action: '发送群聊消息', groupId, hasTxt: Boolean(content.txt), hasImg: Boolean(content.imgPath), hasFile: Boolean(content.filePath) };
|
|
97
97
|
const snapshot = { groupId };
|
|
@@ -127,7 +127,7 @@ const sendGroupPair = makeWritePair({
|
|
|
127
127
|
method: 'POST',
|
|
128
128
|
path: '/api/em/msg/executeIm/send/sendGroupMsg',
|
|
129
129
|
body,
|
|
130
|
-
operation: '
|
|
130
|
+
operation: 'im.msg.send.group',
|
|
131
131
|
});
|
|
132
132
|
assertImOk(res, '发送群聊消息');
|
|
133
133
|
return { groupId: plan.groupId, sent: true };
|
|
@@ -160,21 +160,21 @@ function formatWithdrawInterval(seconds) {
|
|
|
160
160
|
return rest > 0 ? `${minutes} 分钟 ${rest} 秒` : `${minutes} 分钟`;
|
|
161
161
|
}
|
|
162
162
|
const withdrawPair = makeWritePair({
|
|
163
|
-
action: '
|
|
163
|
+
action: 'im.msg.withdraw',
|
|
164
164
|
async plan(args, env) {
|
|
165
165
|
const type = String(args.type || 'single');
|
|
166
166
|
if (type !== 'single' && type !== 'group')
|
|
167
|
-
throw
|
|
167
|
+
throw imValidationError('type_invalid', 'type 必须是 single 或 group');
|
|
168
168
|
const msgid = str(args.msgid);
|
|
169
169
|
if (!msgid || msgid === '0')
|
|
170
|
-
throw
|
|
170
|
+
throw imValidationError('id_invalid', 'msgid 必须非 0');
|
|
171
171
|
const snapshot = { type, msgid };
|
|
172
172
|
let source;
|
|
173
173
|
if (type === 'single') {
|
|
174
174
|
const toUid = str(args.toUid);
|
|
175
175
|
const toCid = str(args.toCid);
|
|
176
176
|
if (!toUid || !toCid || toUid === '0' || toCid === '0')
|
|
177
|
-
throw
|
|
177
|
+
throw imValidationError('id_invalid', 'toUid/toCid 必须非 0(撤回单聊消息)');
|
|
178
178
|
snapshot.toUid = toUid;
|
|
179
179
|
snapshot.toCid = toCid;
|
|
180
180
|
source = { flag: 0, user: { cid: toCid, uid: toUid } };
|
|
@@ -182,7 +182,7 @@ const withdrawPair = makeWritePair({
|
|
|
182
182
|
else {
|
|
183
183
|
const groupId = str(args.groupId);
|
|
184
184
|
if (!groupId || groupId === '0')
|
|
185
|
-
throw
|
|
185
|
+
throw imValidationError('id_invalid', 'groupId 必须非 0');
|
|
186
186
|
snapshot.groupId = groupId;
|
|
187
187
|
source = { flag: 1, group_id: groupId };
|
|
188
188
|
}
|
|
@@ -217,20 +217,20 @@ const withdrawPair = makeWritePair({
|
|
|
217
217
|
method: 'POST',
|
|
218
218
|
path: '/api/em/msg/executeIm/msg/makeMsgWithdraw',
|
|
219
219
|
body,
|
|
220
|
-
operation: '
|
|
220
|
+
operation: 'im.msg.withdraw',
|
|
221
221
|
});
|
|
222
222
|
const actCode = Number(res?.data?.actionMsg?.code ?? res?.code ?? -1);
|
|
223
223
|
const timeOut = findWithdrawTimeOut(res);
|
|
224
224
|
const interval = timeOut !== null ? formatWithdrawInterval(timeOut) : '';
|
|
225
225
|
if (actCode === 1505) {
|
|
226
|
-
throw
|
|
226
|
+
throw imValidationError('withdraw_timeout', `撤销超时${interval ? `(撤回时限 ${interval})` : '(发出超过约 2 分钟)'}:消息发送已超过可撤回时限,无法撤回`, { code: 1505, details: interval ? { withdrawInterval: interval } : undefined });
|
|
227
227
|
}
|
|
228
228
|
if (actCode === 1506)
|
|
229
|
-
throw
|
|
229
|
+
throw imValidationError('withdraw_not_owner', '消息不是自己发送的,无法撤回', { code: 1506 });
|
|
230
230
|
if (actCode === 1507)
|
|
231
|
-
throw
|
|
231
|
+
throw imValidationError('withdraw_edit_timeout', '编辑撤回超时', { code: 1507 });
|
|
232
232
|
if (actCode !== 0)
|
|
233
|
-
throw
|
|
233
|
+
throw imValidationError('withdraw_failed', `撤回失败(code=${actCode})`, { code: actCode });
|
|
234
234
|
return {
|
|
235
235
|
msgid: plan.msgid,
|
|
236
236
|
withdrawn: true,
|
|
@@ -240,21 +240,21 @@ const withdrawPair = makeWritePair({
|
|
|
240
240
|
});
|
|
241
241
|
// ── 群置顶/取消置顶 ──
|
|
242
242
|
const topSetPair = makeWritePair({
|
|
243
|
-
action: '
|
|
243
|
+
action: 'im.msg.top.set',
|
|
244
244
|
async plan(args, env) {
|
|
245
245
|
const groupId = str(args.groupId);
|
|
246
246
|
if (!groupId || groupId === '0')
|
|
247
|
-
throw
|
|
247
|
+
throw imValidationError('id_invalid', 'groupId 必须非 0');
|
|
248
248
|
const msgid = str(args.msgid);
|
|
249
249
|
if (!msgid || msgid === '0')
|
|
250
|
-
throw
|
|
250
|
+
throw imValidationError('id_invalid', 'msgid 必须非 0');
|
|
251
251
|
let type;
|
|
252
252
|
if (args.cancel === true)
|
|
253
253
|
type = 2;
|
|
254
254
|
else if (args.type !== undefined) {
|
|
255
255
|
type = Number(args.type);
|
|
256
256
|
if (type !== 1 && type !== 2)
|
|
257
|
-
throw
|
|
257
|
+
throw imValidationError('type_invalid', 'type 必须是 1(置顶)或 2(取消置顶)');
|
|
258
258
|
}
|
|
259
259
|
else
|
|
260
260
|
type = 1;
|
|
@@ -269,7 +269,7 @@ const topSetPair = makeWritePair({
|
|
|
269
269
|
method: 'POST',
|
|
270
270
|
path: '/api/em/msg/executeIm/msg/setGroupTopMsg',
|
|
271
271
|
body,
|
|
272
|
-
operation: '
|
|
272
|
+
operation: 'im.msg.top.set',
|
|
273
273
|
});
|
|
274
274
|
assertImOk(res, plan.type === 1 ? '置顶消息' : '取消置顶');
|
|
275
275
|
return { groupId: plan.groupId, msgid: plan.msgid, type: plan.type };
|
|
@@ -277,24 +277,24 @@ const topSetPair = makeWritePair({
|
|
|
277
277
|
});
|
|
278
278
|
// ── 必达 sendDing ──
|
|
279
279
|
const dingSendPair = makeWritePair({
|
|
280
|
-
action: '
|
|
280
|
+
action: 'im.ding.send',
|
|
281
281
|
async plan(args, env) {
|
|
282
282
|
const groupId = args.groupId !== undefined && args.groupId !== '' ? str(args.groupId) : '';
|
|
283
283
|
const toUid = args.toUid !== undefined && args.toUid !== '' ? str(args.toUid) : '';
|
|
284
284
|
const convertMsgid = args.convertMsgid !== undefined && args.convertMsgid !== '' ? str(args.convertMsgid) : '';
|
|
285
285
|
if (!groupId && !toUid)
|
|
286
|
-
throw
|
|
286
|
+
throw imValidationError('target_required', 'groupId(群必达)与 toUid(单聊必达)至少其一');
|
|
287
287
|
if (groupId && groupId === '0')
|
|
288
|
-
throw
|
|
288
|
+
throw imValidationError('id_invalid', 'groupId 必须非 0');
|
|
289
289
|
const txtRaw = args.txt !== undefined && args.txt !== null ? String(args.txt) : '';
|
|
290
290
|
const txt = txtRaw.trim() !== '' ? txtRaw : '';
|
|
291
291
|
if (!convertMsgid && !txt)
|
|
292
|
-
throw
|
|
292
|
+
throw imValidationError('content_required', '普通必达需 txt;转必达需 convertMsgid');
|
|
293
293
|
if (args.unreadOnly === true && !groupId) {
|
|
294
|
-
throw
|
|
294
|
+
throw imValidationError('unread_only_group_only', 'unreadOnly 仅支持群聊转必达(需提供 groupId)');
|
|
295
295
|
}
|
|
296
296
|
if (!groupId && convertMsgid && !str(args.toCid)) {
|
|
297
|
-
throw
|
|
297
|
+
throw imValidationError('to_cid_required', '单聊转必达需提供 toCid(用于按消息 id 拉取源消息)');
|
|
298
298
|
}
|
|
299
299
|
const summary = {
|
|
300
300
|
action: convertMsgid ? '已有消息转必达' : '发送必达消息',
|
|
@@ -331,7 +331,7 @@ const dingSendPair = makeWritePair({
|
|
|
331
331
|
const map = await env.host.resolveUsersByIds(requested);
|
|
332
332
|
const failed = requested.filter((uid) => !map[uid]?.cid || map[uid].cid === '0');
|
|
333
333
|
if (failed.length && snapshot.removeFailed !== true) {
|
|
334
|
-
throw
|
|
334
|
+
throw imValidationError('members_resolve_failed', `指定接收人信息获取失败(cid 缺失或为 0):${failed.map((uid) => map[uid]?.name || uid).join('、')};确认跳过请传 removeFailed:true`, { details: failed });
|
|
335
335
|
}
|
|
336
336
|
for (const uid of requested) {
|
|
337
337
|
const cid = map[uid]?.cid;
|
|
@@ -346,7 +346,7 @@ const dingSendPair = makeWritePair({
|
|
|
346
346
|
method: 'POST',
|
|
347
347
|
path: '/api/em/msg/executeIm/group/syncGroupReadStatus',
|
|
348
348
|
body: { trans_id: 0, group_id: groupId, msgid: convertMsgid || '0' },
|
|
349
|
-
operation: '
|
|
349
|
+
operation: 'im.ding.send.unread',
|
|
350
350
|
});
|
|
351
351
|
const readDatas = readRes?.data?.data?.datas || [];
|
|
352
352
|
const unread = readDatas.filter((d) => Number(d.status) === 0);
|
|
@@ -354,7 +354,7 @@ const dingSendPair = makeWritePair({
|
|
|
354
354
|
...new Set(unread.map((d) => String(d?.user?.uid)).filter((uid) => Boolean(uid) && uid !== myUid)),
|
|
355
355
|
];
|
|
356
356
|
if (uidArr.length === 0) {
|
|
357
|
-
throw
|
|
357
|
+
throw imValidationError('unread_empty', '群内没有未读人员(unreadOnly=true 不自动回退全员):请确认改发全体成员、指定人员,或放弃发送');
|
|
358
358
|
}
|
|
359
359
|
const map = await env.host.resolveUsersByIds(uidArr);
|
|
360
360
|
for (const uid of uidArr) {
|
|
@@ -368,7 +368,7 @@ const dingSendPair = makeWritePair({
|
|
|
368
368
|
method: 'POST',
|
|
369
369
|
path: '/api/em/msg/executeIm/group/getGroupUsers',
|
|
370
370
|
body: { group_id: groupId, type: 0, sync_type: 0, member_mask: 6, client_uc: '0' },
|
|
371
|
-
operation: '
|
|
371
|
+
operation: 'im.ding.send.members',
|
|
372
372
|
});
|
|
373
373
|
const uidArr = [...new Set(extractGroupMembers(memRes?.data?.data)
|
|
374
374
|
.map((m) => String(m?.uid))
|
|
@@ -381,7 +381,7 @@ const dingSendPair = makeWritePair({
|
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
383
|
if (groupUsers.length === 0) {
|
|
384
|
-
throw
|
|
384
|
+
throw imValidationError('members_empty', '群内没有可接收必达消息的成员(已排除本人;指定/未读人员可能为空)');
|
|
385
385
|
}
|
|
386
386
|
snapshot.groupUsers = groupUsers;
|
|
387
387
|
snapshot.receiveUserIds = groupUsers.map((u) => u.uid).join(',');
|
|
@@ -416,16 +416,16 @@ const dingSendPair = makeWritePair({
|
|
|
416
416
|
? { trans_id: 0, dev: 4, type: 0, enc_type: 0, datas: [{ group_id: plan.groupId, start: plan.convertMsgid, end: '0', max_num: 1 }] }
|
|
417
417
|
: { trans_id: 0, dev: 4, enc_type: 0, datas: [{ from_cid: plan.toCid, from_uid: plan.toUid, start: plan.convertMsgid, end: '0', max_num: 1 }] };
|
|
418
418
|
const sourcePath = plan.groupId ? '/api/em/msg/executeIm/chat/syncGroupMsg' : '/api/em/msg/executeIm/msg/syncSingleMsg';
|
|
419
|
-
const srcRes = await env.host.request({ method: 'POST', path: sourcePath, body: sourceReq, operation: '
|
|
419
|
+
const srcRes = await env.host.request({ method: 'POST', path: sourcePath, body: sourceReq, operation: 'im.ding.send.source' });
|
|
420
420
|
const srcMsg = srcRes?.data?.data?.datas?.[0]?.datas?.[0] ?? srcRes?.data?.data?.datas?.[0];
|
|
421
421
|
if (!srcMsg?.msg)
|
|
422
|
-
throw
|
|
422
|
+
throw imValidationError('source_not_found', `未找到源消息 ${plan.convertMsgid}`);
|
|
423
423
|
let msgObj;
|
|
424
424
|
try {
|
|
425
425
|
msgObj = typeof srcMsg.msg === 'string' ? JSON.parse(srcMsg.msg) : srcMsg.msg;
|
|
426
426
|
}
|
|
427
427
|
catch {
|
|
428
|
-
throw
|
|
428
|
+
throw imValidationError('source_invalid', '源消息内容无法解析');
|
|
429
429
|
}
|
|
430
430
|
const mtype = Number(msgObj.type ?? 0);
|
|
431
431
|
let tag;
|
|
@@ -481,7 +481,7 @@ const dingSendPair = makeWritePair({
|
|
|
481
481
|
groupUsers = Array.isArray(plan.groupUsers) ? plan.groupUsers : [];
|
|
482
482
|
receiveUserIds = str(plan.receiveUserIds) || groupUsers.map((u) => u.uid).join(',');
|
|
483
483
|
if (!receiveUserIds)
|
|
484
|
-
throw
|
|
484
|
+
throw imValidationError('members_empty', '群内没有可接收必达消息的成员');
|
|
485
485
|
}
|
|
486
486
|
else {
|
|
487
487
|
targetType = 1;
|
|
@@ -507,11 +507,11 @@ const dingSendPair = makeWritePair({
|
|
|
507
507
|
method: 'POST',
|
|
508
508
|
path: '/api/em/msg/createDing',
|
|
509
509
|
body,
|
|
510
|
-
operation: '
|
|
510
|
+
operation: 'im.ding.send',
|
|
511
511
|
});
|
|
512
512
|
const code = Number(res?.code ?? -1);
|
|
513
513
|
if (code !== 200 || !res?.status) {
|
|
514
|
-
throw
|
|
514
|
+
throw imValidationError('ding_failed', `必达发送失败:code=${code} msg=${res?.msg ?? ''}`, { code });
|
|
515
515
|
}
|
|
516
516
|
return { id: str(res?.data?.id ?? ''), msg: res?.data?.msg ?? '' };
|
|
517
517
|
},
|
|
@@ -552,33 +552,33 @@ function buildMsgWriteDefinition(name, method, summary, inputProps, pair) {
|
|
|
552
552
|
];
|
|
553
553
|
}
|
|
554
554
|
const msgWriteOps = [
|
|
555
|
-
...buildMsgWriteDefinition('
|
|
555
|
+
...buildMsgWriteDefinition('im.msg.send.single', 'msg.send.single', '发送单聊消息(文本/图片/文件)', {
|
|
556
556
|
toUid: { type: 'string', pattern: '^\\d+$', description: '接收人 uid' },
|
|
557
557
|
toCid: { type: 'string', pattern: '^\\d+$', description: '接收人 cid' },
|
|
558
558
|
txt: { type: 'string', description: '文本内容' },
|
|
559
559
|
img: { type: 'string', description: '本地图片路径(发送前会上传到 E10 文件服务)' },
|
|
560
560
|
file: { type: 'string', description: '本地文件路径' },
|
|
561
561
|
}, sendSinglePair),
|
|
562
|
-
...buildMsgWriteDefinition('
|
|
562
|
+
...buildMsgWriteDefinition('im.msg.send.group', 'msg.send.group', '发送群聊消息(文本/图片/文件)', {
|
|
563
563
|
groupId: { type: 'string', pattern: '^\\d+$', description: '群 id' },
|
|
564
564
|
txt: { type: 'string', description: '文本内容' },
|
|
565
565
|
img: { type: 'string', description: '本地图片路径' },
|
|
566
566
|
file: { type: 'string', description: '本地文件路径' },
|
|
567
567
|
}, sendGroupPair),
|
|
568
|
-
...buildMsgWriteDefinition('
|
|
568
|
+
...buildMsgWriteDefinition('im.msg.withdraw', 'msg.withdraw', '撤回消息(单聊/群聊,限本人 2 分钟内)', {
|
|
569
569
|
type: { type: 'string', enum: ['single', 'group'], description: 'single 或 group' },
|
|
570
570
|
msgid: { type: 'string', pattern: '^\\d+$', description: '消息 id(ser_msgid)' },
|
|
571
571
|
toUid: { type: 'string', pattern: '^\\d+$', description: '单聊:对方 uid' },
|
|
572
572
|
toCid: { type: 'string', pattern: '^\\d+$', description: '单聊:对方 cid' },
|
|
573
573
|
groupId: { type: 'string', pattern: '^\\d+$', description: '群聊:群 id' },
|
|
574
574
|
}, withdrawPair),
|
|
575
|
-
...buildMsgWriteDefinition('
|
|
575
|
+
...buildMsgWriteDefinition('im.msg.top.set', 'msg.top.set', '群消息置顶 / 取消置顶', {
|
|
576
576
|
groupId: { type: 'string', pattern: '^\\d+$', description: '群 id' },
|
|
577
577
|
msgid: { type: 'string', pattern: '^\\d+$', description: '目标消息 id' },
|
|
578
578
|
type: { type: 'integer', enum: [1, 2], description: '1 置顶 / 2 取消' },
|
|
579
579
|
cancel: { type: 'boolean', description: '等价 type=2' },
|
|
580
580
|
}, topSetPair),
|
|
581
|
-
...buildMsgWriteDefinition('
|
|
581
|
+
...buildMsgWriteDefinition('im.ding.send', 'ding.send', '发送必达消息 / 已有消息转必达(createDing)', {
|
|
582
582
|
groupId: { type: 'string', pattern: '^\\d+$', description: '群场景群 id' },
|
|
583
583
|
toUid: { type: 'string', pattern: '^\\d+$', description: '单聊场景对方 uid' },
|
|
584
584
|
toCid: { type: 'string', pattern: '^\\d+$', description: '单聊转必达对方 cid' },
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { READ, schemaOf,
|
|
1
|
+
import { imValidationError } from '../errors.js';
|
|
2
|
+
import { READ, schemaOf, imSuccess, } from './types.js';
|
|
3
3
|
import { splitIds } from './shared.js';
|
|
4
4
|
/** 姓名 → 人员解析(数据采集走 hrm,不用 IM 群成员姓名接口)。 */
|
|
5
5
|
const personResolve = {
|
|
6
|
-
name: '
|
|
6
|
+
name: 'im.person.resolve',
|
|
7
7
|
resource: 'person',
|
|
8
8
|
method: 'person.resolve',
|
|
9
|
-
action: '
|
|
9
|
+
action: 'im.person.resolve',
|
|
10
10
|
summary: '按姓名/工号/手机/邮箱模糊查询在职员工,返回 uid/cid/部门等(供发消息与成员解析)',
|
|
11
11
|
capability: 'person',
|
|
12
12
|
risk: READ,
|
|
@@ -16,7 +16,7 @@ const personResolve = {
|
|
|
16
16
|
handler: async (args, { host }) => {
|
|
17
17
|
const name = String(args.name ?? '').trim();
|
|
18
18
|
if (!name)
|
|
19
|
-
throw
|
|
19
|
+
throw imValidationError('name_required', 'name 必填');
|
|
20
20
|
const employees = await host.searchEmployeeByName(name);
|
|
21
21
|
const rows = employees.map((e) => ({
|
|
22
22
|
uid: e.uid,
|
|
@@ -30,7 +30,7 @@ const personResolve = {
|
|
|
30
30
|
cid: e.cid,
|
|
31
31
|
ok: Boolean(e.uid && e.cid && e.uid !== '0' && e.cid !== '0'),
|
|
32
32
|
}));
|
|
33
|
-
return
|
|
33
|
+
return imSuccess('im.person.resolve', {
|
|
34
34
|
total: rows.length,
|
|
35
35
|
keyword: name,
|
|
36
36
|
employees: rows,
|
|
@@ -39,10 +39,10 @@ const personResolve = {
|
|
|
39
39
|
};
|
|
40
40
|
/** uid 批量解析(emp-by-ids 语义)。 */
|
|
41
41
|
const personResolveByIds = {
|
|
42
|
-
name: '
|
|
42
|
+
name: 'im.person.resolveByIds',
|
|
43
43
|
resource: 'person',
|
|
44
44
|
method: 'person.resolveByIds',
|
|
45
|
-
action: '
|
|
45
|
+
action: 'im.person.resolveByIds',
|
|
46
46
|
summary: '按 uid 列表批量解析人员姓名/部门/岗位/cid(一次最多 100,超出自动分批)',
|
|
47
47
|
capability: 'person',
|
|
48
48
|
risk: READ,
|
|
@@ -52,9 +52,9 @@ const personResolveByIds = {
|
|
|
52
52
|
handler: async (args, { host }) => {
|
|
53
53
|
const ids = Array.isArray(args.ids) ? args.ids.map((x) => String(x)).filter(Boolean) : [];
|
|
54
54
|
if (ids.length === 0)
|
|
55
|
-
throw
|
|
55
|
+
throw imValidationError('ids_required', 'ids 不能为空');
|
|
56
56
|
const map = await host.resolveUsersByIds(ids);
|
|
57
|
-
return
|
|
57
|
+
return imSuccess('im.person.resolveByIds', {
|
|
58
58
|
requested: ids.length,
|
|
59
59
|
resolved: Object.keys(map).length,
|
|
60
60
|
employees: ids
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { imValidationError } from '../errors.js';
|
|
2
2
|
import { groupReadOperations } from './group-read.js';
|
|
3
3
|
import { groupWriteOperations } from './group-write.js';
|
|
4
4
|
import { msgReadOperations } from './msg-sync.js';
|
|
@@ -6,6 +6,7 @@ import { msgWriteOperations } from './msg-write.js';
|
|
|
6
6
|
import { sessionOperations } from './session.js';
|
|
7
7
|
import { personOperations } from './person.js';
|
|
8
8
|
import { fileUserOperations } from './file-user.js';
|
|
9
|
+
import { userRemindOperations } from './user-remind.js';
|
|
9
10
|
function buildRegistry() {
|
|
10
11
|
const registry = new Map();
|
|
11
12
|
const definitions = [
|
|
@@ -16,23 +17,24 @@ function buildRegistry() {
|
|
|
16
17
|
...groupWriteOperations,
|
|
17
18
|
...sessionOperations,
|
|
18
19
|
...fileUserOperations,
|
|
20
|
+
...userRemindOperations,
|
|
19
21
|
];
|
|
20
22
|
for (const definition of definitions) {
|
|
21
23
|
if (registry.has(definition.name)) {
|
|
22
|
-
throw new Error(`duplicate
|
|
24
|
+
throw new Error(`duplicate im operation: ${definition.name}`);
|
|
23
25
|
}
|
|
24
26
|
registry.set(definition.name, definition);
|
|
25
27
|
}
|
|
26
28
|
return registry;
|
|
27
29
|
}
|
|
28
|
-
const
|
|
29
|
-
export function
|
|
30
|
-
return [...
|
|
30
|
+
const imOperationRegistry = buildRegistry();
|
|
31
|
+
export function imOperationDefinitions() {
|
|
32
|
+
return [...imOperationRegistry.values()];
|
|
31
33
|
}
|
|
32
|
-
export function
|
|
33
|
-
const definition =
|
|
34
|
+
export function getImOperation(operation) {
|
|
35
|
+
const definition = imOperationRegistry.get(operation);
|
|
34
36
|
if (!definition) {
|
|
35
|
-
throw
|
|
37
|
+
throw imValidationError('operation_unknown', `易秒办不支持操作:${operation}`);
|
|
36
38
|
}
|
|
37
39
|
return definition;
|
|
38
40
|
}
|