weaver-work-cli 0.1.29 → 0.1.32

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 (185) hide show
  1. package/dist/chunks/archive-UMGX72K6.js +2537 -0
  2. package/dist/chunks/archive-oa-N2IYBLF3.js +1317 -0
  3. package/dist/chunks/asset-GLEGKFG5.js +2109 -0
  4. package/dist/chunks/attachment-content-AQNX5N3S.js +23 -0
  5. package/dist/chunks/blog-E44OTVDA.js +2157 -0
  6. package/dist/chunks/caizhilian-DQUFZXZL.js +10087 -0
  7. package/dist/chunks/calendar-JKPIRKFD.js +1195 -0
  8. package/dist/chunks/chunk-2GA5ZIQL.js +1615 -0
  9. package/dist/chunks/chunk-4YC43QQ4.js +403 -0
  10. package/dist/chunks/chunk-6EFWDL7Y.js +161 -0
  11. package/dist/chunks/chunk-6RKD4DRZ.js +5556 -0
  12. package/dist/chunks/chunk-AJ62BGAW.js +29 -0
  13. package/dist/chunks/chunk-BUSC6UAE.js +43 -0
  14. package/dist/chunks/chunk-C6R3B2ML.js +358 -0
  15. package/dist/chunks/chunk-CVZ2JOSW.js +62 -0
  16. package/dist/chunks/chunk-DW6AUUKS.js +508 -0
  17. package/dist/chunks/chunk-E4Z23GHM.js +6962 -0
  18. package/dist/chunks/chunk-EG6ZU444.js +654 -0
  19. package/dist/chunks/chunk-EZALDOQH.js +383 -0
  20. package/dist/chunks/chunk-FMPJJYYI.js +106 -0
  21. package/dist/chunks/chunk-G2JSIUWF.js +769 -0
  22. package/dist/chunks/chunk-G3QJULO2.js +387 -0
  23. package/dist/chunks/chunk-GCG2NMWR.js +703 -0
  24. package/dist/chunks/chunk-GPMFD4RD.js +75 -0
  25. package/dist/chunks/chunk-H6XSTSLM.js +2357 -0
  26. package/dist/chunks/chunk-H7J4DC5R.js +464 -0
  27. package/dist/chunks/chunk-IURUFGZK.js +477 -0
  28. package/dist/chunks/chunk-LUSPKZKY.js +53 -0
  29. package/dist/chunks/chunk-NIAJ5ZCG.js +73 -0
  30. package/dist/chunks/chunk-NOODWMCL.js +584 -0
  31. package/dist/chunks/chunk-OOUTBLZ4.js +51 -0
  32. package/dist/chunks/chunk-P26ZWSKU.js +73 -0
  33. package/dist/chunks/chunk-QWY6PGL6.js +3472 -0
  34. package/dist/chunks/chunk-WKI2FBIQ.js +15606 -0
  35. package/dist/chunks/chunk-WSKBSQ2U.js +231 -0
  36. package/dist/chunks/chunk-YLCYX7LE.js +371 -0
  37. package/dist/chunks/chunk-YRVDW4WN.js +205 -0
  38. package/dist/chunks/chunk-ZEDWSH32.js +68 -0
  39. package/dist/chunks/continuation-2CKSBLA6.js +11 -0
  40. package/dist/chunks/continuation-HZIZRZBX.js +13 -0
  41. package/dist/chunks/continuation-NLECEJPX.js +11 -0
  42. package/dist/chunks/ebuilder-form-V5FG2EHC.js +2276 -0
  43. package/dist/chunks/ehr-HMFY6VIL.js +5241 -0
  44. package/dist/chunks/employee-SAK2QYXX.js +11 -0
  45. package/dist/chunks/esb-ZYSVB7SG.js +141 -0
  46. package/dist/chunks/fna-B7RKPAZD.js +1444 -0
  47. package/dist/chunks/host-45WED2KK.js +21 -0
  48. package/dist/chunks/host-I4Z6BFYX.js +23 -0
  49. package/dist/chunks/host-KNZ52LJZ.js +17 -0
  50. package/dist/chunks/host-OCH2BCCV.js +19 -0
  51. package/dist/chunks/hrm-2KAZGUHI.js +244 -0
  52. package/dist/chunks/im-ACJJWH4U.js +252 -0
  53. package/dist/chunks/invoice-ZK3WCX2U.js +5179 -0
  54. package/dist/chunks/jiuchuanhui-5PQD3IL2.js +1940 -0
  55. package/dist/chunks/lazy-dispatch-JQXBW3GM.js +28 -0
  56. package/dist/chunks/mail-S2HDDXO2.js +2695 -0
  57. package/dist/chunks/meeting-QVN3I37L.js +504 -0
  58. package/dist/chunks/msg-parse-4GSQ2WTO.js +41 -0
  59. package/dist/chunks/okr-QNG4VC2Q.js +2482 -0
  60. package/dist/chunks/plan-A25EMW6U.js +2025 -0
  61. package/dist/chunks/project-G6XV66DZ.js +1361 -0
  62. package/dist/chunks/registry-2VLUAESA.js +14 -0
  63. package/dist/chunks/registry-7C5UMIPL.js +19 -0
  64. package/dist/chunks/registry-DC6KR3NH.js +18 -0
  65. package/dist/chunks/registry-NYPYMZXG.js +16 -0
  66. package/dist/chunks/registry-TI3CIUXF.js +19 -0
  67. package/dist/chunks/room-recommend-WRTHO6Y2.js +20 -0
  68. package/dist/chunks/schedule-KFIITGSK.js +24 -0
  69. package/dist/chunks/state-Y2XBP6YE.js +15 -0
  70. package/dist/chunks/workflow-DJ7SYWAF.js +245 -0
  71. package/dist/cmd/argv.js +45 -0
  72. package/dist/cmd/docs/index.js +3 -3
  73. package/dist/cmd/lazy-dispatch.js +20 -0
  74. package/dist/cmd/root.js +2 -4
  75. package/dist/cmd/setup/index.js +2 -2
  76. package/dist/cmd/skills/index.js +2 -2
  77. package/dist/core/package-paths.js +61 -0
  78. package/dist/index.js +163 -7
  79. package/dist/internal/e10/auth/xiaoe.js +3 -3
  80. package/dist/internal/e10/request-runtime.js +18 -62
  81. package/dist/internal/skills/detector.js +2 -2
  82. package/dist/shortcuts/contract/data/performance-catalog.js +1306 -0
  83. package/dist/shortcuts/contract/host.js +91 -35
  84. package/dist/shortcuts/contract/index.js +213 -0
  85. package/dist/shortcuts/contract/manifest.js +928 -0
  86. package/dist/shortcuts/contract/ooxml/docx.js +295 -0
  87. package/dist/shortcuts/contract/ooxml/xlsx.js +221 -0
  88. package/dist/shortcuts/contract/ooxml/zip.js +158 -0
  89. package/dist/shortcuts/contract/operations/assistant.js +1156 -0
  90. package/dist/shortcuts/contract/operations/clause-library.js +522 -0
  91. package/dist/shortcuts/contract/operations/compare.js +193 -0
  92. package/dist/shortcuts/contract/operations/credit-page.js +34 -0
  93. package/dist/shortcuts/contract/operations/flow.js +98 -0
  94. package/dist/shortcuts/contract/operations/page.js +66 -0
  95. package/dist/shortcuts/contract/operations/performance.js +733 -0
  96. package/dist/shortcuts/contract/operations/quote.js +557 -0
  97. package/dist/shortcuts/contract/operations/recommend.js +78 -0
  98. package/dist/shortcuts/contract/operations/registry.js +18 -0
  99. package/dist/shortcuts/contract/operations/review.js +83 -0
  100. package/dist/shortcuts/contract/operations/shared.js +37 -0
  101. package/dist/shortcuts/contract/operations/upload.js +108 -0
  102. package/dist/shortcuts/contract/operations/write.js +3 -2
  103. package/dist/shortcuts/index.js +140 -40
  104. package/dist/shortcuts/invoice/manifest.js +34 -11
  105. package/dist/shortcuts/invoice/operations/reim-auto.js +9 -0
  106. package/dist/shortcuts/invoice/operations/reim.js +81 -5
  107. package/dist/shortcuts/invoice/operations/shared.js +12 -5
  108. package/dist/shortcuts/meeting/host.js +45 -3
  109. package/dist/shortcuts/meeting/invitation/docx.js +442 -0
  110. package/dist/shortcuts/meeting/operations/attachment-content.js +418 -0
  111. package/dist/shortcuts/meeting/operations/attachment.js +442 -0
  112. package/dist/shortcuts/meeting/operations/eb/cache.js +57 -0
  113. package/dist/shortcuts/meeting/operations/eb/catalog.js +343 -28
  114. package/dist/shortcuts/meeting/operations/eb/conflict.js +372 -11
  115. package/dist/shortcuts/meeting/operations/eb/create-flow.js +710 -0
  116. package/dist/shortcuts/meeting/operations/eb/decision.js +47 -1
  117. package/dist/shortcuts/meeting/operations/eb/factory.js +129 -11
  118. package/dist/shortcuts/meeting/operations/eb/index.js +122 -2
  119. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +378 -0
  120. package/dist/shortcuts/meeting/operations/eb/room-summary.js +84 -0
  121. package/dist/shortcuts/meeting/operations/eb/schedule.js +450 -0
  122. package/dist/shortcuts/meeting/operations/from-group-chat.js +576 -0
  123. package/dist/shortcuts/meeting/operations/invitation.js +458 -0
  124. package/dist/shortcuts/meeting/operations/minute-content.js +266 -0
  125. package/dist/shortcuts/meeting/operations/pipeline.js +489 -0
  126. package/dist/shortcuts/meeting/operations/qrcode.js +131 -0
  127. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  128. package/dist/shortcuts/meeting/operations/registry.js +18 -0
  129. package/dist/shortcuts/meeting/operations/summary.js +276 -0
  130. package/dist/shortcuts/meeting/operations/task-notify.js +325 -0
  131. package/dist/shortcuts/meeting/operations.js +42 -1
  132. package/dist/shortcuts/meeting/qr/encoder.js +427 -0
  133. package/dist/shortcuts/meeting/qr/render.js +103 -0
  134. package/dist/shortcuts/workflow/operations/form.js +17 -5
  135. package/docs/contract.md +39 -4
  136. package/docs/invoice.md +5 -5
  137. package/package.json +3 -2
  138. package/scripts/bundle.mjs +63 -0
  139. package/skill-template/business-info.json +25 -4
  140. package/skill-template/domains/jinchengda.md +16 -3
  141. package/skill-template/domains/yepiaotong.md +1 -1
  142. package/skills/weaver-e10-jinchengda/SKILL.md +111 -31
  143. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +7 -13
  144. package/skills/weaver-e10-jinchengda/references/contract-ai-assistant.md +150 -0
  145. package/skills/weaver-e10-jinchengda/references/contract-ai-review.md +87 -0
  146. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +111 -0
  147. package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +0 -15
  148. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +0 -13
  149. package/skills/weaver-e10-jinchengda/references/contract-credit-page.md +50 -0
  150. package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +4 -2
  151. package/skills/weaver-e10-jinchengda/references/contract-doc-compare.md +74 -0
  152. package/skills/weaver-e10-jinchengda/references/contract-flow-launch.md +84 -0
  153. package/skills/weaver-e10-jinchengda/references/contract-performance-query.md +29 -0
  154. package/skills/weaver-e10-jinchengda/references/contract-quote-to-contract.md +28 -0
  155. package/skills/weaver-e10-jinchengda/references/contract-request-status.md +2 -21
  156. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +0 -24
  157. package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +0 -15
  158. package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +0 -17
  159. package/skills/weaver-e10-jinchengda/references/contract-template-recommend.md +70 -0
  160. package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +0 -15
  161. package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +0 -15
  162. package/skills/weaver-e10-jinchengda/references/source-manifest.json +1168 -152
  163. package/skills/weaver-e10-meeting/SKILL.md +493 -17
  164. package/skills/weaver-e10-meeting/references/meeting-change.md +4 -4
  165. package/skills/weaver-e10-meeting/references/meeting-create.md +6 -6
  166. package/skills/weaver-e10-meeting/references/meeting-eb.md +503 -27
  167. package/skills/weaver-e10-meeting/references/meeting-invitation.md +113 -0
  168. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +6 -6
  169. package/skills/weaver-e10-meeting/references/meeting-minute-file.md +425 -0
  170. package/skills/weaver-e10-meeting/references/meeting-queries.md +4 -4
  171. package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +15 -15
  172. package/skills/weaver-e10-meeting/references/meeting-verification.md +19 -11
  173. package/skills/weaver-e10-meeting.zip +0 -0
  174. package/skills/weaver-e10-yepiaotong/SKILL.md +9 -5
  175. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +1 -1
  176. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +6 -5
  177. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +14 -11
  178. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +97 -56
  179. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +84 -60
  180. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +142 -105
  181. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +53 -194
  182. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -7
  183. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +164 -72
  184. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +6 -0
  185. package/templates/meeting/invitation.docx +0 -0
