weaver-work-cli 0.1.6 → 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 +44 -31
  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,40 +1,47 @@
1
- import { ymbValidationError } from '../errors.js';
2
- import { READ, schemaOf, ymbSuccess, } from './types.js';
3
- import { assertImOk, compact, formatFullTime, makeMinMaxIdByTm, minMsgId, parseMsg, parseTimeToSec, resolveAuthUid, str, todayRange, unwrapInner, } from './shared.js';
1
+ import { imValidationError } from '../errors.js';
2
+ import { READ, schemaOf, imSuccess, } from './types.js';
3
+ import { assertImOk, clampTimeRangeTo7Days, compact, DEFAULT_PAGE_SIZE, formatFullTime, makeMinMaxIdByTm, paginationMeta, parseMsg, parseTimeToSec, pullPaged, rangeShrinkMeta, resolveAuthUid, sortMessagesNewestFirst, str, todayRange, unwrapInner, } from './shared.js';
4
4
  import { collapseNewlines, collectI18nIds, collectPersonIds, extractFiles, extractImgs, extractVideos, parseContent, senderName, } from './msg-parse.js';
5
5
  const MAX_MSG_ID = String((1n << 63n) - 1n);
6
- const DEFAULT_PAGE_SIZE = 20;
7
- const MAX_PAGE_SIZE = 50;
8
- /** 时间/最新/游标/显式 id 计算 start/end */
9
- function resolveStartEnd(args, fallback = {}) {
10
- // 1) 显式 start/end 最高优先
11
- if (args.start !== undefined && args.start !== null && args.start !== '') {
12
- const start = String(args.start);
13
- const end = args.end !== undefined && args.end !== null && args.end !== '' ? String(args.end) : '0';
14
- return { start, end };
6
+ /**
7
+ * 时间/最新/显式 id 计算 start/end(与源 skill 一致):
8
+ * 1) 显式 start/end(群聊为 startId/endId)最高优先;
9
+ * 2) `latest:true` 不限日期(无界区间,只拉一页);
10
+ * 3) `from`/`to` 时间范围 → 时间转消息 id 区间,跨度 > 7 天自动收敛为最后 7 个自然日;
11
+ * 4) 缺省 当天(有界区间,自动循环翻页拉完)。
12
+ */
13
+ function resolveRange(args, idKeys = { start: 'start', end: 'end' }) {
14
+ const explicitStart = args[idKeys.start];
15
+ const explicitEnd = args[idKeys.end];
16
+ if (explicitStart !== undefined && explicitStart !== null && explicitStart !== '') {
17
+ return {
18
+ start: String(explicitStart),
19
+ end: explicitEnd !== undefined && explicitEnd !== null && explicitEnd !== '' ? String(explicitEnd) : '0',
20
+ scope: 'explicit-id',
21
+ shrink: null,
22
+ };
15
23
  }
16
24
  if (args.latest === true) {
17
- return { start: MAX_MSG_ID, end: '0' };
25
+ return { start: MAX_MSG_ID, end: '0', scope: 'latest', shrink: null };
18
26
  }
19
- // 2) 时间范围
20
- if ((args.from !== undefined && args.from !== null && args.from !== '')
21
- || (args.to !== undefined && args.to !== null && args.to !== '')) {
22
- const fromSec = parseTimeToSec(args.from, false);
23
- const toSec = parseTimeToSec(args.to, true);
24
- if (toSec > 0) {
25
- const start = makeMinMaxIdByTm(toSec).max;
26
- const end = fromSec > 0 ? makeMinMaxIdByTm(fromSec).min : '0';
27
- return { start, end };
28
- }
29
- return { start: MAX_MSG_ID, end: '0' };
27
+ const hasFrom = args.from !== undefined && args.from !== null && args.from !== '';
28
+ const hasTo = args.to !== undefined && args.to !== null && args.to !== '';
29
+ if (hasFrom || hasTo) {
30
+ const clamp = clampTimeRangeTo7Days(parseTimeToSec(args.from, false), parseTimeToSec(args.to, true));
31
+ return {
32
+ start: clamp.toSec > 0 ? makeMinMaxIdByTm(clamp.toSec).max : MAX_MSG_ID,
33
+ end: clamp.fromSec > 0 ? makeMinMaxIdByTm(clamp.fromSec).min : '0',
34
+ scope: 'range',
35
+ shrink: clamp.shrunk ? clamp : null,
36
+ };
30
37
  }
31
- // 3) 默认当天
32
38
  const range = todayRange();
33
- const startTm = fallback.toSec || range.toSec;
34
- const endTm = fallback.fromSec || range.fromSec;
35
- if (startTm > 0)
36
- return { start: makeMinMaxIdByTm(startTm).max, end: makeMinMaxIdByTm(endTm).min };
37
- return { start: MAX_MSG_ID, end: '0' };
39
+ return {
40
+ start: makeMinMaxIdByTm(range.toSec).max,
41
+ end: makeMinMaxIdByTm(range.fromSec).min,
42
+ scope: 'today',
43
+ shrink: null,
44
+ };
38
45
  }
39
46
  function pageSizeOf(args) {
40
47
  const raw = args.num;
@@ -42,8 +49,8 @@ function pageSizeOf(args) {
42
49
  return DEFAULT_PAGE_SIZE;
43
50
  const n = Number(raw);
44
51
  if (!Number.isInteger(n) || n <= 0)
45
- throw ymbValidationError('num_invalid', 'num 必须是正整数');
46
- return Math.min(n, MAX_PAGE_SIZE);
52
+ throw imValidationError('num_invalid', 'num 必须是正整数');
53
+ return Math.min(n, 50);
47
54
  }
48
55
  /** `actionMsg.code=1303`(无聊天记录)时按成功空列表返回,并说明本次口径。 */
49
56
  function emptyPageNote(args) {
@@ -54,17 +61,6 @@ function emptyPageNote(args) {
54
61
  return '该时间范围内无消息记录';
55
62
  return '当天无消息(如需最新消息请传 latest:true,或指定 from/to 时间范围)';
56
63
  }
57
- /** 单页返回公共字段:`hasMore` + 下一页锚点 + 去重提示。 */
58
- function pageMeta(messages, args) {
59
- const hasMore = messages.length >= pageSizeOf(args);
60
- const nextStart = minMsgId(messages);
61
- return {
62
- hasMore,
63
- ...(hasMore && nextStart
64
- ? { nextStart, dedupeHint: '下一页 start 传 nextStart;服务端会重复返回该条(边界消息),请按 msgid 去重' }
65
- : {}),
66
- };
67
- }
68
64
  /** 富化消息列表:并行取 i18n + 人员姓名,逐条解析 content/sender/media。 */
69
65
  async function enrichMessages(rawRows, host, options = {}) {
70
66
  const rows = rawRows.filter(Boolean);
@@ -173,22 +169,22 @@ async function enrichMessages(rawRows, host, options = {}) {
173
169
  }
174
170
  return enriched;
175
171
  }
176
- /** 拉单聊消息(默认当天,单页,倒序)。 */
172
+ /** 拉单聊消息(默认当天;有界区间自动循环翻页拉完)。 */
177
173
  const msgSyncSingle = {
178
- name: 'yimiaoban.msg.sync.single',
174
+ name: 'im.msg.sync.single',
179
175
  resource: 'msg',
180
176
  method: 'msg.sync.single',
181
- action: 'yimiaoban.msg.sync.single',
182
- summary: '拉取与某人的单聊消息(倒序单页,默认当天;时间范围转消息 id 区间)',
177
+ action: 'im.msg.sync.single',
178
+ summary: '拉取与某人的单聊消息(倒序,默认当天;时间范围转消息 id 区间并自动翻页拉完)',
183
179
  capability: 'msg',
184
180
  risk: READ,
185
181
  inputSchema: schemaOf({
186
182
  fromUid: { type: 'string', pattern: '^\\d+$', description: '对方 uid(必填)' },
187
183
  fromCid: { type: 'string', pattern: '^\\d+$', description: '对方 cid(必填)' },
188
- num: { type: 'integer', minimum: 1, maximum: 50, description: '单页数量(默认 20,最多 50)' },
189
- latest: { type: 'boolean', description: '拉最新不限日期' },
190
- from: { type: 'string', description: '起始时间(YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss 或 unix 秒)' },
191
- to: { type: 'string', description: '结束时间' },
184
+ num: { type: 'integer', minimum: 1, maximum: 50, description: '每页数量(默认 50,最多 50)' },
185
+ latest: { type: 'boolean', description: '拉最新不限日期(无界区间,只拉一页)' },
186
+ from: { type: 'string', description: '起始时间(YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss 或 unix 秒);跨度 > 7 天自动收敛为该范围最后 7 天' },
187
+ to: { type: 'string', description: '结束时间(同上)' },
192
188
  start: { type: 'string', description: '显式起始消息 id(最高优先)' },
193
189
  end: { type: 'string', description: '显式结束消息 id' },
194
190
  imgFormat: { type: 'string', enum: ['small', 'large', 'original'], description: '预览规格(默认 small)' },
@@ -197,63 +193,79 @@ const msgSyncSingle = {
197
193
  const fromUid = String(args.fromUid);
198
194
  const fromCid = String(args.fromCid);
199
195
  if (!fromUid || !fromCid || fromUid === '0' || fromCid === '0') {
200
- throw ymbValidationError('id_invalid', 'fromUid/fromCid 必须非 0');
196
+ throw imValidationError('id_invalid', 'fromUid/fromCid 必须非 0');
201
197
  }
202
- const { start, end } = resolveStartEnd(args);
203
- const body = {
204
- trans_id: 0,
205
- dev: 4,
206
- enc_type: 0,
207
- datas: [{ from_cid: fromCid, from_uid: fromUid, start, end, max_num: pageSizeOf(args) }],
208
- };
209
- const res = await host.request({
210
- method: 'POST',
211
- path: '/api/em/msg/executeIm/msg/syncSingleMsg',
212
- body,
213
- operation: 'yimiaoban.msg.sync.single',
198
+ const { start, end, scope, shrink } = resolveRange(args);
199
+ const num = pageSizeOf(args);
200
+ // 有界区间(end != 0:时间范围/默认当天/显式 end)自动循环翻页拉完;无界区间(latest)只拉一页
201
+ const autoLoop = end !== '0';
202
+ let actCode = 0;
203
+ const pulled = await pullPaged({
204
+ num,
205
+ start,
206
+ end,
207
+ autoLoop,
208
+ requestOnePage: async (pageStart, pageEnd, maxNum) => {
209
+ const body = {
210
+ trans_id: 0,
211
+ dev: 4,
212
+ enc_type: 0,
213
+ datas: [{ from_cid: fromCid, from_uid: fromUid, start: pageStart, end: pageEnd, max_num: maxNum }],
214
+ };
215
+ const res = await host.request({
216
+ method: 'POST',
217
+ path: '/api/em/msg/executeIm/msg/syncSingleMsg',
218
+ body,
219
+ operation: 'im.msg.sync.single',
220
+ });
221
+ // 1303=无聊天记录:按成功空列表返回(与群聊口径一致),并说明本次口径
222
+ actCode = Number(res?.data?.actionMsg?.code ?? -1);
223
+ if (actCode === 1303)
224
+ return [];
225
+ assertImOk(res, '拉取单聊消息');
226
+ const inner = unwrapInner(res);
227
+ const outerDatas = inner?.datas || [];
228
+ const rows = [];
229
+ for (const group of outerDatas) {
230
+ const list = group?.datas || group?.data || [];
231
+ if (Array.isArray(list))
232
+ rows.push(...list);
233
+ }
234
+ return rows;
235
+ },
214
236
  });
215
- const inner = unwrapInner(res);
216
- const outerDatas = inner?.datas || [];
217
- const rawRows = [];
218
- for (const group of outerDatas) {
219
- const list = group?.datas || group?.data || [];
220
- if (Array.isArray(list))
221
- rawRows.push(...list);
222
- }
223
- // 1303=无聊天记录:按成功空列表返回(与群聊口径一致),并说明本次口径
224
- const actCode = Number(res?.data?.actionMsg?.code ?? -1);
225
- if (actCode !== 1303)
226
- assertImOk(res, '拉取单聊消息');
227
237
  const authUid = await resolveAuthUid(host);
228
- const messages = await enrichMessages(rawRows, host, {
238
+ const messages = await enrichMessages(pulled.rows, host, {
229
239
  authUid,
230
240
  user: { cid: fromCid, uid: fromUid },
231
241
  imgFormat: args.imgFormat,
232
242
  });
233
- return ymbSuccess('yimiaoban.msg.sync.single', {
243
+ sortMessagesNewestFirst(messages);
244
+ return imSuccess('im.msg.sync.single', {
234
245
  total: messages.length,
235
246
  messages,
236
- range: { from: args.from, to: args.to, start, end },
237
- ...pageMeta(messages, args),
247
+ range: { from: args.from, to: args.to, start, end, scope, autoPaged: autoLoop },
248
+ ...paginationMeta(pulled, num),
249
+ ...(shrink ? { rangeShrink: rangeShrinkMeta(shrink) } : {}),
238
250
  ...(actCode === 1303 ? { empty: true, emptyReason: emptyPageNote(args) } : {}),
239
251
  });
240
252
  },
241
253
  };
242
254
  /** 拉群聊消息。 */
243
255
  const msgSyncGroup = {
244
- name: 'yimiaoban.msg.sync.group',
256
+ name: 'im.msg.sync.group',
245
257
  resource: 'msg',
246
258
  method: 'msg.sync.group',
247
- action: 'yimiaoban.msg.sync.group',
248
- summary: '拉取某群聊天消息(倒序单页,默认当天;type=0 必传)',
259
+ action: 'im.msg.sync.group',
260
+ summary: '拉取某群聊天消息(倒序,默认当天;有界区间自动翻页拉完;type=0 必传)',
249
261
  capability: 'msg',
250
262
  risk: READ,
251
263
  inputSchema: schemaOf({
252
264
  groupId: { type: 'string', pattern: '^\\d+$', description: '群 id(必填)' },
253
- num: { type: 'integer', minimum: 1, maximum: 50, description: '单页数量(默认 20,最多 50)' },
254
- latest: { type: 'boolean', description: '拉最新不限日期' },
255
- from: { type: 'string', description: '起始时间' },
256
- to: { type: 'string', description: '结束时间' },
265
+ num: { type: 'integer', minimum: 1, maximum: 50, description: '每页数量(默认 50,最多 50)' },
266
+ latest: { type: 'boolean', description: '拉最新不限日期(无界区间,只拉一页)' },
267
+ from: { type: 'string', description: '起始时间;跨度 > 7 天自动收敛为该范围最后 7 天' },
268
+ to: { type: 'string', description: '结束时间(同上)' },
257
269
  startId: { type: 'string', description: '显式起始消息 id(最高优先)' },
258
270
  endId: { type: 'string', description: '显式结束消息 id' },
259
271
  imgFormat: { type: 'string', enum: ['small', 'large', 'original'], description: '预览规格(默认 small)' },
@@ -261,60 +273,70 @@ const msgSyncGroup = {
261
273
  handler: async (args, { host }) => {
262
274
  const groupId = String(args.groupId);
263
275
  if (!groupId || groupId === '0')
264
- throw ymbValidationError('id_invalid', 'groupId 必须非 0');
276
+ throw imValidationError('id_invalid', 'groupId 必须非 0');
265
277
  // 群聊显式 id flag 名为 startId/endId
266
- const start = args.startId !== undefined && args.startId !== null && args.startId !== ''
267
- ? String(args.startId)
268
- : (args.latest === true ? MAX_MSG_ID : resolveStartEnd(args).start);
269
- const end = args.endId !== undefined && args.endId !== null && args.endId !== ''
270
- ? String(args.endId)
271
- : '0';
272
- const body = {
273
- trans_id: 0,
274
- dev: 4,
275
- type: 0,
276
- enc_type: 0,
277
- datas: [{ group_id: groupId, start, end, max_num: pageSizeOf(args) }],
278
- };
279
- const res = await host.request({
280
- method: 'POST',
281
- path: '/api/em/msg/executeIm/chat/syncGroupMsg',
282
- body,
283
- operation: 'yimiaoban.msg.sync.group',
278
+ const { start, end, scope, shrink } = resolveRange(args, { start: 'startId', end: 'endId' });
279
+ const num = pageSizeOf(args);
280
+ const autoLoop = end !== '0';
281
+ let actCode = 0;
282
+ const pulled = await pullPaged({
283
+ num,
284
+ start,
285
+ end,
286
+ autoLoop,
287
+ requestOnePage: async (pageStart, pageEnd, maxNum) => {
288
+ const body = {
289
+ trans_id: 0,
290
+ dev: 4,
291
+ type: 0,
292
+ enc_type: 0,
293
+ datas: [{ group_id: groupId, start: pageStart, end: pageEnd, max_num: maxNum }],
294
+ };
295
+ const res = await host.request({
296
+ method: 'POST',
297
+ path: '/api/em/msg/executeIm/chat/syncGroupMsg',
298
+ body,
299
+ operation: 'im.msg.sync.group',
300
+ });
301
+ actCode = Number(res?.data?.actionMsg?.code ?? -1);
302
+ if (actCode === 1303)
303
+ return [];
304
+ assertImOk(res, '拉取群聊消息');
305
+ const inner = unwrapInner(res);
306
+ const outerDatas = inner?.datas || [];
307
+ const rows = [];
308
+ for (const group of outerDatas) {
309
+ const list = group?.datas || group?.data || [];
310
+ if (Array.isArray(list))
311
+ rows.push(...list);
312
+ }
313
+ return rows;
314
+ },
284
315
  });
285
- const inner = unwrapInner(res);
286
- const outerDatas = inner?.datas || [];
287
- const rawRows = [];
288
- for (const group of outerDatas) {
289
- const list = group?.datas || group?.data || [];
290
- if (Array.isArray(list))
291
- rawRows.push(...list);
292
- }
293
- const actCode = Number(res?.data?.actionMsg?.code ?? -1);
294
- if (actCode !== 1303)
295
- assertImOk(res, '拉取群聊消息');
296
316
  const authUid = await resolveAuthUid(host);
297
- const messages = await enrichMessages(rawRows, host, {
317
+ const messages = await enrichMessages(pulled.rows, host, {
298
318
  authUid,
299
319
  groupId,
300
320
  imgFormat: args.imgFormat,
301
321
  });
302
- return ymbSuccess('yimiaoban.msg.sync.group', {
322
+ sortMessagesNewestFirst(messages);
323
+ return imSuccess('im.msg.sync.group', {
303
324
  groupId,
304
325
  total: messages.length,
305
326
  messages,
306
- range: { from: args.from, to: args.to, start, end },
307
- ...pageMeta(messages, args),
327
+ range: { from: args.from, to: args.to, start, end, scope, autoPaged: autoLoop },
328
+ ...paginationMeta(pulled, num),
329
+ ...(shrink ? { rangeShrink: rangeShrinkMeta(shrink) } : {}),
308
330
  ...(actCode === 1303 ? { empty: true, emptyReason: emptyPageNote(args) } : {}),
309
331
  });
310
332
  },
311
333
  };
312
334
  /** 群置顶消息同步。 */
313
335
  const msgTopSync = {
314
- name: 'yimiaoban.msg.top.sync',
336
+ name: 'im.msg.top.sync',
315
337
  resource: 'msg',
316
338
  method: 'msg.top.sync',
317
- action: 'yimiaoban.msg.top.sync',
339
+ action: 'im.msg.top.sync',
318
340
  summary: '同步群置顶消息(摘要 + 消息内容)',
319
341
  capability: 'msg',
320
342
  risk: READ,
@@ -322,11 +344,12 @@ const msgTopSync = {
322
344
  groupId: { type: 'string', pattern: '^\\d+$', description: '群 id(必填)' },
323
345
  msgids: { type: 'array', items: { type: 'string' }, description: '仅同步指定消息 id(缺省=全部置顶)' },
324
346
  encType: { type: 'integer', enum: [0, 1, 2, 3], description: '加密类型(默认 0,不解密)' },
347
+ imgFormat: { type: 'string', enum: ['small', 'large', 'original'], description: '置顶消息内图片的预览规格(默认 small)' },
325
348
  }, { required: ['groupId'], description: '同步群置顶消息' }),
326
349
  handler: async (args, { host }) => {
327
350
  const groupId = String(args.groupId);
328
351
  if (!groupId || groupId === '0')
329
- throw ymbValidationError('id_invalid', 'groupId 必须非 0');
352
+ throw imValidationError('id_invalid', 'groupId 必须非 0');
330
353
  const body = compact({
331
354
  group_id: groupId,
332
355
  enc_type: Number(args.encType ?? 0),
@@ -336,7 +359,7 @@ const msgTopSync = {
336
359
  method: 'POST',
337
360
  path: '/api/em/msg/executeIm/msg/syncGroupTopMsg',
338
361
  body,
339
- operation: 'yimiaoban.msg.top.sync',
362
+ operation: 'im.msg.top.sync',
340
363
  });
341
364
  assertImOk(res, '同步置顶消息');
342
365
  const inner = unwrapInner(res);
@@ -356,7 +379,7 @@ const msgTopSync = {
356
379
  imgFormat: args.imgFormat,
357
380
  authUid: await resolveAuthUid(host),
358
381
  });
359
- return ymbSuccess('yimiaoban.msg.top.sync', {
382
+ return imSuccess('im.msg.top.sync', {
360
383
  groupId,
361
384
  total: summary.length,
362
385
  infos: summary,
@@ -366,10 +389,10 @@ const msgTopSync = {
366
389
  };
367
390
  /** 单聊已读状态。 */
368
391
  const msgReadSingle = {
369
- name: 'yimiaoban.msg.read.single',
392
+ name: 'im.msg.read.single',
370
393
  resource: 'msg',
371
394
  method: 'msg.read.single',
372
- action: 'yimiaoban.msg.read.single',
395
+ action: 'im.msg.read.single',
373
396
  summary: '查询单聊消息阅读状态(msgids=自己发出 / recvMsgids=自己接收)',
374
397
  capability: 'msg',
375
398
  risk: READ,
@@ -383,7 +406,7 @@ const msgReadSingle = {
383
406
  const hasSent = Array.isArray(args.msgids) && args.msgids.length > 0;
384
407
  const hasRecv = Array.isArray(args.recvMsgids) && args.recvMsgids.length > 0;
385
408
  if (!hasSent && !hasRecv)
386
- throw ymbValidationError('msgids_required', 'msgids / recvMsgids 至少其一');
409
+ throw imValidationError('msgids_required', 'msgids / recvMsgids 至少其一');
387
410
  const body = compact({
388
411
  data: {
389
412
  trans_id: 0,
@@ -396,7 +419,7 @@ const msgReadSingle = {
396
419
  method: 'POST',
397
420
  path: '/api/em/msg/executeIm/msg/getSingleMsgReadStatus',
398
421
  body,
399
- operation: 'yimiaoban.msg.read.single',
422
+ operation: 'im.msg.read.single',
400
423
  });
401
424
  assertImOk(res, '查询单聊阅读状态');
402
425
  const inner = unwrapInner(res);
@@ -410,15 +433,15 @@ const msgReadSingle = {
410
433
  dev: d.dev,
411
434
  }))
412
435
  : [];
413
- return ymbSuccess('yimiaoban.msg.read.single', { total: rows.length, items: rows });
436
+ return imSuccess('im.msg.read.single', { total: rows.length, items: rows });
414
437
  },
415
438
  };
416
439
  /** 群消息已读状态(未读数)。 */
417
440
  const msgReadGroup = {
418
- name: 'yimiaoban.msg.read.group',
441
+ name: 'im.msg.read.group',
419
442
  resource: 'msg',
420
443
  method: 'msg.read.group',
421
- action: 'yimiaoban.msg.read.group',
444
+ action: 'im.msg.read.group',
422
445
  summary: '查询群消息阅读状态汇总(每条消息已读/未读情况,原样输出)',
423
446
  capability: 'msg',
424
447
  risk: READ,
@@ -431,7 +454,7 @@ const msgReadGroup = {
431
454
  const hasSent = Array.isArray(args.msgids) && args.msgids.length > 0;
432
455
  const hasRecv = Array.isArray(args.recvMsgids) && args.recvMsgids.length > 0;
433
456
  if (!hasSent && !hasRecv)
434
- throw ymbValidationError('msgids_required', 'msgids / recvMsgids 至少其一');
457
+ throw imValidationError('msgids_required', 'msgids / recvMsgids 至少其一');
435
458
  const body = compact({
436
459
  trans_id: 0,
437
460
  group_id: String(args.groupId),
@@ -442,11 +465,11 @@ const msgReadGroup = {
442
465
  method: 'POST',
443
466
  path: '/api/em/msg/executeIm/msg/getGroupMsgReadStatus',
444
467
  body,
445
- operation: 'yimiaoban.msg.read.group',
468
+ operation: 'im.msg.read.group',
446
469
  });
447
470
  assertImOk(res, '查询群阅读状态');
448
471
  const inner = unwrapInner(res);
449
- return ymbSuccess('yimiaoban.msg.read.group', {
472
+ return imSuccess('im.msg.read.group', {
450
473
  groupId: String(args.groupId),
451
474
  raw: Array.isArray(inner) ? inner : inner,
452
475
  });
@@ -454,10 +477,10 @@ const msgReadGroup = {
454
477
  };
455
478
  /** 群消息阅读状态详情(谁已读/未读)。 */
456
479
  const msgReadGroupDetail = {
457
- name: 'yimiaoban.msg.read.group.detail',
480
+ name: 'im.msg.read.group.detail',
458
481
  resource: 'msg',
459
482
  method: 'msg.read.group.detail',
460
- action: 'yimiaoban.msg.read.group.detail',
483
+ action: 'im.msg.read.group.detail',
461
484
  summary: '群消息阅读详情(unread/read count + 每人状态),支持分页',
462
485
  capability: 'msg',
463
486
  risk: READ,
@@ -481,7 +504,7 @@ const msgReadGroupDetail = {
481
504
  method: 'POST',
482
505
  path: '/api/em/msg/executeIm/group/syncGroupReadStatus',
483
506
  body,
484
- operation: 'yimiaoban.msg.read.group.detail',
507
+ operation: 'im.msg.read.group.detail',
485
508
  });
486
509
  assertImOk(res, '同步群阅读详情');
487
510
  const inner = unwrapInner(res);
@@ -496,7 +519,7 @@ const msgReadGroupDetail = {
496
519
  dev: d.dev,
497
520
  time: formatFullTime(d.time),
498
521
  }));
499
- return ymbSuccess('yimiaoban.msg.read.group.detail', {
522
+ return imSuccess('im.msg.read.group.detail', {
500
523
  groupId: String(args.groupId),
501
524
  msgid: String(args.msgid),
502
525
  unreadCount: inner?.unread_count,
@@ -516,4 +539,4 @@ export const msgReadOperations = [
516
539
  msgReadGroup,
517
540
  msgReadGroupDetail,
518
541
  ];
519
- export { enrichMessages, resolveStartEnd };
542
+ export { enrichMessages, resolveRange };