@thinkingai/ae-cli 1.0.22 → 1.0.24
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.
- package/README.md +24 -1
- package/README.zh.md +24 -1
- package/dist/{auth-YM7OI23X.js → auth-4OPL4YWG.js} +2 -2
- package/dist/{auth-5S7SPPEJ.js → auth-PBPAZQWP.js} +9 -4
- package/dist/{chunk-24ZKQWG2.js → chunk-47MTN54I.js} +24 -4
- package/dist/{chunk-TMMUBSKW.js → chunk-DC66L5AM.js} +93 -13
- package/dist/{chunk-KM57HI5B.js → chunk-JJCRURTR.js} +7 -1
- package/dist/{chunk-NBFTPIAH.js → chunk-MZW6NOVS.js} +9 -4
- package/dist/{chunk-MPFTXJFG.js → chunk-OVHL4JAC.js} +12 -2
- package/dist/{client-7S23DVHH.js → client-TDH6MUWM.js} +3 -3
- package/dist/{config-RVUESJRF.js → config-5ELRYAIH.js} +2 -2
- package/dist/index.js +167 -20
- package/dist/{raw-5SYAUCJQ.js → raw-EM7AP3RT.js} +4 -4
- package/dist/{te-analysis-RQST6AT3.js → te-analysis-3KFSNUCJ.js} +23 -4
- package/dist/{te-audience-TJ74UJI3.js → te-audience-GMYJFCSC.js} +3 -3
- package/dist/{te-common-W5URM2SH.js → te-common-YLERCMQI.js} +3 -3
- package/dist/{te-community-YRV2VAD4.js → te-community-PYDN5A6B.js} +3 -3
- package/dist/{te-dataops-ZPH72BCK.js → te-dataops-ETWS5O3X.js} +3 -3
- package/dist/{te-engage-57UKFV74.js → te-engage-ROJVZHDA.js} +3 -3
- package/dist/{te-kb-GD7SJRYB.js → te-kb-VUNS2CC7.js} +5 -12
- package/dist/{te-meta-25SLZFXJ.js → te-meta-3EFWLM3A.js} +24 -4
- package/package.json +2 -1
- package/skills/ae-analysis/references/create_entity.md +39 -0
- package/skills/ae-analysis/references/create_space.md +34 -0
package/README.md
CHANGED
|
@@ -60,6 +60,14 @@ ae-cli analysis_meta +list_events --project_id 1 --format table
|
|
|
60
60
|
|
|
61
61
|
# Raw API call
|
|
62
62
|
ae-cli api GET /v1/ta/event/catalog/listEvent --params '{"projectId": 1}'
|
|
63
|
+
|
|
64
|
+
# Knowledge base (create → upload → compile → query)
|
|
65
|
+
ae-cli kb +new --scope company --name engineering-handbook --description "Team docs"
|
|
66
|
+
ae-cli kb +add --name engineering-handbook --files '["./docs/guide.md","https://example.com/page"]'
|
|
67
|
+
ae-cli kb +schema --name engineering-handbook
|
|
68
|
+
ae-cli kb +compile --name engineering-handbook
|
|
69
|
+
ae-cli kb +query -q "How to configure sandbox?" \
|
|
70
|
+
--sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
63
71
|
```
|
|
64
72
|
|
|
65
73
|
## Authentication
|
|
@@ -97,8 +105,21 @@ ae-cli auth logout
|
|
|
97
105
|
| `dataops_integration` | 20+ | Data integration: datasource management, sync solutions, data synchronization |
|
|
98
106
|
| `community` | 10+ | Community analysis: posts search, sentiment analysis, topic trends, livestream data |
|
|
99
107
|
| `analysis_common` | 2 | Cross-module common constraints: resource link completion, project ID gate |
|
|
108
|
+
| `kb` | 7 | Knowledge base lifecycle: query / new / add (md/dir/url) / schema / compile / rm-source / remove |
|
|
100
109
|
| `auth` / `config` | 2 | Authentication and host configuration |
|
|
101
110
|
|
|
111
|
+
### kb
|
|
112
|
+
|
|
113
|
+
Knowledge base lifecycle (`+new` → `+add` → `+schema` → `+compile` → `+query`):
|
|
114
|
+
|
|
115
|
+
- **Create** (`+new`): `--scope personal|company`, `--name`, optional `--description`, `--tags`, `--project-id`, `--project-name`
|
|
116
|
+
- **Upload** (`+add`): `--name`, `--files` JSON array (`.md` file, directory non-recursive scan, or http(s) URL with HTML-to-Markdown conversion)
|
|
117
|
+
- **Schema** (`+schema`): `--name`, optional `--force`, `--model`
|
|
118
|
+
- **Compile** (`+compile`): `--name`, `--mode incremental|full` (default: incremental)
|
|
119
|
+
- **Query** (`+query`): `--query` / `-q`, `--sources` JSON refs e.g. `[{"scope":"company","name":"engineering-handbook"}]`
|
|
120
|
+
- **Remove source** (`+rm-source`): `--name`, `--display-name`
|
|
121
|
+
- **Remove KB** (`+remove`): `--name`
|
|
122
|
+
|
|
102
123
|
### Global Options
|
|
103
124
|
|
|
104
125
|
| Option | Description | Default |
|
|
@@ -108,6 +129,7 @@ ae-cli auth logout
|
|
|
108
129
|
| `--jq <expr>` | Filter expression | - |
|
|
109
130
|
| `--dry-run` | Preview request | false |
|
|
110
131
|
| `--yes` | Skip confirmation | false |
|
|
132
|
+
| `--no-update-check` | Skip checking for newer ae-cli versions | false |
|
|
111
133
|
|
|
112
134
|
## Skills
|
|
113
135
|
|
|
@@ -185,7 +207,8 @@ src/
|
|
|
185
207
|
├── te-engage/
|
|
186
208
|
├── te-dataops/
|
|
187
209
|
├── te-community/
|
|
188
|
-
|
|
210
|
+
├── te-common/
|
|
211
|
+
└── te-kb/
|
|
189
212
|
```
|
|
190
213
|
|
|
191
214
|
## Verification Scripts
|
package/README.zh.md
CHANGED
|
@@ -60,6 +60,14 @@ ae-cli analysis_meta +list_events --project_id 1 --format table
|
|
|
60
60
|
|
|
61
61
|
# 原始 API 调用
|
|
62
62
|
ae-cli api GET /v1/ta/event/catalog/listEvent --params '{"projectId": 1}'
|
|
63
|
+
|
|
64
|
+
# 知识库(新建 → 上传 → 编译 → 查询)
|
|
65
|
+
ae-cli kb +new --scope company --name engineering-handbook --description "Team docs"
|
|
66
|
+
ae-cli kb +add --name engineering-handbook --files '["./docs/guide.md","https://example.com/page"]'
|
|
67
|
+
ae-cli kb +schema --name engineering-handbook
|
|
68
|
+
ae-cli kb +compile --name engineering-handbook
|
|
69
|
+
ae-cli kb +query -q "如何配置 sandbox 容器?" \
|
|
70
|
+
--sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
63
71
|
```
|
|
64
72
|
|
|
65
73
|
## 身份验证
|
|
@@ -97,8 +105,21 @@ ae-cli auth logout
|
|
|
97
105
|
| `dataops_integration` | 20+ | 数据集成:数据源管理、同步方案、数据同步 |
|
|
98
106
|
| `community` | 10+ | 社区分析:帖子搜索、情感分析、话题趋势、直播数据 |
|
|
99
107
|
| `analysis_common` | 2 | 跨模块通用约束:资源链接补全、项目 ID 门控 |
|
|
108
|
+
| `kb` | 7 | 知识库生命周期:查询 / 新建 / 添加源(md/目录/url)/ schema / 编译 / 删除源 / 删除 |
|
|
100
109
|
| `auth` / `config` | 2 | 身份验证和主机配置 |
|
|
101
110
|
|
|
111
|
+
### kb(知识库)
|
|
112
|
+
|
|
113
|
+
知识库生命周期(`+new` → `+add` → `+schema` → `+compile` → `+query`):
|
|
114
|
+
|
|
115
|
+
- **新建** (`+new`):`--scope personal|company`,`--name`,可选 `--description`、`--tags`、`--project-id`、`--project-name`
|
|
116
|
+
- **上传源** (`+add`):`--name`,`--files` JSON 数组(`.md` 文件、目录非递归扫描、或 http(s) URL 自动转 Markdown)
|
|
117
|
+
- **生成 schema** (`+schema`):`--name`,可选 `--force`、`--model`
|
|
118
|
+
- **编译** (`+compile`):`--name`,`--mode incremental|full`(默认 incremental)
|
|
119
|
+
- **查询** (`+query`):`--query` / `-q`,`--sources` JSON 引用,如 `[{"scope":"company","name":"engineering-handbook"}]`
|
|
120
|
+
- **删除源** (`+rm-source`):`--name`,`--display-name`
|
|
121
|
+
- **删除知识库** (`+remove`):`--name`
|
|
122
|
+
|
|
102
123
|
### 全局选项
|
|
103
124
|
|
|
104
125
|
| 选项 | 描述 | 默认值 |
|
|
@@ -108,6 +129,7 @@ ae-cli auth logout
|
|
|
108
129
|
| `--jq <expr>` | 过滤表达式 | - |
|
|
109
130
|
| `--dry-run` | 预览请求 | false |
|
|
110
131
|
| `--yes` | 跳过确认 | false |
|
|
132
|
+
| `--no-update-check` | 跳过 ae-cli 新版本检查 | false |
|
|
111
133
|
|
|
112
134
|
## Skills
|
|
113
135
|
|
|
@@ -185,7 +207,8 @@ src/
|
|
|
185
207
|
├── te-engage/
|
|
186
208
|
├── te-dataops/
|
|
187
209
|
├── te-community/
|
|
188
|
-
|
|
210
|
+
├── te-common/
|
|
211
|
+
└── te-kb/
|
|
189
212
|
```
|
|
190
213
|
|
|
191
214
|
## 验证脚本
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
printError,
|
|
3
3
|
printOutput
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JJCRURTR.js";
|
|
5
5
|
import {
|
|
6
6
|
clearMcpToken,
|
|
7
7
|
loadMcpTokenStore,
|
|
8
8
|
setMcpTokenManual,
|
|
9
9
|
validateMcpToken
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OVHL4JAC.js";
|
|
11
11
|
import {
|
|
12
12
|
clearToken,
|
|
13
13
|
getAuthStatus,
|
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
resolveHost,
|
|
16
16
|
setTokenManual,
|
|
17
17
|
validateToken
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-47MTN54I.js";
|
|
19
19
|
import {
|
|
20
20
|
loadConfig,
|
|
21
|
+
logger,
|
|
21
22
|
saveConfig
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-DC66L5AM.js";
|
|
23
24
|
|
|
24
25
|
// src/commands/auth.ts
|
|
25
26
|
function registerAuth(program) {
|
|
@@ -37,11 +38,13 @@ function registerAuth(program) {
|
|
|
37
38
|
config.activeHost = host;
|
|
38
39
|
}
|
|
39
40
|
saveConfig(config);
|
|
41
|
+
logger.info(`Host config auto-saved for ${host}`);
|
|
40
42
|
process.stderr.write(`[ae-cli] Config saved for ${host}
|
|
41
43
|
`);
|
|
42
44
|
}
|
|
43
45
|
try {
|
|
44
46
|
const token = await getToken(host);
|
|
47
|
+
logger.info(`Auth login successful for ${host}`);
|
|
45
48
|
process.stderr.write(`[ae-cli] Authenticated to ${host}
|
|
46
49
|
`);
|
|
47
50
|
printOutput({ authenticated: true, host, token: token.slice(0, 8) + "..." }, program.opts().format || "json");
|
|
@@ -71,12 +74,14 @@ function registerAuth(program) {
|
|
|
71
74
|
`);
|
|
72
75
|
const isValid = await validateToken(token, host);
|
|
73
76
|
if (!isValid) {
|
|
77
|
+
logger.warn(`Token validation failed for ${host}`);
|
|
74
78
|
process.stderr.write(`[ae-cli] Token validation failed
|
|
75
79
|
`);
|
|
76
80
|
printError("auth", "Invalid token", "Please check your token and try again");
|
|
77
81
|
process.exit(1);
|
|
78
82
|
}
|
|
79
83
|
setTokenManual(token, host);
|
|
84
|
+
logger.info(`Token manually set and validated for ${host}`);
|
|
80
85
|
process.stderr.write(`[ae-cli] Token verified and saved for ${host}
|
|
81
86
|
`);
|
|
82
87
|
printOutput({ saved: true, host, verified: true }, program.opts().format || "json");
|
|
@@ -2,9 +2,10 @@ import {
|
|
|
2
2
|
extractHostname,
|
|
3
3
|
getActiveHost,
|
|
4
4
|
getConfigDir,
|
|
5
|
+
logger,
|
|
5
6
|
safeJsonParse,
|
|
6
7
|
safeReadJsonFile
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DC66L5AM.js";
|
|
8
9
|
|
|
9
10
|
// src/core/auth.ts
|
|
10
11
|
import fs from "fs";
|
|
@@ -90,6 +91,7 @@ function saveToken(token, hostUrl) {
|
|
|
90
91
|
const tokens = loadAllTokens();
|
|
91
92
|
tokens[hostUrl] = { token, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
92
93
|
saveAllTokens(tokens);
|
|
94
|
+
logger.info(`Token saved for ${hostUrl}`);
|
|
93
95
|
}
|
|
94
96
|
function clearToken(hostUrl) {
|
|
95
97
|
const tokens = loadAllTokens();
|
|
@@ -172,6 +174,7 @@ function extractTokenFromAllTabs() {
|
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
176
|
async function requestTokenViaOsascript(hostUrl) {
|
|
177
|
+
logger.info(`Opening Chrome to ${hostUrl} for token extraction`);
|
|
175
178
|
process.stderr.write(`[ae-cli] No AE tab found in Chrome. Opening ${hostUrl} ...
|
|
176
179
|
`);
|
|
177
180
|
process.stderr.write(`[ae-cli] Please login, then your token will be captured automatically.
|
|
@@ -189,24 +192,36 @@ async function requestTokenViaOsascript(hostUrl) {
|
|
|
189
192
|
];
|
|
190
193
|
execFileSync("osascript", openScript.flatMap((line) => ["-e", line]), { timeout: 5e3 });
|
|
191
194
|
} catch {
|
|
195
|
+
logger.warn(`Failed to open Chrome, user may need to open ${hostUrl} manually`);
|
|
192
196
|
process.stderr.write(`[ae-cli] Could not open browser. Please open ${hostUrl} in Chrome manually.
|
|
193
197
|
`);
|
|
194
198
|
}
|
|
195
199
|
const deadline = Date.now() + OSASCRIPT_POLL_TIMEOUT_MS;
|
|
200
|
+
let pollCount = 0;
|
|
196
201
|
while (Date.now() < deadline) {
|
|
197
202
|
await new Promise((r) => setTimeout(r, OSASCRIPT_POLL_INTERVAL_MS));
|
|
203
|
+
pollCount++;
|
|
198
204
|
let result = extractTokenViaOsascript(hostUrl);
|
|
199
205
|
if (result.error === "no_tab") {
|
|
200
206
|
const fallback = extractTokenFromAllTabs();
|
|
201
|
-
if (fallback.token)
|
|
207
|
+
if (fallback.token) {
|
|
208
|
+
logger.info("Token captured via all-tabs fallback search");
|
|
209
|
+
result = fallback;
|
|
210
|
+
}
|
|
202
211
|
}
|
|
203
212
|
if (result.token) {
|
|
213
|
+
saveToken(result.token, hostUrl);
|
|
214
|
+
logger.info(`Token captured after ${pollCount} poll(s)`);
|
|
204
215
|
process.stderr.write(`[ae-cli] Token captured from Chrome for ${hostUrl}.
|
|
205
216
|
`);
|
|
206
217
|
return result.token;
|
|
207
218
|
}
|
|
208
|
-
if (result.error === "no_js_permission")
|
|
219
|
+
if (result.error === "no_js_permission") {
|
|
220
|
+
logger.warn("Chrome JS permission denied during polling");
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
209
223
|
}
|
|
224
|
+
logger.warn(`Token polling timed out after ${OSASCRIPT_POLL_TIMEOUT_MS / 1e3}s (${pollCount} polls)`);
|
|
210
225
|
process.stderr.write(`[ae-cli] Polling timed out after ${OSASCRIPT_POLL_TIMEOUT_MS / 1e3}s.
|
|
211
226
|
`);
|
|
212
227
|
return null;
|
|
@@ -219,12 +234,17 @@ Run: ae-cli config set-host`
|
|
|
219
234
|
);
|
|
220
235
|
}
|
|
221
236
|
if (process.env.TE_TOKEN) {
|
|
237
|
+
logger.info("Using token from env:TE_TOKEN");
|
|
222
238
|
return process.env.TE_TOKEN;
|
|
223
239
|
}
|
|
224
240
|
const cached = loadToken(hostUrl);
|
|
225
|
-
if (cached && cached.token)
|
|
241
|
+
if (cached && cached.token) {
|
|
242
|
+
logger.info(`Using cached token for ${hostUrl}`);
|
|
243
|
+
return cached.token;
|
|
244
|
+
}
|
|
226
245
|
const { token: osascriptToken, error } = extractTokenViaOsascript(hostUrl);
|
|
227
246
|
if (error === "no_js_permission") {
|
|
247
|
+
logger.warn("Chrome JS Apple Events not enabled");
|
|
228
248
|
throw new Error(
|
|
229
249
|
`Chrome JavaScript from Apple Events is not enabled.
|
|
230
250
|
Enable it: Chrome menu \u2192 View \u2192 Developer \u2192 Allow JavaScript from Apple Events`
|
|
@@ -1,5 +1,81 @@
|
|
|
1
|
-
// src/core/
|
|
1
|
+
// src/core/logger.ts
|
|
2
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
|
+
// src/core/json-utils.ts
|
|
78
|
+
import fs2 from "fs";
|
|
3
79
|
import { createRequire } from "module";
|
|
4
80
|
var require2 = createRequire(import.meta.url);
|
|
5
81
|
var JSONbig = require2("json-bigint");
|
|
@@ -8,28 +84,28 @@ function safeJsonParse(text) {
|
|
|
8
84
|
return jsonParser.parse(text);
|
|
9
85
|
}
|
|
10
86
|
function safeReadJsonFile(filePath) {
|
|
11
|
-
const content =
|
|
87
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
12
88
|
return safeJsonParse(content);
|
|
13
89
|
}
|
|
14
90
|
|
|
15
91
|
// src/core/config.ts
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
var CONFIG_DIR =
|
|
19
|
-
var CONFIG_FILE =
|
|
20
|
-
var MCP_TOKENS_FILE =
|
|
92
|
+
import fs3 from "fs";
|
|
93
|
+
import path2 from "path";
|
|
94
|
+
var CONFIG_DIR = path2.join(process.env.HOME || "", ".ae-cli");
|
|
95
|
+
var CONFIG_FILE = path2.join(CONFIG_DIR, "config.json");
|
|
96
|
+
var MCP_TOKENS_FILE = path2.join(CONFIG_DIR, "mcp-tokens.json");
|
|
21
97
|
var FALLBACK_MCP_TOKEN_FILE = "/data/app/te_agent_ta/.ae-config/mcp-token.json";
|
|
22
98
|
function ensureDir() {
|
|
23
|
-
if (!
|
|
99
|
+
if (!fs3.existsSync(CONFIG_DIR)) fs3.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
24
100
|
}
|
|
25
101
|
function migrateFromFallback() {
|
|
26
|
-
if (!
|
|
102
|
+
if (!fs3.existsSync(FALLBACK_MCP_TOKEN_FILE) || fs3.existsSync(MCP_TOKENS_FILE)) {
|
|
27
103
|
return null;
|
|
28
104
|
}
|
|
29
105
|
return doMigrateFromFallback();
|
|
30
106
|
}
|
|
31
107
|
function forceMigrateFromFallback() {
|
|
32
|
-
if (!
|
|
108
|
+
if (!fs3.existsSync(FALLBACK_MCP_TOKEN_FILE)) {
|
|
33
109
|
return null;
|
|
34
110
|
}
|
|
35
111
|
return doMigrateFromFallback();
|
|
@@ -47,7 +123,7 @@ function doMigrateFromFallback() {
|
|
|
47
123
|
}
|
|
48
124
|
if (Object.keys(tokenStore).length > 0) {
|
|
49
125
|
ensureDir();
|
|
50
|
-
|
|
126
|
+
fs3.writeFileSync(MCP_TOKENS_FILE, JSON.stringify(tokenStore, null, 2));
|
|
51
127
|
return tokenStore;
|
|
52
128
|
}
|
|
53
129
|
} catch {
|
|
@@ -57,7 +133,7 @@ function doMigrateFromFallback() {
|
|
|
57
133
|
function loadConfig() {
|
|
58
134
|
try {
|
|
59
135
|
const migratedTokens = migrateFromFallback();
|
|
60
|
-
if (
|
|
136
|
+
if (fs3.existsSync(CONFIG_FILE)) {
|
|
61
137
|
const raw = safeReadJsonFile(CONFIG_FILE);
|
|
62
138
|
if (raw.defaultHost && !raw.activeHost) {
|
|
63
139
|
const migrated = migrateConfig(raw);
|
|
@@ -78,11 +154,13 @@ function loadConfig() {
|
|
|
78
154
|
`);
|
|
79
155
|
process.stderr.write(`[ae-cli] MCP tokens migrated from ${FALLBACK_MCP_TOKEN_FILE}
|
|
80
156
|
`);
|
|
157
|
+
logger.info(`MCP tokens migrated from fallback: activeHost=${activeHost}, hosts=${Object.keys(hosts).length}`);
|
|
81
158
|
const config = { activeHost, hosts };
|
|
82
159
|
saveConfig(config);
|
|
83
160
|
return config;
|
|
84
161
|
}
|
|
85
162
|
} catch (err) {
|
|
163
|
+
logger.error(`Error loading config: ${err.message}`);
|
|
86
164
|
console.error(`Error loading config: ${err.message}`);
|
|
87
165
|
}
|
|
88
166
|
return { activeHost: "", hosts: {} };
|
|
@@ -104,7 +182,8 @@ function migrateConfig(old) {
|
|
|
104
182
|
}
|
|
105
183
|
function saveConfig(config) {
|
|
106
184
|
ensureDir();
|
|
107
|
-
|
|
185
|
+
fs3.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
186
|
+
logger.info(`Config saved: activeHost=${config.activeHost}, hosts=${Object.keys(config.hosts).length}`);
|
|
108
187
|
}
|
|
109
188
|
function getActiveHost() {
|
|
110
189
|
const config = loadConfig();
|
|
@@ -163,6 +242,7 @@ function extractHostname(fullUrl) {
|
|
|
163
242
|
}
|
|
164
243
|
|
|
165
244
|
export {
|
|
245
|
+
logger,
|
|
166
246
|
safeJsonParse,
|
|
167
247
|
safeReadJsonFile,
|
|
168
248
|
forceMigrateFromFallback,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
logger
|
|
3
|
+
} from "./chunk-DC66L5AM.js";
|
|
4
|
+
|
|
1
5
|
// src/framework/output.ts
|
|
2
6
|
import Table from "cli-table3";
|
|
3
7
|
var KNOWN_ARRAY_FIELDS = [
|
|
@@ -95,7 +99,9 @@ function formatError(type, message, hint, code) {
|
|
|
95
99
|
return JSON.stringify(envelope, null, 2);
|
|
96
100
|
}
|
|
97
101
|
function printError(type, message, hint, code) {
|
|
98
|
-
|
|
102
|
+
const formatted = formatError(type, message, hint, code);
|
|
103
|
+
process.stderr.write(formatted + "\n");
|
|
104
|
+
logger.error(`[${type}] ${message}${hint ? " | " + hint : ""}`);
|
|
99
105
|
}
|
|
100
106
|
function printOutput(data, format, jqExpr) {
|
|
101
107
|
process.stdout.write(formatOutput(data, format, jqExpr) + "\n");
|
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
clearToken,
|
|
3
3
|
getToken,
|
|
4
4
|
resolveHost
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-47MTN54I.js";
|
|
6
6
|
import {
|
|
7
|
+
logger,
|
|
7
8
|
safeJsonParse
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DC66L5AM.js";
|
|
9
10
|
|
|
10
11
|
// src/core/client.ts
|
|
11
12
|
import WebSocket from "ws";
|
|
@@ -39,11 +40,13 @@ async function request(method, modulePath, params = {}, body = null, retry = tru
|
|
|
39
40
|
const options = { method, headers };
|
|
40
41
|
if (body && method !== "GET") options.body = JSON.stringify(body);
|
|
41
42
|
const resp = await fetch(url, options);
|
|
43
|
+
const text = await resp.text();
|
|
44
|
+
const data = safeJsonParse(text);
|
|
45
|
+
logger.api(method, url, resp.status, body, data);
|
|
42
46
|
if ((resp.status === 401 || resp.status === 403) && retry) {
|
|
43
47
|
clearToken(resolvedHost);
|
|
44
48
|
return request(method, modulePath, params, body, false, resolvedHost);
|
|
45
49
|
}
|
|
46
|
-
const data = safeJsonParse(await resp.text());
|
|
47
50
|
if (data.return_code === -1001 && retry) {
|
|
48
51
|
clearToken(resolvedHost);
|
|
49
52
|
return request(method, modulePath, params, body, false, resolvedHost);
|
|
@@ -70,11 +73,13 @@ async function uploadRequest(modulePath, form, params = {}, retry = true, hostUr
|
|
|
70
73
|
"Authorization": `bearer ${token}`
|
|
71
74
|
};
|
|
72
75
|
const resp = await fetch(url, { method: "POST", headers, body: form });
|
|
76
|
+
const text = await resp.text();
|
|
77
|
+
const data = safeJsonParse(text);
|
|
78
|
+
logger.api("POST", url, resp.status, { upload: true }, data);
|
|
73
79
|
if ((resp.status === 401 || resp.status === 403) && retry) {
|
|
74
80
|
clearToken(resolvedHost);
|
|
75
81
|
return uploadRequest(modulePath, form, params, false, resolvedHost);
|
|
76
82
|
}
|
|
77
|
-
const data = safeJsonParse(await resp.text());
|
|
78
83
|
if (data.return_code === -1001 && retry) {
|
|
79
84
|
clearToken(resolvedHost);
|
|
80
85
|
return uploadRequest(modulePath, form, params, false, resolvedHost);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getToken
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-47MTN54I.js";
|
|
4
4
|
import {
|
|
5
5
|
forceMigrateFromFallback,
|
|
6
6
|
getActiveHost,
|
|
7
7
|
getConfigDir,
|
|
8
|
+
logger,
|
|
8
9
|
safeJsonParse,
|
|
9
10
|
safeReadJsonFile
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-DC66L5AM.js";
|
|
11
12
|
|
|
12
13
|
// src/core/mcp.ts
|
|
13
14
|
import fs from "fs";
|
|
@@ -98,9 +99,11 @@ async function getMcpToken(hostOverride) {
|
|
|
98
99
|
if (store[hostUrl]) {
|
|
99
100
|
return store[hostUrl];
|
|
100
101
|
}
|
|
102
|
+
logger.info(`Generating MCP token for ${hostUrl}`);
|
|
101
103
|
const mcpToken = await generateMcpToken(hostUrl);
|
|
102
104
|
const updatedStore = { ...store, [hostUrl]: mcpToken };
|
|
103
105
|
saveMcpTokenStore(updatedStore);
|
|
106
|
+
logger.info(`MCP token generated and cached for ${hostUrl}`);
|
|
104
107
|
return mcpToken;
|
|
105
108
|
}
|
|
106
109
|
function clearMcpToken(hostUrl) {
|
|
@@ -118,6 +121,7 @@ function setMcpTokenManual(token, hostUrl) {
|
|
|
118
121
|
const store = loadMcpTokenStore();
|
|
119
122
|
store[hostUrl] = token;
|
|
120
123
|
saveMcpTokenStore(store);
|
|
124
|
+
logger.info(`MCP token manually set for ${hostUrl}`);
|
|
121
125
|
}
|
|
122
126
|
async function validateMcpToken(token, hostUrl) {
|
|
123
127
|
const mapping = getMcpMapping("analysis");
|
|
@@ -180,8 +184,10 @@ async function mcpRequest(url, method, params = {}, hostOverride) {
|
|
|
180
184
|
body: JSON.stringify(body)
|
|
181
185
|
});
|
|
182
186
|
if (!resp.ok) {
|
|
187
|
+
logger.warn(`MCP request failed (HTTP ${resp.status}) for ${hostUrl}, trying fallback`);
|
|
183
188
|
const migrated = forceMigrateFromFallback();
|
|
184
189
|
if (migrated && migrated[hostUrl]) {
|
|
190
|
+
logger.info(`MCP token refreshed from fallback for ${hostUrl}`);
|
|
185
191
|
process.stderr.write(`[ae-cli] MCP token refreshed from fallback for ${hostUrl}
|
|
186
192
|
`);
|
|
187
193
|
headers["mcp-token"] = migrated[hostUrl];
|
|
@@ -212,7 +218,11 @@ async function callMcpTool(url, toolName, args = {}, hostOverride) {
|
|
|
212
218
|
name: toolName,
|
|
213
219
|
arguments: args
|
|
214
220
|
};
|
|
221
|
+
logger.info(`MCP tool call: ${toolName}`);
|
|
215
222
|
const result = await mcpRequest(url, "tools/call", params, hostOverride);
|
|
223
|
+
if (result.isError) {
|
|
224
|
+
logger.warn(`MCP tool call failed: ${toolName}`);
|
|
225
|
+
}
|
|
216
226
|
return {
|
|
217
227
|
content: result.content.map((item) => {
|
|
218
228
|
if (item.type === "text") {
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
queryReportData,
|
|
7
7
|
querySql,
|
|
8
8
|
wsQuery
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-MZW6NOVS.js";
|
|
10
|
+
import "./chunk-47MTN54I.js";
|
|
11
|
+
import "./chunk-DC66L5AM.js";
|
|
12
12
|
export {
|
|
13
13
|
httpDelete,
|
|
14
14
|
httpGet,
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
getToken,
|
|
5
5
|
loadToken,
|
|
6
6
|
validateToken
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-47MTN54I.js";
|
|
8
8
|
import {
|
|
9
9
|
addHost,
|
|
10
10
|
listHosts,
|
|
11
11
|
removeHost,
|
|
12
12
|
setActiveHost,
|
|
13
13
|
updateHostLabel
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DC66L5AM.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/config.ts
|
|
17
17
|
import * as readline from "readline";
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
printError,
|
|
3
3
|
printOutput
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JJCRURTR.js";
|
|
5
5
|
import {
|
|
6
6
|
getActiveHost,
|
|
7
|
+
logger,
|
|
7
8
|
safeJsonParse
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DC66L5AM.js";
|
|
9
10
|
|
|
10
11
|
// src/index.ts
|
|
11
12
|
import { Command as CommanderCommand } from "commander";
|
|
@@ -16,6 +17,8 @@ import * as readline from "readline";
|
|
|
16
17
|
async function runCommand(cmd, opts, globalOpts) {
|
|
17
18
|
try {
|
|
18
19
|
const ctx = createRuntimeContext(cmd, opts, globalOpts);
|
|
20
|
+
const cmdName = `${cmd.service} ${cmd.command}`;
|
|
21
|
+
logger.command(cmdName, opts);
|
|
19
22
|
for (const flag of cmd.flags) {
|
|
20
23
|
if (flag.required) {
|
|
21
24
|
const val = opts[camelCase(flag.name)];
|
|
@@ -48,6 +51,7 @@ async function runCommand(cmd, opts, globalOpts) {
|
|
|
48
51
|
ctx.out(result);
|
|
49
52
|
} catch (err) {
|
|
50
53
|
const message = err.message || String(err);
|
|
54
|
+
logger.error(`Command failed: ${message}`);
|
|
51
55
|
if (message.includes("token") || message.includes("auth") || message.includes("401") || message.includes("403")) {
|
|
52
56
|
printError("auth", message, "Run: ae-cli auth login");
|
|
53
57
|
} else if (message.includes("AE API error")) {
|
|
@@ -62,7 +66,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
|
|
|
62
66
|
let _clientModule = null;
|
|
63
67
|
async function getClient() {
|
|
64
68
|
if (!_clientModule) {
|
|
65
|
-
_clientModule = await import("./client-
|
|
69
|
+
_clientModule = await import("./client-TDH6MUWM.js");
|
|
66
70
|
}
|
|
67
71
|
return _clientModule;
|
|
68
72
|
}
|
|
@@ -88,12 +92,12 @@ function createRuntimeContext(cmd, opts, globalOpts) {
|
|
|
88
92
|
process.exit(1);
|
|
89
93
|
}
|
|
90
94
|
},
|
|
91
|
-
async api(method,
|
|
95
|
+
async api(method, path2, params, data) {
|
|
92
96
|
const client = await getClient();
|
|
93
97
|
if (method.toUpperCase() === "GET") {
|
|
94
|
-
return client.httpGet(
|
|
98
|
+
return client.httpGet(path2, params, ctx.host());
|
|
95
99
|
} else {
|
|
96
|
-
return client.httpPost(
|
|
100
|
+
return client.httpPost(path2, params, data, ctx.host());
|
|
97
101
|
}
|
|
98
102
|
},
|
|
99
103
|
async querySql(projectId, sql) {
|
|
@@ -105,7 +109,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
|
|
|
105
109
|
return client.queryReportData(projectId, reportId, qp, eventModel, options, ctx.host());
|
|
106
110
|
},
|
|
107
111
|
async token() {
|
|
108
|
-
const { getToken } = await import("./auth-
|
|
112
|
+
const { getToken } = await import("./auth-4OPL4YWG.js");
|
|
109
113
|
return getToken(ctx.host());
|
|
110
114
|
},
|
|
111
115
|
host() {
|
|
@@ -202,50 +206,192 @@ function extractGlobalOptions(program2) {
|
|
|
202
206
|
};
|
|
203
207
|
}
|
|
204
208
|
|
|
209
|
+
// src/core/update-check.ts
|
|
210
|
+
import fs from "fs";
|
|
211
|
+
import path from "path";
|
|
212
|
+
var CONFIG_DIR = path.join(process.env.HOME || "", ".ae-cli");
|
|
213
|
+
var CACHE_FILE = path.join(CONFIG_DIR, "update-check.json");
|
|
214
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
215
|
+
var FETCH_TIMEOUT_MS = 3e3;
|
|
216
|
+
var REGISTRY_BY_PACKAGE = {
|
|
217
|
+
"@thinkingai/ae-cli": "https://registry.npmjs.org"
|
|
218
|
+
};
|
|
219
|
+
var UPDATE_CHECK_PACKAGE = "@thinkingai/ae-cli";
|
|
220
|
+
function isUpdateCheckEnabled(packageName) {
|
|
221
|
+
return packageName === UPDATE_CHECK_PACKAGE;
|
|
222
|
+
}
|
|
223
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
224
|
+
function parseVersion(version2) {
|
|
225
|
+
const core = version2.trim().split("-")[0];
|
|
226
|
+
return core.split(".").map((part) => {
|
|
227
|
+
const n = Number.parseInt(part, 10);
|
|
228
|
+
return Number.isFinite(n) ? n : 0;
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function isNewer(latest, current) {
|
|
232
|
+
const a = parseVersion(latest);
|
|
233
|
+
const b = parseVersion(current);
|
|
234
|
+
const len = Math.max(a.length, b.length, 3);
|
|
235
|
+
for (let i = 0; i < len; i += 1) {
|
|
236
|
+
const av = a[i] ?? 0;
|
|
237
|
+
const bv = b[i] ?? 0;
|
|
238
|
+
if (av > bv) return true;
|
|
239
|
+
if (av < bv) return false;
|
|
240
|
+
}
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
function resolveRegistry(packageName) {
|
|
244
|
+
if (REGISTRY_BY_PACKAGE[packageName]) {
|
|
245
|
+
return REGISTRY_BY_PACKAGE[packageName];
|
|
246
|
+
}
|
|
247
|
+
const envRegistry = process.env.npm_config_registry?.replace(/\/$/, "");
|
|
248
|
+
return envRegistry || DEFAULT_REGISTRY;
|
|
249
|
+
}
|
|
250
|
+
function buildInstallCommand(packageName, registry) {
|
|
251
|
+
const base = `npm install -g ${packageName}@latest`;
|
|
252
|
+
if (registry === DEFAULT_REGISTRY) {
|
|
253
|
+
return base;
|
|
254
|
+
}
|
|
255
|
+
return `${base} --registry=${registry}`;
|
|
256
|
+
}
|
|
257
|
+
function shouldSkipUpdateCheck(argv = process.argv) {
|
|
258
|
+
if (process.env.AE_CLI_NO_UPDATE_CHECK === "1") return true;
|
|
259
|
+
if (process.env.CI === "true" || process.env.CI === "1") return true;
|
|
260
|
+
return argv.slice(2).some((arg) => {
|
|
261
|
+
if (arg === "--no-update-check") return true;
|
|
262
|
+
if (arg === "--version" || arg === "-V" || arg === "--help" || arg === "-h") return true;
|
|
263
|
+
return false;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function ensureConfigDir() {
|
|
267
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
268
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function readCache() {
|
|
272
|
+
try {
|
|
273
|
+
if (!fs.existsSync(CACHE_FILE)) return null;
|
|
274
|
+
const raw = fs.readFileSync(CACHE_FILE, "utf8");
|
|
275
|
+
const data = JSON.parse(raw);
|
|
276
|
+
if (!data.packageName || !data.latestVersion || !data.lastCheckedAt) return null;
|
|
277
|
+
return data;
|
|
278
|
+
} catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function writeCache(cache) {
|
|
283
|
+
try {
|
|
284
|
+
ensureConfigDir();
|
|
285
|
+
fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
|
|
286
|
+
} catch {
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function cacheIsStale(cache, packageName) {
|
|
290
|
+
if (!cache || cache.packageName !== packageName) return true;
|
|
291
|
+
const age = Date.now() - new Date(cache.lastCheckedAt).getTime();
|
|
292
|
+
return age >= CHECK_INTERVAL_MS;
|
|
293
|
+
}
|
|
294
|
+
function printUpdateNotice(current, latest, installCommand) {
|
|
295
|
+
process.stderr.write(`[ae-cli] Update available: ${current} \u2192 ${latest}
|
|
296
|
+
`);
|
|
297
|
+
process.stderr.write(` Run: ${installCommand}
|
|
298
|
+
`);
|
|
299
|
+
}
|
|
300
|
+
async function fetchLatestVersion(packageName, registry) {
|
|
301
|
+
const url = `${registry.replace(/\/$/, "")}/${encodeURIComponent(packageName)}`;
|
|
302
|
+
const controller = new AbortController();
|
|
303
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
304
|
+
try {
|
|
305
|
+
const resp = await fetch(url, {
|
|
306
|
+
signal: controller.signal,
|
|
307
|
+
headers: { Accept: "application/json" }
|
|
308
|
+
});
|
|
309
|
+
if (!resp.ok) return null;
|
|
310
|
+
const data = await resp.json();
|
|
311
|
+
const latest = data["dist-tags"]?.latest;
|
|
312
|
+
return typeof latest === "string" && latest.trim() ? latest.trim() : null;
|
|
313
|
+
} catch {
|
|
314
|
+
return null;
|
|
315
|
+
} finally {
|
|
316
|
+
clearTimeout(timer);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async function refreshCache(pkg2, registry) {
|
|
320
|
+
const latest = await fetchLatestVersion(pkg2.name, registry);
|
|
321
|
+
if (!latest) return readCache();
|
|
322
|
+
const cache = {
|
|
323
|
+
packageName: pkg2.name,
|
|
324
|
+
currentVersion: pkg2.version,
|
|
325
|
+
latestVersion: latest,
|
|
326
|
+
lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
327
|
+
};
|
|
328
|
+
writeCache(cache);
|
|
329
|
+
return cache;
|
|
330
|
+
}
|
|
331
|
+
function maybeNotifyFromCache(pkg2, cache, registry) {
|
|
332
|
+
if (!cache || cache.packageName !== pkg2.name) return;
|
|
333
|
+
if (!isNewer(cache.latestVersion, pkg2.version)) return;
|
|
334
|
+
printUpdateNotice(pkg2.version, cache.latestVersion, buildInstallCommand(pkg2.name, registry));
|
|
335
|
+
}
|
|
336
|
+
function notifyIfUpdateAvailable(pkg2) {
|
|
337
|
+
if (!isUpdateCheckEnabled(pkg2.name)) return;
|
|
338
|
+
if (shouldSkipUpdateCheck()) return;
|
|
339
|
+
const registry = resolveRegistry(pkg2.name);
|
|
340
|
+
const cache = readCache();
|
|
341
|
+
maybeNotifyFromCache(pkg2, cache, registry);
|
|
342
|
+
if (!cacheIsStale(cache, pkg2.name)) return;
|
|
343
|
+
void refreshCache(pkg2, registry).then((fresh) => {
|
|
344
|
+
if (!fresh) return;
|
|
345
|
+
if (cache && fresh.latestVersion === cache.latestVersion) return;
|
|
346
|
+
maybeNotifyFromCache(pkg2, fresh, registry);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
205
350
|
// src/index.ts
|
|
206
351
|
var require2 = createRequire(import.meta.url);
|
|
207
|
-
var
|
|
352
|
+
var pkg = require2("../package.json");
|
|
353
|
+
var { version } = pkg;
|
|
208
354
|
var program = new CommanderCommand();
|
|
209
|
-
program.name("ae-cli").version(version).description("CLI tool for ThinkingAI (AE) analytics platform").option("--host <url>", "Override active AE host URL (e.g., https://ta.thinkingdata.cn)").option("--mcp-url <url>", "Override MCP server URL (e.g., http://localhost/mcp/http/example)").option("--format <format>", "Output format: json | table", "json").option("--jq <expr>", "jq filter expression").option("--dry-run", "Show request details without executing", false).option("--yes", "Skip confirmation for write operations", false);
|
|
355
|
+
program.name("ae-cli").version(version).description("CLI tool for ThinkingAI (AE) analytics platform").option("--host <url>", "Override active AE host URL (e.g., https://ta.thinkingdata.cn)").option("--mcp-url <url>", "Override MCP server URL (e.g., http://localhost/mcp/http/example)").option("--format <format>", "Output format: json | table", "json").option("--jq <expr>", "jq filter expression").option("--dry-run", "Show request details without executing", false).option("--yes", "Skip confirmation for write operations", false).option("--no-update-check", "Skip checking for newer ae-cli versions", false);
|
|
210
356
|
async function loadCommands() {
|
|
211
357
|
const commands = [];
|
|
212
358
|
try {
|
|
213
|
-
const teAnalysis = await import("./te-analysis-
|
|
359
|
+
const teAnalysis = await import("./te-analysis-3KFSNUCJ.js");
|
|
214
360
|
commands.push(...teAnalysis.default);
|
|
215
361
|
} catch {
|
|
216
362
|
}
|
|
217
363
|
try {
|
|
218
|
-
const teAudience = await import("./te-audience-
|
|
364
|
+
const teAudience = await import("./te-audience-GMYJFCSC.js");
|
|
219
365
|
commands.push(...teAudience.default);
|
|
220
366
|
} catch {
|
|
221
367
|
}
|
|
222
368
|
try {
|
|
223
|
-
const teMeta = await import("./te-meta-
|
|
369
|
+
const teMeta = await import("./te-meta-3EFWLM3A.js");
|
|
224
370
|
commands.push(...teMeta.default);
|
|
225
371
|
} catch {
|
|
226
372
|
}
|
|
227
373
|
try {
|
|
228
|
-
const teCommon = await import("./te-common-
|
|
374
|
+
const teCommon = await import("./te-common-YLERCMQI.js");
|
|
229
375
|
commands.push(...teCommon.default);
|
|
230
376
|
} catch {
|
|
231
377
|
}
|
|
232
378
|
try {
|
|
233
|
-
const engage = await import("./te-engage-
|
|
379
|
+
const engage = await import("./te-engage-ROJVZHDA.js");
|
|
234
380
|
commands.push(...engage.default);
|
|
235
381
|
} catch {
|
|
236
382
|
}
|
|
237
383
|
try {
|
|
238
|
-
const community = await import("./te-community-
|
|
384
|
+
const community = await import("./te-community-PYDN5A6B.js");
|
|
239
385
|
commands.push(...community.default);
|
|
240
386
|
} catch {
|
|
241
387
|
}
|
|
242
388
|
try {
|
|
243
|
-
const dataops = await import("./te-dataops-
|
|
389
|
+
const dataops = await import("./te-dataops-ETWS5O3X.js");
|
|
244
390
|
commands.push(...dataops.default);
|
|
245
391
|
} catch {
|
|
246
392
|
}
|
|
247
393
|
try {
|
|
248
|
-
const teKb = await import("./te-kb-
|
|
394
|
+
const teKb = await import("./te-kb-VUNS2CC7.js");
|
|
249
395
|
commands.push(...teKb.default);
|
|
250
396
|
} catch {
|
|
251
397
|
}
|
|
@@ -253,26 +399,27 @@ async function loadCommands() {
|
|
|
253
399
|
}
|
|
254
400
|
async function registerAuthCommands() {
|
|
255
401
|
try {
|
|
256
|
-
const { registerAuth } = await import("./auth-
|
|
402
|
+
const { registerAuth } = await import("./auth-PBPAZQWP.js");
|
|
257
403
|
registerAuth(program);
|
|
258
404
|
} catch {
|
|
259
405
|
}
|
|
260
406
|
}
|
|
261
407
|
async function registerConfigCommands() {
|
|
262
408
|
try {
|
|
263
|
-
const { registerConfig } = await import("./config-
|
|
409
|
+
const { registerConfig } = await import("./config-5ELRYAIH.js");
|
|
264
410
|
registerConfig(program);
|
|
265
411
|
} catch {
|
|
266
412
|
}
|
|
267
413
|
}
|
|
268
414
|
async function registerApiCommand() {
|
|
269
415
|
try {
|
|
270
|
-
const { registerApi } = await import("./raw-
|
|
416
|
+
const { registerApi } = await import("./raw-EM7AP3RT.js");
|
|
271
417
|
registerApi(program);
|
|
272
418
|
} catch {
|
|
273
419
|
}
|
|
274
420
|
}
|
|
275
421
|
async function main() {
|
|
422
|
+
notifyIfUpdateAvailable({ name: pkg.name, version: pkg.version });
|
|
276
423
|
const commands = await loadCommands();
|
|
277
424
|
registerCommands(program, commands);
|
|
278
425
|
await registerAuthCommands();
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
printError,
|
|
3
3
|
printOutput
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JJCRURTR.js";
|
|
5
5
|
import {
|
|
6
6
|
httpGet,
|
|
7
7
|
httpPost
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MZW6NOVS.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveHost
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-47MTN54I.js";
|
|
12
12
|
import {
|
|
13
13
|
safeJsonParse
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DC66L5AM.js";
|
|
15
15
|
|
|
16
16
|
// src/api/raw.ts
|
|
17
17
|
function registerApi(program) {
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
callMcpTool,
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
resolveMcpUrl
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-OVHL4JAC.js";
|
|
6
|
+
import "./chunk-47MTN54I.js";
|
|
7
|
+
import "./chunk-DC66L5AM.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/te-analysis/shared.ts
|
|
10
10
|
function createMcpCommand(config) {
|
|
@@ -459,6 +459,24 @@ var updatePublicAccessLink = createMcpCommand({
|
|
|
459
459
|
})
|
|
460
460
|
});
|
|
461
461
|
|
|
462
|
+
// src/commands/te-analysis/dashboard/create-space.ts
|
|
463
|
+
var createSpace = createMcpCommand({
|
|
464
|
+
command: "+create_space",
|
|
465
|
+
description: "Create a new space in a project. A space organizes dashboards and assets under a named container.",
|
|
466
|
+
flags: [
|
|
467
|
+
{ name: "project_id", type: "number", required: true, desc: "Project ID", alias: "p" },
|
|
468
|
+
{ name: "space_name", type: "string", required: true, desc: "Space name (1-64 characters)" },
|
|
469
|
+
{ name: "space_desc", type: "string", required: false, desc: "Optional space description (max 200 characters)" }
|
|
470
|
+
],
|
|
471
|
+
risk: "write",
|
|
472
|
+
mcpService: "te_analysis_extend",
|
|
473
|
+
buildArgs: (ctx) => ({
|
|
474
|
+
projectId: ctx.num("project_id"),
|
|
475
|
+
spaceName: ctx.str("space_name"),
|
|
476
|
+
spaceDesc: optionalString(ctx, "space_desc")
|
|
477
|
+
})
|
|
478
|
+
});
|
|
479
|
+
|
|
462
480
|
// src/commands/te-analysis/dashboard/index.ts
|
|
463
481
|
var commands3 = [
|
|
464
482
|
listDashboards,
|
|
@@ -469,7 +487,8 @@ var commands3 = [
|
|
|
469
487
|
createOrUpdateDashboardNote,
|
|
470
488
|
listPublicAccessLinks,
|
|
471
489
|
createPublicAccessLink,
|
|
472
|
-
updatePublicAccessLink
|
|
490
|
+
updatePublicAccessLink,
|
|
491
|
+
createSpace
|
|
473
492
|
];
|
|
474
493
|
var dashboard_default = commands3;
|
|
475
494
|
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
callMcpTool,
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
resolveMcpUrl
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-OVHL4JAC.js";
|
|
6
|
+
import "./chunk-47MTN54I.js";
|
|
7
|
+
import "./chunk-DC66L5AM.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/te-audience/shared.ts
|
|
10
10
|
function createMcpCommand(config) {
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
callMcpTool,
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
resolveMcpUrl
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-OVHL4JAC.js";
|
|
6
|
+
import "./chunk-47MTN54I.js";
|
|
7
|
+
import "./chunk-DC66L5AM.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/te-common/shared.ts
|
|
10
10
|
function createMcpCommand(config) {
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
registerMcpMappings,
|
|
5
5
|
resolveMcpUrl
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OVHL4JAC.js";
|
|
7
|
+
import "./chunk-47MTN54I.js";
|
|
8
|
+
import "./chunk-DC66L5AM.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/te-community/get_channel_info.ts
|
|
11
11
|
var getChannelInfo = {
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
registerMcpMappings,
|
|
5
5
|
resolveMcpUrl
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OVHL4JAC.js";
|
|
7
|
+
import "./chunk-47MTN54I.js";
|
|
8
|
+
import "./chunk-DC66L5AM.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/te-dataops/datatable/list-tables-by-page.ts
|
|
11
11
|
var listTablesByPage = {
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
registerMcpMappings,
|
|
5
5
|
resolveMcpUrl
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OVHL4JAC.js";
|
|
7
|
+
import "./chunk-47MTN54I.js";
|
|
8
|
+
import "./chunk-DC66L5AM.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/te-engage/utils.ts
|
|
11
11
|
function buildMcpDryRun(ctx, serviceName44, toolName44, args) {
|
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
httpDelete,
|
|
3
3
|
httpUpload
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-MZW6NOVS.js";
|
|
5
|
+
import "./chunk-47MTN54I.js";
|
|
6
|
+
import "./chunk-DC66L5AM.js";
|
|
7
7
|
|
|
8
8
|
// src/commands/te-kb/query.ts
|
|
9
9
|
var API_PATH = "/agent/api/external/knowledge-bases/query";
|
|
10
10
|
function buildBody(ctx) {
|
|
11
|
-
|
|
11
|
+
return {
|
|
12
12
|
query: ctx.str("query"),
|
|
13
13
|
sources: ctx.json("sources")
|
|
14
14
|
};
|
|
15
|
-
const modelId = ctx.str("model-id");
|
|
16
|
-
if (modelId) body.modelId = modelId;
|
|
17
|
-
const maxTurnsRaw = ctx.str("max-turns");
|
|
18
|
-
if (maxTurnsRaw !== "") body.maxTurns = ctx.num("max-turns");
|
|
19
|
-
return body;
|
|
20
15
|
}
|
|
21
16
|
var query = {
|
|
22
17
|
service: "kb",
|
|
@@ -24,9 +19,7 @@ var query = {
|
|
|
24
19
|
description: "Query knowledge.",
|
|
25
20
|
flags: [
|
|
26
21
|
{ name: "query", type: "string", required: true, alias: "q", desc: "Natural language question to query against the knowledge bases" },
|
|
27
|
-
{ name: "sources", type: "json", required: true, desc: 'JSON array of knowledge base refs, e.g. [{"scope":"company","name":"engineering-handbook"}]' }
|
|
28
|
-
{ name: "model-id", type: "string", required: false, default: "AE-Auto", desc: "Model identifier (default: AE-Auto)" },
|
|
29
|
-
{ name: "max-turns", type: "number", required: false, default: 6, desc: "Maximum reasoning turns (default: 6)" }
|
|
22
|
+
{ name: "sources", type: "json", required: true, desc: 'JSON array of knowledge base refs, e.g. [{"scope":"company","name":"engineering-handbook"}]' }
|
|
30
23
|
],
|
|
31
24
|
risk: "read",
|
|
32
25
|
dryRun: (ctx) => ({
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
callMcpTool,
|
|
3
3
|
parseMcpResult,
|
|
4
4
|
resolveMcpUrl
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-OVHL4JAC.js";
|
|
6
|
+
import "./chunk-47MTN54I.js";
|
|
7
|
+
import "./chunk-DC66L5AM.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/te-meta/shared.ts
|
|
10
10
|
function createMcpCommand(config) {
|
|
@@ -533,8 +533,28 @@ var listEntities = createMcpCommand({
|
|
|
533
533
|
})
|
|
534
534
|
});
|
|
535
535
|
|
|
536
|
+
// src/commands/te-meta/entity/create-entity.ts
|
|
537
|
+
var createEntity = createMcpCommand({
|
|
538
|
+
command: "+create_entity",
|
|
539
|
+
description: "Create a new entity that links an event or user property as an analysis dimension.",
|
|
540
|
+
flags: [
|
|
541
|
+
{ name: "project_id", type: "number", required: true, desc: "Project ID", alias: "p" },
|
|
542
|
+
{ name: "entity_name", type: "string", required: true, desc: "Entity name" },
|
|
543
|
+
{ name: "column_name", type: "string", required: true, desc: "Property column name to associate with the entity" },
|
|
544
|
+
{ name: "table_type", type: "number", required: true, desc: "Table type: 0 = event property, 1 = user property" }
|
|
545
|
+
],
|
|
546
|
+
risk: "write",
|
|
547
|
+
mcpService: "te_analysis_extend",
|
|
548
|
+
buildArgs: (ctx) => ({
|
|
549
|
+
projectId: ctx.num("project_id"),
|
|
550
|
+
entityName: ctx.str("entity_name"),
|
|
551
|
+
columnName: ctx.str("column_name"),
|
|
552
|
+
tableType: ctx.num("table_type")
|
|
553
|
+
})
|
|
554
|
+
});
|
|
555
|
+
|
|
536
556
|
// src/commands/te-meta/entity/index.ts
|
|
537
|
-
var commands3 = [listEntities];
|
|
557
|
+
var commands3 = [listEntities, createEntity];
|
|
538
558
|
var entity_default = commands3;
|
|
539
559
|
|
|
540
560
|
// src/commands/te-meta/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thinkingai/ae-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"description": "CLI tool for ThinkingAI (AE) analytics platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"verify:analysis-audience-tools": "node scripts/verify-te-audience-tools.mjs",
|
|
22
22
|
"verify:analysis-meta-tools": "node scripts/verify-te-meta-tools.mjs",
|
|
23
23
|
"verify:analysis-common-tools": "node scripts/verify-te-common-tools.mjs",
|
|
24
|
+
"verify:update-check": "npx tsx test/update-check.test.mjs",
|
|
24
25
|
"prepublishOnly": "npm run build",
|
|
25
26
|
"start": "node dist/index.js",
|
|
26
27
|
"test": "npx tsx src/index.ts --help"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# analysis_meta +create_entity (Create Entity)
|
|
2
|
+
|
|
3
|
+
> **Prerequisite:** Follow the Global AE CLI Rules in [`../SKILL.md`](../SKILL.md).
|
|
4
|
+
|
|
5
|
+
Domain: **Entity Management**
|
|
6
|
+
|
|
7
|
+
## Use Cases
|
|
8
|
+
- Create a new entity that links an event property or user property as an analysis dimension.
|
|
9
|
+
- Use `+list_entities` first to confirm the entity does not already exist.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
```bash
|
|
13
|
+
ae-cli analysis_meta +create_entity --project_id <project_id> --entity_name "User Entity" --column_name user_id --table_type 1
|
|
14
|
+
ae-cli analysis_meta +create_entity --project_id <project_id> --entity_name "Event Entity" --column_name event_col --table_type 0
|
|
15
|
+
ae-cli analysis_meta +create_entity --dry-run
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Parameters
|
|
19
|
+
| Parameter | Required | Description |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `--project_id` / `-p` | Yes | Project ID |
|
|
22
|
+
| `--entity_name` | Yes | Entity name |
|
|
23
|
+
| `--column_name` | Yes | Property column name to associate with the entity |
|
|
24
|
+
| `--table_type` | Yes | Table type: `0` = event property, `1` = user property |
|
|
25
|
+
|
|
26
|
+
## Decision Rules
|
|
27
|
+
- `--table_type` must be `0` (event property) or `1` (user property); no other values are accepted.
|
|
28
|
+
- Before using `--column_name`, call `analysis_meta +list_properties` to verify it exists. If the same column name appears in **both** event properties and user properties, **stop and ask the user which table type to use** — do not guess `--table_type`. Ask every time this condition is met; never carry over the answer from a previous request.
|
|
29
|
+
- For the first run, pass only the required parameters and confirm before adding others.
|
|
30
|
+
- Write operations keep the confirmation prompt by default; use `--yes` only for automation.
|
|
31
|
+
|
|
32
|
+
## Next Steps After Failure
|
|
33
|
+
- If `PROJECT_ID_REQUIRED` or `ENTITY_NAME_REQUIRED` appears, check that all required parameters are provided.
|
|
34
|
+
- If `INVALID_TABLE_TYPE` appears, verify `--table_type` is exactly `0` or `1`.
|
|
35
|
+
- If the result after writing is not as expected, use `analysis_meta +list_entities` to compare before and after.
|
|
36
|
+
|
|
37
|
+
## Recommended Chaining
|
|
38
|
+
- `analysis_meta +list_entities` → `+create_entity`
|
|
39
|
+
- `analysis_meta +list_properties` → `+create_entity`
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# analysis +create_space (Create Space)
|
|
2
|
+
|
|
3
|
+
> **Prerequisite:** Follow the Global AE CLI Rules in [`../SKILL.md`](../SKILL.md).
|
|
4
|
+
|
|
5
|
+
Domain: **Space Management**
|
|
6
|
+
|
|
7
|
+
## Use Cases
|
|
8
|
+
- Create a new space in a project to organize dashboards and assets under a named container.
|
|
9
|
+
- Returns basic space information (ID, name, avatar settings).
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
```bash
|
|
13
|
+
ae-cli analysis +create_space --project_id <project_id> --space_name "My Space"
|
|
14
|
+
ae-cli analysis +create_space --project_id <project_id> --space_name "Team Space" --space_desc "Team dashboards"
|
|
15
|
+
ae-cli analysis +create_space --dry-run
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Parameters
|
|
19
|
+
| Parameter | Required | Description |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `--project_id` / `-p` | Yes | Project ID |
|
|
22
|
+
| `--space_name` | Yes | Space name (1-64 characters) |
|
|
23
|
+
| `--space_desc` | No | Optional space description (max 200 characters) |
|
|
24
|
+
|
|
25
|
+
## Decision Rules
|
|
26
|
+
- `--space_name` must be between 1 and 64 characters.
|
|
27
|
+
- Write operations keep the confirmation prompt by default; use `--yes` only for automation.
|
|
28
|
+
|
|
29
|
+
## Next Steps After Failure
|
|
30
|
+
- If `SPACE_NAME_TOO_LONG` appears, shorten `--space_name` to 64 characters or fewer.
|
|
31
|
+
- If the result after writing is not as expected, use `analysis +list_dashboards` to inspect the space context.
|
|
32
|
+
|
|
33
|
+
## Recommended Chaining
|
|
34
|
+
- `+create_space` → `+create_dashboard` (create dashboard inside the new space using `--space_id`)
|