weaver-work-cli 0.1.25 → 0.1.28

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 (173) hide show
  1. package/README.md +35 -30
  2. package/dist/cmd/root.js +1 -0
  3. package/dist/cmd/setup/index.js +1 -1
  4. package/dist/core/runtime-agent.js +19 -0
  5. package/dist/internal/e10/auth/commands.js +48 -33
  6. package/dist/internal/e10/auth/messages.js +3 -0
  7. package/dist/internal/e10/auth/session.js +8 -0
  8. package/dist/internal/e10/auth/xiaoe.js +62 -43
  9. package/dist/internal/e10/auth-recovery.js +148 -0
  10. package/dist/internal/e10/client.js +47 -15
  11. package/dist/internal/e10/context.js +9 -31
  12. package/dist/internal/e10/index.js +1 -0
  13. package/dist/internal/e10/request-runtime.js +51 -9
  14. package/dist/shortcuts/archive/host.js +3 -2
  15. package/dist/shortcuts/archive/manifest.js +1 -1
  16. package/dist/shortcuts/archive-oa/constants.js +66 -0
  17. package/dist/shortcuts/archive-oa/continuation.js +70 -0
  18. package/dist/shortcuts/archive-oa/errors.js +53 -0
  19. package/dist/shortcuts/archive-oa/host.js +158 -0
  20. package/dist/shortcuts/archive-oa/index.js +225 -0
  21. package/dist/shortcuts/archive-oa/manifest.js +62 -0
  22. package/dist/shortcuts/archive-oa/operations/borrow-car.js +159 -0
  23. package/dist/shortcuts/archive-oa/operations/borrow-url.js +108 -0
  24. package/dist/shortcuts/archive-oa/operations/confirm.js +48 -0
  25. package/dist/shortcuts/archive-oa/operations/contract.js +120 -0
  26. package/dist/shortcuts/archive-oa/operations/locate.js +50 -0
  27. package/dist/shortcuts/archive-oa/operations/registry.js +40 -0
  28. package/dist/shortcuts/archive-oa/operations/shared.js +181 -0
  29. package/dist/shortcuts/archive-oa/operations/types.js +45 -0
  30. package/dist/shortcuts/archive-oa/operations.js +13 -0
  31. package/dist/shortcuts/asset/host.js +7 -6
  32. package/dist/shortcuts/blog/host.js +4 -3
  33. package/dist/shortcuts/caizhilian/host.js +3 -2
  34. package/dist/shortcuts/caizhilian/manifest.js +1 -1
  35. package/dist/shortcuts/calendar/host.js +2 -1
  36. package/dist/shortcuts/contract/host.js +34 -59
  37. package/dist/shortcuts/ehr/host.js +2 -1
  38. package/dist/shortcuts/esb/host.js +2 -1
  39. package/dist/shortcuts/fna/host.js +6 -3
  40. package/dist/shortcuts/fna/manifest.js +10 -5
  41. package/dist/shortcuts/fna/operations/expense-chart.js +162 -0
  42. package/dist/shortcuts/fna/operations/registry.js +2 -0
  43. package/dist/shortcuts/hrm/host.js +2 -1
  44. package/dist/shortcuts/im/host.js +3 -2
  45. package/dist/shortcuts/index.js +2 -0
  46. package/dist/shortcuts/invoice/host.js +9 -7
  47. package/dist/shortcuts/invoice/manifest.js +38 -47
  48. package/dist/shortcuts/invoice/operations/issuing-qys.js +328 -0
  49. package/dist/shortcuts/invoice/operations/registry.js +2 -3
  50. package/dist/shortcuts/jiuchuanhui/host.js +2 -1
  51. package/dist/shortcuts/mail/host.js +2 -1
  52. package/dist/shortcuts/meeting/host.js +2 -1
  53. package/dist/shortcuts/meeting/operations/eb/conflict.js +78 -12
  54. package/dist/shortcuts/okr/host.js +2 -1
  55. package/dist/shortcuts/plan/host.js +2 -1
  56. package/dist/shortcuts/project/host.js +2 -1
  57. package/dist/shortcuts/workflow/endpoints.js +11 -0
  58. package/dist/shortcuts/workflow/host.js +5 -7
  59. package/dist/shortcuts/workflow/index.js +6 -36
  60. package/dist/shortcuts/workflow/operations/chatscene.js +252 -0
  61. package/dist/shortcuts/workflow/operations/form.js +1047 -191
  62. package/dist/shortcuts/workflow/operations/read.js +137 -8
  63. package/dist/shortcuts/workflow/operations/sign-input.js +106 -0
  64. package/dist/shortcuts/workflow/operations/write.js +9 -1
  65. package/dist/shortcuts/workflow/stdout-compact.js +16 -1
  66. package/docs/SKILL.md +1 -1
  67. package/docs/_catalog.md +1 -1
  68. package/docs/agent-invoice.md +1 -1
  69. package/docs/archive-oa.md +79 -0
  70. package/docs/caizhilian.md +1 -1
  71. package/docs/e10-auth.md +7 -6
  72. package/docs/fna.md +7 -3
  73. package/docs/invoice.md +4 -6
  74. package/package.json +1 -1
  75. package/skill-template/business-info.json +20 -1
  76. package/skill-template/domains/archive-oa.md +19 -0
  77. package/skill-template/domains/caizhilian.md +2 -1
  78. package/skill-template/domains/qiyecheng.md +1 -0
  79. package/skill-template/domains/yepiaotong.md +8 -4
  80. package/skill-template/skill-template.md +1 -0
  81. package/skills/weaver-e10-archive-oa/SKILL.md +159 -0
  82. package/skills/weaver-e10-archive-oa/references/archive-locate.md +49 -0
  83. package/skills/weaver-e10-archive-oa/references/borrow-car.md +76 -0
  84. package/skills/weaver-e10-archive-oa/references/borrow-flow.md +53 -0
  85. package/skills/weaver-e10-archive-oa/references/contract-search.md +63 -0
  86. package/skills/weaver-e10-archive-oa/references/disabled-capabilities.md +29 -0
  87. package/skills/weaver-e10-archive-oa/references/qys-contract-search.md +47 -0
  88. package/skills/weaver-e10-archive-oa/references/source-manifest.json +400 -0
  89. package/skills/weaver-e10-blog/SKILL.md +6 -1
  90. package/skills/weaver-e10-blog/references/blog-query.md +3 -1
  91. package/skills/weaver-e10-builder/SKILL.md +22 -0
  92. package/skills/weaver-e10-caizhilian/SKILL.md +47 -16
  93. package/skills/weaver-e10-caizhilian/references/action-flow.md +70 -0
  94. package/skills/weaver-e10-caizhilian/references/agent-entry.md +12 -4
  95. package/skills/weaver-e10-caizhilian/references/auth-and-install.md +207 -0
  96. package/skills/weaver-e10-caizhilian/references/collaboration.md +5 -3
  97. package/skills/weaver-e10-caizhilian/references/document.md +33 -11
  98. package/skills/weaver-e10-caizhilian/references/file-collection.md +57 -54
  99. package/skills/weaver-e10-caizhilian/references/file-upload.md +5 -6
  100. package/skills/weaver-e10-caizhilian/references/files.md +9 -3
  101. package/skills/weaver-e10-caizhilian/references/folder.md +48 -16
  102. package/skills/weaver-e10-caizhilian/references/host-executor-prompt.md +32 -0
  103. package/skills/weaver-e10-caizhilian/references/host-platform-integration.md +46 -0
  104. package/skills/weaver-e10-caizhilian/references/rule-index.md +56 -0
  105. package/skills/weaver-e10-caizhilian/references/setting-attach.md +17 -54
  106. package/skills/weaver-e10-caizhilian/references/setting-backup.md +16 -63
  107. package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +24 -64
  108. package/skills/weaver-e10-caizhilian/references/setting-storage-docs-summary.md +126 -0
  109. package/skills/weaver-e10-caizhilian/references/setting-storage-field-map.md +57 -0
  110. package/skills/weaver-e10-caizhilian/references/setting-storage.md +143 -548
  111. package/skills/weaver-e10-caizhilian/references/source-manifest.json +7 -7
  112. package/skills/weaver-e10-caizhilian/references/task-workflow.md +87 -0
  113. package/skills/weaver-e10-caizhilian/references/withheld.md +21 -45
  114. package/skills/weaver-e10-caizhilian/references/write-protocol.md +7 -0
  115. package/skills/weaver-e10-calendar/SKILL.md +6 -1
  116. package/skills/weaver-e10-esb/SKILL.md +8 -0
  117. package/skills/weaver-e10-esb/references/input-format.md +3 -1
  118. package/skills/weaver-e10-esb/references/source-manifest.json +5 -5
  119. package/skills/weaver-e10-hrm/SKILL.md +6 -1
  120. package/skills/weaver-e10-hrm/references/employee.md +1 -1
  121. package/skills/weaver-e10-hrm/references/org.md +1 -1
  122. package/skills/weaver-e10-hrm/references/position.md +1 -1
  123. package/skills/weaver-e10-jinchengda/SKILL.md +2 -1
  124. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +1 -1
  125. package/skills/weaver-e10-jiuchuanhui/SKILL.md +6 -1
  126. package/skills/weaver-e10-jucailin/SKILL.md +6 -1
  127. package/skills/weaver-e10-jucailin/references/hr-contact.md +1 -1
  128. package/skills/weaver-e10-jucailin/references/salary.md +1 -1
  129. package/skills/weaver-e10-mail/SKILL.md +6 -1
  130. package/skills/weaver-e10-meeting/SKILL.md +11 -6
  131. package/skills/weaver-e10-meeting/references/meeting-eb.md +7 -3
  132. package/skills/weaver-e10-meeting/references/meeting-queries.md +3 -1
  133. package/skills/weaver-e10-meeting/references/meeting-verification.md +4 -2
  134. package/skills/weaver-e10-okr/SKILL.md +6 -1
  135. package/skills/weaver-e10-okr/references/source-manifest.json +5 -5
  136. package/skills/weaver-e10-plan/SKILL.md +6 -1
  137. package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +3 -1
  138. package/skills/weaver-e10-plan/references/plan-report-query.md +3 -1
  139. package/skills/weaver-e10-plan/references/source-manifest.json +7 -7
  140. package/skills/weaver-e10-qiyecheng/SKILL.md +16 -6
  141. package/skills/weaver-e10-qiyecheng/references/catalog.md +6 -3
  142. package/skills/weaver-e10-qiyecheng/references/expense-center.md +2 -0
  143. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +78 -0
  144. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +87 -33
  145. package/skills/weaver-e10-shared/SKILL.md +53 -28
  146. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +22 -20
  147. package/skills/weaver-e10-shared/references/non-interactive-environment.md +13 -13
  148. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +3 -1
  149. package/skills/weaver-e10-wenshuding/SKILL.md +6 -1
  150. package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
  151. package/skills/weaver-e10-workflow/references/source-manifest.json +33 -24
  152. package/skills/weaver-e10-workflow/references/workflow-create.md +41 -26
  153. package/skills/weaver-e10-yepiaotong/SKILL.md +23 -18
  154. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +87 -45
  155. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +152 -0
  156. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +210 -0
  157. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +59 -36
  158. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +63 -512
  159. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +205 -346
  160. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +4 -5
  161. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +231 -344
  162. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +5 -5
  163. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +201 -162
  164. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +121 -145
  165. package/skills/weaver-e10-yimiaoban/SKILL.md +9 -2
  166. package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +1 -1
  167. package/skills/weaver-e10-yimiaoban/references/msg-read.md +1 -1
  168. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +9 -9
  169. package/skills/weaver-e10-ziguanjia/SKILL.md +6 -1
  170. package/dist/shortcuts/invoice/operations/issuing.js +0 -198
  171. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-field-rules.md +0 -161
  172. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +0 -107
  173. package/skills/weaver-e10-yepiaotong/references/reim-fast-path.md +0 -119
