weaver-work-cli 0.1.36 → 0.1.39

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 (169) hide show
  1. package/README.md +4 -2
  2. package/dist/chunks/{archive-XBVH7JU7.js → archive-ENZYBBME.js} +559 -68
  3. package/dist/chunks/{archive-oa-MZM3EKFQ.js → archive-oa-YWLEC5V4.js} +4 -3
  4. package/dist/chunks/{asset-4XO7UOUW.js → asset-OOV6DWPA.js} +8 -7
  5. package/dist/chunks/asset-idle-RE632MY5.js +670 -0
  6. package/dist/chunks/{attachment-content-VXSWANAC.js → attachment-content-RWN2FCLL.js} +3 -3
  7. package/dist/chunks/{blog-PGZKOPSC.js → blog-PEPOJAL7.js} +5 -4
  8. package/dist/chunks/{caizhilian-BH4ZVGUN.js → caizhilian-WYIQDVPJ.js} +5 -4
  9. package/dist/chunks/{calendar-MXEMTIO4.js → calendar-CIARBAOX.js} +4 -3
  10. package/dist/chunks/{chunk-NCOVUAZK.js → chunk-36DIFZAH.js} +4 -3
  11. package/dist/chunks/{chunk-I6QGIBDM.js → chunk-BJGXMFGD.js} +4 -3
  12. package/dist/chunks/{chunk-TC6MZAO3.js → chunk-CQHGNCK2.js} +52 -2
  13. package/dist/chunks/{chunk-WXFPWCXG.js → chunk-EINRJHQ3.js} +3 -3
  14. package/dist/chunks/{chunk-JUXVYKII.js → chunk-EZGFHJFW.js} +201 -19
  15. package/dist/chunks/{chunk-VPUTVEMC.js → chunk-F2EQXUEE.js} +436 -290
  16. package/dist/chunks/{chunk-JYKABYCV.js → chunk-GVPJZXJ2.js} +3 -3
  17. package/dist/chunks/{chunk-6LLJFKJE.js → chunk-HJYVHXUQ.js} +1 -1
  18. package/dist/chunks/{chunk-T72N74ZT.js → chunk-I2HB737U.js} +5 -4
  19. package/dist/chunks/{chunk-VPXOPQJI.js → chunk-K3RUEEOL.js} +4 -2
  20. package/dist/chunks/{chunk-HXJQI5NM.js → chunk-KTCB5R5H.js} +3 -2
  21. package/dist/chunks/{chunk-XMGSYD6S.js → chunk-L4N7B7ZD.js} +4 -4
  22. package/dist/chunks/{chunk-QYGO5EE2.js → chunk-MUQUHKPG.js} +4 -3
  23. package/dist/chunks/{chunk-QHFANTX7.js → chunk-NLK2RZKG.js} +1348 -90
  24. package/dist/chunks/{chunk-F746NKNF.js → chunk-P2DAISYW.js} +1 -1
  25. package/dist/chunks/{chunk-BPE37FPB.js → chunk-T7JDJJ7H.js} +3 -3
  26. package/dist/chunks/{chunk-JNG42JKG.js → chunk-XXJOSZTQ.js} +6 -6
  27. package/dist/chunks/{chunk-5DQEEGCC.js → chunk-YS5DPN4T.js} +1 -1
  28. package/dist/chunks/{chunk-EG6ZU444.js → chunk-ZUX3P6BQ.js} +10 -5
  29. package/dist/chunks/{chunk-JCSN3JGM.js → chunk-ZXRNHZTE.js} +7 -6
  30. package/dist/chunks/{conflict-JAB2LJEZ.js → conflict-DRMDOL56.js} +2 -2
  31. package/dist/chunks/{contract-XI2EEIZU.js → contract-73MERZWN.js} +4 -3
  32. package/dist/chunks/{cowork-SCPGLBA4.js → cowork-HNGBPD7A.js} +4 -3
  33. package/dist/chunks/{ebuilder-form-EYLHNOTA.js → ebuilder-form-OY6DVNRK.js} +3 -3
  34. package/dist/chunks/{ehr-EAP77IMT.js → ehr-RAQNEQO7.js} +4 -3
  35. package/dist/chunks/{esb-2TGGXEE7.js → esb-6XV7C7YV.js} +4 -4
  36. package/dist/chunks/{fna-2X7ZE7BU.js → fna-XTSRB7G7.js} +4 -3
  37. package/dist/chunks/{host-Q4LZGCRU.js → host-3F5UM5GN.js} +3 -3
  38. package/dist/chunks/{host-XCLDDXKQ.js → host-A7J6GDUP.js} +3 -3
  39. package/dist/chunks/{host-I4NRK4MX.js → host-VGPVP7YF.js} +3 -3
  40. package/dist/chunks/{host-C6EL2RKL.js → host-YAQAPYNP.js} +3 -3
  41. package/dist/chunks/{host-UEI5FGDM.js → host-YMBXWFWX.js} +3 -3
  42. package/dist/chunks/{hrm-YXERJM76.js → hrm-TLHKC545.js} +3 -3
  43. package/dist/chunks/{im-A4VZN2TQ.js → im-YOUCFMUK.js} +3 -3
  44. package/dist/chunks/{invoice-2Z6YPMIS.js → invoice-WNBS2B4C.js} +3 -3
  45. package/dist/chunks/{jiuchuanhui-AR5GMKZB.js → jiuchuanhui-XABWS5RN.js} +4 -3
  46. package/dist/chunks/{lazy-dispatch-QXW7P4X3.js → lazy-dispatch-NLZ5UQQI.js} +5 -5
  47. package/dist/chunks/{mail-7GZ6CPBJ.js → mail-LRYMBFNL.js} +4 -3
  48. package/dist/chunks/{meeting-3NMGA3MB.js → meeting-ESXL6MFI.js} +13 -12
  49. package/dist/chunks/{okr-BZ6XUOAG.js → okr-EOV65SSF.js} +4 -3
  50. package/dist/chunks/{plan-DR5CMUYP.js → plan-YFPVKW6Y.js} +4 -3
  51. package/dist/chunks/{project-6J63MK33.js → project-MDVZUYQW.js} +4 -3
  52. package/dist/chunks/{registry-VRTNC6UR.js → registry-QCLZEDAP.js} +8 -8
  53. package/dist/chunks/{registry-KDD7DHNK.js → registry-VT5Y2HLA.js} +4 -4
  54. package/dist/chunks/{registry-TKX2E7C7.js → registry-YX4CSEMD.js} +3 -3
  55. package/dist/chunks/{room-recommend-XCWRMB5P.js → room-recommend-L3MWH4JW.js} +4 -4
  56. package/dist/chunks/{schedule-IVBICP32.js → schedule-UASAVDVD.js} +4 -4
  57. package/dist/chunks/{workflow-D74NFK3C.js → workflow-KDGIUCNW.js} +9 -6
  58. package/dist/core/output.js +16 -6
  59. package/dist/index.js +33 -28
  60. package/dist/internal/e10/auth/messages.js +1 -0
  61. package/dist/internal/e10/auth-recovery.js +127 -7
  62. package/dist/internal/e10/client.js +16 -2
  63. package/dist/internal/e10/context.js +16 -3
  64. package/dist/internal/e10/request-runtime.js +106 -8
  65. package/dist/shortcuts/archive/host.js +5 -2
  66. package/dist/shortcuts/archive/manifest.js +1 -1
  67. package/dist/shortcuts/archive/operations/borrow-list.js +13 -1
  68. package/dist/shortcuts/archive/operations/flow-url.js +1 -1
  69. package/dist/shortcuts/archive/operations/prelib.js +472 -0
  70. package/dist/shortcuts/archive/operations/registry.js +2 -0
  71. package/dist/shortcuts/archive/operations/upload.js +1 -1
  72. package/dist/shortcuts/archive-oa/host.js +2 -1
  73. package/dist/shortcuts/asset/host.js +6 -5
  74. package/dist/shortcuts/asset-idle/errors.js +44 -0
  75. package/dist/shortcuts/asset-idle/host.js +161 -0
  76. package/dist/shortcuts/asset-idle/index.js +114 -0
  77. package/dist/shortcuts/asset-idle/manifest.js +159 -0
  78. package/dist/shortcuts/asset-idle/operations/idle.js +47 -0
  79. package/dist/shortcuts/asset-idle/operations/registry.js +33 -0
  80. package/dist/shortcuts/asset-idle/operations/shared.js +142 -0
  81. package/dist/shortcuts/asset-idle/operations/types.js +9 -0
  82. package/dist/shortcuts/asset-idle/operations.js +15 -0
  83. package/dist/shortcuts/blog/host.js +3 -2
  84. package/dist/shortcuts/caizhilian/host.js +3 -2
  85. package/dist/shortcuts/calendar/host.js +2 -1
  86. package/dist/shortcuts/contract/host.js +2 -1
  87. package/dist/shortcuts/cowork/host.js +2 -1
  88. package/dist/shortcuts/ebuilder-form/host.js +3 -1
  89. package/dist/shortcuts/ehr/host.js +2 -1
  90. package/dist/shortcuts/esb/host.js +2 -1
  91. package/dist/shortcuts/fna/host.js +2 -1
  92. package/dist/shortcuts/hrm/host.js +2 -1
  93. package/dist/shortcuts/im/host.js +3 -2
  94. package/dist/shortcuts/index.js +5 -0
  95. package/dist/shortcuts/invoice/host.js +5 -4
  96. package/dist/shortcuts/jiuchuanhui/host.js +2 -1
  97. package/dist/shortcuts/mail/host.js +2 -1
  98. package/dist/shortcuts/meeting/host.js +3 -2
  99. package/dist/shortcuts/meeting/invitation/text.js +71 -0
  100. package/dist/shortcuts/meeting/operations/eb/create-flow.js +1073 -50
  101. package/dist/shortcuts/meeting/operations/eb/crm-search.js +478 -0
  102. package/dist/shortcuts/meeting/operations/eb/factory.js +60 -1
  103. package/dist/shortcuts/meeting/operations/eb/index.js +2 -0
  104. package/dist/shortcuts/meeting/operations/invitation.js +122 -9
  105. package/dist/shortcuts/okr/host.js +2 -1
  106. package/dist/shortcuts/plan/host.js +2 -1
  107. package/dist/shortcuts/project/host.js +2 -1
  108. package/dist/shortcuts/workflow/host.js +3 -0
  109. package/dist/shortcuts/workflow/index.js +1 -1
  110. package/dist/shortcuts/workflow/operations/form.js +44 -11
  111. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +77 -26
  112. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.js +6 -0
  113. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +59 -117
  114. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +44 -7
  115. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +37 -29
  116. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +20 -6
  117. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +22 -18
  118. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +34 -10
  119. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +4 -2
  120. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +9 -2
  121. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +110 -20
  122. package/docs/_catalog.md +3 -0
  123. package/docs/asset-idle.md +45 -0
  124. package/docs/e10-auth.md +1 -1
  125. package/docs/todo-smart-convert/subgroup-rules.md +1 -1
  126. package/package.json +1 -1
  127. package/scripts/package-skill.mjs +2 -0
  128. package/skill-template/business-info.json +14 -1
  129. package/skill-template/domains/asset-idle.md +13 -0
  130. package/skill-template/domains/wenshuding.md +3 -0
  131. package/skills/weaver-e10-archive-oa/SKILL.md +1 -0
  132. package/skills/weaver-e10-archive-oa/references/my-borrow.md +49 -0
  133. package/skills/weaver-e10-asset-idle/SKILL.md +73 -0
  134. package/skills/weaver-e10-asset-idle/references/idle-list.md +62 -0
  135. package/skills/weaver-e10-asset-idle/references/idle-stats-and-charts.md +65 -0
  136. package/skills/weaver-e10-asset-idle/references/source-manifest.json +193 -0
  137. package/skills/weaver-e10-asset-idle/references/widget-style.md +205 -0
  138. package/skills/weaver-e10-caizhilian/SKILL.md +29 -11
  139. package/skills/weaver-e10-caizhilian/references/auth-and-install.md +12 -0
  140. package/skills/weaver-e10-caizhilian/references/files.md +1 -1
  141. package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +1 -1
  142. package/skills/weaver-e10-caizhilian/references/source-manifest.json +45 -45
  143. package/skills/weaver-e10-cowork/SKILL.md +2 -0
  144. package/skills/weaver-e10-jucailin/SKILL.md +2 -0
  145. package/skills/weaver-e10-jucailin/references/recruit-read.md +2 -0
  146. package/skills/weaver-e10-jucailin/references/recruit-write.md +1 -1
  147. package/skills/weaver-e10-mail/SKILL.md +3 -0
  148. package/skills/weaver-e10-meeting/SKILL.md +250 -301
  149. package/skills/weaver-e10-meeting/references/meeting-eb.md +203 -0
  150. package/skills/weaver-e10-meeting/references/meeting-invitation.md +37 -5
  151. package/skills/weaver-e10-meeting.zip +0 -0
  152. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  153. package/skills/weaver-e10-shared/SKILL.md +5 -5
  154. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +3 -3
  155. package/skills/weaver-e10-wenshuding/SKILL.md +29 -6
  156. package/skills/weaver-e10-wenshuding/references/archive-borrow-list.md +14 -0
  157. package/skills/weaver-e10-wenshuding/references/archive-download.md +2 -0
  158. package/skills/weaver-e10-wenshuding/references/archive-flow.md +1 -1
  159. package/skills/weaver-e10-wenshuding/references/archive-prelib-arrange.md +76 -0
  160. package/skills/weaver-e10-wenshuding/references/archive-prelib-list.md +107 -0
  161. package/skills/weaver-e10-wenshuding/references/archive-prelib-open.md +59 -0
  162. package/skills/weaver-e10-wenshuding/references/archive-upload.md +4 -1
  163. package/skills/weaver-e10-wenshuding/references/source-manifest.json +108 -65
  164. package/skills/weaver-e10-workflow/SKILL.md +5 -2
  165. package/skills/weaver-e10-workflow/aigroup/default.json +154 -19
  166. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +59 -27
  167. package/skills/weaver-e10-workflow/tools/todo-serve.cjs +113 -25
  168. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +292 -42
  169. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
