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.
Files changed (225) hide show
  1. package/README.md +14 -9
  2. package/dist/cmd/skills/index.js +60 -0
  3. package/dist/internal/e10/auth/commands.js +48 -32
  4. package/dist/internal/e10/auth/session.js +44 -3
  5. package/dist/internal/e10/auth/xiaoe.js +363 -11
  6. package/dist/internal/e10/context.js +4 -2
  7. package/dist/internal/skills/detector.js +42 -0
  8. package/dist/internal/skills/install.js +50 -3
  9. package/dist/shortcuts/archive/render/search-format.js +12 -3
  10. package/dist/shortcuts/ebuilder-form/continuation.js +70 -0
  11. package/dist/shortcuts/ebuilder-form/errors.js +54 -0
  12. package/dist/shortcuts/ebuilder-form/host.js +1238 -0
  13. package/dist/shortcuts/ebuilder-form/index.js +108 -0
  14. package/dist/shortcuts/ebuilder-form/manifest.js +347 -0
  15. package/dist/shortcuts/ebuilder-form/operations/read.js +157 -0
  16. package/dist/shortcuts/ebuilder-form/operations/registry.js +56 -0
  17. package/dist/shortcuts/ebuilder-form/operations/shared.js +132 -0
  18. package/dist/shortcuts/ebuilder-form/operations/types.js +19 -0
  19. package/dist/shortcuts/ebuilder-form/operations/write.js +277 -0
  20. package/dist/shortcuts/ebuilder-form/operations.js +8 -0
  21. package/dist/shortcuts/ehr/operations/salary.js +2 -140
  22. package/dist/shortcuts/im/continuation.js +70 -0
  23. package/dist/shortcuts/{yimiaoban → im}/errors.js +14 -14
  24. package/dist/shortcuts/{yimiaoban → im}/host.js +26 -26
  25. package/dist/shortcuts/{yimiaoban → im}/index.js +42 -42
  26. package/dist/shortcuts/{yimiaoban → im}/manifest.js +7 -6
  27. package/dist/shortcuts/{yimiaoban → im}/operations/file-user.js +54 -41
  28. package/dist/shortcuts/{yimiaoban → im}/operations/group-read.js +46 -44
  29. package/dist/shortcuts/{yimiaoban → im}/operations/group-write.js +113 -66
  30. package/dist/shortcuts/{yimiaoban → im}/operations/msg-sync.js +164 -141
  31. package/dist/shortcuts/{yimiaoban → im}/operations/msg-write.js +47 -47
  32. package/dist/shortcuts/{yimiaoban → im}/operations/person.js +10 -10
  33. package/dist/shortcuts/{yimiaoban → im}/operations/registry.js +10 -8
  34. package/dist/shortcuts/{yimiaoban → im}/operations/session.js +82 -83
  35. package/dist/shortcuts/im/operations/shared.js +442 -0
  36. package/dist/shortcuts/{yimiaoban → im}/operations/types.js +1 -1
  37. package/dist/shortcuts/im/operations/user-remind.js +201 -0
  38. package/dist/shortcuts/{yimiaoban → im}/operations/write-util.js +7 -7
  39. package/dist/shortcuts/{yimiaoban → im}/operations.js +3 -3
  40. package/dist/shortcuts/index.js +10 -2
  41. package/dist/shortcuts/invoice/manifest.js +113 -10
  42. package/dist/shortcuts/invoice/operations/import.js +39 -14
  43. package/dist/shortcuts/invoice/operations/reim.js +38 -18
  44. package/dist/shortcuts/invoice/operations/shared.js +35 -6
  45. package/dist/shortcuts/jiuchuanhui/manifest.js +3 -3
  46. package/dist/shortcuts/jiuchuanhui/operations/registry.js +2 -2
  47. package/dist/shortcuts/{yimiaoban → okr}/continuation.js +10 -10
  48. package/dist/shortcuts/okr/errors.js +70 -0
  49. package/dist/shortcuts/okr/host.js +169 -0
  50. package/dist/shortcuts/okr/index.js +155 -0
  51. package/dist/shortcuts/okr/manifest.js +70 -0
  52. package/dist/shortcuts/okr/operations/link.js +305 -0
  53. package/dist/shortcuts/okr/operations/read.js +481 -0
  54. package/dist/shortcuts/okr/operations/registry.js +31 -0
  55. package/dist/shortcuts/okr/operations/shared.js +381 -0
  56. package/dist/shortcuts/okr/operations/types.js +88 -0
  57. package/dist/shortcuts/okr/operations/write.js +838 -0
  58. package/dist/shortcuts/okr/operations.js +8 -0
  59. package/dist/shortcuts/project/continuation.js +70 -0
  60. package/dist/shortcuts/project/errors.js +53 -0
  61. package/dist/shortcuts/project/host.js +160 -0
  62. package/dist/shortcuts/project/index.js +106 -0
  63. package/dist/shortcuts/project/manifest.js +36 -0
  64. package/dist/shortcuts/project/operations/read.js +551 -0
  65. package/dist/shortcuts/project/operations/registry.js +31 -0
  66. package/dist/shortcuts/project/operations/shared.js +68 -0
  67. package/dist/shortcuts/project/operations/types.js +39 -0
  68. package/dist/shortcuts/project/operations/write.js +266 -0
  69. package/dist/shortcuts/project/operations.js +8 -0
  70. package/dist/shortcuts/workflow/continuation.js +508 -0
  71. package/dist/shortcuts/workflow/endpoints.js +149 -0
  72. package/dist/shortcuts/workflow/errors.js +112 -0
  73. package/dist/shortcuts/workflow/host.js +224 -0
  74. package/dist/shortcuts/workflow/index.js +116 -0
  75. package/dist/shortcuts/workflow/manifest.js +30 -0
  76. package/dist/shortcuts/workflow/operations/form.js +4159 -0
  77. package/dist/shortcuts/workflow/operations/read.js +3778 -0
  78. package/dist/shortcuts/workflow/operations/registry.js +33 -0
  79. package/dist/shortcuts/workflow/operations/shared.js +167 -0
  80. package/dist/shortcuts/workflow/operations/types.js +44 -0
  81. package/dist/shortcuts/workflow/operations/write.js +1991 -0
  82. package/dist/shortcuts/workflow/operations.js +119 -0
  83. package/dist/shortcuts/workflow/state.js +182 -0
  84. package/docs/SKILL.md +5 -3
  85. package/docs/_catalog.md +10 -1
  86. package/docs/agent-invoice.md +2 -2
  87. package/docs/agent-skill-install.md +2 -2
  88. package/docs/e10-auth.md +3 -1
  89. package/docs/ebuilder-form.md +38 -0
  90. package/docs/im.md +104 -0
  91. package/docs/invoice.md +5 -5
  92. package/docs/okr.md +122 -0
  93. package/docs/operation-manual.md +10 -7
  94. package/docs/project.md +69 -0
  95. package/docs/skill-review-2026-09-19.md +68 -0
  96. package/package.json +3 -2
  97. package/scripts/package-skill.mjs +38 -11
  98. package/scripts/sync-connector-skills.mjs +172 -0
  99. package/skill-template/business-info.json +357 -16
  100. package/skill-template/domains/ebuilder-form.md +5 -0
  101. package/skill-template/domains/okr.md +18 -0
  102. package/skill-template/domains/shijingran.md +3 -0
  103. package/skill-template/domains/skill-maker.md +4 -4
  104. package/skill-template/domains/workflow.md +22 -0
  105. package/skill-template/domains/yepiaotong.md +4 -2
  106. package/skill-template/domains/yimiaoban.md +13 -10
  107. package/skill-template/product.json +5 -0
  108. package/skill-template/skill-template.md +1 -0
  109. package/skills/weaver-e10-calendar/SKILL.md +5 -1
  110. package/skills/weaver-e10-calendar/references/calendar-query.md +7 -0
  111. package/skills/weaver-e10-calendar/references/source-manifest.json +314 -32
  112. package/skills/weaver-e10-ebuilder-form/SKILL.md +123 -0
  113. package/skills/weaver-e10-ebuilder-form/references/context-routing.md +90 -0
  114. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +86 -0
  115. package/skills/weaver-e10-ebuilder-form/references/disabled-capabilities.md +50 -0
  116. package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +100 -0
  117. package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +91 -0
  118. package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +74 -0
  119. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +86 -0
  120. package/skills/weaver-e10-ebuilder-form/references/source-manifest.json +107 -0
  121. package/skills/weaver-e10-esb/SKILL.md +1 -1
  122. package/skills/weaver-e10-esb/references/source-manifest.json +15 -14
  123. package/skills/weaver-e10-hrm/SKILL.md +1 -1
  124. package/skills/weaver-e10-hrm/references/source-manifest.json +357 -38
  125. package/skills/weaver-e10-jiuchuanhui/SKILL.md +22 -4
  126. package/skills/weaver-e10-jiuchuanhui/references/clue.md +4 -2
  127. package/skills/weaver-e10-jiuchuanhui/references/contact.md +1 -1
  128. package/skills/weaver-e10-jiuchuanhui/references/customer.md +3 -3
  129. package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +1 -1
  130. package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +10 -10
  131. package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +3 -3
  132. package/skills/weaver-e10-jiuchuanhui/references/sale.md +7 -7
  133. package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +3 -3
  134. package/skills/weaver-e10-jucailin/SKILL.md +2 -2
  135. package/skills/weaver-e10-mail/SKILL.md +22 -6
  136. package/skills/weaver-e10-meeting/SKILL.md +22 -1
  137. package/skills/weaver-e10-okr/SKILL.md +139 -0
  138. package/skills/weaver-e10-okr/references/okr-align.md +59 -0
  139. package/skills/weaver-e10-okr/references/okr-keyresult.md +68 -0
  140. package/skills/weaver-e10-okr/references/okr-link-routing.md +67 -0
  141. package/skills/weaver-e10-okr/references/okr-query.md +105 -0
  142. package/skills/weaver-e10-okr/references/okr-write.md +94 -0
  143. package/skills/weaver-e10-okr/references/source-manifest.json +672 -0
  144. package/skills/weaver-e10-plan/SKILL.md +3 -3
  145. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  146. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  147. package/skills/weaver-e10-qiyecheng/SKILL.md +21 -1
  148. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +17 -17
  149. package/skills/weaver-e10-shared/SKILL.md +79 -11
  150. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +41 -8
  151. package/skills/weaver-e10-shared/references/non-interactive-environment.md +78 -0
  152. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +39 -0
  153. package/skills/weaver-e10-shijingran/SKILL.md +83 -0
  154. package/skills/weaver-e10-shijingran/references/field-resolution.md +105 -0
  155. package/skills/weaver-e10-shijingran/references/operations.md +154 -0
  156. package/skills/weaver-e10-shijingran/references/source-manifest.json +1380 -0
  157. package/skills/weaver-e10-shijingran/references/write-operations.md +90 -0
  158. package/skills/weaver-e10-skill-maker/SKILL.md +26 -9
  159. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +39 -8
  160. package/skills/weaver-e10-skill-maker/references/detector-validation.md +25 -8
  161. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +66 -5
  162. package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +86 -0
  163. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +59 -5
  164. package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +16 -8
  165. package/skills/weaver-e10-wenshuding/SKILL.md +28 -4
  166. package/skills/weaver-e10-wenshuding/references/archive-search.md +14 -0
  167. package/skills/weaver-e10-wenshuding/references/source-manifest.json +27 -26
  168. package/skills/weaver-e10-workflow/SKILL.md +250 -0
  169. package/skills/weaver-e10-workflow/references/source-manifest.json +1062 -0
  170. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +96 -0
  171. package/skills/weaver-e10-workflow/references/workflow-batch.md +275 -0
  172. package/skills/weaver-e10-workflow/references/workflow-create.md +182 -0
  173. package/skills/weaver-e10-workflow/references/workflow-edit.md +106 -0
  174. package/skills/weaver-e10-workflow/references/workflow-memory.md +165 -0
  175. package/skills/weaver-e10-workflow/references/workflow-operate.md +153 -0
  176. package/skills/weaver-e10-workflow/references/workflow-query.md +821 -0
  177. package/skills/weaver-e10-workflow/references/workflow-share.md +117 -0
  178. package/skills/weaver-e10-workflow/references/workflow-view.md +189 -0
  179. package/skills/weaver-e10-yepiaotong/SKILL.md +28 -28
  180. package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +11 -5
  181. package/skills/weaver-e10-yepiaotong/references/invoice-import.md +14 -8
  182. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +9 -43
  183. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +8 -0
  184. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +13 -17
  185. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +6 -7
  186. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +2 -2
  187. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1155 -553
  188. package/skills/weaver-e10-yimiaoban/SKILL.md +56 -38
  189. package/skills/weaver-e10-yimiaoban/references/ding-write.md +8 -8
  190. package/skills/weaver-e10-yimiaoban/references/error-codes.md +16 -0
  191. package/skills/weaver-e10-yimiaoban/references/field-resolution.md +10 -10
  192. package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +12 -12
  193. package/skills/weaver-e10-yimiaoban/references/group-read.md +16 -16
  194. package/skills/weaver-e10-yimiaoban/references/group-write.md +17 -15
  195. package/skills/weaver-e10-yimiaoban/references/msg-read.md +21 -17
  196. package/skills/weaver-e10-yimiaoban/references/msg-write.md +10 -10
  197. package/skills/weaver-e10-yimiaoban/references/person.md +6 -6
  198. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +15 -11
  199. package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +11 -10
  200. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +2164 -154
  201. package/skills/weaver-e10-yimiaoban/references/user-remind.md +75 -0
  202. package/skills/weaver-e10-ziguanjia/SKILL.md +4 -2
  203. package/skills/weaver-e10-ziguanjia/references/source-manifest.json +99 -29
  204. package/tools/weaver-skill-detector-1.0.13/SKILL.md +253 -0
  205. package/tools/weaver-skill-detector-1.0.13/_meta.json +6 -0
  206. package/tools/weaver-skill-detector-1.0.13/references/checklist.md +298 -0
  207. package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +4190 -0
  208. package/dist/shortcuts/yimiaoban/operations/shared.js +0 -236
  209. package/docs/yimiaoban.md +0 -86
  210. package/skills/weaver-e10-calendar/product.json +0 -8
  211. package/skills/weaver-e10-esb/product.json +0 -8
  212. package/skills/weaver-e10-hrm/product.json +0 -8
  213. package/skills/weaver-e10-jiuchuanhui/product.json +0 -8
  214. package/skills/weaver-e10-jucailin/product.json +0 -8
  215. package/skills/weaver-e10-mail/product.json +0 -8
  216. package/skills/weaver-e10-meeting/product.json +0 -8
  217. package/skills/weaver-e10-plan/product.json +0 -8
  218. package/skills/weaver-e10-qiyecheng/product.json +0 -8
  219. package/skills/weaver-e10-skill-maker/product.json +0 -8
  220. package/skills/weaver-e10-wenshuding/product.json +0 -8
  221. package/skills/weaver-e10-yepiaotong/product.json +0 -8
  222. package/skills/weaver-e10-yepiaotong/references/invoice-red.md +0 -261
  223. package/skills/weaver-e10-yimiaoban/product.json +0 -8
  224. package/skills/weaver-e10-ziguanjia/product.json +0 -8
  225. /package/dist/shortcuts/{yimiaoban → im}/operations/msg-parse.js +0 -0
