@thinkingai/ae-cli 1.0.27 → 1.0.30

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 (90) hide show
  1. package/README.md +1 -16
  2. package/README.zh.md +1 -16
  3. package/dist/auth-H3GJD55A.js +457 -0
  4. package/dist/{auth-TXFJHPXU.js → auth-U25QJU5D.js} +3 -3
  5. package/dist/{chunk-B4UL2VIJ.js → chunk-CLJF7MQA.js} +1 -1
  6. package/dist/{chunk-6T7245YE.js → chunk-EGEIXA2Z.js} +90 -18
  7. package/dist/{chunk-2NGWYMLB.js → chunk-GLNZSDKO.js} +88 -50
  8. package/dist/chunk-GSJGPNKK.js +49 -0
  9. package/dist/{chunk-VT6VC4PA.js → chunk-I42JGQ2J.js} +26 -11
  10. package/dist/chunk-JM34JPCO.js +239 -0
  11. package/dist/chunk-NOO24N7W.js +11 -0
  12. package/dist/chunk-SF3KTPIC.js +98 -0
  13. package/dist/chunk-SRJIAOBN.js +244 -0
  14. package/dist/chunk-U6TKB3IV.js +171 -0
  15. package/dist/{chunk-TG64AQV4.js → chunk-VJFUB3H3.js} +99 -56
  16. package/dist/{client-IU2E5IOL.js → client-IN42F223.js} +4 -4
  17. package/dist/config-64G36TJL.js +130 -0
  18. package/dist/index.js +52 -25
  19. package/dist/{model-CC7U5XOJ.js → model-VZCYNIOG.js} +11 -10
  20. package/dist/{raw-TUHZQ4UB.js → raw-WJIWC6YP.js} +13 -7
  21. package/dist/{sync-EVEDS7YE.js → sync-NVASAISS.js} +146 -47
  22. package/dist/{te-agent-FLTDYV3L.js → te-agent-YV4DXEXK.js} +24 -23
  23. package/dist/{te-analysis-CMXADIJM.js → te-analysis-CB3DA5I5.js} +61 -13
  24. package/dist/{te-audience-LPZFFSXM.js → te-audience-W7SCQFC7.js} +7 -5
  25. package/dist/{te-common-BXQFKTB3.js → te-common-FBXVWBSI.js} +21 -9
  26. package/dist/{te-community-K5S3VOZY.js → te-community-LNVDZSGW.js} +6 -4
  27. package/dist/{te-dataops-567IMCQG.js → te-dataops-IPCSSWYH.js} +29 -27
  28. package/dist/{te-engage-TBUTGW5F.js → te-engage-KARARMIR.js} +6 -4
  29. package/dist/{te-kb-XHVBWP5E.js → te-kb-2Z2CARN3.js} +7 -5
  30. package/dist/{te-meta-NQ4U3VJW.js → te-meta-PDKLMWXN.js} +6 -4
  31. package/dist/{te-team-556APRIU.js → te-team-SW5B7DHO.js} +17 -12
  32. package/package.json +6 -2
  33. package/skills/ae-agent/SKILL.md +2 -1
  34. package/skills/ae-analysis/SKILL.md +1 -1
  35. package/skills/ae-analysis/references/list_clusters.md +4 -2
  36. package/skills/ae-analysis-global/SKILL.md +51 -0
  37. package/skills/ae-analysis-global/references/list_query_clusters.md +67 -0
  38. package/skills/ae-community/SKILL.md +2 -3
  39. package/skills/ae-dataops/SKILL.md +1 -2
  40. package/skills/ae-engage/SKILL.md +1 -0
  41. package/skills/ae-engage/references/add-approver.md +0 -1
  42. package/skills/ae-engage/references/add-channel.md +0 -1
  43. package/skills/ae-engage/references/approver-list.md +0 -1
  44. package/skills/ae-engage/references/cancel-query-by-request-id.md +0 -1
  45. package/skills/ae-engage/references/channel-detail.md +0 -1
  46. package/skills/ae-engage/references/channel-list.md +0 -1
  47. package/skills/ae-engage/references/config-channel-detail.md +0 -1
  48. package/skills/ae-engage/references/config-channel-list.md +0 -1
  49. package/skills/ae-engage/references/config-item-analysis-report.md +0 -1
  50. package/skills/ae-engage/references/config-item-detail.md +0 -1
  51. package/skills/ae-engage/references/config-item-list.md +0 -1
  52. package/skills/ae-engage/references/config-item-strategy-comparison.md +0 -1
  53. package/skills/ae-engage/references/config-item-trigger-report.md +0 -1
  54. package/skills/ae-engage/references/copy-config-template.md +0 -1
  55. package/skills/ae-engage/references/delete-channel.md +0 -1
  56. package/skills/ae-engage/references/delete-config-channel.md +0 -1
  57. package/skills/ae-engage/references/delete-config-item.md +0 -1
  58. package/skills/ae-engage/references/delete-flow.md +0 -1
  59. package/skills/ae-engage/references/flow-ab-split-node-report.md +0 -1
  60. package/skills/ae-engage/references/flow-detail.md +0 -1
  61. package/skills/ae-engage/references/flow-list.md +0 -1
  62. package/skills/ae-engage/references/flow-node-config-schema.md +0 -1
  63. package/skills/ae-engage/references/flow-node-detail-report.md +0 -1
  64. package/skills/ae-engage/references/flow-node-overview-report.md +0 -1
  65. package/skills/ae-engage/references/flow-process-report.md +0 -1
  66. package/skills/ae-engage/references/manage-flow.md +0 -1
  67. package/skills/ae-engage/references/manage-strategy.md +0 -1
  68. package/skills/ae-engage/references/manage-task.md +0 -1
  69. package/skills/ae-engage/references/modify-flow-base-info.md +0 -1
  70. package/skills/ae-engage/references/strategy-detail.md +0 -1
  71. package/skills/ae-engage/references/strategy-list.md +0 -1
  72. package/skills/ae-engage/references/task-data-detail.md +0 -1
  73. package/skills/ae-engage/references/task-data-overview.md +0 -1
  74. package/skills/ae-engage/references/task-detail.md +0 -1
  75. package/skills/ae-engage/references/task-experiment-report.md +0 -1
  76. package/skills/ae-engage/references/task-list.md +0 -1
  77. package/skills/ae-engage/references/task-metric-detail.md +0 -1
  78. package/skills/ae-engage/references/task-stats.md +0 -1
  79. package/skills/ae-engage/references/update-channel-status.md +0 -1
  80. package/skills/ae-engage/references/update-config-channel-status.md +0 -1
  81. package/skills/ae-engage/references/validate-flow-node-config.md +0 -1
  82. package/skills/ae-engage/references/whitelist-list.md +0 -1
  83. package/skills/ae-kb/SKILL.md +1 -0
  84. package/skills/ae-team/SKILL.md +1 -1
  85. package/dist/auth-W2JZ3DKA.js +0 -170
  86. package/dist/chunk-BI5ZVD6T.js +0 -186
  87. package/dist/chunk-MNHE6SSI.js +0 -79
  88. package/dist/chunk-MWWYGZ76.js +0 -130
  89. package/dist/chunk-SRRUNQIM.js +0 -312
  90. package/dist/config-WH3R3IRY.js +0 -258
