weaver-work-cli 0.1.40 → 0.1.44

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 (401) hide show
  1. package/README.md +17 -0
  2. package/dist/chunks/{archive-JHTONRST.js → archive-P6TBQGKL.js} +13 -5
  3. package/dist/chunks/{archive-oa-FCHLCPHC.js → archive-oa-7TQ2NXOH.js} +12 -5
  4. package/dist/chunks/{asset-RLIHC7DB.js → asset-3ELRG37G.js} +11 -4
  5. package/dist/chunks/{asset-idle-KVOFTLCP.js → asset-idle-WIGMUFMD.js} +7 -3
  6. package/dist/chunks/{attachment-content-RZYDB3MB.js → attachment-content-E3276UOV.js} +5 -4
  7. package/dist/chunks/{blog-42OZTJNP.js → blog-C5NMZAAC.js} +11 -4
  8. package/dist/chunks/{caizhilian-KRK547K5.js → caizhilian-5XSM2DFP.js} +13 -6
  9. package/dist/chunks/{calendar-RTWAMKHD.js → calendar-FI2WNSBO.js} +71 -26
  10. package/dist/chunks/{chunk-CXRQWOZ5.js → chunk-3YBDYOC4.js} +3 -3
  11. package/dist/chunks/{chunk-OOUTBLZ4.js → chunk-56EZERK4.js} +1 -1
  12. package/dist/chunks/chunk-6N4JPNFL.js +76 -0
  13. package/dist/chunks/{chunk-ZUX3P6BQ.js → chunk-727FH2NI.js} +1 -1
  14. package/dist/chunks/chunk-7BDPM5ST.js +11 -0
  15. package/dist/chunks/{chunk-LN447PY2.js → chunk-BCVYBYYT.js} +432 -2247
  16. package/dist/chunks/{chunk-7E6MUOEK.js → chunk-CWYGFU5B.js} +2 -2
  17. package/dist/chunks/{chunk-NOODWMCL.js → chunk-D4ADSZ7H.js} +1 -1
  18. package/dist/chunks/{chunk-WFFNM65B.js → chunk-ETNJSKMM.js} +281 -29
  19. package/dist/chunks/{chunk-CAQNBBQA.js → chunk-F4E4EM35.js} +3 -3
  20. package/dist/chunks/{chunk-4CTESSKI.js → chunk-FAZTGX7S.js} +6 -6
  21. package/dist/chunks/chunk-FRZKBMSW.js +2562 -0
  22. package/dist/chunks/{chunk-BYBSCN4X.js → chunk-G7PQWD4L.js} +6 -3
  23. package/dist/chunks/{chunk-NJKREDA3.js → chunk-GAMZLAG2.js} +1 -1
  24. package/dist/chunks/{chunk-FLS4DPGP.js → chunk-GM6J7Q4B.js} +28 -15
  25. package/dist/chunks/{chunk-NETCCARD.js → chunk-GRDRG6HP.js} +3 -3
  26. package/dist/chunks/chunk-HIT4Y6OI.js +1238 -0
  27. package/dist/chunks/{chunk-EZALDOQH.js → chunk-HP7JIYMT.js} +5 -2
  28. package/dist/chunks/{chunk-IZSSVYAG.js → chunk-IAZ3UPY6.js} +3 -3
  29. package/dist/chunks/{chunk-ZEDWSH32.js → chunk-IC62NFM5.js} +1 -1
  30. package/dist/chunks/{chunk-P26ZWSKU.js → chunk-KIHNAS25.js} +5 -2
  31. package/dist/chunks/{chunk-57IECMWX.js → chunk-N4M2DDFE.js} +29 -15
  32. package/dist/chunks/{chunk-JWRZM2H2.js → chunk-OF4S23UB.js} +4 -4
  33. package/dist/chunks/{chunk-VNBU55SL.js → chunk-PC7VKEB5.js} +80 -2458
  34. package/dist/chunks/{chunk-G2JSIUWF.js → chunk-PUQS5MWL.js} +91 -2
  35. package/dist/chunks/{chunk-E7OK5WD5.js → chunk-Q4OYAQYH.js} +5 -5
  36. package/dist/chunks/{chunk-7BRU4EFH.js → chunk-QVSWRLLU.js} +35 -6
  37. package/dist/chunks/{chunk-T6EGVBKU.js → chunk-TA7FXXJD.js} +6 -3
  38. package/dist/chunks/{chunk-GPMFD4RD.js → chunk-TXUG266F.js} +1 -1
  39. package/dist/chunks/{chunk-4TEDNCON.js → chunk-UFIT2UU3.js} +354 -56
  40. package/dist/chunks/{chunk-LUSPKZKY.js → chunk-UG5G54VL.js} +1 -0
  41. package/dist/chunks/{chunk-NIAJ5ZCG.js → chunk-UL5XUQ25.js} +5 -2
  42. package/dist/chunks/{chunk-FMPJJYYI.js → chunk-WRXSAVKO.js} +1 -1
  43. package/dist/chunks/{chunk-7U577Q7U.js → chunk-WSF4NNMR.js} +3 -3
  44. package/dist/chunks/chunk-XHK4MDR5.js +2497 -0
  45. package/dist/chunks/{chunk-LFMSDBZN.js → chunk-XNIK66I4.js} +326 -161
  46. package/dist/chunks/{chunk-3SO6QL6U.js → chunk-YWX377BY.js} +5 -2
  47. package/dist/chunks/{chunk-BYATLLEF.js → chunk-Z3GDFVJR.js} +1 -1
  48. package/dist/chunks/{chunk-I566ZYNF.js → chunk-Z7VYWPZV.js} +1 -1
  49. package/dist/chunks/{conflict-VR55AOOO.js → conflict-ARLSZJ6V.js} +4 -3
  50. package/dist/chunks/{continuation-2CKSBLA6.js → continuation-3S37AUSH.js} +4 -3
  51. package/dist/chunks/{continuation-RN6PZN2M.js → continuation-3XLYYTKV.js} +4 -3
  52. package/dist/chunks/{continuation-HZIZRZBX.js → continuation-HFW2YT5S.js} +4 -3
  53. package/dist/chunks/{continuation-NLECEJPX.js → continuation-KI7DRRZN.js} +4 -3
  54. package/dist/chunks/{contract-HI4FNPYE.js → contract-DNIIW5VJ.js} +13 -5
  55. package/dist/chunks/{cowork-HJLI353D.js → cowork-GMLRGVIW.js} +31 -14
  56. package/dist/chunks/create-flow-J22BO65E.js +56 -0
  57. package/dist/chunks/{ebuilder-form-HTGI63UU.js → ebuilder-form-ANV2FHYV.js} +12 -7
  58. package/dist/chunks/{ehr-GYXIYH3A.js → ehr-GSTGAIY3.js} +695 -1255
  59. package/dist/chunks/{employee-SAK2QYXX.js → employee-22BGJ3QS.js} +3 -3
  60. package/dist/chunks/{env-DW3G4HUO.js → env-BX3VRFS7.js} +4 -3
  61. package/dist/chunks/{esb-I5INCEFE.js → esb-ATAIASX2.js} +12 -7
  62. package/dist/chunks/{factory-TKXGXS6L.js → factory-PETTFME6.js} +3 -2
  63. package/dist/chunks/{fna-K2MHTQ24.js → fna-YEKBSFSX.js} +14 -8
  64. package/dist/chunks/{group-chat-VYBNMJLG.js → group-chat-BFVXAYFX.js} +7 -4
  65. package/dist/chunks/{host-D5SERMAJ.js → host-HRBXEPDQ.js} +5 -5
  66. package/dist/chunks/{host-JM4YVHFM.js → host-LR55CTHP.js} +5 -5
  67. package/dist/chunks/{host-L3VLITMT.js → host-SUOY6VYQ.js} +5 -5
  68. package/dist/chunks/{host-ZUQTJYYK.js → host-SZGV4UNT.js} +5 -5
  69. package/dist/chunks/{host-256GVCAH.js → host-WIKN2EJ5.js} +5 -5
  70. package/dist/chunks/{hrm-VLRBKTZB.js → hrm-NRDO4W5G.js} +11 -7
  71. package/dist/chunks/{im-QK3VTLXK.js → im-IQ2HN23S.js} +11 -10
  72. package/dist/chunks/{invoice-T5JTA32H.js → invoice-MNRW76PP.js} +636 -1768
  73. package/dist/chunks/{jiuchuanhui-P2FNEQVZ.js → jiuchuanhui-DTRBAX4N.js} +14 -6
  74. package/dist/chunks/{lazy-dispatch-XRRI46M6.js → lazy-dispatch-ZVWAI25B.js} +7 -6
  75. package/dist/chunks/{mail-3Y7MJ6PS.js → mail-ZVAUXOJA.js} +16 -14
  76. package/dist/chunks/{meeting-M7LTXGJE.js → meeting-FEVPZ67S.js} +21 -13
  77. package/dist/chunks/{okr-OBC6S67L.js → okr-SDH3E5RA.js} +12 -5
  78. package/dist/chunks/{operations-5QL3AECO.js → operations-62N6EP3C.js} +4 -3
  79. package/dist/chunks/{plan-5H6I53SK.js → plan-E35JFDI7.js} +12 -5
  80. package/dist/chunks/{project-L75QZV4S.js → project-73QXBAB2.js} +49 -25
  81. package/dist/chunks/reception-UWZVACBN.js +1899 -0
  82. package/dist/chunks/recruit-stage-4MAOCKFY.js +4770 -0
  83. package/dist/chunks/registry-IM5G23LS.js +24 -0
  84. package/dist/chunks/{registry-UGRBCBHO.js → registry-JDUS4E7D.js} +7 -6
  85. package/dist/chunks/{registry-RXPN6BBT.js → registry-KNKSCJNT.js} +7 -6
  86. package/dist/chunks/{registry-NYPYMZXG.js → registry-PO7SI256.js} +4 -4
  87. package/dist/chunks/{registry-QGHFNUWS.js → registry-PVUZQDDQ.js} +3 -3
  88. package/dist/chunks/{room-recommend-A3UDC3CA.js → room-recommend-H7KLXA5R.js} +6 -5
  89. package/dist/chunks/{schedule-5GCACCK7.js → schedule-ESZIBAUO.js} +6 -5
  90. package/dist/chunks/{workflow-M5ZJ7DWF.js → workflow-CWJFJLQU.js} +15 -10
  91. package/dist/cmd/action.js +6 -0
  92. package/dist/cmd/identity/index.js +45 -0
  93. package/dist/cmd/index.js +2 -0
  94. package/dist/core/continuation-ttl.js +18 -0
  95. package/dist/core/error-codes.js +85 -0
  96. package/dist/core/logger.js +11 -0
  97. package/dist/index.js +41 -30
  98. package/dist/internal/e10/auth/commands.js +164 -8
  99. package/dist/internal/e10/auth/error-log.js +182 -0
  100. package/dist/internal/e10/auth/messages.js +6 -0
  101. package/dist/internal/e10/auth/session.js +34 -3
  102. package/dist/internal/e10/auth/xiaoe.js +286 -44
  103. package/dist/internal/e10/auth-recovery.js +72 -14
  104. package/dist/internal/e10/context.js +72 -13
  105. package/dist/internal/e10/index.js +1 -1
  106. package/dist/internal/e10/network-error.js +93 -0
  107. package/dist/internal/e10/request-runtime.js +6 -0
  108. package/dist/internal/skills/install.js +9 -1
  109. package/dist/shortcuts/archive/continuation.js +2 -1
  110. package/dist/shortcuts/archive/index.js +3 -0
  111. package/dist/shortcuts/archive/operations/confirm.js +2 -1
  112. package/dist/shortcuts/archive-oa/continuation.js +2 -1
  113. package/dist/shortcuts/archive-oa/index.js +2 -0
  114. package/dist/shortcuts/archive-oa/operations/confirm.js +2 -1
  115. package/dist/shortcuts/asset/continuation.js +2 -1
  116. package/dist/shortcuts/asset/index.js +2 -0
  117. package/dist/shortcuts/asset-idle/index.js +2 -0
  118. package/dist/shortcuts/blog/continuation.js +2 -1
  119. package/dist/shortcuts/blog/index.js +2 -0
  120. package/dist/shortcuts/caizhilian/continuation.js +2 -1
  121. package/dist/shortcuts/caizhilian/index.js +2 -0
  122. package/dist/shortcuts/caizhilian/operations/confirm.js +3 -2
  123. package/dist/shortcuts/calendar/continuation.js +2 -1
  124. package/dist/shortcuts/calendar/index.js +2 -0
  125. package/dist/shortcuts/calendar/operations/read.js +31 -22
  126. package/dist/shortcuts/calendar/operations/write.js +46 -2
  127. package/dist/shortcuts/contract/continuation.js +2 -1
  128. package/dist/shortcuts/contract/index.js +2 -0
  129. package/dist/shortcuts/contract/operations/write.js +2 -1
  130. package/dist/shortcuts/cowork/continuation.js +2 -1
  131. package/dist/shortcuts/cowork/index.js +2 -0
  132. package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
  133. package/dist/shortcuts/cowork/operations/item-write.js +1 -7
  134. package/dist/shortcuts/cowork/operations/member-write.js +3 -1
  135. package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
  136. package/dist/shortcuts/cowork/operations/shared.js +7 -0
  137. package/dist/shortcuts/ebuilder-form/continuation.js +2 -1
  138. package/dist/shortcuts/ebuilder-form/index.js +2 -0
  139. package/dist/shortcuts/ebuilder-form/operations/write.js +3 -2
  140. package/dist/shortcuts/ehr/continuation.js +2 -1
  141. package/dist/shortcuts/ehr/index.js +2 -0
  142. package/dist/shortcuts/ehr/operations/attend-write.js +44 -2
  143. package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
  144. package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
  145. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +317 -63
  146. package/dist/shortcuts/ehr/operations/recruit-position.js +134 -2
  147. package/dist/shortcuts/ehr/operations/recruit-write.js +263 -18
  148. package/dist/shortcuts/ehr/operations/recruit.js +10 -4
  149. package/dist/shortcuts/ehr/operations/shared.js +47 -0
  150. package/dist/shortcuts/esb/continuation.js +2 -1
  151. package/dist/shortcuts/esb/index.js +2 -0
  152. package/dist/shortcuts/esb/operations/trigger.js +2 -1
  153. package/dist/shortcuts/fna/continuation.js +2 -1
  154. package/dist/shortcuts/fna/index.js +2 -0
  155. package/dist/shortcuts/fna/operations/invoice-writeoff.js +1 -1
  156. package/dist/shortcuts/fna/operations/loan.js +1 -1
  157. package/dist/shortcuts/hrm/index.js +2 -0
  158. package/dist/shortcuts/hrm/operations/org.js +118 -0
  159. package/dist/shortcuts/im/continuation.js +2 -1
  160. package/dist/shortcuts/index.js +10 -0
  161. package/dist/shortcuts/invoice/continuation.js +2 -1
  162. package/dist/shortcuts/invoice/index.js +14 -15
  163. package/dist/shortcuts/invoice/invoice-record.js +93 -0
  164. package/dist/shortcuts/invoice/manifest.js +190 -393
  165. package/dist/shortcuts/invoice/operations/add.js +2 -1
  166. package/dist/shortcuts/invoice/operations/delete.js +2 -1
  167. package/dist/shortcuts/invoice/operations/import.js +2 -1
  168. package/dist/shortcuts/invoice/operations/issuing-contract-detail.js +86 -0
  169. package/dist/shortcuts/invoice/operations/issuing-contracts.js +210 -0
  170. package/dist/shortcuts/invoice/operations/registry.js +17 -17
  171. package/dist/shortcuts/invoice/operations/reim-auto.js +4 -569
  172. package/dist/shortcuts/invoice/operations/reim.js +52 -341
  173. package/dist/shortcuts/invoice/operations/shared.js +21 -4
  174. package/dist/shortcuts/invoice/operations/update.js +2 -1
  175. package/dist/shortcuts/invoice/projection.js +10 -62
  176. package/dist/shortcuts/jiuchuanhui/continuation.js +2 -1
  177. package/dist/shortcuts/jiuchuanhui/index.js +2 -0
  178. package/dist/shortcuts/jiuchuanhui/operations/datajson.js +2 -1
  179. package/dist/shortcuts/jiuchuanhui/operations/esb.js +2 -1
  180. package/dist/shortcuts/mail/continuation.js +2 -1
  181. package/dist/shortcuts/mail/index.js +2 -0
  182. package/dist/shortcuts/mail/operations/mail-blacklist.js +1 -1
  183. package/dist/shortcuts/mail/operations/mail-contacts.js +1 -1
  184. package/dist/shortcuts/mail/operations/mail-send.js +1 -1
  185. package/dist/shortcuts/mail/operations/mail-sign.js +1 -1
  186. package/dist/shortcuts/mail/operations/mail-template.js +1 -1
  187. package/dist/shortcuts/meeting/continuation.js +2 -1
  188. package/dist/shortcuts/meeting/index.js +2 -0
  189. package/dist/shortcuts/meeting/operations/change.js +1 -1
  190. package/dist/shortcuts/meeting/operations/create.js +1 -1
  191. package/dist/shortcuts/meeting/operations/eb/catalog.js +4 -1
  192. package/dist/shortcuts/meeting/operations/eb/create-flow.js +101 -35
  193. package/dist/shortcuts/meeting/operations/eb/decision.js +1 -1
  194. package/dist/shortcuts/meeting/operations/eb/factory.js +34 -1
  195. package/dist/shortcuts/meeting/operations/eb/group-chat.js +25 -3
  196. package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
  197. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +33 -11
  198. package/dist/shortcuts/meeting/operations/lifecycle.js +1 -1
  199. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  200. package/dist/shortcuts/meeting/operations/signs.js +1 -1
  201. package/dist/shortcuts/okr/continuation.js +2 -1
  202. package/dist/shortcuts/okr/index.js +2 -0
  203. package/dist/shortcuts/okr/operations/write.js +1 -1
  204. package/dist/shortcuts/plan/continuation.js +2 -1
  205. package/dist/shortcuts/plan/index.js +2 -0
  206. package/dist/shortcuts/plan/operations/write.js +1 -1
  207. package/dist/shortcuts/project/continuation.js +2 -1
  208. package/dist/shortcuts/project/index.js +2 -0
  209. package/dist/shortcuts/project/operations/read.js +6 -25
  210. package/dist/shortcuts/project/operations/shared.js +22 -0
  211. package/dist/shortcuts/project/operations/write.js +28 -2
  212. package/dist/shortcuts/reception/constants.js +53 -0
  213. package/dist/shortcuts/reception/errors.js +54 -0
  214. package/dist/shortcuts/reception/host.js +125 -0
  215. package/dist/shortcuts/reception/index.js +198 -0
  216. package/dist/shortcuts/reception/manifest.js +177 -0
  217. package/dist/shortcuts/reception/operations/ask.js +71 -0
  218. package/dist/shortcuts/reception/operations/browsertool.js +58 -0
  219. package/dist/shortcuts/reception/operations/compose.js +129 -0
  220. package/dist/shortcuts/reception/operations/customparams.js +74 -0
  221. package/dist/shortcuts/reception/operations/doc.js +238 -0
  222. package/dist/shortcuts/reception/operations/docrender.js +36 -0
  223. package/dist/shortcuts/reception/operations/panels.js +179 -0
  224. package/dist/shortcuts/reception/operations/registry.js +26 -0
  225. package/dist/shortcuts/reception/operations/render-assets.js +184 -0
  226. package/dist/shortcuts/reception/operations/render.js +123 -0
  227. package/dist/shortcuts/reception/operations/runs.js +38 -0
  228. package/dist/shortcuts/reception/operations/schedule.js +127 -0
  229. package/dist/shortcuts/reception/operations/shared.js +196 -0
  230. package/dist/shortcuts/reception/operations/snapshot.js +68 -0
  231. package/dist/shortcuts/reception/operations/types.js +1 -0
  232. package/dist/shortcuts/reception/operations.js +33 -0
  233. package/dist/shortcuts/reception/upload.js +218 -0
  234. package/dist/shortcuts/recruit-stage/context.js +231 -0
  235. package/dist/shortcuts/recruit-stage/continuation.js +74 -0
  236. package/dist/shortcuts/recruit-stage/errors.js +65 -0
  237. package/dist/shortcuts/recruit-stage/host.js +109 -0
  238. package/dist/shortcuts/recruit-stage/index.js +115 -0
  239. package/dist/shortcuts/recruit-stage/manifest.js +29 -0
  240. package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
  241. package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
  242. package/dist/shortcuts/recruit-stage/operations/jd-create.js +719 -0
  243. package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
  244. package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
  245. package/dist/shortcuts/recruit-stage/operations/resume-import.js +1354 -0
  246. package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
  247. package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
  248. package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
  249. package/dist/shortcuts/recruit-stage/shared.js +608 -0
  250. package/dist/shortcuts/workflow/continuation.js +2 -1
  251. package/dist/shortcuts/workflow/index.js +2 -0
  252. package/dist/shortcuts/workflow/operations/form.js +32 -8
  253. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
  254. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +13 -6
  255. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
  256. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
  257. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +50 -8
  258. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +2 -1
  259. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
  260. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +7 -39
  261. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
  262. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +51 -15
  263. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
  264. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
  265. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
  266. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +39 -14
  267. package/dist/shortcuts/workflow/operations/write.js +1 -1
  268. package/docs/_catalog.md +3 -0
  269. package/docs/agent-invoice.md +1 -1
  270. package/docs/archive-oa.md +1 -1
  271. package/docs/caizhilian.md +1 -1
  272. package/docs/calendar.md +1 -1
  273. package/docs/contract.md +1 -1
  274. package/docs/e10-auth.md +23 -1
  275. package/docs/ehr.md +2 -2
  276. package/docs/esb.md +1 -1
  277. package/docs/im.md +1 -1
  278. package/docs/invoice.md +8 -12
  279. package/docs/okr.md +1 -1
  280. package/docs/operation-manual.md +8 -0
  281. package/docs/reception.md +119 -0
  282. package/package.json +1 -1
  283. package/scripts/clean.mjs +43 -2
  284. package/scripts/install-skill-to-xiaoe.mjs +105 -0
  285. package/scripts/package-skill.mjs +4 -2
  286. package/skill-template/business-info.json +42 -2
  287. package/skill-template/domains/caizhilian.md +1 -1
  288. package/skill-template/domains/reception-flow.md +18 -0
  289. package/skill-template/domains/recruit-stage.md +29 -0
  290. package/skill-template/domains/yepiaotong.md +4 -7
  291. package/skills/weaver-e10-archive-oa/references/source-manifest.json +14 -14
  292. package/skills/weaver-e10-blog/references/blog-publish.md +1 -1
  293. package/skills/weaver-e10-blog/references/source-manifest.json +7 -7
  294. package/skills/weaver-e10-caizhilian/references/source-manifest.json +21 -21
  295. package/skills/weaver-e10-caizhilian/references/write-protocol.md +2 -2
  296. package/skills/weaver-e10-calendar/SKILL.md +2 -1
  297. package/skills/weaver-e10-calendar/references/calendar-write.md +55 -1
  298. package/skills/weaver-e10-cowork/SKILL.md +1 -1
  299. package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
  300. package/skills/weaver-e10-ebuilder-form/SKILL.md +1 -1
  301. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -1
  302. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -1
  303. package/skills/weaver-e10-esb/SKILL.md +2 -2
  304. package/skills/weaver-e10-esb/references/source-manifest.json +22 -22
  305. package/skills/weaver-e10-esb/references/trigger.md +2 -2
  306. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +1 -1
  307. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +1 -1
  308. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +1 -1
  309. package/skills/weaver-e10-jinchengda/references/source-manifest.json +29 -29
  310. package/skills/weaver-e10-jucailin/SKILL.md +1 -1
  311. package/skills/weaver-e10-jucailin/references/attend-write.md +10 -2
  312. package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
  313. package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
  314. package/skills/weaver-e10-jucailin/references/recruit-create.md +14 -5
  315. package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
  316. package/skills/weaver-e10-jucailin/references/recruit-write.md +5 -4
  317. package/skills/weaver-e10-mail/SKILL.md +1 -1
  318. package/skills/weaver-e10-meeting/SKILL.md +39 -7
  319. package/skills/weaver-e10-meeting/references/meeting-change.md +1 -1
  320. package/skills/weaver-e10-meeting/references/meeting-create.md +1 -1
  321. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +1 -1
  322. package/skills/weaver-e10-meeting/references/meeting-verification.md +1 -1
  323. package/skills/weaver-e10-okr/references/okr-align.md +1 -1
  324. package/skills/weaver-e10-okr/references/okr-keyresult.md +1 -1
  325. package/skills/weaver-e10-okr/references/okr-write.md +1 -1
  326. package/skills/weaver-e10-okr/references/source-manifest.json +8 -8
  327. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  328. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  329. package/skills/weaver-e10-qiyecheng/references/loan-management.md +1 -1
  330. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +18 -18
  331. package/skills/weaver-e10-reception-flow/SKILL.md +173 -0
  332. package/skills/weaver-e10-reception-flow/assets//350/241/214/347/250/213/345/215/225/346/250/241/346/235/277-/346/263/233/345/276/256.docx +0 -0
  333. package/skills/weaver-e10-reception-flow/data/fields-snapshot.json +213 -0
  334. package/skills/weaver-e10-reception-flow/references/browsertool.md +68 -0
  335. package/skills/weaver-e10-reception-flow/references/env-pitfalls.md +51 -0
  336. package/skills/weaver-e10-reception-flow/references/fields-snapshot.md +227 -0
  337. package/skills/weaver-e10-reception-flow/references/guide.md +179 -0
  338. package/skills/weaver-e10-reception-flow/scripts/locate.sh +14 -0
  339. package/skills/weaver-e10-reception-flow/scripts/render.py +724 -0
  340. package/skills/weaver-e10-recruit-stage/SKILL.md +230 -0
  341. package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
  342. package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
  343. package/skills/weaver-e10-recruit-stage/lib/xiaoe-session.mjs +66 -0
  344. package/skills/weaver-e10-recruit-stage/references/position-templates.md +202 -0
  345. package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
  346. package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
  347. package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
  348. package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
  349. package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
  350. package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +95 -0
  351. package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
  352. package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
  353. package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
  354. package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
  355. package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
  356. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
  357. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
  358. package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +451 -0
  359. package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
  360. package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
  361. package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
  362. package/skills/weaver-e10-shared/SKILL.md +1 -1
  363. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -2
  364. package/skills/weaver-e10-shijingran/SKILL.md +7 -6
  365. package/skills/weaver-e10-shijingran/references/operations.md +3 -1
  366. package/skills/weaver-e10-shijingran/references/source-manifest.json +30 -28
  367. package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
  368. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +2 -0
  369. package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
  370. package/skills/weaver-e10-workflow/SKILL.md +4 -2
  371. package/skills/weaver-e10-workflow/aigroup/default.json +11 -9
  372. package/skills/weaver-e10-workflow/references/source-manifest.json +32 -32
  373. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +23 -13
  374. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +62 -20
  375. package/skills/weaver-e10-yepiaotong/SKILL.md +28 -36
  376. package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
  377. package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +13 -10
  378. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +2 -0
  379. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +194 -155
  380. package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +28 -32
  381. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +5 -1
  382. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +8 -10
  383. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +211 -616
  384. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +149 -117
  385. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +17 -20
  386. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +20 -39
  387. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +55 -22
  388. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -17
  389. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +88 -92
  390. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +144 -354
  391. package/skills/weaver-e10-yimiaoban/SKILL.md +1 -1
  392. package/skills/weaver-e10-yimiaoban/references/msg-write.md +1 -1
  393. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +1 -1
  394. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +7 -7
  395. package/dist/chunks/chunk-SPRHHSVC.js +0 -465
  396. package/dist/chunks/registry-KMHCPAAD.js +0 -22
  397. package/dist/shortcuts/invoice/markdown.js +0 -172
  398. package/dist/shortcuts/invoice/operations/issuing-qys.js +0 -424
  399. package/skills/weaver-e10-meeting.zip +0 -0
  400. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +0 -131
  401. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +0 -179