@@ -0,0 +1,15 @@
1
+ import { assetIdleManifest } from './manifest.js';
2
+ import { getAssetIdleOperation } from './operations/registry.js';
3
+ import { assertKnownKeys, assertNoForbiddenKeys, asObject } from './operations/shared.js';
4
+ /** 顶层输入白名单直接取自 manifest:schema 即运行时约束,避免两处规则漂移。 */
5
+ const ALLOWED_KEYS = Object.fromEntries(assetIdleManifest.operations.map((operation) => [
6
+ operation.name,
7
+ Object.keys(operation.inputSchema.properties ?? {}),
8
+ ]));
9
+ export async function executeAssetIdleOperation(operation, rawInput, context) {
10
+ const definition = getAssetIdleOperation(operation);
11
+ const input = asObject(rawInput);
12
+ assertNoForbiddenKeys(input);
13
+ assertKnownKeys(input, ALLOWED_KEYS[operation] ?? [], operation);
14
+ return definition.handler(input, context);
15
+ }
@@ -3,6 +3,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
3
3
  import { requireE10Session } from '../../internal/e10/context.js';
4
4
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
5
5
  import { createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
6
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
6
7
  import { BlogCliError, blogAuthError, blogNetworkError, blogValidationError, } from './errors.js';
7
8
  const MAX_EXPORT_BYTES = 50 * 1024 * 1024;
8
9
  /** E10 登录失效在业务响应体里的 code(实测 -2 既可能是数字也可能是字符串) */
@@ -91,7 +92,7 @@ export function createBlogHost(ctx, dependencies = {}) {
91
92
  body,
92
93
  timeoutMs,
93
94
  });
