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,1615 @@
1
+ import { createRequire as __esbuildCreateRequire } from 'node:module';
2
+ const require = __esbuildCreateRequire(import.meta.url);
3
+ import {
4
+ CliError
5
+ } from "./chunk-LUSPKZKY.js";
6
+
7
+ // src/internal/e10/auth/session.ts
8
+ import { constants, createDecipheriv as createDecipheriv2, createHash, publicEncrypt } from "node:crypto";
9
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync, unlinkSync } from "node:fs";
10
+ import { dirname, resolve as resolve3 } from "node:path";
11
+
12
+ // src/core/connector.ts
13
+ var CONNECTOR_PROFILE = "eteams";
14
+ function isConnectorEnabled(value) {
15
+ if (value === void 0 || value === null || value === false) return false;
16
+ if (value === true) return true;
17
+ const normalized = String(value).trim().toLowerCase();
18
+ return normalized === "" || normalized === "true" || normalized === "1" || normalized === "yes";
19
+ }
20
+ var connectorMode = false;
21
+ function isConnectorMode() {
22
+ return connectorMode;
23
+ }
24
+ function normalizeGlobalOptions(options) {
25
+ if (!isConnectorEnabled(options.isConnector)) {
26
+ connectorMode = false;
27
+ return options;
28
+ }
29
+ connectorMode = true;
30
+ return { ...options, profile: CONNECTOR_PROFILE };
31
+ }
32
+
33
+ // src/core/write-with-retry.ts
34
+ import { writeFileSync } from "node:fs";
35
+ var RETRIABLE_WRITE_ERRORS = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY", "ENOTEMPTY"]);
36
+ function sleepSync(ms) {
37
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
38
+ }
39
+ function writeWithRetry(path, data, options) {
40
+ const maxAttempts = 4;
41
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
42
+ try {
43
+ writeFileSync(path, data, options);
44
+ return;
45
+ } catch (error) {
46
+ const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
47
+ if (!RETRIABLE_WRITE_ERRORS.has(code) || attempt === maxAttempts - 1) {
48
+ throw error;
49
+ }
50
+ sleepSync(80 * (attempt + 1));
51
+ }
52
+ }
53
+ }
54
+
55
+ // src/internal/e10/auth/crypto.ts
56
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
57
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
58
+ import { createRequire } from "node:module";
59
+ import { resolve as resolve2 } from "node:path";
60
+
61
+ // src/internal/e10/auth/paths.ts
62
+ import { homedir } from "node:os";
63
+ import { resolve } from "node:path";
64
+ function getE10AuthRoot() {
65
+ const override = process.env.WEAVER_WORK_CLI_AUTH_ROOT?.trim();
66
+ return override ? resolve(override) : resolve(homedir(), ".weaver-work-cli", "e10");
67
+ }
68
+ function getE10ProfilesRoot() {
69
+ return resolve(getE10AuthRoot(), "profiles");
70
+ }
71
+ function getE10ActiveProfilePath() {
72
+ return resolve(getE10AuthRoot(), "profile");
73
+ }
74
+
75
+ // src/internal/e10/auth/crypto.ts
76
+ var ALGORITHM = "aes-256-gcm";
77
+ var IV_LENGTH = 12;
78
+ var TAG_LENGTH = 16;
79
+ var KEYCHAIN_SERVICE = "weaver-work-cli";
80
+ var KEYCHAIN_ACCOUNT = "auth-key";
81
+ var require2 = createRequire(import.meta.url);
82
+ var encKey = null;
83
+ var keyringEntryConstructor;
84
+ function getKeyFilePath() {
85
+ return resolve2(getE10AuthRoot(), ".key");
86
+ }
87
+ function loadKeyringEntryConstructor() {
88
+ if (keyringEntryConstructor !== void 0) return keyringEntryConstructor;
89
+ try {
90
+ const module = require2("@napi-rs/keyring");
91
+ keyringEntryConstructor = typeof module.Entry === "function" ? module.Entry : null;
92
+ } catch {
93
+ keyringEntryConstructor = null;
94
+ }
95
+ return keyringEntryConstructor;
96
+ }
97
+ function readKeychainKey(service) {
98
+ const KeyringEntry = loadKeyringEntryConstructor();
99
+ if (!KeyringEntry) return null;
100
+ try {
101
+ const entry = new KeyringEntry(service, KEYCHAIN_ACCOUNT);
102
+ const stored = entry.getPassword();
103
+ if (stored && /^[A-Za-z0-9+/=]{40,}$/.test(stored)) {
104
+ const key = Buffer.from(stored, "base64");
105
+ if (key.length === 32) return key;
106
+ }
107
+ } catch {
108
+ }
109
+ return null;
110
+ }
111
+ function writeKeychainKey(service, key) {
112
+ const KeyringEntry = loadKeyringEntryConstructor();
113
+ if (!KeyringEntry) return false;
114
+ try {
115
+ const entry = new KeyringEntry(service, KEYCHAIN_ACCOUNT);
116
+ entry.setPassword(key.toString("base64"));
117
+ return true;
118
+ } catch {
119
+ return false;
120
+ }
121
+ }
122
+ function readKeyFile(filePath) {
123
+ if (!existsSync(filePath)) return null;
124
+ try {
125
+ const key = Buffer.from(readFileSync(filePath, "utf-8").trim(), "base64");
126
+ return key.length === 32 ? key : null;
127
+ } catch {
128
+ return null;
129
+ }
130
+ }
131
+ function getEncKey() {
132
+ if (encKey) return encKey;
133
+ const storedKey = readKeychainKey(KEYCHAIN_SERVICE);
134
+ if (storedKey) {
135
+ encKey = storedKey;
136
+ return encKey;
137
+ }
138
+ const keyFile = getKeyFilePath();
139
+ const fileKey = readKeyFile(keyFile);
140
+ if (fileKey) {
141
+ encKey = fileKey;
142
+ return encKey;
143
+ }
144
+ const fresh = randomBytes(32);
145
+ if (writeKeychainKey(KEYCHAIN_SERVICE, fresh)) {
146
+ encKey = fresh;
147
+ return encKey;
148
+ }
149
+ encKey = fresh;
150
+ mkdirSync(getE10AuthRoot(), { recursive: true });
151
+ writeWithRetry(keyFile, encKey.toString("base64"), { mode: 384 });
152
+ return encKey;
153
+ }
154
+ function encryptAuthData(plaintext) {
155
+ const iv = randomBytes(IV_LENGTH);
156
+ const cipher = createCipheriv(ALGORITHM, getEncKey(), iv, { authTagLength: TAG_LENGTH });
157
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf-8"), cipher.final()]);
158
+ const tag = cipher.getAuthTag();
159
+ const combined = Buffer.concat([iv, encrypted, tag]);
160
+ return { enc: true, v: 1, data: combined.toString("base64") };
161
+ }
162
+ function decryptAuthData(wrapper) {
163
+ const combined = Buffer.from(wrapper.data, "base64");
164
+ if (combined.length < IV_LENGTH + TAG_LENGTH + 1) return null;
165
+ const iv = combined.subarray(0, IV_LENGTH);
166
+ const tag = combined.subarray(combined.length - TAG_LENGTH);
167
+ const encrypted = combined.subarray(IV_LENGTH, combined.length - TAG_LENGTH);
168
+ try {
169
+ const decipher = createDecipheriv(ALGORITHM, getEncKey(), iv, { authTagLength: TAG_LENGTH });
170
+ decipher.setAuthTag(tag);
171
+ return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString("utf-8");
172
+ } catch {
173
+ return null;
174
+ }
175
+ }
176
+ function parseAuthFile(raw) {
177
+ try {
178
+ const parsed = JSON.parse(raw);
179
+ if (parsed.enc === true && typeof parsed.data === "string") {
180
+ const decrypted = decryptAuthData(parsed);
181
+ if (!decrypted) return null;
182
+ return JSON.parse(decrypted);
183
+ }
184
+ if (parsed.cookies && parsed.userId) return parsed;
185
+ return null;
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+
191
+ // src/internal/e10/auth/session.ts
192
+ var RSA_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
193
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCEOk/WyyJKdAHIfMODFnKg7MBoraFBnL3F18hhLx5n01J5g4hCkmpc5+KQFKIQIA/QWk9m7QBzI/OV9ZDFk54LaWm3xP8C+P1TPp7UVGz3iNDLdvgSxuGEYPmML3NaqkbVlvW7/NlNA3ED4Kao7rR5GUYSdFfbaBoxBFae638hzQIDAQAB
194
+ -----END PUBLIC KEY-----`;
195
+ var AES_SEED = "yoJXYSzZhAOpbEFJklGtqd74X2ChTKOL";
196
+ function sha1(data) {
197
+ return createHash("sha1").update(data).digest();
198
+ }
199
+ function getAesKey() {
200
+ const h = sha1(sha1(Buffer.from(AES_SEED))).toString("hex").slice(0, 32);
201
+ return Buffer.from(h, "hex");
202
+ }
203
+ function decryptAES(key, encryptedHex) {
204
+ const encrypted = Buffer.from(encryptedHex, "hex");
205
+ const decipher = createDecipheriv2("aes-128-ecb", key, null);
206
+ decipher.setAutoPadding(true);
207
+ return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString("utf-8");
208
+ }
209
+ async function fetchPublicKey(baseUrl, passportUrl) {
210
+ try {
211
+ const url = `${passportUrl}/papi/passport/info/getUrlInfo?type=login&service=${encodeURIComponent(baseUrl)}`;
212
+ const resp = await fetch(url, {
213
+ headers: {
214
+ accept: "application/json",
215
+ langtype: "zh_CN",
216
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
217
+ }
218
+ });
219
+ if (resp.status !== 200) return null;
220
+ const data = await resp.json();
221
+ if (data.code !== 200 || !data.data?.publicKey) return null;
222
+ const decrypted = decryptAES(getAesKey(), data.data.publicKey);
223
+ return "-----BEGIN PUBLIC KEY-----\n" + decrypted + "\n-----END PUBLIC KEY-----";
224
+ } catch {
225
+ return null;
226
+ }
227
+ }
228
+ function getActiveProfile() {
229
+ const activeProfileFile = getE10ActiveProfilePath();
230
+ try {
231
+ if (existsSync2(activeProfileFile)) {
232
+ const name = readFileSync2(activeProfileFile, "utf-8").trim();
233
+ if (name) return name;
234
+ }
235
+ } catch {
236
+ }
237
+ return "default";
238
+ }
239
+ function setActiveProfile(name) {
240
+ if (isConnectorMode()) return;
241
+ switchActiveProfile(name);
242
+ }
243
+ function switchActiveProfile(name) {
244
+ mkdirSync2(getE10ProfilesRoot(), { recursive: true });
245
+ mkdirSync2(resolve3(getE10ProfilesRoot(), name), { recursive: true });
246
+ writeWithRetry(getE10ActiveProfilePath(), name, "utf-8");
247
+ }
248
+ function listProfiles() {
249
+ try {
250
+ if (!existsSync2(getE10ProfilesRoot())) return [];
251
+ return readdirSync(getE10ProfilesRoot(), { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
252
+ } catch {
253
+ return [];
254
+ }
255
+ }
256
+ function getProfileDir(name) {
257
+ return resolve3(getE10ProfilesRoot(), name);
258
+ }
259
+ function getProfileAuthPath(name) {
260
+ return resolve3(getProfileDir(name), "auth");
261
+ }
262
+ function getProfileConfigPath(name) {
263
+ return resolve3(getProfileDir(name), "config.json");
264
+ }
265
+ var MULTI_LABEL_PUBLIC_SUFFIXES = /* @__PURE__ */ new Set([
266
+ "com.cn",
267
+ "net.cn",
268
+ "org.cn",
269
+ "gov.cn",
270
+ "edu.cn",
271
+ "ac.cn",
272
+ "com.hk",
273
+ "net.hk",
274
+ "org.hk",
275
+ "edu.hk",
276
+ "gov.hk",
277
+ "com.tw",
278
+ "net.tw",
279
+ "org.tw",
280
+ "edu.tw",
281
+ "gov.tw",
282
+ "com.mo",
283
+ "net.mo",
284
+ "org.mo",
285
+ "edu.mo",
286
+ "gov.mo",
287
+ "co.uk",
288
+ "org.uk",
289
+ "me.uk",
290
+ "ac.uk",
291
+ "gov.uk",
292
+ "co.jp",
293
+ "ne.jp",
294
+ "or.jp",
295
+ "ac.jp",
296
+ "go.jp",
297
+ "com.au",
298
+ "net.au",
299
+ "org.au",
300
+ "co.nz",
301
+ "net.nz",
302
+ "com.sg",
303
+ "com.my",
304
+ "com.br",
305
+ "com.mx",
306
+ "com.tr"
307
+ ]);
308
+ function profileNameFromUrl(baseUrl) {
309
+ try {
310
+ const host = new URL(baseUrl).hostname.toLowerCase();
311
+ if (!host) return "default";
312
+ if (/^(\d{1,3}\.){3}\d{1,3}$/u.test(host)) return host.replace(/[^0-9a-z]+/gu, "-");
313
+ const parts = host.split(".").filter(Boolean);
314
+ if (parts.length <= 1) return parts[0] || "default";
315
+ const hasMultiLabelSuffix = parts.length >= 3 && MULTI_LABEL_PUBLIC_SUFFIXES.has(parts.slice(-2).join("."));
316
+ const index = hasMultiLabelSuffix ? parts.length - 3 : parts.length - 2;
317
+ return parts[index] || parts[0] || "default";
318
+ } catch {
319
+ return "default";
320
+ }
321
+ }
322
+ function readProfileConfig(profile = getActiveProfile()) {
323
+ const configPath = getProfileConfigPath(profile);
324
+ if (existsSync2(configPath)) {
325
+ try {
326
+ return JSON.parse(readFileSync2(configPath, "utf-8"));
327
+ } catch {
328
+ return {};
329
+ }
330
+ }
331
+ return {};
332
+ }
333
+ function saveProfileConfig(baseUrl, passportUrl, profile = getActiveProfile(), tenantKey) {
334
+ const configPath = getProfileConfigPath(profile);
335
+ mkdirSync2(dirname(configPath), { recursive: true });
336
+ writeWithRetry(configPath, JSON.stringify({ baseUrl, passportUrl, tenantKey }, null, 2) + "\n", { mode: 384 });
337
+ }
338
+ function saveAuthFile(data, profile = getActiveProfile()) {
339
+ const authPath = getProfileAuthPath(profile);
340
+ mkdirSync2(dirname(authPath), { recursive: true });
341
+ writeWithRetry(authPath, JSON.stringify(encryptAuthData(JSON.stringify(data))), { mode: 384 });
342
+ return authPath;
343
+ }
344
+ function clearProfileAuthFile(profile = getActiveProfile()) {
345
+ const authFile = getProfileAuthPath(profile);
346
+ if (!existsSync2(authFile)) return { profile, authFile, cleared: false };
347
+ unlinkSync(authFile);
348
+ return { profile, authFile, cleared: true };
349
+ }
350
+ function findAuthFile(startDir = process.cwd(), options = {}) {
351
+ if (options.auth) return options.auth;
352
+ if (options.profile) {
353
+ const profileAuth = getProfileAuthPath(options.profile);
354
+ if (existsSync2(profileAuth)) return profileAuth;
355
+ }
356
+ const envAuth = process.env.E10_AUTH_PATH;
357
+ if (envAuth && existsSync2(envAuth)) return envAuth;
358
+ const activeProfileAuth = getProfileAuthPath(getActiveProfile());
359
+ if (existsSync2(activeProfileAuth)) return activeProfileAuth;
360
+ return null;
361
+ }
362
+ function asRecord(value) {
363
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
364
+ }
365
+ function readTeamsCheckUserInfo(resp, data) {
366
+ const root = asRecord(data);
367
+ const nested = asRecord(root.data);
368
+ const currentUser = asRecord(root.currentUser || nested.currentUser);
369
+ const currentTenant = asRecord(root.currentTenant || nested.currentTenant);
370
+ const department = asRecord(currentUser.department);
371
+ const position = asRecord(currentUser.position);
372
+ const userId = resp.headers.get("employeeId") || currentUser.employeeId || currentUser.id || nested.employeeId || root.employeeId || "";
373
+ const tenantKey = currentUser.tenantKey || currentTenant.tenantKey || nested.tenantKey || nested.tenantkey || root.tenantKey || root.tenantkey || "";
374
+ return {
375
+ userId: String(userId || ""),
376
+ tenantKey: String(tenantKey || ""),
377
+ tenantName: String(currentTenant.tenantName || currentTenant.name || ""),
378
+ department: String(department.name || ""),
379
+ subcompany: String(root.subCompanyName || nested.subCompanyName || ""),
380
+ position: String(position.name || "")
381
+ };
382
+ }
383
+ function buildE10CookieHeader(rawCookie, eteamsId, agentType = "") {
384
+ let cookie = rawCookie || "";
385
+ if (cookie) {
386
+ if (/ETEAMSID=/.test(cookie)) {
387
+ cookie = cookie.replace(/ETEAMSID=[^;]+/, `ETEAMSID=${eteamsId}`);
388
+ } else if (eteamsId) {
389
+ cookie += `; ETEAMSID=${eteamsId}`;
390
+ }
391
+ } else if (eteamsId) {
392
+ cookie = `ETEAMSID=${eteamsId}`;
393
+ }
394
+ if (agentType && !/agentType=/.test(cookie)) {
395
+ cookie = cookie ? `${cookie}; agentType=${agentType}` : `agentType=${agentType}`;
396
+ }
397
+ if (!/isAgent=/.test(cookie)) {
398
+ cookie = cookie ? `${cookie}; isAgent=true` : "isAgent=true";
399
+ }
400
+ return cookie;
401
+ }
402
+ function splitSetCookie(value) {
403
+ return value.split(/,\s*(?=[^;,]+=)/).filter(Boolean);
404
+ }
405
+ function extractRawSetCookie(resp) {
406
+ const headers = resp.headers;
407
+ const setCookies = headers.getSetCookie?.() || splitSetCookie(headers.get("set-cookie") || "");
408
+ return setCookies.map((cookie) => cookie.split(";")[0]).filter(Boolean).join("; ");
409
+ }
410
+ function extractSessionTicket(...sources) {
411
+ for (const source of sources) {
412
+ if (!source) continue;
413
+ const match = source.match(/(?:^|;\s*)ZT_SESSION=([^;]+)/u);
414
+ if (match?.[1]) return match[1];
415
+ }
416
+ return "";
417
+ }
418
+ function readSessionTicketExpiry(ticket) {
419
+ const payload = ticket.split(".")[1];
420
+ if (!payload) return null;
421
+ try {
422
+ const data = JSON.parse(Buffer.from(payload, "base64url").toString("utf-8"));
423
+ const exp = Number(data?.exp);
424
+ return Number.isFinite(exp) && exp > 0 ? exp : null;
425
+ } catch {
426
+ return null;
427
+ }
428
+ }
429
+ function usableSessionTicket(ticket) {
430
+ const trimmed = (ticket || "").trim();
431
+ if (!trimmed) return "";
432
+ const exp = readSessionTicketExpiry(trimmed);
433
+ if (exp !== null && exp * 1e3 <= Date.now()) return "";
434
+ return trimmed;
435
+ }
436
+ function hasUsableUserId(session) {
437
+ const id = session.userId;
438
+ return Boolean(id) && id !== "unknown";
439
+ }
440
+ var E10AuthSession = class _E10AuthSession {
441
+ constructor(data, filePath = null, baseUrlFallback, passportUrlFallback) {
442
+ this.filePath = filePath;
443
+ this.data = data;
444
+ this.data.baseUrl = this.data.baseUrl || baseUrlFallback || "";
445
+ this.data.passportUrl = this.data.passportUrl || passportUrlFallback || this.data.baseUrl;
446
+ }
447
+ filePath;
448
+ data;
449
+ get cookies() {
450
+ return this.data.cookies || {};
451
+ }
452
+ get eteamsId() {
453
+ return this.cookies.ETEAMSID || "";
454
+ }
455
+ get userId() {
456
+ return this.data.userId || "";
457
+ }
458
+ get tenantKey() {
459
+ return this.data.tenantKey || "";
460
+ }
461
+ get tenantName() {
462
+ return this.data.tenantName || "";
463
+ }
464
+ get department() {
465
+ return this.data.department || "";
466
+ }
467
+ get subcompany() {
468
+ return this.data.subcompany || "";
469
+ }
470
+ get position() {
471
+ return this.data.position || "";
472
+ }
473
+ get agentType() {
474
+ return this.data.agentType || this.data.agent_type || "";
475
+ }
476
+ get version() {
477
+ return this.data.version || this.data.baselineVersion || "";
478
+ }
479
+ get loginSource() {
480
+ return this.data.loginSource || "";
481
+ }
482
+ get credentialSourceStep() {
483
+ return this.data.credentialSourceStep;
484
+ }
485
+ get credentialSourceType() {
486
+ return this.data.credentialSourceType || "";
487
+ }
488
+ get credentialSourceLabel() {
489
+ return this.data.credentialSourceLabel || "";
490
+ }
491
+ getBaseUrl() {
492
+ return (this.data.baseUrl || "").replace(/\/$/, "");
493
+ }
494
+ getPassportUrl() {
495
+ return (this.data.passportUrl || this.getBaseUrl()).replace(/\/$/, "");
496
+ }
497
+ cookieHeader() {
498
+ const raw = this.cookies.raw || "";
499
+ return buildE10CookieHeader(raw, this.eteamsId, this.agentType);
500
+ }
501
+ /** 在 `cookieHeader()` 基础上附加网关会话票据(`ZT_SESSION`)。
502
+ *
503
+ * **只在票存在、非空且未过期时才追加**:没有票(老 auth 文件/网关未下发 set-cookie/set-cookie 为空)
504
+ * 或票已过期时,返回值与 `cookieHeader()` **逐字节相同** ⇒ 未受惠也算不上回退。
505
+ * 是否使用本方法由调用方决定(目前只有流程侧,见 `E10RequestRuntimeDependencies.attachSessionTicket`)。 */
506
+ cookieHeaderWithSessionTicket() {
507
+ const base = this.cookieHeader();
508
+ const ticket = usableSessionTicket(this.data.ztSession);
509
+ return ticket ? `${base}; ZT_SESSION=${ticket}` : base;
510
+ }
511
+ uaHeader() {
512
+ return this.agentType ? `AgentType=${this.agentType},IsAgent=true` : "weaver-work-cli";
513
+ }
514
+ /**
515
+ * Adopt a freshly authenticated session in place. Hosts cache this object for
516
+ * the lifetime of one command, so mutating it keeps every subsequent request
517
+ * on the refreshed credential without exposing or re-reading auth data.
518
+ */
519
+ replaceWith(session) {
520
+ this.data = { ...session.data, cookies: { ...session.data.cookies } };
521
+ }
522
+ toJSON() {
523
+ const sourceInfo = {
524
+ ...this.loginSource ? { loginSource: this.loginSource } : {},
525
+ ...this.credentialSourceStep ? { credentialSourceStep: this.credentialSourceStep } : {},
526
+ ...this.credentialSourceType ? { credentialSourceType: this.credentialSourceType } : {},
527
+ ...this.credentialSourceLabel ? { credentialSourceLabel: this.credentialSourceLabel } : {}
528
+ };
529
+ return {
530
+ userId: this.userId,
531
+ tenantKey: this.tenantKey,
532
+ tenantName: this.tenantName,
533
+ department: this.department,
534
+ subcompany: this.subcompany,
535
+ position: this.position,
536
+ agentType: this.agentType,
537
+ version: this.version,
538
+ baseUrl: this.getBaseUrl(),
539
+ passportUrl: this.getPassportUrl(),
540
+ stTicket: this.data.stTicket,
541
+ redirectUrl: this.data.redirectUrl,
542
+ cookieSavedAt: this.data.cookieSavedAt,
543
+ mainUrl: this.data.mainUrl,
544
+ ...sourceInfo,
545
+ hasEteamsId: Boolean(this.eteamsId)
546
+ };
547
+ }
548
+ static fromFile(filePath, baseUrlFallback, passportUrlFallback) {
549
+ try {
550
+ const raw = readFileSync2(filePath, "utf-8");
551
+ const data = parseAuthFile(raw);
552
+ if (!data || !data.cookies?.ETEAMSID || !data.baseUrl) return null;
553
+ return new _E10AuthSession(data, filePath, baseUrlFallback, passportUrlFallback);
554
+ } catch {
555
+ return null;
556
+ }
557
+ }
558
+ static async fromOptions(options, startDir = process.cwd(), load = {}) {
559
+ let baseUrl = options.baseUrl;
560
+ let passportUrl = options.passportUrl;
561
+ if (options.profile) {
562
+ const cfg = readProfileConfig(options.profile);
563
+ baseUrl ||= cfg.baseUrl;
564
+ passportUrl ||= cfg.passportUrl;
565
+ }
566
+ const authPath = findAuthFile(startDir, options);
567
+ if (!authPath) return null;
568
+ const session = _E10AuthSession.fromFile(authPath, baseUrl, passportUrl);
569
+ if (session && !(load.skipProfileEnrichment && hasUsableUserId(session))) {
570
+ await session.fetchEmployeeId();
571
+ }
572
+ return session;
573
+ }
574
+ async fetchEmployeeId() {
575
+ try {
576
+ const resp = await fetch(
577
+ `${this.getBaseUrl()}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(this.getBaseUrl())}`,
578
+ {
579
+ method: "POST",
580
+ headers: {
581
+ accept: "application/json",
582
+ "content-type": "application/json",
583
+ eteamsid: this.eteamsId,
584
+ cookie: this.cookieHeader(),
585
+ "user-agent": this.uaHeader(),
586
+ origin: this.getBaseUrl()
587
+ }
588
+ }
589
+ );
590
+ const data = await resp.json().catch(() => ({}));
591
+ const userInfo = readTeamsCheckUserInfo(resp, data);
592
+ if (userInfo.userId && userInfo.userId !== this.data.userId) this.data.userId = userInfo.userId;
593
+ if (userInfo.tenantKey) this.data.tenantKey = userInfo.tenantKey;
594
+ if (userInfo.tenantName) this.data.tenantName = userInfo.tenantName;
595
+ if (userInfo.department) this.data.department = userInfo.department;
596
+ if (userInfo.subcompany) this.data.subcompany = userInfo.subcompany;
597
+ if (userInfo.position) this.data.position = userInfo.position;
598
+ } catch {
599
+ }
600
+ }
601
+ async checkValid() {
602
+ try {
603
+ const resp = await fetch(`${this.getBaseUrl()}/api/ecode/tree/list?parentId=0`, {
604
+ headers: {
605
+ accept: "application/json",
606
+ eteamsid: this.eteamsId,
607
+ cookie: this.cookieHeader(),
608
+ "user-agent": this.uaHeader()
609
+ },
610
+ redirect: "manual"
611
+ });
612
+ return resp.status === 200;
613
+ } catch {
614
+ return false;
615
+ }
616
+ }
617
+ async ensureValid() {
618
+ if (await this.checkValid()) return true;
619
+ const account = process.env.E10_ACCOUNT;
620
+ const password = process.env.E10_PASSWORD;
621
+ if (!account || !password) return false;
622
+ await this.rsaLogin(account, password);
623
+ this.save();
624
+ return true;
625
+ }
626
+ async rsaLogin(account, password) {
627
+ const passport = this.getPassportUrl();
628
+ const base = this.getBaseUrl();
629
+ const pem = await fetchPublicKey(base, passport) || RSA_PUBLIC_KEY_PEM;
630
+ const enc = (value) => publicEncrypt(
631
+ { key: pem, padding: constants.RSA_PKCS1_PADDING },
632
+ Buffer.from(value, "utf-8")
633
+ ).toString("base64");
634
+ const resp = await fetch(`${passport}/papi/passport/login/pclogin`, {
635
+ method: "POST",
636
+ headers: {
637
+ accept: "application/json, text/plain, */*",
638
+ "content-type": "application/json;charset=UTF-8",
639
+ langtype: "zh_CN",
640
+ origin: passport
641
+ },
642
+ body: JSON.stringify({
643
+ account: enc(account),
644
+ password: enc(password),
645
+ service: base,
646
+ tenantKey: "all_teams",
647
+ teamsInfo: JSON.stringify({ urlSearchParams: `?service=${encodeURIComponent(base)}` }),
648
+ passportCusLoginDomain: passport,
649
+ serviceToken: "",
650
+ auxiliaryToken: "",
651
+ language: "zh_CN",
652
+ onlySelfTenant: 0,
653
+ loginRedirectUrl: "",
654
+ devType: "72",
655
+ registerDataSource: "",
656
+ registerSource: "",
657
+ registerSourceUrl: "",
658
+ moduleSource: "",
659
+ integratedLoginId: "",
660
+ agreementChecked: "0",
661
+ needPassword: true
662
+ }),
663
+ redirect: "manual"
664
+ });
665
+ const result = await resp.json();
666
+ if (result.code !== 200 || !result.status || !result.data?.stTicket) {
667
+ throw new CliError(result.msg || "E10 RSA login failed", 3 /* AuthError */);
668
+ }
669
+ const ticketResp = await fetch(`${base}/papi/baseserver/layout/checkTicket`, {
670
+ method: "POST",
671
+ headers: {
672
+ accept: "application/json",
673
+ "content-type": "application/json",
674
+ origin: base
675
+ },
676
+ body: JSON.stringify({ ticket: result.data.stTicket, service: base }),
677
+ redirect: "manual"
678
+ });
679
+ const headers = ticketResp.headers;
680
+ const setCookies = headers.getSetCookie?.() || [];
681
+ const cookies = {};
682
+ for (const cookie of setCookies) {
683
+ const match = cookie.match(/^([^=]+)=([^;]+)/);
684
+ if (match) cookies[match[1].trim()] = match[2];
685
+ }
686
+ const rawCookie = extractRawSetCookie(ticketResp);
687
+ if (rawCookie) cookies.raw = rawCookie;
688
+ const ticketData = await ticketResp.json().catch(() => ({}));
689
+ const userInfo = readTeamsCheckUserInfo(ticketResp, ticketData);
690
+ this.data = {
691
+ cookies,
692
+ userId: userInfo.userId || account,
693
+ tenantKey: userInfo.tenantKey || this.tenantKey,
694
+ tenantName: userInfo.tenantName,
695
+ department: userInfo.department,
696
+ subcompany: userInfo.subcompany,
697
+ position: userInfo.position,
698
+ baseUrl: base,
699
+ passportUrl: passport,
700
+ stTicket: "",
701
+ redirectUrl: "",
702
+ cookieSavedAt: Date.now()
703
+ };
704
+ }
705
+ save() {
706
+ if (!this.filePath) return;
707
+ writeWithRetry(this.filePath, JSON.stringify(encryptAuthData(JSON.stringify(this.data))), { mode: 384 });
708
+ }
709
+ };
710
+
711
+ // src/internal/e10/auth/messages.ts
712
+ var E10_REAUTH_GUIDANCE = "\u8BF7\u7ED3\u5408\u5F53\u524D\u5BBF\u4E3B\u73AF\u5883\u9009\u62E9\u5408\u9002\u7684\u767B\u5F55\u65B9\u5F0F\uFF0C\u6062\u590D\u767B\u5F55\u540E\u91CD\u8BD5\u539F\u8BF7\u6C42\u3002";
713
+ var E10_AUTH_REQUIRED_MESSAGE = `E10 \u767B\u5F55\u6001\u4E0D\u53EF\u7528\u3002${E10_REAUTH_GUIDANCE}`;
714
+ var E10_SESSION_EXPIRED_MESSAGE = `E10 \u767B\u5F55\u6001\u5DF2\u5931\u6548\uFF0C\u672C\u6B21\u64CD\u4F5C\u5DF2\u505C\u6B62\u3002${E10_REAUTH_GUIDANCE}`;
715
+
716
+ // src/core/package-paths.ts
717
+ import { existsSync as existsSync3, realpathSync } from "node:fs";
718
+ import { dirname as dirname2, join, resolve as resolve4 } from "node:path";
719
+ import { fileURLToPath, pathToFileURL } from "node:url";
720
+ var cachedRoot;
721
+ function entryDirectory(entry) {
722
+ const absoluteEntry = resolve4(entry);
723
+ try {
724
+ return dirname2(realpathSync(absoluteEntry));
725
+ } catch {
726
+ return dirname2(absoluteEntry);
727
+ }
728
+ }
729
+ function packageRootDir() {
730
+ if (cachedRoot) return cachedRoot;
731
+ const seeds = [];
732
+ const entry = process.argv[1];
733
+ if (entry) seeds.push(entryDirectory(entry));
734
+ seeds.push(dirname2(fileURLToPath(import.meta.url)));
735
+ for (const seed of seeds) {
736
+ let dir = seed;
737
+ for (let depth = 0; depth < 10; depth += 1) {
738
+ if (existsSync3(join(dir, "package.json"))) {
739
+ cachedRoot = dir;
740
+ return dir;
741
+ }
742
+ const parent = dirname2(dir);
743
+ if (parent === dir) break;
744
+ dir = parent;
745
+ }
746
+ }
747
+ cachedRoot = process.cwd();
748
+ return cachedRoot;
749
+ }
750
+ function packagePath(...segments) {
751
+ return join(packageRootDir(), ...segments);
752
+ }
753
+ function packageFileUrl(...segments) {
754
+ return pathToFileURL(packagePath(...segments));
755
+ }
756
+
757
+ // src/internal/e10/auth/xiaoe.ts
758
+ import { execFile } from "node:child_process";
759
+ import { accessSync, constants as fsConstants, existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync } from "node:fs";
760
+ import { homedir as homedir2 } from "node:os";
761
+ import { join as join2 } from "node:path";
762
+
763
+ // src/core/runtime-agent.ts
764
+ var XIAOE_RUNTIME_AGENT_ALIASES = /* @__PURE__ */ new Set([
765
+ "xiaoe",
766
+ "xiaoeclient",
767
+ "\u5C0Fe",
768
+ "\u5C0Fe\u5BA2\u6237\u7AEF",
769
+ "\u667A\u80FD\u5C0Fe",
770
+ "\u667A\u80FD\u5C0Fe\u5BA2\u6237\u7AEF"
771
+ ]);
772
+ function normalizeRuntimeAgent(value) {
773
+ if (typeof value !== "string") return "";
774
+ return value.toLowerCase().replace(/[^a-z0-9\p{Script=Han}]+/gu, "");
775
+ }
776
+ function isXiaoERuntimeAgent(value) {
777
+ return XIAOE_RUNTIME_AGENT_ALIASES.has(normalizeRuntimeAgent(value));
778
+ }
779
+ function isXiaoERuntime(options) {
780
+ return isXiaoERuntimeAgent(options?.runtimeAgent);
781
+ }
782
+
783
+ // src/internal/e10/auth/xiaoe.ts
784
+ var DEFAULT_E10_BASE_URL = "https://www.e-cology.com.cn";
785
+ var XIAOE_AGENT_TYPE = "XiaoE";
786
+ var XIAOE_UNIFIED_LOGIN_MAP_ENV_KEYS = [
787
+ "WEAVER_XIAOE_AUTH_MAP",
788
+ "WEAVER_XIAOE_E10_AUTH_MAP",
789
+ "WEAVER_XIAOE_DOMAIN_ETEAMSID_MAP",
790
+ "WEAVER_XIAOE_UNIFIED_LOGIN_MAP",
791
+ "XIAOE_E10_AUTH_MAP",
792
+ "XIAOE_E10_DOMAIN_ETEAMSID_MAP",
793
+ "XIAOE_DOMAIN_ETEAMSID_MAP",
794
+ "XIAOE_UNIFIED_LOGIN_MAP"
795
+ ];
796
+ var XIAOE_SINGLE_DOMAIN_ENV_KEYS = [
797
+ "WEAVER_XIAOE_E10_DOMAIN",
798
+ "WEAVER_XIAOE_BASE_URL",
799
+ "WEAVER_XIAOE_E10_BASE_URL",
800
+ "XIAOE_E10_DOMAIN",
801
+ "XIAOE_BASE_URL",
802
+ "XIAOE_E10_BASE_URL"
803
+ ];
804
+ var XIAOE_DEFAULT_DOMAIN_ENV_KEYS = [
805
+ "WEAVER_XIAOE_DEFAULT_DOMAIN",
806
+ "WEAVER_XIAOE_DEFAULT_BASE_URL",
807
+ "WEAVER_XIAOE_E10_DEFAULT_DOMAIN",
808
+ "WEAVER_XIAOE_E10_DEFAULT_BASE_URL",
809
+ "XIAOE_DEFAULT_DOMAIN",
810
+ "XIAOE_DEFAULT_BASE_URL",
811
+ "XIAOE_E10_DEFAULT_DOMAIN",
812
+ "XIAOE_E10_DEFAULT_BASE_URL"
813
+ ];
814
+ var XIAOE_TOKEN_SCRIPT_ENV_KEY = "WEAVER_XIAOE_TOKEN_SCRIPT_PATH";
815
+ var XIAOE_TOKEN_SCRIPT_PYTHON_ENV_KEY = "WEAVER_XIAOE_TOKEN_SCRIPT_PYTHON";
816
+ var XIAOE_TOKEN_SCRIPT_LEGACY_ENV_KEY = "XIAOE_TOKEN_SCRIPT_PATH";
817
+ var XIAOE_TOKEN_SCRIPT_PYTHON_LEGACY_ENV_KEY = "XIAOE_TOKEN_SCRIPT_PYTHON";
818
+ var XIAOE_TOKEN_SCRIPT_TIMEOUT_MS = 15e3;
819
+ var XIAOE_CLIENT_TOKEN_TIMEOUT_MS = 15e3;
820
+ var XIAOE_USER_SETTINGS_PATH_ENV_KEY = "XIAOE_USER_SETTINGS_PATH";
821
+ var XIAOE_CLIENT_SETTINGS_ROOT_ENV_KEYS = [
822
+ "XIAOE_ROBOT_DATA_ROOT",
823
+ "XIAOE_ROBOT_ROOT"
824
+ ];
825
+ var XIAOE_SKILL_ETEAMID_API_PATH = "/spec-apps/api/app/rpachat/skill/extend/eteamId";
826
+ var XIAOE_CLIENT_SETTINGS_SOURCE = "XiaoE/Robots/user_settings.json";
827
+ var XIAOE_USER_TOKEN_SOURCE = "XIAOE_USER_TOKEN";
828
+ var XIAOE_BUNDLED_ENV_SCRIPT_SOURCE = "bundled scripts/xiaoe_env.py";
829
+ function envString(env, ...keys) {
830
+ for (const key of keys) {
831
+ const value = env[key];
832
+ if (typeof value === "string" && value.trim()) return value.trim();
833
+ }
834
+ return "";
835
+ }
836
+ function hasXiaoEEnv(env = process.env, options = {}) {
837
+ if (isXiaoERuntime(options)) return true;
838
+ if (Object.keys(env).some((key) => key.startsWith("XIAOE_"))) return true;
839
+ const explicitHostAgentType = envString(env, "WORKBUDDY_AGENT_TYPE", "CODEX_AGENT_TYPE");
840
+ if (explicitHostAgentType) return isXiaoERuntimeAgent(explicitHostAgentType);
841
+ if (Object.keys(env).some((key) => key.startsWith("WORKBUDDY_") || key.startsWith("CODEX_"))) {
842
+ return false;
843
+ }
844
+ const explicitAgentType = envString(env, "WEAVER_AGENT_TYPE");
845
+ return explicitAgentType ? isXiaoERuntimeAgent(explicitAgentType) : false;
846
+ }
847
+ function describeXiaoECredentialSource(source) {
848
+ if (source === XIAOE_USER_TOKEN_SOURCE || source === XIAOE_BUNDLED_ENV_SCRIPT_SOURCE) {
849
+ return {
850
+ credentialSourceStep: 1,
851
+ credentialSourceType: "xiaoe_platform",
852
+ credentialSourceLabel: source === XIAOE_BUNDLED_ENV_SCRIPT_SOURCE ? "XiaoE platform user token (bundled Python fallback)" : "XiaoE platform user token"
853
+ };
854
+ }
855
+ if (source === "xiaoeUserData/tokens.py") {
856
+ return {
857
+ credentialSourceStep: 2,
858
+ credentialSourceType: "token_script",
859
+ credentialSourceLabel: "xiaoeUserData/tokens.py"
860
+ };
861
+ }
862
+ if (source === XIAOE_CLIENT_SETTINGS_SOURCE) {
863
+ return {
864
+ credentialSourceStep: 3,
865
+ credentialSourceType: "xiaoe_client",
866
+ credentialSourceLabel: "XiaoE client settings"
867
+ };
868
+ }
869
+ return {
870
+ credentialSourceStep: 4,
871
+ credentialSourceType: "xiaoe_env",
872
+ credentialSourceLabel: "WEAVER_XIAOE_* environment variables"
873
+ };
874
+ }
875
+ function normalizeUrl(value) {
876
+ return value.replace(/\/+$/, "");
877
+ }
878
+ function readString(data, ...keys) {
879
+ for (const key of keys) {
880
+ const value = data[key];
881
+ if (typeof value === "string" && value) return value;
882
+ if (typeof value === "number") return String(value);
883
+ }
884
+ return "";
885
+ }
886
+ function cookieString(value) {
887
+ if (!value) return "";
888
+ if (typeof value === "string") return value;
889
+ if (typeof value === "object" && !Array.isArray(value)) {
890
+ return Object.entries(value).filter(([, cookieValue2]) => cookieValue2 !== void 0 && cookieValue2 !== null && cookieValue2 !== "").map(([name, cookieValue2]) => `${name}=${String(cookieValue2)}`).join("; ");
891
+ }
892
+ return "";
893
+ }
894
+ function cookieValue(rawCookie, name) {
895
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
896
+ const match = rawCookie.match(new RegExp(`(?:^|;\\s*)${escaped}=([^;]+)`));
897
+ return match?.[1] || "";
898
+ }
899
+ function recordCandidates(value) {
900
+ return [
901
+ value,
902
+ value.data,
903
+ value.result,
904
+ value.auth,
905
+ value.session,
906
+ value.e10,
907
+ value.e10Auth,
908
+ value.e10_auth
909
+ ].filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry));
910
+ }
911
+ function normalizeDomainKey(value) {
912
+ const raw = normalizeUrl(value.trim());
913
+ if (!raw) return null;
914
+ try {
915
+ const url = new URL(raw.includes("://") ? raw : `https://${raw}`);
916
+ return {
917
+ raw: raw.toLowerCase(),
918
+ origin: normalizeUrl(url.origin).toLowerCase(),
919
+ host: url.hostname.toLowerCase()
920
+ };
921
+ } catch {
922
+ return {
923
+ raw: raw.toLowerCase(),
924
+ origin: raw.toLowerCase(),
925
+ host: ""
926
+ };
927
+ }
928
+ }
929
+ function domainMatches(baseUrl, candidate) {
930
+ const base = normalizeDomainKey(baseUrl);
931
+ const target = normalizeDomainKey(candidate);
932
+ if (!base || !target) return false;
933
+ return base.origin === target.origin || base.raw === target.raw || Boolean(base.host && target.host && base.host === target.host);
934
+ }
935
+ function readXiaoECredentialRecord(value, source, fallbackBaseUrl = "") {
936
+ const candidates = recordCandidates(value);
937
+ const baseUrl = candidates.map((entry) => readString(entry, "domain", "baseUrl", "base_url", "url", "host", "e10BaseUrl", "e10_base_url")).find(Boolean) || fallbackBaseUrl;
938
+ const rawCookie = candidates.map((entry) => cookieString(entry.cookies || entry.cookie || entry.rawCookie || entry.raw_cookie)).find(Boolean) || "";
939
+ const eteamsId = candidates.map((entry) => readString(entry, "eteamsId", "eteamsid", "ETEAMSID", "eteamId", "eteam_id", "eTeamId", "eteamID", "eteam_id")).find(Boolean) || cookieValue(rawCookie, "ETEAMSID");
940
+ if (!baseUrl || !eteamsId) return null;
941
+ return { baseUrl: normalizeUrl(baseUrl), eteamsId, source, rawCookie };
942
+ }
943
+ function parseXiaoEUnifiedLoginMap(raw, source) {
944
+ const value = raw.trim();
945
+ if (!value) return [];
946
+ try {
947
+ const parsed = JSON.parse(value);
948
+ if (Array.isArray(parsed)) {
949
+ return parsed.map((entry) => entry && typeof entry === "object" && !Array.isArray(entry) ? readXiaoECredentialRecord(entry, source) : null).filter((entry) => Boolean(entry));
950
+ }
951
+ if (parsed && typeof parsed === "object") {
952
+ const record = parsed;
953
+ const direct = readXiaoECredentialRecord(record, source);
954
+ if (direct) return [direct];
955
+ return Object.entries(record).map(([baseUrl, entry]) => {
956
+ if (typeof entry === "string" || typeof entry === "number") {
957
+ return { baseUrl: normalizeUrl(baseUrl), eteamsId: String(entry), source };
958
+ }
959
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) {
960
+ return readXiaoECredentialRecord(entry, source, baseUrl);
961
+ }
962
+ return null;
963
+ }).filter((entry) => Boolean(entry));
964
+ }
965
+ } catch {
966
+ }
967
+ return value.split(/[;,\n]+/u).map((entry) => entry.trim()).filter(Boolean).map((entry) => {
968
+ const delimiter = entry.includes("|") ? "|" : entry.includes("=") ? "=" : "";
969
+ if (delimiter) {
970
+ const index = entry.indexOf(delimiter);
971
+ const baseUrl = entry.slice(0, index).trim();
972
+ const eteamsId = entry.slice(index + delimiter.length).trim();
973
+ return baseUrl && eteamsId ? { baseUrl: normalizeUrl(baseUrl), eteamsId, source } : null;
974
+ }
975
+ const parts = entry.split(/\s+/u).filter(Boolean);
976
+ return parts.length === 2 ? { baseUrl: normalizeUrl(parts[0]), eteamsId: parts[1], source } : null;
977
+ }).filter((entry) => Boolean(entry));
978
+ }
979
+ function listXiaoEUnifiedLoginCredentials(env = process.env) {
980
+ const candidates = [];
981
+ for (const key of XIAOE_UNIFIED_LOGIN_MAP_ENV_KEYS) {
982
+ const raw = envString(env, key);
983
+ if (raw) candidates.push(...parseXiaoEUnifiedLoginMap(raw, key));
984
+ }
985
+ return candidates;
986
+ }
987
+ function resolveXiaoEUnifiedLoginCredential(baseUrl, env = process.env) {
988
+ const candidates = listXiaoEUnifiedLoginCredentials(env);
989
+ return candidates.find((candidate) => domainMatches(baseUrl, candidate.baseUrl)) || null;
990
+ }
991
+ function normalizeBaseUrlValue(value) {
992
+ const raw = normalizeUrl(value.trim());
993
+ if (!raw) return "";
994
+ return /^https?:\/\//i.test(raw) ? raw : `https://${raw}`;
995
+ }
996
+ function resolveXiaoEConfiguredBaseUrl(env) {
997
+ const explicitDefault = envString(env, ...XIAOE_DEFAULT_DOMAIN_ENV_KEYS);
998
+ if (explicitDefault) return normalizeBaseUrlValue(explicitDefault);
999
+ const singleDomain = envString(env, ...XIAOE_SINGLE_DOMAIN_ENV_KEYS);
1000
+ if (singleDomain) return normalizeBaseUrlValue(singleDomain);
1001
+ const firstCredential = listXiaoEUnifiedLoginCredentials(env)[0];
1002
+ if (firstCredential?.baseUrl) return normalizeUrl(firstCredential.baseUrl);
1003
+ return "";
1004
+ }
1005
+ function uniqueStrings(values) {
1006
+ const seen = /* @__PURE__ */ new Set();
1007
+ const result = [];
1008
+ for (const value of values) {
1009
+ if (!value || seen.has(value)) continue;
1010
+ seen.add(value);
1011
+ result.push(value);
1012
+ }
1013
+ return result;
1014
+ }
1015
+ function xiaoETokenScriptCandidatePaths(env = process.env) {
1016
+ const explicit = envString(env, XIAOE_TOKEN_SCRIPT_ENV_KEY, XIAOE_TOKEN_SCRIPT_LEGACY_ENV_KEY);
1017
+ if (explicit) return [explicit];
1018
+ if (process.platform === "win32") {
1019
+ const localAppData = envString(env, "LOCALAPPDATA");
1020
+ const userProfile = envString(env, "USERPROFILE");
1021
+ return uniqueStrings([
1022
+ localAppData ? join2(localAppData, "xiaoeUserData", "tokens.py") : "",
1023
+ userProfile ? join2(userProfile, "AppData", "Local", "xiaoeUserData", "tokens.py") : ""
1024
+ ]);
1025
+ }
1026
+ const envHome = envString(env, "HOME");
1027
+ const nodeHome = envHome ? "" : homedir2();
1028
+ return uniqueStrings([
1029
+ envHome ? join2(envHome, "Library", "Application Support", "xiaoeUserData", "tokens.py") : "",
1030
+ nodeHome ? join2(nodeHome, "Library", "Application Support", "xiaoeUserData", "tokens.py") : ""
1031
+ ]);
1032
+ }
1033
+ function xiaoETokenScriptPath(env = process.env) {
1034
+ return xiaoETokenScriptCandidatePaths(env).find((path) => existsSync4(path)) || "";
1035
+ }
1036
+ function xiaoEBundledEnvScriptPath() {
1037
+ const scriptPath = packagePath("scripts", "xiaoe_env.py");
1038
+ return existsSync4(scriptPath) ? scriptPath : "";
1039
+ }
1040
+ function hasXiaoETokenScript(env = process.env, allowLocalDiscovery = true) {
1041
+ const explicit = envString(env, XIAOE_TOKEN_SCRIPT_ENV_KEY, XIAOE_TOKEN_SCRIPT_LEGACY_ENV_KEY);
1042
+ if (explicit) return existsSync4(explicit);
1043
+ if (!allowLocalDiscovery) return false;
1044
+ const scriptPath = xiaoETokenScriptPath(env);
1045
+ return Boolean(scriptPath && existsSync4(scriptPath));
1046
+ }
1047
+ function isExecutableFile(path) {
1048
+ try {
1049
+ if (!statSync(path).isFile()) return false;
1050
+ accessSync(path, fsConstants.X_OK);
1051
+ return true;
1052
+ } catch {
1053
+ return false;
1054
+ }
1055
+ }
1056
+ function listXiaoEPythonRuntimeDirectories(resourcesRoot) {
1057
+ if (!resourcesRoot || !existsSync4(resourcesRoot)) return [];
1058
+ try {
1059
+ return readdirSync2(resourcesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^Python3(?:[-_.]\d[\d.]*)?$/iu.test(entry.name)).map((entry) => join2(resourcesRoot, entry.name)).sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
1060
+ } catch {
1061
+ return [];
1062
+ }
1063
+ }
1064
+ function listExecutablePythonFiles(directory, platform) {
1065
+ if (!directory || !existsSync4(directory)) return [];
1066
+ try {
1067
+ const pattern = platform === "win32" ? /^python(?:3(?:\.\d+)*)?\.exe$/iu : /^python3(?:\.\d+)*$/u;
1068
+ return readdirSync2(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && pattern.test(entry.name)).map((entry) => join2(directory, entry.name)).filter(isExecutableFile).sort((left, right) => right.localeCompare(left, void 0, { numeric: true }));
1069
+ } catch {
1070
+ return [];
1071
+ }
1072
+ }
1073
+ function xiaoEClientPythonCandidates(env = process.env, platform = process.platform) {
1074
+ const appRoots = [];
1075
+ if (platform === "darwin") {
1076
+ const envHome = envString(env, "HOME");
1077
+ const nodeHome = homedir2();
1078
+ for (const home of uniqueStrings([envHome, nodeHome])) {
1079
+ appRoots.push(join2(home, "Applications", "\u667A\u80FD\u5C0Fe.app"));
1080
+ }
1081
+ appRoots.push("/Applications/\u667A\u80FD\u5C0Fe.app");
1082
+ } else if (platform === "win32") {
1083
+ const localAppData = envString(env, "LOCALAPPDATA");
1084
+ const programFiles = uniqueStrings([
1085
+ envString(env, "ProgramW6432"),
1086
+ envString(env, "ProgramFiles"),
1087
+ envString(env, "ProgramFiles(x86)")
1088
+ ]);
1089
+ const appNames = ["\u667A\u80FD\u5C0Fe", "XiaoE", "XiaoEClient", "XiaoEAI"];
1090
+ if (localAppData) {
1091
+ for (const appName of appNames) {
1092
+ appRoots.push(join2(localAppData, "Programs", appName), join2(localAppData, appName));
1093
+ }
1094
+ }
1095
+ for (const programFilesRoot of programFiles) {
1096
+ for (const appName of appNames) appRoots.push(join2(programFilesRoot, appName));
1097
+ }
1098
+ }
1099
+ const candidates = [];
1100
+ for (const appRoot of uniqueStrings(appRoots)) {
1101
+ const resourcesRoots = platform === "darwin" ? [join2(appRoot, "Contents", "Resources")] : [join2(appRoot, "Resources"), appRoot];
1102
+ for (const resourcesRoot of resourcesRoots) {
1103
+ for (const runtimeRoot of listXiaoEPythonRuntimeDirectories(resourcesRoot)) {
1104
+ const executableDirectories = platform === "win32" ? [runtimeRoot, join2(runtimeRoot, "bin")] : [join2(runtimeRoot, "bin")];
1105
+ for (const executableDirectory of executableDirectories) {
1106
+ candidates.push(...listExecutablePythonFiles(executableDirectory, platform));
1107
+ }
1108
+ }
1109
+ }
1110
+ }
1111
+ return uniqueStrings(candidates);
1112
+ }
1113
+ function xiaoETokenScriptPythonCandidates(env = process.env, platform = process.platform) {
1114
+ const explicit = envString(env, XIAOE_TOKEN_SCRIPT_PYTHON_ENV_KEY, XIAOE_TOKEN_SCRIPT_PYTHON_LEGACY_ENV_KEY);
1115
+ if (explicit) return [explicit];
1116
+ return uniqueStrings(
1117
+ platform === "win32" ? [...xiaoEClientPythonCandidates(env, platform), "python", "python3", "py"] : [...xiaoEClientPythonCandidates(env, platform), "python3", "/usr/bin/python3", "python"]
1118
+ );
1119
+ }
1120
+ function isXiaoETokenScriptEnvFailure(message) {
1121
+ return /No module named|ModuleNotFoundError|ENOENT|EACCES|permission denied|command not found|not recognized as an internal|cannot find the file/i.test(message);
1122
+ }
1123
+ async function runXiaoETokenScriptOnce(pythonCommand, scriptPath, baseUrl, env) {
1124
+ const wrapper = [
1125
+ "import ast,contextlib,io,json,runpy,sys",
1126
+ `path = ${JSON.stringify(scriptPath)}`,
1127
+ `base_url = ${JSON.stringify(baseUrl)}`,
1128
+ "sys.argv = [path, base_url]",
1129
+ "buf = io.StringIO()",
1130
+ "data = None",
1131
+ "with contextlib.redirect_stdout(buf):",
1132
+ ' runpy.run_path(path, run_name="__main__")',
1133
+ "text = buf.getvalue().strip()",
1134
+ "if text:",
1135
+ " lines = [line.strip() for line in text.splitlines() if line.strip()]",
1136
+ " candidates = [text] + (lines[-1:] if lines else [])",
1137
+ " last_error = None",
1138
+ " for candidate in candidates:",
1139
+ " try:",
1140
+ " data = json.loads(candidate)",
1141
+ " break",
1142
+ " except Exception as exc:",
1143
+ " last_error = exc",
1144
+ " try:",
1145
+ " data = ast.literal_eval(candidate)",
1146
+ " break",
1147
+ " except Exception as exc:",
1148
+ " last_error = exc",
1149
+ " if data is None:",
1150
+ ' raise SystemExit("XiaoE credential script stdout is not valid JSON object")',
1151
+ "else:",
1152
+ ' raise SystemExit("XiaoE credential script produced empty stdout")',
1153
+ "print(json.dumps(data, ensure_ascii=False))"
1154
+ ].join("\n");
1155
+ return await new Promise((resolve6, reject) => {
1156
+ execFile(
1157
+ pythonCommand,
1158
+ ["-c", wrapper],
1159
+ {
1160
+ env,
1161
+ timeout: XIAOE_TOKEN_SCRIPT_TIMEOUT_MS,
1162
+ maxBuffer: 1024 * 1024
1163
+ },
1164
+ (error, stdout, stderr) => {
1165
+ if (error) {
1166
+ const detail = (stderr || error.message || "unknown error").trim().split("\n").slice(-1)[0];
1167
+ reject(new CliError("XiaoE credential script failed: " + detail, 3 /* AuthError */));
1168
+ return;
1169
+ }
1170
+ const text = stdout.trim();
1171
+ if (!text) {
1172
+ reject(new CliError("XiaoE credential script returned empty stdout.", 3 /* AuthError */));
1173
+ return;
1174
+ }
1175
+ try {
1176
+ const parsed = JSON.parse(text);
1177
+ resolve6(parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null);
1178
+ } catch {
1179
+ reject(new CliError("XiaoE credential script stdout is not valid JSON.", 3 /* AuthError */));
1180
+ }
1181
+ }
1182
+ );
1183
+ });
1184
+ }
1185
+ async function runXiaoEPythonCredentialScript(scriptPath, baseUrl, env) {
1186
+ if (!scriptPath || !existsSync4(scriptPath)) return null;
1187
+ let lastError = null;
1188
+ for (const pythonCommand of xiaoETokenScriptPythonCandidates(env)) {
1189
+ try {
1190
+ return await runXiaoETokenScriptOnce(pythonCommand, scriptPath, baseUrl, env);
1191
+ } catch (error) {
1192
+ lastError = error;
1193
+ const message = error instanceof Error ? error.message : String(error);
1194
+ if (!isXiaoETokenScriptEnvFailure(message)) break;
1195
+ }
1196
+ }
1197
+ throw lastError instanceof Error ? lastError : new CliError("XiaoE credential script failed.", 3 /* AuthError */);
1198
+ }
1199
+ async function runXiaoETokenScript(baseUrl, env = process.env) {
1200
+ return runXiaoEPythonCredentialScript(xiaoETokenScriptPath(env), baseUrl, env);
1201
+ }
1202
+ async function resolveXiaoETokenScriptCredential(baseUrl, env = process.env) {
1203
+ const tokenData = await runXiaoETokenScript(baseUrl, env);
1204
+ if (!tokenData) return null;
1205
+ return readXiaoECredentialRecord(tokenData, "xiaoeUserData/tokens.py", baseUrl);
1206
+ }
1207
+ async function resolveXiaoEBundledEnvScriptCredential(baseUrl, env = process.env) {
1208
+ const scriptPath = xiaoEBundledEnvScriptPath();
1209
+ if (!scriptPath) return null;
1210
+ const tokenData = await runXiaoEPythonCredentialScript(scriptPath, baseUrl, env);
1211
+ if (!tokenData) return null;
1212
+ return readXiaoECredentialRecord(tokenData, XIAOE_BUNDLED_ENV_SCRIPT_SOURCE, baseUrl);
1213
+ }
1214
+ function xiaoEClientRobotsRoot(env = process.env) {
1215
+ if (process.platform === "win32") {
1216
+ const localAppData = envString(env, "LOCALAPPDATA");
1217
+ return localAppData ? join2(localAppData, "XiaoE", "Robots") : "";
1218
+ }
1219
+ const home = envString(env, "HOME") || homedir2();
1220
+ return home ? join2(home, "Library", "Application Support", "XiaoE", "Robots") : "";
1221
+ }
1222
+ function isFile(path) {
1223
+ if (!path || !existsSync4(path)) return false;
1224
+ try {
1225
+ return statSync(path).isFile();
1226
+ } catch {
1227
+ return false;
1228
+ }
1229
+ }
1230
+ function isDirectory(path) {
1231
+ if (!path || !existsSync4(path)) return false;
1232
+ try {
1233
+ return statSync(path).isDirectory();
1234
+ } catch {
1235
+ return false;
1236
+ }
1237
+ }
1238
+ function listXiaoEClientSettingsFiles(root) {
1239
+ if (!root) return [];
1240
+ if (isFile(root)) return [root];
1241
+ if (!isDirectory(root)) return [];
1242
+ const candidates = [];
1243
+ const addCandidate = (path) => {
1244
+ if (isFile(path)) candidates.push(path);
1245
+ };
1246
+ const addChildSettings = (directory) => {
1247
+ if (!isDirectory(directory)) return;
1248
+ try {
1249
+ for (const entry of readdirSync2(directory, { withFileTypes: true })) {
1250
+ if (entry.isDirectory()) addCandidate(join2(directory, entry.name, "user_settings.json"));
1251
+ }
1252
+ } catch {
1253
+ }
1254
+ };
1255
+ addCandidate(join2(root, "user_settings.json"));
1256
+ addChildSettings(root);
1257
+ const robotsRoot = join2(root, "Robots");
1258
+ addCandidate(join2(robotsRoot, "user_settings.json"));
1259
+ addChildSettings(robotsRoot);
1260
+ return uniqueStrings(candidates);
1261
+ }
1262
+ function sortedXiaoEClientSettingsFiles(root) {
1263
+ const files = listXiaoEClientSettingsFiles(root);
1264
+ return files.sort((left, right) => statSync(right).mtimeMs - statSync(left).mtimeMs);
1265
+ }
1266
+ function xiaoEClientSettingsCandidateFiles(env, allowLocalDiscovery = true) {
1267
+ const candidates = [];
1268
+ const explicitSettingsPath = envString(env, XIAOE_USER_SETTINGS_PATH_ENV_KEY);
1269
+ if (isFile(explicitSettingsPath)) candidates.push(explicitSettingsPath);
1270
+ for (const key of XIAOE_CLIENT_SETTINGS_ROOT_ENV_KEYS) {
1271
+ const injectedRoot = envString(env, key);
1272
+ candidates.push(...sortedXiaoEClientSettingsFiles(injectedRoot));
1273
+ }
1274
+ if (allowLocalDiscovery) {
1275
+ candidates.push(...sortedXiaoEClientSettingsFiles(xiaoEClientRobotsRoot(env)));
1276
+ }
1277
+ return uniqueStrings(candidates);
1278
+ }
1279
+ function readXiaoEPlatformCredential(env = process.env) {
1280
+ const envToken = envString(env, "XIAOE_USER_TOKEN");
1281
+ if (!envToken) return null;
1282
+ const rawErpa = envString(
1283
+ env,
1284
+ "WEAVER_XIAOE_ERP",
1285
+ "WEAVER_XIAOE_ERPA",
1286
+ "WEAVER_XIAOE_ERP_URL",
1287
+ "XIAOE_ERP",
1288
+ "XIAOE_ERPA",
1289
+ "XIAOE_ERP_URL",
1290
+ "XIAOE_DOMAIN"
1291
+ );
1292
+ const erpaUrl = normalizeBaseUrlValue(rawErpa);
1293
+ if (!erpaUrl) return null;
1294
+ return { authToken: envToken, erpaUrl, source: XIAOE_USER_TOKEN_SOURCE };
1295
+ }
1296
+ function hasXiaoEPlatformCredential(env = process.env) {
1297
+ return Boolean(readXiaoEPlatformCredential(env));
1298
+ }
1299
+ function readXiaoEClientCredential(env = process.env) {
1300
+ for (const settingsFile of xiaoEClientSettingsCandidateFiles(env)) {
1301
+ try {
1302
+ const parsed = JSON.parse(readFileSync3(settingsFile, "utf8"));
1303
+ const authToken = readString(parsed, "session_id", "sessionId");
1304
+ const erpaUrl = normalizeUrl(readString(parsed, "erpa", "erpa_url", "erpaUrl"));
1305
+ if (authToken && erpaUrl) return { authToken, erpaUrl, source: XIAOE_CLIENT_SETTINGS_SOURCE };
1306
+ } catch {
1307
+ }
1308
+ }
1309
+ return null;
1310
+ }
1311
+ function hasXiaoEClientCredential(env = process.env, allowLocalDiscovery = true) {
1312
+ return Boolean(xiaoEClientSettingsCandidateFiles(env, allowLocalDiscovery)[0]);
1313
+ }
1314
+ function inspectXiaoEUnifiedLoginSources(options = {}) {
1315
+ const env = options.env || process.env;
1316
+ const baseUrl = resolveXiaoEPreferredBaseUrl({
1317
+ explicitBaseUrl: options.baseUrl,
1318
+ profileBaseUrl: options.profileBaseUrl,
1319
+ env
1320
+ });
1321
+ const platformCredential = hasXiaoEPlatformCredential(env);
1322
+ const allowLocalDiscovery = options.allowLocalDiscovery !== false;
1323
+ const tokenScript = options.allowTokenScript !== false && hasXiaoETokenScript(env, allowLocalDiscovery);
1324
+ const clientCredential = hasXiaoEClientCredential(env, allowLocalDiscovery);
1325
+ const environmentCredential = Boolean(baseUrl && resolveXiaoEUnifiedLoginCredential(baseUrl, env));
1326
+ return {
1327
+ platformCredential,
1328
+ tokenScript,
1329
+ clientCredential,
1330
+ environmentCredential,
1331
+ any: platformCredential || tokenScript || clientCredential || environmentCredential
1332
+ };
1333
+ }
1334
+ async function fetchXiaoEClientEteamId(credential, domain) {
1335
+ const controller = new AbortController();
1336
+ const timer = setTimeout(() => controller.abort(), XIAOE_CLIENT_TOKEN_TIMEOUT_MS);
1337
+ try {
1338
+ let endpoint = new URL(`${credential.erpaUrl}${XIAOE_SKILL_ETEAMID_API_PATH}`);
1339
+ let resp = null;
1340
+ for (let redirects = 0; redirects <= 5; redirects += 1) {
1341
+ resp = await fetch(endpoint, {
1342
+ method: "POST",
1343
+ headers: {
1344
+ "content-type": "application/json",
1345
+ authorization: credential.authToken
1346
+ },
1347
+ body: JSON.stringify({ domain: domain || DEFAULT_E10_BASE_URL }),
1348
+ redirect: "manual",
1349
+ signal: controller.signal
1350
+ });
1351
+ if (resp.status < 300 || resp.status >= 400) break;
1352
+ if (redirects === 5) {
1353
+ throw new CliError("XiaoE client token endpoint redirected too many times.", 3 /* AuthError */);
1354
+ }
1355
+ const location = resp.headers.get("location");
1356
+ if (!location) {
1357
+ throw new CliError("XiaoE client token endpoint returned a redirect without Location.", 3 /* AuthError */);
1358
+ }
1359
+ const next = new URL(location, endpoint);
1360
+ const sameOrigin = next.origin === endpoint.origin;
1361
+ const sameHostHttpsUpgrade = endpoint.protocol === "http:" && next.protocol === "https:" && next.hostname === endpoint.hostname;
1362
+ const safeProtocol = next.protocol === "http:" || next.protocol === "https:";
1363
+ if (!safeProtocol || next.username || next.password || !sameOrigin && !sameHostHttpsUpgrade) {
1364
+ throw new CliError("XiaoE client token endpoint attempted an unsafe cross-origin redirect.", 3 /* AuthError */);
1365
+ }
1366
+ await resp.body?.cancel().catch(() => void 0);
1367
+ endpoint = next;
1368
+ }
1369
+ if (!resp?.ok) {
1370
+ throw new CliError(`XiaoE client token endpoint returned HTTP ${resp?.status || 0}.`, 3 /* AuthError */);
1371
+ }
1372
+ const data = await resp.json().catch(() => null);
1373
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
1374
+ throw new CliError("XiaoE client token endpoint returned invalid JSON.", 3 /* AuthError */);
1375
+ }
1376
+ const payload = data;
1377
+ const businessCode = payload.code;
1378
+ const businessData = payload.data && typeof payload.data === "object" && !Array.isArray(payload.data) ? payload.data : {};
1379
+ if (businessCode !== "0000" && businessCode !== 0 && businessCode !== 200 || !readString(businessData, "eteamId")) {
1380
+ const codeText = businessCode === void 0 ? "missing" : String(businessCode);
1381
+ throw new CliError(`XiaoE client token exchange failed with business code ${codeText}.`, 3 /* AuthError */);
1382
+ }
1383
+ return payload;
1384
+ } finally {
1385
+ clearTimeout(timer);
1386
+ }
1387
+ }
1388
+ async function resolveXiaoETokenCredential(credential, baseUrl) {
1389
+ const targetBaseUrl = baseUrl || DEFAULT_E10_BASE_URL;
1390
+ const payload = await fetchXiaoEClientEteamId(credential, targetBaseUrl);
1391
+ const resolvedBaseUrl = payload.code === 0 ? credential.erpaUrl : targetBaseUrl;
1392
+ return readXiaoECredentialRecord(payload, credential.source, resolvedBaseUrl);
1393
+ }
1394
+ async function resolveXiaoEPlatformCredential(baseUrl, env = process.env) {
1395
+ const credential = readXiaoEPlatformCredential(env);
1396
+ if (!credential) return null;
1397
+ return resolveXiaoETokenCredential(credential, baseUrl);
1398
+ }
1399
+ async function resolveXiaoEClientCredential(baseUrl, env = process.env) {
1400
+ const clientCredential = readXiaoEClientCredential(env);
1401
+ if (!clientCredential) return null;
1402
+ return resolveXiaoETokenCredential(clientCredential, baseUrl);
1403
+ }
1404
+ function resolveXiaoEPreferredBaseUrl(options) {
1405
+ const env = options.env || process.env;
1406
+ const explicit = normalizeUrl(options.explicitBaseUrl || "");
1407
+ if (explicit) return explicit;
1408
+ const configured = resolveXiaoEConfiguredBaseUrl(env);
1409
+ if (configured) return configured;
1410
+ const profileBaseUrl = normalizeUrl(options.profileBaseUrl || "");
1411
+ if (profileBaseUrl) return profileBaseUrl;
1412
+ return DEFAULT_E10_BASE_URL;
1413
+ }
1414
+ function createXiaoEUnifiedLoginUnavailableError(baseUrl = "") {
1415
+ const target = normalizeUrl(baseUrl);
1416
+ const message = [
1417
+ "XiaoE unified login did not return a usable E10 session.",
1418
+ target ? `Resolved E10 baseUrl: ${target}.` : "No E10 baseUrl could be resolved.",
1419
+ "The auth xiaoe command never falls back to browser OAuth.",
1420
+ "Refresh the XiaoE web session or restore host credential injection before retrying."
1421
+ ].join(" ");
1422
+ return Object.assign(new CliError(message, 3 /* AuthError */), {
1423
+ type: "authentication",
1424
+ subtype: "xiaoe_credential_unavailable",
1425
+ retryable: false,
1426
+ stage: "xiaoe_unified_login"
1427
+ });
1428
+ }
1429
+ async function resolveUserInfo(baseUrl, eteamsId, rawCookie = "", agentType = "") {
1430
+ const resp = await fetch(`${baseUrl}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(baseUrl)}`, {
1431
+ method: "POST",
1432
+ headers: {
1433
+ accept: "application/json",
1434
+ "content-type": "application/json",
1435
+ eteamsid: eteamsId,
1436
+ cookie: buildE10CookieHeader(rawCookie, eteamsId, agentType),
1437
+ "user-agent": agentType ? `AgentType=${agentType},IsAgent=true` : "weaver-work-cli",
1438
+ origin: baseUrl
1439
+ },
1440
+ redirect: "manual"
1441
+ });
1442
+ const data = await resp.json().catch(() => ({}));
1443
+ return { userInfo: readTeamsCheckUserInfo(resp, data), setCookie: extractRawSetCookie(resp) };
1444
+ }
1445
+ async function saveXiaoEUnifiedLogin(input) {
1446
+ const baseUrl = normalizeUrl(input.baseUrl);
1447
+ const { userInfo, setCookie } = await resolveUserInfo(baseUrl, input.eteamsId, input.rawCookie || "", XIAOE_AGENT_TYPE);
1448
+ if (!userInfo.userId) {
1449
+ throw new CliError("Could not resolve userId. Check whether XiaoE unified login is valid for this E10 domain.", 3 /* AuthError */);
1450
+ }
1451
+ const tenantKey = userInfo.tenantKey || input.tenantKeyFallback || "";
1452
+ const profile = input.profileHint || profileNameFromUrl(baseUrl);
1453
+ setActiveProfile(profile);
1454
+ const cookies = { ETEAMSID: input.eteamsId };
1455
+ if (input.rawCookie) cookies.raw = input.rawCookie;
1456
+ const ztSession = extractSessionTicket(setCookie, input.rawCookie || "");
1457
+ const authData = {
1458
+ cookies,
1459
+ userId: userInfo.userId,
1460
+ tenantKey,
1461
+ tenantName: userInfo.tenantName,
1462
+ department: userInfo.department,
1463
+ subcompany: userInfo.subcompany,
1464
+ position: userInfo.position,
1465
+ agentType: XIAOE_AGENT_TYPE,
1466
+ version: "",
1467
+ baseUrl,
1468
+ passportUrl: baseUrl,
1469
+ cookieSavedAt: Date.now(),
1470
+ loginSource: "xiaoe-unified",
1471
+ credentialSourceStep: input.credentialSource.credentialSourceStep,
1472
+ credentialSourceType: input.credentialSource.credentialSourceType,
1473
+ credentialSourceLabel: input.credentialSource.credentialSourceLabel,
1474
+ ...ztSession ? { ztSession } : {}
1475
+ };
1476
+ const authFile = saveAuthFile(authData, profile);
1477
+ saveProfileConfig(baseUrl, baseUrl, profile, tenantKey);
1478
+ const session = new E10AuthSession(authData, authFile);
1479
+ return {
1480
+ session,
1481
+ result: {
1482
+ ...userInfo,
1483
+ tenantKey,
1484
+ eteamsId: input.eteamsId,
1485
+ baseUrl,
1486
+ passportUrl: baseUrl,
1487
+ profile,
1488
+ authFile,
1489
+ agentType: XIAOE_AGENT_TYPE,
1490
+ version: "",
1491
+ loginSource: "xiaoe-unified",
1492
+ ...input.credentialSource
1493
+ }
1494
+ };
1495
+ }
1496
+ async function tryXiaoEUnifiedLogin(options = {}) {
1497
+ const env = options.env || process.env;
1498
+ const explicitBaseUrl = normalizeUrl(options.baseUrl || "");
1499
+ const baseUrl = resolveXiaoEPreferredBaseUrl({
1500
+ explicitBaseUrl,
1501
+ profileBaseUrl: options.profileBaseUrl,
1502
+ env
1503
+ });
1504
+ const mayUseTokenScript = options.allowTokenScript === true;
1505
+ if (!baseUrl && !mayUseTokenScript) return null;
1506
+ let credential = null;
1507
+ if (hasXiaoEPlatformCredential(env)) {
1508
+ options.logger?.info("Trying XiaoE platform credential from XIAOE_USER_TOKEN...");
1509
+ try {
1510
+ credential = await resolveXiaoEPlatformCredential(baseUrl || DEFAULT_E10_BASE_URL, env);
1511
+ } catch (error) {
1512
+ const message = error instanceof Error ? error.message : String(error);
1513
+ options.logger?.warn("XiaoE platform credential failed. " + message);
1514
+ }
1515
+ if (!credential) {
1516
+ options.logger?.warn(options.allowBundledEnvScript ? "XiaoE platform credential did not return usable ETEAMSID; will try the CLI-bundled xiaoe_env.py compatibility path next." : "XiaoE platform credential did not return usable ETEAMSID; will try xiaoeUserData/tokens.py next.");
1517
+ }
1518
+ }
1519
+ if (!credential && options.allowBundledEnvScript && hasXiaoEPlatformCredential(env)) {
1520
+ const scriptPath = xiaoEBundledEnvScriptPath();
1521
+ if (!scriptPath) {
1522
+ options.logger?.warn("CLI-bundled xiaoe_env.py was not found; will try desktop XiaoE credential sources next.");
1523
+ } else {
1524
+ options.logger?.info("Trying CLI-bundled xiaoe_env.py compatibility credential...");
1525
+ try {
1526
+ credential = await resolveXiaoEBundledEnvScriptCredential(baseUrl || DEFAULT_E10_BASE_URL, env);
1527
+ } catch (error) {
1528
+ const message = error instanceof Error ? error.message : String(error);
1529
+ options.logger?.warn("CLI-bundled xiaoe_env.py failed. " + message);
1530
+ }
1531
+ if (!credential) {
1532
+ options.logger?.warn("CLI-bundled xiaoe_env.py did not return usable ETEAMSID; will try xiaoeUserData/tokens.py next.");
1533
+ }
1534
+ }
1535
+ }
1536
+ if (!credential && mayUseTokenScript) {
1537
+ const tokenScriptPath = xiaoETokenScriptPath(env);
1538
+ if (!tokenScriptPath) {
1539
+ options.logger?.warn("XiaoE token script not found. Expected xiaoeUserData/tokens.py; will try the local XiaoE client session next.");
1540
+ } else {
1541
+ options.logger?.info("Trying XiaoE token script credential...");
1542
+ try {
1543
+ credential = await resolveXiaoETokenScriptCredential(baseUrl || DEFAULT_E10_BASE_URL, env);
1544
+ } catch (error) {
1545
+ const message = error instanceof Error ? error.message : String(error);
1546
+ options.logger?.warn("XiaoE token script failed. " + message);
1547
+ }
1548
+ if (!credential) {
1549
+ options.logger?.warn("XiaoE token script did not return usable ETEAMSID; will try the local XiaoE client session next.");
1550
+ }
1551
+ }
1552
+ if (!credential && hasXiaoEClientCredential(env)) {
1553
+ options.logger?.info("Trying built-in XiaoE client session credential...");
1554
+ try {
1555
+ credential = await resolveXiaoEClientCredential(baseUrl || DEFAULT_E10_BASE_URL, env);
1556
+ } catch (error) {
1557
+ const message = error instanceof Error ? error.message : String(error);
1558
+ options.logger?.warn("Built-in XiaoE client credential failed. " + message);
1559
+ }
1560
+ if (!credential) {
1561
+ options.logger?.warn("Built-in XiaoE client credential did not return usable ETEAMSID; will try WEAVER_XIAOE_* credentials next.");
1562
+ }
1563
+ }
1564
+ }
1565
+ if (!credential && baseUrl) credential = resolveXiaoEUnifiedLoginCredential(baseUrl, env);
1566
+ if (!credential) return null;
1567
+ options.logger?.info("Detected XiaoE unified login for this E10 domain. Trying XiaoE auth...");
1568
+ try {
1569
+ return await saveXiaoEUnifiedLogin({
1570
+ baseUrl: credential.baseUrl || baseUrl || DEFAULT_E10_BASE_URL,
1571
+ eteamsId: credential.eteamsId,
1572
+ rawCookie: credential.rawCookie,
1573
+ tenantKeyFallback: options.tenantKeyFallback,
1574
+ profileHint: options.profileHint,
1575
+ credentialSource: describeXiaoECredentialSource(credential.source)
1576
+ });
1577
+ } catch (error) {
1578
+ const message = error instanceof Error ? error.message : String(error);
1579
+ options.logger?.warn("XiaoE unified login failed. " + message);
1580
+ return null;
1581
+ }
1582
+ }
1583
+
1584
+ export {
1585
+ packagePath,
1586
+ packageFileUrl,
1587
+ normalizeGlobalOptions,
1588
+ getE10AuthRoot,
1589
+ getActiveProfile,
1590
+ setActiveProfile,
1591
+ switchActiveProfile,
1592
+ listProfiles,
1593
+ getProfileDir,
1594
+ getProfileAuthPath,
1595
+ profileNameFromUrl,
1596
+ readProfileConfig,
1597
+ saveProfileConfig,
1598
+ saveAuthFile,
1599
+ clearProfileAuthFile,
1600
+ findAuthFile,
1601
+ readTeamsCheckUserInfo,
1602
+ buildE10CookieHeader,
1603
+ extractRawSetCookie,
1604
+ extractSessionTicket,
1605
+ E10AuthSession,
1606
+ E10_REAUTH_GUIDANCE,
1607
+ E10_AUTH_REQUIRED_MESSAGE,
1608
+ E10_SESSION_EXPIRED_MESSAGE,
1609
+ XIAOE_AGENT_TYPE,
1610
+ hasXiaoEEnv,
1611
+ inspectXiaoEUnifiedLoginSources,
1612
+ resolveXiaoEPreferredBaseUrl,
1613
+ createXiaoEUnifiedLoginUnavailableError,
1614
+ tryXiaoEUnifiedLogin
1615
+ };