weaver-work-cli 0.1.2 → 0.1.5

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 (405) hide show
  1. package/README.md +176 -78
  2. package/dist/cmd/setup/index.js +5 -5
  3. package/dist/cmd/skills/index.js +1 -1
  4. package/dist/core/hooks.js +7 -0
  5. package/dist/index.js +0 -0
  6. package/dist/internal/e10/auth/commands.js +159 -54
  7. package/dist/internal/e10/auth/xiaoe.js +268 -0
  8. package/dist/internal/e10/context.js +16 -2
  9. package/dist/internal/e10/index.js +1 -0
  10. package/dist/internal/e10/request-runtime.js +345 -0
  11. package/dist/internal/skills/install.js +48 -6
  12. package/dist/internal/skills/reader.js +27 -0
  13. package/dist/shortcuts/archive/continuation.js +70 -0
  14. package/dist/shortcuts/archive/errors.js +53 -0
  15. package/dist/shortcuts/archive/host.js +197 -0
  16. package/dist/shortcuts/archive/index.js +363 -0
  17. package/dist/shortcuts/archive/manifest.js +45 -0
  18. package/dist/shortcuts/archive/operations/archive-info.js +55 -0
  19. package/dist/shortcuts/archive/operations/borrow-car.js +146 -0
  20. package/dist/shortcuts/archive/operations/borrow-list.js +200 -0
  21. package/dist/shortcuts/archive/operations/confirm.js +46 -0
  22. package/dist/shortcuts/archive/operations/download.js +238 -0
  23. package/dist/shortcuts/archive/operations/flow-url.js +240 -0
  24. package/dist/shortcuts/archive/operations/fonds.js +95 -0
  25. package/dist/shortcuts/archive/operations/getPageUrl.js +137 -0
  26. package/dist/shortcuts/archive/operations/registry.js +43 -0
  27. package/dist/shortcuts/archive/operations/search.js +88 -0
  28. package/dist/shortcuts/archive/operations/shared.js +120 -0
  29. package/dist/shortcuts/archive/operations/types.js +23 -0
  30. package/dist/shortcuts/archive/operations/upload.js +182 -0
  31. package/dist/shortcuts/archive/operations.js +13 -0
  32. package/dist/shortcuts/archive/render/search-format.js +276 -0
  33. package/dist/shortcuts/archive/render/search-view.js +125 -0
  34. package/dist/shortcuts/asset/continuation.js +70 -0
  35. package/dist/shortcuts/asset/errors.js +67 -0
  36. package/dist/shortcuts/asset/host.js +438 -0
  37. package/dist/shortcuts/asset/index.js +255 -0
  38. package/dist/shortcuts/asset/manifest.js +471 -0
  39. package/dist/shortcuts/asset/operations/query.js +249 -0
  40. package/dist/shortcuts/asset/operations/registry.js +85 -0
  41. package/dist/shortcuts/asset/operations/shared.js +100 -0
  42. package/dist/shortcuts/asset/operations/type-cache.js +49 -0
  43. package/dist/shortcuts/asset/operations/types.js +1 -0
  44. package/dist/shortcuts/asset/operations/viewlink.js +117 -0
  45. package/dist/shortcuts/asset/operations/write.js +435 -0
  46. package/dist/shortcuts/asset/operations.js +9 -0
  47. package/dist/shortcuts/calendar/continuation.js +70 -0
  48. package/dist/shortcuts/calendar/errors.js +53 -0
  49. package/dist/shortcuts/calendar/host.js +148 -0
  50. package/dist/shortcuts/calendar/index.js +125 -0
  51. package/dist/shortcuts/calendar/manifest.js +26 -0
  52. package/dist/shortcuts/calendar/operations/read.js +259 -0
  53. package/dist/shortcuts/calendar/operations/registry.js +31 -0
  54. package/dist/shortcuts/calendar/operations/shared.js +132 -0
  55. package/dist/shortcuts/calendar/operations/types.js +25 -0
  56. package/dist/shortcuts/calendar/operations/write.js +439 -0
  57. package/dist/shortcuts/calendar/operations.js +8 -0
  58. package/dist/shortcuts/ehr/continuation.js +70 -0
  59. package/dist/shortcuts/ehr/errors.js +53 -0
  60. package/dist/shortcuts/ehr/host.js +213 -0
  61. package/dist/shortcuts/ehr/index.js +205 -0
  62. package/dist/shortcuts/ehr/manifest.js +47 -0
  63. package/dist/shortcuts/ehr/operations/attend-read.js +373 -0
  64. package/dist/shortcuts/ehr/operations/attend-write.js +514 -0
  65. package/dist/shortcuts/ehr/operations/hr-contact.js +363 -0
  66. package/dist/shortcuts/ehr/operations/hr-ds.js +298 -0
  67. package/dist/shortcuts/ehr/operations/hr-report.js +386 -0
  68. package/dist/shortcuts/ehr/operations/recruit-write.js +1629 -0
  69. package/dist/shortcuts/ehr/operations/recruit.js +803 -0
  70. package/dist/shortcuts/ehr/operations/registry.js +43 -0
  71. package/dist/shortcuts/ehr/operations/salary.js +319 -0
  72. package/dist/shortcuts/ehr/operations/shared.js +246 -0
  73. package/dist/shortcuts/ehr/operations/types.js +25 -0
  74. package/dist/shortcuts/ehr/operations.js +25 -0
  75. package/dist/shortcuts/esb/continuation.js +70 -0
  76. package/dist/shortcuts/esb/errors.js +65 -0
  77. package/dist/shortcuts/esb/host.js +187 -0
  78. package/dist/shortcuts/esb/index.js +112 -0
  79. package/dist/shortcuts/esb/manifest.js +91 -0
  80. package/dist/shortcuts/esb/operations/input-format.js +31 -0
  81. package/dist/shortcuts/esb/operations/registry.js +48 -0
  82. package/dist/shortcuts/esb/operations/shared.js +152 -0
  83. package/dist/shortcuts/esb/operations/trigger.js +76 -0
  84. package/dist/shortcuts/esb/operations/types.js +21 -0
  85. package/dist/shortcuts/esb/operations.js +15 -0
  86. package/dist/shortcuts/fna/continuation.js +70 -0
  87. package/dist/shortcuts/fna/errors.js +59 -0
  88. package/dist/shortcuts/fna/host.js +146 -0
  89. package/dist/shortcuts/fna/index.js +111 -0
  90. package/dist/shortcuts/fna/manifest.js +41 -0
  91. package/dist/shortcuts/fna/operations/budget.js +124 -0
  92. package/dist/shortcuts/fna/operations/expense-center.js +148 -0
  93. package/dist/shortcuts/fna/operations/invoice-writeoff.js +212 -0
  94. package/dist/shortcuts/fna/operations/loan.js +195 -0
  95. package/dist/shortcuts/fna/operations/registry.js +35 -0
  96. package/dist/shortcuts/fna/operations/shared.js +210 -0
  97. package/dist/shortcuts/fna/operations/types.js +25 -0
  98. package/dist/shortcuts/fna/operations.js +19 -0
  99. package/dist/shortcuts/hrm/errors.js +38 -0
  100. package/dist/shortcuts/hrm/host.js +156 -0
  101. package/dist/shortcuts/hrm/index.js +111 -0
  102. package/dist/shortcuts/hrm/manifest.js +32 -0
  103. package/dist/shortcuts/hrm/operations/employee.js +338 -0
  104. package/dist/shortcuts/hrm/operations/org.js +110 -0
  105. package/dist/shortcuts/hrm/operations/position.js +176 -0
  106. package/dist/shortcuts/hrm/operations/registry.js +33 -0
  107. package/dist/shortcuts/hrm/operations/shared.js +143 -0
  108. package/dist/shortcuts/hrm/operations/types.js +23 -0
  109. package/dist/shortcuts/hrm/operations.js +19 -0
  110. package/dist/shortcuts/index.js +24 -0
  111. package/dist/shortcuts/invoice/host.js +99 -94
  112. package/dist/shortcuts/invoice/index.js +58 -59
  113. package/dist/shortcuts/invoice/manifest.js +200 -3
  114. package/dist/shortcuts/invoice/operations/browse-field.js +17 -0
  115. package/dist/shortcuts/invoice/operations/issuing.js +198 -0
  116. package/dist/shortcuts/invoice/operations/registry.js +17 -0
  117. package/dist/shortcuts/invoice/operations/reim.js +401 -0
  118. package/dist/shortcuts/invoice/operations/shared.js +247 -0
  119. package/dist/shortcuts/jiuchuanhui/cache.js +441 -0
  120. package/dist/shortcuts/jiuchuanhui/continuation.js +70 -0
  121. package/dist/shortcuts/jiuchuanhui/errors.js +59 -0
  122. package/dist/shortcuts/jiuchuanhui/host.js +159 -0
  123. package/dist/shortcuts/jiuchuanhui/index.js +109 -0
  124. package/dist/shortcuts/jiuchuanhui/manifest.js +469 -0
  125. package/dist/shortcuts/jiuchuanhui/operations/datajson.js +214 -0
  126. package/dist/shortcuts/jiuchuanhui/operations/esb.js +157 -0
  127. package/dist/shortcuts/jiuchuanhui/operations/generic.js +146 -0
  128. package/dist/shortcuts/jiuchuanhui/operations/registry.js +133 -0
  129. package/dist/shortcuts/jiuchuanhui/operations/shared.js +158 -0
  130. package/dist/shortcuts/jiuchuanhui/operations/types.js +1 -0
  131. package/dist/shortcuts/jiuchuanhui/operations.js +8 -0
  132. package/dist/shortcuts/mail/continuation.js +70 -0
  133. package/dist/shortcuts/mail/errors.js +53 -0
  134. package/dist/shortcuts/mail/host.js +182 -0
  135. package/dist/shortcuts/mail/index.js +519 -0
  136. package/dist/shortcuts/mail/manifest.js +38 -0
  137. package/dist/shortcuts/mail/operations/mail-blacklist.js +79 -0
  138. package/dist/shortcuts/mail/operations/mail-contacts.js +195 -0
  139. package/dist/shortcuts/mail/operations/mail-manage.js +335 -0
  140. package/dist/shortcuts/mail/operations/mail-read.js +508 -0
  141. package/dist/shortcuts/mail/operations/mail-send.js +474 -0
  142. package/dist/shortcuts/mail/operations/mail-sign.js +203 -0
  143. package/dist/shortcuts/mail/operations/mail-template.js +170 -0
  144. package/dist/shortcuts/mail/operations/registry.js +41 -0
  145. package/dist/shortcuts/mail/operations/shared.js +64 -0
  146. package/dist/shortcuts/mail/operations/types.js +27 -0
  147. package/dist/shortcuts/mail/operations.js +19 -0
  148. package/dist/shortcuts/meeting/continuation.js +70 -0
  149. package/dist/shortcuts/meeting/errors.js +63 -0
  150. package/dist/shortcuts/meeting/host.js +167 -0
  151. package/dist/shortcuts/meeting/index.js +123 -0
  152. package/dist/shortcuts/meeting/manifest.js +64 -0
  153. package/dist/shortcuts/meeting/operations/catalogs.js +58 -0
  154. package/dist/shortcuts/meeting/operations/change.js +242 -0
  155. package/dist/shortcuts/meeting/operations/conflicts.js +142 -0
  156. package/dist/shortcuts/meeting/operations/create.js +349 -0
  157. package/dist/shortcuts/meeting/operations/env.js +191 -0
  158. package/dist/shortcuts/meeting/operations/lifecycle.js +139 -0
  159. package/dist/shortcuts/meeting/operations/meetings.js +73 -0
  160. package/dist/shortcuts/meeting/operations/receipts.js +195 -0
  161. package/dist/shortcuts/meeting/operations/registry.js +47 -0
  162. package/dist/shortcuts/meeting/operations/rooms.js +132 -0
  163. package/dist/shortcuts/meeting/operations/shared.js +112 -0
  164. package/dist/shortcuts/meeting/operations/signs.js +41 -0
  165. package/dist/shortcuts/meeting/operations/types.js +25 -0
  166. package/dist/shortcuts/meeting/operations.js +19 -0
  167. package/dist/shortcuts/plan/continuation.js +70 -0
  168. package/dist/shortcuts/plan/errors.js +70 -0
  169. package/dist/shortcuts/plan/host.js +180 -0
  170. package/dist/shortcuts/plan/index.js +150 -0
  171. package/dist/shortcuts/plan/manifest.js +53 -0
  172. package/dist/shortcuts/plan/operations/link.js +256 -0
  173. package/dist/shortcuts/plan/operations/read.js +259 -0
  174. package/dist/shortcuts/plan/operations/registry.js +33 -0
  175. package/dist/shortcuts/plan/operations/shared.js +246 -0
  176. package/dist/shortcuts/plan/operations/types.js +49 -0
  177. package/dist/shortcuts/plan/operations/version.js +49 -0
  178. package/dist/shortcuts/plan/operations/write.js +710 -0
  179. package/dist/shortcuts/plan/operations.js +8 -0
  180. package/dist/shortcuts/yimiaoban/continuation.js +70 -0
  181. package/dist/shortcuts/yimiaoban/errors.js +61 -0
  182. package/dist/shortcuts/yimiaoban/host.js +469 -0
  183. package/dist/shortcuts/yimiaoban/index.js +271 -0
  184. package/dist/shortcuts/yimiaoban/manifest.js +28 -0
  185. package/dist/shortcuts/yimiaoban/operations/file-user.js +288 -0
  186. package/dist/shortcuts/yimiaoban/operations/group-read.js +477 -0
  187. package/dist/shortcuts/yimiaoban/operations/group-write.js +591 -0
  188. package/dist/shortcuts/yimiaoban/operations/msg-parse.js +429 -0
  189. package/dist/shortcuts/yimiaoban/operations/msg-sync.js +519 -0
  190. package/dist/shortcuts/yimiaoban/operations/msg-write.js +593 -0
  191. package/dist/shortcuts/yimiaoban/operations/person.js +102 -0
  192. package/dist/shortcuts/yimiaoban/operations/registry.js +38 -0
  193. package/dist/shortcuts/yimiaoban/operations/session.js +437 -0
  194. package/dist/shortcuts/yimiaoban/operations/shared.js +236 -0
  195. package/dist/shortcuts/yimiaoban/operations/types.js +27 -0
  196. package/dist/shortcuts/yimiaoban/operations/write-util.js +78 -0
  197. package/dist/shortcuts/yimiaoban/operations.js +8 -0
  198. package/docs/SKILL.md +11 -7
  199. package/docs/_catalog.md +28 -5
  200. package/docs/agent-invoice.md +19 -9
  201. package/docs/agent-skill-install.md +141 -22
  202. package/docs/calendar.md +87 -0
  203. package/docs/e10-auth.md +28 -9
  204. package/docs/ehr.md +186 -0
  205. package/docs/esb.md +64 -0
  206. package/docs/fna.md +72 -0
  207. package/docs/hrm.md +89 -0
  208. package/docs/invoice.md +61 -20
  209. package/docs/jiuchuanhui.md +131 -0
  210. package/docs/meeting.md +48 -0
  211. package/docs/operation-manual.md +443 -0
  212. package/docs/plan.md +82 -0
  213. package/docs/wenshuding.md +129 -0
  214. package/docs/yimiaoban.md +86 -0
  215. package/docs/ziguanjia.md +89 -0
  216. package/package.json +4 -4
  217. package/scripts/package-skill.mjs +127 -34
  218. package/scripts/postbuild.mjs +13 -0
  219. package/skill-template/business-info.json +16 -2
  220. package/skill-template/domains/calendar.md +15 -0
  221. package/skill-template/domains/esb.md +13 -0
  222. package/skill-template/domains/hrm.md +16 -0
  223. package/skill-template/domains/jiuchuanhui.md +23 -0
  224. package/skill-template/domains/jucailin.md +22 -0
  225. package/skill-template/domains/mail.md +21 -0
  226. package/skill-template/domains/meeting.md +3 -0
  227. package/skill-template/domains/plan.md +17 -0
  228. package/skill-template/domains/qiyecheng.md +17 -0
  229. package/skill-template/domains/shared.md +5 -3
  230. package/skill-template/domains/skill-maker.md +10 -0
  231. package/skill-template/domains/wenshuding.md +22 -0
  232. package/skill-template/domains/{invoice.md → yepiaotong.md} +4 -0
  233. package/skill-template/domains/yimiaoban.md +21 -0
  234. package/skill-template/domains/ziguanjia.md +21 -0
  235. package/skill-template/master-skill-template.md +12 -6
  236. package/skill-template/skill-template.md +26 -10
  237. package/skills/weaver-e10-calendar/SKILL.md +102 -0
  238. package/skills/weaver-e10-calendar/product.json +8 -0
  239. package/skills/weaver-e10-calendar/references/calendar-app-check.md +65 -0
  240. package/skills/weaver-e10-calendar/references/calendar-dict.md +55 -0
  241. package/skills/weaver-e10-calendar/references/calendar-query.md +70 -0
  242. package/skills/weaver-e10-calendar/references/calendar-write.md +97 -0
  243. package/skills/weaver-e10-calendar/references/source-manifest.json +54 -0
  244. package/skills/weaver-e10-esb/SKILL.md +103 -0
  245. package/skills/weaver-e10-esb/product.json +8 -0
  246. package/skills/weaver-e10-esb/references/input-format.md +52 -0
  247. package/skills/weaver-e10-esb/references/source-manifest.json +242 -0
  248. package/skills/weaver-e10-esb/references/trigger.md +99 -0
  249. package/skills/weaver-e10-hrm/SKILL.md +88 -0
  250. package/skills/weaver-e10-hrm/product.json +8 -0
  251. package/skills/weaver-e10-hrm/references/employee.md +109 -0
  252. package/skills/weaver-e10-hrm/references/org.md +95 -0
  253. package/skills/weaver-e10-hrm/references/position.md +95 -0
  254. package/skills/weaver-e10-hrm/references/source-manifest.json +121 -0
  255. package/skills/weaver-e10-jiuchuanhui/SKILL.md +175 -0
  256. package/skills/weaver-e10-jiuchuanhui/product.json +8 -0
  257. package/skills/weaver-e10-jiuchuanhui/references/cache.md +110 -0
  258. package/skills/weaver-e10-jiuchuanhui/references/clue.md +61 -0
  259. package/skills/weaver-e10-jiuchuanhui/references/contact-plan.md +56 -0
  260. package/skills/weaver-e10-jiuchuanhui/references/contact-records.md +48 -0
  261. package/skills/weaver-e10-jiuchuanhui/references/contact.md +56 -0
  262. package/skills/weaver-e10-jiuchuanhui/references/customer.md +69 -0
  263. package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +24 -0
  264. package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +60 -0
  265. package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +59 -0
  266. package/skills/weaver-e10-jiuchuanhui/references/jiuchuanhui-entry.md +60 -0
  267. package/skills/weaver-e10-jiuchuanhui/references/sale.md +72 -0
  268. package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +2632 -0
  269. package/skills/weaver-e10-jucailin/SKILL.md +102 -0
  270. package/skills/weaver-e10-jucailin/product.json +8 -0
  271. package/skills/weaver-e10-jucailin/references/attend-read.md +73 -0
  272. package/skills/weaver-e10-jucailin/references/attend-write.md +82 -0
  273. package/skills/weaver-e10-jucailin/references/hr-contact.md +92 -0
  274. package/skills/weaver-e10-jucailin/references/hr-datasource.md +104 -0
  275. package/skills/weaver-e10-jucailin/references/hr-report.md +76 -0
  276. package/skills/weaver-e10-jucailin/references/recruit-read.md +76 -0
  277. package/skills/weaver-e10-jucailin/references/recruit-write.md +70 -0
  278. package/skills/weaver-e10-jucailin/references/safety-boundaries.md +35 -0
  279. package/skills/weaver-e10-jucailin/references/salary.md +110 -0
  280. package/skills/weaver-e10-jucailin/references/source-manifest.json +152 -0
  281. package/skills/weaver-e10-mail/SKILL.md +152 -0
  282. package/skills/weaver-e10-mail/product.json +8 -0
  283. package/skills/weaver-e10-mail/references/mail-agent-entry.md +47 -0
  284. package/skills/weaver-e10-mail/references/mail-attachment.md +30 -0
  285. package/skills/weaver-e10-mail/references/mail-blacklist.md +27 -0
  286. package/skills/weaver-e10-mail/references/mail-contacts.md +33 -0
  287. package/skills/weaver-e10-mail/references/mail-manage.md +44 -0
  288. package/skills/weaver-e10-mail/references/mail-read.md +76 -0
  289. package/skills/weaver-e10-mail/references/mail-send.md +43 -0
  290. package/skills/weaver-e10-mail/references/mail-sign.md +33 -0
  291. package/skills/weaver-e10-mail/references/mail-template.md +31 -0
  292. package/skills/weaver-e10-mail/references/safety-boundaries.md +32 -0
  293. package/skills/weaver-e10-meeting/SKILL.md +106 -0
  294. package/skills/weaver-e10-meeting/product.json +8 -0
  295. package/skills/weaver-e10-meeting/references/meeting-change.md +67 -0
  296. package/skills/weaver-e10-meeting/references/meeting-create.md +52 -0
  297. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +57 -0
  298. package/skills/weaver-e10-meeting/references/meeting-queries.md +61 -0
  299. package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +48 -0
  300. package/skills/weaver-e10-meeting/references/meeting-update.md +7 -0
  301. package/skills/weaver-e10-meeting/references/source-manifest.json +50 -0
  302. package/skills/weaver-e10-plan/SKILL.md +140 -0
  303. package/skills/weaver-e10-plan/product.json +8 -0
  304. package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +123 -0
  305. package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +138 -0
  306. package/skills/weaver-e10-plan/references/plan-report-query.md +154 -0
  307. package/skills/weaver-e10-plan/references/plan-report-remind.md +104 -0
  308. package/skills/weaver-e10-plan/references/plan-report-write.md +162 -0
  309. package/skills/weaver-e10-plan/references/source-manifest.json +858 -0
  310. package/skills/weaver-e10-qiyecheng/SKILL.md +119 -0
  311. package/skills/weaver-e10-qiyecheng/product.json +8 -0
  312. package/skills/weaver-e10-qiyecheng/references/budget.md +65 -0
  313. package/skills/weaver-e10-qiyecheng/references/catalog.md +56 -0
  314. package/skills/weaver-e10-qiyecheng/references/expense-center.md +51 -0
  315. package/skills/weaver-e10-qiyecheng/references/invoice-writeoff.md +57 -0
  316. package/skills/weaver-e10-qiyecheng/references/loan-management.md +59 -0
  317. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +698 -0
  318. package/skills/weaver-e10-shared/SKILL.md +90 -0
  319. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +127 -0
  320. package/skills/{weaver-work-cli-shared → weaver-e10-shared}/references/json-output-contract.md +34 -0
  321. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +110 -0
  322. package/skills/weaver-e10-skill-maker/SKILL.md +78 -0
  323. package/skills/weaver-e10-skill-maker/product.json +8 -0
  324. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +124 -0
  325. package/skills/weaver-e10-skill-maker/references/detector-validation.md +101 -0
  326. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +230 -0
  327. package/skills/weaver-e10-skill-maker/references/post-generation-install.md +105 -0
  328. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +261 -0
  329. package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +141 -0
  330. package/skills/weaver-e10-wenshuding/SKILL.md +158 -0
  331. package/skills/weaver-e10-wenshuding/product.json +8 -0
  332. package/skills/weaver-e10-wenshuding/references/archive-agent-entry.md +63 -0
  333. package/skills/weaver-e10-wenshuding/references/archive-borrow-car.md +52 -0
  334. package/skills/weaver-e10-wenshuding/references/archive-borrow-list.md +52 -0
  335. package/skills/weaver-e10-wenshuding/references/archive-disabled-capabilities.md +22 -0
  336. package/skills/weaver-e10-wenshuding/references/archive-download.md +48 -0
  337. package/skills/weaver-e10-wenshuding/references/archive-flow.md +46 -0
  338. package/skills/weaver-e10-wenshuding/references/archive-fonds.md +34 -0
  339. package/skills/weaver-e10-wenshuding/references/archive-info.md +33 -0
  340. package/skills/weaver-e10-wenshuding/references/archive-search.md +52 -0
  341. package/skills/weaver-e10-wenshuding/references/archive-upload.md +41 -0
  342. package/skills/weaver-e10-wenshuding/references/source-manifest.json +517 -0
  343. package/skills/weaver-e10-yepiaotong/SKILL.md +184 -0
  344. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-add.md +1 -1
  345. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-agent-entry.md +16 -9
  346. package/skills/weaver-e10-yepiaotong/references/invoice-browse-field-data.md +204 -0
  347. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-delete.md +1 -1
  348. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-detail.md +13 -5
  349. package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +28 -0
  350. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-download.md +9 -2
  351. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-enterprise-list.md +12 -4
  352. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-file-upload.md +9 -2
  353. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-import.md +16 -7
  354. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +120 -0
  355. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-field-rules.md +161 -0
  356. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +99 -0
  357. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-ocr-preview.md +12 -4
  358. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-personal-list.md +12 -4
  359. package/skills/weaver-e10-yepiaotong/references/invoice-red.md +261 -0
  360. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +97 -0
  361. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-update.md +1 -1
  362. package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/references/invoice-validation-preview.md +9 -2
  363. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +1340 -0
  364. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +845 -0
  365. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +94 -0
  366. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +449 -0
  367. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +266 -0
  368. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +494 -0
  369. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1103 -0
  370. package/skills/weaver-e10-yimiaoban/SKILL.md +104 -0
  371. package/skills/weaver-e10-yimiaoban/product.json +8 -0
  372. package/skills/weaver-e10-yimiaoban/references/ding-write.md +68 -0
  373. package/skills/weaver-e10-yimiaoban/references/error-codes.md +85 -0
  374. package/skills/weaver-e10-yimiaoban/references/field-resolution.md +46 -0
  375. package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +54 -0
  376. package/skills/weaver-e10-yimiaoban/references/group-read.md +55 -0
  377. package/skills/weaver-e10-yimiaoban/references/group-write.md +72 -0
  378. package/skills/weaver-e10-yimiaoban/references/msg-read.md +59 -0
  379. package/skills/weaver-e10-yimiaoban/references/msg-write.md +64 -0
  380. package/skills/weaver-e10-yimiaoban/references/person.md +44 -0
  381. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +61 -0
  382. package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +47 -0
  383. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +485 -0
  384. package/skills/weaver-e10-ziguanjia/SKILL.md +163 -0
  385. package/skills/weaver-e10-ziguanjia/product.json +8 -0
  386. package/skills/weaver-e10-ziguanjia/references/source-manifest.json +147 -0
  387. package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +65 -0
  388. package/skills/weaver-e10-ziguanjia/references/ziguanjia-create.md +45 -0
  389. package/skills/weaver-e10-ziguanjia/references/ziguanjia-depre.md +48 -0
  390. package/skills/weaver-e10-ziguanjia/references/ziguanjia-disabled-capabilities.md +22 -0
  391. package/skills/weaver-e10-ziguanjia/references/ziguanjia-purch.md +57 -0
  392. package/skills/weaver-e10-ziguanjia/references/ziguanjia-query.md +62 -0
  393. package/skills/weaver-e10-ziguanjia/references/ziguanjia-repair.md +83 -0
  394. package/skills/weaver-e10-ziguanjia/references/ziguanjia-resolve.md +49 -0
  395. package/skills/weaver-e10-ziguanjia/references/ziguanjia-return.md +70 -0
  396. package/skills/weaver-e10-ziguanjia/references/ziguanjia-update.md +45 -0
  397. package/skills/weaver-e10-ziguanjia/references/ziguanjia-use.md +60 -0
  398. package/skills/weaver-e10-ziguanjia/references/ziguanjia-viewlink.md +81 -0
  399. package/skills/weaver-work-cli-invoice/SKILL.md +0 -122
  400. package/skills/weaver-work-cli-invoice/references/invoice-disabled-capabilities.md +0 -26
  401. package/skills/weaver-work-cli-shared/SKILL.md +0 -63
  402. package/skills/weaver-work-cli-shared/references/e10-auth-and-session.md +0 -90
  403. package/skills/weaver-work-cli-shared/references/weaver-work-cli-installation.md +0 -73
  404. /package/skills/{weaver-work-cli-shared → weaver-e10-shared}/references/high-risk-write.md +0 -0
  405. /package/skills/{weaver-work-cli-invoice → weaver-e10-yepiaotong}/product.json +0 -0