94
- if (response.status === 401 || response.status === 302) {
95
+ if (isE10SessionExpiredResponse(response)) {
95
96
  throw blogAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
96
97
  }
97
98
  if (response.parseError) {
@@ -134,7 +135,7 @@ export function createBlogHost(ctx, dependencies = {}) {
134
135
  timeoutMs,
135
136
  headers: { Accept: 'application/octet-stream, */*' },
136
137
  });
137
- if (response.status === 401 || response.status === 302) {
138
+ if (isE10SessionExpiredResponse(response)) {
138
139
  throw blogAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
139
140
  }
140
141
  const contentType = response.contentType;
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { CaizhilianCliError, caizhilianAuthError, caizhilianNetworkError, caizhilianValidationError, } from './errors.js';
6
7
  /** 业务请求默认超时(源 assets/config.json:http.timeout = 12 秒)。 */
7
8
  export const CAIZHILAN_TIMEOUT_MS = 12_000;
@@ -152,7 +153,7 @@ export function createCaizhilianHost(ctx, dependencies = {}) {
152
153
  }
153
154
  async function request(request) {
154
155
  const response = await doRequest(request, false).catch((error) => mapRuntimeNetworkError(error));
155
- if (response.status === 401 || response.status === 302) {
156
+ if (isE10SessionExpiredResponse(response)) {
156
157
  throw caizhilianAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
157
158
  }
158
159
  if (response.parseError) {
@@ -183,7 +184,7 @@ export function createCaizhilianHost(ctx, dependencies = {}) {
183
184
  }
184
185
  async function requestBinary(request) {
185
186
  const response = await doRequest(request, true).catch((error) => mapRuntimeNetworkError(error));
186
- if (response.status === 401 || response.status === 302) {
187
+ if (isE10SessionExpiredResponse(response)) {
187
188
  throw caizhilianAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
188
189
  }
189
190
  if (response.status < 200 || response.status >= 300) {
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { calendarAuthError, calendarNetworkError, CalendarCliError, calendarValidationError } from './errors.js';
6
7
  function inferProfile(ctx) {
7
8
  const options = ctx.getGlobalOptions();
@@ -110,7 +111,7 @@ export function createCalendarHost(ctx, dependencies = {}) {
110
111
  catch (error) {
111
112
  mapRuntimeNetworkError(error);
112
113
  }
113
- if (response.status === 401 || response.status === 302) {
114
+ if (isE10SessionExpiredResponse(response)) {
114
115
  throw calendarAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
115
116
  }
116
117
  if (response.parseError) {
@@ -1,6 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { basename } from 'node:path';
3
3
  import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js';
4
+ import { isE10SessionExpiredResponse, } from '../../internal/e10/auth-recovery.js';
4
5
  import { requireE10Session } from '../../internal/e10/context.js';
5
6
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
6
7
  import { E10ApiError, createE10RequestRuntime, } from '../../internal/e10/request-runtime.js';
@@ -179,7 +180,7 @@ export function createContractHost(ctx, dependencies = {}) {
179
180
  }
180
181
  throw error;
181
182
  }
182
- if (response.status === 401 || response.status === 302) {
183
+ if (isE10SessionExpiredResponse(response)) {
183
184
  throw contractAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status, path });
184
185
  }
185
186
  const { text, value } = response;
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { CoworkCliError, coworkAuthError, coworkNetworkError, coworkValidationError } from './errors.js';
6
7
  import { coworkPerf } from './operations/types.js';
7
8
  function inferProfile(ctx) {
@@ -147,7 +148,7 @@ export function createCoworkHost(ctx, dependencies = {}) {
147
148
  coworkPerf.requestCount += 1;
148
149
  coworkPerf.requestMs += Date.now() - reqStart;
149
150
  }
150
- if (response.status === 401 || response.status === 302) {
151
+ if (isE10SessionExpiredResponse(response)) {
151
152
  throw coworkAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
152
153
  }
153
154
  if (response.parseError) {
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
3
4
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
5
  import { createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
6
  import { ebuilderAuthError, ebuilderBusinessError, ebuilderNetworkError, ebuilderValidationError, } from './errors.js';
@@ -231,7 +232,8 @@ export function createEbuilderFormHost(ctx) {
231
232
  headers: options.headers,
232
233
  bigIntStrings: options.bigIntStrings ?? true,
233
234
  });
234
- if ([302, 401, 403].includes(response.status)) {
235
+ // 403 在 eBuilder 这里偏「无权」,3xx 只有跳到登录页才算登录失效(文件服务交接不算)。
236
+ if (isE10SessionExpiredResponse(response) || response.status === 403) {
235
237
  throw ebuilderAuthError('session_expired', 'E10 登录态已失效或当前账号无权访问该 eBuilder 数据', { httpStatus: response.status });
236
238
  }
237
239
  if (response.parseError) {
@@ -3,6 +3,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
3
3
  import { requireE10Session } from '../../internal/e10/context.js';
4
4
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
5
5
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
6
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
6
7
  import { ehrAuthError, ehrNetworkError, EhrCliError, ehrValidationError } from './errors.js';
7
8
  function inferProfile(ctx) {
8
9
  const options = ctx.getGlobalOptions();
@@ -165,7 +166,7 @@ export function createEhrHost(ctx, dependencies = {}) {
165
166
  catch (error) {
166
167
  mapRuntimeNetworkError(error);
167
168
  }
168
- if (response.status === 401 || response.status === 302) {
169
+ if (isE10SessionExpiredResponse(response)) {
169
170
  throw ehrAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
170
171
  }
171
172
  if (response.parseError) {
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { EsbCliError, esbApiError, esbAuthError, esbNetworkError, esbPermissionError, esbValidationError, esbWriteUncertain, } from './errors.js';
6
7
  /** 源接口文档给出的去域名路径;域名与认证由 E10 会话层托管。 */
7
8
  export const ESB_PATHS = {
@@ -117,7 +118,7 @@ export function createEsbHost(ctx, dependencies = {}) {
117
118
  catch (error) {
118
119
  mapRuntimeNetworkError(error);
119
120
  }
120
- if (response.status === 401 || response.status === 302) {
121
+ if (isE10SessionExpiredResponse(response)) {
121
122
  throw esbAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
122
123
  }
123
124
  if (response.parseError) {
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { FnaCliError, fnaAuthError, fnaNetworkError, fnaValidationError } from './errors.js';
6
7
  function inferProfile(ctx) {
7
8
  const options = ctx.getGlobalOptions();
@@ -116,7 +117,7 @@ export function createFnaHost(ctx, dependencies = {}) {
116
117
  catch (error) {
117
118
  mapRuntimeNetworkError(error);
118
119
  }
119
- if (response.status === 401 || response.status === 302) {
120
+ if (isE10SessionExpiredResponse(response)) {
120
121
  throw fnaAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
121
122
  }
122
123
  if (response.parseError) {
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { HrmCliError, hrmAuthError, hrmNetworkError, hrmValidationError } from './errors.js';
6
7
  function inferProfile(ctx) {
7
8
  const options = ctx.getGlobalOptions();
@@ -114,7 +115,7 @@ export function createHrmHost(ctx, dependencies = {}) {
114
115
  catch (error) {
115
116
  mapRuntimeNetworkError(error);
116
117
  }
117
- if (response.status === 401 || response.status === 302) {
118
+ if (isE10SessionExpiredResponse(response)) {
118
119
  throw hrmAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
119
120
  }
120
121
  if (response.parseError) {
@@ -3,6 +3,7 @@ import { existsSync } from 'node:fs';
3
3
  import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';
4
4
  import { dirname, extname, resolve } from 'node:path';
5
5
  import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js';
6
+ import { isE10SessionExpiredResponse, } from '../../internal/e10/auth-recovery.js';
6
7
  import { requireE10Session } from '../../internal/e10/context.js';
7
8
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
8
9
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
@@ -121,7 +122,7 @@ export function createImHost(ctx, dependencies = {}) {
121
122
  catch (error) {
122
123
  mapRuntimeNetworkError(error);
123
124
  }
124
- if (response.status === 401 || response.status === 302) {
125
+ if (isE10SessionExpiredResponse(response)) {
125
126
  throw imAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
126
127
  }
127
128
  if (response.parseError) {
@@ -182,7 +183,7 @@ export function createImHost(ctx, dependencies = {}) {
182
183
  catch (error) {
183
184
  mapRuntimeNetworkError(error);
184
185
  }
185
- if (response.status === 401 || response.status === 302) {
186
+ if (isE10SessionExpiredResponse(response)) {
186
187
  throw imAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE);
187
188
  }
188
189
  if (response.status !== 200) {
@@ -105,6 +105,11 @@ export const builtinShortcuts = [
105
105
  description: 'E10 资产管理(资管家)CLI',
106
106
  load: async () => (await import('./asset/index.js')).assetShortcut,
107
107
  }),
108
+ lazyShortcut({
109
+ name: 'asset-idle',
110
+ description: 'E10 闲置资产判定结果查询 CLI(分页获取/聚合统计)',
111
+ load: async () => (await import('./asset-idle/index.js')).assetIdleShortcut,
112
+ }),
108
113
  lazyShortcut({
109
114
  name: 'im',
110
115
  description: '泛微E10易秒办(即时通讯)CLI',
@@ -4,6 +4,7 @@ import { E10_REAUTH_GUIDANCE, E10_SESSION_EXPIRED_MESSAGE } from '../../internal
4
4
  import { requireE10Session } from '../../internal/e10/context.js';
5
5
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
6
6
  import { createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
7
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
7
8
  import { InvoiceCliError, invoiceAuthError, invoiceNetworkError, invoiceValidationError, } from './errors.js';
8
9
  const MAX_DOWNLOAD_BYTES = 50 * 1024 * 1024;
9
10
  const TOKEN_SERVICE = 'cn.weaver.weaver-work-cli.invoice-token';
@@ -199,7 +200,7 @@ export function createInvoiceHost(ctx, dependencies = {}) {
199
200
  timeoutMs,
200
201
  trustedHeaders: trustedInvoiceHeaders(token),
201
202
  });
202
- if (response.status === 401 || response.status === 302) {
203
+ if (isE10SessionExpiredResponse(response)) {
203
204
  throw invoiceAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
204
205
  }
205
206
  if (response.parseError) {
@@ -258,7 +259,7 @@ export function createInvoiceHost(ctx, dependencies = {}) {
258
259
  timeoutMs,
259
260
  trustedHeaders: trustedInvoiceHeaders(token),
260
261
  });
261
- if (response.status === 401 || response.status === 302) {
262
+ if (isE10SessionExpiredResponse(response)) {
262
263
  throw invoiceAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
263
264
  }
264
265
  if (response.parseError) {
@@ -293,7 +294,7 @@ export function createInvoiceHost(ctx, dependencies = {}) {
293
294
  timeoutMs,
294
295
  trustedHeaders: trustedInvoiceHeaders(token),
295
296
  });
296
- if (response.status === 401 || response.status === 302) {
297
+ if (isE10SessionExpiredResponse(response)) {
297
298
  throw invoiceAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
298
299
  }
299
300
  if (response.parseError) {
@@ -320,7 +321,7 @@ export function createInvoiceHost(ctx, dependencies = {}) {
320
321
  timeoutMs,
321
322
  trustedHeaders: trustedInvoiceHeaders(token),
322
323
  });
323
- if (response.status === 401 || response.status === 302) {
324
+ if (isE10SessionExpiredResponse(response)) {
324
325
  throw invoiceAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
325
326
  }
326
327
  const contentType = response.contentType;
@@ -2,6 +2,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
2
2
  import { requireE10Session } from '../../internal/e10/context.js';
3
3
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
4
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
5
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
5
6
  import { JiuchuanhuiCliError, jiuchuanhuiAuthError, jiuchuanhuiNetworkError, jiuchuanhuiValidationError, } from './errors.js';
6
7
  function inferProfile(ctx) {
7
8
  const options = ctx.getGlobalOptions();
@@ -127,7 +128,7 @@ export function createJiuchuanhuiHost(ctx, dependencies = {}) {
127
128
  catch (error) {
128
129
  mapRuntimeNetworkError(error);
129
130
  }
130
- if (response.status === 401 || response.status === 302) {
131
+ if (isE10SessionExpiredResponse(response)) {
131
132
  throw jiuchuanhuiAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
132
133
  }
133
134
  if (response.parseError) {
@@ -3,6 +3,7 @@ import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js
3
3
  import { requireE10Session } from '../../internal/e10/context.js';
4
4
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
5
5
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
6
+ import { isE10SessionExpiredResponse } from '../../internal/e10/auth-recovery.js';
6
7
  import { mailAuthError, mailNetworkError, MailCliError, mailValidationError } from './errors.js';
7
8
  import { mailPerf } from './operations/types.js';
8
9
  function inferProfile(ctx) {
@@ -160,7 +161,7 @@ export function createMailHost(ctx, dependencies = {}) {
160
161
  mailPerf.requestCount += 1;
161
162
  mailPerf.requestMs += Date.now() - reqStart;
162
163
  }
163
- if (response.status === 401 || response.status === 302) {
164
+ if (isE10SessionExpiredResponse(response)) {
164
165
  throw mailAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
165
166
  }
166
167
  if (response.parseError) {
@@ -1,4 +1,5 @@
1
1
  import { E10_SESSION_EXPIRED_MESSAGE } from '../../internal/e10/auth/messages.js';
2
+ import { isE10SessionExpiredResponse, } from '../../internal/e10/auth-recovery.js';
2
3
  import { requireE10Session } from '../../internal/e10/context.js';
3
4
  import { getActiveProfile } from '../../internal/e10/auth/session.js';
4
5
  import { E10ApiError, createE10RequestRuntime } from '../../internal/e10/request-runtime.js';
@@ -127,7 +128,7 @@ export function createMeetingHost(ctx, dependencies = {}) {
127
128
  catch (error) {
128
129
  mapRuntimeNetworkError(error);
129
130
  }
130
- if (response.status === 401 || response.status === 302) {
131
+ if (isE10SessionExpiredResponse(response)) {
131
132
  throw meetingAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
132
133
  }
133
134
  if (response.status !== 200) {
@@ -177,7 +178,7 @@ export function createMeetingHost(ctx, dependencies = {}) {
177
178
  catch (error) {
178
179
  mapRuntimeNetworkError(error);
179
180
  }
180
- if (response.status === 401 || response.status === 302) {
181
+ if (isE10SessionExpiredResponse(response)) {
181
182
  throw meetingAuthError('session_expired', E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
182
183
  }
183
184
  if (response.parseError) {
@@ -0,0 +1,71 @@
1
+ /**
2
+ * 邀请函的**对话内文本版**(Markdown),与 docx 版同源同字段。
3
+ *
4
+ * 为什么要有这一份(2026-10-31 用户明确要求):
5
+ * 「邀请函不是在对话里给个文件让我自己下载,而是**直接展示在对话里**」。
6
+ * docx 是给人打印/发出去的成品,但小E 会话里用户看不到 docx 内容 ——
7
+ * 只回一个 filePath,用户还得去本地打开才知道写了什么。
8
+ * 所以渲染 docx 的同时产出一份纯文本,模型可以把正文直接贴进回复。
9
+ *
10
+ * 版式与 `templates/meeting/invitation.docx` 一致:标题 / 称呼 / 邀请语 /
11
+ * 会议要素 / 议程表 / 落款 / 备注。取不到的字段统一写【待补充】,与 docx 的黄色高亮同义。
12
+ */
13
+ import { PENDING_MARK } from './docx.js';
14
+ /** 单元格里的 `|` 会破坏 Markdown 表格,换行会破坏行结构 —— 统一折成空格。 */
15
+ function cell(value) {
16
+ return String(value ?? '').replace(/\|/g, '/').replace(/\s*\r?\n\s*/g, ' ').trim();
17
+ }
18
+ /**
19
+ * 生成邀请函的对话文本版。
20
+ *
21
+ * @param resolver 与 docx 共用的占位符解析器(保证两版内容一字不差)
22
+ * @param agendaRows 议程行(来自会议议题 / extra.agenda / 模板示例行)
23
+ * @param options.pendingHint 是否在末尾附「【待补充】需人工补」的提示(默认附)
24
+ */
25
+ export function renderInvitationMarkdown(resolver, agendaRows, options = {}) {
26
+ const pending = new Set();
27
+ const val = (key) => {
28
+ const rendered = resolver(key);
29
+ if (rendered.pending) {
30
+ pending.add(key);
31
+ return PENDING_MARK;
32
+ }
33
+ return String(rendered.text ?? '').trim();
34
+ };
35
+ const lines = [];
36
+ lines.push('# 邀请函');
37
+ lines.push('');
38
+ lines.push(`**尊敬的 ${val('guest_org')}:**`);
39
+ lines.push('');
40
+ lines.push(`${val('caller')} 诚邀您参加「${val('mt_name')}」,现将会议安排通知如下:`);
41
+ lines.push('');
42
+ lines.push(`- **会议名称**:${val('mt_name')}`);
43
+ lines.push(`- **会议时间**:${val('begin_datetime')}~${val('end_datetime')}`);
44
+ lines.push(`- **会议地点**:${val('address')}`);
45
+ lines.push(`- **参会人员**:${val('hrm_members')}`);
46
+ lines.push(`- **会议内容**:${val('mt_desc')}`);
47
+ lines.push('');
48
+ lines.push(`**${val('begin_date')}会议议程安排:**`);
49
+ lines.push('');
50
+ lines.push('| 议程安排 | 议程内容 | 议程时间 |');
51
+ lines.push('| --- | --- | --- |');
52
+ if (agendaRows.length === 0) {
53
+ lines.push('| — | 暂无议程 | — |');
54
+ }
55
+ else {
56
+ for (const [name, content, timeRange] of agendaRows) {
57
+ lines.push(`| ${cell(name) || '—'} | ${cell(content) || '—'} | ${cell(timeRange) || '—'} |`);
58
+ }
59
+ }
60
+ lines.push('');
61
+ lines.push(val('company_name'));
62
+ lines.push('');
63
+ lines.push(val('issue_date'));
64
+ lines.push('');
65
+ lines.push('> 注:以上为拟定会议安排,具体会议时间与议程需根据实际情况确认。');
66
+ if (options.pendingHint !== false && pending.size > 0) {
67
+ lines.push('');
68
+ lines.push(`> ⚠️ 标 ${PENDING_MARK} 的字段会议里没有值,需要人工补;补完可用 mtId 重新生成。`);
69
+ }
70
+ return { markdown: lines.join('\n'), pendingFields: [...pending] };
71
+ }