@@ -1,170 +0,0 @@
1
- import {
2
- printError,
3
- printOutput
4
- } from "./chunk-B4UL2VIJ.js";
5
- import {
6
- clearMcpToken,
7
- loadMcpTokenStore,
8
- setMcpTokenManual,
9
- validateMcpToken
10
- } from "./chunk-2NGWYMLB.js";
11
- import {
12
- clearToken,
13
- getAuthStatus,
14
- getToken,
15
- resolveHost,
16
- setTokenManual,
17
- validateToken
18
- } from "./chunk-SRRUNQIM.js";
19
- import {
20
- loadConfig,
21
- saveConfig
22
- } from "./chunk-BI5ZVD6T.js";
23
- import {
24
- logger
25
- } from "./chunk-MNHE6SSI.js";
26
-
27
- // src/commands/auth.ts
28
- function registerAuth(program) {
29
- const auth = program.command("auth").description("Authentication management");
30
- auth.command("login").description("Login to AE (auto-extract token from Chrome on macOS)").action(async () => {
31
- const host = resolveHost(program.opts().host);
32
- if (!host) {
33
- printError("config", "No AE host configured.", "Run: ae-cli config set-host");
34
- process.exit(1);
35
- }
36
- const config = loadConfig();
37
- if (!config.hosts[host]) {
38
- config.hosts[host] = { label: host };
39
- if (!config.activeHost) {
40
- config.activeHost = host;
41
- }
42
- saveConfig(config);
43
- logger.info(`Host config auto-saved for ${host}`);
44
- process.stderr.write(`[ae-cli] Config saved for ${host}
45
- `);
46
- }
47
- try {
48
- const token = await getToken(host);
49
- logger.info(`Auth login successful for ${host}`);
50
- process.stderr.write(`[ae-cli] Authenticated to ${host}
51
- `);
52
- printOutput({ authenticated: true, host, token: token.slice(0, 8) + "..." }, program.opts().format || "json");
53
- } catch (err) {
54
- printError("auth", err.message);
55
- process.exit(1);
56
- }
57
- });
58
- auth.command("set-token <token>").description("Manually set authentication token for active host").action(async (token) => {
59
- const host = resolveHost(program.opts().host);
60
- if (!host) {
61
- printError("config", "No AE host configured.", "Run: ae-cli config set-host");
62
- process.exit(1);
63
- }
64
- const config = loadConfig();
65
- if (!config.hosts[host]) {
66
- config.hosts[host] = { label: host };
67
- if (!config.activeHost) {
68
- config.activeHost = host;
69
- }
70
- saveConfig(config);
71
- process.stderr.write(`[ae-cli] Config saved for ${host}
72
- `);
73
- printOutput({ saved: true, config }, program.opts().format || "json");
74
- }
75
- process.stderr.write(`[ae-cli] Validating token...
76
- `);
77
- const isValid = await validateToken(token, host);
78
- if (!isValid) {
79
- logger.warn(`Token validation failed for ${host}`);
80
- process.stderr.write(`[ae-cli] Token validation failed
81
- `);
82
- printError("auth", "Invalid token", "Please check your token and try again");
83
- process.exit(1);
84
- }
85
- setTokenManual(token, host);
86
- logger.info(`Token manually set and validated for ${host}`);
87
- process.stderr.write(`[ae-cli] Token verified and saved for ${host}
88
- `);
89
- printOutput({ saved: true, host, verified: true }, program.opts().format || "json");
90
- });
91
- auth.command("status").description("Show current authentication status").action(async () => {
92
- const host = resolveHost(program.opts().host);
93
- if (!host) {
94
- printOutput({ authenticated: false, host: "(none)", hint: "Run: ae-cli config set-host" }, program.opts().format || "json");
95
- return;
96
- }
97
- const tokenStatus = getAuthStatus(host);
98
- const hasValidToken = tokenStatus.authenticated;
99
- const mcpStore = loadMcpTokenStore();
100
- const cachedMcpToken = mcpStore[host];
101
- let hasValidMcpToken = false;
102
- if (cachedMcpToken) {
103
- hasValidMcpToken = await validateMcpToken(cachedMcpToken, host);
104
- }
105
- const authenticated = hasValidToken || hasValidMcpToken;
106
- printOutput({ authenticated, host }, program.opts().format || "json");
107
- });
108
- auth.command("logout").description("Clear stored token for active host").action(() => {
109
- const host = resolveHost(program.opts().host);
110
- if (!host) {
111
- printError("config", "No AE host configured.", "Run: ae-cli config set-host");
112
- process.exit(1);
113
- }
114
- clearToken(host);
115
- process.stderr.write(`[ae-cli] Token cleared for ${host}
116
- `);
117
- printOutput({ cleared: true, host }, program.opts().format || "json");
118
- });
119
- auth.command("set-mcp-token <token>").description("Manually set MCP token for a host").option("--host <host>", "Target host URL (defaults to active host)").action(async (token, opts) => {
120
- const host = opts.host || resolveHost(program.opts().host);
121
- if (!host) {
122
- printError("config", "No AE host configured.", "Use --host <url> or run: ae-cli config set-host");
123
- process.exit(1);
124
- }
125
- const config = loadConfig();
126
- if (!config.hosts[host]) {
127
- config.hosts[host] = { label: host };
128
- if (!config.activeHost) {
129
- config.activeHost = host;
130
- }
131
- saveConfig(config);
132
- process.stderr.write(`[ae-cli] Host config saved for ${host}
133
- `);
134
- }
135
- process.stderr.write(`[ae-cli] Validating MCP token...
136
- `);
137
- const isValid = await validateMcpToken(token, host);
138
- if (!isValid) {
139
- process.stderr.write(`[ae-cli] MCP token validation failed
140
- `);
141
- printError("auth", "Invalid MCP token", "Please check your MCP token and try again");
142
- process.exit(1);
143
- }
144
- setMcpTokenManual(token, host);
145
- process.stderr.write(`[ae-cli] MCP token verified and saved for ${host}
146
- `);
147
- printOutput({ saved: true, host, verified: true, type: "mcp-token" }, program.opts().format || "json");
148
- });
149
- auth.command("clear-mcp-token").description("Clear stored MCP token for a host").option("--host <host>", "Target host URL (defaults to active host)").option("--all", "Clear MCP tokens for all hosts").action((opts) => {
150
- if (opts.all) {
151
- clearMcpToken();
152
- process.stderr.write(`[ae-cli] All MCP tokens cleared
153
- `);
154
- printOutput({ cleared: true, type: "all-mcp-tokens" }, program.opts().format || "json");
155
- return;
156
- }
157
- const host = opts.host || resolveHost(program.opts().host);
158
- if (!host) {
159
- printError("config", "No AE host configured.", "Use --host <url> or run: ae-cli config set-host");
160
- process.exit(1);
161
- }
162
- clearMcpToken(host);
163
- process.stderr.write(`[ae-cli] MCP token cleared for ${host}
164
- `);
165
- printOutput({ cleared: true, host }, program.opts().format || "json");
166
- });
167
- }
168
- export {
169
- registerAuth
170
- };
@@ -1,186 +0,0 @@
1
- import {
2
- logger
3
- } from "./chunk-MNHE6SSI.js";
4
-
5
- // src/core/json-utils.ts
6
- import fs from "fs";
7
- import { createRequire } from "module";
8
- var require2 = createRequire(import.meta.url);
9
- var JSONbig = require2("json-bigint");
10
- var jsonParser = JSONbig({ storeAsString: true });
11
- function safeJsonParse(text) {
12
- return jsonParser.parse(text);
13
- }
14
- function safeReadJsonFile(filePath) {
15
- const content = fs.readFileSync(filePath, "utf-8");
16
- return safeJsonParse(content);
17
- }
18
-
19
- // src/core/config.ts
20
- import fs2 from "fs";
21
- import path from "path";
22
- var CONFIG_DIR = path.join(process.env.HOME || "", ".ae-cli");
23
- var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
24
- var MCP_TOKENS_FILE = path.join(CONFIG_DIR, "mcp-tokens.json");
25
- var FALLBACK_MCP_TOKEN_FILE = "/home/ta/te_agent_ta/.ae-config/mcp-token.json";
26
- function ensureDir() {
27
- if (!fs2.existsSync(CONFIG_DIR)) fs2.mkdirSync(CONFIG_DIR, { recursive: true });
28
- }
29
- function migrateFromFallback() {
30
- if (!fs2.existsSync(FALLBACK_MCP_TOKEN_FILE) || fs2.existsSync(MCP_TOKENS_FILE)) {
31
- return null;
32
- }
33
- return doMigrateFromFallback();
34
- }
35
- function forceMigrateFromFallback() {
36
- if (!fs2.existsSync(FALLBACK_MCP_TOKEN_FILE)) {
37
- return null;
38
- }
39
- return doMigrateFromFallback();
40
- }
41
- function doMigrateFromFallback() {
42
- try {
43
- const fallbackData = safeReadJsonFile(FALLBACK_MCP_TOKEN_FILE);
44
- const tokenStore = {};
45
- if (fallbackData && typeof fallbackData === "object" && !Array.isArray(fallbackData)) {
46
- const url = fallbackData.url;
47
- const token = fallbackData["mcp-token"];
48
- if (url && token) {
49
- tokenStore[url] = token;
50
- }
51
- }
52
- if (Object.keys(tokenStore).length > 0) {
53
- ensureDir();
54
- fs2.writeFileSync(MCP_TOKENS_FILE, JSON.stringify(tokenStore, null, 2));
55
- return tokenStore;
56
- }
57
- } catch {
58
- }
59
- return null;
60
- }
61
- function loadConfig() {
62
- try {
63
- const migratedTokens = migrateFromFallback();
64
- if (fs2.existsSync(CONFIG_FILE)) {
65
- const raw = safeReadJsonFile(CONFIG_FILE);
66
- if (raw.defaultHost && !raw.activeHost) {
67
- const migrated = migrateConfig(raw);
68
- saveConfig(migrated);
69
- return migrated;
70
- }
71
- return raw;
72
- }
73
- if (migratedTokens && Object.keys(migratedTokens).length > 0) {
74
- const hosts = {};
75
- for (const url of Object.keys(migratedTokens)) {
76
- hosts[url] = { label: url };
77
- process.stderr.write(`[ae-cli] Added host: ${url}
78
- `);
79
- }
80
- const activeHost = Object.keys(migratedTokens)[0];
81
- process.stderr.write(`[ae-cli] Active host set to: ${activeHost}
82
- `);
83
- process.stderr.write(`[ae-cli] MCP tokens migrated from ${FALLBACK_MCP_TOKEN_FILE}
84
- `);
85
- logger.info(`MCP tokens migrated from fallback: activeHost=${activeHost}, hosts=${Object.keys(hosts).length}`);
86
- const config = { activeHost, hosts };
87
- saveConfig(config);
88
- return config;
89
- }
90
- } catch (err) {
91
- logger.error(`Error loading config: ${err.message}`);
92
- console.error(`Error loading config: ${err.message}`);
93
- }
94
- return { activeHost: "", hosts: {} };
95
- }
96
- function migrateConfig(old) {
97
- const hosts = {};
98
- const oldHost = old.defaultHost;
99
- if (old.hosts) {
100
- for (const [key, val] of Object.entries(old.hosts)) {
101
- const url = key.startsWith("http") ? key : `https://${key}`;
102
- hosts[url] = val;
103
- }
104
- }
105
- const activeHost = oldHost.startsWith("http") ? oldHost : `https://${oldHost}`;
106
- if (!hosts[activeHost]) {
107
- hosts[activeHost] = { label: "default" };
108
- }
109
- return { activeHost, hosts };
110
- }
111
- function saveConfig(config) {
112
- ensureDir();
113
- fs2.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
114
- logger.info(`Config saved: activeHost=${config.activeHost}, hosts=${Object.keys(config.hosts).length}`);
115
- }
116
- function getActiveHost() {
117
- const config = loadConfig();
118
- return config.activeHost;
119
- }
120
- function setActiveHost(url) {
121
- const config = loadConfig();
122
- if (!config.hosts[url]) {
123
- throw new Error(`Host ${url} is not in the configured hosts list. Add it first.`);
124
- }
125
- config.activeHost = url;
126
- saveConfig(config);
127
- }
128
- function addHost(url, label) {
129
- const config = loadConfig();
130
- config.hosts[url] = { label };
131
- if (!config.activeHost) {
132
- config.activeHost = url;
133
- }
134
- saveConfig(config);
135
- }
136
- function updateHostLabel(url, label) {
137
- const config = loadConfig();
138
- if (config.hosts[url]) {
139
- config.hosts[url].label = label;
140
- saveConfig(config);
141
- }
142
- }
143
- function removeHost(url) {
144
- const config = loadConfig();
145
- delete config.hosts[url];
146
- if (config.activeHost === url) {
147
- const remaining = Object.keys(config.hosts);
148
- config.activeHost = remaining.length > 0 ? remaining[0] : "";
149
- }
150
- saveConfig(config);
151
- }
152
- function listHosts() {
153
- const config = loadConfig();
154
- return Object.entries(config.hosts).map(([url, entry]) => ({
155
- url,
156
- label: entry.label,
157
- active: url === config.activeHost
158
- }));
159
- }
160
- function getConfigDir() {
161
- return CONFIG_DIR;
162
- }
163
- function extractHostname(fullUrl) {
164
- try {
165
- const u = new URL(fullUrl);
166
- return u.host;
167
- } catch {
168
- return fullUrl;
169
- }
170
- }
171
-
172
- export {
173
- safeJsonParse,
174
- safeReadJsonFile,
175
- forceMigrateFromFallback,
176
- loadConfig,
177
- saveConfig,
178
- getActiveHost,
179
- setActiveHost,
180
- addHost,
181
- updateHostLabel,
182
- removeHost,
183
- listHosts,
184
- getConfigDir,
185
- extractHostname
186
- };
@@ -1,79 +0,0 @@
1
- // src/core/logger.ts
2
- import fs from "fs";
3
- import path from "path";
4
- var LOG_DIR = path.join(process.env.HOME || "", ".ae-cli", "log");
5
- var Logger = class {
6
- logDir;
7
- date;
8
- constructor() {
9
- this.logDir = LOG_DIR;
10
- this.date = this.today();
11
- this.ensureDir();
12
- }
13
- today() {
14
- const d = /* @__PURE__ */ new Date();
15
- return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}${String(d.getDate()).padStart(2, "0")}`;
16
- }
17
- timestamp() {
18
- return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").split(".")[0];
19
- }
20
- ensureDir() {
21
- if (!fs.existsSync(this.logDir)) {
22
- fs.mkdirSync(this.logDir, { recursive: true });
23
- }
24
- }
25
- filePath(level) {
26
- const today = this.today();
27
- if (today !== this.date) {
28
- this.date = today;
29
- }
30
- return path.join(this.logDir, `${this.date}_${level}.log`);
31
- }
32
- /**
33
- * 写入日志到文件(不输出到控制台,控制台由现有 process.stderr.write 负责)
34
- */
35
- write(level, message) {
36
- const ts = this.timestamp();
37
- const line = `[${ts}] ${message}
38
- `;
39
- try {
40
- fs.appendFileSync(this.filePath(level), line);
41
- } catch {
42
- }
43
- }
44
- /** 常规操作日志 */
45
- info(message) {
46
- this.write("info", message);
47
- }
48
- /** 警告日志 */
49
- warn(message) {
50
- this.write("warning", message);
51
- }
52
- /** 错误日志 */
53
- error(message) {
54
- this.write("error", message);
55
- }
56
- /** 记录 HTTP API 请求详情 */
57
- api(method, url, status, reqBody, respBody) {
58
- const parts = [`API ${method} ${url} \u2192 HTTP ${status}`];
59
- if (reqBody !== void 0 && reqBody !== null) {
60
- const s = typeof reqBody === "string" ? reqBody : JSON.stringify(reqBody);
61
- parts.push(`REQ: ${s.slice(0, 500)}`);
62
- }
63
- if (respBody !== void 0 && respBody !== null) {
64
- const s = typeof respBody === "string" ? respBody : JSON.stringify(respBody);
65
- parts.push(`RESP: ${s.slice(0, 500)}`);
66
- }
67
- this.info(parts.join(" | "));
68
- }
69
- /** 记录命令执行 */
70
- command(name, args) {
71
- const filtered = Object.entries(args).filter(([, v]) => v !== void 0 && v !== null && v !== "").map(([k, v]) => `--${k}=${JSON.stringify(v)}`).join(" ");
72
- this.info(`CMD ${name}${filtered ? " " + filtered : ""}`);
73
- }
74
- };
75
- var logger = new Logger();
76
-
77
- export {
78
- logger
79
- };
@@ -1,130 +0,0 @@
1
- import {
2
- loadMcpTokenStore
3
- } from "./chunk-2NGWYMLB.js";
4
- import {
5
- forceMigrateFromFallback,
6
- safeJsonParse
7
- } from "./chunk-BI5ZVD6T.js";
8
- import {
9
- logger
10
- } from "./chunk-MNHE6SSI.js";
11
-
12
- // src/core/mcp-access.ts
13
- function buildUrl(host, path, params = {}) {
14
- const base = host.replace(/\/$/, "");
15
- const p = path.startsWith("/") ? path : `/${path}`;
16
- const url = new URL(`${base}${p}`);
17
- for (const [key, value] of Object.entries(params)) {
18
- if (value !== void 0 && value !== null) {
19
- url.searchParams.set(key, String(value));
20
- }
21
- }
22
- return url.toString();
23
- }
24
- function getMcpTokenForHost(host) {
25
- const store = loadMcpTokenStore();
26
- const normalizedHost = host.replace(/\/+$/, "");
27
- if (store[host]) return store[host];
28
- if (store[normalizedHost]) return store[normalizedHost];
29
- for (const [key, token] of Object.entries(store)) {
30
- if (key.replace(/\/+$/, "") === normalizedHost) {
31
- return token;
32
- }
33
- }
34
- return void 0;
35
- }
36
- function getTokenFromStore(store, host) {
37
- const normalizedHost = host.replace(/\/+$/, "");
38
- if (store[host]) return store[host];
39
- if (store[normalizedHost]) return store[normalizedHost];
40
- for (const [key, token] of Object.entries(store)) {
41
- if (key.replace(/\/+$/, "") === normalizedHost) {
42
- return token;
43
- }
44
- }
45
- return void 0;
46
- }
47
- function refreshMcpTokenFromFallback(host) {
48
- logger.warn(`KB MCP request failed for ${host}, trying fallback`);
49
- const migrated = forceMigrateFromFallback();
50
- const token = migrated ? getTokenFromStore(migrated, host) : void 0;
51
- if (token) {
52
- logger.info(`KB MCP token refreshed from fallback for ${host}`);
53
- process.stderr.write(`[ae-cli] MCP token refreshed from fallback for ${host}
54
- `);
55
- }
56
- return token;
57
- }
58
- function isMcpAuthFailure(resp, data) {
59
- return !resp.ok || data.return_code === -1001;
60
- }
61
- function parseKbResponse(resp, text) {
62
- if (resp.status === 401 || resp.status === 403) {
63
- throw new Error(`KB MCP token auth failed: HTTP ${resp.status} ${resp.statusText}`);
64
- }
65
- const data = safeJsonParse(text);
66
- if (data.return_code === -1001) {
67
- throw new Error(`KB MCP token auth failed: ${data.return_message || "unauthorized"} (code: ${data.return_code})`);
68
- }
69
- if (data.return_code !== 0 && data.return_code !== void 0) {
70
- throw new Error(`AE API error: ${data.return_message || "unknown"} (code: ${data.return_code})`);
71
- }
72
- return data.data !== void 0 ? data.data : data;
73
- }
74
- async function fetchWithMcpToken(host, input, init, mcpToken) {
75
- const headers = new Headers(init.headers);
76
- headers.set("mcp-token", mcpToken);
77
- const resp = await fetch(input, { ...init, headers });
78
- const text = await resp.text();
79
- if (!resp.ok) {
80
- const refreshedToken = refreshMcpTokenFromFallback(host);
81
- if (refreshedToken) {
82
- headers.set("mcp-token", refreshedToken);
83
- const retryResp = await fetch(input, { ...init, headers });
84
- return parseKbResponse(retryResp, await retryResp.text());
85
- }
86
- return parseKbResponse(resp, text);
87
- }
88
- const data = safeJsonParse(text);
89
- if (isMcpAuthFailure(resp, data)) {
90
- const refreshedToken = refreshMcpTokenFromFallback(host);
91
- if (refreshedToken) {
92
- headers.set("mcp-token", refreshedToken);
93
- const retryResp = await fetch(input, { ...init, headers });
94
- return parseKbResponse(retryResp, await retryResp.text());
95
- }
96
- }
97
- return parseKbResponse(resp, text);
98
- }
99
- async function kbApi(ctx, method, path, params = {}, body) {
100
- const host = ctx.host();
101
- const mcpToken = getMcpTokenForHost(host);
102
- if (!mcpToken) {
103
- return ctx.api(method, path, params, body);
104
- }
105
- const upperMethod = method.toUpperCase();
106
- return fetchWithMcpToken(host, buildUrl(host, path, params), {
107
- method: upperMethod,
108
- headers: {
109
- "Content-Type": "application/json"
110
- },
111
- body: upperMethod === "GET" ? void 0 : JSON.stringify(body ?? {})
112
- }, mcpToken);
113
- }
114
- async function kbUpload(ctx, path, form, params = {}) {
115
- const host = ctx.host();
116
- const mcpToken = getMcpTokenForHost(host);
117
- if (!mcpToken) {
118
- const { httpUpload } = await import("./client-IU2E5IOL.js");
119
- return httpUpload(path, form, params, host);
120
- }
121
- return fetchWithMcpToken(host, buildUrl(host, path, params), {
122
- method: "POST",
123
- body: form
124
- }, mcpToken);
125
- }
126
-
127
- export {
128
- kbApi,
129
- kbUpload
130
- };