@@ -1,3 +1,4 @@
1
+ import { CONTINUATION_TTL_MS, CONTINUATION_TTL_SECONDS } from '../../../core/continuation-ttl.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import { readFile, stat } from 'node:fs/promises';
3
4
  import { basename } from 'node:path';
@@ -100,6 +101,133 @@ function joinRange(start, end) {
100
101
  return undefined;
101
102
  return `${s},${e}`;
102
103
  }
104
+ // ── 日期格式预检与归一(2026-11-05 与 recruit-stage 同步修复)──
105
+ // 人才表单接口只接受 yyyy-MM-dd。模型常给「2020.11」「2008-08」「2004.09-2008.07」,
106
+ // 会让 dataset 新增整批校验失败 → 回退建主表 → 补明细又被同一格式拦下 → 明细全丢。
107
+ // 规则同 recruit-stage:只有年月时开始补 -01、结束补当月最后一天;「至今」归一为空(不伪造结束日);
108
+ // 无法识别则跳过该字段并在 warnings 明示,绝不静默改写。
109
+ const DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
110
+ const ONGOING_RE = /至今|现在|今|now|present/i;
111
+ const RE_RANGE_FULL = /^\s*(\d{4}[.\-/年]\d{1,2}[.\-/月]\d{1,2}\s*日?)\s*[-–—~至,,]\s*(\d{4}[.\-/年]\d{1,2}[.\-/月]\d{1,2}\s*日?|至今|现在|今)\s*$/;
112
+ const RE_RANGE_YM = /^\s*(\d{4}[.\-/年]\d{1,2})\s*[-–—~至,,]\s*(\d{4}[.\-/年]\d{1,2}|至今|现在|今)\s*$/;
113
+ /** 单日期片段 → yyyy-MM-dd;isEnd=true 且缺日时补该月最后一天。无法解析返回 ''。 */
114
+ function normDatePart(raw, isEnd) {
115
+ const s = String(raw ?? '').trim();
116
+ if (!s)
117
+ return '';
118
+ if (ONGOING_RE.test(s))
119
+ return '';
120
+ if (DATE_ONLY_RE.test(s))
121
+ return s;
122
+ const m = s.match(/^(\d{4})\s*[.\-/年]?\s*(\d{1,2})?\s*[.\-/月]?\s*(\d{1,2})?\s*日?$/);
123
+ if (!m)
124
+ return '';
125
+ const y = Number(m[1]);
126
+ const mo = m[2] ? Number(m[2]) : 1;
127
+ if (!y || mo < 1 || mo > 12)
128
+ return '';
129
+ const lastDay = new Date(y, mo, 0).getDate();
130
+ let d;
131
+ if (m[3]) {
132
+ d = Number(m[3]);
133
+ if (d < 1 || d > lastDay)
134
+ return '';
135
+ }
136
+ else {
137
+ d = isEnd ? lastDay : 1;
138
+ }
139
+ return `${y}-${String(mo).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
140
+ }
141
+ /** 日期区间 → "start,end";单值原样归一。 */
142
+ function normDateRange(raw) {
143
+ const s = Array.isArray(raw)
144
+ ? raw.map((x) => String(x ?? '').trim()).filter(Boolean).join(',')
145
+ : String(raw ?? '').trim();
146
+ if (!s)
147
+ return '';
148
+ const m = s.match(RE_RANGE_FULL) || s.match(RE_RANGE_YM);
149
+ if (m) {
150
+ const a = normDatePart(m[1], false);
151
+ if (!a)
152
+ return '';
153
+ const b = normDatePart(m[2], true);
154
+ return b ? `${a},${b}` : a;
155
+ }
156
+ return normDatePart(s, false);
157
+ }
158
+ /**
159
+ * 就地归一简历入参里的全部日期字段,把每处改动写入 warnings(不静默改写)。
160
+ * 覆盖:joinworkdate / graduate_date / birthday;academicInformations[].study_date;
161
+ * jobInformations|workExperiences|projectExperiences 的 start_date/end_date;
162
+ * internshipExperiences[].entry_time;awardExperiences[].award_date。
163
+ */
164
+ export function normalizeImportDates(input, warnings) {
165
+ if (!input || typeof input !== 'object')
166
+ return;
167
+ const one = (label, val, isEnd = false) => {
168
+ const before = String(val ?? '').trim();
169
+ if (!before)
170
+ return '';
171
+ if (ONGOING_RE.test(before))
172
+ return '';
173
+ const after = normDatePart(before, isEnd);
174
+ if (!after) {
175
+ warnings.push(`日期无法识别,已跳过该字段(避免接口整批校验失败):${label} = 「${before}」`);
176
+ return '';
177
+ }
178
+ if (after !== before)
179
+ warnings.push(`日期已规范化:${label} 「${before}」→「${after}」`);
180
+ return after;
181
+ };
182
+ for (const k of ['joinworkdate', 'graduate_date', 'birthday']) {
183
+ if (input[k] === undefined || input[k] === null)
184
+ continue;
185
+ input[k] = one(k, input[k], false);
186
+ }
187
+ if (Array.isArray(input.academicInformations)) {
188
+ input.academicInformations.forEach((r, i) => {
189
+ if (!r || typeof r !== 'object' || r.study_date === undefined)
190
+ return;
191
+ const before = String(r.study_date ?? '').trim();
192
+ if (!before)
193
+ return;
194
+ const after = normDateRange(before);
195
+ if (!after) {
196
+ warnings.push(`日期区间无法识别,已跳过:academicInformations[${i}].study_date = 「${before}」`);
197
+ r.study_date = '';
198
+ }
199
+ else {
200
+ if (after !== before)
201
+ warnings.push(`日期已规范化:academicInformations[${i}].study_date 「${before}」→「${after}」`);
202
+ r.study_date = after;
203
+ }
204
+ });
205
+ }
206
+ for (const key of ['jobInformations', 'workExperiences', 'projectExperiences']) {
207
+ const arr = input[key];
208
+ if (!Array.isArray(arr))
209
+ continue;
210
+ arr.forEach((r, i) => {
211
+ if (!r || typeof r !== 'object')
212
+ return;
213
+ if (r.start_date !== undefined && r.start_date !== null)
214
+ r.start_date = one(`${key}[${i}].start_date`, r.start_date, false);
215
+ if (r.end_date !== undefined && r.end_date !== null)
216
+ r.end_date = one(`${key}[${i}].end_date`, r.end_date, true);
217
+ });
218
+ }
219
+ for (const [key, field] of [['internshipExperiences', 'entry_time'], ['awardExperiences', 'award_date']]) {
220
+ const arr = input[key];
221
+ if (!Array.isArray(arr))
222
+ continue;
223
+ arr.forEach((r, i) => {
224
+ if (!r || typeof r !== 'object')
225
+ return;
226
+ if (r[field] !== undefined && r[field] !== null)
227
+ r[field] = one(`${key}[${i}].${field}`, r[field], false);
228
+ });
229
+ }
230
+ }
103
231
  async function resolveSubTableMeta(env, formId) {
104
232
  let data = null;
105
233
  try {
@@ -335,45 +463,122 @@ async function uploadResumeFile(env, filePath, fieldId, formId) {
335
463
  }
336
464
  return { fileid: String(fileid), name, size };
337
465
  }
338
- /** 平台标签:按名称在本环境标签清单里解析 id(同名优先公共),不自动创建。 */
339
- async function applyPlatformTags(env, talentId, tagNames) {
340
- if (!tagNames.length)
341
- return { applied: [], skipped: [] };
342
- const list = (await env.host.request({
466
+ /** 按名查标签(并行 type=0 公共 / type=1 个人)。服务端若忽略 name 会返回满页 → filtered=false,由调用方回退全量。
467
+ * 🔴 2026-11-04 修:原实现只取第 1 页 500 条,环境标签超 500 时后续标签永远匹配不到(静默跳过)。 */
468
+ async function queryTagByName(env, name) {
469
+ const pageSize = 100;
470
+ const bodyOf = (type) => ({ type, name, order: 8, pageSize, pageNo: 1, search: 1, tagGroup: 0, tagModules: ['ebuilderform'] });
471
+ const rs = await Promise.all([0, 1].map((type) => env.host
472
+ .request({
343
473
  path: '/api/my/tag/query',
344
474
  method: 'POST',
345
- body: { tagModules: ['ebuilderform'], current: 1, pageSize: 500 },
475
+ body: bodyOf(type),
346
476
  operation: 'ehr.recruit.candidate.import.apply',
347
- }));
348
- const rows = list?.data?.data || list?.data?.list || [];
477
+ })
478
+ .catch(() => null)));
479
+ const items = [];
480
+ let filtered = true;
481
+ for (const r of rs) {
482
+ const d = r?.data || {};
483
+ const list = Array.isArray(d.data) ? d.data : [];
484
+ const total = Number(d.total || 0);
485
+ if (list.length >= pageSize && total >= pageSize)
486
+ filtered = false;
487
+ items.push(...list);
488
+ }
489
+ return { items, filtered };
490
+ }
491
+ /** 单类型的全量标签(首轮取 total 后并发翻页,限并发 5、上限 40 页)——仅在按名查询不可用时回退 */
492
+ async function fetchTagsOfType(env, type) {
493
+ const pageSize = 100;
494
+ const bodyOf = (pageNo) => ({ type, name: '', order: 8, pageSize, pageNo, search: 1, tagGroup: 0, tagModules: ['ebuilderform'] });
495
+ const requestPage = (pageNo) => env.host
496
+ .request({
497
+ path: '/api/my/tag/query',
498
+ method: 'POST',
499
+ body: bodyOf(pageNo),
500
+ operation: 'ehr.recruit.candidate.import.apply',
501
+ })
502
+ .catch(() => null);
503
+ const first = (await requestPage(1));
504
+ const d = first?.data || {};
505
+ const rows = Array.isArray(d.data) ? [...d.data] : [];
506
+ const total = Number(d.total || 0);
507
+ const pages = Math.min(40, Math.max(1, Math.ceil(total / pageSize)));
508
+ if (pages > 1 && rows.length) {
509
+ const rest = Array.from({ length: pages - 1 }, (_, i) => i + 2);
510
+ for (let i = 0; i < rest.length; i += 5) {
511
+ const batch = rest.slice(i, i + 5);
512
+ const rs = await Promise.all(batch.map((p) => requestPage(p)));
513
+ for (const r of rs) {
514
+ const list = r?.data?.data;
515
+ if (Array.isArray(list))
516
+ rows.push(...list);
517
+ }
518
+ }
519
+ }
520
+ return rows;
521
+ }
522
+ /** 解析标签名 → id(同名优先公共),不创建标签。
523
+ * ① 按名精确查询(N 个名字 → 1 轮请求);② 服务端未按名过滤时才回退全量(不落盘、不缓存)。 */
524
+ async function resolveTagIds(env, tagNames) {
525
+ const norm = (s) => String(s == null ? '' : s).trim().toLowerCase();
526
+ const uniqNames = [...new Set(tagNames.map((n) => String(n)).filter(Boolean))];
349
527
  const byName = new Map();
350
- for (const row of rows) {
351
- const name = String(row.name ?? row.tagName ?? '').trim();
352
- const id = row.tagId ?? row.id;
353
- if (name && id !== undefined && !byName.has(name))
354
- byName.set(name, { id: String(id), name });
355
- }
356
- const tags = [];
357
- const applied = [];
528
+ const absorb = (row) => {
529
+ const name = String(row?.name ?? row?.tagName ?? '').trim();
530
+ const id = row?.tagId ?? row?.id;
531
+ if (!name || id === undefined)
532
+ return;
533
+ const key = norm(name);
534
+ const prev = byName.get(key);
535
+ if (!prev)
536
+ byName.set(key, { id: String(id), name });
537
+ else if ((row?.type ?? 0) === 0)
538
+ byName.set(key, { id: String(id), name });
539
+ };
540
+ const probes = await Promise.all(uniqNames.map((n) => queryTagByName(env, n)));
541
+ const nameQueryUsable = probes.every((p) => p.filtered);
542
+ if (nameQueryUsable) {
543
+ for (const p of probes)
544
+ for (const item of p.items)
545
+ absorb(item);
546
+ }
547
+ else {
548
+ for (const type of [0, 1]) {
549
+ const rows = await fetchTagsOfType(env, type).catch(() => []);
550
+ for (const item of rows)
551
+ absorb(item);
552
+ }
553
+ }
554
+ const resolved = [];
555
+ const found = [];
358
556
  const skipped = [];
359
557
  for (const name of tagNames) {
360
- const hit = byName.get(name);
558
+ const hit = byName.get(norm(name));
361
559
  if (!hit) {
362
560
  skipped.push(name);
363
561
  continue;
364
562
  }
365
- tags.push({ id: hit.id, name: hit.name, type: 0 });
366
- applied.push(name);
563
+ resolved.push({ id: hit.id, name: hit.name, type: 0 });
564
+ found.push(name);
367
565
  }
368
- if (tags.length) {
566
+ return { resolved, found, skipped };
567
+ }
568
+ /** 写入平台标签(解析 + batchAddEntityTag)。解析结果不存在时静默跳过,不自动创建标签。 */
569
+ async function applyPlatformTags(env, talentId, tagNames) {
570
+ if (!tagNames.length)
571
+ return { applied: [], skipped: [] };
572
+ const r = await resolveTagIds(env, tagNames);
573
+ if (r.resolved.length) {
369
574
  await env.host.request({
370
575
  path: '/api/my/tag/common/batchAddEntityTag',
371
576
  method: 'POST',
372
- body: { tags, batchDatas: [{ entityId: talentId, module: 'ebuilderform' }] },
577
+ body: { tags: r.resolved, batchDatas: [{ entityId: talentId, module: 'ebuilderform' }] },
373
578
  operation: 'ehr.recruit.candidate.import.apply',
374
579
  });
375
580
  }
376
- return { applied, skipped };
581
+ return { applied: r.found, skipped: r.skipped };
377
582
  }
378
583
  async function requireCache(env) {
379
584
  if (!env.recruitContext)
@@ -387,6 +592,9 @@ function str(value) {
387
592
  }
388
593
  async function buildImportPlan(env, cache, args) {
389
594
  const warnings = [];
595
+ // 日期格式预检与归一:必须在构建主表/明细之前执行。原实现直接把模型给的
596
+ // 「2020.11」「2004.09-2008.07」写进接口,导致 dataset 整批校验失败、明细全丢。
597
+ normalizeImportDates(args, warnings);
390
598
  const talent = cache.forms.talent_pool;
391
599
  const objId = talent?.objId;
392
600
  const formId = talent?.formId || objId;
@@ -582,7 +790,16 @@ const candidateImportPrepare = {
582
790
  handler: async (args, env) => {
583
791
  const cache = await requireCache(env);
584
792
  const plan = await buildImportPlan(env, cache, args);
585
- const dup = await checkDuplicateByMobile(env, cache, plan.mobile);
793
+ // 标签预检(只读)+ 查重并行:让用户在确认摘要里就能看到哪些标签在本环境不存在(apply 会跳过它们)
794
+ const tagNames = Array.isArray(args.tags) ? args.tags.map(String).filter(Boolean) : [];
795
+ const [dup, tagCheck] = await Promise.all([
796
+ checkDuplicateByMobile(env, cache, plan.mobile),
797
+ tagNames.length
798
+ ? resolveTagIds(env, tagNames)
799
+ .then((rt) => ({ requested: tagNames, found: rt.found, missing: rt.skipped }))
800
+ .catch((error) => ({ requested: tagNames, missing: [], error: error?.message || '标签预检失败' }))
801
+ : Promise.resolve(null),
802
+ ]);
586
803
  if (dup.length > 1) {
587
804
  throw ehrValidationError('duplicate_ambiguous', `手机号 ${plan.mobile} 存在多条候选(数据异常),请人工核对后再决定,不自动新建`);
588
805
  }
@@ -605,7 +822,7 @@ const candidateImportPrepare = {
605
822
  candidateName: plan.talentName,
606
823
  telephone: plan.mobile,
607
824
  },
608
- }, 10 * 60 * 1000);
825
+ }, CONTINUATION_TTL_MS);
609
826
  return ehrSuccess('ehr.recruit.candidate.import.prepare', {
610
827
  status: 'AWAITING_CONFIRMATION',
611
828
  preview: {
@@ -621,8 +838,9 @@ const candidateImportPrepare = {
621
838
  details: plan.details,
622
839
  tags: Array.isArray(args.tags) ? args.tags : [],
623
840
  },
841
+ ...(tagCheck ? { tagCheck } : {}),
624
842
  continuation,
625
- expiresInSeconds: 600,
843
+ expiresInSeconds: CONTINUATION_TTL_SECONDS,
626
844
  });
627
845
  },
628
846
  };
@@ -684,43 +902,31 @@ const candidateImportApply = {
684
902
  throw error;
685
903
  throw ehrPartialError(`简历建档写入结果不确定(${error?.message || '未知错误'}):请先用人才库搜索手机号 ${payload.telephone} 核对是否已建档,禁止直接重试`, { candidateName: payload.candidateName, telephone: payload.telephone });
686
904
  }
687
- // ③ 初始化人才批次(失败不回滚人才,仅记 warning)
688
- let batchOk = null;
689
- let batchNote;
690
- try {
691
- await env.host.request({
692
- path: `/api/recruit/candidate/initTalentBatch?formDataId=${encodeURIComponent(talentId)}`,
693
- method: 'POST',
694
- operation: 'ehr.recruit.candidate.import.apply',
695
- });
696
- batchOk = true;
697
- }
698
- catch (error) {
699
- batchOk = false;
700
- batchNote = `人才已建档,但初始化人才批次失败:${error?.message || '未知错误'}(可在人才卡片手动处理)`;
701
- }
702
- // ④ 触发后台智能标签规则(规则未配置时不产生标签,属正常)
703
- let labelMatch = null;
704
- try {
705
- const r = (await env.host.request({
706
- path: `/api/recruit/label/matchTalentLabel?talentId=${encodeURIComponent(talentId)}`,
707
- method: 'POST',
708
- body: {},
709
- operation: 'ehr.recruit.candidate.import.apply',
710
- }));
711
- labelMatch = r?.data === undefined ? 'TRIGGERED' : String(r.data);
712
- }
713
- catch {
714
- labelMatch = 'FAILED(不影响建档,可稍后在人才卡片手动触发)';
715
- }
716
- // ⑤ 平台标签(按名命中清单写入,不存在则跳过)
717
- let tagResult = { applied: [], skipped: [] };
718
- try {
719
- tagResult = await applyPlatformTags(env, talentId, Array.isArray(payload.tags) ? payload.tags.map(String) : []);
720
- }
721
- catch (error) {
722
- tagResult = { applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] };
723
- }
905
+ // ③④⑤ 初始化批次 / 触发电商后台标签规则 / 平台标签:三者只依赖 talentId,并行执行(各自 catch 等价原语义)
906
+ const batchTask = env.host
907
+ .request({
908
+ path: `/api/recruit/candidate/initTalentBatch?formDataId=${encodeURIComponent(talentId)}`,
909
+ method: 'POST',
910
+ operation: 'ehr.recruit.candidate.import.apply',
911
+ })
912
+ .then(() => ({ ok: true, note: undefined }))
913
+ .catch((error) => ({
914
+ ok: false,
915
+ note: `人才已建档,但初始化人才批次失败:${error?.message || '未知错误'}(可在人才卡片手动处理)`,
916
+ }));
917
+ const labelTask = env.host
918
+ .request({
919
+ path: `/api/recruit/label/matchTalentLabel?talentId=${encodeURIComponent(talentId)}`,
920
+ method: 'POST',
921
+ body: {},
922
+ operation: 'ehr.recruit.candidate.import.apply',
923
+ })
924
+ .then((r) => (r?.data === undefined ? 'TRIGGERED' : String(r.data)))
925
+ .catch(() => 'FAILED(不影响建档,可稍后在人才卡片手动触发)');
926
+ const tagTask = applyPlatformTags(env, talentId, Array.isArray(payload.tags) ? payload.tags.map(String) : []).catch(() => ({ applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] }));
927
+ const [batchOutcome, labelMatch, tagResult] = await Promise.all([batchTask, labelTask, tagTask]);
928
+ const batchOk = batchOutcome.ok;
929
+ const batchNote = batchOutcome.note;
724
930
  // ⑥ 产物链接:人才卡片单页 + 人才库列表定位(自用系统追加 recruitType=useSelf)
725
931
  const baseUrl = session.baseUrl.replace(/\/+$/, '');
726
932
  const extra = String(cache.selfUse) === '1' ? '&recruitType=useSelf' : '';
@@ -734,13 +940,61 @@ const candidateImportApply = {
734
940
  const warnings = [...(payload.warnings || [])];
735
941
  if (batchNote)
736
942
  warnings.push(batchNote);
943
+ // 明细完整性判定(2026-11-05 与 recruit-stage 同步修复):
944
+ // 主表建成 ≠ 建档成功。原实现 result 硬编码 'success' 且从不回读明细,
945
+ // 一旦日期格式等原因导致明细整批被拒,会出现「人才已建、经历全空」却仍报成功的静默事故。
946
+ // 规则:期望行数 > 0 时读回行数必须 >= 期望,否则 result 只能报 partial;回读失败标 unverified。
947
+ let detailsState = 'complete';
948
+ const expectedDetailRows = Object.values(payload.subStats || {}).reduce((sum, n) => sum + Number(n || 0), 0);
949
+ if (expectedDetailRows > 0) {
950
+ try {
951
+ const snapshot = (await env.host.request({
952
+ path: '/api/ebuilder/form/form/core/getFormDataAndLayout',
953
+ method: 'POST',
954
+ body: {
955
+ terminalType: 'PC',
956
+ dataId: talentId,
957
+ formId,
958
+ module: 'ebuilderform',
959
+ newLayout: true,
960
+ dataCrossLayout: false,
961
+ permissionId: '',
962
+ allReadOnly: true,
963
+ initialDatas: [],
964
+ dynamicData: false,
965
+ cost: false,
966
+ customParam: { objId, dataId: talentId },
967
+ },
968
+ operation: 'ehr.recruit.candidate.import.apply',
969
+ }));
970
+ const detailData = snapshot?.data?.formData?.dataDetails || [];
971
+ const seenRows = {};
972
+ for (const d of detailData) {
973
+ if (!d?.subFormId)
974
+ continue;
975
+ const key = String(d.subFormId);
976
+ (seenRows[key] = seenRows[key] || new Set()).add(String(d.dataIndex));
977
+ }
978
+ const gotRows = Object.values(seenRows).reduce((sum, set) => sum + set.size, 0);
979
+ if (gotRows < expectedDetailRows) {
980
+ detailsState = 'missing';
981
+ warnings.push(`明细行未完整落库(期望 ${expectedDetailRows} 行,读回 ${gotRows} 行):主表已写入,请核对后补齐明细`);
982
+ }
983
+ }
984
+ catch (error) {
985
+ detailsState = 'unverified';
986
+ warnings.push(`明细读回校验失败(无法确认明细是否落库):${error?.message || '未知错误'}`);
987
+ }
988
+ }
737
989
  return ehrSuccess('ehr.recruit.candidate.import.apply', {
738
- result: 'success',
990
+ result: detailsState === 'complete' ? 'success' : 'partial',
991
+ detailsState,
739
992
  talentId,
740
993
  candidateName: payload.candidateName,
741
994
  telephone: payload.telephone,
742
995
  mainTableFields: Object.keys(mainTable).length,
743
996
  detailRows: payload.subStats || undefined,
997
+ detailRowsExpected: expectedDetailRows || undefined,
744
998
  attachment: uploaded ? { name: uploaded.name, size: uploaded.size } : null,
745
999
  batch: { ok: batchOk, note: batchNote },
746
1000
  labelMatch,
@@ -1,3 +1,4 @@
1
+ import { CONTINUATION_TTL_MS, CONTINUATION_TTL_SECONDS } from '../../../core/continuation-ttl.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import { ehrConfirmationError, ehrValidationError } from '../errors.js';
3
4
  import { WRITE, SCHEMA_ID, ehrSuccess, schemaOf, } from './types.js';
@@ -25,6 +26,10 @@ const TEXT_KEYS = ['position_name'];
25
26
  const MTEXT_KEYS = ['position_duty', 'work_request'];
26
27
  const ASSOC_KEYS = ['demand'];
27
28
  const PERSON_DEFAULT_KEYS = ['recr_principal', 'employ_manager'];
29
+ // 🔴 薪资(salary_min / salary_max)必须沿用现值,不能留空:
30
+ // 这两个字段是**表单必填项**,不传就会导致后端必填校验失败、整个建职位流程直接报错。
31
+ // 但历史职位薪资确实可能是脏数据(实测抓到过 300 元月薪),因此不静默使用——
32
+ // 通过 summary.inheritedFromRef 逐项暴露给用户核对,并对明显偏低的值追加 inheritedSalaryWarnings 提示。
28
33
  const REF_COPY_KEYS = [
29
34
  'position_nature',
30
35
  'job_category',
@@ -41,6 +46,7 @@ const OPTION_DEFAULTS = { salary_type: '月薪', recruit_type: '社会招聘', s
41
46
  const SET_FIELDS = [
42
47
  { arg: 'education', key: 'education', kind: 'dict', label: '学历要求(按数据字典名称)' },
43
48
  { arg: 'workYears', key: 'work_years', kind: 'dict', label: '工作年限(按数据字典名称)' },
49
+ { arg: 'workLocation', key: 'work_location', kind: 'assoc', label: '工作地点(办公地点名称/详细地址,如「上海」或完整地址)' },
44
50
  { arg: 'jobCategory', key: 'job_category', kind: 'dict', label: '职位类别(按数据字典名称)' },
45
51
  { arg: 'positionNature', key: 'position_nature', kind: 'dict', label: '职位属性(按数据字典名称)' },
46
52
  { arg: 'salaryType', key: 'salary_type', kind: 'option', label: '薪酬类型(月薪/年薪等)' },
@@ -95,6 +101,105 @@ async function fetchReferenceDetails(env, cache, objId, formId) {
95
101
  return [];
96
102
  }
97
103
  }
104
+ const WORK_PLACE_NAMES = ['办公地点', '工作地点'];
105
+ /** 「办公地点」菜单定位:三级来源(lists.all_search → cache.menus(若存在)→ allMenus 接口),不依赖单一缓存键。
106
+ * 背景同 recruit-stage:原实现直接读 cache.menus,而该环境缓存没有 menus 字段 → 恒取不到 → 工作地点永远写不进去。 */
107
+ async function findWorkPlaceMenu(env, cache) {
108
+ const ok = (m) => !!(m && m.listId);
109
+ const pick = (list) => {
110
+ const hit = list.find((m) => ok(m) && WORK_PLACE_NAMES.some((n) => String(m.menuName || '').includes(n)));
111
+ return hit ? hit : null;
112
+ };
113
+ // ① 环境缓存 all_search(与面试数字人菜单同一模式)
114
+ const hit1 = pick((cache.lists?.all_search || []));
115
+ if (hit1)
116
+ return hit1;
117
+ // ② legacy menus(部分环境可能有)
118
+ const hit2 = pick((cache.menus || []));
119
+ if (hit2)
120
+ return hit2;
121
+ // ③ allMenus 接口兜底
122
+ try {
123
+ const r = (await env.host.request({
124
+ path: '/api/cusapp/app/allMenus',
125
+ query: { isFront: 1, appId: String(cache.appId || ''), terminalType: 'PC' },
126
+ }));
127
+ const flat = [];
128
+ (function walk(nodes) {
129
+ for (const n of nodes || []) {
130
+ if (n && typeof n === 'object') {
131
+ flat.push(n);
132
+ walk(n.children || n.childs);
133
+ }
134
+ }
135
+ })((r?.data?.cusAppMenus || r?.data));
136
+ return pick(flat);
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
142
+ /** 工作地点:按名称/详细地址/区域文本解析「办公地点」记录 id;解析不到返回 null(调用方进 setSkipped,不臆造 id)。 */
143
+ async function resolveWorkLocation(env, cache, value) {
144
+ const v = String(value).trim();
145
+ if (!v)
146
+ return null;
147
+ const menu = await findWorkPlaceMenu(env, cache);
148
+ if (!menu?.listId)
149
+ return null;
150
+ let pObj = '';
151
+ try {
152
+ const t = (await env.host.request({
153
+ path: '/api/ebuilder/form/obj/getObjsByTag',
154
+ query: { appId: String(cache.appId || ''), tag: 'uf_rcrt_work_place' },
155
+ }));
156
+ const d = t?.data;
157
+ if (Array.isArray(d) && d[0])
158
+ pObj = String(d[0].id || '');
159
+ }
160
+ catch {
161
+ /* tag 未注册:用菜单节点兜底 */
162
+ }
163
+ if (!pObj)
164
+ pObj = String(menu.objId || '');
165
+ if (!pObj)
166
+ return null;
167
+ const body = buildListBody({
168
+ listId: menu.listId,
169
+ cusMenuId: menu.cusMenuId,
170
+ menuName: menu.menuName || '办公地点',
171
+ title: menu.menuName || '办公地点',
172
+ pageSize: 200,
173
+ });
174
+ const r = (await env.host.request({
175
+ path: `/api/ebuilder/form/list/getListDatas?passid=${pObj}&cid=${pObj}`,
176
+ body,
177
+ headers: { ebBusinessId: menu.listId },
178
+ }));
179
+ const rows = (r?.data?.data || r?.data?.displayData || []);
180
+ const hit = rows.find((x) => {
181
+ const name = String(x?.name || '');
182
+ const detail = String(x?.detail_location || '');
183
+ const area = String(x?.area_text || '');
184
+ return name.includes(v) || detail.includes(v) || area.includes(v) || (!!detail && v.includes(detail));
185
+ });
186
+ return hit ? { id: String(hit.form_data_id || hit.id), name: String(hit.detail_location || hit.name || v) } : null;
187
+ }
188
+ /** 从提交 detail 取可读值(用于 summary 里点名「继承来的值」) */
189
+ function detailDisplayValue(detail) {
190
+ if (!detail)
191
+ return '';
192
+ const d = detail;
193
+ if (d.content !== undefined && d.content !== null)
194
+ return String(d.content);
195
+ if (Array.isArray(d.dataOptions) && d.dataOptions[0]) {
196
+ const o = d.dataOptions[0];
197
+ return String(o.content ?? o.optionId ?? '');
198
+ }
199
+ if (d.dataText?.content !== undefined)
200
+ return String(d.dataText.content).replace(/<[^>]+>/g, '').slice(0, 60);
201
+ return '';
202
+ }
98
203
  async function buildPositionPlan(env, cache, args) {
99
204
  const form = cache.forms.position_manage;
100
205
  const objId = form?.objId;
@@ -169,6 +274,15 @@ async function buildPositionPlan(env, cache, args) {
169
274
  put({ formField: { id: fieldId }, dataOptions: [{ optionId: String(optionId), content: value }] });
170
275
  applied.push(`${field.key}=${value}`);
171
276
  }
277
+ else if (field.kind === 'assoc') {
278
+ const loc = await resolveWorkLocation(env, cache, value);
279
+ if (!loc) {
280
+ skipped.push(`${field.key}=${value}(未匹配到「办公地点」记录,已跳过)`);
281
+ continue;
282
+ }
283
+ put({ formField: { id: fieldId }, dataOptions: [{ optionId: loc.id, content: loc.name }] });
284
+ applied.push(`${field.key}=${value}`);
285
+ }
172
286
  else if (field.kind === 'dict') {
173
287
  const ids = cache.dict.by_name[value] || [];
174
288
  const unique = [...new Set(ids.map(String))];
@@ -237,6 +351,18 @@ async function buildPositionPlan(env, cache, args) {
237
351
  const inverse = {};
238
352
  for (const [dataKey, fieldId] of Object.entries(fields))
239
353
  inverse[String(fieldId)] = dataKey;
354
+ // 继承来的薪资若明显偏低(历史脏数据,实测出现过 300 元月薪),额外点名提示。
355
+ // 不阻断提交(薪资是必填项,阻断等于无法建档),但要求 Agent 在确认摘要里明确提示用户核对。
356
+ const inheritedSalaryWarnings = [];
357
+ for (const key of ['salary_min', 'salary_max']) {
358
+ if (!inherited.includes(key))
359
+ continue;
360
+ const raw = detailDisplayValue(refMap.get(String(fid(key))));
361
+ const num = Number(String(raw).replace(/[^\d.]/g, ''));
362
+ if (raw && Number.isFinite(num) && num > 0 && num < 1000) {
363
+ inheritedSalaryWarnings.push(`${key} 继承值「${raw}」明显偏低(疑历史脏数据),请人工核对后再提交`);
364
+ }
365
+ }
240
366
  return {
241
367
  objId,
242
368
  formId,
@@ -250,6 +376,12 @@ async function buildPositionPlan(env, cache, args) {
250
376
  explicitApplied: applied,
251
377
  explicitSkipped: skipped,
252
378
  inheritedFromExistingPosition: inherited,
379
+ // 带值的继承清单:Agent 必须在确认摘要里逐项点名(尤其 work_location),
380
+ // 不得因为它是默认值就略过——历史上这里曾静默带出过重复地点等脏数据。
381
+ inheritedFromRef: inherited.length
382
+ ? inherited.map((k) => ({ field: k, value: detailDisplayValue(refMap.get(String(fid(k)))) }))
383
+ : undefined,
384
+ inheritedSalaryWarnings: inheritedSalaryWarnings.length ? inheritedSalaryWarnings : undefined,
253
385
  noReferenceValue: missingRef,
254
386
  principalDefault: session.userId ? '当前登录用户' : '未解析到当前用户',
255
387
  },
@@ -283,13 +415,13 @@ const positionCreatePrepare = {
283
415
  userId: session.userId,
284
416
  payload: { objId: plan.objId, formId: plan.formId, positionName: String(args.positionName).trim(), dataDetails: plan.dataDetails },
285
417
  fingerprint: fingerprint({ objId: plan.objId, dataDetails: plan.dataDetails }),
286
- }, 10 * 60 * 1000);
418
+ }, CONTINUATION_TTL_MS);
287
419
  return ehrSuccess('ehr.recruit.position.create.prepare', {
288
420
  status: 'AWAITING_CONFIRMATION',
289
421
  preview: { action: '生成职位JD并建职位(saveFormData → addPosition)', ...plan.summary },
290
422
  willSubmit: { objId: plan.objId, formId: plan.formId, dataDetails: plan.dataDetails },
291
423
  continuation,
292
- expiresInSeconds: 600,
424
+ expiresInSeconds: CONTINUATION_TTL_SECONDS,
293
425
  });
294
426
  },
295
427
  };