weaver-work-cli 0.1.32 → 0.1.36

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 (211) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/{archive-UMGX72K6.js → archive-XBVH7JU7.js} +2 -2
  3. package/dist/chunks/{archive-oa-N2IYBLF3.js → archive-oa-MZM3EKFQ.js} +2 -2
  4. package/dist/chunks/{asset-GLEGKFG5.js → asset-4XO7UOUW.js} +2 -2
  5. package/dist/chunks/{attachment-content-AQNX5N3S.js → attachment-content-VXSWANAC.js} +3 -2
  6. package/dist/chunks/{blog-E44OTVDA.js → blog-PGZKOPSC.js} +2 -2
  7. package/dist/chunks/{caizhilian-DQUFZXZL.js → caizhilian-BH4ZVGUN.js} +2 -2
  8. package/dist/chunks/{calendar-JKPIRKFD.js → calendar-MXEMTIO4.js} +2 -2
  9. package/dist/chunks/{chunk-QWY6PGL6.js → chunk-2LV74IWP.js} +361 -56
  10. package/dist/chunks/chunk-3SO6QL6U.js +73 -0
  11. package/dist/chunks/chunk-5DQEEGCC.js +229 -0
  12. package/dist/chunks/{chunk-G3QJULO2.js → chunk-6LLJFKJE.js} +1 -1
  13. package/dist/chunks/{chunk-C6R3B2ML.js → chunk-BPE37FPB.js} +35 -7
  14. package/dist/chunks/chunk-BYATLLEF.js +68 -0
  15. package/dist/chunks/chunk-BYBSCN4X.js +932 -0
  16. package/dist/chunks/{chunk-CVZ2JOSW.js → chunk-F746NKNF.js} +1 -1
  17. package/dist/chunks/{chunk-GCG2NMWR.js → chunk-HXJQI5NM.js} +4 -2
  18. package/dist/chunks/{chunk-YRVDW4WN.js → chunk-I6QGIBDM.js} +2 -2
  19. package/dist/chunks/{chunk-H7J4DC5R.js → chunk-JCSN3JGM.js} +2 -2
  20. package/dist/chunks/{chunk-2GA5ZIQL.js → chunk-JNG42JKG.js} +30 -1
  21. package/dist/chunks/{chunk-DW6AUUKS.js → chunk-JUXVYKII.js} +9 -4
  22. package/dist/chunks/{chunk-6RKD4DRZ.js → chunk-JYKABYCV.js} +2 -2
  23. package/dist/chunks/{chunk-6EFWDL7Y.js → chunk-NCOVUAZK.js} +2 -2
  24. package/dist/chunks/{chunk-E4Z23GHM.js → chunk-QHFANTX7.js} +1114 -904
  25. package/dist/chunks/{ebuilder-form-V5FG2EHC.js → chunk-QYGO5EE2.js} +22 -1148
  26. package/dist/chunks/{chunk-IURUFGZK.js → chunk-T72N74ZT.js} +50 -33
  27. package/dist/chunks/{chunk-H6XSTSLM.js → chunk-TC6MZAO3.js} +137 -204
  28. package/dist/chunks/{chunk-WKI2FBIQ.js → chunk-VPUTVEMC.js} +737 -341
  29. package/dist/chunks/{chunk-WSKBSQ2U.js → chunk-VPXOPQJI.js} +2 -2
  30. package/dist/chunks/chunk-WXFPWCXG.js +774 -0
  31. package/dist/chunks/{chunk-4YC43QQ4.js → chunk-XMGSYD6S.js} +4 -4
  32. package/dist/chunks/conflict-JAB2LJEZ.js +21 -0
  33. package/dist/chunks/continuation-RN6PZN2M.js +11 -0
  34. package/dist/chunks/contract-XI2EEIZU.js +9110 -0
  35. package/dist/chunks/cowork-SCPGLBA4.js +2527 -0
  36. package/dist/chunks/ebuilder-form-EYLHNOTA.js +121 -0
  37. package/dist/chunks/{ehr-HMFY6VIL.js → ehr-EAP77IMT.js} +1344 -27
  38. package/dist/chunks/{esb-ZYSVB7SG.js → esb-2TGGXEE7.js} +4 -4
  39. package/dist/chunks/{fna-B7RKPAZD.js → fna-2X7ZE7BU.js} +13 -8
  40. package/dist/chunks/{host-OCH2BCCV.js → host-C6EL2RKL.js} +3 -3
  41. package/dist/chunks/{host-45WED2KK.js → host-I4NRK4MX.js} +3 -3
  42. package/dist/chunks/{host-I4Z6BFYX.js → host-Q4LZGCRU.js} +3 -3
  43. package/dist/chunks/host-UEI5FGDM.js +23 -0
  44. package/dist/chunks/{host-KNZ52LJZ.js → host-XCLDDXKQ.js} +3 -3
  45. package/dist/chunks/{hrm-2KAZGUHI.js → hrm-YXERJM76.js} +3 -3
  46. package/dist/chunks/{im-ACJJWH4U.js → im-A4VZN2TQ.js} +88 -12
  47. package/dist/chunks/{invoice-ZK3WCX2U.js → invoice-2Z6YPMIS.js} +3 -3
  48. package/dist/chunks/{jiuchuanhui-5PQD3IL2.js → jiuchuanhui-AR5GMKZB.js} +2 -2
  49. package/dist/chunks/{lazy-dispatch-JQXBW3GM.js → lazy-dispatch-QXW7P4X3.js} +4 -4
  50. package/dist/chunks/{mail-S2HDDXO2.js → mail-7GZ6CPBJ.js} +45 -24
  51. package/dist/chunks/{meeting-QVN3I37L.js → meeting-3NMGA3MB.js} +278 -43
  52. package/dist/chunks/{okr-QNG4VC2Q.js → okr-BZ6XUOAG.js} +2 -2
  53. package/dist/chunks/operations-5QL3AECO.js +11 -0
  54. package/dist/chunks/{plan-A25EMW6U.js → plan-DR5CMUYP.js} +2 -2
  55. package/dist/chunks/{project-G6XV66DZ.js → project-6J63MK33.js} +2 -2
  56. package/dist/chunks/{registry-DC6KR3NH.js → registry-KDD7DHNK.js} +4 -4
  57. package/dist/chunks/{registry-2VLUAESA.js → registry-OZSMDVPP.js} +2 -2
  58. package/dist/chunks/{registry-7C5UMIPL.js → registry-TKX2E7C7.js} +2 -2
  59. package/dist/chunks/{registry-TI3CIUXF.js → registry-VRTNC6UR.js} +8 -6
  60. package/dist/chunks/{room-recommend-WRTHO6Y2.js → room-recommend-XCWRMB5P.js} +4 -3
  61. package/dist/chunks/{schedule-KFIITGSK.js → schedule-IVBICP32.js} +4 -3
  62. package/dist/chunks/{workflow-DJ7SYWAF.js → workflow-D74NFK3C.js} +179 -6
  63. package/dist/index.js +35 -25
  64. package/dist/internal/e10/auth-recovery.js +14 -4
  65. package/dist/internal/e10/fetch-timing.js +31 -0
  66. package/dist/internal/e10/request-runtime.js +5 -0
  67. package/dist/shortcuts/contract/host.js +34 -59
  68. package/dist/shortcuts/cowork/continuation.js +70 -0
  69. package/dist/shortcuts/cowork/errors.js +59 -0
  70. package/dist/shortcuts/cowork/host.js +180 -0
  71. package/dist/shortcuts/cowork/index.js +166 -0
  72. package/dist/shortcuts/cowork/manifest.js +65 -0
  73. package/dist/shortcuts/cowork/operations/discuss-write.js +277 -0
  74. package/dist/shortcuts/cowork/operations/item-write.js +380 -0
  75. package/dist/shortcuts/cowork/operations/member-write.js +283 -0
  76. package/dist/shortcuts/cowork/operations/permission-write.js +286 -0
  77. package/dist/shortcuts/cowork/operations/read.js +423 -0
  78. package/dist/shortcuts/cowork/operations/registry.js +39 -0
  79. package/dist/shortcuts/cowork/operations/review-write.js +157 -0
  80. package/dist/shortcuts/cowork/operations/shared.js +215 -0
  81. package/dist/shortcuts/cowork/operations/types.js +39 -0
  82. package/dist/shortcuts/cowork/operations.js +19 -0
  83. package/dist/shortcuts/ehr/host.js +4 -1
  84. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +757 -0
  85. package/dist/shortcuts/ehr/operations/recruit-position.js +367 -0
  86. package/dist/shortcuts/ehr/operations/recruit-stats.js +133 -0
  87. package/dist/shortcuts/ehr/operations/recruit-write.js +43 -16
  88. package/dist/shortcuts/ehr/operations/recruit.js +182 -10
  89. package/dist/shortcuts/ehr/operations/registry.js +6 -0
  90. package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
  91. package/dist/shortcuts/im/diagnostics.js +97 -0
  92. package/dist/shortcuts/im/host.js +58 -31
  93. package/dist/shortcuts/im/index.js +7 -2
  94. package/dist/shortcuts/im/operations/at-mention.js +127 -0
  95. package/dist/shortcuts/im/operations/file-user.js +10 -2
  96. package/dist/shortcuts/im/operations/group-read.js +26 -5
  97. package/dist/shortcuts/im/operations/group-write.js +35 -28
  98. package/dist/shortcuts/im/operations/msg-sync.js +7 -2
  99. package/dist/shortcuts/im/operations/msg-write.js +76 -10
  100. package/dist/shortcuts/im/operations/quote-mention.js +119 -0
  101. package/dist/shortcuts/im/operations/session.js +1 -1
  102. package/dist/shortcuts/im/operations/shared.js +10 -0
  103. package/dist/shortcuts/im/operations/types.js +13 -0
  104. package/dist/shortcuts/index.js +10 -0
  105. package/dist/shortcuts/mail/host.js +12 -1
  106. package/dist/shortcuts/mail/operations/types.js +17 -2
  107. package/dist/shortcuts/meeting/host.js +27 -34
  108. package/dist/shortcuts/meeting/index.js +79 -1
  109. package/dist/shortcuts/meeting/manifest.js +10 -0
  110. package/dist/shortcuts/meeting/operations/create.js +4 -1
  111. package/dist/shortcuts/meeting/operations/eb/catalog.js +10 -0
  112. package/dist/shortcuts/meeting/operations/eb/conflict.js +84 -8
  113. package/dist/shortcuts/meeting/operations/eb/create-flow.js +1195 -140
  114. package/dist/shortcuts/meeting/operations/eb/factory.js +170 -8
  115. package/dist/shortcuts/meeting/operations/eb/index.js +16 -3
  116. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +50 -5
  117. package/dist/shortcuts/meeting/operations/eb-fallback.js +163 -0
  118. package/dist/shortcuts/meeting/operations/env.js +99 -46
  119. package/dist/shortcuts/meeting/operations/form-fields.js +110 -0
  120. package/dist/shortcuts/meeting/operations/invitation.js +79 -20
  121. package/dist/shortcuts/meeting/operations/registry.js +2 -0
  122. package/dist/shortcuts/meeting/operations/standard-guard.js +71 -0
  123. package/dist/shortcuts/meeting/operations.js +16 -0
  124. package/dist/shortcuts/workflow/endpoints.js +8 -3
  125. package/dist/shortcuts/workflow/index.js +110 -1
  126. package/dist/shortcuts/workflow/operations/form.js +204 -36
  127. package/dist/shortcuts/workflow/operations/read.js +104 -23
  128. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +448 -0
  129. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.js +106 -0
  130. package/dist/shortcuts/workflow/operations/todoSmartConvert/businessRules.js +47 -0
  131. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +30 -23
  132. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +1 -0
  133. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +1 -0
  134. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +2 -1
  135. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +2 -4
  136. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +138 -181
  137. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +12 -7
  138. package/dist/shortcuts/workflow/operations.js +23 -1
  139. package/docs/e10-auth.md +1 -1
  140. package/docs/ehr.md +1 -1
  141. package/docs/fna.md +2 -1
  142. package/docs/im.md +8 -1
  143. package/docs/todo-smart-convert/README.md +1 -1
  144. package/docs/todo-smart-convert/data-contract.md +2 -2
  145. package/docs/todo-smart-convert/subgroup-rules.md +6 -0
  146. package/package.json +1 -1
  147. package/skill-template/business-info.json +18 -0
  148. package/skill-template/domains/cowork.md +14 -0
  149. package/skill-template/domains/yimiaoban.md +3 -3
  150. package/skill-template/skill-template.md +1 -1
  151. package/skills/weaver-e10-blog/SKILL.md +5 -5
  152. package/skills/weaver-e10-caizhilian/SKILL.md +5 -5
  153. package/skills/weaver-e10-calendar/SKILL.md +5 -5
  154. package/skills/weaver-e10-cowork/SKILL.md +101 -0
  155. package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
  156. package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
  157. package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
  158. package/skills/weaver-e10-esb/SKILL.md +5 -5
  159. package/skills/weaver-e10-hrm/SKILL.md +5 -5
  160. package/skills/weaver-e10-jinchengda/SKILL.md +2 -2
  161. package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -5
  162. package/skills/weaver-e10-jucailin/SKILL.md +38 -14
  163. package/skills/weaver-e10-jucailin/references/recruit-create.md +104 -0
  164. package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
  165. package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
  166. package/skills/weaver-e10-jucailin/references/salary.md +15 -11
  167. package/skills/weaver-e10-mail/SKILL.md +17 -14
  168. package/skills/weaver-e10-meeting/SKILL.md +442 -46
  169. package/skills/weaver-e10-meeting/references/meeting-eb.md +135 -3
  170. package/skills/weaver-e10-meeting/references/meeting-invitation.md +28 -2
  171. package/skills/weaver-e10-meeting/references/meeting-queries.md +9 -6
  172. package/skills/weaver-e10-meeting/references/meeting-verification.md +8 -6
  173. package/skills/weaver-e10-meeting.zip +0 -0
  174. package/skills/weaver-e10-okr/SKILL.md +5 -5
  175. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  176. package/skills/weaver-e10-plan/SKILL.md +5 -5
  177. package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
  178. package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
  179. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
  180. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
  181. package/skills/weaver-e10-shared/SKILL.md +12 -12
  182. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -4
  183. package/skills/weaver-e10-wenshuding/SKILL.md +5 -5
  184. package/skills/weaver-e10-workflow/SKILL.md +29 -5
  185. package/skills/weaver-e10-workflow/aigroup/default.json +88 -0
  186. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +66 -14
  187. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +1 -1
  188. package/skills/weaver-e10-workflow/references/workflow-memory.md +1 -1
  189. package/skills/weaver-e10-workflow/references/workflow-query.md +12 -10
  190. package/skills/weaver-e10-workflow/references/workflow-view.md +2 -2
  191. package/skills/weaver-e10-workflow/tools/todo-serve.cjs +239 -0
  192. package/skills/weaver-e10-workflow/{scripts → tools}/todo-summary.cjs +218 -28
  193. package/skills/weaver-e10-yepiaotong/SKILL.md +10 -8
  194. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +7 -7
  195. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +10 -10
  196. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +40 -37
  197. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +4 -4
  198. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +27 -38
  199. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +4 -4
  200. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +37 -29
  201. package/skills/weaver-e10-yimiaoban/SKILL.md +156 -33
  202. package/skills/weaver-e10-yimiaoban/references/ding-write.md +1 -1
  203. package/skills/weaver-e10-yimiaoban/references/error-codes.md +5 -1
  204. package/skills/weaver-e10-yimiaoban/references/group-read.md +5 -1
  205. package/skills/weaver-e10-yimiaoban/references/group-write.md +6 -4
  206. package/skills/weaver-e10-yimiaoban/references/msg-read.md +1 -0
  207. package/skills/weaver-e10-yimiaoban/references/msg-write.md +34 -2
  208. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +5 -2
  209. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +79 -58
  210. package/skills/weaver-e10-yimiaoban/references/user-remind.md +2 -2
  211. package/skills/weaver-e10-ziguanjia/SKILL.md +5 -5