@@ -0,0 +1,1444 @@
1
+ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
+ const require = __esbuildCreateRequire(import.meta.url);
3
+ import {
4
+ E10ApiError,
5
+ createE10RequestRuntime,
6
+ requireE10Session
7
+ } from "./chunk-DW6AUUKS.js";
8
+ import {
9
+ E10_SESSION_EXPIRED_MESSAGE,
10
+ getActiveProfile
11
+ } from "./chunk-2GA5ZIQL.js";
12
+ import {
13
+ CliError,
14
+ isCliError,
15
+ toErrorEnvelope
16
+ } from "./chunk-LUSPKZKY.js";
17
+ import "./chunk-BUSC6UAE.js";
18
+
19
+ // src/shortcuts/fna/index.ts
20
+ import { readFile as readFile2 } from "node:fs/promises";
21
+
22
+ // src/shortcuts/fna/continuation.ts
23
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
24
+ import { existsSync } from "node:fs";
25
+ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
26
+ import { homedir } from "node:os";
27
+ import { resolve } from "node:path";
28
+
29
+ // src/shortcuts/fna/errors.ts
30
+ var FnaCliError = class extends CliError {
31
+ type;
32
+ subtype;
33
+ code;
34
+ retryable;
35
+ stage;
36
+ details;
37
+ partialData;
38
+ constructor(type, subtype, message, options = {}) {
39
+ super(message, options.exitCode ?? 5 /* InternalError */);
40
+ this.name = "FnaCliError";
41
+ this.type = type;
42
+ this.subtype = subtype;
43
+ this.code = options.code;
44
+ this.retryable = options.retryable ?? false;
45
+ this.stage = options.stage;
46
+ this.details = options.details;
47
+ this.partialData = options.partialData;
48
+ }
49
+ };
50
+ function fnaValidationError(subtype, message, details) {
51
+ return new FnaCliError("validation", subtype, message, {
52
+ details,
53
+ exitCode: 2 /* UsageError */
54
+ });
55
+ }
56
+ function fnaAuthError(subtype, message, details) {
57
+ return new FnaCliError("authentication", subtype, message, {
58
+ details,
59
+ exitCode: 3 /* AuthError */
60
+ });
61
+ }
62
+ function fnaNetworkError(subtype, message, options = {}) {
63
+ return new FnaCliError("network", subtype, message, {
64
+ ...options,
65
+ retryable: options.retryable ?? true,
66
+ exitCode: 4 /* NetworkError */
67
+ });
68
+ }
69
+ function fnaConfirmationError(action, details) {
70
+ return new FnaCliError("confirmation", "required", "\u8BE5\u64CD\u4F5C\u9700\u8981\u660E\u786E\u786E\u8BA4", {
71
+ details: { action, ...details },
72
+ exitCode: 10 /* ConfirmationRequired */
73
+ });
74
+ }
75
+ function fnaPartialError(message, partialData, details) {
76
+ return new FnaCliError("partial", "write_uncertain", message, {
77
+ details,
78
+ partialData,
79
+ exitCode: 11 /* Partial */
80
+ });
81
+ }
82
+ function isFnaNetworkError(error) {
83
+ return Boolean(
84
+ error && typeof error === "object" && "type" in error && error.type === "network"
85
+ );
86
+ }
87
+
88
+ // src/shortcuts/fna/continuation.ts
89
+ function stateRoot(ctx) {
90
+ const configured = ctx?.config?.path();
91
+ if (configured) return resolve(configured, "..");
92
+ return process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve(homedir(), ".weaver-work-cli");
93
+ }
94
+ async function loadKey(ctx) {
95
+ const keysDir = resolve(stateRoot(ctx), "keys");
96
+ const filename = resolve(keysDir, "fna-continuation.key");
97
+ await mkdir(keysDir, { recursive: true, mode: 448 });
98
+ if (existsSync(filename)) return readFile(filename);
99
+ const key = randomBytes(32);
100
+ try {
101
+ await writeFile(filename, key, { flag: "wx", mode: 384 });
102
+ if (process.platform !== "win32") await chmod(filename, 384).catch(() => void 0);
103
+ return key;
104
+ } catch {
105
+ return readFile(filename);
106
+ }
107
+ }
108
+ function encode(value) {
109
+ return Buffer.from(JSON.stringify(value)).toString("base64url");
110
+ }
111
+ function signature(payload, key) {
112
+ return createHmac("sha256", key).update(payload).digest("base64url");
113
+ }
114
+ function createFnaContinuationSigner(ctx) {
115
+ return {
116
+ async issue(payload, ttlMs = 10 * 6e4) {
117
+ const issuedAt = Date.now();
118
+ const body = encode({ ...payload, issuedAt, expiresAt: issuedAt + ttlMs });
119
+ const sig = signature(body, await loadKey(ctx));
120
+ return `${body}.${sig}`;
121
+ },
122
+ async verify(token, expectedOperation) {
123
+ if (typeof token !== "string" || !token.includes(".")) {
124
+ throw fnaValidationError("continuation_invalid", "continuation \u65E0\u6548");
125
+ }
126
+ const [body, provided] = token.split(".");
127
+ const expected = signature(body, await loadKey(ctx));
128
+ const valid = provided.length === expected.length && timingSafeEqual(Buffer.from(provided), Buffer.from(expected));
129
+ if (!valid) throw fnaValidationError("continuation_invalid", "continuation \u7B7E\u540D\u6821\u9A8C\u5931\u8D25");
130
+ let value;
131
+ try {
132
+ value = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
133
+ } catch {
134
+ throw fnaValidationError("continuation_invalid", "continuation \u5185\u5BB9\u65E0\u6CD5\u89E3\u6790");
135
+ }
136
+ if (value.operation !== expectedOperation) {
137
+ throw fnaValidationError("continuation_mismatch", "continuation \u4E0D\u5C5E\u4E8E\u5F53\u524D\u64CD\u4F5C");
138
+ }
139
+ if (!Number.isSafeInteger(value.expiresAt) || value.expiresAt < Date.now()) {
140
+ throw fnaValidationError("continuation_expired", "continuation \u5DF2\u8FC7\u671F");
141
+ }
142
+ return value;
143
+ }
144
+ };
145
+ }
146
+
147
+ // src/shortcuts/fna/host.ts
148
+ function inferProfile(ctx) {
149
+ const options = ctx.getGlobalOptions();
150
+ return options.profile || getActiveProfile();
151
+ }
152
+ function isBusinessSuccess(value) {
153
+ if (!value || typeof value !== "object") return false;
154
+ if (typeof value.success === "boolean") return value.success;
155
+ if (typeof value.status === "boolean") return value.status;
156
+ if (value.code !== void 0 && value.code !== null) return Number(value.code) === 200;
157
+ return false;
158
+ }
159
+ function businessMessage(value) {
160
+ if (!value || typeof value !== "object") return "\u6CDB\u5FAE\u63A5\u53E3\u8FD4\u56DE\u4E1A\u52A1\u5931\u8D25";
161
+ const candidates = [value.msg, value.message, value.data?.message];
162
+ for (const item of candidates) {
163
+ if (typeof item === "string" && item.trim()) return item;
164
+ }
165
+ return "\u6CDB\u5FAE\u63A5\u53E3\u8FD4\u56DE\u4E1A\u52A1\u5931\u8D25";
166
+ }
167
+ function businessCode(value) {
168
+ if (!value || typeof value !== "object") return void 0;
169
+ const code = value.code ?? value.status;
170
+ if (typeof code === "string" || typeof code === "number") return code;
171
+ return void 0;
172
+ }
173
+ function assertPath(requestPath) {
174
+ if (typeof requestPath !== "string" || !requestPath.startsWith("/") || requestPath.startsWith("//")) {
175
+ throw fnaValidationError("path_invalid", "\u8BF7\u6C42\u8DEF\u5F84\u5FC5\u987B\u662F\u76F8\u5BF9\u7EDD\u5BF9\u8DEF\u5F84");
176
+ }
177
+ if (/^https?:/i.test(requestPath) || /[\r\n]/.test(requestPath) || requestPath.includes("/../")) {
178
+ throw fnaValidationError("path_invalid", "\u8BF7\u6C42\u8DEF\u5F84\u4E0D\u5141\u8BB8\u8DE8\u57DF\u6216\u8DEF\u5F84\u9003\u9038");
179
+ }
180
+ if (!requestPath.startsWith("/api/fna/") && !requestPath.startsWith("/api/app/fna/") && !requestPath.startsWith("/api/secondev/fna/")) {
181
+ throw fnaValidationError(
182
+ "path_not_allowed",
183
+ "FNA \u8D39\u63A7\u4E2D\u5FC3\u53EA\u80FD\u8C03\u7528 /api/fna/\u3001/api/app/fna/ \u6216 /api/secondev/fna/ \u8DEF\u5F84"
184
+ );
185
+ }
186
+ }
187
+ function omitEmptyQueryValues(query) {
188
+ if (!query) return void 0;
189
+ return Object.fromEntries(Object.entries(query).filter(([, value]) => value !== ""));
190
+ }
191
+ function mapRuntimeNetworkError(error) {
192
+ if (error instanceof E10ApiError && error.type === "network") {
193
+ throw fnaNetworkError(error.subtype, error.message, {
194
+ retryable: error.retryable,
195
+ details: error.details
196
+ });
197
+ }
198
+ throw error;
199
+ }
200
+ function createFnaHost(ctx, dependencies = {}) {
201
+ let e10Session = null;
202
+ let sessionContext = null;
203
+ const requireSession = dependencies.requireSession || requireE10Session;
204
+ async function ensureSession() {
205
+ if (!e10Session) {
206
+ e10Session = await requireSession(ctx);
207
+ sessionContext = {
208
+ baseUrl: e10Session.getBaseUrl(),
209
+ profile: inferProfile(ctx),
210
+ userId: e10Session.userId,
211
+ tenantKey: e10Session.tenantKey,
212
+ eteamsId: e10Session.eteamsId
213
+ };
214
+ }
215
+ return e10Session;
216
+ }
217
+ async function getSession() {
218
+ await ensureSession();
219
+ return sessionContext;
220
+ }
221
+ async function runtime() {
222
+ return createE10RequestRuntime(ctx, await ensureSession(), {
223
+ interceptors: dependencies.interceptors,
224
+ fetch: dependencies.fetch
225
+ });
226
+ }
227
+ async function request(request2) {
228
+ const {
229
+ method,
230
+ path,
231
+ query,
232
+ body,
233
+ operation,
234
+ headers: extraHeaders = {},
235
+ timeoutMs = 3e4
236
+ } = request2;
237
+ assertPath(path);
238
+ const resolvedMethod = method || (body === void 0 ? "GET" : "POST");
239
+ let response;
240
+ try {
241
+ response = await (await runtime()).requestJson({
242
+ module: "fna",
243
+ operation,
244
+ method: resolvedMethod,
245
+ path,
246
+ query: omitEmptyQueryValues(query),
247
+ body,
248
+ headers: { "X-Requested-With": "XMLHttpRequest", ...extraHeaders },
249
+ timeoutMs
250
+ });
251
+ } catch (error) {
252
+ mapRuntimeNetworkError(error);
253
+ }
254
+ if (response.status === 401 || response.status === 302) {
255
+ throw fnaAuthError("session_expired", E10_SESSION_EXPIRED_MESSAGE, { httpStatus: response.status });
256
+ }
257
+ if (response.parseError) {
258
+ if (response.status < 200 || response.status >= 300) {
259
+ throw new FnaCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
260
+ code: response.status,
261
+ details: { status: response.status },
262
+ exitCode: 1
263
+ });
264
+ }
265
+ throw fnaNetworkError("protocol", `\u63A5\u53E3\u8FD4\u56DE\u4E0D\u662F\u5408\u6CD5 JSON\uFF08HTTP ${response.status}\uFF09`, { retryable: false });
266
+ }
267
+ if (response.status < 200 || response.status >= 300) {
268
+ throw new FnaCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
269
+ code: response.status,
270
+ details: { status: response.status, message: businessMessage(response.value) },
271
+ exitCode: 1
272
+ });
273
+ }
274
+ if (!isBusinessSuccess(response.value)) {
275
+ throw new FnaCliError("api", "business_error", businessMessage(response.value), {
276
+ code: businessCode(response.value),
277
+ details: { code: businessCode(response.value), message: businessMessage(response.value) },
278
+ exitCode: 1
279
+ });
280
+ }
281
+ return response.value;
282
+ }
283
+ return { request, getSession };
284
+ }
285
+
286
+ // src/shortcuts/fna/operations/types.ts
287
+ var READ = "read";
288
+ var WRITE = "write";
289
+ function fnaSuccess(action, data, meta) {
290
+ const payload = { ok: true, action, data };
291
+ if (meta && Object.keys(meta).length > 0) payload.meta = meta;
292
+ return payload;
293
+ }
294
+ function schemaOf(properties, options = {}) {
295
+ return {
296
+ type: "object",
297
+ additionalProperties: false,
298
+ properties,
299
+ ...options.required?.length ? { required: options.required } : {},
300
+ ...options.description ? { description: options.description } : {}
301
+ };
302
+ }
303
+ var SCHEMA_INTEGER_POSITIVE = { type: "integer", minimum: 1 };
304
+ var SCHEMA_DATE = { type: "string", pattern: "^\\d{4}-\\d{2}-\\d{2}$" };
305
+ var SCHEMA_ID = { oneOf: [{ type: "integer" }, { type: "string", pattern: "^\\d+$" }] };
306
+ var SCHEMA_STRING_NONEMPTY = { type: "string", minLength: 1 };
307
+
308
+ // src/shortcuts/fna/operations/shared.ts
309
+ import { createHash } from "node:crypto";
310
+ var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
311
+ function asObject(value) {
312
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
313
+ throw fnaValidationError("input_not_object", "\u8F93\u5165\u5FC5\u987B\u662F JSON \u5BF9\u8C61");
314
+ }
315
+ return value;
316
+ }
317
+ function assertNoForbiddenKeys(input) {
318
+ for (const key of Object.keys(input)) {
319
+ if (FORBIDDEN_KEYS.has(key)) {
320
+ throw fnaValidationError("forbidden_key", `\u8F93\u5165\u5305\u542B\u975E\u6CD5\u5B57\u6BB5\uFF1A${key}`);
321
+ }
322
+ }
323
+ }
324
+ var DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
325
+ function isRealDate(value) {
326
+ const [year, month, day] = value.split("-").map(Number);
327
+ if (month < 1 || month > 12) return false;
328
+ const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate();
329
+ return day >= 1 && day <= daysInMonth;
330
+ }
331
+ function assertDate(value, field) {
332
+ if (typeof value !== "string" || !DATE_PATTERN.test(value)) {
333
+ throw fnaValidationError("date_invalid", `${field} \u5FC5\u987B\u662F YYYY-MM-DD \u683C\u5F0F`);
334
+ }
335
+ if (!isRealDate(value)) {
336
+ throw fnaValidationError("date_invalid", `${field} \u4E0D\u662F\u5408\u6CD5\u65E5\u671F\uFF08\u6708\u4EFD\u9700 01-12\uFF0C\u65E5\u671F\u9700\u5728\u8BE5\u6708\u6709\u6548\u8303\u56F4\u5185\uFF09\uFF1A${value}`);
337
+ }
338
+ return value;
339
+ }
340
+ function assertDateRange(args, startField = "startDate", endField = "endDate") {
341
+ const start = args[startField];
342
+ const end = args[endField];
343
+ if ((start === void 0 || start === null) !== (end === void 0 || end === null)) {
344
+ throw fnaValidationError("date_range_incomplete", `${startField} \u4E0E ${endField} \u5FC5\u987B\u6210\u5BF9\u63D0\u4F9B`);
345
+ }
346
+ if (start === void 0 || start === null) return {};
347
+ const startDate = assertDate(start, startField);
348
+ const endDate = assertDate(end, endField);
349
+ if (startDate > endDate) {
350
+ throw fnaValidationError("date_range_invalid", `${startField} \u4E0D\u5F97\u665A\u4E8E ${endField}`);
351
+ }
352
+ return { start: startDate, end: endDate };
353
+ }
354
+ function toPositiveInt(value, field) {
355
+ if (value === void 0 || value === null || value === "") return void 0;
356
+ const numeric = Number(value);
357
+ if (!Number.isFinite(numeric)) {
358
+ throw fnaValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57`);
359
+ }
360
+ const truncated = Math.trunc(numeric);
361
+ if (truncated !== numeric || truncated <= 0) {
362
+ throw fnaValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
363
+ }
364
+ return truncated;
365
+ }
366
+ function numericId(value, field) {
367
+ if (value === void 0 || value === null || value === "") return void 0;
368
+ if (typeof value === "number") {
369
+ if (!Number.isFinite(value)) throw fnaValidationError("id_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57 ID`);
370
+ return value;
371
+ }
372
+ const text = String(value).trim();
373
+ if (!/^\d+$/.test(text)) {
374
+ throw fnaValidationError("id_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57 ID`);
375
+ }
376
+ const numeric = Number(text);
377
+ return Number.isSafeInteger(numeric) ? numeric : text;
378
+ }
379
+ function unwrapData(response) {
380
+ if (!response || typeof response !== "object") return response;
381
+ return response.data;
382
+ }
383
+ function toAmount(value) {
384
+ if (value === void 0 || value === null || value === "") return 0;
385
+ const numeric = Number(String(value).replace(/,/g, ""));
386
+ return Number.isFinite(numeric) ? numeric : 0;
387
+ }
388
+ function compact(body) {
389
+ for (const key of Object.keys(body)) {
390
+ if (body[key] === void 0) delete body[key];
391
+ }
392
+ return body;
393
+ }
394
+ function fingerprint(value) {
395
+ return createHash("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
396
+ }
397
+ function requireConfirm(args, action) {
398
+ if (args.confirm !== true) {
399
+ throw fnaConfirmationError(action, { hint: "\u91CD\u65B0\u8C03\u7528\u65F6\u4F20\u5165 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation" });
400
+ }
401
+ }
402
+ async function verifyLease(args, action, env) {
403
+ const lease = await env.continuation.verify(args.continuation, action);
404
+ const session = await env.host.getSession();
405
+ if (lease.baseUrl !== session.baseUrl || lease.profile !== session.profile || lease.userId !== session.userId) {
406
+ throw fnaValidationError("context_mismatch", "\u786E\u8BA4\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF08\u79DF\u6237\u6216\u767B\u5F55\u8D26\u53F7\u4E0D\u540C\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
407
+ }
408
+ return lease;
409
+ }
410
+ var MAX_ROWS = 200;
411
+ var MAX_ROWS_BYTES = 80 * 1024;
412
+ function requireRemindRows(value) {
413
+ if (!Array.isArray(value) || value.length === 0) {
414
+ throw fnaValidationError("rows_empty", "data \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08mainPageList \u8FD4\u56DE\u7684 displayData \u884C\uFF09");
415
+ }
416
+ if (value.length > MAX_ROWS) {
417
+ throw fnaValidationError("rows_too_many", `\u4E00\u6B21\u6700\u591A\u63D0\u9192 ${MAX_ROWS} \u6761\u8BB0\u5F55`);
418
+ }
419
+ const rows = value;
420
+ for (let index = 0; index < rows.length; index += 1) {
421
+ const row = rows[index];
422
+ if (!row || typeof row !== "object" || Array.isArray(row)) {
423
+ throw fnaValidationError("rows_invalid", `data[${index}] \u5FC5\u987B\u662F\u5BF9\u8C61\uFF08displayData \u884C\uFF09`);
424
+ }
425
+ const id = String(row.id ?? "");
426
+ const workflowId = String(row.workflowId ?? row.workflowid ?? "");
427
+ if (!/^\d+$/.test(id) || !/^\d+$/.test(workflowId)) {
428
+ throw fnaValidationError("rows_invalid", `data[${index}] \u7F3A\u5C11\u5408\u6CD5 id \u4E0E workflowId\uFF0C\u65E0\u6CD5\u5B9A\u4F4D\u501F\u6B3E\u8BB0\u5F55`);
429
+ }
430
+ }
431
+ const serialized = JSON.stringify(rows);
432
+ if (Buffer.byteLength(serialized, "utf8") > MAX_ROWS_BYTES) {
433
+ throw fnaValidationError("rows_too_large", "\u63D0\u9192\u8BB0\u5F55\u8FC7\u5927\uFF0C\u8BF7\u5206\u6279\u5904\u7406");
434
+ }
435
+ return rows;
436
+ }
437
+ function summarizeRemindRows(rows) {
438
+ const borrowers = [...new Set(rows.map((row) => String(row.jkrPersonName || row.createPerson || row.userId || "").trim()).filter(Boolean))];
439
+ const totalDhk = rows.reduce((sum, row) => sum + toAmount(row.dhkAmount), 0);
440
+ const ids = rows.map((row) => String(row.id));
441
+ return {
442
+ count: rows.length,
443
+ borrowers,
444
+ totalDhkAmount: totalDhk.toFixed(2),
445
+ ids
446
+ };
447
+ }
448
+ function normalizeWeaTable(table, defaults) {
449
+ const payload = table ?? {};
450
+ const displayRows = Array.isArray(payload.displayData) ? payload.displayData : null;
451
+ const rawRows = Array.isArray(payload.data) ? payload.data : [];
452
+ return {
453
+ pageUid: payload.pageUid ?? "",
454
+ total: payload.total ?? 0,
455
+ current: payload.current ?? defaults.current,
456
+ pageSize: payload.pageSize ?? defaults.pageSize,
457
+ hasMore: payload.hasMore ?? false,
458
+ pageSizeFromPageUid: payload.pageSizeFromPageUid ?? defaults.pageSize,
459
+ columns: Array.isArray(payload.columns) ? payload.columns : [],
460
+ operates: Array.isArray(payload.operates) ? payload.operates : [],
461
+ rows: displayRows ?? rawRows
462
+ };
463
+ }
464
+ function requireRequestIds(value) {
465
+ if (!Array.isArray(value) || value.length === 0) {
466
+ throw fnaValidationError("requestids_empty", "requestids \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF08writeOffList \u8FD4\u56DE\u884C\u7684 requestId\uFF09");
467
+ }
468
+ if (value.length > MAX_ROWS) {
469
+ throw fnaValidationError("requestids_too_many", `\u4E00\u6B21\u6700\u591A\u50AC\u7968 ${MAX_ROWS} \u6761\u8BB0\u5F55`);
470
+ }
471
+ const ids = value.map((item, index) => {
472
+ if (item === void 0 || item === null || item === "") {
473
+ throw fnaValidationError("requestids_invalid", `requestids[${index}] \u4E0D\u80FD\u4E3A\u7A7A`);
474
+ }
475
+ const text = String(item).trim();
476
+ if (!/^\d+$/.test(text)) {
477
+ throw fnaValidationError("requestids_invalid", `requestids[${index}] \u5FC5\u987B\u662F\u6570\u5B57\u6D41\u7A0B ID`);
478
+ }
479
+ return text;
480
+ });
481
+ return ids;
482
+ }
483
+
484
+ // src/shortcuts/fna/operations/budget.ts
485
+ var fnaBudgetApplicationDetail = {
486
+ name: "fna.budget.application.detail",
487
+ resource: "budget",
488
+ method: "budget.application.detail",
489
+ action: "fna.budget.application.detail",
490
+ summary: "\u4E8B\u524D\u7533\u8BF7\u5355\u9884\u7B97\u8BE6\u60C5\uFF1A\u6309 requestId \u8FD4\u56DE\u7533\u8BF7\u540D\u79F0\u3001\u521B\u5EFA\u4EBA\u3001\u53D1\u8D77\u65F6\u95F4\u4E0E\u9884\u7B97\u53E3\u5F84\uFF08\u603B\u989D/\u5DF2\u62A5\u9500/\u62A5\u9500\u4E2D/\u5269\u4F59\u53EF\u7528/\u5DF2\u91CA\u653E\uFF09\uFF0C\u5E76\u9644\u539F\u59CB\u8868\u5355 items",
491
+ capability: "budget",
492
+ risk: READ,
493
+ inputSchema: schemaOf(
494
+ { requestId: { ...SCHEMA_ID, description: "\u4E8B\u524D\u7533\u8BF7\u5355 ID\uFF08\u5FC5\u586B\uFF09" } },
495
+ { required: ["requestId"], description: "\u9884\u7B97\uFF1A\u4E8B\u524D\u7533\u8BF7\u5355\u9884\u7B97\u8BE6\u60C5" }
496
+ ),
497
+ handler: async (args, { host }) => {
498
+ const requestId = numericId(args.requestId, "requestId");
499
+ if (requestId === void 0) {
500
+ throw fnaValidationError("request_id_required", "requestId \u5FC5\u586B\uFF08\u4E8B\u524D\u7533\u8BF7\u5355 ID\uFF09");
501
+ }
502
+ const response = await host.request({
503
+ method: "GET",
504
+ path: "/api/fna/expense/preApplication/getApplicationDetail",
505
+ query: { requestId }
506
+ });
507
+ const form = unwrapData(response);
508
+ const items = form?.items ?? {};
509
+ const budgetInfo = items.budgetInfo?.otherParams ?? {};
510
+ const budget = {
511
+ totalAmount: budgetInfo.budgeteTotalAmount ?? 0,
512
+ reimbursedFee: budgetInfo.reimbursedFee ?? 0,
513
+ reimbursingFee: budgetInfo.reimburserFee ?? 0,
514
+ remainingBudget: budgetInfo.remainingBudgete ?? 0,
515
+ releasedBudgetAmount: budgetInfo.releasedBudgetAmount ?? 0,
516
+ isDisplay: budgetInfo.isDisplay ?? false
517
+ };
518
+ const detail = {
519
+ requestId: String(requestId),
520
+ requestName: items.requestName?.value ?? "",
521
+ createPerson: items.createPerson?.value ?? "",
522
+ createPersonUserId: items.createPerson?.otherParams?.userId ?? "",
523
+ createTime: items.createTime?.value ?? "",
524
+ budget,
525
+ consistencyHint: "\u9884\u7B97\u603B\u989D = \u5DF2\u62A5\u9500 + \u62A5\u9500\u4E2D + \u5269\u4F59\u53EF\u7528 + \u5DF2\u91CA\u653E\uFF1B\u82E5\u4E0D\u7B49\uFF0C\u6570\u636E\u53EF\u80FD\u672A\u5237\u65B0\u6216\u5B58\u5728\u5E76\u53D1\u5728\u9014\u53D8\u66F4"
526
+ };
527
+ return fnaSuccess("fna.budget.application.detail", detail, { rawForm: form });
528
+ }
529
+ };
530
+ var fnaBudgetExecuteList = {
531
+ name: "fna.budget.execute.list",
532
+ resource: "budget",
533
+ method: "budget.execute.list",
534
+ action: "fna.budget.execute.list",
535
+ summary: "\u9884\u7B97\u6267\u884C\u62A5\u8868\uFF1A\u6309\u9884\u7B97\u6A21\u677F + \u7EF4\u5EA6/\u671F\u95F4\u7B5B\u9009\uFF0C\u8FD4\u56DE\u5206\u9875\u660E\u7EC6\u884C\u4E0E customParameters \u5408\u8BA1\uFF08budget_sumAmount \u524D\u7F00\uFF09\uFF0C\u4EC5\u5217\u660E\u5F53\u524D\u6A21\u677F\u53EF\u7528\u7684\u7EF4\u5EA6 key",
536
+ capability: "budget",
537
+ risk: READ,
538
+ inputSchema: schemaOf(
539
+ {
540
+ current: { ...SCHEMA_INTEGER_POSITIVE, description: "\u5F53\u524D\u9875\u7801\uFF08\u5FC5\u586B\uFF0C\u4ECE 1 \u5F00\u59CB\uFF09" },
541
+ pageSize: { ...SCHEMA_INTEGER_POSITIVE, description: "\u6BCF\u9875\u6761\u6570\uFF08\u5FC5\u586B\uFF09" },
542
+ templateId: { ...SCHEMA_ID, description: "\u9884\u7B97\u6A21\u677F ID\uFF1B\u4E3A\u7A7A\u53EA\u8FD4\u56DE\u8868\u5934" },
543
+ formDatas: {
544
+ type: "object",
545
+ description: "\u7EF4\u5EA6/\u671F\u95F4\u7B5B\u9009\uFF0Cvalue \u4E3A\u300C\u5355\u5143\u7D20\u6570\u7EC4\u5305\u88F9\u540C\u540D key \u6570\u7EC4\u300D\u7684\u4E8C\u5C42\u5D4C\u5957\uFF1BperiodName \u4F20\u91D1\u989D\u5217\u540D budget_amount1~12\uFF0CdimenMem1 \u7B49\u7EF4\u5EA6 key \u7531\u6A21\u677F corrColumn \u51B3\u5B9A"
546
+ },
547
+ type: { type: "string", enum: ["and", "or"], description: "\u7B5B\u9009\u5173\u8054\u65B9\u5F0F" },
548
+ departmentFlag: { type: "string", description: "\u90E8\u95E8\u6807\u8BC6" },
549
+ exportType: { type: "string", description: "\u5BFC\u51FA\u7C7B\u578B" },
550
+ ignoreReportPower: { type: "boolean", description: "\u662F\u5426\u5FFD\u7565\u62A5\u8868\u6743\u9650\u6821\u9A8C\uFF08\u4EC5\u5185\u90E8/\u7BA1\u7406\u5458\uFF09" }
551
+ },
552
+ {
553
+ required: ["current", "pageSize"],
554
+ description: "\u9884\u7B97\uFF1A\u9884\u7B97\u6267\u884C\u62A5\u8868\u67E5\u8BE2\uFF08\u6A21\u677F + \u7EF4\u5EA6 + \u671F\u95F4\uFF09"
555
+ }
556
+ ),
557
+ handler: async (args, { host }) => {
558
+ const current = toPositiveInt(args.current, "current");
559
+ const pageSize = toPositiveInt(args.pageSize, "pageSize");
560
+ if (current === void 0) throw fnaValidationError("current_required", "current \u5FC5\u586B\uFF08\u6B63\u6574\u6570\u9875\u7801\uFF09");
561
+ if (pageSize === void 0) throw fnaValidationError("page_size_required", "pageSize \u5FC5\u586B\uFF08\u6B63\u6574\u6570\u6BCF\u9875\u6761\u6570\uFF09");
562
+ const body = { current, pageSize };
563
+ if (args.templateId !== void 0) body.templateId = numericId(args.templateId, "templateId");
564
+ if (args.formDatas !== void 0) body.formDatas = args.formDatas;
565
+ if (args.type !== void 0) body.type = args.type;
566
+ if (args.departmentFlag !== void 0) body.departmentFlag = args.departmentFlag;
567
+ if (args.exportType !== void 0) body.exportType = args.exportType;
568
+ if (args.ignoreReportPower !== void 0) body.ignoreReportPower = args.ignoreReportPower;
569
+ const response = await host.request({
570
+ method: "POST",
571
+ path: "/api/fna/execute/getExecuteListByAi",
572
+ body
573
+ });
574
+ const table = unwrapData(response);
575
+ const result = {
576
+ pageUid: table?.pageUid ?? "FnaBudgetExecuteList",
577
+ total: table?.total ?? 0,
578
+ current: table?.current ?? current,
579
+ pageSize: table?.pageSize ?? pageSize,
580
+ hasMore: table?.hasMore ?? false,
581
+ periodFlag: table?.periodFlag ?? false,
582
+ columns: table?.columns ?? [],
583
+ rows: Array.isArray(table?.data) ? table.data : [],
584
+ totals: table?.customParameters ?? {}
585
+ };
586
+ return fnaSuccess("fna.budget.execute.list", result, {
587
+ hint: "templateId \u4E3A\u7A7A\u65F6\u4EC5\u8FD4\u56DE\u8868\u5934\u5217\u5B9A\u4E49\uFF08\u6B63\u5E38\u884C\u4E3A\uFF09\uFF1B\u6C47\u603B\u95EE\u9898\u4F18\u5148\u8BFB totals \u4E2D budget_sumAmount \u524D\u7F00\u5B57\u6BB5\uFF1B\u91D1\u989D/\u6BD4\u7387\u4E3A\u5B57\u7B26\u4E32\u9700\u8F6C\u6570\u503C\u5E76\u53BB %"
588
+ });
589
+ }
590
+ };
591
+ var budgetOperations = [
592
+ fnaBudgetApplicationDetail,
593
+ fnaBudgetExecuteList
594
+ ];
595
+
596
+ // src/shortcuts/fna/operations/expense-center.ts
597
+ var SUM_AMOUNT_PROPERTIES = {
598
+ employeeId: { ...SCHEMA_ID, description: "\u5458\u5DE5 ID\uFF08\u6570\u5B57\uFF09\uFF1B\u4E3A\u7A7A\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u4EBA" },
599
+ startDate: { ...SCHEMA_DATE, description: "\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08\u95ED\u533A\u95F4\uFF09" },
600
+ endDate: { ...SCHEMA_DATE, description: "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD\uFF08\u95ED\u533A\u95F4\uFF09" },
601
+ workflowId: { ...SCHEMA_ID, description: "\u6D41\u7A0B\u7C7B\u578B ID\uFF08\u6570\u5B57\uFF09" },
602
+ requestId: { ...SCHEMA_ID, description: "\u6D41\u7A0B\u5B9E\u4F8B ID\uFF08\u6570\u5B57\uFF09" }
603
+ };
604
+ function sleep(ms) {
605
+ return new Promise((resolve2) => {
606
+ setTimeout(resolve2, ms);
607
+ });
608
+ }
609
+ function sumAmountBody(args) {
610
+ const range = assertDateRange(args, "startDate", "endDate");
611
+ const body = {};
612
+ const employeeId = numericId(args.employeeId, "employeeId");
613
+ const workflowId = numericId(args.workflowId, "workflowId");
614
+ const requestId = numericId(args.requestId, "requestId");
615
+ if (employeeId !== void 0) body.employeeId = employeeId;
616
+ if (range.start !== void 0) body.startDate = range.start;
617
+ if (range.end !== void 0) body.endDate = range.end;
618
+ if (workflowId !== void 0) body.workflowId = workflowId;
619
+ if (requestId !== void 0) body.requestId = requestId;
620
+ return body;
621
+ }
622
+ function hasDataKey(value) {
623
+ return Boolean(value && typeof value === "object" && Object.prototype.hasOwnProperty.call(value, "data"));
624
+ }
625
+ var fnaExpenseReimbursedSum = {
626
+ name: "fna.expense.reimbursed.sum",
627
+ resource: "expense",
628
+ method: "expense.reimbursed.sum",
629
+ action: "fna.expense.reimbursed.sum",
630
+ summary: "\u62A5\u9500\u91D1\u989D\u5408\u8BA1\uFF08\u5DF2\u62A5\u9500\u53E3\u5F84\uFF0C\u5BA1\u6279\u5B8C\u6210\u660E\u7EC6\u5408\u8BA1\uFF09\uFF1A\u6309\u5458\u5DE5/\u65E5\u671F/\u6D41\u7A0B\u8FC7\u6EE4\uFF0C\u8FD4\u56DE\u91D1\u989D\uFF08\u5143\uFF09\u4E0E\u53E3\u5F84\u8BF4\u660E",
631
+ capability: "expense",
632
+ risk: READ,
633
+ inputSchema: schemaOf(SUM_AMOUNT_PROPERTIES, { description: "\u8D39\u7528\u4E2D\u5FC3\uFF1A\u62A5\u9500\u91D1\u989D\u5408\u8BA1\uFF08body \u53EF\u4E3A\u7A7A\uFF0C\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u4EBA\uFF09" }),
634
+ handler: async (args, { host }) => {
635
+ const response = await host.request({
636
+ method: "POST",
637
+ path: "/api/fna/expense/center/getSumReimbursedAmountByAi",
638
+ body: sumAmountBody(args)
639
+ });
640
+ const amount = response?.data ?? 0;
641
+ return fnaSuccess("fna.expense.reimbursed.sum", {
642
+ amount,
643
+ currency: "CNY",
644
+ note: "\u5DF2\u62A5\u9500\u53E3\u5F84\uFF1A\u5BA1\u6279\u5B8C\u6210\uFF08\u660E\u7EC6\u72B6\u6001 status=1\uFF09\u660E\u7EC6\u7684 reimburse_amount \u5408\u8BA1\uFF1B\u65E0\u5339\u914D\u6570\u636E\u8FD4\u56DE 0.0"
645
+ });
646
+ }
647
+ };
648
+ var fnaExpenseLoanSum = {
649
+ name: "fna.expense.loan.sum",
650
+ resource: "expense",
651
+ method: "expense.loan.sum",
652
+ action: "fna.expense.loan.sum",
653
+ summary: "\u501F\u6B3E\u91D1\u989D\u5206\u6BB5\u6C47\u603B\uFF08\u5F85\u8FD8\u6B3E dhk/\u8FD8\u6B3E\u4E2D hkz/\u5DF2\u8FD8\u6B3E yhk/\u501F\u6B3E\u603B\u989D jk\uFF0C\u542B\u7B14\u6570\uFF09\uFF1A\u6CE8\u610F\u670D\u52A1\u7AEF\u53EA\u7EDF\u8BA1\u9996\u6761\u501F\u6B3E\u8BB0\u5F55\u7684\u5DF2\u77E5\u7F3A\u9677",
654
+ capability: "expense",
655
+ risk: READ,
656
+ inputSchema: schemaOf(SUM_AMOUNT_PROPERTIES, { description: "\u8D39\u7528\u4E2D\u5FC3\uFF1A\u501F\u6B3E\u91D1\u989D\u5206\u6BB5\u6C47\u603B\uFF08body \u53EF\u4E3A\u7A7A\uFF0C\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u4EBA\uFF09" }),
657
+ handler: async (args, { host }) => {
658
+ const body = sumAmountBody(args);
659
+ let response;
660
+ let attempts = 0;
661
+ for (; ; ) {
662
+ response = await host.request({
663
+ method: "POST",
664
+ path: "/api/fna/expense/center/getSumLoanAmountByAi",
665
+ body
666
+ });
667
+ if (hasDataKey(response) || attempts >= 2) break;
668
+ attempts += 1;
669
+ await sleep(150);
670
+ }
671
+ if (!hasDataKey(response)) {
672
+ return fnaSuccess("fna.expense.loan.sum", { segments: null }, {
673
+ note: "\u8FDE\u7EED 3 \u6B21\u8BF7\u6C42\u5747\u672A\u8FD4\u56DE data\uFF0C\u6309\u300C\u6682\u65E0\u501F\u6B3E\u8BB0\u5F55\u300D\u5904\u7406\uFF1B\u82E5\u786E\u6709\u501F\u6B3E\uFF0C\u53EF\u7A0D\u540E\u91CD\u8BD5"
674
+ });
675
+ }
676
+ const segments = response.data;
677
+ return fnaSuccess("fna.expense.loan.sum", {
678
+ segments,
679
+ note: "\u8BE5\u501F\u6B3E\u63A5\u53E3\u4EC5\u7EDF\u8BA1\u9996\u6761\u501F\u6B3E\u8BB0\u5F55\uFF08for \u5FAA\u73AF\u5185 return\uFF09\uFF0C\u91D1\u989D/\u7B14\u6570\u53EF\u80FD\u4E0D\u5168\uFF0C\u5F85\u5F00\u53D1\u4FEE\u590D\uFF1B\u5C55\u793A\u4E0E\u56DE\u4F20\u4EE5 key\uFF08dhk/hkz/yhk/jk\uFF09\u4E3A\u51C6\uFF0C\u4E0D\u4F9D\u8D56 costType \u6587\u6848"
680
+ });
681
+ }
682
+ };
683
+ var fnaExpensePrepayWriteOffSum = {
684
+ name: "fna.expense.prepay.writeoff.sum",
685
+ resource: "expense",
686
+ method: "expense.prepay.writeoff.sum",
687
+ action: "fna.expense.prepay.writeoff.sum",
688
+ summary: "\u9884\u4ED8\u6838\u9500\u91D1\u989D\u6C47\u603B\uFF08\u5BF9\u516C\u652F\u4ED8\u9884\u4ED8\u5355\uFF09\uFF1A\u9884\u4ED8\u91D1\u989D/\u6838\u9500\u4E2D/\u5DF2\u6838\u9500/\u672A\u5230\u8D26\u5408\u8BA1\uFF0C\u6309\u521B\u5EFA\u4EBA/\u65E5\u671F/\u6D41\u7A0B\u8FC7\u6EE4",
689
+ capability: "expense",
690
+ risk: READ,
691
+ inputSchema: schemaOf(SUM_AMOUNT_PROPERTIES, { description: "\u8D39\u7528\u4E2D\u5FC3\uFF1A\u9884\u4ED8\u6838\u9500\u91D1\u989D\u6C47\u603B\uFF08body \u53EF\u4E3A\u7A7A\uFF0C\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u4EBA\uFF09" }),
692
+ handler: async (args, { host }) => {
693
+ const response = await host.request({
694
+ method: "POST",
695
+ path: "/api/fna/expense/center/selectPrepayWriteOffAmountBySkill",
696
+ body: sumAmountBody(args)
697
+ });
698
+ const value = response?.data ?? {};
699
+ const result = {
700
+ paymentAmount: value.payment_amount ?? 0,
701
+ writeOffing: value.writeOffing ?? 0,
702
+ writeOffed: value.writeOffed ?? 0,
703
+ noArrivedAmount: value.noArrivedAmount ?? 0,
704
+ note: "\u53E3\u5F84\uFF1AemployeeId \u5339\u914D\u9884\u4ED8\u5355\u521B\u5EFA\u4EBA\uFF1B\u65E5\u671F\u6309\u6838\u9500\u8BB0\u5F55\u521B\u5EFA\u65F6\u95F4\u8FC7\u6EE4\uFF1B\u672A\u5230\u8D26 = \u9884\u4ED8\u91D1\u989D \u2212 \u5DF2\u5230\u8D26 \u2212 \u5DF2\u6838\u9500\uFF1B\u65E0\u5339\u914D\u6570\u636E\u515C\u5E95 0"
705
+ };
706
+ return fnaSuccess("fna.expense.prepay.writeoff.sum", result);
707
+ }
708
+ };
709
+ var expenseCenterOperations = [
710
+ fnaExpenseReimbursedSum,
711
+ fnaExpenseLoanSum,
712
+ fnaExpensePrepayWriteOffSum
713
+ ];
714
+
715
+ // src/shortcuts/fna/operations/expense-chart.ts
716
+ var CHART_TIMEOUT_MS = 18e4;
717
+ var DEFAULT_MAX_ROWS = 200;
718
+ var MAX_ROWS_LIMIT = 5e3;
719
+ var USER_INPUT_LIMIT = 500;
720
+ var BLOCKED_MESSAGE = /拦截|高危|安全校验/;
721
+ var CLARIFY_MESSAGE = /不明确|请补充|补充查询/;
722
+ function requireUserInput(value) {
723
+ if (typeof value !== "string" || value.trim().length === 0) {
724
+ throw fnaValidationError("user_input_required", "userInput \u5FC5\u586B\uFF08\u81EA\u7136\u8BED\u8A00\u95EE\u9898\uFF0C\u4E0D\u80FD\u4E3A\u7A7A\u767D\uFF09");
725
+ }
726
+ const userInput = value.trim();
727
+ if (userInput.length > USER_INPUT_LIMIT) {
728
+ throw fnaValidationError("user_input_too_long", "userInput \u4E0D\u80FD\u8D85\u8FC7 500 \u4E2A\u5B57\u7B26");
729
+ }
730
+ return userInput;
731
+ }
732
+ function resolveMaxRows(value) {
733
+ if (value === void 0 || value === null || value === "") return DEFAULT_MAX_ROWS;
734
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > MAX_ROWS_LIMIT) {
735
+ throw fnaValidationError("max_rows_invalid", "maxRows \u5FC5\u987B\u662F 1 \u5230 5000 \u7684\u6574\u6570");
736
+ }
737
+ return value;
738
+ }
739
+ function mapChartApiError(error) {
740
+ if (error instanceof FnaCliError && error.type === "api") {
741
+ const code = Number(error.code);
742
+ if (code === 400) {
743
+ throw fnaValidationError("user_input_required", "userInput \u672A\u901A\u8FC7\u670D\u52A1\u7AEF\u6821\u9A8C\uFF08\u7F3A\u5C11\u6216\u975E\u6CD5\uFF09");
744
+ }
745
+ if (code === 500) {
746
+ throw new FnaCliError("api", "server_error", error.message || "\u62A5\u9500\u62A5\u8868\u670D\u52A1\u5F02\u5E38", {
747
+ code: error.code ?? 500,
748
+ retryable: false,
749
+ details: error.details
750
+ });
751
+ }
752
+ }
753
+ throw error;
754
+ }
755
+ function dataTypeOf(value) {
756
+ if (value === null) return "null";
757
+ if (Array.isArray(value)) return "array";
758
+ return typeof value;
759
+ }
760
+ function isRow(value) {
761
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
762
+ }
763
+ function collectColumns(rows) {
764
+ const columns = [];
765
+ const seen = /* @__PURE__ */ new Set();
766
+ for (const row of rows) {
767
+ for (const key of Object.keys(row)) {
768
+ if (seen.has(key)) continue;
769
+ seen.add(key);
770
+ columns.push(key);
771
+ }
772
+ }
773
+ return columns;
774
+ }
775
+ function classifyMessage(message) {
776
+ if (BLOCKED_MESSAGE.test(message)) return "blocked";
777
+ if (CLARIFY_MESSAGE.test(message)) return "clarify";
778
+ return void 0;
779
+ }
780
+ function normalizeChart(data, maxRows) {
781
+ if (Array.isArray(data) && data.every(isRow)) {
782
+ const columns = collectColumns(data);
783
+ const rows = data.slice(0, maxRows);
784
+ if (data.length === 0) {
785
+ return fnaSuccess("fna.expense.chart", {
786
+ kind: "empty",
787
+ columns,
788
+ rows,
789
+ rowCount: 0,
790
+ truncated: false
791
+ }, {
792
+ requestedRows: 0,
793
+ returnedRows: 0,
794
+ maxRows
795
+ });
796
+ }
797
+ return fnaSuccess("fna.expense.chart", {
798
+ kind: "rows",
799
+ columns,
800
+ rows,
801
+ rowCount: data.length,
802
+ truncated: rows.length < data.length
803
+ }, {
804
+ requestedRows: data.length,
805
+ returnedRows: rows.length,
806
+ maxRows
807
+ });
808
+ }
809
+ if (typeof data === "string") {
810
+ const kind = classifyMessage(data);
811
+ if (kind) {
812
+ return fnaSuccess("fna.expense.chart", { kind, message: data }, { messageKindInferred: true });
813
+ }
814
+ }
815
+ return fnaSuccess("fna.expense.chart", { kind: "unexpected" }, { dataType: dataTypeOf(data) });
816
+ }
817
+ var fnaExpenseChart = {
818
+ name: "fna.expense.chart",
819
+ resource: "expense",
820
+ method: "expense.chart",
821
+ action: "fna.expense.chart",
822
+ summary: "\u62A5\u9500\u62A5\u8868 AI \u95EE\u7B54\uFF1A\u7528\u81EA\u7136\u8BED\u8A00\u67E5\u8BE2\u5206\u7EC4/\u6392\u540D/\u8D8B\u52BF\uFF0C\u8FD4\u56DE kind=rows/empty/clarify/blocked/unexpected\uFF1BmaxRows \u53EA\u622A\u65AD\u672C\u5730\u5C55\u793A",
823
+ capability: "expense-chart",
824
+ risk: READ,
825
+ inputSchema: schemaOf(
826
+ {
827
+ userInput: {
828
+ ...SCHEMA_STRING_NONEMPTY,
829
+ maxLength: USER_INPUT_LIMIT,
830
+ description: "\u81EA\u7136\u8BED\u8A00\u95EE\u9898\uFF08\u5FC5\u586B\uFF0C\u2264500 \u5B57\u7B26\uFF09\u3002\u53EA\u5199\u4E1A\u52A1\u95EE\u9898\uFF0C\u4E0D\u8981\u4F20 SQL\uFF0C\u4E5F\u4E0D\u8981\u81EA\u62FC\u5F53\u524D\u7528\u6237/\u90E8\u95E8 ID"
831
+ },
832
+ maxRows: {
833
+ ...SCHEMA_INTEGER_POSITIVE,
834
+ maximum: MAX_ROWS_LIMIT,
835
+ description: "\u672C\u5730\u5C55\u793A\u884C\u6570\u4E0A\u9650\uFF0C\u9ED8\u8BA4 200\uFF0C\u6700\u5927 5000\uFF1B\u4E0D\u4F20\u7ED9\u670D\u52A1\u7AEF\uFF0C\u4E0D\u6539\u53D8\u67E5\u8BE2"
836
+ }
837
+ },
838
+ { required: ["userInput"], description: "\u62A5\u9500\u62A5\u8868 AI \u95EE\u7B54\uFF08\u4E8C\u5F00\u63A5\u53E3\uFF0C\u6BCF\u6B21\u6D88\u8017\u4E00\u6B21\u5927\u6A21\u578B\u5BF9\u8BDD\u4E0E\u4E00\u6B21 SQL\uFF09" }
839
+ ),
840
+ handler: async (args, { host }) => {
841
+ const userInput = requireUserInput(args.userInput);
842
+ const maxRows = resolveMaxRows(args.maxRows);
843
+ let response;
844
+ try {
845
+ response = await host.request({
846
+ method: "GET",
847
+ path: "/api/secondev/fna/getExpenseChart",
848
+ query: { userInput },
849
+ timeoutMs: CHART_TIMEOUT_MS
850
+ });
851
+ } catch (error) {
852
+ throw mapChartApiError(error);
853
+ }
854
+ return normalizeChart(unwrapData(response), maxRows);
855
+ }
856
+ };
857
+ var expenseChartOperations = [
858
+ fnaExpenseChart
859
+ ];
860
+
861
+ // src/shortcuts/fna/operations/loan.ts
862
+ var CONTINUATION_TTL_SECONDS = 600;
863
+ var LOAN_MENU_FIELDS = {
864
+ menuCode: { ...SCHEMA_STRING_NONEMPTY, description: "\u83DC\u5355\u7F16\u7801\uFF0C\u5982 fesx_fna_borrowingManagement\uFF08\u4E0E\u73AF\u5883\u6838\u5BF9\uFF09" },
865
+ permissionSetCode: { ...SCHEMA_STRING_NONEMPTY, description: "\u6743\u9650\u96C6\u7F16\u7801\uFF0C\u5982 fesx_fna_borrowingManagement.default\uFF08\u4E0E\u73AF\u5883\u6838\u5BF9\uFF09" },
866
+ departmentId: { type: "string", description: "\u90E8\u95E8 ID\uFF0C\u4E3A\u7A7A\u67E5\u5168\u90E8" }
867
+ };
868
+ var fnaLoanMainPage = {
869
+ name: "fna.loan.main.page",
870
+ resource: "loan",
871
+ method: "loan.main.page",
872
+ action: "fna.loan.main.page",
873
+ summary: "\u501F\u6B3E\u7BA1\u7406\u9996\u9875\u6C47\u603B\uFF08\u5168\u516C\u53F8\u5F85\u8FD8\u6B3E/\u8FD8\u6B3E\u4E2D\u91D1\u989D\u4E0E\u7B14\u6570\uFF0C\u9700\u7BA1\u7406\u5458\u767B\u5F55\uFF09",
874
+ capability: "loan",
875
+ risk: READ,
876
+ inputSchema: schemaOf(
877
+ {
878
+ ...LOAN_MENU_FIELDS,
879
+ borrowingStatus: { type: "string", description: "\u501F\u6B3E\u72B6\u6001\uFF0C\u5982 waitReimbursement\uFF08\u5F85\u8FD8\u6B3E\uFF09" }
880
+ },
881
+ { description: "\u501F\u6B3E\u7BA1\u7406\uFF1A\u9996\u9875\u6C47\u603B\uFF08body \u53EF\u4E3A\u7A7A\uFF1B\u5EFA\u8BAE\u5E26 menuCode/permissionSetCode\uFF09" }
882
+ ),
883
+ handler: async (args, { host }) => {
884
+ const body = compact({
885
+ borrowingStatus: args.borrowingStatus,
886
+ departmentId: args.departmentId,
887
+ menuCode: args.menuCode,
888
+ permissionSetCode: args.permissionSetCode
889
+ });
890
+ const response = await host.request({
891
+ method: "POST",
892
+ path: "/api/fna/expense/loanManagementMenu/mainPage",
893
+ body
894
+ });
895
+ const summary = unwrapData(response);
896
+ return fnaSuccess("fna.loan.main.page", {
897
+ dhk: summary?.dhk ?? null,
898
+ hkz: summary?.hkz ?? null,
899
+ note: "amount \u4E3A\u683C\u5F0F\u5316\u5B57\u7B26\u4E32\uFF08\u5143\uFF09\uFF0Ccount \u4E3A\u7B14\u6570\uFF1BmenuCode/permissionSetCode \u73AF\u5883\u76F8\u5173\uFF0C\u793A\u4F8B\u503C\u9700\u4E0E\u73AF\u5883\u6838\u5BF9"
900
+ });
901
+ }
902
+ };
903
+ var fnaLoanMainList = {
904
+ name: "fna.loan.main.list",
905
+ resource: "loan",
906
+ method: "loan.main.list",
907
+ action: "fna.loan.main.list",
908
+ summary: "\u501F\u6B3E\u7BA1\u7406\u9996\u9875\u5217\u8868\uFF08\u5168\u5458\u501F\u6B3E\u5355\u5206\u9875\uFF0C\u9700\u7BA1\u7406\u5458\u767B\u5F55\uFF09\uFF1A\u8FD4\u56DE displayData \u884C\uFF08\u542B id/workflowId\uFF0C\u53EF\u56DE\u4F20\u63D0\u9192\u8FD8\u6B3E\uFF09",
909
+ capability: "loan",
910
+ risk: READ,
911
+ inputSchema: schemaOf(
912
+ {
913
+ current: { ...SCHEMA_INTEGER_POSITIVE, description: "\u5F53\u524D\u9875\u7801\uFF08\u5FC5\u586B\uFF09" },
914
+ pageSize: { ...SCHEMA_INTEGER_POSITIVE, description: "\u6BCF\u9875\u6761\u6570\uFF08\u5FC5\u586B\uFF09" },
915
+ ...LOAN_MENU_FIELDS,
916
+ isBatchConfirmRepaymentSearch: { type: "boolean", description: "\u662F\u5426\u6279\u91CF\u786E\u8BA4\u8FD8\u6B3E\u641C\u7D22" }
917
+ },
918
+ { required: ["current", "pageSize", "menuCode", "permissionSetCode"], description: "\u501F\u6B3E\u7BA1\u7406\uFF1A\u9996\u9875\u5217\u8868" }
919
+ ),
920
+ handler: async (args, { host }) => {
921
+ const current = toPositiveInt(args.current, "current");
922
+ const pageSize = toPositiveInt(args.pageSize, "pageSize");
923
+ if (current === void 0) throw fnaValidationError("current_required", "current \u5FC5\u586B\uFF08\u6B63\u6574\u6570\u9875\u7801\uFF09");
924
+ if (pageSize === void 0) throw fnaValidationError("page_size_required", "pageSize \u5FC5\u586B\uFF08\u6B63\u6574\u6570\u6BCF\u9875\u6761\u6570\uFF09");
925
+ if (!args.menuCode || !args.permissionSetCode) {
926
+ throw fnaValidationError("menu_code_required", "menuCode \u4E0E permissionSetCode \u5FC5\u586B\uFF08\u501F\u6B3E\u7BA1\u7406\u83DC\u5355\u7F16\u7801\uFF0C\u4E0E\u73AF\u5883\u6838\u5BF9\uFF09");
927
+ }
928
+ const body = compact({
929
+ current,
930
+ pageSize,
931
+ isBatchConfirmRepaymentSearch: args.isBatchConfirmRepaymentSearch,
932
+ departmentId: args.departmentId,
933
+ menuCode: args.menuCode,
934
+ permissionSetCode: args.permissionSetCode
935
+ });
936
+ const response = await host.request({
937
+ method: "POST",
938
+ path: "/api/fna/expense/loanManagementMenu/mainPageList",
939
+ body
940
+ });
941
+ const table = normalizeWeaTable(unwrapData(response), { current, pageSize });
942
+ return fnaSuccess("fna.loan.main.list", table, {
943
+ hint: "\u63D0\u9192\u8FD8\u6B3E\u8BF7\u53D6 rows \u4E2D displayData \u884C\u539F\u6837\u56DE\u4F20\uFF08fna.loan.remind.repay.prepare\uFF09\uFF1B\u91D1\u989D\u5C55\u793A\u4EE5 displayData \u4E3A\u51C6\uFF0Cdata \u884C\u91D1\u989D\u4E3A\u539F\u59CB\u7CBE\u5EA6"
944
+ });
945
+ }
946
+ };
947
+ var fnaLoanRemindRepayPrepare = {
948
+ name: "fna.loan.remind.repay.prepare",
949
+ resource: "loan",
950
+ method: "loan.remind.repay.prepare",
951
+ action: "fna.loan.remind.repay.prepare",
952
+ summary: "\u63D0\u9192\u8FD8\u6B3E\uFF08\u51C6\u5907\uFF09\uFF1A\u4F20\u5165 mainPageList \u7684 displayData \u884C\uFF0C\u6821\u9A8C\u5E76\u751F\u6210\u9884\u89C8\u4E0E continuation\uFF0C\u4E0D\u53D1\u9001\u63D0\u9192",
953
+ capability: "loan",
954
+ risk: WRITE,
955
+ requiresConfirmation: true,
956
+ inputSchema: schemaOf(
957
+ {
958
+ type: { type: "string", description: "\u63D0\u9192\u7C7B\u578B\uFF0C\u9ED8\u8BA4 batchRemindReimbursement" },
959
+ data: {
960
+ type: "array",
961
+ items: { type: "object", description: "mainPageList \u8FD4\u56DE\u7684 displayData \u884C\uFF08\u539F\u6837\u56DE\u4F20\uFF09" },
962
+ minItems: 1,
963
+ description: "\u63D0\u9192\u8FD8\u6B3E\u8BB0\u5F55\u5217\u8868\uFF08\u6700\u591A 200 \u6761\uFF09"
964
+ }
965
+ },
966
+ { required: ["data"], description: "\u501F\u6B3E\u7BA1\u7406\uFF1A\u63D0\u9192\u8FD8\u6B3E\uFF08\u51C6\u5907\uFF09" }
967
+ ),
968
+ handler: async (args, { host, continuation }) => {
969
+ const rows = requireRemindRows(args.data);
970
+ const session = await host.getSession();
971
+ const summary = summarizeRemindRows(rows);
972
+ const token = await continuation.issue(
973
+ {
974
+ operation: "fna.loan.remind.repay.apply",
975
+ baseUrl: session.baseUrl,
976
+ profile: session.profile,
977
+ userId: session.userId,
978
+ fingerprint: fingerprint(rows),
979
+ count: rows.length
980
+ },
981
+ CONTINUATION_TTL_SECONDS * 1e3
982
+ );
983
+ return fnaSuccess("fna.loan.remind.repay.prepare", {
984
+ status: "AWAITING_CONFIRMATION",
985
+ preview: {
986
+ ...summary,
987
+ action: "\u5411\u501F\u6B3E\u4EBA\u53D1\u9001\u8FD8\u6B3E\u63D0\u9192\u901A\u77E5",
988
+ hint: "\u5411\u7528\u6237\u5C55\u793A\u6761\u6570\u3001\u501F\u6B3E\u4EBA\u3001\u5269\u4F59\u5F85\u8FD8\u5408\u8BA1\u5E76\u83B7\u5F97\u660E\u786E\u786E\u8BA4\u540E\uFF0C\u518D\u8C03\u7528 fna.loan.remind.repay.apply"
989
+ },
990
+ continuation: token,
991
+ expiresInSeconds: CONTINUATION_TTL_SECONDS
992
+ });
993
+ }
994
+ };
995
+ var fnaLoanRemindRepayApply = {
996
+ name: "fna.loan.remind.repay.apply",
997
+ resource: "loan",
998
+ method: "loan.remind.repay.apply",
999
+ action: "fna.loan.remind.repay.apply",
1000
+ summary: "\u63D0\u9192\u8FD8\u6B3E\uFF08\u6267\u884C\uFF09\uFF1A\u9700 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation\uFF0C\u884C\u96C6\u5408\u4E0E prepare \u4E00\u81F4\u624D\u4F1A\u53D1\u9001\u63D0\u9192",
1001
+ capability: "loan",
1002
+ risk: WRITE,
1003
+ requiresConfirmation: true,
1004
+ inputSchema: schemaOf(
1005
+ {
1006
+ type: { type: "string", description: "\u63D0\u9192\u7C7B\u578B\uFF0C\u9ED8\u8BA4 batchRemindReimbursement" },
1007
+ data: { type: "array", items: { type: "object" }, minItems: 1, description: "\u4E0E prepare \u76F8\u540C\u7684 displayData \u884C" },
1008
+ confirm: { const: true },
1009
+ continuation: { type: "string", minLength: 1 }
1010
+ },
1011
+ { required: ["data", "confirm", "continuation"], description: "\u501F\u6B3E\u7BA1\u7406\uFF1A\u63D0\u9192\u8FD8\u6B3E\uFF08\u6267\u884C\uFF09" }
1012
+ ),
1013
+ handler: async (args, env) => {
1014
+ requireConfirm(args, "fna.loan.remind.repay.apply");
1015
+ const rows = requireRemindRows(args.data);
1016
+ const lease = await verifyLease(args, "fna.loan.remind.repay.apply", env);
1017
+ if (fingerprint(rows) !== lease.fingerprint || rows.length !== lease.count) {
1018
+ throw fnaValidationError("target_changed", "\u63D0\u9192\u8BB0\u5F55\u4E0E prepare \u65F6\u7684\u5FEB\u7167\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
1019
+ }
1020
+ const body = { type: args.type ?? "batchRemindReimbursement", data: rows };
1021
+ let response;
1022
+ try {
1023
+ response = await env.host.request({
1024
+ method: "POST",
1025
+ path: "/api/fna/expense/loanManagementMenu/remindRepay",
1026
+ body
1027
+ });
1028
+ } catch (error) {
1029
+ if (isFnaNetworkError(error)) {
1030
+ throw fnaPartialError(
1031
+ "\u63D0\u9192\u8FD8\u6B3E\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u662F\u5426\u5DF2\u53D1\u9001\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u53EF\u901A\u8FC7 fna.loan.main.list \u56DE\u67E5\u6216\u91CD\u65B0 prepare \u786E\u8BA4",
1032
+ { attempted: { count: rows.length } },
1033
+ { stage: "loan.remindRepay" }
1034
+ );
1035
+ }
1036
+ throw error;
1037
+ }
1038
+ const message = response?.data?.msg ?? "\u63D0\u9192\u8FD8\u6B3E\u6210\u529F";
1039
+ return fnaSuccess("fna.loan.remind.repay.apply", {
1040
+ msg: message,
1041
+ remindedCount: rows.length,
1042
+ note: "\u672C\u63A5\u53E3\u53EA\u53D1\u9001\u8FD8\u6B3E\u63D0\u9192\uFF0C\u4E0D\u6539\u53D8\u501F\u6B3E/\u8FD8\u6B3E\u91D1\u989D\u72B6\u6001"
1043
+ });
1044
+ }
1045
+ };
1046
+ var loanOperations = [
1047
+ fnaLoanMainPage,
1048
+ fnaLoanMainList,
1049
+ fnaLoanRemindRepayPrepare,
1050
+ fnaLoanRemindRepayApply
1051
+ ];
1052
+
1053
+ // src/shortcuts/fna/operations/invoice-writeoff.ts
1054
+ var CONTINUATION_TTL_SECONDS2 = 600;
1055
+ var WRITE_OFF_FILTER_FIELDS = {
1056
+ invoiceStatus: {
1057
+ type: "string",
1058
+ enum: ["unWritten", "unarrivedTicket", "dealing", "callTicket"],
1059
+ description: "\u53D1\u7968\u72B6\u6001\u8FC7\u6EE4\uFF1AunWritten \u672A\u6838\u9500 / unarrivedTicket \u672A\u5230\u7968 / dealing \u6838\u9500\u4E2D / callTicket \u50AC\u7968"
1060
+ },
1061
+ type: { type: "string", description: "\u7C7B\u578B\uFF0C\u9ED8\u8BA4 1" },
1062
+ departmentId: { type: "string", description: "\u90E8\u95E8 ID\uFF0C\u4E3A\u7A7A\u67E5\u5168\u90E8" },
1063
+ menuCode: { type: "string", description: "\u83DC\u5355\u7F16\u7801\uFF0C\u5982 inv_write_off_financial\uFF08\u4E0E\u73AF\u5883\u6838\u5BF9\uFF09" },
1064
+ permissionSetCode: { type: "string", description: "\u6743\u9650\u96C6\u7F16\u7801\uFF0C\u5982 inv_write_off_financial.default\uFF08\u4E0E\u73AF\u5883\u6838\u5BF9\uFF09" },
1065
+ dataSource: { type: "string", description: "\u6570\u636E\u6765\u6E90" },
1066
+ cfgType: { type: "string", description: "\u914D\u7F6E\u7C7B\u578B" },
1067
+ dataStatisticCfgId: { type: "string", description: "\u6570\u636E\u7EDF\u8BA1\u914D\u7F6E ID" },
1068
+ requestId: { type: "string", description: "\u6D41\u7A0B\u8BF7\u6C42 ID" }
1069
+ };
1070
+ var fnaInvoiceWriteOffTab = {
1071
+ name: "fna.invoice.writeoff.summary",
1072
+ resource: "invoice-writeoff",
1073
+ method: "invoice.writeoff.summary",
1074
+ action: "fna.invoice.writeoff.summary",
1075
+ summary: "\u53D1\u7968\u6838\u9500\u91D1\u989D tab \u6C47\u603B\uFF08\u672A\u6838\u9500/\u6838\u9500\u4E2D/\u90E8\u5206\u6838\u9500/\u5B8C\u5168\u6838\u9500\u7684\u91D1\u989D\u4E0E\u7B14\u6570\uFF0C\u8D22\u52A1/\u7BA1\u7406\u5458\uFF09",
1076
+ capability: "invoice-writeoff",
1077
+ risk: READ,
1078
+ inputSchema: schemaOf(WRITE_OFF_FILTER_FIELDS, { description: "\u53D1\u7968\u6838\u9500\uFF1A\u91D1\u989D tab \u6C47\u603B\uFF08\u53EF\u4F20 invoiceStatus \u8FC7\u6EE4\uFF0C\u4E0D\u5206\u9875\uFF09" }),
1079
+ handler: async (args, { host }) => {
1080
+ const body = compact({
1081
+ invoiceStatus: args.invoiceStatus,
1082
+ type: args.type,
1083
+ departmentId: args.departmentId,
1084
+ menuCode: args.menuCode,
1085
+ permissionSetCode: args.permissionSetCode,
1086
+ dataSource: args.dataSource,
1087
+ cfgType: args.cfgType,
1088
+ dataStatisticCfgId: args.dataStatisticCfgId,
1089
+ requestId: args.requestId
1090
+ });
1091
+ const response = await host.request({
1092
+ method: "POST",
1093
+ path: "/api/fna/expense/inv/financial/writeOffPageTab",
1094
+ body
1095
+ });
1096
+ const data = unwrapData(response);
1097
+ return fnaSuccess("fna.invoice.writeoff.summary", {
1098
+ whx: data?.whx ?? null,
1099
+ hxz: data?.hxz ?? null,
1100
+ bfhx: data?.bfhx ?? null,
1101
+ wqhx: data?.wqhx ?? null,
1102
+ note: "amount \u4E3A\u683C\u5F0F\u5316\u5B57\u7B26\u4E32\uFF08\u5143\uFF09\uFF1BmenuCode/permissionSetCode \u73AF\u5883\u76F8\u5173\uFF0C\u793A\u4F8B\u503C\u9700\u4E0E\u73AF\u5883\u6838\u5BF9"
1103
+ });
1104
+ }
1105
+ };
1106
+ var fnaInvoiceWriteOffList = {
1107
+ name: "fna.invoice.writeoff.list",
1108
+ resource: "invoice-writeoff",
1109
+ method: "invoice.writeoff.list",
1110
+ action: "fna.invoice.writeoff.list",
1111
+ summary: "\u53D1\u7968\u6838\u9500\u5217\u8868\uFF08\u5206\u9875\uFF0C\u8D22\u52A1/\u7BA1\u7406\u5458\uFF09\uFF1A\u8FD4\u56DE\u6838\u9500\u5355\u884C\uFF08requestId/id \u53EF\u7528\u4E8E\u50AC\u7968\uFF09",
1112
+ capability: "invoice-writeoff",
1113
+ risk: READ,
1114
+ inputSchema: schemaOf(
1115
+ {
1116
+ current: { ...SCHEMA_INTEGER_POSITIVE, description: "\u5F53\u524D\u9875\u7801\uFF08\u5FC5\u586B\uFF09" },
1117
+ pageSize: { ...SCHEMA_INTEGER_POSITIVE, description: "\u6BCF\u9875\u6761\u6570\uFF08\u5FC5\u586B\uFF09" },
1118
+ ...WRITE_OFF_FILTER_FIELDS,
1119
+ quickSearchDatas: { type: "object", description: "\u5FEB\u6377\u641C\u7D22\u6570\u636E" },
1120
+ formDatas: { type: "object", description: "\u8868\u5355\u641C\u7D22\u6570\u636E" }
1121
+ },
1122
+ { required: ["current", "pageSize"], description: "\u53D1\u7968\u6838\u9500\uFF1A\u6838\u9500\u5217\u8868" }
1123
+ ),
1124
+ handler: async (args, { host }) => {
1125
+ const current = toPositiveInt(args.current, "current");
1126
+ const pageSize = toPositiveInt(args.pageSize, "pageSize");
1127
+ if (current === void 0) throw fnaValidationError("current_required", "current \u5FC5\u586B\uFF08\u6B63\u6574\u6570\u9875\u7801\uFF09");
1128
+ if (pageSize === void 0) throw fnaValidationError("page_size_required", "pageSize \u5FC5\u586B\uFF08\u6B63\u6574\u6570\u6BCF\u9875\u6761\u6570\uFF09");
1129
+ const body = compact({
1130
+ current,
1131
+ pageSize,
1132
+ invoiceStatus: args.invoiceStatus,
1133
+ type: args.type,
1134
+ departmentId: args.departmentId,
1135
+ menuCode: args.menuCode,
1136
+ permissionSetCode: args.permissionSetCode,
1137
+ dataSource: args.dataSource,
1138
+ quickSearchDatas: args.quickSearchDatas,
1139
+ formDatas: args.formDatas,
1140
+ cfgType: args.cfgType,
1141
+ dataStatisticCfgId: args.dataStatisticCfgId,
1142
+ requestId: args.requestId
1143
+ });
1144
+ const response = await host.request({
1145
+ method: "POST",
1146
+ path: "/api/fna/expense/inv/financial/writeOffList",
1147
+ body
1148
+ });
1149
+ const table = normalizeWeaTable(unwrapData(response), { current, pageSize });
1150
+ return fnaSuccess("fna.invoice.writeoff.list", table, {
1151
+ hint: "\u50AC\u7968\u8BF7\u53D6 rows \u884C\u7684 requestId\uFF08\u6216 id\uFF09\u7EC4\u88C5 requestids \u4F20\u7ED9 fna.invoice.writeoff.callticket.prepare\uFF1B\u91D1\u989D\u5B57\u6BB5\u4E3A\u683C\u5F0F\u5316\u5B57\u7B26\u4E32\uFF08\u5143\uFF09"
1152
+ });
1153
+ }
1154
+ };
1155
+ var fnaInvoiceCallTicketPrepare = {
1156
+ name: "fna.invoice.writeoff.callticket.prepare",
1157
+ resource: "invoice-writeoff",
1158
+ method: "invoice.writeoff.callticket.prepare",
1159
+ action: "fna.invoice.writeoff.callticket.prepare",
1160
+ summary: "\u50AC\u7968\uFF08\u51C6\u5907\uFF09\uFF1A\u4F20\u5165 writeOffList \u884C\u7684 requestId \u5217\u8868\uFF0C\u6821\u9A8C\u5E76\u751F\u6210\u9884\u89C8\u4E0E continuation\uFF0C\u4E0D\u53D1\u9001\u50AC\u7968",
1161
+ capability: "invoice-writeoff",
1162
+ risk: WRITE,
1163
+ requiresConfirmation: true,
1164
+ inputSchema: schemaOf(
1165
+ {
1166
+ requestids: {
1167
+ type: "array",
1168
+ items: { type: "string", pattern: "^\\d+$" },
1169
+ minItems: 1,
1170
+ description: "\u6D41\u7A0B\u8BF7\u6C42 ID \u5217\u8868\uFF08writeOffList \u8FD4\u56DE\u884C\u7684 requestId / id\uFF0C\u6700\u591A 200 \u6761\uFF09"
1171
+ }
1172
+ },
1173
+ { required: ["requestids"], description: "\u53D1\u7968\u6838\u9500\uFF1A\u50AC\u7968\uFF08\u51C6\u5907\uFF09" }
1174
+ ),
1175
+ handler: async (args, { host, continuation }) => {
1176
+ const requestids = requireRequestIds(args.requestids);
1177
+ const session = await host.getSession();
1178
+ const token = await continuation.issue(
1179
+ {
1180
+ operation: "fna.invoice.writeoff.callticket.apply",
1181
+ baseUrl: session.baseUrl,
1182
+ profile: session.profile,
1183
+ userId: session.userId,
1184
+ fingerprint: fingerprint(requestids),
1185
+ count: requestids.length
1186
+ },
1187
+ CONTINUATION_TTL_SECONDS2 * 1e3
1188
+ );
1189
+ return fnaSuccess("fna.invoice.writeoff.callticket.prepare", {
1190
+ status: "AWAITING_CONFIRMATION",
1191
+ preview: {
1192
+ count: requestids.length,
1193
+ ids: requestids.slice(0, 20),
1194
+ action: "\u5BF9\u4EE5\u4E0A\u9884\u4ED8\u6D41\u7A0B\u53D1\u9001\u50AC\u7968\u901A\u77E5",
1195
+ hint: "\u5411\u7528\u6237\u5C55\u793A\u6761\u6570\u4E0E\u76EE\u6807\u6D41\u7A0B\uFF08\u5EFA\u8BAE\u540C\u65F6\u7528 fna.invoice.writeoff.list \u7684\u884C\u5C55\u793A\u7533\u8BF7\u540D\u79F0/\u672A\u6838\u9500\u91D1\u989D\uFF09\uFF0C\u83B7\u5F97\u660E\u786E\u786E\u8BA4\u540E\u518D\u8C03\u7528 fna.invoice.writeoff.callticket.apply"
1196
+ },
1197
+ continuation: token,
1198
+ expiresInSeconds: CONTINUATION_TTL_SECONDS2
1199
+ });
1200
+ }
1201
+ };
1202
+ var fnaInvoiceCallTicketApply = {
1203
+ name: "fna.invoice.writeoff.callticket.apply",
1204
+ resource: "invoice-writeoff",
1205
+ method: "invoice.writeoff.callticket.apply",
1206
+ action: "fna.invoice.writeoff.callticket.apply",
1207
+ summary: "\u50AC\u7968\uFF08\u6267\u884C\uFF09\uFF1A\u9700 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation\uFF0Crequestids \u4E0E prepare \u4E00\u81F4\u624D\u4F1A\u53D1\u9001\u50AC\u7968",
1208
+ capability: "invoice-writeoff",
1209
+ risk: WRITE,
1210
+ requiresConfirmation: true,
1211
+ inputSchema: schemaOf(
1212
+ {
1213
+ requestids: { type: "array", items: { type: "string", pattern: "^\\d+$" }, minItems: 1 },
1214
+ confirm: { const: true },
1215
+ continuation: { type: "string", minLength: 1 }
1216
+ },
1217
+ { required: ["requestids", "confirm", "continuation"], description: "\u53D1\u7968\u6838\u9500\uFF1A\u50AC\u7968\uFF08\u6267\u884C\uFF09" }
1218
+ ),
1219
+ handler: async (args, env) => {
1220
+ requireConfirm(args, "fna.invoice.writeoff.callticket.apply");
1221
+ const requestids = requireRequestIds(args.requestids);
1222
+ const lease = await verifyLease(args, "fna.invoice.writeoff.callticket.apply", env);
1223
+ if (fingerprint(requestids) !== lease.fingerprint || requestids.length !== lease.count) {
1224
+ throw fnaValidationError("target_changed", "\u50AC\u7968\u76EE\u6807\u4E0E prepare \u65F6\u7684\u5FEB\u7167\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
1225
+ }
1226
+ let response;
1227
+ try {
1228
+ response = await env.host.request({
1229
+ method: "POST",
1230
+ path: "/api/fna/expense/inv/financial/callTicket",
1231
+ body: { requestids }
1232
+ });
1233
+ } catch (error) {
1234
+ if (isFnaNetworkError(error)) {
1235
+ throw fnaPartialError(
1236
+ "\u50AC\u7968\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u662F\u5426\u5DF2\u53D1\u9001\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u53EF\u901A\u8FC7 fna.invoice.writeoff.list \u56DE\u67E5\u6216\u91CD\u65B0 prepare \u786E\u8BA4",
1237
+ { attempted: { count: requestids.length } },
1238
+ { stage: "invoice.writeoff.callTicket" }
1239
+ );
1240
+ }
1241
+ throw error;
1242
+ }
1243
+ const message = response?.data?.msg ?? "\u50AC\u7968\u6D88\u606F\u53D1\u9001\u6210\u529F";
1244
+ return fnaSuccess("fna.invoice.writeoff.callticket.apply", {
1245
+ msg: message,
1246
+ calledCount: requestids.length,
1247
+ note: "\u672C\u63A5\u53E3\u53EA\u53D1\u9001\u50AC\u7968\u901A\u77E5\uFF0C\u4E0D\u6539\u53D8\u6838\u9500\u91D1\u989D\u72B6\u6001"
1248
+ });
1249
+ }
1250
+ };
1251
+ var invoiceWriteOffOperations = [
1252
+ fnaInvoiceWriteOffTab,
1253
+ fnaInvoiceWriteOffList,
1254
+ fnaInvoiceCallTicketPrepare,
1255
+ fnaInvoiceCallTicketApply
1256
+ ];
1257
+
1258
+ // src/shortcuts/fna/operations/registry.ts
1259
+ function buildRegistry() {
1260
+ const registry = /* @__PURE__ */ new Map();
1261
+ const definitions = [
1262
+ ...budgetOperations,
1263
+ ...expenseCenterOperations,
1264
+ ...expenseChartOperations,
1265
+ ...loanOperations,
1266
+ ...invoiceWriteOffOperations
1267
+ ];
1268
+ for (const definition of definitions) {
1269
+ if (registry.has(definition.name)) {
1270
+ throw new Error(`duplicate fna operation: ${definition.name}`);
1271
+ }
1272
+ registry.set(definition.name, definition);
1273
+ }
1274
+ return registry;
1275
+ }
1276
+ var fnaOperationRegistry = buildRegistry();
1277
+ function fnaOperationDefinitions() {
1278
+ return [...fnaOperationRegistry.values()];
1279
+ }
1280
+ function getFnaOperation(operation) {
1281
+ const definition = fnaOperationRegistry.get(operation);
1282
+ if (!definition) {
1283
+ throw fnaValidationError("operation_unknown", `\u9F50\u4E1A\u6210\u8D39\u63A7\u4E0D\u652F\u6301\u64CD\u4F5C\uFF1A${operation}`);
1284
+ }
1285
+ return definition;
1286
+ }
1287
+
1288
+ // src/shortcuts/fna/manifest.ts
1289
+ var FNA_WITHHELD = [
1290
+ {
1291
+ name: "fna.loan.confirm.repay",
1292
+ reason: "\u501F\u6B3E\u7BA1\u7406\u83DC\u5355\u63D0\u4F9B\u300C\u786E\u8BA4\u5DF2\u8FD8 confirmRepay\u300D\u6309\u94AE\uFF0C\u4F46\u6E90\u8D44\u6599\u672A\u63D0\u4F9B\u5176\u63A5\u53E3\u8DEF\u5F84\u3001\u8BF7\u6C42\u65B9\u6CD5\u3001\u5173\u952E\u5B57\u6BB5\u4E0E\u786E\u8BA4\u6761\u4EF6\uFF0C\u672A\u5B9E\u73B0\uFF1B\u4E0D\u5F97\u731C\u6D4B\u63A5\u53E3\u3002"
1293
+ },
1294
+ {
1295
+ name: "fna.resolve.person.workflow",
1296
+ reason: "\u59D3\u540D\u2192employeeId\u3001\u6D41\u7A0B\u540D\u2192workflowId \u7684\u89E3\u6790\u4F9D\u8D56\u4EBA\u5458/\u6D41\u7A0B\u57FA\u8868\u63A5\u53E3\uFF0C\u6E90\u8D44\u6599\u672A\u63D0\u4F9B\uFF1B\u9700\u8981\u65F6\u8BF7\u4F7F\u7528\u5DF2\u63D0\u4F9B\u7684 ID \u6216\u7531\u7528\u6237\u5728\u5BF9\u8BDD\u4E2D\u63D0\u4F9B\u3002"
1297
+ },
1298
+ {
1299
+ name: "fna.expense.chart.raw.sql",
1300
+ reason: "\u62A5\u9500\u62A5\u8868 AI \u95EE\u7B54\u7531\u670D\u52A1\u7AEF\u751F\u6210 SQL \u5E76\u505A\u79DF\u6237\u9694\u79BB\u6539\u5199\u4E0E\u5B89\u5168\u6821\u9A8C\uFF1BCLI \u53EA\u63A5\u53D7 userInput\uFF0C\u4E0D\u66B4\u9732\u3001\u4E0D\u56DE\u4F20 SQL\uFF0C\u4E5F\u4E0D\u5141\u8BB8\u8C03\u7528\u65B9\u7ED5\u8FC7\u5B89\u5168\u6821\u9A8C\u81EA\u5199 SQL\u3002"
1301
+ }
1302
+ ];
1303
+ function buildOperations() {
1304
+ return fnaOperationDefinitions().map((definition) => ({
1305
+ name: definition.name,
1306
+ resource: definition.resource,
1307
+ summary: definition.summary,
1308
+ ...definition.capability ? { capability: definition.capability } : {},
1309
+ risk: definition.risk,
1310
+ ...definition.requiresConfirmation ? { requiresConfirmation: true } : {},
1311
+ inputSchema: definition.inputSchema
1312
+ }));
1313
+ }
1314
+ var fnaManifest = {
1315
+ schemaVersion: 1,
1316
+ name: "fna",
1317
+ title: "\u6CDB\u5FAEE10\u9F50\u4E1A\u6210\u8D39\u63A7\u4E2D\u5FC3\uFF08\u9884\u7B97\u67E5\u8BE2/\u8D39\u7528\u4E2D\u5FC3/\u62A5\u9500\u62A5\u8868/\u501F\u6B3E\u7BA1\u7406/\u53D1\u7968\u6838\u9500\uFF09",
1318
+ version: "0.1.1",
1319
+ host: "e10-fna",
1320
+ status: "builtin",
1321
+ sourceSkill: "weaver-e10-qiyecheng",
1322
+ capabilities: ["budget", "expense", "expense-chart", "loan", "invoice-writeoff"],
1323
+ operations: buildOperations(),
1324
+ withheldOperations: FNA_WITHHELD
1325
+ };
1326
+
1327
+ // src/shortcuts/fna/operations.ts
1328
+ async function executeFnaOperation(operation, rawInput, context) {
1329
+ const definition = getFnaOperation(operation);
1330
+ const input = asObject(rawInput);
1331
+ assertNoForbiddenKeys(input);
1332
+ const host = {
1333
+ request(request) {
1334
+ return context.host.request({
1335
+ ...request,
1336
+ operation: request.operation || operation
1337
+ });
1338
+ },
1339
+ getSession() {
1340
+ return context.host.getSession();
1341
+ }
1342
+ };
1343
+ return definition.handler(input, { ...context, host });
1344
+ }
1345
+
1346
+ // src/shortcuts/fna/index.ts
1347
+ function asOptions(value) {
1348
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
1349
+ }
1350
+ async function readStdin() {
1351
+ const chunks = [];
1352
+ for await (const chunk of process.stdin) {
1353
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
1354
+ }
1355
+ return Buffer.concat(chunks).toString("utf8");
1356
+ }
1357
+ function stripBom(value) {
1358
+ return value.replace(/^\uFEFF+/, "");
1359
+ }
1360
+ async function inputFrom(options, extra = {}) {
1361
+ const opts = asOptions(options);
1362
+ let input = {};
1363
+ if (opts.input && opts.inputJson) {
1364
+ throw fnaValidationError("input_conflict", "\u4E0D\u80FD\u540C\u65F6\u4F20 --input \u548C --input-json");
1365
+ }
1366
+ if (opts.inputJson) {
1367
+ input = parseJsonInput(String(opts.inputJson), "--input-json");
1368
+ }
1369
+ if (opts.input) {
1370
+ let raw;
1371
+ try {
1372
+ raw = stripBom(opts.input === "-" ? await readStdin() : await readFile2(String(opts.input), "utf8"));
1373
+ } catch {
1374
+ throw fnaValidationError("input_unreadable", `\u65E0\u6CD5\u8BFB\u53D6 --input\uFF1A${String(opts.input)}`);
1375
+ }
1376
+ input = parseJsonInput(raw, "--input");
1377
+ }
1378
+ return {
1379
+ ...input,
1380
+ ...Object.fromEntries(Object.entries(extra).filter(([, value]) => value !== void 0 && value !== ""))
1381
+ };
1382
+ }
1383
+ function parseJsonInput(raw, label) {
1384
+ try {
1385
+ const parsed = JSON.parse(stripBom(raw));
1386
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1387
+ throw new Error("input must be an object");
1388
+ }
1389
+ return parsed;
1390
+ } catch {
1391
+ throw fnaValidationError("input_invalid", `${label} \u4E0D\u662F\u5408\u6CD5 JSON \u5BF9\u8C61`);
1392
+ }
1393
+ }
1394
+ function successEnvelope(operation, result) {
1395
+ return {
1396
+ schemaVersion: 1,
1397
+ ok: true,
1398
+ operation,
1399
+ data: result.data === void 0 ? null : result.data,
1400
+ ...result.meta ? { meta: result.meta } : {},
1401
+ warnings: []
1402
+ };
1403
+ }
1404
+ function failureEnvelope(error) {
1405
+ const structured = error;
1406
+ return {
1407
+ schemaVersion: 1,
1408
+ ok: false,
1409
+ ...structured?.partialData === void 0 ? {} : { data: structured.partialData },
1410
+ error: toErrorEnvelope(error)
1411
+ };
1412
+ }
1413
+ async function executeAndPrint(ctx, operation, input) {
1414
+ try {
1415
+ const result = await executeFnaOperation(operation, input, {
1416
+ ctx,
1417
+ host: createFnaHost(ctx),
1418
+ continuation: createFnaContinuationSigner(ctx)
1419
+ });
1420
+ ctx.output.write(successEnvelope(operation, result), { json: true });
1421
+ } catch (error) {
1422
+ console.error(JSON.stringify(failureEnvelope(error), null, 2));
1423
+ process.exitCode = isCliError(error) ? error.exitCode : 1 /* GeneralError */;
1424
+ }
1425
+ }
1426
+ var fnaShortcut = {
1427
+ name: "fna",
1428
+ description: "\u6CDB\u5FAEE10\u9F50\u4E1A\u6210\u8D39\u63A7\u4E2D\u5FC3\uFF08\u9884\u7B97/\u8D39\u7528\u4E2D\u5FC3/\u501F\u6B3E\u7BA1\u7406/\u53D1\u7968\u6838\u9500\uFF09CLI",
1429
+ category: "shortcut",
1430
+ register({ program, action }) {
1431
+ const fna = program.command("fna").description("\u6CDB\u5FAEE10\u9F50\u4E1A\u6210\u8D39\u63A7\u4E2D\u5FC3\uFF08\u9884\u7B97\u67E5\u8BE2/\u8D39\u7528\u4E2D\u5FC3/\u501F\u6B3E\u7BA1\u7406/\u53D1\u7968\u6838\u9500\uFF09");
1432
+ fna.command("schema").description("Print fna operation manifest for agents").action(action((ctx) => {
1433
+ ctx.output.write(fnaManifest, { json: true });
1434
+ }));
1435
+ fna.command("run").description("Run an fna operation with JSON input").argument("<operation>", "operation name, e.g. fna.expense.reimbursed.sum").option("--input <path>", "JSON input file, or - for stdin").option("--input-json <json>", "inline JSON input object").action(action(async (ctx, operation, options) => {
1436
+ await executeAndPrint(ctx, String(operation), await inputFrom(options));
1437
+ }));
1438
+ }
1439
+ };
1440
+ export {
1441
+ fnaShortcut,
1442
+ inputFrom,
1443
+ successEnvelope
1444
+ };