@@ -7,6 +7,7 @@
7
7
  // 顺序定位约定:查询类 operation 把"序号 → requestId"写入本地检索索引
8
8
  // (saveSearchIndex / findIndexedItem,由 CLI 托管,本文件不读写索引文件);
9
9
  // 查看/操作类 operation 允许用 requestId 或 group+index 定位(findIndexedItem)。
10
+ import { E10_REAUTH_GUIDANCE } from '../../../internal/e10/auth/messages.js';
10
11
  import { workflowSuccess, schemaOf, SCHEMA_REQUEST_ID, SCHEMA_CATEGORY, SCHEMA_INDEX, SCHEMA_PAGE_SIZE, } from './types.js';
11
12
  import { asString, asInt, asStringArray, asBool, compact, responseData, detailDataOf, toArray, resolveMemoryAppId, withLeadingMeta, STDOUT_SAFE_BYTES, stdoutBytesOf, parseNameWithId, } from './shared.js';
12
13
  import { workflowValidationError, WorkflowCliError, workflowClarificationError, CLARIFICATION_SUBTYPE, } from '../errors.js';
@@ -1478,6 +1479,25 @@ async function enforceSearchStdoutBudget(result, env, fileName) {
1478
1479
  };
1479
1480
  }
1480
1481
  // ---------------------------------------------------------------------------
1482
+ // 命令耗时(`durationMs`)
1483
+ // ---------------------------------------------------------------------------
1484
+ /**
1485
+ * 给 envelope 的 `data` 顶层补一个 `durationMs`(整数毫秒)。
1486
+ *
1487
+ * 口径与 `createForm` 的 `durationMs` **完全一致**(2026-10-19 用户裁定把这条命令也纳入):
1488
+ * 起点 = 命令 handler 入口(含会话解析、取数、落盘等全部动作),终点 = 返回之前;
1489
+ * 放在 `data` 顶层而不是信封 `meta`,这样「超线落盘」那一档 `data` 只剩一句提示时耗时依然在。
1490
+ *
1491
+ * 只在 `workflow.search` / `workflow.memoryPrompt` 两条命令上接线(用户明确「其他命令暂时不动」)。
1492
+ * `data` 不是普通对象(数组/字符串/空)时原样返回,绝不因为加耗时而改变返回形态。
1493
+ */
1494
+ function stampDurationMs(envelope, startedAt) {
1495
+ const data = envelope?.data;
1496
+ if (!data || typeof data !== 'object' || Array.isArray(data))
1497
+ return envelope;
1498
+ return { ...envelope, data: { ...data, durationMs: Date.now() - startedAt } };
1499
+ }
1500
+ // ---------------------------------------------------------------------------
1481
1501
  // 序号定位(查询类写索引;查看类读索引)
1482
1502
  // ---------------------------------------------------------------------------
1483
1503
  async function saveListIndex(env, normalized) {
@@ -1566,6 +1586,8 @@ const workflowSearch = {
1566
1586
  queryJson: { type: 'object', description: '已生成的完整查询 JSON(跳过 build-query)' },
1567
1587
  }),
1568
1588
  handler: async (args, env) => {
1589
+ // 耗时起点:整条命令的入口(含 plan 门禁的版本探测、取数、落盘)。
1590
+ const startedAt = Date.now();
1569
1591
  const plan = args.planJson;
1570
1592
  if (plan && typeof plan === 'object') {
1571
1593
  // plan 批量编排仅智能分组模式支持(来源:Python cmd_workflow_search_plan 首行的
@@ -1578,7 +1600,7 @@ const workflowSearch = {
1578
1600
  throw workflowValidationError('plan_requires_smart_mode', `plan 批量编排模式仅支持智能分组模式(OA ≥ ${formatOaVersion(SMART_GROUPING_MIN_OA_VERSION)});低版本请改用单条 workflow.search`, { retryAllowed: false });
1579
1601
  }
1580
1602
  // 顶层 pageSize 即 plan 的展示窗口 page_cap(来源:Python cmd_workflow_search_plan 的 page_cap)
1581
- return executePlanSearch(env, plan, asInt(args.pageSize) ?? 10);
1603
+ return stampDurationMs(await executePlanSearch(env, plan, asInt(args.pageSize) ?? 10), startedAt);
1582
1604
  }
1583
1605
  const category = (asString(args.category) || 'todo');
1584
1606
  const searchMode = await resolveSearchMode(env);
@@ -1588,7 +1610,7 @@ const workflowSearch = {
1588
1610
  // grouping_active 分支):未显式指定子分类、非 total-only、非批量取数时按「待处理/超时/紧急」
1589
1611
  // 分组取数并输出分组统计。smart 模式不做 CLI 侧分组(分组由模型按 countDetails 规划)。
1590
1612
  if (searchMode === 'legacy' && category === 'todo' && !batchType && !totalOnly && !hasExplicitTab(args)) {
1591
- return executeLegacyGroupedTodoSearch(env, args);
1613
+ return stampDurationMs(await executeLegacyGroupedTodoSearch(env, args), startedAt);
1592
1614
  }
1593
1615
  const { query, tabid } = await buildSearchQuery(env, { ...args, searchMode }, 'list');
1594
1616
  const prefix = ENDPOINT_PREFIX[category];
@@ -1652,13 +1674,13 @@ const workflowSearch = {
1652
1674
  }
1653
1675
  }
1654
1676
  if (totalOnly) {
1655
- return workflowSuccess('workflow.search', {
1677
+ return stampDurationMs(workflowSuccess('workflow.search', {
1656
1678
  type: 'workflowSearch',
1657
1679
  category,
1658
1680
  categoryName: CATEGORY_NAMES[category],
1659
1681
  total,
1660
1682
  finalMarkdown: buildSearchFinalMarkdown(null, probes, total, category, true, searchMode === 'smart', waitReadTotal),
1661
- });
1683
+ }), startedAt);
1662
1684
  }
1663
1685
  // 卡片摘要行只在 **legacy(低版本模式)** 生成——契约见 references/workflow-query.md
1664
1686
  // 「执行模式与返回形态」的「卡片摘要行」一行(低版本=标题/摘要/辅助三行;智能分组=标题/辅助
@@ -1674,7 +1696,7 @@ const workflowSearch = {
1674
1696
  await enrichWorkflowCardSummaries(env, normalized, asInt(args.pageSize) ?? normalized.pageSize);
1675
1697
  }
1676
1698
  const index = await saveListIndex(env, normalized);
1677
- return workflowSuccess('workflow.search', await enforceSearchStdoutBudget({
1699
+ return stampDurationMs(workflowSuccess('workflow.search', await enforceSearchStdoutBudget({
1678
1700
  type: 'workflowSearch',
1679
1701
  category,
1680
1702
  categoryName: CATEGORY_NAMES[category],
@@ -1688,7 +1710,7 @@ const workflowSearch = {
1688
1710
  finalMarkdown: buildSearchFinalMarkdown(normalized, probes, total, category, false, searchMode === 'smart', waitReadTotal, withCardSummaries),
1689
1711
  queryId: index.queryId,
1690
1712
  sessionMap: { queryId: index.queryId, itemCount: normalized.items.length },
1691
- }, env, { json: 'last_search.json', md: 'last_search.md' }));
1713
+ }, env, { json: 'last_search.json', md: 'last_search.md' })), startedAt);
1692
1714
  },
1693
1715
  };