@@ -0,0 +1,803 @@
1
+ import { randomBytes, randomUUID } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join, resolve } from 'node:path';
5
+ import { ehrValidationError } from '../errors.js';
6
+ import { READ, SCHEMA_ID, ehrSuccess, schemaOf, } from './types.js';
7
+ import { compact, normalizePaged, toNumber, toPageQuery, toPositiveInt } from './shared.js';
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ // 五层运行时解析(迁移自 ehr 技能 _init_env_cache.mjs,真机验证过)
10
+ // getAppIds -> getObjsByTag -> allMenus -> ds/fields -> ds/options
11
+ // 缓存:进程内 memo + 磁盘(缓存根 = E10_SKILL_CACHE_DIR 环境变量优先,
12
+ // 未设置回退 CLI 数据目录 WEAVER_WORK_CLI_HOME(默认用户主目录下 .weaver-work-cli)的
13
+ // env-cache/recruit-ops/<host>_<port>/<appId>.json。与 ehr 技能同构,
14
+ // 设同一 E10_SKILL_CACHE_DIR 即可共享缓存)。菜单名跨版本不同,解析不到必须报错,禁止臆造。
15
+ // ─────────────────────────────────────────────────────────────────────────────
16
+ const RECRUIT_APP_TAG = 'weaver-recruit-service';
17
+ /** 逻辑名 -> objTag(权威映射,与 _init_env_cache.mjs 一致) */
18
+ const RECRUIT_TAGS = {
19
+ talent_pool: 'uf_rcrt_talent_pool',
20
+ interview_plan: 'uf_rcrt_interview_plan',
21
+ interview_detail: 'uf_rcrt_interview_detail',
22
+ demand_manage: 'uf_rcrt_demand_manage',
23
+ position_manage: 'uf_rcrt_position_manage',
24
+ entry_manage: 'uf_rcrt_entry_manage',
25
+ offer: 'uf_rcrt_offer',
26
+ offer_sending: 'uf_rcrt_offer_sending',
27
+ candidate_manage: 'uf_rcrt_candidate_manage',
28
+ entry_transact: 'uf_rcrt_entry_transact',
29
+ entry_cancel: 'uf_rcrt_entry_cancel',
30
+ entry_change: 'uf_rcrt_entry_change',
31
+ dictionary: 'uf_rcrt_dictionary',
32
+ biz_config: 'uf_rcrt_biz_config_mapper',
33
+ };
34
+ /** 列表业务名 -> 菜单名关键词(按 ehr 技能 KEYWORDS,跨版本菜单名用 includes 匹配) */
35
+ const LIST_KEYWORDS = {
36
+ talent: ['人才库', '人才管理'],
37
+ demand: ['招聘需求', '需求'],
38
+ position: ['招聘职位', '职位列表', '职位管理'],
39
+ entry: ['入职管理'],
40
+ offer: ['录用管理', 'offer管理', 'offer'],
41
+ interview: ['面试管理'],
42
+ biz_config: ['业务配置映射表'],
43
+ };
44
+ /** 列表类型 -> 缓存键 + 表单逻辑名(candidate.list 四列表映射,同 recruit-list.mjs TYPES) */
45
+ const LIST_TYPES = {
46
+ demand: { listKey: 'demand', formType: 'demand_manage', title: '招聘需求' },
47
+ position: { listKey: 'position', formType: 'position_manage', title: '招聘职位' },
48
+ entry: { listKey: 'entry', formType: 'entry_manage', title: '入职管理' },
49
+ offer: { listKey: 'offer', formType: 'offer', title: '录用管理' },
50
+ };
51
+ /** 剔除与展示无关的内部键(同 recruit-list.mjs) */
52
+ const INTERNAL_KEYS = new Set([
53
+ 'id', 'form_data_id', 'form_table_id', 'rowKey', 'ebrecord_rowkey',
54
+ 'isFollow', 'is_flow', 'data_status', 'data_status_value', 'update_time',
55
+ 'formDataId', 'isFollowSearch', 'isShareToMe',
56
+ ]);
57
+ /** displayData 显示层的额外 UI/内部字段(同 recruit-list.mjs DISPLAY_UI_KEYS) */
58
+ const DISPLAY_UI_KEYS = new Set([
59
+ ...INTERNAL_KEYS, 'operate', 'isToDo', 'todoPropSpan', 'flow_status',
60
+ ]);
61
+ function randHex32() {
62
+ return randomUUID().replace(/-/g, '');
63
+ }
64
+ function randHex6() {
65
+ return randomBytes(3).toString('hex');
66
+ }
67
+ /** 缓存目录:E10_SKILL_CACHE_DIR 优先(与 ehr 技能同语义:根下直接 <host>_<port>);未设置回退 CLI 数据目录 env-cache/recruit-ops */
68
+ function cacheDirFor(baseUrl) {
69
+ const url = new URL(baseUrl);
70
+ const host = url.hostname + (url.port ? `_${url.port}` : '');
71
+ const envRoot = process.env.E10_SKILL_CACHE_DIR;
72
+ if (envRoot)
73
+ return join(envRoot, host);
74
+ const home = process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve(homedir(), '.weaver-work-cli');
75
+ return join(home, 'env-cache', 'recruit-ops', host);
76
+ }
77
+ /** 内联展示字段解析:门户字段三种形态(数组/对象/字符串 JSON),同 recruit-detail.mjs namesOf */
78
+ function namesOf(field) {
79
+ if (!field)
80
+ return null;
81
+ let arr;
82
+ if (Array.isArray(field))
83
+ arr = field;
84
+ else if (typeof field === 'object')
85
+ arr = [field];
86
+ else if (typeof field === 'string') {
87
+ const text = field.trim();
88
+ if (!text.startsWith('[') && !text.startsWith('{'))
89
+ return text || null;
90
+ try {
91
+ arr = JSON.parse(text);
92
+ }
93
+ catch {
94
+ return text || null;
95
+ }
96
+ if (!Array.isArray(arr))
97
+ arr = [arr];
98
+ }
99
+ else
100
+ return null;
101
+ const names = arr
102
+ .map((item) => (item && typeof item === 'object' ? item.name || item.username || item.text || item.title : null))
103
+ .filter(Boolean);
104
+ return names.length ? names.join('、') : null;
105
+ }
106
+ function isPlainId(value) {
107
+ return value != null && /^\d+$/.test(String(value).trim());
108
+ }
109
+ class RecruitContextError extends Error {
110
+ subtype;
111
+ constructor(subtype, message) {
112
+ super(message);
113
+ this.subtype = subtype;
114
+ }
115
+ }
116
+ /** ds/fields 单表单结构拉取(multipart,与 _init_env_cache.mjs fetchFields 等价) */
117
+ async function fetchFormFields(host, appId, objId) {
118
+ const form = new FormData();
119
+ form.set('groupId', appId);
120
+ form.set('sourceId', objId);
121
+ form.set('sourceType', 'FORM');
122
+ form.set('detailFieldsGroup', 'true');
123
+ form.set('enableMerge', 'true');
124
+ form.set('customParam', '{"terminal":""}');
125
+ form.set('params', '[]');
126
+ const response = (await host.request({
127
+ method: 'POST',
128
+ path: '/api/ebuilder/common/ds/fields',
129
+ multipart: form,
130
+ }));
131
+ const fmap = {};
132
+ const omap = {};
133
+ for (const group of response?.data || []) {
134
+ for (const field of group?.fields || []) {
135
+ const config = field?.config || {};
136
+ const dataKey = config.dataKey || '';
137
+ const fieldId = String(field?.id || '');
138
+ if (dataKey && fieldId)
139
+ fmap[dataKey] = fieldId;
140
+ if (fieldId && Array.isArray(config.options) && config.options.length) {
141
+ const map = {};
142
+ for (const option of config.options) {
143
+ if (!option || typeof option !== 'object')
144
+ continue;
145
+ const name = option.name;
146
+ let selectionId = option.selectionId;
147
+ if (!selectionId && typeof option.extra === 'string') {
148
+ try {
149
+ const extra = JSON.parse(option.extra);
150
+ selectionId = extra.selectionId || extra.id;
151
+ }
152
+ catch { /* 坏 extra 回退 */ }
153
+ }
154
+ if (!selectionId)
155
+ selectionId = option.value || option.valueKey || option.id;
156
+ if (selectionId && name)
157
+ map[String(selectionId)] = name;
158
+ }
159
+ if (Object.keys(map).length)
160
+ omap[fieldId] = map;
161
+ }
162
+ }
163
+ }
164
+ return { fmap, omap };
165
+ }
166
+ /** 五层解析主流程(磁盘缓存缺失时执行;每层失败必须报错,禁止臆造) */
167
+ async function resolveRecruitEnv(host, appId) {
168
+ // L2:tag 解析各表单 objId/formId(顺带 tenantKey)
169
+ const forms = {};
170
+ let tenantKey = '';
171
+ for (const [logic, tag] of Object.entries(RECRUIT_TAGS)) {
172
+ const response = (await host.request({
173
+ path: '/api/ebuilder/form/obj/getObjsByTag',
174
+ query: { appId, tag },
175
+ }));
176
+ const entry = Array.isArray(response?.data) && response.data.length ? response.data[0] : null;
177
+ forms[logic] = {
178
+ objId: String(entry?.id || ''),
179
+ formId: String(entry?.formId || ''),
180
+ objName: entry?.objName || '',
181
+ };
182
+ if (!tenantKey && entry?.tenantKey)
183
+ tenantKey = String(entry.tenantKey);
184
+ }
185
+ // L3:allMenus 菜单树 -> SEARCH 列表 + PAGE 页面
186
+ const menuResponse = (await host.request({
187
+ path: '/api/cusapp/app/allMenus',
188
+ query: { isFront: 1, appId, terminalType: 'PC' },
189
+ }));
190
+ const flat = [];
191
+ const walk = (nodes) => {
192
+ for (const node of nodes || []) {
193
+ if (node && typeof node === 'object') {
194
+ flat.push(node);
195
+ walk(node.children || node.childs);
196
+ }
197
+ }
198
+ };
199
+ const menuData = menuResponse?.data;
200
+ walk(typeof menuData === 'object' && menuData ? menuData.cusAppMenus || menuData : menuData);
201
+ const searchMenus = [];
202
+ const pages = [];
203
+ for (const node of flat) {
204
+ if (node.pageType === 'SEARCH') {
205
+ searchMenus.push({ menuName: node.menuName, listId: String(node.pageId || ''), cusMenuId: String(node.id || '') });
206
+ }
207
+ else if (node.pageType === 'PAGE') {
208
+ pages.push({ menuName: node.menuName, pageId: String(node.pageId || '') });
209
+ }
210
+ }
211
+ // L4:ds/fields 并行拉全部已解析表单的字段映射 + 选择类字段选项(零额外请求)
212
+ const fields = {};
213
+ const fieldOptions = {};
214
+ const resolvedForms = Object.entries(forms).filter(([, v]) => v.objId);
215
+ await Promise.all(resolvedForms.map(async ([logic, entry]) => {
216
+ const { fmap, omap } = await fetchFormFields(host, appId, entry.objId);
217
+ if (Object.keys(fmap).length)
218
+ fields[entry.objId] = fmap;
219
+ if (Object.keys(omap).length)
220
+ fieldOptions[entry.objId] = omap;
221
+ void logic;
222
+ }));
223
+ // L5:数据字典表全量映射(字典引用类字段如渠道的 optionId 来源)
224
+ const dictByName = {};
225
+ const dictRaw = [];
226
+ const dictMenu = searchMenus.find((m) => (m.menuName || '').trim() === '数据字典') || null;
227
+ const dictObjId = forms.dictionary?.objId || '';
228
+ if (dictObjId && dictMenu) {
229
+ const size = 500;
230
+ let current = 1;
231
+ for (;;) {
232
+ const response = (await host.request({
233
+ path: `/api/ebuilder/form/list/getListDatas?passid=${dictObjId}&cid=${dictObjId}`,
234
+ body: {
235
+ current, pageSize: size, tableuid: randHex32(),
236
+ listId: dictMenu.listId,
237
+ searchParamData: { searchType: '3', type: 'and' },
238
+ terminal: 'PC', browser: 'Chrome', requiredMatch: 1, mapResult: 1,
239
+ recheckQuery: 1, isFollow: 0, isShareToMe: 0, filterCondition: {},
240
+ cusMenuId: dictMenu.cusMenuId, urlPageTitle: '数据字典', menuName: '数据字典',
241
+ },
242
+ headers: { ebBusinessId: dictMenu.listId },
243
+ }));
244
+ const rows = response?.data?.data || [];
245
+ for (const row of rows) {
246
+ const name = row.selection_name;
247
+ const optionId = row.form_data_id;
248
+ if (name && optionId) {
249
+ (dictByName[String(name)] ||= []).push(String(optionId));
250
+ dictRaw.push({ selection_name: String(name), option_id: String(optionId), dict_type: row.dict_type, browser_key: row.browser_key });
251
+ }
252
+ }
253
+ if (rows.length < size)
254
+ break;
255
+ current += 1;
256
+ }
257
+ }
258
+ // 人才卡片页面 id(L1 业务配置表 config_key=28 前台可查;L2 page/list 兜底,失败不阻塞)+ 泛微自用标记
259
+ let ebdDetailPageId = '';
260
+ let selfUse = '0';
261
+ const bizConfig = forms.biz_config || { objId: '', formId: '', objName: '' };
262
+ const bizConfigMenu = searchMenus.find((m) => (m.menuName || '').trim() === '业务配置映射表') || null;
263
+ if (bizConfig.objId && bizConfigMenu) {
264
+ try {
265
+ const { fmap } = await fetchFormFields(host, appId, bizConfig.objId);
266
+ const keyField = fmap.config_key || '';
267
+ const valueField = fmap.config || '';
268
+ if (keyField && valueField) {
269
+ let current = 1;
270
+ for (;;) {
271
+ const response = (await host.request({
272
+ path: `/api/ebuilder/form/list/getListDatas?passid=${bizConfig.objId}&cid=${bizConfig.objId}`,
273
+ body: {
274
+ current, pageSize: 100, tableuid: randHex32(),
275
+ listId: bizConfigMenu.listId,
276
+ searchParamData: { searchType: '3', type: 'and' },
277
+ terminal: 'PC', browser: 'Chrome', requiredMatch: 1, mapResult: 1,
278
+ recheckQuery: 1, isFollow: 0, isShareToMe: 0, filterCondition: {},
279
+ cusMenuId: bizConfigMenu.cusMenuId, urlPageTitle: '业务配置映射表', menuName: '业务配置映射表',
280
+ },
281
+ headers: { ebBusinessId: bizConfigMenu.listId },
282
+ }));
283
+ const rows = response?.data?.data || [];
284
+ if (!rows.length)
285
+ break;
286
+ for (const row of rows) {
287
+ if (String(row.config_key || '') === '28' && row.config) {
288
+ const match = String(row.config).match(/\/sp\/ebdpage\/view\/(\d+)/);
289
+ if (match)
290
+ ebdDetailPageId = match[1];
291
+ }
292
+ if (String(row.config_key || '') === '-9999' && String(row.config) === '1')
293
+ selfUse = '1';
294
+ }
295
+ if (rows.length < 100)
296
+ break;
297
+ current += 1;
298
+ }
299
+ }
300
+ }
301
+ catch { /* 配置表权限不足不阻塞,保持空 */ }
302
+ }
303
+ if (!ebdDetailPageId) {
304
+ try {
305
+ const response = (await host.request({
306
+ path: '/api/bs/ebuilder/page/list',
307
+ query: { appid: appId },
308
+ }));
309
+ for (const page of (Array.isArray(response?.data) ? response.data : [])) {
310
+ if ((page?.name || '') === '人才卡片' && page?.type === 'PAGE' && page?.id) {
311
+ ebdDetailPageId = String(page.id);
312
+ break;
313
+ }
314
+ }
315
+ }
316
+ catch { /* 后台权限不足不阻塞,保持空 */ }
317
+ }
318
+ // ds/options 兼容通道(人才库 recruit_status/channel;字典引用类返回空则跳过)
319
+ const options = {};
320
+ for (const [dataKey, logic] of [['recruit_status', 'talent_pool'], ['channel', 'talent_pool']]) {
321
+ const entry = forms[logic] || { objId: '', formId: '', objName: '' };
322
+ const fieldId = (fields[entry.objId] || {})[dataKey] || '';
323
+ if (fieldId && entry.objId) {
324
+ const response = (await host.request({
325
+ path: '/api/ebuilder/common/ds/options',
326
+ query: { fieldName: fieldId, objId: entry.objId, sourceType: 'FORM', groupId: appId },
327
+ }));
328
+ if (Array.isArray(response?.data)) {
329
+ options[dataKey] = {};
330
+ for (const option of response.data) {
331
+ if (option?.id)
332
+ options[dataKey][String(option.id)] = option.name;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ const lists = {
338
+ talent: null, demand: null, position: null, entry: null, offer: null,
339
+ interview: null, dict: dictMenu, biz_config: bizConfigMenu,
340
+ all_search: searchMenus, pages,
341
+ };
342
+ for (const [biz, keywords] of Object.entries(LIST_KEYWORDS)) {
343
+ for (const menu of searchMenus) {
344
+ if (keywords.some((keyword) => (menu.menuName || '').includes(keyword))) {
345
+ lists[biz] = menu;
346
+ break;
347
+ }
348
+ }
349
+ }
350
+ return {
351
+ appId,
352
+ tenantKey,
353
+ forms,
354
+ lists,
355
+ fields,
356
+ field_options: fieldOptions,
357
+ options,
358
+ dict: { by_name: dictByName, raw: dictRaw },
359
+ ebdDetailPageId,
360
+ selfUse,
361
+ };
362
+ }
363
+ export function createRecruitContextLoader() {
364
+ const memo = new Map();
365
+ async function load(host) {
366
+ const session = await host.getSession();
367
+ const baseUrl = session.baseUrl.replace(/\/+$/, '');
368
+ const memoKey = baseUrl;
369
+ // 磁盘缓存优先:目录内唯一 <appId>.json 直接命中(省安装闸门 1 次 RTT,
370
+ // 与 ehr 技能播种的缓存共享同一目录结构)。
371
+ let cached = memo.get(memoKey);
372
+ if (cached)
373
+ return cached;
374
+ let appId = '';
375
+ let diskCache = null;
376
+ try {
377
+ const dir = cacheDirFor(baseUrl);
378
+ if (existsSync(dir)) {
379
+ const files = readdirSync(dir).filter((file) => file.endsWith('.json'));
380
+ if (files.length === 1) {
381
+ appId = files[0].replace(/\.json$/, '');
382
+ diskCache = JSON.parse(readFileSync(join(dir, files[0]), 'utf8'));
383
+ }
384
+ }
385
+ }
386
+ catch { /* 缓存读取失败回退闸门链路 */ }
387
+ if (diskCache) {
388
+ memo.set(memoKey, diskCache);
389
+ return diskCache;
390
+ }
391
+ // 安装闸门:getAppIds(tag) 取 appId(空=未安装招聘服务,必须明确报错)
392
+ const gate = (await host.request({
393
+ path: '/api/bs/ebuilder/app/tags/getAppIds',
394
+ query: { tag: RECRUIT_APP_TAG },
395
+ }));
396
+ const appIds = gate?.data;
397
+ if (!Array.isArray(appIds) || !appIds.length) {
398
+ throw new RecruitContextError('recruit_service_not_installed', '当前租户未安装招聘服务(weaver-recruit-service),无法使用招聘能力。请先在 E10 应用市场安装「招聘」应用。');
399
+ }
400
+ appId = String(appIds[0]);
401
+ const resolved = await resolveRecruitEnv(host, appId);
402
+ // 写磁盘缓存(结构同 ehr 技能 v5,供后续进程/ehr 技能共享)
403
+ try {
404
+ const dir = cacheDirFor(baseUrl);
405
+ mkdirSync(dir, { recursive: true });
406
+ writeFileSync(join(dir, `${appId}.json`), JSON.stringify({
407
+ __meta__: {
408
+ capturedAt: new Date().toISOString().replace('T', ' ').substring(0, 19),
409
+ note: 'recruit-ops 环境参数缓存(weaver-work-cli 运行时解析产物,不含认证字段)',
410
+ },
411
+ envKey: `${dir.split(/[\\/]/).pop()}|${appId}`,
412
+ ...resolved,
413
+ }, null, 2), 'utf8');
414
+ }
415
+ catch { /* 缓存落盘失败不影响本次调用 */ }
416
+ memo.set(memoKey, resolved);
417
+ return resolved;
418
+ }
419
+ return { load };
420
+ }
421
+ /** EB 列表通用查询体(同 recruit-list.mjs baseBody) */
422
+ function buildListBody(params) {
423
+ return {
424
+ current: params.current ?? 1,
425
+ pageSize: params.pageSize ?? 10,
426
+ tableuid: randHex32(),
427
+ listId: params.listId,
428
+ searchParamData: {
429
+ searchType: '3',
430
+ type: 'and',
431
+ ...(params.conditions && Object.keys(params.conditions).length ? { commonSearchFields: params.conditions } : {}),
432
+ },
433
+ terminal: 'PC',
434
+ browser: 'Chrome',
435
+ requiredMatch: 1,
436
+ mapResult: 1,
437
+ recheckQuery: 1,
438
+ isFollow: 0,
439
+ isShareToMe: 0,
440
+ filterCondition: {},
441
+ cusMenuId: params.cusMenuId,
442
+ urlPageTitle: params.title,
443
+ menuName: params.menuName,
444
+ };
445
+ }
446
+ /** 列表 + 计数并行;displayData 优先(同 recruit-search/recruit-list 的显示层策略) */
447
+ async function fetchListRows(host, objId, listId, body) {
448
+ const countBody = { ...body };
449
+ delete countBody.current;
450
+ delete countBody.pageSize;
451
+ const [listResponse, countResponse] = await Promise.all([
452
+ host.request({
453
+ path: `/api/ebuilder/form/list/getListDatas?passid=${objId}&cid=${objId}`,
454
+ body,
455
+ headers: { ebBusinessId: listId },
456
+ }),
457
+ host.request({
458
+ path: `/api/ebuilder/form/list/getListDataCount?passid=${objId}&cid=${objId}`,
459
+ body: countBody,
460
+ headers: { ebBusinessId: listId },
461
+ }).catch(() => null),
462
+ ]);
463
+ const data = normalizePaged(listResponse).data;
464
+ const rawRows = data?.data || [];
465
+ const displayRows = data?.displayData;
466
+ const hasDisplay = Array.isArray(displayRows) && displayRows.length > 0;
467
+ const rows = hasDisplay ? displayRows : rawRows;
468
+ const countData = countResponse ? normalizePaged(countResponse).data : null;
469
+ const total = countData?.total !== undefined ? countData.total : rows.length;
470
+ return { rows, displayRows: hasDisplay ? displayRows : null, total };
471
+ }
472
+ // ─────────────────────────────────────────────────────────────────────────────
473
+ // operations
474
+ // ─────────────────────────────────────────────────────────────────────────────
475
+ const contextResolve = {
476
+ name: 'ehr.recruit.context.resolve',
477
+ resource: 'recruit',
478
+ method: 'context.resolve',
479
+ action: 'ehr.recruit.context.resolve',
480
+ summary: '解析招聘模块运行时参数(appId/表单 objId/列表 listId+cusMenuId/字段映射),主要供调试与兜底;业务 operation 会隐式自动解析',
481
+ capability: 'recruit',
482
+ risk: READ,
483
+ inputSchema: schemaOf({}),
484
+ handler: async (_args, env) => {
485
+ if (!env.recruitContext) {
486
+ throw ehrValidationError('recruit_context_unavailable', '招聘上下文加载器未初始化');
487
+ }
488
+ const cache = await env.recruitContext.load(env.host);
489
+ return ehrSuccess('ehr.recruit.context.resolve', {
490
+ appId: cache.appId,
491
+ tenantKey: cache.tenantKey || null,
492
+ forms: cache.forms,
493
+ lists: cache.lists,
494
+ ebdDetailPageId: cache.ebdDetailPageId || null,
495
+ selfUse: cache.selfUse,
496
+ });
497
+ },
498
+ };
499
+ const candidateSearch = {
500
+ name: 'ehr.recruit.candidate.search',
501
+ resource: 'recruit',
502
+ method: 'candidate.search',
503
+ action: 'ehr.recruit.candidate.search',
504
+ summary: '按姓名/手机号模糊搜索人才库人才;无筛选条件时列出全部人才用于浏览。返回白名单展示字段',
505
+ capability: 'recruit',
506
+ risk: READ,
507
+ inputSchema: schemaOf({
508
+ name: { type: 'string', description: '姓名模糊匹配' },
509
+ mobile: { type: 'string', description: '手机号模糊匹配' },
510
+ current: SCHEMA_ID,
511
+ pageSize: SCHEMA_ID,
512
+ }),
513
+ handler: async (args, env) => {
514
+ if (!env.recruitContext) {
515
+ throw ehrValidationError('recruit_context_unavailable', '招聘上下文加载器未初始化');
516
+ }
517
+ const cache = await env.recruitContext.load(env.host);
518
+ const talentList = cache.lists.talent;
519
+ const talentObjId = cache.forms.talent_pool?.objId;
520
+ if (!talentList?.listId || !talentObjId) {
521
+ throw new RecruitContextError('recruit_context_missing', '当前环境未解析到「人才库」菜单或人才库表单,无法搜索人才。请先运行 ehr.recruit.context.resolve 检查环境。');
522
+ }
523
+ const fields = cache.fields[talentObjId] || {};
524
+ const nameField = 'field_' + (fields.candidate_name || fields.name);
525
+ const mobileField = 'field_' + fields.telephone;
526
+ const conditions = {};
527
+ if (args.name)
528
+ conditions[nameField] = [{ [nameField]: args.name, [`${nameField}_condition_type`]: 'like' }];
529
+ if (args.mobile)
530
+ conditions[mobileField] = [{ [mobileField]: args.mobile, [`${mobileField}_condition_type`]: 'like' }];
531
+ const body = buildListBody({
532
+ listId: talentList.listId,
533
+ cusMenuId: talentList.cusMenuId,
534
+ menuName: talentList.menuName || '人才管理',
535
+ title: '人才库',
536
+ current: toPositiveInt(args.current, 'current') ?? 1,
537
+ pageSize: toNumber(args.pageSize, 'pageSize') ?? 10,
538
+ conditions,
539
+ });
540
+ const { rows, displayRows, total } = await fetchListRows(env.host, talentObjId, talentList.listId, body);
541
+ // 显示层优先:displayData 已内联人员/字典中文,零额外请求;
542
+ // 缺失时回退原始层:字典映射 + 纯 ID 经 hrm getEmployeeByIds 批量反查(兜底,行为不变)
543
+ let creatorNameMap = {};
544
+ if (!displayRows) {
545
+ const pureIds = [...new Set(rows
546
+ .map((row) => row?.creator)
547
+ .filter(isPlainId)
548
+ .map((value) => String(value).trim()))];
549
+ if (pureIds.length) {
550
+ creatorNameMap = {};
551
+ for (let index = 0; index < pureIds.length; index += 100) {
552
+ const batch = pureIds.slice(index, index + 100);
553
+ try {
554
+ const response = (await env.host.request({
555
+ path: '/api/hrm/common/getEmployeeByIds',
556
+ body: { userIdList: batch, externalIdList: [] },
557
+ headers: { devtype: '5' },
558
+ }));
559
+ for (const user of response?.data?.userList || []) {
560
+ if (user?.id != null)
561
+ creatorNameMap[String(user.id)] = user.name || null;
562
+ }
563
+ }
564
+ catch { /* 单批失败回退裸 ID */ }
565
+ }
566
+ }
567
+ }
568
+ const statusMap = cache.options?.recruit_status || {};
569
+ const dictNameMap = {};
570
+ for (const item of cache.dict?.raw || []) {
571
+ if (item.option_id && item.selection_name)
572
+ dictNameMap[item.option_id] = item.selection_name;
573
+ }
574
+ const dataRows = rows.map((row) => {
575
+ let creator = null;
576
+ if (displayRows) {
577
+ creator = namesOf(row?.creator);
578
+ }
579
+ else if (row?.creator != null) {
580
+ const raw = String(row.creator).trim();
581
+ creator = isPlainId(raw) ? (creatorNameMap[raw] || raw) : (namesOf(raw) || raw);
582
+ }
583
+ return {
584
+ talentId: row?.form_data_id || row?.id || null,
585
+ name: row?.candidate_name || row?.name || null,
586
+ mobile: row?.telephone || null,
587
+ channel: dictNameMap[row?.channel] || row?.channel || null,
588
+ status: statusMap[row?.recruit_status] || row?.recruit_status || null,
589
+ creator,
590
+ createTime: row?.create_time || null,
591
+ };
592
+ });
593
+ return ehrSuccess('ehr.recruit.candidate.search', { total, rows: dataRows });
594
+ },
595
+ };
596
+ const candidateList = {
597
+ name: 'ehr.recruit.candidate.list',
598
+ resource: 'recruit',
599
+ method: 'candidate.list',
600
+ action: 'ehr.recruit.candidate.list',
601
+ summary: '查询招聘业务列表(demand 招聘需求 / position 招聘职位 / entry 入职管理 / offer 录用管理),displayData 显示层零翻译输出',
602
+ capability: 'recruit',
603
+ risk: READ,
604
+ inputSchema: schemaOf({
605
+ type: { type: 'string', enum: ['demand', 'position', 'entry', 'offer'], description: '列表类型' },
606
+ current: SCHEMA_ID,
607
+ pageSize: SCHEMA_ID,
608
+ }, { required: ['type'] }),
609
+ handler: async (args, env) => {
610
+ const type = typeof args.type === 'string' ? args.type : '';
611
+ const listType = LIST_TYPES[type];
612
+ if (!listType) {
613
+ throw ehrValidationError('enum_invalid', `type 取值必须是 ${Object.keys(LIST_TYPES).join(' / ')} 之一`);
614
+ }
615
+ if (!env.recruitContext) {
616
+ throw ehrValidationError('recruit_context_unavailable', '招聘上下文加载器未初始化');
617
+ }
618
+ const cache = await env.recruitContext.load(env.host);
619
+ const listParam = cache.lists[listType.listKey];
620
+ if (!listParam?.listId) {
621
+ throw new RecruitContextError('recruit_list_unavailable', `当前环境未启用「${listType.title}」功能(未找到对应菜单/列表参数,按能力探测拦截)。`);
622
+ }
623
+ const formObjId = cache.forms[listType.formType]?.objId;
624
+ if (!formObjId) {
625
+ throw new RecruitContextError('recruit_context_missing', `未解析到「${listType.title}」对应表单,无法查询。`);
626
+ }
627
+ const body = buildListBody({
628
+ listId: listParam.listId,
629
+ cusMenuId: listParam.cusMenuId,
630
+ menuName: listParam.menuName || listType.title,
631
+ title: listType.title,
632
+ current: toPositiveInt(args.current, 'current') ?? 1,
633
+ pageSize: toNumber(args.pageSize, 'pageSize') ?? 10,
634
+ });
635
+ const { rows, displayRows, total } = await fetchListRows(env.host, formObjId, listParam.listId, body);
636
+ const outRows = rows.map((row) => {
637
+ const cleaned = { form_data_id: row?.form_data_id || row?.id };
638
+ for (const [key, value] of Object.entries(row || {})) {
639
+ if (displayRows) {
640
+ // 显示层:剔除 UI/内部键与动态后缀,门户数组/对象取 name 连接
641
+ if (DISPLAY_UI_KEYS.has(key) || key === 'form_data_id')
642
+ continue;
643
+ if (key.endsWith('Span') || key.endsWith('Action'))
644
+ continue;
645
+ const text = String(value ?? '');
646
+ if (!text)
647
+ continue;
648
+ if (typeof value === 'object' || (typeof value === 'string' && text.trimStart().startsWith('['))) {
649
+ const names = namesOf(value);
650
+ cleaned[key] = names != null ? names : text;
651
+ continue;
652
+ }
653
+ cleaned[key] = text;
654
+ continue;
655
+ }
656
+ // 原始层兜底:只输出可读值(非内部键、非 16+ 位裸大 ID)
657
+ if (INTERNAL_KEYS.has(key))
658
+ continue;
659
+ const text = String(value ?? '');
660
+ if (!text)
661
+ continue;
662
+ if (/^\d{16,}$/.test(text))
663
+ continue;
664
+ const names = typeof value === 'object' || (typeof value === 'string' && text.trimStart().startsWith('['))
665
+ ? namesOf(value)
666
+ : null;
667
+ cleaned[key] = names != null ? names : text;
668
+ }
669
+ return cleaned;
670
+ });
671
+ return ehrSuccess('ehr.recruit.candidate.list', {
672
+ type, total, current: body.current, pageSize: body.pageSize, rows: outRows,
673
+ });
674
+ },
675
+ };
676
+ const candidateCard = {
677
+ name: 'ehr.recruit.candidate.card',
678
+ resource: 'recruit',
679
+ method: 'candidate.card',
680
+ action: 'ehr.recruit.candidate.card',
681
+ summary: '查看人才详情卡片:权限校验 + 四张卡片(基本信息/应聘进展/面试安排/沟通备注)并行拉取,姓名与字典全部内联解析',
682
+ capability: 'recruit',
683
+ risk: READ,
684
+ inputSchema: schemaOf({ talentId: { oneOf: [{ type: 'integer' }, { type: 'string', pattern: '^\\d+$' }], description: '人才 ID,来自 candidate.search 的 talentId' } }, { required: ['talentId'] }),
685
+ handler: async (args, env) => {
686
+ const talentId = args.talentId;
687
+ if (talentId === undefined || talentId === null || talentId === '') {
688
+ throw ehrValidationError('talent_id_required', 'talentId 必填');
689
+ }
690
+ if (!/^\d+$/.test(String(talentId).trim())) {
691
+ throw ehrValidationError('talent_id_invalid', 'talentId 必须是数字 ID');
692
+ }
693
+ const id = String(talentId).trim();
694
+ if (!env.recruitContext) {
695
+ throw ehrValidationError('recruit_context_unavailable', '招聘上下文加载器未初始化');
696
+ }
697
+ const cache = await env.recruitContext.load(env.host);
698
+ const talentListId = cache.lists.talent?.listId || '';
699
+ const extra = talentListId ? { ebBusinessId: talentListId } : {};
700
+ // 权限校验与 batchId 并行(两请求无依赖);权限闸门仍严格前置在四张卡片之前
701
+ const rk1 = randHex6();
702
+ const [rightsResponse, prepareResponse] = await Promise.all([
703
+ env.host.request({
704
+ path: `/api/recruit/talent/hasRights?formDataId=${id}`,
705
+ method: 'POST',
706
+ headers: extra,
707
+ }),
708
+ env.host.request({
709
+ path: `/api/recruit/candidate/getCandidateCardPrepareQuery?talentId=${id}&randomkey_${rk1}=${rk1}`,
710
+ headers: extra,
711
+ }),
712
+ ]);
713
+ const rights = rightsResponse?.data || [];
714
+ if (!rights.includes('READ')) {
715
+ throw ehrValidationError('recruit_rights_denied', '当前账号无该人才详情的 READ 权限,无法查看。');
716
+ }
717
+ const batchId = prepareResponse?.data?.batchId;
718
+ if (!batchId) {
719
+ throw new RecruitContextError('recruit_batch_id_missing', '未取到 batchId(prepareQuery 返回异常),无法查看详情卡片。');
720
+ }
721
+ // 四张卡片并行;pageSize 100 防面试/沟通记录被默认 10 条静默截断
722
+ const rk2 = randHex6();
723
+ const v = randHex6();
724
+ const query = `talentId=${id}&batchId=${batchId}&v=${v}&randomkey_${rk2}=${rk2}`;
725
+ const cardBody = { talentId: id, batchId, current: 1, pageSize: 100 };
726
+ const [base, other, interview, remark] = await Promise.all([
727
+ env.host.request({ path: `/api/recruit/candidate/getCandidateCardBaseInfo?${query}`, headers: extra }),
728
+ env.host.request({ path: `/api/recruit/candidate/getCandidateCardOtherInfo?${query}`, headers: extra }),
729
+ env.host.request({ path: '/api/recruit/candidate/getCandidateCardInterviewInfo', body: cardBody, headers: extra }),
730
+ env.host.request({ path: '/api/recruit/candidate/getCandidateCardRemark', body: cardBody, headers: extra }),
731
+ ]);
732
+ const statusMap = cache.options?.recruit_status || {};
733
+ const talent = base?.data?.talent || {};
734
+ const currentBatch = other?.data?.currentCandidateBatch || {};
735
+ const interviewList = interview?.data?.list || [];
736
+ const remarkList = remark?.data?.list || [];
737
+ const baseUrl = (await env.host.getSession()).baseUrl.replace(/\/+$/, '');
738
+ return ehrSuccess('ehr.recruit.candidate.card', {
739
+ talentId: id,
740
+ cardLink: cache.ebdDetailPageId
741
+ // selfUse 缓存值为字符串 "0"/"1",必须 === '1'(字符串 "0" truthy 会误拼 recruitType)
742
+ ? `${baseUrl}/sp/ebdpage/view/${cache.ebdDetailPageId}?talentId=${id}${String(cache.selfUse ?? '') === '1' ? '&recruitType=useSelf' : ''}`
743
+ : null,
744
+ baseInfo: {
745
+ name: talent?.hrm?.name,
746
+ mobile: talent?.telephone,
747
+ channel: talent?.channel,
748
+ status: statusMap[base?.data?.recruitStatus] || base?.data?.recruitStatus || null,
749
+ createTime: talent?.createTime,
750
+ },
751
+ position: {
752
+ position: currentBatch?.position?.name,
753
+ stage: currentBatch?.currentStageName,
754
+ stages: (currentBatch?.allStage || []).map((stage) => stage?.stageName).filter(Boolean),
755
+ archiveStatus: currentBatch?.archiveStatus?.name,
756
+ employManager: namesOf(currentBatch?.employManager),
757
+ channel: currentBatch?.channel,
758
+ candidateManageId: currentBatch?.id || currentBatch?.candidateManageId || null,
759
+ batchId: currentBatch?.batchId || batchId,
760
+ positionId: currentBatch?.position?.id || null,
761
+ },
762
+ interviews: interviewList.map((item) => ({
763
+ subject: item?.subject,
764
+ startTime: item?.startTime || null,
765
+ endTime: item?.endTime || null,
766
+ status: namesOf(item?.unionStatus),
767
+ type: namesOf(item?.interviewType),
768
+ round: namesOf(item?.interviewSession),
769
+ interviewer: namesOf(item?.interviewer),
770
+ arranger: namesOf(item?.creator),
771
+ updater: namesOf(item?.updater),
772
+ position: namesOf(item?.positionManageId),
773
+ feedbacks: (item?.interviewFeedBack || []).map((feedback) => ({
774
+ result: feedback?.result?.[0]?.name || null,
775
+ comment: feedback?.judgement ? feedback.judgement.replace(/<[^>]+>/g, '').trim() : null,
776
+ feedbacker: namesOf(feedback?.updater),
777
+ createTime: feedback?.createTime,
778
+ })),
779
+ })),
780
+ remarks: remarkList.map((item) => ({
781
+ time: item?.contactTime || item?.createTime,
782
+ creator: item?.creator?.username || item?.creator?.name || null,
783
+ content: item?.remark,
784
+ })),
785
+ });
786
+ },
787
+ };
788
+ export const recruitOperations = [
789
+ contextResolve,
790
+ candidateSearch,
791
+ candidateList,
792
+ candidateCard,
793
+ ];
794
+ export const RECRUIT_SECOND_PHASE_WITHHELD = [
795
+ 'recruit.candidate.create',
796
+ 'recruit.interview.arrange',
797
+ 'recruit.offer.send',
798
+ 'recruit.entry.process',
799
+ 'recruit.interview.feedback.edit',
800
+ 'recruit.interview.feedback.urge',
801
+ 'recruit.entry.cancel.change',
802
+ ];
803
+ export { compact, toPageQuery };