@@ -1,42 +1,54 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { rename, stat, writeFile } from 'node:fs/promises';
3
3
  import { dirname, extname, resolve } from 'node:path';
4
- import { ymbValidationError } from '../errors.js';
5
- import { READ, schemaOf, ymbSuccess, } from './types.js';
6
- import { assertImOk, compact, splitIds, str, toUint, unwrapInner } from './shared.js';
4
+ import { imValidationError } from '../errors.js';
5
+ import { READ, schemaOf, imSuccess, } from './types.js';
6
+ import { assertImOk, compact, normalizeAliases, splitIds, str, toUint, unwrapInner } from './shared.js';
7
7
  import { fileObjToFile, fileObjToImg } from './write-util.js';
8
+ /** file.upload 旧字段兼容映射(已发布版本接受过这些旧名,按 CLI 规范登记为 deprecated alias)。 */
9
+ const FILE_UPLOAD_ALIASES = {
10
+ file: ['filePath'],
11
+ shareGroup: ['shareGroups'],
12
+ };
8
13
  /** 文件上传(两段式,module=im),返回 fileObj + 消息对象两种形态。 */
9
14
  const fileUpload = {
10
- name: 'yimiaoban.file.upload',
15
+ name: 'im.file.upload',
11
16
  resource: 'file',
12
17
  method: 'file.upload',
13
- action: 'yimiaoban.file.upload',
18
+ action: 'im.file.upload',
14
19
  summary: '上传本地文件到 E10 文件服务(module=im),返回文件 id(供消息 img/file 引用)',
15
20
  capability: 'file',
16
21
  risk: 'external-artifact',
17
- inputSchema: schemaOf({
18
- file: { type: 'string', description: '本地文件路径(必填,兼容旧名 filePath)' },
19
- name: { type: 'string', description: '文件名(默认取 basename)' },
20
- shareGroup: { type: 'string', description: '分享群 id(发群消息用;兼容 shareGroups 逗号串)' },
21
- shareUsers: { type: 'array', items: { type: 'string' }, description: '分享用户 uid(发单聊用)' },
22
- permission: { type: 'string', description: '文件权限(默认 3)' },
23
- }, { required: ['file'], description: '文件上传' }),
22
+ deprecatedInputAliases: FILE_UPLOAD_ALIASES,
23
+ inputSchema: {
24
+ ...schemaOf({
25
+ file: { type: 'string', description: '本地文件路径(必填)' },
26
+ filePath: { type: 'string', description: '旧名字段,等价 file(已废弃,与新名同时出现且不一致会报 alias_conflict)' },
27
+ name: { type: 'string', description: '文件名(默认取 basename)' },
28
+ shareGroup: { type: 'string', description: '分享群 id(发群消息用)' },
29
+ shareGroups: { type: 'string', description: '旧名字段,等价 shareGroup(已废弃)' },
30
+ shareUsers: { type: 'array', items: { type: 'string' }, description: '分享用户 uid(发单聊用)' },
31
+ permission: { type: 'string', description: '文件权限(默认 3)' },
32
+ }, { description: '文件上传:file(或旧名 filePath)必填' }),
33
+ anyOf: [{ required: ['file'] }, { required: ['filePath'] }],
34
+ },
24
35
  handler: async (args, { host }) => {
25
- const filePath = String(args.file ?? args.filePath ?? '');
36
+ const input = normalizeAliases(args, FILE_UPLOAD_ALIASES);
37
+ const filePath = String(input.file ?? '');
26
38
  if (!filePath)
27
- throw ymbValidationError('file_required', 'file 必填');
39
+ throw imValidationError('file_required', 'file 必填');
28
40
  const abs = resolve(filePath);
29
41
  if (!existsSync(abs))
30
- throw ymbValidationError('file_not_found', `文件不存在: ${abs}`);
31
- const shareUsers = Array.isArray(args.shareUsers) ? args.shareUsers.join(',') : String(args.shareUsers ?? '');
32
- const shareGroups = args.shareGroup ?? args.shareGroups;
42
+ throw imValidationError('file_not_found', `文件不存在: ${abs}`);
43
+ const shareUsers = Array.isArray(input.shareUsers) ? input.shareUsers.join(',') : String(input.shareUsers ?? '');
44
+ const shareGroups = input.shareGroup;
33
45
  const fileObj = await host.uploadFile(abs, {
34
- name: args.name !== undefined ? String(args.name) : undefined,
46
+ name: input.name !== undefined ? String(input.name) : undefined,
35
47
  shareGroups: shareGroups !== undefined && shareGroups !== '' ? String(shareGroups) : undefined,
36
48
  shareUsers: shareUsers || undefined,
37
- permission: args.permission !== undefined ? String(args.permission) : undefined,
49
+ permission: input.permission !== undefined ? String(input.permission) : undefined,
38
50
  });
39
- return ymbSuccess('yimiaoban.file.upload', {
51
+ return imSuccess('im.file.upload', {
40
52
  fileObj,
41
53
  img: fileObjToImg(fileObj),
42
54
  file: fileObjToFile(fileObj),
@@ -45,10 +57,10 @@ const fileUpload = {
45
57
  };
46
58
  /** 媒体预览(img/video)URL 构造 + 可选下载。 */
47
59
  const filePreview = {
48
- name: 'yimiaoban.file.preview',
60
+ name: 'im.file.preview',
49
61
  resource: 'file',
50
62
  method: 'file.preview',
51
- action: 'yimiaoban.file.preview',
63
+ action: 'im.file.preview',
52
64
  summary: '生成图片/视频预览与下载 URL(需登录态访问;图片支持 small/large/original)',
53
65
  capability: 'file',
54
66
  risk: READ,
@@ -68,7 +80,7 @@ const filePreview = {
68
80
  const groupId = args.groupId !== undefined && args.groupId !== '' ? String(args.groupId) : undefined;
69
81
  const user = args.toUid || args.toCid ? { cid: str(args.toCid), uid: str(args.toUid) } : undefined;
70
82
  if (!groupId && !user) {
71
- throw ymbValidationError('context_required', 'groupId(群聊)或 toUid+toCid(单聊)必须提供其一');
83
+ throw imValidationError('context_required', 'groupId(群聊)或 toUid+toCid(单聊)必须提供其一');
72
84
  }
73
85
  const opts = {
74
86
  fileId,
@@ -78,12 +90,12 @@ const filePreview = {
78
90
  ...(groupId ? { groupId } : {}),
79
91
  ...(user ? { user } : {}),
80
92
  };
81
- return ymbSuccess('yimiaoban.file.preview', {
93
+ return imSuccess('im.file.preview', {
82
94
  kind,
83
95
  fileId,
84
96
  previewUrl: await host.buildPreviewUrl(opts),
85
97
  downloadUrl: await host.buildDownloadUrl(opts),
86
- note: '预览/下载 URL 需要登录态(Cookie+eteamsid),直接嵌入 Markdown 会 401;需要真正可见请用 yimiaoban.file.download 落地到本地。',
98
+ note: '预览/下载 URL 需要登录态(Cookie+eteamsid),直接嵌入 Markdown 会 401;需要真正可见请用 im.file.download 落地到本地。',
87
99
  });
88
100
  },
89
101
  };
@@ -109,10 +121,10 @@ function detectImageExt(buffer) {
109
121
  }
110
122
  /** 消息媒体/文件落地到本地(需登录态;父目录必须存在,禁止覆盖已存在文件)。 */
111
123
  const fileDownload = {
112
- name: 'yimiaoban.file.download',
124
+ name: 'im.file.download',
113
125
  resource: 'file',
114
126
  method: 'file.download',
115
- action: 'yimiaoban.file.download',
127
+ action: 'im.file.download',
116
128
  summary: '下载消息里的图片/视频/文件到本地(需登录态;父目录必须存在,禁止覆盖)',
117
129
  capability: 'file',
118
130
  risk: 'local-file-write',
@@ -133,20 +145,20 @@ const fileDownload = {
133
145
  const kind = kindRaw === 'video' ? 'video' : 'img';
134
146
  const output = String(args.output ?? '').trim();
135
147
  if (!output)
136
- throw ymbValidationError('output_required', 'output 必须是明确的本地文件路径');
148
+ throw imValidationError('output_required', 'output 必须是明确的本地文件路径');
137
149
  const groupId = args.groupId !== undefined && args.groupId !== '' ? String(args.groupId) : undefined;
138
150
  const user = args.toUid || args.toCid ? { cid: str(args.toCid), uid: str(args.toUid) } : undefined;
139
151
  if (!groupId && !user) {
140
- throw ymbValidationError('context_required', 'groupId(群聊)或 toUid+toCid(单聊)必须提供其一');
152
+ throw imValidationError('context_required', 'groupId(群聊)或 toUid+toCid(单聊)必须提供其一');
141
153
  }
142
154
  const resolved = resolve(output);
143
155
  const parent = await stat(dirname(resolved)).catch(() => null);
144
156
  if (!parent)
145
- throw ymbValidationError('output_parent_missing', `输出目录不存在:${dirname(resolved)}`);
157
+ throw imValidationError('output_parent_missing', `输出目录不存在:${dirname(resolved)}`);
146
158
  if (!parent.isDirectory())
147
- throw ymbValidationError('output_parent_invalid', '输出文件的父路径不是目录');
159
+ throw imValidationError('output_parent_invalid', '输出文件的父路径不是目录');
148
160
  if (existsSync(resolved))
149
- throw ymbValidationError('output_exists', `输出文件已存在,拒绝覆盖:${resolved}`);
161
+ throw imValidationError('output_exists', `输出文件已存在,拒绝覆盖:${resolved}`);
150
162
  const url = await host.buildDownloadUrl({
151
163
  fileId,
152
164
  msgid,
@@ -174,7 +186,7 @@ const fileDownload = {
174
186
  }
175
187
  }
176
188
  }
177
- return ymbSuccess('yimiaoban.file.download', {
189
+ return imSuccess('im.file.download', {
178
190
  fileId,
179
191
  msgid,
180
192
  kind: kindRaw,
@@ -188,10 +200,10 @@ const fileDownload = {
188
200
  };
189
201
  /** 人员在线状态。 */
190
202
  const userState = {
191
- name: 'yimiaoban.user.state',
203
+ name: 'im.user.state',
192
204
  resource: 'user',
193
205
  method: 'user.state',
194
- action: 'yimiaoban.user.state',
206
+ action: 'im.user.state',
195
207
  summary: '查询指定人员各在线设备状态(sub_state 强制 0 不订阅)',
196
208
  capability: 'user',
197
209
  risk: READ,
@@ -199,6 +211,7 @@ const userState = {
199
211
  users: { type: 'array', items: { type: 'string' }, description: '人员 uid 列表' },
200
212
  devType: { type: 'integer', description: '设备类型(缺省查全部在线设备)' },
201
213
  mask: { type: 'integer', description: '信息掩码(默认 7)' },
214
+ removeFailed: { type: 'boolean', description: '解析失败的人员跳过(默认 false:解析失败会报 members_resolve_failed)' },
202
215
  }, { required: ['users'], description: '查询人员在线状态' }),
203
216
  handler: async (args, { host }) => {
204
217
  const rawUids = Array.isArray(args.users) ? args.users.map((x) => String(x)) : splitIds(args.users, 'users');
@@ -214,7 +227,7 @@ const userState = {
214
227
  members.push({ cid: p.cid, uid });
215
228
  }
216
229
  if (failed.length && args.removeFailed !== true) {
217
- throw ymbValidationError('members_resolve_failed', `以下人员解析失败:${failed.map((f) => f.name || f.uid).join('、')};确认跳过请传 removeFailed:true`);
230
+ throw imValidationError('members_resolve_failed', `以下人员解析失败:${failed.map((f) => f.name || f.uid).join('、')};确认跳过请传 removeFailed:true`);
218
231
  }
219
232
  const body = compact({
220
233
  users: members,
@@ -226,7 +239,7 @@ const userState = {
226
239
  method: 'POST',
227
240
  path: '/api/em/msg/executeIm/state/syncUserState',
228
241
  body,
229
- operation: 'yimiaoban.user.state',
242
+ operation: 'im.user.state',
230
243
  });
231
244
  assertImOk(res, '查询人员状态');
232
245
  const inner = unwrapInner(res);
@@ -246,7 +259,7 @@ const userState = {
246
259
  }));
247
260
  return { uid, name: map[uid]?.name || uid, devices };
248
261
  });
249
- return ymbSuccess('yimiaoban.user.state', { total: infos.length, infos });
262
+ return imSuccess('im.user.state', { total: infos.length, infos });
250
263
  },
251
264
  };
252
265
  function formatTime(ts) {
@@ -260,10 +273,10 @@ function formatTime(ts) {
260
273
  }
261
274
  /** i18n 标签翻译(内部支撑,也可单独查询)。 */
262
275
  const i18nLabels = {
263
- name: 'yimiaoban.i18n.labels',
276
+ name: 'im.i18n.labels',
264
277
  resource: 'i18n',
265
278
  method: 'i18n.labels',
266
- action: 'yimiaoban.i18n.labels',
279
+ action: 'im.i18n.labels',
267
280
  summary: '批量翻译国际化标签 id → 当前语言文案',
268
281
  capability: 'i18n',
269
282
  risk: READ,
@@ -273,7 +286,7 @@ const i18nLabels = {
273
286
  handler: async (args, { host }) => {
274
287
  const ids = Array.isArray(args.ids) ? args.ids.map((x) => String(x)) : splitIds(args.ids, 'ids');
275
288
  const labels = await host.fetchI18nLabels(ids);
276
- return ymbSuccess('yimiaoban.i18n.labels', {
289
+ return imSuccess('im.i18n.labels', {
277
290
  total: Object.keys(labels).length,
278
291
  labels: ids.map((id) => ({ id, text: labels[id] ?? '(未取到文案)' })),
279
292
  });
@@ -1,5 +1,5 @@
1
- import { ymbValidationError } from '../errors.js';
2
- import { READ, schemaOf, ymbSuccess, } from './types.js';
1
+ import { imValidationError } from '../errors.js';
2
+ import { READ, schemaOf, imSuccess, } from './types.js';
3
3
  import { assertImOk, compact, extractGroupMembers, formatFullTime, splitIds, str, toPositiveInt, toUint, unwrapInner, } from './shared.js';
4
4
  const SEARCH_TYPE_MASK = {
5
5
  type: 1,
@@ -14,7 +14,7 @@ function requireCidUid(cid, uid) {
14
14
  const c = String(cid ?? '');
15
15
  const u = String(uid ?? '');
16
16
  if (!c || !u || c === '0' || u === '0') {
17
- throw ymbValidationError('self_identity_missing', '该查询需要当前登录人的 cid/uid(非 0),请确认登录态完整');
17
+ throw imValidationError('self_identity_missing', '该查询需要当前登录人的 cid/uid(非 0),请确认登录态完整');
18
18
  }
19
19
  return { cid: c, uid: u };
20
20
  }
@@ -22,7 +22,7 @@ function requireCidUid(cid, uid) {
22
22
  function requireGroupId(value) {
23
23
  const text = String(value ?? '').trim();
24
24
  if (!/^\d+$/.test(text) || text === '0') {
25
- throw ymbValidationError('id_invalid', `groupId 必须是非 0 数字 ID(收到:${text || '(空)'})`);
25
+ throw imValidationError('id_invalid', `groupId 必须是非 0 数字 ID(收到:${text || '(空)'})`);
26
26
  }
27
27
  return text;
28
28
  }
@@ -49,10 +49,10 @@ function stateName(state) {
49
49
  }
50
50
  /** 群搜索。 */
51
51
  const groupSearch = {
52
- name: 'yimiaoban.group.search',
52
+ name: 'im.group.search',
53
53
  resource: 'group',
54
54
  method: 'group.search',
55
- action: 'yimiaoban.group.search',
55
+ action: 'im.group.search',
56
56
  summary: '按条件搜索群(cond+mask 全服务端过滤,禁止本地过滤)',
57
57
  capability: 'group',
58
58
  risk: READ,
@@ -93,13 +93,15 @@ const groupSearch = {
93
93
  }
94
94
  if (args.owner === true) {
95
95
  const self = await host.getSelfIdentity();
96
+ const { cid, uid } = requireCidUid(self.cid, self.uid);
96
97
  mask |= SEARCH_TYPE_MASK.owners;
97
- cond.owners = [{ cid: self.cid, uid: self.uid }];
98
+ cond.owners = [{ cid, uid }];
98
99
  }
99
100
  if (args.creator === true) {
100
101
  const self = await host.getSelfIdentity();
102
+ const { cid, uid } = requireCidUid(self.cid, self.uid);
101
103
  mask |= SEARCH_TYPE_MASK.creators;
102
- cond.creators = [{ cid: self.cid, uid: self.uid }];
104
+ cond.creators = [{ cid, uid }];
103
105
  }
104
106
  let create;
105
107
  if (args.today === true)
@@ -114,7 +116,7 @@ const groupSearch = {
114
116
  cond.create = create;
115
117
  }
116
118
  if (mask === 0)
117
- throw ymbValidationError('cond_required', '至少提供一个搜索条件(name/type/members/owner/creator/today/yesterday/create*)');
119
+ throw imValidationError('cond_required', '至少提供一个搜索条件(name/type/members/owner/creator/today/yesterday/create*)');
118
120
  cond.mask = mask;
119
121
  const pageSize = Math.min(toPositiveInt(args.pageSize, 'pageSize') ?? 100, 200);
120
122
  const body = { page: { size: pageSize, num: 1 }, cond };
@@ -122,12 +124,12 @@ const groupSearch = {
122
124
  method: 'POST',
123
125
  path: '/api/em/msg/executeIm/group/searchGroup',
124
126
  body,
125
- operation: 'yimiaoban.group.search',
127
+ operation: 'im.group.search',
126
128
  });
127
129
  assertImOk(res, '搜索群');
128
130
  const inner = unwrapInner(res);
129
131
  const datas = inner?.datas || [];
130
- return ymbSuccess('yimiaoban.group.search', {
132
+ return imSuccess('im.group.search', {
131
133
  total: inner?.total ?? datas.length,
132
134
  groups: datas.map((g) => ({
133
135
  id: str(g.id),
@@ -141,10 +143,10 @@ const groupSearch = {
141
143
  };
142
144
  /** 群基础信息(支持多群)。 */
143
145
  const groupInfo = {
144
- name: 'yimiaoban.group.info',
146
+ name: 'im.group.info',
145
147
  resource: 'group',
146
148
  method: 'group.info',
147
- action: 'yimiaoban.group.info',
149
+ action: 'im.group.info',
148
150
  summary: '按群 id 查基础信息(支持批量;类型位组合 + 状态展示)',
149
151
  capability: 'group',
150
152
  risk: READ,
@@ -162,17 +164,17 @@ const groupInfo = {
162
164
  ids.push(String(args.groupId));
163
165
  ids = [...new Set(ids)];
164
166
  if (ids.length === 0)
165
- throw ymbValidationError('group_ids_required', 'groupIds / groupId 至少其一');
167
+ throw imValidationError('group_ids_required', 'groupIds / groupId 至少其一');
166
168
  for (const id of ids) {
167
169
  if (!/^\d+$/.test(id) || id === '0')
168
- throw ymbValidationError('id_invalid', `群 id 必须非 0 数字:${id}`);
170
+ throw imValidationError('id_invalid', `群 id 必须非 0 数字:${id}`);
169
171
  }
170
172
  const body = { trans_id: 0, type: 0, mask: 0, group_id: ids, flag: 0 };
171
173
  const res = await host.request({
172
174
  method: 'POST',
173
175
  path: '/api/em/msg/executeIm/group/queryGroupInfo',
174
176
  body,
175
- operation: 'yimiaoban.group.info',
177
+ operation: 'im.group.info',
176
178
  });
177
179
  assertImOk(res, '查询群信息');
178
180
  const inner = unwrapInner(res);
@@ -189,15 +191,15 @@ const groupInfo = {
189
191
  stateName: stateName(Number(g.state ?? -1)),
190
192
  createTime: formatFullTime(g.create_time ?? g.createTime),
191
193
  }));
192
- return ymbSuccess('yimiaoban.group.info', { total: groups.length, groups });
194
+ return imSuccess('im.group.info', { total: groups.length, groups });
193
195
  },
194
196
  };
195
197
  /** 群成员列表。 */
196
198
  const groupUsers = {
197
- name: 'yimiaoban.group.users',
199
+ name: 'im.group.users',
198
200
  resource: 'group',
199
201
  method: 'group.users',
200
- action: 'yimiaoban.group.users',
202
+ action: 'im.group.users',
201
203
  summary: '拉取群成员列表(姓名一律走 hrm,默认 mask 不含 name 位)',
202
204
  capability: 'group',
203
205
  risk: READ,
@@ -221,7 +223,7 @@ const groupUsers = {
221
223
  method: 'POST',
222
224
  path: '/api/em/msg/executeIm/group/getGroupUsers',
223
225
  body,
224
- operation: 'yimiaoban.group.users',
226
+ operation: 'im.group.users',
225
227
  });
226
228
  assertImOk(res, '拉取群成员');
227
229
  const inner = unwrapInner(res);
@@ -242,7 +244,7 @@ const groupUsers = {
242
244
  roleName: hasRole ? roleNames[Number(m.role_type ?? m.role ?? -1)] ?? '-' : undefined,
243
245
  addTime: hasAddTime ? formatFullTime(m.add_time ?? m.addTime) : undefined,
244
246
  }));
245
- return ymbSuccess('yimiaoban.group.users', {
247
+ return imSuccess('im.group.users', {
246
248
  groupId,
247
249
  totalNum: inner?.total_num ?? rows.length,
248
250
  endFlag: inner?.end_flag,
@@ -253,10 +255,10 @@ const groupUsers = {
253
255
  };
254
256
  /** 批量查群管理员/群主。 */
255
257
  const groupAdmins = {
256
- name: 'yimiaoban.group.admins',
258
+ name: 'im.group.admins',
257
259
  resource: 'group',
258
260
  method: 'group.admins',
259
- action: 'yimiaoban.group.admins',
261
+ action: 'im.group.admins',
260
262
  summary: '批量获取群主/管理员(mask 位 1=群主/负责人 2=管理员,默认 3)',
261
263
  capability: 'group',
262
264
  risk: READ,
@@ -271,7 +273,7 @@ const groupAdmins = {
271
273
  method: 'POST',
272
274
  path: '/api/em/msg/executeIm/group/getGroupAdminBatch',
273
275
  body,
274
- operation: 'yimiaoban.group.admins',
276
+ operation: 'im.group.admins',
275
277
  });
276
278
  assertImOk(res, '查询群管理员');
277
279
  const inner = unwrapInner(res);
@@ -295,15 +297,15 @@ const groupAdmins = {
295
297
  roleName: roleNames[Number(it.role ?? -1)] ?? '-',
296
298
  })),
297
299
  }));
298
- return ymbSuccess('yimiaoban.group.admins', { total: groups.length, groups });
300
+ return imSuccess('im.group.admins', { total: groups.length, groups });
299
301
  },
300
302
  };
301
303
  /** 批量判断群是否存在。 */
302
304
  const groupExist = {
303
- name: 'yimiaoban.group.exist',
305
+ name: 'im.group.exist',
304
306
  resource: 'group',
305
307
  method: 'group.exist',
306
- action: 'yimiaoban.group.exist',
308
+ action: 'im.group.exist',
307
309
  summary: '批量判断群是否存在(ret=0 存在;1209 不存在)',
308
310
  capability: 'group',
309
311
  risk: READ,
@@ -314,19 +316,19 @@ const groupExist = {
314
316
  const ids = Array.isArray(args.groupIds) ? args.groupIds.map((x) => String(x)) : splitIds(args.groupIds, 'groupIds');
315
317
  for (const id of ids) {
316
318
  if (!/^\d+$/.test(id) || id === '0')
317
- throw ymbValidationError('id_invalid', `群 id 必须非 0 数字:${id || '(空)'}`);
319
+ throw imValidationError('id_invalid', `群 id 必须非 0 数字:${id || '(空)'}`);
318
320
  }
319
321
  const body = { groupIds: ids };
320
322
  const res = await host.request({
321
323
  method: 'POST',
322
324
  path: '/api/em/msg/executeIm/group/checkGroupExist',
323
325
  body,
324
- operation: 'yimiaoban.group.exist',
326
+ operation: 'im.group.exist',
325
327
  });
326
328
  assertImOk(res, '检查群是否存在');
327
329
  const inner = unwrapInner(res);
328
330
  const results = inner?.results || [];
329
- return ymbSuccess('yimiaoban.group.exist', {
331
+ return imSuccess('im.group.exist', {
330
332
  groups: results.map((r) => ({
331
333
  groupId: str(r.group_id),
332
334
  exists: Number(r.ret) === 0,
@@ -337,10 +339,10 @@ const groupExist = {
337
339
  };
338
340
  /** 检查用户是否在某群内。 */
339
341
  const groupUserExist = {
340
- name: 'yimiaoban.group.userExist',
342
+ name: 'im.group.userExist',
341
343
  resource: 'group',
342
344
  method: 'group.userExist',
343
- action: 'yimiaoban.group.userExist',
345
+ action: 'im.group.userExist',
344
346
  summary: '检查用户是否在某群内(tenantKey 自动注入)',
345
347
  capability: 'group',
346
348
  risk: READ,
@@ -353,13 +355,13 @@ const groupUserExist = {
353
355
  const users = Array.isArray(args.users) ? args.users.map((x) => String(x)) : splitIds(args.users, 'users');
354
356
  const session = await host.getSession();
355
357
  if (!session.tenantKey)
356
- throw ymbValidationError('tenant_key_missing', '登录态缺少 tenantKey,请重新登录');
358
+ throw imValidationError('tenant_key_missing', '登录态缺少 tenantKey,请重新登录');
357
359
  const body = { tenantKey: session.tenantKey, groupId, users };
358
360
  const res = await host.request({
359
361
  method: 'POST',
360
362
  path: '/api/em/msg/executeIm/group/checkGroupUserExist',
361
363
  body,
362
- operation: 'yimiaoban.group.userExist',
364
+ operation: 'im.group.userExist',
363
365
  });
364
366
  assertImOk(res, '检查群成员');
365
367
  const inner = unwrapInner(res);
@@ -371,15 +373,15 @@ const groupUserExist = {
371
373
  name: personMap[uid]?.name || uid,
372
374
  inGroup: inSet.has(uid),
373
375
  }));
374
- return ymbSuccess('yimiaoban.group.userExist', { groupId, total: rows.length, users: rows });
376
+ return imSuccess('im.group.userExist', { groupId, total: rows.length, users: rows });
375
377
  },
376
378
  };
377
379
  /** 群公告:获取单条。 */
378
380
  const groupAnnounceGet = {
379
- name: 'yimiaoban.group.announce.get',
381
+ name: 'im.group.announce.get',
380
382
  resource: 'group',
381
383
  method: 'group.announce.get',
382
- action: 'yimiaoban.group.announce.get',
384
+ action: 'im.group.announce.get',
383
385
  summary: '获取群公告(aid=0/不传=最新公告)',
384
386
  capability: 'group',
385
387
  risk: READ,
@@ -393,17 +395,17 @@ const groupAnnounceGet = {
393
395
  method: 'POST',
394
396
  path: '/api/em/msg/executeIm/group/getAnnouce',
395
397
  body,
396
- operation: 'yimiaoban.group.announce.get',
398
+ operation: 'im.group.announce.get',
397
399
  });
398
400
  assertImOk(res, '获取群公告');
399
401
  const inner = unwrapInner(res);
400
402
  // 公告主体位于 data.data.data(兼容 data.data 直挂 annouce 的形态)
401
403
  const data = inner && typeof inner === 'object' && inner.data && typeof inner.data === 'object' ? inner.data : inner;
402
404
  if (!data || (data.aid === undefined && data.annouce === undefined)) {
403
- return ymbSuccess('yimiaoban.group.announce.get', { found: false });
405
+ return imSuccess('im.group.announce.get', { found: false });
404
406
  }
405
407
  const personMap = await host.resolveUsersByIds(data?.add_user?.uid ? [String(data.add_user.uid)] : []);
406
- return ymbSuccess('yimiaoban.group.announce.get', {
408
+ return imSuccess('im.group.announce.get', {
407
409
  found: true,
408
410
  aid: str(data.aid),
409
411
  annouce: data.annouce ?? '',
@@ -418,10 +420,10 @@ const groupAnnounceGet = {
418
420
  };
419
421
  /** 群公告列表。 */
420
422
  const groupAnnounceList = {
421
- name: 'yimiaoban.group.announce.list',
423
+ name: 'im.group.announce.list',
422
424
  resource: 'group',
423
425
  method: 'group.announce.list',
424
- action: 'yimiaoban.group.announce.list',
426
+ action: 'im.group.announce.list',
425
427
  summary: '群公告列表(按 id 降序,end_flag=1 还有下一页)',
426
428
  capability: 'group',
427
429
  risk: READ,
@@ -440,7 +442,7 @@ const groupAnnounceList = {
440
442
  method: 'POST',
441
443
  path: '/api/em/msg/executeIm/group/getAnnouceList',
442
444
  body,
443
- operation: 'yimiaoban.group.announce.list',
445
+ operation: 'im.group.announce.list',
444
446
  });
445
447
  assertImOk(res, '获取公告列表');
446
448
  const inner = unwrapInner(res);
@@ -457,7 +459,7 @@ const groupAnnounceList = {
457
459
  mustRead: Number(d.fmark ?? 0) === 1,
458
460
  related: str(d.related ?? ''),
459
461
  }));
460
- return ymbSuccess('yimiaoban.group.announce.list', {
462
+ return imSuccess('im.group.announce.list', {
461
463
  total: rows.length,
462
464
  endFlag: inner?.end_flag,
463
465
  hasMore: Number(inner?.end_flag) === 1,