@@ -0,0 +1,283 @@
1
+ import { CoworkCliError, coworkNotFoundError, coworkPartialError, coworkValidationError } from '../errors.js';
2
+ import { READ_BEFORE_WRITE, WRITE, SCHEMA_ID, coworkSuccess, schemaOf, } from './types.js';
3
+ import { assertEnum, compact, normalizeList, requireConfirm, toId, toIdList, toPositiveInt, unwrapData, verifyLease, } from './shared.js';
4
+ function isNetworkError(error) {
5
+ return error instanceof CoworkCliError && error.type === 'network';
6
+ }
7
+ const MEMBER_ACTIONS = ['invite', 'rejoin', 'join'];
8
+ /** 三动作的接口与表单形状(invite/rejoin 由 behavior 域、join 由 apply 域承担)。 */
9
+ const MEMBER_SPECS = {
10
+ invite: { path: '/api/cowork/behavior/inviteJoin' },
11
+ rejoin: { path: '/api/cowork/behavior/reJoin' },
12
+ join: { path: '/api/cowork/apply/applyCwItem' },
13
+ };
14
+ /** 已在协作内的人员(用参与人列表判定,仅作重复邀请提示,不作为存在性判据)。 */
15
+ async function currentParticipantIds(env, coworkId) {
16
+ try {
17
+ const response = await env.host.request({
18
+ method: 'POST',
19
+ path: '/api/cowork/view/participationAllList',
20
+ body: { id: coworkId, participationFrom: 'participant', current: 1, pageSize: 100 },
21
+ operation: 'cowork.member.action.prepare',
22
+ });
23
+ const { data } = normalizeList(response);
24
+ const rows = Array.isArray(data) ? data : [];
25
+ return new Set(rows.map((row) => String(row.id ?? row.userId ?? '')).filter(Boolean));
26
+ }
27
+ catch {
28
+ // 参与人列表失败不阻断主流程:它只用于"可能重复邀请"的提示。
29
+ return new Set();
30
+ }
31
+ }
32
+ const memberActionPrepare = {
33
+ name: 'cowork.member.action.prepare',
34
+ resource: 'cowork',
35
+ method: 'member.action.prepare',
36
+ action: 'cowork.member.action.prepare',
37
+ summary: '成员动作摘要:invite 邀请 / rejoin 重新加入 / join 申请加入;先读协作详情确认存在,并提示已在协作内的人员,不写入',
38
+ risk: READ_BEFORE_WRITE,
39
+ inputSchema: schemaOf({
40
+ action: { type: 'string', enum: [...MEMBER_ACTIONS], description: 'invite 邀请他人 / rejoin 重新加入 / join 申请加入(我)' },
41
+ coworkId: { ...SCHEMA_ID, description: '协作 id' },
42
+ userIds: {
43
+ type: 'array',
44
+ items: SCHEMA_ID,
45
+ maxItems: 50,
46
+ description: 'invite / rejoin 必填:人员 id 数组(join 不需要)',
47
+ },
48
+ }, { required: ['action', 'coworkId'] }),
49
+ handler: async (args, env) => {
50
+ const action = assertEnum(args.action, MEMBER_ACTIONS, 'action');
51
+ const coworkId = toId(args.coworkId, 'coworkId');
52
+ const detailResponse = await env.host.request({
53
+ method: 'POST',
54
+ path: '/api/cowork/view/viewCowork',
55
+ form: { id: coworkId },
56
+ operation: 'cowork.member.action.prepare',
57
+ });
58
+ const detail = (unwrapData(detailResponse) ?? {});
59
+ if (!detail || Object.keys(detail).length === 0) {
60
+ throw coworkNotFoundError('item_not_found', `协作 ${coworkId} 不存在或无权查看`);
61
+ }
62
+ let userIds;
63
+ let alreadyIn = [];
64
+ if (action !== 'join') {
65
+ userIds = toIdList(args.userIds, 'userIds');
66
+ if (!userIds || userIds.length === 0) {
67
+ throw coworkValidationError('user_ids_required', `${action} 必须提供 userIds(人员 id 数组)`);
68
+ }
69
+ const current = await currentParticipantIds(env, coworkId);
70
+ alreadyIn = userIds.filter((id) => current.has(id));
71
+ }
72
+ const session = await env.host.getSession();
73
+ const continuation = await env.continuation.issue({
74
+ operation: 'cowork.member.action.apply',
75
+ baseUrl: session.baseUrl,
76
+ profile: session.profile,
77
+ userId: session.userId,
78
+ action,
79
+ coworkId,
80
+ userIds: userIds ?? [],
81
+ });
82
+ return coworkSuccess('cowork.member.action.prepare', {
83
+ summary: {
84
+ action,
85
+ coworkId,
86
+ itemName: detail.itemName ?? '',
87
+ userIds: userIds ?? undefined,
88
+ userCount: userIds?.length,
89
+ alreadyParticipant: alreadyIn.length > 0 ? alreadyIn : undefined,
90
+ note: alreadyIn.length > 0
91
+ ? '上述人员已在协作参与人列表中,重复邀请可能被服务端判为无变化;请与用户确认后决定'
92
+ : undefined,
93
+ },
94
+ continuation,
95
+ });
96
+ },
97
+ };
98
+ const memberActionApply = {
99
+ name: 'cowork.member.action.apply',
100
+ resource: 'cowork',
101
+ method: 'member.action.apply',
102
+ action: 'cowork.member.action.apply',
103
+ summary: '执行成员动作(invite / rejoin / join),需 confirm=true 与 continuation',
104
+ risk: WRITE,
105
+ requiresConfirmation: true,
106
+ inputSchema: schemaOf({
107
+ action: { type: 'string', enum: [...MEMBER_ACTIONS] },
108
+ coworkId: { ...SCHEMA_ID },
109
+ userIds: { type: 'array', items: SCHEMA_ID, maxItems: 50 },
110
+ confirm: { type: 'boolean' },
111
+ continuation: { type: 'string' },
112
+ }, { required: ['action', 'coworkId', 'confirm', 'continuation'] }),
113
+ handler: async (args, env) => {
114
+ requireConfirm(args, 'cowork.member.action.apply');
115
+ const lease = await verifyLease(args, 'cowork.member.action.apply', env);
116
+ const action = assertEnum(args.action, MEMBER_ACTIONS, 'action');
117
+ const coworkId = toId(args.coworkId, 'coworkId');
118
+ if (lease.action !== action || lease.coworkId !== coworkId) {
119
+ throw coworkValidationError('target_changed', '与 prepare 时的目标不一致,请重新执行 prepare');
120
+ }
121
+ let form;
122
+ if (action === 'join') {
123
+ form = { ids: coworkId };
124
+ }
125
+ else {
126
+ const userIds = toIdList(args.userIds, 'userIds') ?? lease.userIds ?? [];
127
+ const leaseIds = lease.userIds ?? [];
128
+ if (userIds.join(',') !== leaseIds.join(',')) {
129
+ throw coworkValidationError('target_changed', '人员名单与 prepare 时不一致,请重新执行 prepare');
130
+ }
131
+ if (userIds.length === 0) {
132
+ throw coworkValidationError('user_ids_required', `${action} 必须提供 userIds`);
133
+ }
134
+ form = { ids: userIds.join(','), coworkId };
135
+ }
136
+ let response;
137
+ try {
138
+ response = await env.host.request({
139
+ method: 'POST',
140
+ path: MEMBER_SPECS[action].path,
141
+ form,
142
+ operation: 'cowork.member.action.apply',
143
+ });
144
+ }
145
+ catch (error) {
146
+ if (isNetworkError(error)) {
147
+ throw coworkPartialError('成员动作请求已发出但未收到确定结果,禁止自动重试:请用 cowork.participant.list 核对参与人', { action, coworkId });
148
+ }
149
+ throw error;
150
+ }
151
+ return coworkSuccess('cowork.member.action.apply', {
152
+ action,
153
+ coworkId,
154
+ userIds: action === 'join' ? undefined : String(form.ids).split(','),
155
+ result: unwrapData(response) ?? null,
156
+ });
157
+ },
158
+ };
159
+ const DECISIONS = ['approve', 'refuse'];
160
+ const DECISION_PATHS = {
161
+ approve: '/api/cowork/apply/approveCwItem',
162
+ refuse: '/api/cowork/apply/refuseCwItem',
163
+ };
164
+ /** 在待审批列表里定位申请记录(写动作必须先查真实 id,禁止猜)。 */
165
+ async function locateApplyRecord(env, applyId, maxPages = 5, pageSize = 50) {
166
+ for (let page = 1; page <= maxPages; page++) {
167
+ const response = await env.host.request({
168
+ method: 'POST',
169
+ path: '/api/cowork/apply/getCoworkApplyApproveList',
170
+ body: {
171
+ current: page,
172
+ applyerCondition: 'bl',
173
+ applyer: '',
174
+ applyerDeptCondition: 'bl',
175
+ applyerDept: '',
176
+ itemNameCondition: 'in',
177
+ type: 'and',
178
+ },
179
+ operation: 'cowork.apply.decide.prepare',
180
+ });
181
+ const { data } = normalizeList(response);
182
+ const rows = Array.isArray(data) ? data : [];
183
+ if (rows.length === 0)
184
+ return null;
185
+ const hit = rows.find((row) => String(row.id ?? '') === applyId);
186
+ if (hit)
187
+ return hit;
188
+ if (rows.length < pageSize)
189
+ return null;
190
+ }
191
+ return null;
192
+ }
193
+ const applyDecidePrepare = {
194
+ name: 'cowork.apply.decide.prepare',
195
+ resource: 'cowork',
196
+ method: 'apply.decide.prepare',
197
+ action: 'cowork.apply.decide.prepare',
198
+ summary: '加入申请审批摘要(approve 通过 / refuse 拒绝):在待审批列表中定位申请记录并回显申请人与协作主题,不写入',
199
+ risk: READ_BEFORE_WRITE,
200
+ inputSchema: schemaOf({
201
+ decision: { type: 'string', enum: [...DECISIONS], description: 'approve 通过 / refuse 拒绝' },
202
+ applyId: { ...SCHEMA_ID, description: '申请记录 id(来自 cowork.list scope=approve)' },
203
+ maxPages: { type: 'integer', minimum: 1, maximum: 20, description: '定位记录的翻页上限,默认 5' },
204
+ }, { required: ['decision', 'applyId'] }),
205
+ handler: async (args, env) => {
206
+ const decision = assertEnum(args.decision, DECISIONS, 'decision');
207
+ const applyId = toId(args.applyId, 'applyId');
208
+ const maxPages = toPositiveInt(args.maxPages, 'maxPages') ?? 5;
209
+ const hit = await locateApplyRecord(env, applyId, maxPages);
210
+ if (!hit) {
211
+ throw coworkNotFoundError('apply_not_found', `在前 ${maxPages} 页待审批列表中未找到申请记录 ${applyId}:请先用 cowork.list(scope=approve)确认,禁止对未确认的记录审批`);
212
+ }
213
+ const session = await env.host.getSession();
214
+ const continuation = await env.continuation.issue({
215
+ operation: 'cowork.apply.decide.apply',
216
+ baseUrl: session.baseUrl,
217
+ profile: session.profile,
218
+ userId: session.userId,
219
+ decision,
220
+ applyId,
221
+ });
222
+ return coworkSuccess('cowork.apply.decide.prepare', {
223
+ summary: {
224
+ decision,
225
+ applyId,
226
+ itemName: hit.itemName ?? null,
227
+ applyer: hit.applyerName ?? hit.applyer ?? null,
228
+ applyTime: hit.applyTime ?? hit.createTime ?? null,
229
+ },
230
+ continuation,
231
+ });
232
+ },
233
+ };
234
+ const applyDecideApply = {
235
+ name: 'cowork.apply.decide.apply',
236
+ resource: 'cowork',
237
+ method: 'apply.decide.apply',
238
+ action: 'cowork.apply.decide.apply',
239
+ summary: '执行加入申请审批(approve / refuse),需 confirm=true 与 continuation',
240
+ risk: WRITE,
241
+ requiresConfirmation: true,
242
+ inputSchema: schemaOf({
243
+ decision: { type: 'string', enum: [...DECISIONS] },
244
+ applyId: { ...SCHEMA_ID },
245
+ confirm: { type: 'boolean' },
246
+ continuation: { type: 'string' },
247
+ }, { required: ['decision', 'applyId', 'confirm', 'continuation'] }),
248
+ handler: async (args, env) => {
249
+ requireConfirm(args, 'cowork.apply.decide.apply');
250
+ const lease = await verifyLease(args, 'cowork.apply.decide.apply', env);
251
+ const decision = assertEnum(args.decision, DECISIONS, 'decision');
252
+ const applyId = toId(args.applyId, 'applyId');
253
+ if (lease.decision !== decision || lease.applyId !== applyId) {
254
+ throw coworkValidationError('target_changed', '与 prepare 时的目标不一致,请重新执行 prepare');
255
+ }
256
+ let response;
257
+ try {
258
+ response = await env.host.request({
259
+ method: 'POST',
260
+ path: DECISION_PATHS[decision],
261
+ form: compact({ ids: applyId }),
262
+ operation: 'cowork.apply.decide.apply',
263
+ });
264
+ }
265
+ catch (error) {
266
+ if (isNetworkError(error)) {
267
+ throw coworkPartialError('审批请求已发出但未收到确定结果,禁止自动重试:请用 cowork.list(scope=approve)核对是否已消失', { decision, applyId });
268
+ }
269
+ throw error;
270
+ }
271
+ return coworkSuccess('cowork.apply.decide.apply', {
272
+ decision,
273
+ applyId,
274
+ result: unwrapData(response) ?? null,
275
+ });
276
+ },
277
+ };
278
+ export const coworkMemberWriteOperations = [
279
+ memberActionPrepare,
280
+ memberActionApply,
281
+ applyDecidePrepare,
282
+ applyDecideApply,
283
+ ];
@@ -0,0 +1,286 @@
1
+ import { CoworkCliError, coworkNotFoundError, coworkPartialError, coworkValidationError } from '../errors.js';
2
+ import { READ_BEFORE_WRITE, WRITE, SCHEMA_ID, coworkSuccess, schemaOf, } from './types.js';
3
+ import { normalizeList, requireConfirm, toId, unwrapData, verifyLease, } from './shared.js';
4
+ function isNetworkError(error) {
5
+ return error instanceof CoworkCliError && error.type === 'network';
6
+ }
7
+ const DEFAULT_PERMISSION_ID = '5';
8
+ /** 共享权限列表(写操作前定位真实记录的唯一来源)。 */
9
+ async function listSharePermissions(env, coworkId, permissionId, pageSize = 50) {
10
+ const response = await env.host.request({
11
+ method: 'POST',
12
+ path: '/api/cowork/permission/getCoworkSharePermissionList',
13
+ body: {
14
+ sourceId: coworkId,
15
+ permissionId,
16
+ sourceType: 1,
17
+ current: 1,
18
+ pageSize,
19
+ id: coworkId,
20
+ permissionFrom: permissionId,
21
+ },
22
+ operation: 'cowork.permission.list',
23
+ });
24
+ const { data } = normalizeList(response);
25
+ return Array.isArray(data) ? data : [];
26
+ }
27
+ const permAddPrepare = {
28
+ name: 'cowork.permission.add.prepare',
29
+ resource: 'cowork',
30
+ method: 'permission.add.prepare',
31
+ action: 'cowork.permission.add.prepare',
32
+ summary: '新增共享对象的摘要:先读协作详情与现有共享权限列表,提示该人员是否已在,不写入',
33
+ risk: READ_BEFORE_WRITE,
34
+ inputSchema: schemaOf({
35
+ coworkId: { ...SCHEMA_ID, description: '协作 id' },
36
+ userId: { ...SCHEMA_ID, description: '被授权人员 id' },
37
+ userName: { type: 'string', maxLength: 100, description: '人员姓名(接口必填,用于展示)' },
38
+ userDept: { type: 'string', maxLength: 200, description: '部门名(可选,缺失可能导致服务端拒绝)' },
39
+ userTitle: { type: 'string', maxLength: 200, description: '岗位名(可选)' },
40
+ userCid: { type: 'string', maxLength: 100, description: '人员 cid(部分环境必填,缺失会被拒)' },
41
+ permissionId: { ...SCHEMA_ID, description: `权限类型 id,默认 ${DEFAULT_PERMISSION_ID}` },
42
+ }, { required: ['coworkId', 'userId', 'userName'] }),
43
+ handler: async (args, env) => {
44
+ const coworkId = toId(args.coworkId, 'coworkId');
45
+ const userId = toId(args.userId, 'userId');
46
+ const userName = String(args.userName ?? '').trim();
47
+ if (!userName)
48
+ throw coworkValidationError('user_name_required', 'userName 必填(接口要求展示名)');
49
+ const permissionId = toId(args.permissionId, 'permissionId') ?? DEFAULT_PERMISSION_ID;
50
+ const detailResponse = await env.host.request({
51
+ method: 'POST',
52
+ path: '/api/cowork/view/viewCowork',
53
+ form: { id: coworkId },
54
+ operation: 'cowork.permission.add.prepare',
55
+ });
56
+ const detail = (unwrapData(detailResponse) ?? {});
57
+ if (!detail || Object.keys(detail).length === 0) {
58
+ throw coworkNotFoundError('item_not_found', `协作 ${coworkId} 不存在或无权查看`);
59
+ }
60
+ const existing = await listSharePermissions(env, coworkId, permissionId);
61
+ const already = existing.some((row) => {
62
+ const rowUserId = String(row.userid ?? row.userId ?? row.id ?? '');
63
+ return rowUserId === userId;
64
+ });
65
+ const session = await env.host.getSession();
66
+ const continuation = await env.continuation.issue({
67
+ operation: 'cowork.permission.add.apply',
68
+ baseUrl: session.baseUrl,
69
+ profile: session.profile,
70
+ userId: session.userId,
71
+ coworkId,
72
+ targetUserId: userId,
73
+ userName,
74
+ permissionId,
75
+ });
76
+ return coworkSuccess('cowork.permission.add.prepare', {
77
+ summary: {
78
+ coworkId,
79
+ itemName: detail.itemName ?? '',
80
+ permissionId,
81
+ targetUser: { id: userId, name: userName, dept: args.userDept ?? null, title: args.userTitle ?? null },
82
+ alreadyShared: already,
83
+ note: already
84
+ ? '该人员已在共享权限列表中,重复新增可能被服务端判为无变化'
85
+ : (args.userCid ? undefined : '未提供 userCid:部分环境要求 cid/部门/岗位齐全才接受新增,失败时可补齐后重试'),
86
+ },
87
+ continuation,
88
+ });
89
+ },
90
+ };
91
+ const permAddApply = {
92
+ name: 'cowork.permission.add.apply',
93
+ resource: 'cowork',
94
+ method: 'permission.add.apply',
95
+ action: 'cowork.permission.add.apply',
96
+ summary: '新增共享对象(需 confirm=true 与 continuation)',
97
+ risk: WRITE,
98
+ requiresConfirmation: true,
99
+ inputSchema: schemaOf({
100
+ coworkId: { ...SCHEMA_ID },
101
+ userId: { ...SCHEMA_ID },
102
+ userName: { type: 'string', maxLength: 100 },
103
+ userDept: { type: 'string', maxLength: 200 },
104
+ userTitle: { type: 'string', maxLength: 200 },
105
+ userCid: { type: 'string', maxLength: 100 },
106
+ permissionId: { ...SCHEMA_ID },
107
+ confirm: { type: 'boolean' },
108
+ continuation: { type: 'string' },
109
+ }, { required: ['coworkId', 'userId', 'userName', 'confirm', 'continuation'] }),
110
+ handler: async (args, env) => {
111
+ requireConfirm(args, 'cowork.permission.add.apply');
112
+ const lease = await verifyLease(args, 'cowork.permission.add.apply', env);
113
+ const coworkId = toId(args.coworkId, 'coworkId');
114
+ const userId = toId(args.userId, 'userId');
115
+ if (lease.coworkId !== coworkId || lease.targetUserId !== userId) {
116
+ throw coworkValidationError('target_changed', '协作或人员与 prepare 时不一致,请重新执行 prepare');
117
+ }
118
+ const userName = String(args.userName ?? '').trim();
119
+ if (!userName)
120
+ throw coworkValidationError('user_name_required', 'userName 必填');
121
+ const permissionId = toId(args.permissionId, 'permissionId') ?? String(lease.permissionId ?? DEFAULT_PERMISSION_ID);
122
+ const dept = typeof args.userDept === 'string' ? args.userDept : '';
123
+ const position = typeof args.userTitle === 'string' ? args.userTitle : '';
124
+ const obj = {
125
+ id: userId,
126
+ userid: userId,
127
+ name: userName,
128
+ content: userName,
129
+ title: [userName, dept, position].filter(Boolean).join('|'),
130
+ contentDesc: [userName, dept].filter(Boolean).join('|'),
131
+ statusCode: 'normal',
132
+ department: dept,
133
+ position,
134
+ cid: typeof args.userCid === 'string' ? args.userCid : '',
135
+ };
136
+ const body = {
137
+ sourceId: coworkId,
138
+ permissionId,
139
+ sourceType: 1,
140
+ refId: coworkId,
141
+ permissionFrom: permissionId,
142
+ objType: 'resource',
143
+ obj_id: [obj],
144
+ };
145
+ let response;
146
+ try {
147
+ response = await env.host.request({
148
+ method: 'POST',
149
+ path: '/api/cowork/permission/addSharePermission',
150
+ body,
151
+ operation: 'cowork.permission.add.apply',
152
+ });
153
+ }
154
+ catch (error) {
155
+ if (isNetworkError(error)) {
156
+ throw coworkPartialError('新增共享对象请求已发出但未收到确定结果,禁止自动重试:请用 cowork.permission.list 核对', { coworkId, userId });
157
+ }
158
+ throw error;
159
+ }
160
+ return coworkSuccess('cowork.permission.add.apply', {
161
+ coworkId,
162
+ permissionId,
163
+ userId,
164
+ userName,
165
+ result: unwrapData(response) ?? null,
166
+ });
167
+ },
168
+ };
169
+ const permRemovePrepare = {
170
+ name: 'cowork.permission.remove.prepare',
171
+ resource: 'cowork',
172
+ method: 'permission.remove.prepare',
173
+ action: 'cowork.permission.remove.prepare',
174
+ summary: '删除共享对象的摘要:先按 pkId 在共享权限列表中定位真实记录并回显,不写入',
175
+ risk: READ_BEFORE_WRITE,
176
+ inputSchema: schemaOf({
177
+ coworkId: { ...SCHEMA_ID, description: '协作 id' },
178
+ pkId: { ...SCHEMA_ID, description: '共享记录 id(来自 cowork.permission.list 的行 id)' },
179
+ permissionId: { ...SCHEMA_ID, description: `权限类型 id,默认 ${DEFAULT_PERMISSION_ID}` },
180
+ }, { required: ['coworkId', 'pkId'] }),
181
+ handler: async (args, env) => {
182
+ const coworkId = toId(args.coworkId, 'coworkId');
183
+ const pkId = toId(args.pkId, 'pkId');
184
+ const permissionId = toId(args.permissionId, 'permissionId') ?? DEFAULT_PERMISSION_ID;
185
+ const rows = await listSharePermissions(env, coworkId, permissionId);
186
+ const hit = rows.find((row) => String(row.id ?? '') === pkId);
187
+ if (!hit) {
188
+ throw coworkNotFoundError('permission_record_not_found', `共享权限列表中未找到 id=${pkId} 的记录,无法删除(禁止凭空构造 datas 提交)`);
189
+ }
190
+ const session = await env.host.getSession();
191
+ const continuation = await env.continuation.issue({
192
+ operation: 'cowork.permission.remove.apply',
193
+ baseUrl: session.baseUrl,
194
+ profile: session.profile,
195
+ userId: session.userId,
196
+ coworkId,
197
+ pkId,
198
+ permissionId,
199
+ });
200
+ return coworkSuccess('cowork.permission.remove.prepare', {
201
+ summary: {
202
+ coworkId,
203
+ pkId,
204
+ permissionId,
205
+ targetUser: {
206
+ id: hit.userid ?? hit.userId ?? hit.id ?? null,
207
+ name: hit.username ?? hit.name ?? hit.content ?? null,
208
+ },
209
+ warning: '删除共享对象后该人员将失去对应权限,页面无撤销入口',
210
+ },
211
+ continuation,
212
+ });
213
+ },
214
+ };
215
+ const permRemoveApply = {
216
+ name: 'cowork.permission.remove.apply',
217
+ resource: 'cowork',
218
+ method: 'permission.remove.apply',
219
+ action: 'cowork.permission.remove.apply',
220
+ summary: '删除共享对象(需 confirm=true 与 continuation):apply 阶段重新取真实记录后全量回传',
221
+ risk: WRITE,
222
+ requiresConfirmation: true,
223
+ inputSchema: schemaOf({
224
+ coworkId: { ...SCHEMA_ID },
225
+ pkId: { ...SCHEMA_ID },
226
+ permissionId: { ...SCHEMA_ID },
227
+ confirm: { type: 'boolean' },
228
+ continuation: { type: 'string' },
229
+ }, { required: ['coworkId', 'pkId', 'confirm', 'continuation'] }),
230
+ handler: async (args, env) => {
231
+ requireConfirm(args, 'cowork.permission.remove.apply');
232
+ const lease = await verifyLease(args, 'cowork.permission.remove.apply', env);
233
+ const coworkId = toId(args.coworkId, 'coworkId');
234
+ const pkId = toId(args.pkId, 'pkId');
235
+ if (lease.coworkId !== coworkId || lease.pkId !== pkId) {
236
+ throw coworkValidationError('target_changed', '协作或记录与 prepare 时不一致,请重新执行 prepare');
237
+ }
238
+ const permissionId = toId(args.permissionId, 'permissionId') ?? String(lease.permissionId ?? DEFAULT_PERMISSION_ID);
239
+ // 写操作纪律:删除前必须重新取当前真实记录(记录内容可能已被他人修改),全量回传。
240
+ const rows = await listSharePermissions(env, coworkId, permissionId);
241
+ const record = rows.find((row) => String(row.id ?? '') === pkId);
242
+ if (!record) {
243
+ throw coworkNotFoundError('permission_record_gone', `共享记录 ${pkId} 已不存在(可能已被他人移除),无需重复删除`);
244
+ }
245
+ const body = {
246
+ sourceId: coworkId,
247
+ permissionId,
248
+ sourceType: 1,
249
+ id: coworkId,
250
+ permissionFrom: permissionId,
251
+ ids: pkId,
252
+ datas: [record],
253
+ };
254
+ let response;
255
+ try {
256
+ response = await env.host.request({
257
+ method: 'POST',
258
+ path: '/api/cowork/permission/deleteSharePermissionByPKIds',
259
+ body,
260
+ operation: 'cowork.permission.remove.apply',
261
+ });
262
+ }
263
+ catch (error) {
264
+ if (isNetworkError(error)) {
265
+ throw coworkPartialError('删除共享对象请求已发出但未收到确定结果,禁止自动重试:请用 cowork.permission.list 核对', { coworkId, pkId });
266
+ }
267
+ throw error;
268
+ }
269
+ // 回查:确认该记录已从列表中消失,避免"接口说成功但实际还在"。
270
+ const after = await listSharePermissions(env, coworkId, permissionId).catch(() => null);
271
+ const stillThere = after ? after.some((row) => String(row.id ?? '') === pkId) : null;
272
+ return coworkSuccess('cowork.permission.remove.apply', {
273
+ coworkId,
274
+ pkId,
275
+ removed: stillThere === false ? true : undefined,
276
+ verified: stillThere !== null,
277
+ result: unwrapData(response) ?? null,
278
+ });
279
+ },
280
+ };
281
+ export const coworkPermissionWriteOperations = [
282
+ permAddPrepare,
283
+ permAddApply,
284
+ permRemovePrepare,
285
+ permRemoveApply,
286
+ ];