1694
1716
  // ---------------------------------------------------------------------------
@@ -4815,6 +4837,8 @@ const workflowMemoryPrompt = {
4815
4837
  dynamicContext: { type: 'object', description: '动态上下文参数(可选,合并进 dynamicContextParams)' },
4816
4838
  }),
4817
4839
  handler: async (args, env) => {
4840
+ // 耗时起点:整条命令的入口(含记忆接口那一趟与会话解析)。
4841
+ const startedAt = Date.now();
4818
4842
  // 记忆接口契约(来源:Python memory_chat_params):
4819
4843
  // { appid: <记忆应用 ID>, dynamicContextParams: { workflowId?, ...额外上下文 } }
4820
4844
  // 缺 appid 时接口判为无效应用,直接返回空 promptText(available=false)——
@@ -4895,8 +4919,10 @@ const workflowMemoryPrompt = {
4895
4919
  result.oaContext = hasOaContext ? oaContext : null;
4896
4920
  result.oaContextMissing = !hasOaContext;
4897
4921
  if (!hasOaContext) {
4898
- result.oaContextMissingReason = '当前 E10 会话中未包含 OA 版本与用户身份信息。请先运行 weaver-work-cli auth status 确认登录态;若会话确已失效,请用 weaver-work-cli auth login --base-url <域名> --agent_type <当前智能体名称> 重新登录后重试。';
4922
+ result.oaContextMissingReason = `当前 E10 会话中未包含 OA 版本与用户身份信息。请先确认登录态;若会话确已失效,${E10_REAUTH_GUIDANCE}`;
4899
4923
  }
4924
+ // 命令耗时(毫秒):与 createForm / workflow.search 同口径,`data` 顶层。
4925
+ result.durationMs = Date.now() - startedAt;
4900
4926
  return workflowSuccess('workflow.memoryPrompt', result, {
4901
4927
  oaContextMissing: !hasOaContext,
4902
4928
  });
@@ -4939,6 +4965,18 @@ export const workflowReadOperations = [
4939
4965
  export const HISTORY_REQUEST_LIMIT = 5;
4940
4966
  /** 历史参考数据回溯窗口(天):近一年。 */
4941
4967
  const HISTORY_LOOKBACK_DAYS = 365;
4968
+ /**
4969
+ * 历史取数列表**只要这两列**(2026-10-26 用户口径)。
4970
+ *
4971
+ * 不带 `customDisplayColumns` 时服务端按"我发起的"默认列集全量解析、格式化、拼装
4972
+ * (响应里 `columns` / `data` / `displayData` 三份都要出一遍),而我们实际只读
4973
+ * `requestId` / `requestnameTitle` / `createdatetime` 三个字段 ⇒ 把列压到两列能直接砍掉
4974
+ * 这部分服务端开销,接口更快返回。
4975
+ */
4976
+ const HISTORY_LIST_COLUMNS = [
4977
+ { dataIndex: 'requestname', type: 'text', title: '标题', width: 200, orderKey: 'requestname' },
4978
+ { dataIndex: 'createdatetime', type: 'date', title: '创建时间', width: 150, orderKey: 'createdatetime' },
4979
+ ];
4942
4980
  /** 本地日期 → `YYYY-MM-DD`(不用 `toISOString`:那是 UTC,会跨日)。 */
4943
4981
  function formatLocalDate(date) {
4944
4982
  const pad = (value) => String(value).padStart(2, '0');
@@ -5129,7 +5167,17 @@ export async function fetchHistoryListSnapshot(env, options = {}) {
5129
5167
  path: WORKFLOW_ENDPOINTS.MINE_LIST,
5130
5168
  operation: 'workflow.createRequest.history',
5131
5169
  body: {
5132
- params: { tabid: DEFAULT_TABID.mine, dimension: 'mine', flowSpareType: 1, outType: 0 },
5170
+ // `needIutData: false`:关掉本次取数用不到的 IUT 附加数据(我们只看标题/创建时间)。
5171
+ params: {
5172
+ tabid: DEFAULT_TABID.mine,
5173
+ dimension: 'mine',
5174
+ flowSpareType: 1,
5175
+ outType: 0,
5176
+ needIutData: false,
5177
+ },
5178
+ // `needParseData: true`:让服务端把日期等字段直接解析成可读文本(`displayData`),
5179
+ // 客户端不再自己转。
5180
+ needParseData: true,
5133
5181
  searchParams: {
5134
5182
  formDatas: {
5135
5183
  // 非草稿 = 「未结束」+「已结束」(选项类系统条件必须是 multiContent,见 flow-status.ts;
@@ -5151,6 +5199,7 @@ export async function fetchHistoryListSnapshot(env, options = {}) {
5151
5199
  },
5152
5200
  customDisplayPage: { current: 1, size: HISTORY_REQUEST_LIMIT },
5153
5201
  sortParams: [{ orderkey: SORT_OPTIONS['发起时间'], sortType: 'desc' }],
5202
+ customDisplayColumns: HISTORY_LIST_COLUMNS,
5154
5203
  },
5155
5204
  });
5156
5205
  const listed = normalizeListResponse(listResponse, 'mine', CATEGORY_NAMES.mine);
@@ -5165,6 +5214,86 @@ export async function fetchHistoryListSnapshot(env, options = {}) {
5165
5214
  return null;
5166
5215
  }
5167
5216
  }
5217
+ /**
5218
+ * 「多候选里按用户近一年的发起记录消歧」——`createForm` 澄清前的最后一次尝试。
5219
+ *
5220
+ * 场景(2026-10-20 用户裁定):`workflow` 只给了名称、**多命中又没有全名精确匹配**,本来要返回
5221
+ * 多候选澄清。但用户往往只发起过其中之一 ⇒ 用「我发起的」**工作流树**把候选里他真发起过的捞出来:
5222
+ * 只剩一个就直接用它,不必再问一遍;否则照旧澄清。
5223
+ *
5224
+ * 请求 = `getMineListData` 的 body **去掉分页**(`customDisplayPage`),外加一个 `workflowid`
5225
+ * 条件把范围**限定在待澄清候选上**("涉及这次要澄清的那些工作流的流程")。`workflowid` 属
5226
+ * 浏览按钮类条件,**只认 `browserDatas`**——`multiContent` 会被服务端静默忽略(2026-09-29 实测)。
5227
+ *
5228
+ * 判据(用户逐字给定):`data.data` 恰一个根、该根 `children` 恰一个子 ⇒ 唯一。子节点 id 形如
5229
+ * `wf_<workflowId>`,去掉 `wf_` 即工作流 ID。
5230
+ *
5231
+ * 返回 `null` 的**所有**情形(候选不足 2 个 / 无数据 / 多个根 / 单个根多个子 / 命中项不在候选内 /
5232
+ * 接口失败或返回异常)都由调用方**回落原澄清**:本函数只回答"能不能确定",绝不上抛错误
5233
+ * ——兜底查询的失败不能顶掉用户本来要看到的那条澄清文案。
5234
+ */
5235
+ export async function pickUniqueMineWorkflow(candidates, env) {
5236
+ const candidateIds = [];
5237
+ const nameById = new Map();
5238
+ for (const item of toArray(candidates)) {
5239
+ const id = String(item?.id ?? '').trim();
5240
+ if (!id || nameById.has(id))
5241
+ continue;
5242
+ candidateIds.push(id);
5243
+ nameById.set(id, String(item?.name ?? ''));
5244
+ }
5245
+ // 只有一个候选时上游已经直接采用了,不会走到这里;0 个也没得消歧。
5246
+ if (candidateIds.length < 2)
5247
+ return null;
5248
+ try {
5249
+ const now = new Date();
5250
+ const start = new Date(now.getTime() - HISTORY_LOOKBACK_DAYS * 24 * 60 * 60 * 1000);
5251
+ const response = await env.host.workflowRequest({
5252
+ method: 'POST',
5253
+ path: WORKFLOW_ENDPOINTS.MINE_TREE,
5254
+ operation: 'workflow.createForm.mineTree',
5255
+ body: {
5256
+ params: { tabid: DEFAULT_TABID.mine, dimension: 'mine', flowSpareType: 1, outType: 0 },
5257
+ searchParams: {
5258
+ formDatas: {
5259
+ // 与历史取数同一口径:非草稿(未结束 + 已结束)。选项类条件必须是 `multiContent`。
5260
+ flowstatus: flowStatusCondition('notFinish,finish')?.condition ?? [],
5261
+ createdatetime: [{
5262
+ dateContent: [formatLocalDate(start), formatLocalDate(now)],
5263
+ term: 'like',
5264
+ }],
5265
+ workflowid: [{
5266
+ term: 'in',
5267
+ browserDatas: candidateIds.map((id) => ({ id, name: nameById.get(id) ?? '' })),
5268
+ }],
5269
+ },
5270
+ type: 'and',
5271
+ initSearch: false,
5272
+ },
5273
+ },
5274
+ });
5275
+ const body = (response && typeof response === 'object' ? response : {});
5276
+ if (body.fail === true || body.status === false)
5277
+ return null;
5278
+ const roots = toArray(body.data?.data);
5279
+ if (roots.length !== 1)
5280
+ return null;
5281
+ const children = toArray(roots[0]?.children);
5282
+ if (children.length !== 1)
5283
+ return null;
5284
+ const rawId = String(children[0]?.id ?? '').trim();
5285
+ const id = rawId.startsWith('wf_') ? rawId.slice(3) : rawId;
5286
+ // 双保险:服务端若没认 `workflowid` 条件、回了别的流程,这里必须挡掉(宁可澄清也不猜)。
5287
+ if (!id || !nameById.has(id))
5288
+ return null;
5289
+ const title = String(children[0]?.title ?? '').trim();
5290
+ return { id, name: title || (nameById.get(id) ?? '') };
5291
+ }
5292
+ catch {
5293
+ // 认证/网络/格式错误一律按"没能确定"处理 —— 澄清才是用户能继续操作的出口。
5294
+ return null;
5295
+ }
5296
+ }
5168
5297
  export async function buildHistoryRequestData(env, fields, targets, options = {},
5169
5298
  /**
5170
5299
  * 已提前发起的列表请求(见 `fetchHistoryListSnapshot`)。传入即直接复用,不再重复发请求;
@@ -0,0 +1,106 @@
1
+ import { AJAX_QUERY, FORM_ENDPOINTS } from '../endpoints.js';
2
+ /** 接口没给出可用值时的兜底 —— 与真机默认值一致(`微软雅黑/Microsoft YaHei`、`18/18px`)。 */
3
+ const DEFAULT_FONT_FAMILY = 'Microsoft YaHei';
4
+ const DEFAULT_FONT_SIZE = '18px';
5
+ const DEFAULT_FONT_ID = 'wea_rich_text_default_font';
6
+ /**
7
+ * `defaultFontFamily` / `defaultFontSize` 都是「中文名/实际值」的双段形态
8
+ * (`微软雅黑/Microsoft YaHei`、`18/18px`)。CSS 要的是斜杠**后面**那段;没有斜杠就整段用。
9
+ */
10
+ function cssValue(raw, fallback) {
11
+ const text = String(raw ?? '').trim();
12
+ if (!text)
13
+ return fallback;
14
+ const segments = text.split('/').map((item) => item.trim()).filter(Boolean);
15
+ const value = segments.length ? segments[segments.length - 1] : '';
16
+ if (!value)
17
+ return fallback;
18
+ return value;
19
+ }
20
+ /** 字号只给数字(`18`)时补单位 —— 否则拼出来的 `font-size:18` 是无效 CSS,浏览器会整条丢弃。 */
21
+ function cssFontSize(raw) {
22
+ const value = cssValue(raw, DEFAULT_FONT_SIZE);
23
+ return /^\d+(\.\d+)?$/u.test(value) ? `${value}px` : value;
24
+ }
25
+ /**
26
+ * 取签字意见的默认样式。**失败一律返回 `null`**(调用方据此退回原行为),绝不阻断提交 ——
27
+ * 这只是给意见加样式,不能因为样式接口挂了就让整条流程发不出去。
28
+ */
29
+ export async function loadSignInputCfg(env, target) {
30
+ const workflowId = String(target.workflowId ?? '').trim();
31
+ const requestId = String(target.requestId ?? '').trim();
32
+ // 发起流程用 `workflowId` + `isCreate:1`;提交已有流程用 `requestId` + `isCreate:0`。
33
+ const isCreate = workflowId && !requestId;
34
+ if (!isCreate && !requestId)
35
+ return null;
36
+ const body = isCreate
37
+ ? { isRemark: '', workflowId, isCreate: 1 }
38
+ : {
39
+ isRemark: 0,
40
+ operResultType: 'SUCCESS_RELOAD_CURRENT_PAGE',
41
+ userSpecifiedNodeId: '0',
42
+ autoMaxDisplay: '0',
43
+ isCreate: 0,
44
+ requestId,
45
+ };
46
+ try {
47
+ const response = await env.host.workflowRequest({
48
+ method: 'POST',
49
+ path: FORM_ENDPOINTS.signInputInfo,
50
+ // 与同族 `flowPage/*` 接口(loadBaseParam / loadFrameParam / loadMinorInfo)取同一份公共 query。
51
+ query: AJAX_QUERY,
52
+ body,
53
+ operation: isCreate ? 'workflow.createRequest' : 'workflow.operateApply',
54
+ });
55
+ const cfg = response?.data?.signInputCfg;
56
+ if (!cfg || typeof cfg !== 'object')
57
+ return null;
58
+ const raw = cfg.plainTextSignInput;
59
+ return {
60
+ plainText: raw === true || String(raw ?? '').toLowerCase() === 'true',
61
+ fontFamily: cssValue(cfg.defaultFontFamily, DEFAULT_FONT_FAMILY),
62
+ fontSize: cssFontSize(cfg.defaultFontSize),
63
+ };
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ function escapeText(text) {
70
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
71
+ }
72
+ /**
73
+ * 把签字意见包成服务端能正确渲染的形态。
74
+ *
75
+ * - 空内容 ⇒ `_weaverMte_`(与历史一致,表示"没有意见");
76
+ * - 已带 `_weaverMte_` 前缀(模型自己给了富文本)⇒ 原样,不重复嵌套;
77
+ * - `cfg` 取不到 ⇒ 退回历史行为 `_weaverMte_<p>内容</p>`(不知道协商格式就不猜);
78
+ * - `plainTextSignInput` 为真 ⇒ `<span id=... style=...>内容</span>`;
79
+ * - 否则 ⇒ `_weaverMte_<div id=... style=...><p>内容</p></div>`。
80
+ */
81
+ export function wrapSignRemark(raw, cfg) {
82
+ const text = String(raw ?? '').trim();
83
+ if (!text)
84
+ return '_weaverMte_';
85
+ if (text.startsWith('_weaverMte_'))
86
+ return text;
87
+ if (!cfg)
88
+ return `_weaverMte_<p>${escapeText(text)}</p>`;
89
+ const style = `font-family:${cfg.fontFamily};font-size:${cfg.fontSize};`;
90
+ const escaped = escapeText(text);
91
+ if (cfg.plainText) {
92
+ return `<span id="${DEFAULT_FONT_ID}" style="${style}">${escaped}</span>`;
93
+ }
94
+ return `_weaverMte_<div id="${DEFAULT_FONT_ID}" style="${style}"><p>${escaped}</p></div>`;
95
+ }
96
+ /**
97
+ * 提交侧的入口:**只在真有意见、且还没带富文本前缀时**才去问样式接口。
98
+ *
99
+ * 没有意见 / 已经是 `_weaverMte_` 富文本 ⇒ 一次请求都不发(这两档包与不包结果一样)。
100
+ */
101
+ export async function resolveSignRemark(env, raw, target) {
102
+ const text = String(raw ?? '').trim();
103
+ if (!text || text.startsWith('_weaverMte_'))
104
+ return wrapSignRemark(raw, null);
105
+ return wrapSignRemark(text, await loadSignInputCfg(env, target));
106
+ }
@@ -5,6 +5,7 @@ import { defaultTabIdOf, rethrowAuthOrNetworkError, runWorkflowSearch } from './
5
5
  import { CONTINUATION_INPUT, SCHEMA_CATEGORY, SCHEMA_CONFIRM, SCHEMA_INDEX, SCHEMA_REQUEST_ID, schemaOf, workflowSuccess, } from './types.js';
6
6
  import { asInt, asString, asStringArray, compact, responseData, detailDataOf, toArray, resolveMemoryAppId } from './shared.js';
7
7
  import { WORKFLOW_ENDPOINTS } from '../endpoints.js';
8
+ import { resolveSignRemark } from './sign-input.js';
8
9
  import { findIndexedItem, loadSearchIndex, } from '../state.js';
9
10
  // ===========================================================================
10
11
  // 工作流写操作(operate / share / batch / memory)
@@ -1013,7 +1014,14 @@ const workflowOperateApply = {
1013
1014
  verification,
1014
1015
  });
1015
1016
  }
1016
- const payload = await withUserId(env, { requestId, remark });
1017
+ // 提交前先按租户配置把签字意见包成带默认字体/字号的形态(已有流程 ⇒ `isCreate:0` + `requestId`)。
1018
+ // 取不到样式时 `resolveSignRemark` 内部已退回原形态,不会阻断提交。
1019
+ // **没意见就原样传空串**:这条命令历史上空意见就是 `''`(不像发起侧用 `_weaverMte_` 占位),
1020
+ // 改成占位符会改变提交请求体,没有必要。
1021
+ const signRemark = String(remark ?? '').trim()
1022
+ ? await resolveSignRemark(env, remark, { requestId })
1023
+ : remark;
1024
+ const payload = await withUserId(env, { requestId, remark: signRemark });
1017
1025
  if (nodeId)
1018
1026
  payload.userCurrentNodeId = nodeId;
1019
1027
  if (prepared.requestName)
@@ -25,7 +25,22 @@
25
25
  * 两边都正向引用,依赖图仍是单向的。
26
26
  */
27
27
  export const COMPACT_STDOUT_PATHS = {
28
- 'workflow.createForm': ['data.fields', 'data.historyRequestData', 'data.systemFields'],
28
+ // `data.data`(智能填参算出的字段值)与 `fields` 同构:键是字段 id、层级深,压掉缩进省得可观。
29
+ // 它与 `historyRequestData` / `systemFields` **互斥出现**(智能体成功时后两者已被删),
30
+ // 三个都登记在这里不会互相干扰。
31
+ 'workflow.createForm': [
32
+ 'data.fields',
33
+ 'data.historyRequestData',
34
+ 'data.systemFields',
35
+ 'data.data',
36
+ ],
37
+ // `createRequestDirect`(2026-10-22 起只取数、不发起):返回面就是「fields + historyRequestData +
38
+ // userMemory」,前两个同样是"逐条长、层级深"的数组 —— 压掉缩进省 24%~31%,直接把大量表单从
39
+ // 触线降到线下。`userMemory` 是单行 Markdown 字符串,本身没有缩进可压,不必登记。
40
+ 'workflow.createRequestDirect': [
41
+ 'data.fields',
42
+ 'data.historyRequestData',
43
+ ],
29
44
  };
30
45
  /** 该 operation 的紧凑路径(不声明 = 维持全量缩进)。导出让用例锁住接线。 */
31
46
  export function compactStdoutPaths(operation) {
package/docs/SKILL.md CHANGED
@@ -32,7 +32,7 @@ skills/weaver-e10-<name>/
32
32
  ## 已内置业务模块
33
33
 
34
34
  - `invoice`:E10 业票通发票管理。源码说明先读 `docs/invoice.md`;面向 Agent 时先读 `skills/weaver-e10-yepiaotong/SKILL.md`,再按入口路由读取对应 reference。
35
- - `fna`:E10 齐业成费控中心(预算查询/费用中心/借款管理/发票核销)。源码说明先读 `docs/fna.md`;面向 Agent 时先读 `skills/weaver-e10-qiyecheng/SKILL.md`,再按入口路由读取对应 reference。写操作(提醒还款/催票)走 prepare/apply 确认链。
35
+ - `fna`:E10 齐业成费控中心(预算查询/费用中心/报销报表 AI 问答/借款管理/发票核销)。源码说明先读 `docs/fna.md`;面向 Agent 时先读 `skills/weaver-e10-qiyecheng/SKILL.md`,再按入口路由读取对应 reference。写操作(提醒还款/催票)走 prepare/apply 确认链。
36
36
  - `plan`:E10 计划报告(报告查询/新建/修改/发布/撤回/提交提醒/评论),自动适配标准版与 e10-ebuilder 两套报告接口链路。源码说明先读 `docs/plan.md`;面向 Agent 时先读 `skills/weaver-e10-plan/SKILL.md`,再按入口路由读取对应 reference。写操作走 prepare/apply 确认链。
37
37
  - `esb`:E10 ESB 中心自定义触发动作流(入参模板查询 + 触发)。源码说明先读 `docs/esb.md`;面向 Agent 时先读 `skills/weaver-e10-esb/SKILL.md`,再按入口路由读取对应 reference。触发动作流是写操作,走 prepare/apply 确认链。
38
38
  - `okr`:E10 OKR 目标管理(目标分页查询/详情、关键成果查询与保存、目标对齐、目标评论、详情页链接),按 `ver_name` 自动适配 e10 标准版与 e10-ebuilder 两套接口链路。源码说明先读 `docs/okr.md`;面向 Agent 时先读 `skills/weaver-e10-okr/SKILL.md`,再按入口路由读取对应 reference。写操作(新建/编辑目标、保存关键成果、添加目标对齐)走 prepare/apply 确认链。
package/docs/_catalog.md CHANGED
@@ -10,7 +10,7 @@
10
10
  | 业票通发票管理、报销填单、智能开票、invoice operation、写操作 prepare/apply | `docs/invoice.md` |
11
11
  | E10 会议管理(标准版:查询/冲突/预约/回执/签到)、meeting operation、写操作 prepare/apply | `docs/meeting.md` |
12
12
  | 聚才林人事云(人事档案/出勤/薪酬)、ehr operation、写操作 prepare/apply | `docs/ehr.md` |
13
- | 齐业成费控中心(预算/费用中心/借款管理/发票核销)、fna operation、提醒还款与催票 prepare/apply | `docs/fna.md` |
13
+ | 齐业成费控中心(预算/费用中心/报销报表 AI 问答/借款管理/发票核销)、fna operation、提醒还款与催票 prepare/apply | `docs/fna.md` |
14
14
  | 文书定档案管理(全宗/检索/借阅车/借阅单/发起借阅/预归档上传)、wenshuding operation | `docs/wenshuding.md` |
15
15
  | 计划报告管理(报告查询/新建/修改/发布/撤回/提交提醒/评论)、plan operation、写操作 prepare/apply | `docs/plan.md` |
16
16
  | OKR 目标管理(目标查询/详情、关键成果、目标对齐、评论)、okr operation、标准版与 ebuilder 双链路、写操作 prepare/apply | `docs/okr.md` |
@@ -67,7 +67,7 @@ weaver-work-cli --json invoice run invoice.list --input-json '{"page_size":10,"s
67
67
 
68
68
  删除、编辑、新增同样必须使用 `prepare -> apply`。出现 `partial/write_uncertain` 时停止,不能自动重试写操作。
69
69
 
70
- 处理“把发票填进流程表单”的场景,使用 `invoice.browse-field.data` 生成浏览按钮控件所需 JSON。处理“报销发票/自动填单”时,先读取 `invoice-reim.md`,用报销相关只读 operation 获取事前申请、工作流、表单结构、预填信息和人员上级;Agent 组装报销单结构化 JSON 后,必须通过 `invoice.reim.flow.create.prepare/apply` 或 `invoice.reim.flow.update.prepare/apply` 写入,创建报销单的 `work_flow_id/mainFormId/request_name/main_fields/detail_rows` 等字段在 operation 顶层传入,不包通用 `payload`。处理“开票/存台账”时,先读取 `invoice-issuing.md` 和 `invoice-issuing-field-rules.md`,从用户输入或附件提取购方、税号、明细、税率和金额;资料不足时追问用户补齐,再走 `invoice.issuing.make.prepare/apply`。当前修正资料包没有客户档案查询或红字发票红冲接口,`invoice.customer.*` 和 `invoice.red.*` 不能调用或绕过。
70
+ 处理“把发票填进流程表单”的场景,使用 `invoice.browse-field.data` 生成浏览按钮控件所需 JSON。处理“报销发票/自动填单”时,先读取 `invoice-reim.md`,用报销相关只读 operation 获取事前申请、工作流、表单结构、预填信息和人员上级;Agent 组装报销单结构化 JSON 后,必须通过 `invoice.reim.flow.create.prepare/apply` 或 `invoice.reim.flow.update.prepare/apply` 写入,创建报销单的 `work_flow_id/mainFormId/request_name/main_fields/detail_rows` 等字段在 operation 顶层传入,不包通用 `payload`。处理“开票”时默认读取 `invoice-issuing-workflow.md`:用 `invoice.issuing.qys.list` 的 `groups` 按合同号选定一组,确认后调用 `weaver-e10-workflow` 的 `workflow.createForm` / `workflow.createRequest`(`action` 固定 `draft`)发起开票流程草稿。只有用户明确要求“直接开票/不走流程/存待开台账”时,才读取 `invoice-issuing-qys-ledger.md`(台账行)或 `invoice-issuing.md` + `invoice-issuing-field-rules.md`(口述字段),走 `invoice.issuing.make.prepare/apply`。当前修正资料包没有客户档案查询或红字发票红冲接口,`invoice.customer.*` 和 `invoice.red.*` 不能调用或绕过。
71
71
 
72
72
  ## 暂缓能力
73
73
 
@@ -0,0 +1,79 @@
1
+ # 泛微商务合同档案查询 CLI
2
+
3
+ 来源 Skill:`weaver-e10-archive-oa`。本模块把接口文档中可安全自动化的能力封装为 `weaver-work-cli archive-oa` 命令,供 AI Agent 通过结构化 JSON 调用。
4
+
5
+ 源码位于 `src/shortcuts/archive-oa`。命令注册、`operation manifest` 和业务执行逻辑分离:manifest 由 `operations/registry.ts` 汇总各 operation 定义生成,具体执行逻辑在 `src/shortcuts/archive-oa/operations` 中按业务分组维护(档案定位、合同查询、借阅车、发起借阅)。
6
+
7
+ 面向 Agent 的说明位于 `skills/weaver-e10-archive-oa`。入口 `SKILL.md` 只负责共享规则和 reference 路由;具体细节拆在 `skills/weaver-e10-archive-oa/references/`,与飞书 CLI 的业务 Skill 组织方式保持一致。
8
+
9
+ ## 公共前置
10
+
11
+ 先通过 E10 鉴权模块登录:
12
+
13
+ ```text
14
+ weaver-work-cli auth login --base-url "https://weapp.xxx.cn" --agent_type "<当前智能体名称>"
15
+ weaver-work-cli auth status --no-check
16
+ ```
17
+
18
+ 每个业务请求由 CLI 托管:
19
+
20
+ 1. 读取当前 `weaver-work-cli auth` Profile 的 E10 会话。
21
+ 2. 请求只允许 `/api/`(ebuilder 业务接口)与 `/openserver/`(E10 开放服务)路径,由 CLI 携带 E10 Cookie/ETEAMSID 与必要的业务头。
22
+ 3. 响应按以下规则判定业务成功:ebuilder 列表/ESB 看 `code=200` 与 `status=true`;ebuilder 自定义接口看 `datajson.status`。
23
+
24
+ Agent 不得在业务 JSON 中传 Cookie、ETEAMSID、Token 或内部控制字段。
25
+
26
+ ## Agent 入口
27
+
28
+ 优先使用 `archive-oa run <operation>`:
29
+
30
+ Windows PowerShell:
31
+
32
+ ```powershell
33
+ weaver-work-cli archive-oa schema
34
+ weaver-work-cli --json archive-oa run archive-oa.contract.list --input-json '{"pageNo":1}'
35
+ ```
36
+
37
+ macOS/Linux(bash/zsh):
38
+
39
+ ```bash
40
+ weaver-work-cli archive-oa schema
41
+ weaver-work-cli --json archive-oa run archive-oa.contract.list --input-json '{"pageNo":1}'
42
+ ```
43
+
44
+ 复杂或多行 JSON:先写成 UTF-8 文件,再用 `--input <path>`(`--input -` 读 stdin)。不要存在 `~/.tmp` 之类的路径假设;Windows 用 `$env:TEMP`,macOS/Linux 用临时目录。
45
+
46
+ ## operation 划分
47
+
48
+ | 分组 | operation |
49
+ | --- | --- |
50
+ | 档案定位 | `archive-oa.archive.locate` |
51
+ | 泛微合同 | `archive-oa.contract.list`、`archive-oa.contract.fields` |
52
+ | 泛微借阅车 | `archive-oa.borrow-car.list`、`archive-oa.borrow-car.add.prepare`、`archive-oa.borrow-car.add.apply` |
53
+ | 契约锁合同 | `archive-oa.qys.contract.list` |
54
+ | 契约锁借阅车 | `archive-oa.qys.borrow-car.list`、`archive-oa.qys.borrow-car.add.prepare`、`archive-oa.qys.borrow-car.add.apply` |
55
+
56
+ | 发起借阅(生成流程页 URL) | `archive-oa.borrow.start.url`、`archive-oa.qys.borrow.start.url` |
57
+
58
+ **发起借阅由 `archive-oa.borrow.start.url` 生成流程创建页 URL**:`<baseUrl>/sp/workflow/flowpage/fullCreate/100003460000002090?fb=<fb>&data=<JSON>`,`data` 为 `[{hth, htmc, yfhd, fph}]`。该 operation 只读:不写数据、不触发流程、不需要后台应用凭据;URL 可直接在浏览器打开,表单由用户填写并提交。已下线的 `archive-oa.borrow.start.prepare` / `.apply`(OpenESB webhook)不再提供。
59
+
60
+ ## 两套链路的参数差异
61
+
62
+ | 项 | 泛微商务合同 | 契约锁协作采纳 |
63
+ | --- | --- | --- |
64
+ | 合同查询 `passid` / `listId` | `850741972510941185` / `850741985437786120` | `850742853046345728` / `1190611964371984450` |
65
+ | 借阅车 `listId` | `882393480417296390` | `883819516961857839` |
66
+ | 加入借阅车 `esbActionIds` | `882395911377174530` | `892706856573648911` |
67
+
68
+ ## 写操作确认协议
69
+
70
+ - `*.prepare`:只读回查与参数校验(加入借阅车会查一次借阅车现状),返回 `preview` 与 `continuation`。
71
+ - `*.apply`:必须带 `continuation` 且 `confirm: true`(CLI `--yes`);票据含环境与登录账号指纹,10 分钟有效。
72
+ - 发起借阅用 `archive-oa.borrow.start.url` 生成流程页 URL(只读,`risk: read`):生成后优先用系统默认浏览器打开,无法打开时原样输出完整 URL;流程表单由用户在浏览器确认并提交。OpenESB 版 `borrow.start.prepare` / `.apply` 已下线。
73
+ - `failNum > 0` 时返回 `partial / write_uncertain`,不自动重放。
74
+
75
+ ## 参考
76
+
77
+ - `skills/weaver-e10-archive-oa/SKILL.md`:Agent 路由与执行原则。
78
+ - `skills/weaver-e10-archive-oa/references/`:按意图拆分的用法说明。
79
+ - `skill-template/domains/archive-oa.md`:业务域 Agent 调优要点。
@@ -4,7 +4,7 @@
4
4
 
5
5
  源码位于 `src/shortcuts/caizhilian`。命令注册、`operation manifest` 和业务执行逻辑分离:`manifest.ts` 汇总对外契约(含 `withheldOperations`),`operations/registry.ts` 由 `operations/specs.ts` 的 60 条操作规格展开成 87 条对外 operation(写操作展开为 `.prepare` / `.apply`),具体执行逻辑在 `src/shortcuts/caizhilian/operations/handlers` 中按业务分组维护(document、folder、collab、search、fileops、system),公共能力在 `operations/api.ts`、`operations/files.ts`、`operations/form.ts`、`operations/shared.ts`。
6
6
 
7
- 面向 Agent 的说明位于 `skills/weaver-e10-caizhilian`。入口 `SKILL.md` 只负责共享规则和 reference 路由;具体细节拆在 `skills/weaver-e10-caizhilian/references/`。
7
+ 面向 Agent 的说明位于 `skills/weaver-e10-caizhilian`。入口 `SKILL.md` 只负责接入前置和 reference 路由;具体细节拆在 `skills/weaver-e10-caizhilian/references/`。
8
8
 
9
9
  ## 公共前置
10
10
 
package/docs/e10-auth.md CHANGED
@@ -57,18 +57,19 @@ Chrome/Edge 原生确认框。宿主需要返回特定会话时,可以传
57
57
  返回地址只接受桌面应用自定义协议,不接受 `http(s)`、脚本或本地文件 URL。“始终打开”
58
58
  偏好保存在当前本地回调地址的浏览器存储中。本地 CLI 打开通道默认保留 15 分钟;通道
59
59
  结束后页面会自动退回浏览器自定义协议打开方式,不直接显示网络请求错误。
60
- 智能小 E 统一登录成功时不会经过浏览器;只有统一登录不可用并降级为桌面浏览器 OAuth 时,
61
- 才显示“返回智能小 E”弹层。
60
+ 智能小 E 统一登录不会经过浏览器,也不会显示“返回智能小 E”弹层;该弹层只属于用户另行显式发起的 `auth login` 浏览器 OAuth。
62
61
 
63
- 只有当前智能体身份明确为 XiaoE 时,`auth xiaoe` 和未显式指定认证来源的业务命令才先使用统一登录。Web/沙箱宿主可由成对的 `XIAOE_USER_TOKEN` + `XIAOE_DOMAIN` 识别;桌面客户端则可由其精确注入的 `XIAOE_DATA_ROOT`、`XIAOE_ROBOT_DATA_ROOT`、`XIAOE_USER_SETTINGS_PATH`、`XIAOE_ROBOT_ROOT` 运行时路径标记识别。通用 `WORKBUDDY_*` / `CODEX_*` 变量可能来自 XiaoE 复用的智能体运行时,不能覆盖这些 XiaoE 信号;明确的 `WORKBUDDY_AGENT_TYPE` / `CODEX_AGENT_TYPE` 非 XiaoE 身份除外。普通 `XIAOE_SKILL_*`、`WEAVER_XIAOE_*` 配置或仅在磁盘上发现客户端文件仍不足以触发。这里的 `XIAOE_DOMAIN` 是 XiaoE/erpa 换票服务地址,不是 E10 登录地址。Node 主路径调用与 `xiaoe_env.py` / `tokens.py` 相同的接口,校验业务 `code`(`"0000"` 或 `200`)及 `data.eteamId`,保留系统 CA 校验,并只跟随同源重定向或同主机 HTTP→HTTPS 升级。Node 路径失败时,CLI 会在内部执行 npm 包自带的 `scripts/xiaoe_env.py` 兼容路径;它只依赖 Python 标准库,凭证 stdout 由 CLI 内部消费,不进入 Agent 上下文,也不会关闭 TLS 证书校验。之后才依次读取宿主 `xiaoeUserData/tokens.py`、桌面 XiaoE 客户端本地会话和 `WEAVER_XIAOE_*` ETEAMSID 映射。客户端会话优先读取 `XIAOE_USER_SETTINGS_PATH`,再从 `XIAOE_ROBOT_DATA_ROOT` / `XIAOE_ROBOT_ROOT` 查找,最后回退 macOS `~/Library/Application Support/XiaoE/Robots/<id>/user_settings.json` 或 Windows `%LOCALAPPDATA%/XiaoE/Robots/<id>/user_settings.json`;只要其中的 `session_id` 与 `erpa` 有效,Node 即可在没有 `tokens.py` 时直接换票。宿主不会注入 ETEAMSID 环境变量,CLI 也不读取 `XIAOE_ETEAMSID`。
62
+ XiaoE 宿主身份有两种判定入口:桌面客户端由 Agent 根据“智能小 e 客户端”“小 E”、`XiaoE`、`xiaoe-client` 等明确上下文判断,并传入 `--runtime-agent xiaoe`;网页端沿用原有环境变量规则,成对的 `XIAOE_USER_TOKEN` + `XIAOE_DOMAIN` 会被识别为 XiaoE。工作目录、客户端文件、内置 Node.js、历史登录、路径变量或单个凭据变量都不能单独用于判定。判定为 XiaoE 后,Agent 显式执行 `weaver-work-cli auth xiaoe`。
64
63
 
65
- E10 目标地址按“显式 `--base-url` → 专用 `WEAVER_XIAOE_*` E10 配置/映射 → 当前 profile → `https://www.e-cology.com.cn`”解析,绝不会把 `XIAOE_DOMAIN` 当作 E10 地址。凭证可用时,CLI 直接保存登录态,保存的 `agentType` 固定为 `XiaoE`;业务命令在未显式指定 `--auth` / `--profile` 时,也会自动优先尝试 XiaoE 统一登录。统一登录失败后,`auth xiaoe` 仅在 macOS/Windows 桌面宿主自动降级浏览器 OAuth;Web/Linux 环境直接返回 `authentication/xiaoe_web_credential_unavailable`,不再启动无法回调的 localhost 登录。用户明确希望浏览器授权且宿主能够接收本地回调时,可以显式运行 `auth login`。
64
+ CLI 依次尝试成对的平台凭据、npm 包自带的 `scripts/xiaoe_env.py` 兼容路径、宿主 `xiaoeUserData/tokens.py`、桌面 XiaoE 客户端本地会话和 `WEAVER_XIAOE_*` ETEAMSID 映射。客户端会话优先读取 `XIAOE_USER_SETTINGS_PATH`,再从 `XIAOE_ROBOT_DATA_ROOT` / `XIAOE_ROBOT_ROOT` 查找,最后回退 macOS `~/Library/Application Support/XiaoE/Robots/<id>/user_settings.json` 或 Windows `%LOCALAPPDATA%/XiaoE/Robots/<id>/user_settings.json`。这些变量和文件只用于定位凭据,不能用于识别宿主。`XIAOE_DOMAIN` 是 XiaoE/erpa 换票服务地址,不是 E10 登录地址。
65
+
66
+ E10 目标地址按“显式 `--base-url` → 专用 `WEAVER_XIAOE_*` E10 配置/映射 → 当前 profile → `https://www.e-cology.com.cn`”解析。凭证可用时,CLI 直接保存登录态,保存的 `agentType` 固定为 `XiaoE`。统一登录失败时,所有操作系统都返回 `authentication/xiaoe_credential_unavailable`,不启动浏览器 OAuth。需要浏览器授权时必须另行显式执行 `auth login`。
66
67
 
67
68
  脚本兼容链路会先自动发现桌面 XiaoE 客户端内置 Python(macOS 应用包与 Windows 按用户/全局安装均支持),再回退到系统 `python3`、`/usr/bin/python3`、`python`;Windows 的系统回退顺序为 `python`、`python3`、`py`。可用 `WEAVER_XIAOE_TOKEN_SCRIPT_PYTHON` 精确指定解释器,用 `WEAVER_XIAOE_TOKEN_SCRIPT_PATH` 指定桌面宿主脚本路径(旧名 `XIAOE_TOKEN_SCRIPT_PYTHON` / `XIAOE_TOKEN_SCRIPT_PATH` 仍兼容)。CLI 自带的 `xiaoe_env.py` 位于 npm 包 `scripts/`,不会放入 `weaver-e10-shared` Skill;Skill 包禁止携带或直接执行 Token 脚本。`XIAOE_` 是平台保留前缀,本 CLI 的自定义变量统一使用 `WEAVER_XIAOE_*`。
68
69
 
69
- `auth xiaoe` 会先打印不含凭证的 preflight 摘要,明确给出 `hostDetected`、`attempted`、`tokenScriptDetected`、`clientSettingsDetected` 和目标 `baseUrl`。进入脚本分支时会打印 `Trying XiaoE token script credential...`;进入内置 Node 会话分支时会打印 `Trying built-in XiaoE client session credential...`。成功结果和后续 `auth status` 会显示 `credentialSourceStep`、`credentialSourceType`、`credentialSourceLabel`;`2 / token_script / xiaoeUserData/tokens.py` 表示宿主脚本换票,`3 / xiaoe_client / XiaoE client settings` 表示没有依赖 `tokens.py`、由 Node 直接换票。
70
+ `auth xiaoe` 会先打印不含凭证的 preflight 摘要,给出 `authMode=xiaoe`、`credentialSourceDetected`、`attempted`、各凭据源检测结果和目标 `baseUrl`。进入脚本分支时会打印 `Trying XiaoE token script credential...`;进入内置 Node 会话分支时会打印 `Trying built-in XiaoE client session credential...`。成功结果和后续 `auth status` 会显示 `credentialSourceStep`、`credentialSourceType`、`credentialSourceLabel`。
70
71
 
71
- 上述“业务命令自动优先尝试”仅适用于当前智能体身份明确为 XiaoE 的进程。WorkBuddy、Codex 及其他智能体不会因为本机存在 XiaoE 文件或配置而进入该分支,并必须使用 `auth login --base-url <url> --agent_type <agent_type>` 的浏览器 OAuth 流程。
72
+ 业务命令不会在缺少本地会话时主动建立 XiaoE 登录态,首次使用仍需显式执行 `auth xiaoe`。已有会话被 E10 接口明确拒绝为失效时,公共请求运行时会静默换票并重放原请求一次;不会打印中间登录步骤,不会自动打开浏览器,也不会对流式请求、网络错误、`partial` / `write_uncertain` 做重放。桌面客户端需要 XiaoE 专属业务行为时,Agent 必须显式传全局参数,例如 `weaver-work-cli --runtime-agent xiaoe workflow ...`;网页端由原有环境变量规则自动识别,不要求补这个参数。`--runtime-agent` 只控制运行时行为,不携带也不选择凭据。WorkBuddy、Codex 及其他智能体使用 `auth login --base-url <url> --agent_type <agent_type>` 的浏览器 OAuth 流程。
72
73
 
73
74
  无法使用浏览器回调时,可以用 `auth set` 直接写入浏览器中复制到的
74
75
  `ETEAMSID`。命令会调用 `teamsCheck` 解析当前用户、租户和组织信息,并写入
package/docs/fna.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # 齐业成费控中心(FNA)CLI
2
2
 
3
- 对应 `src/shortcuts/fna`,把泛微齐业成 FNA 费控中心 11 个源接口固化为 13 个 operation(预算 2 / 费用中心 3 / 借款管理 4 / 发票核销 4,其中提醒还款与催票为 prepare/apply 写链)。源资料:`/Users/zhufangyuan/Desktop/weaver-e10-qiyecheng`(指纹见 `skills/weaver-e10-qiyecheng/references/source-manifest.json`)。
3
+ 对应 `src/shortcuts/fna`,把泛微齐业成 FNA 费控中心 12 个源接口固化为 14 个 operation(预算 2 / 费用中心 3 + 报销报表 AI 问答 1 / 借款管理 4 / 发票核销 4,其中提醒还款与催票为 prepare/apply 写链)。源资料:`/Users/zhufangyuan/Desktop/weaver-e10-qiyecheng`(指纹见 `skills/weaver-e10-qiyecheng/references/source-manifest.json`)。
4
4
 
5
5
  ## 公共前置
6
6
 
7
- - 认证、profile、HTTP client 由 `src/internal/e10` 托管;业务 host 只适配 `/api/fna/` 与 `/api/app/fna/` 路径(`src/shortcuts/fna/host.ts` 的 `assertPath` 白名单)。
7
+ - 认证、profile、HTTP client 由 `src/internal/e10` 托管;业务 host 只适配 `/api/fna/`、`/api/app/fna/` 与 `/api/secondev/fna/` 路径(`src/shortcuts/fna/host.ts` 的 `assertPath` 白名单)。
8
8
  - 成功判定统一走 WeaResult(`success` 或 `status` 布尔 / `code==200`);费用中心 AI 查询用 `success`,预算/借款/核销用 `status`。
9
9
  - JSON 输出与错误 envelope、退出码遵循共享规则;写操作不满足确认条件返回 `confirmation.required`(exit 10),请求发出后结果不确定返回 `partial/write_uncertain`(exit 11)。
10
10
 
11
11
  ## Agent 入口
12
12
 
13
- 面向 Agent 时先读 `skills/weaver-e10-qiyecheng/SKILL.md`,再按入口路由读取 `references/`(catalog/budget/expense-center/loan-management/invoice-writeoff)。
13
+ 面向 Agent 时先读 `skills/weaver-e10-qiyecheng/SKILL.md`,再按入口路由读取 `references/`(catalog/budget/expense-center/expense-chart/loan-management/invoice-writeoff)。
14
14
 
15
15
  ## Operation 目录
16
16
 
@@ -21,6 +21,7 @@
21
21
  | `fna.expense.reimbursed.sum` | read | POST `expense/center/getSumReimbursedAmountByAi`;body 可空 |
22
22
  | `fna.expense.loan.sum` | read | POST `expense/center/getSumLoanAmountByAi`;只认数字 ID;空 data 自动重试 2 次;已知仅统计首条记录缺陷 |
23
23
  | `fna.expense.prepay.writeoff.sum` | read | POST `expense/center/selectPrepayWriteOffAmountBySkill`;body 可空 |
24
+ | `fna.expense.chart` | read | GET `getExpenseChart`(`/api/secondev/fna/`);`userInput` 必填 ≤500 字;`maxRows` 本地截断 1-5000,默认 200;超时 180s;返回 `kind=rows/empty/clarify/blocked/unexpected` |
24
25
  | `fna.loan.main.page` | read | POST `loanManagementMenu/mainPage` |
25
26
  | `fna.loan.main.list` | read | POST `loanManagementMenu/mainPageList`;`current`/`pageSize`/`menuCode`/`permissionSetCode` 必填 |
26
27
  | `fna.loan.remind.repay.prepare` | write | 校验 displayData 行并预览,不发送 |
@@ -39,6 +40,7 @@ Windows PowerShell:
39
40
  ```powershell
40
41
  weaver-work-cli --json fna run fna.budget.application.detail --input-json '{"requestId":"1001"}'
41
42
  weaver-work-cli --json fna run fna.expense.reimbursed.sum --input-json '{"startDate":"2026-01-01","endDate":"2026-08-31"}'
43
+ weaver-work-cli --json fna run fna.expense.chart --input-json '{"userInput":"2026-08 各部门报销金额排名前三"}'
42
44
  weaver-work-cli --json fna run fna.loan.main.list --input-json '{"current":1,"pageSize":20,"menuCode":"fesx_fna_borrowingManagement","permissionSetCode":"fesx_fna_borrowingManagement.default"}'
43
45
  weaver-work-cli --json fna run fna.invoice.writeoff.list --input-json '{"current":1,"pageSize":20,"invoiceStatus":"unarrivedTicket"}'
44
46
  ```
@@ -48,6 +50,7 @@ macOS/Linux(bash/zsh):
48
50
  ```bash
49
51
  weaver-work-cli --json fna run fna.budget.application.detail --input-json '{"requestId":"1001"}'
50
52
  weaver-work-cli --json fna run fna.expense.reimbursed.sum --input-json '{"startDate":"2026-01-01","endDate":"2026-08-31"}'
53
+ weaver-work-cli --json fna run fna.expense.chart --input-json '{"userInput":"2026-08 各部门报销金额排名前三"}'
51
54
  weaver-work-cli --json fna run fna.loan.main.list --input-json '{"current":1,"pageSize":20,"menuCode":"fesx_fna_borrowingManagement","permissionSetCode":"fesx_fna_borrowingManagement.default"}'
52
55
  weaver-work-cli --json fna run fna.invoice.writeoff.list --input-json '{"current":1,"pageSize":20,"invoiceStatus":"unarrivedTicket"}'
53
56
  ```
@@ -61,6 +64,7 @@ weaver-work-cli --json fna run fna.invoice.writeoff.list --input-json '{"current
61
64
  - 日期口径:报销按明细费用日期、借款按流程创建时间、预付核销按核销记录创建时间。
62
65
  - `menuCode`/`permissionSetCode` 环境相关,示例值需与环境核对。
63
66
  - 超 2^53 的 requestId 无法用 JS 数字精确表达,保留字符串并提示人工核验(真实环境 ID 一般在安全整数内,已按数字发送)。
67
+ - `fna.expense.chart`:`code` 恒为 200,必须按 `data` 类型/`kind` 判成败;追问与安全拦截都是字符串 `data`,`meta.messageKindInferred=true` 表示归类为 CLI 推断。实测真实查询 3.3~66.6s,CLI 超时设 180s,禁止自动重试(每次都会消耗模型额度)。不做当前人强制过滤,结果可能是全租户范围;`userInput` 为商品化输入,个人口径必须改用 `fna.expense.reimbursed.sum`。二开包未安装时该 operation 会 404/500,需与其它 `fna.*` 正常但本 operation 失败区分。
64
68
 
65
69
  ## 验证
66
70