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
@@ -0,0 +1,481 @@
1
+ import { okrApiError, okrValidationError } from '../errors.js';
2
+ import { businessMessage, isDatajsonSuccess } from '../host.js';
3
+ import { OKR_EB_FORM_TAG, buildStandardDetailPath, createDetailUrlResolver, fetchGoalRaw, okrAbsoluteUrl, resolveEbFormId, resolveLink, } from './link.js';
4
+ import { assertLinkSupported, buildGoalTable, compact, ebMainTables, ebPeriodFilters, normalizeEbGoal, normalizeStandardGoal, resolvePeriod, toIdString, toPersonIdString, } from './shared.js';
5
+ import { okrSuccess, schemaOf, SCHEMA_ID, SCHEMA_PERSON_ID } from './types.js';
6
+ // ---------------------------------------------------------------------------
7
+ // 链路判定(租户缓存 1 天,禁止跳过缓存直接调用 okr_searchAppver)
8
+ // ---------------------------------------------------------------------------
9
+ const okrVersionCheck = {
10
+ name: 'okr.version.check',
11
+ resource: 'okr',
12
+ method: 'version.check',
13
+ action: 'okr.version.check',
14
+ summary: '判定当前租户的 OKR 目标接口链路(standard / eb):先读 1 天租户缓存,未命中才调用 okr_searchAppver 读取 ver_name',
15
+ capability: 'okr',
16
+ risk: 'read',
17
+ inputSchema: schemaOf({
18
+ refresh: { type: 'boolean', default: false, description: 'true 时忽略缓存重新调用版本接口' },
19
+ }),
20
+ handler: async (args, { host }) => {
21
+ const info = await resolveLink(host, { refresh: args.refresh === true });
22
+ return okrSuccess('okr.version.check', {
23
+ ...info,
24
+ versionInterface: 'okr_searchAppver',
25
+ });
26
+ },
27
+ };
28
+ // ---------------------------------------------------------------------------
29
+ // ebuilder 目标详情表单 id(长期缓存)
30
+ // ---------------------------------------------------------------------------
31
+ const okrEbFormResolve = {
32
+ name: 'okr.eb.form.resolve',
33
+ resource: 'okr',
34
+ method: 'eb.form.resolve',
35
+ action: 'okr.eb.form.resolve',
36
+ summary: '解析 ebuilder 目标详情表单 id(appTag weaver-wr-goal-eb + formTag uf_wrgm_baseinfo),用于生成目标详情页链接;结果按租户长期缓存',
37
+ capability: 'okr',
38
+ risk: 'read',
39
+ inputSchema: schemaOf({}),
40
+ handler: async (_args, { host }) => {
41
+ const { link } = await resolveLink(host);
42
+ assertLinkSupported(link, 'eb', 'okr.eb.form.resolve', '当前租户走 e10 标准版链路,目标详情页地址为 /sp/goal/openDetail?id=目标id,无需 ebuilder 表单 id');
43
+ const info = await resolveEbFormId(host);
44
+ return okrSuccess('okr.eb.form.resolve', { ...info, appTag: info.appTag, formTag: OKR_EB_FORM_TAG });
45
+ },
46
+ };
47
+ // ---------------------------------------------------------------------------
48
+ // 目标详情页链接
49
+ // ---------------------------------------------------------------------------
50
+ function toIdList(value) {
51
+ if (Array.isArray(value))
52
+ return value.map((item) => toIdString(item, 'ids'));
53
+ if (typeof value === 'string' || typeof value === 'number') {
54
+ return String(value)
55
+ .split(',')
56
+ .map((part) => part.trim())
57
+ .filter((part) => part !== '')
58
+ .map((part) => toIdString(part, 'ids'));
59
+ }
60
+ throw okrValidationError('ids_required', 'ids 必填,传目标 ID 数组或英文逗号拼接的目标 ID 字符串');
61
+ }
62
+ const okrViewlink = {
63
+ name: 'okr.viewlink',
64
+ resource: 'okr',
65
+ method: 'viewlink',
66
+ action: 'okr.viewlink',
67
+ summary: '为已有目标 ID 生成可点击的目标详情页链接(标准版 /sp/goal/openDetail?id=,eb 版 /sp/ebdfpage/card/0/表单id/目标id)',
68
+ capability: 'okr',
69
+ risk: 'read',
70
+ inputSchema: schemaOf({
71
+ ids: {
72
+ oneOf: [
73
+ { type: 'array', items: SCHEMA_ID, minItems: 1 },
74
+ { type: 'string', pattern: '^\\d+(,\\d+)*$' },
75
+ ],
76
+ description: '目标 ID 数组,或英文逗号拼接的目标 ID 字符串',
77
+ },
78
+ anchor: { type: 'string', minLength: 1, description: '链接展示文案,默认用目标名称;未查详情时默认「查看详情」' },
79
+ }, { required: ['ids'] }),
80
+ handler: async (args, { host }) => {
81
+ const ids = toIdList(args.ids);
82
+ const { link } = await resolveLink(host);
83
+ const resolver = await createDetailUrlResolver(host, link);
84
+ const links = [];
85
+ const session = await host.getSession();
86
+ for (const id of ids) {
87
+ const path = await resolver.resolve(id);
88
+ links.push({
89
+ goalId: id,
90
+ path,
91
+ url: okrAbsoluteUrl(session.baseUrl, path),
92
+ anchor: typeof args.anchor === 'string' && args.anchor ? args.anchor : '查看详情',
93
+ });
94
+ }
95
+ const available = links.every((item) => Boolean(item.path));
96
+ if (!available) {
97
+ return okrSuccess('okr.viewlink', {
98
+ status: 'VIEWLINK_UNAVAILABLE',
99
+ link,
100
+ available: false,
101
+ links,
102
+ warnings: resolver.warnings.length > 0 ? resolver.warnings : ['目标详情页链接暂不可用'],
103
+ });
104
+ }
105
+ return okrSuccess('okr.viewlink', { status: 'COMPLETE', link, available: true, links });
106
+ },
107
+ };
108
+ // ---------------------------------------------------------------------------
109
+ // 分页查询目标
110
+ // ---------------------------------------------------------------------------
111
+ function pageOf(args) {
112
+ const pageNo = args.page_no === undefined ? 1 : Number(args.page_no);
113
+ const pageSize = args.page_size === undefined ? 10 : Number(args.page_size);
114
+ if (!Number.isInteger(pageNo) || pageNo < 1) {
115
+ throw okrValidationError('page_invalid', 'page_no 必须是大于 0 的整数');
116
+ }
117
+ if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > 100) {
118
+ throw okrValidationError('page_invalid', 'page_size 必须是 1 到 100 之间的整数');
119
+ }
120
+ return { pageNo, pageSize };
121
+ }
122
+ function resolveQueryScope(args) {
123
+ const scope = args.query_scope === undefined ? 'self' : String(args.query_scope);
124
+ if (scope !== 'self' && scope !== 'all') {
125
+ throw okrValidationError('query_scope_invalid', 'query_scope 取值必须是 self(本人对应周期)或 all(跨人检索)');
126
+ }
127
+ return scope;
128
+ }
129
+ const okrList = {
130
+ name: 'okr.list',
131
+ resource: 'okr',
132
+ method: 'list',
133
+ action: 'okr.list',
134
+ summary: '分页查询 OKR 目标,返回固定四列(目标名称、目标责任人名称、目标周期类型、目标周期范围)的表格,目标名称可点击跳转详情',
135
+ capability: 'okr',
136
+ risk: 'read',
137
+ inputSchema: schemaOf({
138
+ query_scope: {
139
+ type: 'string',
140
+ enum: ['self', 'all'],
141
+ default: 'self',
142
+ description: 'self=查询本人对应周期目标;all=按条件跨人检索',
143
+ },
144
+ period_type: { type: 'string', enum: ['1', '2', '3', '4'], description: '周期类型:1-年度 2-季度 3-月度 4-自定义(self 必填)' },
145
+ period_range: { type: 'string', description: '周期范围:年度/季度为 yyyy,月度为 yyyy-MM,自定义为「开始日期,结束日期」' },
146
+ period_quarter: { type: 'string', enum: ['1', '2', '3', '4'], description: '季度值(period_type=2 时必填)' },
147
+ name: { type: 'string', minLength: 1, description: '目标名称关键字(仅标准版链路,模糊匹配)' },
148
+ principalid: SCHEMA_PERSON_ID,
149
+ status: { type: 'string', pattern: '^\\d+(,\\d+)*$', description: '目标状态码,英文逗号拼接(仅标准版链路)' },
150
+ match: { type: 'string', enum: ['and', 'or'], default: 'and', description: '多条件关系(仅标准版链路)' },
151
+ page_no: { type: 'integer', minimum: 1, default: 1 },
152
+ page_size: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
153
+ }, { description: 'self 模式必填 period_type + period_range;all 模式按需传 name / principalid / status' }),
154
+ handler: async (args, { host }) => {
155
+ const { pageNo, pageSize } = pageOf(args);
156
+ const queryScope = resolveQueryScope(args);
157
+ const { link } = await resolveLink(host);
158
+ const session = await host.getSession();
159
+ const resolver = await createDetailUrlResolver(host, link);
160
+ const warnings = [];
161
+ const notes = [];
162
+ const hasPeriod = args.period_type !== undefined || args.period_range !== undefined;
163
+ if (queryScope === 'self' && !hasPeriod) {
164
+ throw okrValidationError('period_required', 'query_scope=self 时必须传 period_type 与 period_range');
165
+ }
166
+ const period = hasPeriod ? resolvePeriod(args) : null;
167
+ let goals = [];
168
+ let raw;
169
+ let paging = {};
170
+ if (link === 'standard') {
171
+ const body = compact({
172
+ page: pageNo,
173
+ pageSize,
174
+ viewType: 'list',
175
+ ...(queryScope === 'self'
176
+ ? {
177
+ condtype: '1',
178
+ subcondtype: '1',
179
+ status: 1,
180
+ statusList: [{ content: '0,1,4,5,6' }],
181
+ }
182
+ : {
183
+ condtype: '4',
184
+ subcondtype: '6',
185
+ isMore: 0,
186
+ scopeId: '0',
187
+ hideSubDep: 0,
188
+ hideSub: 1,
189
+ statusList: [{ content: args.status === undefined ? '1,2,4,5,6,7' : String(args.status) }],
190
+ type: args.match === undefined ? 'and' : String(args.match),
191
+ ...(args.name === undefined ? {} : { nameList: [{ mode: 'contain', content: String(args.name) }] }),
192
+ ...(args.principalid === undefined
193
+ ? {}
194
+ : { principalidList: [{ mode: 'eq', content: toPersonIdString(args.principalid, 'principalid') }] }),
195
+ }),
196
+ });
197
+ if (period) {
198
+ body.periodType = period.periodType;
199
+ body.periodRange = period.periodRange;
200
+ if (period.periodQuarter)
201
+ body.periodQuarter = Number(period.periodQuarter);
202
+ }
203
+ raw = await host.request({
204
+ method: 'POST',
205
+ path: '/api/workrelate/goal/getSearchList',
206
+ operation: 'okr.list',
207
+ body,
208
+ });
209
+ const list = Array.isArray(raw?.data?.list) ? raw.data.list : [];
210
+ goals = [];
211
+ for (const item of list) {
212
+ const goalId = item?.id === undefined || item?.id === null ? null : String(item.id);
213
+ const detailUrl = okrAbsoluteUrl(session.baseUrl, await resolver.resolve(goalId));
214
+ goals.push(normalizeStandardGoal(item, detailUrl, item?.keyresultList));
215
+ }
216
+ const total = raw?.data?.total ?? raw?.data?.count;
217
+ if (total !== undefined && total !== null)
218
+ paging.total = Number(total);
219
+ paging.hasNext = list.length === pageSize;
220
+ }
221
+ else {
222
+ // eb 链路:列表筛选只支持源资料列出的字段(creator / principalid / 周期字段),
223
+ // 名称模糊匹配与状态多选不具备实现依据,明确报错而不是静默忽略。
224
+ if (args.name !== undefined || args.status !== undefined) {
225
+ throw okrValidationError('link_filter_unsupported', 'ebuilder 链路的分页查询接口不支持按目标名称关键字或目标状态筛选;请改用 query_scope=self 或 principalid + 周期条件', { link, unsupportedFilters: ['name', 'status'] });
226
+ }
227
+ const mainTable = compact({
228
+ ...(queryScope === 'self' ? { creator: session.userId } : {}),
229
+ ...(args.principalid === undefined
230
+ ? {}
231
+ : { principalid: toPersonIdString(args.principalid, 'principalid') }),
232
+ ...(period ? ebPeriodFilters(period) : {}),
233
+ });
234
+ raw = await host.request({
235
+ method: 'POST',
236
+ path: '/api/ebuilder/form/formdata/v2/getFormDataList/okr_pageQueryGoal',
237
+ operation: 'okr.list',
238
+ body: {
239
+ datajson: {
240
+ mainTable,
241
+ pageInfo: { pageNo: String(pageNo), pageSize: String(pageSize) },
242
+ header: { operator: session.userId },
243
+ },
244
+ },
245
+ });
246
+ if (!isDatajsonSuccess(raw)) {
247
+ throw okrApiError('business_error', businessMessage(raw), { response: businessMessage(raw) });
248
+ }
249
+ const tables = ebMainTables(raw);
250
+ goals = [];
251
+ for (const mainTable of tables) {
252
+ const goalId = mainTable?.id === undefined || mainTable?.id === null ? null : String(mainTable.id);
253
+ const detailUrl = okrAbsoluteUrl(session.baseUrl, await resolver.resolve(goalId));
254
+ goals.push(normalizeEbGoal(mainTable, detailUrl));
255
+ }
256
+ paging.hasNext = tables.length === pageSize;
257
+ }
258
+ warnings.push(...resolver.warnings);
259
+ return okrSuccess('okr.list', {
260
+ status: 'COMPLETE',
261
+ link,
262
+ queryScope,
263
+ period: period
264
+ ? { periodType: period.periodType, periodRange: period.periodRange, periodQuarter: period.periodQuarter ?? null }
265
+ : null,
266
+ page: { pageNo, pageSize, ...paging },
267
+ count: goals.length,
268
+ goals,
269
+ table: buildGoalTable(goals),
270
+ }, { notes, ...(warnings.length > 0 ? { warnings } : {}) });
271
+ },
272
+ };
273
+ async function fetchCommentCount(host, goalId) {
274
+ try {
275
+ const response = await host.request({
276
+ method: 'POST',
277
+ path: '/api/goal/common/comment/commentPage',
278
+ operation: 'okr.get',
279
+ body: { pageNo: 1, pageSize: 1, targetId: goalId, module: 'goal', foldCommentList: false },
280
+ });
281
+ const total = response?.data?.page?.totalCount;
282
+ return { totalCount: total === undefined || total === null ? 0 : Number(total), unavailable: false };
283
+ }
284
+ catch {
285
+ return { totalCount: null, unavailable: true };
286
+ }
287
+ }
288
+ const okrGet = {
289
+ name: 'okr.get',
290
+ resource: 'okr',
291
+ method: 'get',
292
+ action: 'okr.get',
293
+ summary: '按目标 ID 查询单个目标详情;标准版链路会额外查询评论总条数并只返回「是否需要查看评论内容」的提示,不输出评论正文',
294
+ capability: 'okr',
295
+ risk: 'read',
296
+ inputSchema: schemaOf({
297
+ id: SCHEMA_ID,
298
+ include_comment_count: {
299
+ type: 'boolean',
300
+ default: true,
301
+ description: '是否查询评论总条数(仅标准版链路生效,源资料要求查询详情时执行)',
302
+ },
303
+ }, { required: ['id'] }),
304
+ handler: async (args, { host }) => {
305
+ const goalId = toIdString(args.id, 'id');
306
+ const { link } = await resolveLink(host);
307
+ const resolver = await createDetailUrlResolver(host, link);
308
+ const raw = await fetchGoalRaw(host, link, goalId);
309
+ if (!raw) {
310
+ throw okrValidationError('not_found', `未查询到目标 ${goalId},请确认目标 ID 是否正确或当前账号是否有查看权限`);
311
+ }
312
+ const session = await host.getSession();
313
+ const detailUrl = okrAbsoluteUrl(session.baseUrl, await resolver.resolve(goalId));
314
+ const goal = link === 'standard'
315
+ ? normalizeStandardGoal(raw, detailUrl, raw?.keyresultList)
316
+ : normalizeEbGoal(raw, detailUrl);
317
+ const notes = [];
318
+ let commentSummary = null;
319
+ if (link === 'standard' && args.include_comment_count !== false) {
320
+ const comment = await fetchCommentCount(host, goalId);
321
+ // 源资料:评论总条数为 0 时完全忽略评论模块,不输出任何评论相关文字。
322
+ if (!comment.unavailable && comment.totalCount !== null && comment.totalCount > 0) {
323
+ commentSummary = {
324
+ totalCount: comment.totalCount,
325
+ prompt: `该目标下共有${comment.totalCount}条评论,是否需要查看评论内容?`,
326
+ };
327
+ }
328
+ else if (comment.unavailable) {
329
+ notes.push('comment_count_unavailable');
330
+ }
331
+ }
332
+ else if (link === 'eb') {
333
+ notes.push('comment_api_unsupported_on_eb_link');
334
+ }
335
+ const data = {
336
+ status: 'COMPLETE',
337
+ link,
338
+ goalId,
339
+ goal,
340
+ ...(commentSummary ? { commentSummary } : {}),
341
+ raw,
342
+ };
343
+ return okrSuccess('okr.get', data, {
344
+ ...(notes.length > 0 ? { notes } : {}),
345
+ ...(resolver.warnings.length > 0 ? { warnings: resolver.warnings } : {}),
346
+ });
347
+ },
348
+ };
349
+ // ---------------------------------------------------------------------------
350
+ // 分页查询目标关键成果(ebuilder 链路专属)
351
+ // ---------------------------------------------------------------------------
352
+ const okrKrList = {
353
+ name: 'okr.kr.list',
354
+ resource: 'okr',
355
+ method: 'kr.list',
356
+ action: 'okr.kr.list',
357
+ summary: '分页查询指定目标下的关键成果(仅 ebuilder 链路:okr_pageQueryGoalKeyResults)',
358
+ capability: 'okr',
359
+ risk: 'read',
360
+ inputSchema: schemaOf({
361
+ object_id: SCHEMA_ID,
362
+ page_no: { type: 'integer', minimum: 1, default: 1 },
363
+ page_size: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
364
+ }, { required: ['object_id'] }),
365
+ handler: async (args, { host }) => {
366
+ const objectId = toIdString(args.object_id, 'object_id');
367
+ const { pageNo, pageSize } = pageOf(args);
368
+ const { link } = await resolveLink(host);
369
+ assertLinkSupported(link, 'eb', 'okr.kr.list', 'e10 标准版链路没有独立的关键成果分页接口,关键成果随目标列表/详情返回(okr.list 的 goals[].keyresultList、okr.get 的 goal.keyresultList)');
370
+ const session = await host.getSession();
371
+ const response = await host.request({
372
+ method: 'POST',
373
+ path: '/api/ebuilder/form/formdata/v2/getFormDataList/okr_pageQueryGoalKeyResults',
374
+ operation: 'okr.kr.list',
375
+ body: {
376
+ datajson: {
377
+ mainTable: { object_id: objectId },
378
+ pageInfo: { pageNo: String(pageNo), pageSize: String(pageSize) },
379
+ header: { operator: session.userId },
380
+ },
381
+ },
382
+ });
383
+ if (!isDatajsonSuccess(response)) {
384
+ throw okrApiError('business_error', businessMessage(response), { response: businessMessage(response) });
385
+ }
386
+ const items = ebMainTables(response);
387
+ return okrSuccess('okr.kr.list', {
388
+ status: 'COMPLETE',
389
+ link,
390
+ objectId,
391
+ page: { pageNo, pageSize, count: items.length, hasNext: items.length === pageSize },
392
+ keyresults: items,
393
+ });
394
+ },
395
+ };
396
+ // ---------------------------------------------------------------------------
397
+ // 分页查询目标评论(标准版链路专属)
398
+ // ---------------------------------------------------------------------------
399
+ const okrCommentList = {
400
+ name: 'okr.comment.list',
401
+ resource: 'okr',
402
+ method: 'comment.list',
403
+ action: 'okr.comment.list',
404
+ summary: '分页查询目标评论(仅标准版链路);只有在用户明确要求查看评论内容后才可调用',
405
+ capability: 'okr',
406
+ risk: 'read',
407
+ inputSchema: schemaOf({
408
+ target_id: SCHEMA_ID,
409
+ page_no: { type: 'integer', minimum: 1, default: 1 },
410
+ page_size: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
411
+ }, { required: ['target_id'] }),
412
+ handler: async (args, { host }) => {
413
+ const targetId = toIdString(args.target_id, 'target_id');
414
+ const { pageNo, pageSize } = pageOf(args);
415
+ const { link } = await resolveLink(host);
416
+ assertLinkSupported(link, 'standard', 'okr.comment.list', 'ebuilder 链路源资料未提供目标评论接口,无法查询评论内容');
417
+ const response = await host.request({
418
+ method: 'POST',
419
+ path: '/api/goal/common/comment/commentPage',
420
+ operation: 'okr.comment.list',
421
+ body: { pageNo, pageSize, targetId, module: 'goal', foldCommentList: false },
422
+ });
423
+ const page = response?.data?.page ?? {};
424
+ return okrSuccess('okr.comment.list', {
425
+ status: 'COMPLETE',
426
+ link,
427
+ targetId,
428
+ page: {
429
+ pageNo: page.pageNo ?? pageNo,
430
+ pageSize: page.pageSize ?? pageSize,
431
+ totalCount: page.totalCount ?? 0,
432
+ totalPages: page.totalPages ?? null,
433
+ hasNext: page.hasNext ?? false,
434
+ },
435
+ comments: Array.isArray(page.result) ? page.result : [],
436
+ });
437
+ },
438
+ };
439
+ // ---------------------------------------------------------------------------
440
+ // 目标详情页链接(供无法拿到 ID 时直接取链接的快捷能力)
441
+ // ---------------------------------------------------------------------------
442
+ const okrDetailLink = {
443
+ name: 'okr.detail.link',
444
+ resource: 'okr',
445
+ method: 'detail.link',
446
+ action: 'okr.detail.link',
447
+ summary: '返回当前链路的目标详情页地址模板(标准版 /sp/goal/openDetail?id=目标id;eb 版 /sp/ebdfpage/card/0/表单id/目标id)',
448
+ capability: 'okr',
449
+ risk: 'read',
450
+ inputSchema: schemaOf({}),
451
+ handler: async (_args, { host }) => {
452
+ const { link } = await resolveLink(host);
453
+ const session = await host.getSession();
454
+ if (link === 'standard') {
455
+ return okrSuccess('okr.detail.link', {
456
+ link,
457
+ pathTemplate: buildStandardDetailPath('{goalId}'),
458
+ urlTemplate: okrAbsoluteUrl(session.baseUrl, buildStandardDetailPath('{goalId}')),
459
+ formId: null,
460
+ });
461
+ }
462
+ const info = await resolveEbFormId(host);
463
+ return okrSuccess('okr.detail.link', {
464
+ link,
465
+ pathTemplate: info.detailUrlTemplate,
466
+ urlTemplate: okrAbsoluteUrl(session.baseUrl, info.detailUrlTemplate),
467
+ formId: info.formId,
468
+ formIdSource: info.source,
469
+ });
470
+ },
471
+ };
472
+ export const okrReadOperations = [
473
+ okrVersionCheck,
474
+ okrEbFormResolve,
475
+ okrDetailLink,
476
+ okrViewlink,
477
+ okrList,
478
+ okrGet,
479
+ okrKrList,
480
+ okrCommentList,
481
+ ];
@@ -0,0 +1,31 @@
1
+ import { okrValidationError } from '../errors.js';
2
+ import { okrReadOperations } from './read.js';
3
+ import { okrWriteOperations } from './write.js';
4
+ function buildRegistry() {
5
+ const registry = new Map();
6
+ const definitions = [
7
+ ...okrReadOperations,
8
+ ...okrWriteOperations,
9
+ ];
10
+ for (const definition of definitions) {
11
+ if (registry.has(definition.name)) {
12
+ throw new Error(`duplicate okr operation: ${definition.name}`);
13
+ }
14
+ registry.set(definition.name, definition);
15
+ }
16
+ return registry;
17
+ }
18
+ const okrOperationRegistry = buildRegistry();
19
+ export function okrOperationDefinitions() {
20
+ return [...okrOperationRegistry.values()];
21
+ }
22
+ export function getOkrOperation(operation) {
23
+ const definition = okrOperationRegistry.get(operation);
24
+ if (!definition) {
25
+ throw okrValidationError('operation_unknown', `OKR 目标模块不支持操作:${operation}`);
26
+ }
27
+ return definition;
28
+ }
29
+ export function hasOkrOperation(operation) {
30
+ return okrOperationRegistry.has(operation);
31
+ }