@thinkingai/ae-cli 1.0.15 → 1.0.18
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 +23 -24
- package/README.zh.md +21 -22
- package/dist/auth-2UTBG5U3.js +144 -0
- package/dist/{auth-4GAHTBVH.js → auth-ECD46NBA.js} +6 -4
- package/dist/{chunk-UK6HO5O5.js → chunk-4KQ7H7DY.js} +13 -1
- package/dist/{chunk-TJIMDNAU.js → chunk-7QBNU44L.js} +101 -3
- package/dist/{chunk-OQ4XEG77.js → chunk-LAAS6ITR.js} +2 -2
- package/dist/{chunk-EBFUVWIZ.js → chunk-MR57UIKC.js} +42 -0
- package/dist/{client-HU63573O.js → client-O56G2SNJ.js} +3 -3
- package/dist/{config-OLF7RBPM.js → config-BU5FHGGE.js} +20 -5
- package/dist/index.js +13 -13
- package/dist/{raw-GDO4IWNW.js → raw-A3VN2B6I.js} +3 -3
- package/dist/{te-analysis-ZDJXMWZY.js → te-analysis-UGKESPBE.js} +3 -3
- package/dist/{te-audience-T5B52EEB.js → te-audience-THZNVHYB.js} +3 -3
- package/dist/{te-common-BPTXXTHQ.js → te-common-QZOUME3S.js} +3 -3
- package/dist/{te-community-FPB5LH56.js → te-community-AZVW3NFX.js} +3 -3
- package/dist/{te-dataops-2NUJVG47.js → te-dataops-OE5PX2K6.js} +3 -3
- package/dist/{te-engage-K3EANZ5P.js → te-engage-RYGEQTYK.js} +3 -3
- package/dist/{te-meta-JJMV75KB.js → te-meta-MGO5BCMG.js} +6 -4
- package/package.json +1 -1
- package/skills/ae-analysis/SKILL.md +58 -0
- package/skills/ae-analysis/references/generate_track_program.md +8 -8
- package/skills/ae-analysis/references/list_alerts.md +4 -0
- package/skills/ae-analysis/references/list_clusters.md +4 -0
- package/skills/ae-analysis/references/list_dashboards.md +4 -0
- package/skills/ae-analysis/references/list_events.md +4 -0
- package/skills/ae-analysis/references/list_metrics.md +4 -0
- package/skills/ae-analysis/references/list_reports.md +4 -0
- package/skills/ae-analysis/references/list_tags.md +4 -0
- package/skills/ae-analysis/references/query_adhoc.md +10 -0
- package/dist/auth-U2GHFMFY.js +0 -81
package/README.md
CHANGED
|
@@ -86,14 +86,18 @@ ae-cli auth logout
|
|
|
86
86
|
|
|
87
87
|
| Domain | Commands | Description |
|
|
88
88
|
|--------|----------|-------------|
|
|
89
|
-
| `analysis` |
|
|
90
|
-
| `analysis_audience` |
|
|
91
|
-
| `analysis_meta` | 20 | Metadata governance: events/properties, metrics, virtual metadata, project config, tracking plan, mark times,
|
|
89
|
+
| `analysis` | 30+ | Analysis workflows: alerts, reports, dashboards, ad-hoc/drilldown, entity/event details, analysis schema |
|
|
90
|
+
| `analysis_audience` | 10+ | Audience operations: clusters, tags, and cluster/tag definition schema |
|
|
91
|
+
| `analysis_meta` | 20+ | Metadata governance: events/properties, metrics, virtual metadata, project config, tracking plan, mark times, entity catalog |
|
|
92
92
|
| `engage` | 40+ | Hermes Engage MCP: channels, tasks, configs, flows, strategies |
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
93
|
+
| `dataops_repo` | 8 | Data warehouse repos: spaces, catalogs, schemas, members |
|
|
94
|
+
| `dataops_datatable` | 10+ | Data tables: table creation, views, batch operations, data dictionary |
|
|
95
|
+
| `dataops_flow` | 20+ | Task flows: flow creation, task nodes, scheduling, execution, monitoring |
|
|
96
|
+
| `dataops_ide` | 10+ | IDE queries: metadata browsing, SQL execution, query management |
|
|
97
|
+
| `dataops_integration` | 20+ | Data integration: datasource management, sync solutions, data synchronization |
|
|
98
|
+
| `community` | 10+ | Community analysis: posts search, sentiment analysis, topic trends, livestream data |
|
|
95
99
|
| `analysis_common` | 2 | Cross-module common constraints: resource link completion, project ID gate |
|
|
96
|
-
| `
|
|
100
|
+
| `auth` / `config` | 2 | Authentication and host configuration |
|
|
97
101
|
|
|
98
102
|
### Global Options
|
|
99
103
|
|
|
@@ -124,44 +128,39 @@ npx skills add ThinkingAIAgenticEngine/ae-cli -g -y
|
|
|
124
128
|
|
|
125
129
|
## Skill Details
|
|
126
130
|
|
|
127
|
-
### ae-analysis
|
|
131
|
+
### ae-analysis
|
|
128
132
|
|
|
129
133
|
Unified AE analysis capabilities:
|
|
130
|
-
- **
|
|
131
|
-
- **Reports & Dashboards**: create, query, update reports and dashboards
|
|
132
|
-
- **Model Analysis**: event analysis, retention analysis, funnel analysis, SQL analysis, user property analysis, distribution analysis, interval analysis, path analysis, attribution analysis
|
|
134
|
+
- **Analysis**: alerts, reports, dashboards, ad-hoc/drilldown, entity/event details, analysis schema
|
|
133
135
|
- **Audience**: cluster and tag lifecycle management, plus definition schema tools
|
|
134
|
-
- **Metadata
|
|
135
|
-
- **Common
|
|
136
|
-
- **Entity/Event Details**: query details, generate analysis SQL
|
|
137
|
-
- **Schema Helpers**: analysis query schema, filter schema, groupby schema
|
|
136
|
+
- **Metadata**: events/properties, metrics, virtual metadata, project config, tracking plans, mark times
|
|
137
|
+
- **Common**: mandatory project ID gate and post-write resource-link completion
|
|
138
138
|
|
|
139
|
-
### engage
|
|
139
|
+
### engage
|
|
140
140
|
|
|
141
141
|
Hermes Engage MCP capabilities:
|
|
142
|
-
- **Channels**: channel management, config channels, approval
|
|
143
|
-
- **Tasks**: task list,
|
|
144
|
-
- **Configs**: config items, strategies,
|
|
145
|
-
- **Flows**: flow creation, node config,
|
|
142
|
+
- **Channels**: channel management, config channels, approval, whitelist
|
|
143
|
+
- **Tasks**: task list, details, data/metrics overview, experiment reports
|
|
144
|
+
- **Configs**: config items, strategies, comparison, trigger/analysis reports
|
|
145
|
+
- **Flows**: flow creation, node config, reports, validation
|
|
146
146
|
|
|
147
|
-
### ae-dataops
|
|
147
|
+
### ae-dataops
|
|
148
148
|
|
|
149
149
|
Data warehouse management:
|
|
150
150
|
- **Repo Management**: spaces, catalogs, schemas, members
|
|
151
151
|
- **Data Tables**: table creation, views, batch operations, data dictionary
|
|
152
152
|
- **Task Flows**: flow creation, task nodes, scheduling, execution, monitoring
|
|
153
153
|
- **IDE Queries**: metadata browsing, SQL execution, query management
|
|
154
|
-
- **Integration**: datasource management, sync solutions, data synchronization
|
|
155
|
-
- **Operations**: flow instances, task instances, backfill jobs
|
|
154
|
+
- **Data Integration**: datasource management, sync solutions, data synchronization
|
|
156
155
|
|
|
157
|
-
### ae-community
|
|
156
|
+
### ae-community
|
|
158
157
|
|
|
159
158
|
Community social media analysis:
|
|
160
159
|
- **Posts**: search, detail, corpus tags
|
|
161
160
|
- **Comments**: sentiment analysis, tag analysis, summary
|
|
162
161
|
- **Topics**: hot topics, trends, daily summaries
|
|
163
162
|
- **Livestreams**: rooms, sessions, analysis, metrics
|
|
164
|
-
- **
|
|
163
|
+
- **Channel Info**: channel overview metrics
|
|
165
164
|
|
|
166
165
|
## Architecture
|
|
167
166
|
|
package/README.zh.md
CHANGED
|
@@ -86,14 +86,18 @@ ae-cli auth logout
|
|
|
86
86
|
|
|
87
87
|
| 域 | 命令数 | 描述 |
|
|
88
88
|
|---|---|---|
|
|
89
|
-
| `analysis` |
|
|
90
|
-
| `analysis_audience` |
|
|
91
|
-
| `analysis_meta` | 20 |
|
|
89
|
+
| `analysis` | 30+ | 分析工作流:告警、报表、仪表板、即时分析/下钻、实体/事件详情、分析模型 |
|
|
90
|
+
| `analysis_audience` | 10+ | 受众运营:分群、标签及其定义模型 |
|
|
91
|
+
| `analysis_meta` | 20+ | 元数据治理:事件/属性、指标、虚拟元数据、项目配置、埋点方案、标记时间、实体目录 |
|
|
92
92
|
| `engage` | 40+ | Hermes Engage MCP:渠道、任务、配置、流程、策略 |
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
93
|
+
| `dataops_repo` | 8 | 数仓仓库:空间、目录、模式、成员 |
|
|
94
|
+
| `dataops_datatable` | 10+ | 数据表:表创建、视图、批量操作、数据字典 |
|
|
95
|
+
| `dataops_flow` | 20+ | 任务流:流程创建、任务节点、调度、执行、监控 |
|
|
96
|
+
| `dataops_ide` | 10+ | IDE 查询:元数据浏览、SQL 执行、查询管理 |
|
|
97
|
+
| `dataops_integration` | 20+ | 数据集成:数据源管理、同步方案、数据同步 |
|
|
98
|
+
| `community` | 10+ | 社区分析:帖子搜索、情感分析、话题趋势、直播数据 |
|
|
95
99
|
| `analysis_common` | 2 | 跨模块通用约束:资源链接补全、项目 ID 门控 |
|
|
96
|
-
| `
|
|
100
|
+
| `auth` / `config` | 2 | 身份验证和主机配置 |
|
|
97
101
|
|
|
98
102
|
### 全局选项
|
|
99
103
|
|
|
@@ -124,27 +128,23 @@ npx skills add ThinkingAIAgenticEngine/ae-cli -g -y
|
|
|
124
128
|
|
|
125
129
|
## Skill 详情
|
|
126
130
|
|
|
127
|
-
### ae-analysis
|
|
131
|
+
### ae-analysis
|
|
128
132
|
|
|
129
133
|
统一的 AE 分析能力:
|
|
130
|
-
-
|
|
131
|
-
- **报表和仪表板**:创建、查询、更新报表和仪表板
|
|
132
|
-
- **模型分析**:事件分析、留存分析、漏斗分析、SQL 分析、用户属性分析、分布分析、间隔分析、路径分析、归因分析
|
|
134
|
+
- **分析**:告警、报表、仪表板、即时分析/下钻、实体/事件详情、分析模型
|
|
133
135
|
- **受众**:分群和标签生命周期管理,以及定义模型工具
|
|
134
|
-
-
|
|
136
|
+
- **元数据**:事件/属性、指标、虚拟元数据、项目配置、埋点方案、标记时间
|
|
135
137
|
- **通用约束**:强制的项目 ID 门控和写入后资源链接补全
|
|
136
|
-
- **实体/事件详情**:查询详情、生成分析 SQL
|
|
137
|
-
- **模型辅助**:分析查询模型、过滤模型、分组模型
|
|
138
138
|
|
|
139
|
-
### engage
|
|
139
|
+
### engage
|
|
140
140
|
|
|
141
141
|
Hermes Engage MCP 能力:
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
145
|
-
-
|
|
142
|
+
- **渠道**:渠道管理、配置渠道、审批、白名单
|
|
143
|
+
- **任务**:任务列表、详情、数据/指标概览、实验报告
|
|
144
|
+
- **配置**:配置项、策略、对比、触发/分析报告
|
|
145
|
+
- **流程**:流程创建、节点配置、报告、验证
|
|
146
146
|
|
|
147
|
-
### ae-dataops
|
|
147
|
+
### ae-dataops
|
|
148
148
|
|
|
149
149
|
数仓管理:
|
|
150
150
|
- **仓库管理**:空间、目录、模式、成员
|
|
@@ -152,16 +152,15 @@ Hermes Engage MCP 能力:
|
|
|
152
152
|
- **任务流**:流程创建、任务节点、调度、执行、监控
|
|
153
153
|
- **IDE 查询**:元数据浏览、SQL 执行、查询管理
|
|
154
154
|
- **数据集成**:数据源管理、同步方案、数据同步
|
|
155
|
-
- **运维管理**:流程实例、任务实例、补数据任务
|
|
156
155
|
|
|
157
|
-
### ae-community
|
|
156
|
+
### ae-community
|
|
158
157
|
|
|
159
158
|
社区社媒分析:
|
|
160
159
|
- **帖子**:搜索、详情、语料标签
|
|
161
160
|
- **评论**:情感分析、标签分析、摘要
|
|
162
161
|
- **话题**:热门话题、趋势、每日摘要
|
|
163
162
|
- **直播**:直播间、场次、分析、指标
|
|
164
|
-
-
|
|
163
|
+
- **渠道信息**:渠道概览指标
|
|
165
164
|
|
|
166
165
|
## 架构
|
|
167
166
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printError,
|
|
3
|
+
printOutput
|
|
4
|
+
} from "./chunk-KM57HI5B.js";
|
|
5
|
+
import {
|
|
6
|
+
clearMcpToken,
|
|
7
|
+
setMcpTokenManual,
|
|
8
|
+
validateMcpToken
|
|
9
|
+
} from "./chunk-7QBNU44L.js";
|
|
10
|
+
import {
|
|
11
|
+
clearToken,
|
|
12
|
+
getAuthStatus,
|
|
13
|
+
getToken,
|
|
14
|
+
resolveHost,
|
|
15
|
+
setTokenManual,
|
|
16
|
+
validateToken
|
|
17
|
+
} from "./chunk-4KQ7H7DY.js";
|
|
18
|
+
import {
|
|
19
|
+
loadConfig,
|
|
20
|
+
saveConfig
|
|
21
|
+
} from "./chunk-MR57UIKC.js";
|
|
22
|
+
|
|
23
|
+
// src/commands/auth.ts
|
|
24
|
+
function registerAuth(program) {
|
|
25
|
+
const auth = program.command("auth").description("Authentication management");
|
|
26
|
+
auth.command("login").description("Login to AE (auto-extract token from Chrome on macOS)").action(async () => {
|
|
27
|
+
const host = resolveHost(program.opts().host);
|
|
28
|
+
if (!host) {
|
|
29
|
+
printError("config", "No AE host configured.", "Run: ae-cli config set-host");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const token = await getToken(host);
|
|
34
|
+
process.stderr.write(`[ae-cli] Authenticated to ${host}
|
|
35
|
+
`);
|
|
36
|
+
printOutput({ authenticated: true, host, token: token.slice(0, 8) + "..." }, program.opts().format || "json");
|
|
37
|
+
} catch (err) {
|
|
38
|
+
printError("auth", err.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
auth.command("set-token <token>").description("Manually set authentication token for active host").action(async (token) => {
|
|
43
|
+
const host = resolveHost(program.opts().host);
|
|
44
|
+
if (!host) {
|
|
45
|
+
printError("config", "No AE host configured.", "Run: ae-cli config set-host");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
const config = loadConfig();
|
|
49
|
+
if (!config.hosts[host]) {
|
|
50
|
+
config.hosts[host] = { label: host };
|
|
51
|
+
if (!config.activeHost) {
|
|
52
|
+
config.activeHost = host;
|
|
53
|
+
}
|
|
54
|
+
saveConfig(config);
|
|
55
|
+
process.stderr.write(`[ae-cli] Config saved for ${host}
|
|
56
|
+
`);
|
|
57
|
+
printOutput({ saved: true, config }, program.opts().format || "json");
|
|
58
|
+
}
|
|
59
|
+
process.stderr.write(`[ae-cli] Validating token...
|
|
60
|
+
`);
|
|
61
|
+
const isValid = await validateToken(token, host);
|
|
62
|
+
if (!isValid) {
|
|
63
|
+
process.stderr.write(`[ae-cli] Token validation failed
|
|
64
|
+
`);
|
|
65
|
+
printError("auth", "Invalid token", "Please check your token and try again");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
setTokenManual(token, host);
|
|
69
|
+
process.stderr.write(`[ae-cli] Token verified and saved for ${host}
|
|
70
|
+
`);
|
|
71
|
+
printOutput({ saved: true, host, verified: true }, program.opts().format || "json");
|
|
72
|
+
});
|
|
73
|
+
auth.command("status").description("Show current authentication status").action(() => {
|
|
74
|
+
const host = resolveHost(program.opts().host);
|
|
75
|
+
if (!host) {
|
|
76
|
+
printOutput({ authenticated: false, host: "(none)", hint: "Run: ae-cli config set-host" }, program.opts().format || "json");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const status = getAuthStatus(host);
|
|
80
|
+
printOutput(status, program.opts().format || "json");
|
|
81
|
+
});
|
|
82
|
+
auth.command("logout").description("Clear stored token for active host").action(() => {
|
|
83
|
+
const host = resolveHost(program.opts().host);
|
|
84
|
+
if (!host) {
|
|
85
|
+
printError("config", "No AE host configured.", "Run: ae-cli config set-host");
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
clearToken(host);
|
|
89
|
+
process.stderr.write(`[ae-cli] Token cleared for ${host}
|
|
90
|
+
`);
|
|
91
|
+
printOutput({ cleared: true, host }, program.opts().format || "json");
|
|
92
|
+
});
|
|
93
|
+
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) => {
|
|
94
|
+
const host = opts.host || resolveHost(program.opts().host);
|
|
95
|
+
if (!host) {
|
|
96
|
+
printError("config", "No AE host configured.", "Use --host <url> or run: ae-cli config set-host");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
const config = loadConfig();
|
|
100
|
+
if (!config.hosts[host]) {
|
|
101
|
+
config.hosts[host] = { label: host };
|
|
102
|
+
if (!config.activeHost) {
|
|
103
|
+
config.activeHost = host;
|
|
104
|
+
}
|
|
105
|
+
saveConfig(config);
|
|
106
|
+
process.stderr.write(`[ae-cli] Host config saved for ${host}
|
|
107
|
+
`);
|
|
108
|
+
}
|
|
109
|
+
process.stderr.write(`[ae-cli] Validating MCP token...
|
|
110
|
+
`);
|
|
111
|
+
const isValid = await validateMcpToken(token, host);
|
|
112
|
+
if (!isValid) {
|
|
113
|
+
process.stderr.write(`[ae-cli] MCP token validation failed
|
|
114
|
+
`);
|
|
115
|
+
printError("auth", "Invalid MCP token", "Please check your MCP token and try again");
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
setMcpTokenManual(token, host);
|
|
119
|
+
process.stderr.write(`[ae-cli] MCP token verified and saved for ${host}
|
|
120
|
+
`);
|
|
121
|
+
printOutput({ saved: true, host, verified: true, type: "mcp-token" }, program.opts().format || "json");
|
|
122
|
+
});
|
|
123
|
+
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) => {
|
|
124
|
+
if (opts.all) {
|
|
125
|
+
clearMcpToken();
|
|
126
|
+
process.stderr.write(`[ae-cli] All MCP tokens cleared
|
|
127
|
+
`);
|
|
128
|
+
printOutput({ cleared: true, type: "all-mcp-tokens" }, program.opts().format || "json");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const host = opts.host || resolveHost(program.opts().host);
|
|
132
|
+
if (!host) {
|
|
133
|
+
printError("config", "No AE host configured.", "Use --host <url> or run: ae-cli config set-host");
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
clearMcpToken(host);
|
|
137
|
+
process.stderr.write(`[ae-cli] MCP token cleared for ${host}
|
|
138
|
+
`);
|
|
139
|
+
printOutput({ cleared: true, host }, program.opts().format || "json");
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
registerAuth
|
|
144
|
+
};
|
|
@@ -5,9 +5,10 @@ import {
|
|
|
5
5
|
loadToken,
|
|
6
6
|
resolveHost,
|
|
7
7
|
saveToken,
|
|
8
|
-
setTokenManual
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
setTokenManual,
|
|
9
|
+
validateToken
|
|
10
|
+
} from "./chunk-4KQ7H7DY.js";
|
|
11
|
+
import "./chunk-MR57UIKC.js";
|
|
11
12
|
export {
|
|
12
13
|
clearToken,
|
|
13
14
|
getAuthStatus,
|
|
@@ -15,5 +16,6 @@ export {
|
|
|
15
16
|
loadToken,
|
|
16
17
|
resolveHost,
|
|
17
18
|
saveToken,
|
|
18
|
-
setTokenManual
|
|
19
|
+
setTokenManual,
|
|
20
|
+
validateToken
|
|
19
21
|
};
|
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
extractHostname,
|
|
3
3
|
getActiveHost,
|
|
4
4
|
getConfigDir,
|
|
5
|
+
safeJsonParse,
|
|
5
6
|
safeReadJsonFile
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MR57UIKC.js";
|
|
7
8
|
|
|
8
9
|
// src/core/auth.ts
|
|
9
10
|
import fs from "fs";
|
|
@@ -22,6 +23,16 @@ function resolveHost(hostOverride) {
|
|
|
22
23
|
if (hostOverride) return hostOverride;
|
|
23
24
|
return getActiveHost();
|
|
24
25
|
}
|
|
26
|
+
async function validateToken(token, hostUrl) {
|
|
27
|
+
const url = `${hostUrl}/v1/oauth/checkToken?accessToken=${token}`;
|
|
28
|
+
try {
|
|
29
|
+
const resp = await fetch(url, { method: "POST" });
|
|
30
|
+
const respJson = safeJsonParse(await resp.text());
|
|
31
|
+
return respJson?.return_code === 0;
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
25
36
|
function loadAllTokens() {
|
|
26
37
|
try {
|
|
27
38
|
const legacyTokens = path.join(LEGACY_DIR, "tokens.json");
|
|
@@ -209,6 +220,7 @@ Options:
|
|
|
209
220
|
|
|
210
221
|
export {
|
|
211
222
|
resolveHost,
|
|
223
|
+
validateToken,
|
|
212
224
|
loadToken,
|
|
213
225
|
saveToken,
|
|
214
226
|
clearToken,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getToken
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4KQ7H7DY.js";
|
|
4
4
|
import {
|
|
5
5
|
getActiveHost,
|
|
6
6
|
getConfigDir,
|
|
7
7
|
safeJsonParse,
|
|
8
8
|
safeReadJsonFile
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MR57UIKC.js";
|
|
10
10
|
|
|
11
11
|
// src/core/mcp.ts
|
|
12
12
|
import fs from "fs";
|
|
@@ -54,6 +54,7 @@ function genRequestId() {
|
|
|
54
54
|
}
|
|
55
55
|
var MCP_TOKEN_FILE = path.join(getConfigDir(), "mcp-tokens.json");
|
|
56
56
|
var MCP_TOKEN_GENERATE_PATH = "/v1/ta/mcp/token/generate";
|
|
57
|
+
var FALLBACK_MCP_TOKEN_FILE = "/data/app/te_agent_ta/.ae-config/mcp-token.json";
|
|
57
58
|
function loadMcpTokenStore() {
|
|
58
59
|
try {
|
|
59
60
|
if (fs.existsSync(MCP_TOKEN_FILE)) {
|
|
@@ -68,6 +69,23 @@ function saveMcpTokenStore(store) {
|
|
|
68
69
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
69
70
|
fs.writeFileSync(MCP_TOKEN_FILE, JSON.stringify(store, null, 2));
|
|
70
71
|
}
|
|
72
|
+
function getFallbackMcpToken(hostUrl) {
|
|
73
|
+
try {
|
|
74
|
+
if (!fs.existsSync(FALLBACK_MCP_TOKEN_FILE)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const fallbackData = safeReadJsonFile(FALLBACK_MCP_TOKEN_FILE);
|
|
78
|
+
if (fallbackData && typeof fallbackData === "object" && !Array.isArray(fallbackData)) {
|
|
79
|
+
const url = fallbackData.url;
|
|
80
|
+
const token = fallbackData["mcp-token"];
|
|
81
|
+
if (url === hostUrl && token) {
|
|
82
|
+
return token;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
71
89
|
async function generateMcpToken(hostUrl) {
|
|
72
90
|
const teToken = await getToken(hostUrl);
|
|
73
91
|
const base = hostUrl.replace(/\/+$/, "");
|
|
@@ -102,8 +120,60 @@ async function getMcpToken(hostOverride) {
|
|
|
102
120
|
saveMcpTokenStore(updatedStore);
|
|
103
121
|
return mcpToken;
|
|
104
122
|
}
|
|
123
|
+
function clearMcpToken(hostUrl) {
|
|
124
|
+
const store = loadMcpTokenStore();
|
|
125
|
+
if (hostUrl) {
|
|
126
|
+
delete store[hostUrl];
|
|
127
|
+
} else {
|
|
128
|
+
for (const key of Object.keys(store)) {
|
|
129
|
+
delete store[key];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
saveMcpTokenStore(store);
|
|
133
|
+
}
|
|
134
|
+
function setMcpTokenManual(token, hostUrl) {
|
|
135
|
+
const store = loadMcpTokenStore();
|
|
136
|
+
store[hostUrl] = token;
|
|
137
|
+
saveMcpTokenStore(store);
|
|
138
|
+
}
|
|
139
|
+
async function validateMcpToken(token, hostUrl) {
|
|
140
|
+
const mapping = getMcpMapping("analysis");
|
|
141
|
+
const base = hostUrl.replace(/\/+$/, "");
|
|
142
|
+
const url = `${base}/mcp/${mapping.componentName}/http/${mapping.mappingPath}`;
|
|
143
|
+
const requestId = 1;
|
|
144
|
+
const body = {
|
|
145
|
+
jsonrpc: JSONRPC_VERSION,
|
|
146
|
+
id: requestId,
|
|
147
|
+
method: "tools/list",
|
|
148
|
+
params: { _meta: { progressToken: requestId } }
|
|
149
|
+
};
|
|
150
|
+
const headers = {
|
|
151
|
+
"Content-Type": "application/json",
|
|
152
|
+
"Accept": "application/json, text/event-stream",
|
|
153
|
+
"mcp-protocol-version": MCP_PROTOCOL_VERSION,
|
|
154
|
+
"mcp-token": token
|
|
155
|
+
};
|
|
156
|
+
try {
|
|
157
|
+
const resp = await fetch(url, {
|
|
158
|
+
method: "POST",
|
|
159
|
+
headers,
|
|
160
|
+
body: JSON.stringify(body)
|
|
161
|
+
});
|
|
162
|
+
if (!resp.ok) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
const data = safeJsonParse(await resp.text());
|
|
166
|
+
if (data.error) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return data.result?.tools !== void 0;
|
|
170
|
+
} catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
105
174
|
async function mcpRequest(url, method, params = {}, hostOverride) {
|
|
106
|
-
const
|
|
175
|
+
const hostUrl = hostOverride || getActiveHost();
|
|
176
|
+
const token = await getMcpToken(hostUrl);
|
|
107
177
|
const requestId = genRequestId();
|
|
108
178
|
const paramsWithMeta = {
|
|
109
179
|
...params,
|
|
@@ -126,6 +196,31 @@ async function mcpRequest(url, method, params = {}, hostOverride) {
|
|
|
126
196
|
headers,
|
|
127
197
|
body: JSON.stringify(body)
|
|
128
198
|
});
|
|
199
|
+
if (resp.status === 403) {
|
|
200
|
+
const fallbackToken = getFallbackMcpToken(hostUrl);
|
|
201
|
+
if (fallbackToken) {
|
|
202
|
+
const store = loadMcpTokenStore();
|
|
203
|
+
store[hostUrl] = fallbackToken;
|
|
204
|
+
saveMcpTokenStore(store);
|
|
205
|
+
process.stderr.write(`[ae-cli] MCP token refreshed from fallback for ${hostUrl}
|
|
206
|
+
`);
|
|
207
|
+
headers["mcp-token"] = fallbackToken;
|
|
208
|
+
const retryResp = await fetch(url, {
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers,
|
|
211
|
+
body: JSON.stringify(body)
|
|
212
|
+
});
|
|
213
|
+
if (!retryResp.ok) {
|
|
214
|
+
throw new Error(`MCP HTTP error: ${retryResp.status} ${retryResp.statusText}`);
|
|
215
|
+
}
|
|
216
|
+
const retryData = safeJsonParse(await retryResp.text());
|
|
217
|
+
if (retryData.error) {
|
|
218
|
+
throw new Error(`MCP error: ${retryData.error.message || JSON.stringify(retryData.error)}`);
|
|
219
|
+
}
|
|
220
|
+
return retryData.result;
|
|
221
|
+
}
|
|
222
|
+
throw new Error(`MCP token expired or invalid. Please set a new MCP token: ae-cli auth set-mcp-token <token> --host ${hostUrl}`);
|
|
223
|
+
}
|
|
129
224
|
if (!resp.ok) {
|
|
130
225
|
throw new Error(`MCP HTTP error: ${resp.status} ${resp.statusText}`);
|
|
131
226
|
}
|
|
@@ -169,6 +264,9 @@ function parseMcpResult(result) {
|
|
|
169
264
|
export {
|
|
170
265
|
registerMcpMappings,
|
|
171
266
|
resolveMcpUrl,
|
|
267
|
+
clearMcpToken,
|
|
268
|
+
setMcpTokenManual,
|
|
269
|
+
validateMcpToken,
|
|
172
270
|
callMcpTool,
|
|
173
271
|
parseMcpResult
|
|
174
272
|
};
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
clearToken,
|
|
3
3
|
getToken,
|
|
4
4
|
resolveHost
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4KQ7H7DY.js";
|
|
6
6
|
import {
|
|
7
7
|
safeJsonParse
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MR57UIKC.js";
|
|
9
9
|
|
|
10
10
|
// src/core/client.ts
|
|
11
11
|
import WebSocket from "ws";
|
|
@@ -17,11 +17,37 @@ import fs2 from "fs";
|
|
|
17
17
|
import path from "path";
|
|
18
18
|
var CONFIG_DIR = path.join(process.env.HOME || "", ".ae-cli");
|
|
19
19
|
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
20
|
+
var MCP_TOKENS_FILE = path.join(CONFIG_DIR, "mcp-tokens.json");
|
|
21
|
+
var FALLBACK_MCP_TOKEN_FILE = "/data/app/te_agent_ta/.ae-config/mcp-token.json";
|
|
20
22
|
function ensureDir() {
|
|
21
23
|
if (!fs2.existsSync(CONFIG_DIR)) fs2.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
22
24
|
}
|
|
25
|
+
function migrateFromFallback() {
|
|
26
|
+
if (!fs2.existsSync(FALLBACK_MCP_TOKEN_FILE) || fs2.existsSync(MCP_TOKENS_FILE)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const fallbackData = safeReadJsonFile(FALLBACK_MCP_TOKEN_FILE);
|
|
31
|
+
const tokenStore = {};
|
|
32
|
+
if (fallbackData && typeof fallbackData === "object" && !Array.isArray(fallbackData)) {
|
|
33
|
+
const url = fallbackData.url;
|
|
34
|
+
const token = fallbackData["mcp-token"];
|
|
35
|
+
if (url && token) {
|
|
36
|
+
tokenStore[url] = token;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (Object.keys(tokenStore).length > 0) {
|
|
40
|
+
ensureDir();
|
|
41
|
+
fs2.writeFileSync(MCP_TOKENS_FILE, JSON.stringify(tokenStore, null, 2));
|
|
42
|
+
return tokenStore;
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
23
48
|
function loadConfig() {
|
|
24
49
|
try {
|
|
50
|
+
const migratedTokens = migrateFromFallback();
|
|
25
51
|
if (fs2.existsSync(CONFIG_FILE)) {
|
|
26
52
|
const raw = safeReadJsonFile(CONFIG_FILE);
|
|
27
53
|
if (raw.defaultHost && !raw.activeHost) {
|
|
@@ -31,6 +57,22 @@ function loadConfig() {
|
|
|
31
57
|
}
|
|
32
58
|
return raw;
|
|
33
59
|
}
|
|
60
|
+
if (migratedTokens && Object.keys(migratedTokens).length > 0) {
|
|
61
|
+
const hosts = {};
|
|
62
|
+
for (const url of Object.keys(migratedTokens)) {
|
|
63
|
+
hosts[url] = { label: url };
|
|
64
|
+
process.stderr.write(`[ae-cli] Added host: ${url}
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
const activeHost = Object.keys(migratedTokens)[0];
|
|
68
|
+
process.stderr.write(`[ae-cli] Active host set to: ${activeHost}
|
|
69
|
+
`);
|
|
70
|
+
process.stderr.write(`[ae-cli] MCP tokens migrated from ${FALLBACK_MCP_TOKEN_FILE}
|
|
71
|
+
`);
|
|
72
|
+
const config = { activeHost, hosts };
|
|
73
|
+
saveConfig(config);
|
|
74
|
+
return config;
|
|
75
|
+
}
|
|
34
76
|
} catch (err) {
|
|
35
77
|
console.error(`Error loading config: ${err.message}`);
|
|
36
78
|
}
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
queryReportData,
|
|
5
5
|
querySql,
|
|
6
6
|
wsQuery
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-LAAS6ITR.js";
|
|
8
|
+
import "./chunk-4KQ7H7DY.js";
|
|
9
|
+
import "./chunk-MR57UIKC.js";
|
|
10
10
|
export {
|
|
11
11
|
httpGet,
|
|
12
12
|
httpPost,
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
clearToken,
|
|
2
3
|
getAuthStatus,
|
|
3
|
-
getToken
|
|
4
|
-
|
|
4
|
+
getToken,
|
|
5
|
+
loadToken,
|
|
6
|
+
validateToken
|
|
7
|
+
} from "./chunk-4KQ7H7DY.js";
|
|
5
8
|
import {
|
|
6
9
|
addHost,
|
|
7
10
|
listHosts,
|
|
8
11
|
removeHost,
|
|
9
12
|
setActiveHost,
|
|
10
13
|
updateHostLabel
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MR57UIKC.js";
|
|
12
15
|
|
|
13
16
|
// src/commands/config.ts
|
|
14
17
|
import * as readline from "readline";
|
|
@@ -136,9 +139,21 @@ Delete \x1B[1m${label}\x1B[0m (${url})? [y/N]: `, (a) => {
|
|
|
136
139
|
async function ensureAuth(hostUrl) {
|
|
137
140
|
const status = getAuthStatus(hostUrl);
|
|
138
141
|
if (status.authenticated) {
|
|
139
|
-
|
|
142
|
+
const cached = loadToken(hostUrl);
|
|
143
|
+
if (cached && cached.token) {
|
|
144
|
+
process.stderr.write(`\x1B[2m[ae-cli] Validating token...\x1B[0m
|
|
140
145
|
`);
|
|
141
|
-
|
|
146
|
+
const isValid = await validateToken(cached.token, hostUrl);
|
|
147
|
+
if (isValid) {
|
|
148
|
+
process.stderr.write(`\x1B[32m\u2713\x1B[0m Token valid for ${hostUrl}
|
|
149
|
+
`);
|
|
150
|
+
return;
|
|
151
|
+
} else {
|
|
152
|
+
clearToken(hostUrl);
|
|
153
|
+
process.stderr.write(`\x1B[33m!\x1B[0m Token expired or invalid. Re-authenticating...
|
|
154
|
+
`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
142
157
|
}
|
|
143
158
|
process.stderr.write(`
|
|
144
159
|
\x1B[33m!\x1B[0m No valid token for ${hostUrl}. Starting login...
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
getActiveHost,
|
|
7
7
|
safeJsonParse
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MR57UIKC.js";
|
|
9
9
|
|
|
10
10
|
// src/index.ts
|
|
11
11
|
import { Command as CommanderCommand } from "commander";
|
|
@@ -62,7 +62,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
|
|
|
62
62
|
let _clientModule = null;
|
|
63
63
|
async function getClient() {
|
|
64
64
|
if (!_clientModule) {
|
|
65
|
-
_clientModule = await import("./client-
|
|
65
|
+
_clientModule = await import("./client-O56G2SNJ.js");
|
|
66
66
|
}
|
|
67
67
|
return _clientModule;
|
|
68
68
|
}
|
|
@@ -105,7 +105,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
|
|
|
105
105
|
return client.queryReportData(projectId, reportId, qp, eventModel, options, ctx.host());
|
|
106
106
|
},
|
|
107
107
|
async token() {
|
|
108
|
-
const { getToken } = await import("./auth-
|
|
108
|
+
const { getToken } = await import("./auth-ECD46NBA.js");
|
|
109
109
|
return getToken(ctx.host());
|
|
110
110
|
},
|
|
111
111
|
host() {
|
|
@@ -210,37 +210,37 @@ program.name("ae-cli").version(version).description("CLI tool for ThinkingAI (AE
|
|
|
210
210
|
async function loadCommands() {
|
|
211
211
|
const commands = [];
|
|
212
212
|
try {
|
|
213
|
-
const teAnalysis = await import("./te-analysis-
|
|
213
|
+
const teAnalysis = await import("./te-analysis-UGKESPBE.js");
|
|
214
214
|
commands.push(...teAnalysis.default);
|
|
215
215
|
} catch {
|
|
216
216
|
}
|
|
217
217
|
try {
|
|
218
|
-
const teAudience = await import("./te-audience-
|
|
218
|
+
const teAudience = await import("./te-audience-THZNVHYB.js");
|
|
219
219
|
commands.push(...teAudience.default);
|
|
220
220
|
} catch {
|
|
221
221
|
}
|
|
222
222
|
try {
|
|
223
|
-
const teMeta = await import("./te-meta-
|
|
223
|
+
const teMeta = await import("./te-meta-MGO5BCMG.js");
|
|
224
224
|
commands.push(...teMeta.default);
|
|
225
225
|
} catch {
|
|
226
226
|
}
|
|
227
227
|
try {
|
|
228
|
-
const teCommon = await import("./te-common-
|
|
228
|
+
const teCommon = await import("./te-common-QZOUME3S.js");
|
|
229
229
|
commands.push(...teCommon.default);
|
|
230
230
|
} catch {
|
|
231
231
|
}
|
|
232
232
|
try {
|
|
233
|
-
const engage = await import("./te-engage-
|
|
233
|
+
const engage = await import("./te-engage-RYGEQTYK.js");
|
|
234
234
|
commands.push(...engage.default);
|
|
235
235
|
} catch {
|
|
236
236
|
}
|
|
237
237
|
try {
|
|
238
|
-
const community = await import("./te-community-
|
|
238
|
+
const community = await import("./te-community-AZVW3NFX.js");
|
|
239
239
|
commands.push(...community.default);
|
|
240
240
|
} catch {
|
|
241
241
|
}
|
|
242
242
|
try {
|
|
243
|
-
const dataops = await import("./te-dataops-
|
|
243
|
+
const dataops = await import("./te-dataops-OE5PX2K6.js");
|
|
244
244
|
commands.push(...dataops.default);
|
|
245
245
|
} catch {
|
|
246
246
|
}
|
|
@@ -248,21 +248,21 @@ async function loadCommands() {
|
|
|
248
248
|
}
|
|
249
249
|
async function registerAuthCommands() {
|
|
250
250
|
try {
|
|
251
|
-
const { registerAuth } = await import("./auth-
|
|
251
|
+
const { registerAuth } = await import("./auth-2UTBG5U3.js");
|
|
252
252
|
registerAuth(program);
|
|
253
253
|
} catch {
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
async function registerConfigCommands() {
|
|
257
257
|
try {
|
|
258
|
-
const { registerConfig } = await import("./config-
|
|
258
|
+
const { registerConfig } = await import("./config-BU5FHGGE.js");
|
|
259
259
|
registerConfig(program);
|
|
260
260
|
} catch {
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
async function registerApiCommand() {
|
|
264
264
|
try {
|
|
265
|
-
const { registerApi } = await import("./raw-
|
|
265
|
+
const { registerApi } = await import("./raw-A3VN2B6I.js");
|
|
266
266
|
registerApi(program);
|
|
267
267
|
} catch {
|
|
268
268
|
}
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
httpGet,
|
|
7
7
|
httpPost
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LAAS6ITR.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveHost
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-4KQ7H7DY.js";
|
|
12
12
|
import {
|
|
13
13
|
safeJsonParse
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-MR57UIKC.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-7QBNU44L.js";
|
|
6
|
+
import "./chunk-4KQ7H7DY.js";
|
|
7
|
+
import "./chunk-MR57UIKC.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/te-analysis/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-7QBNU44L.js";
|
|
6
|
+
import "./chunk-4KQ7H7DY.js";
|
|
7
|
+
import "./chunk-MR57UIKC.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-7QBNU44L.js";
|
|
6
|
+
import "./chunk-4KQ7H7DY.js";
|
|
7
|
+
import "./chunk-MR57UIKC.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-7QBNU44L.js";
|
|
7
|
+
import "./chunk-4KQ7H7DY.js";
|
|
8
|
+
import "./chunk-MR57UIKC.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-7QBNU44L.js";
|
|
7
|
+
import "./chunk-4KQ7H7DY.js";
|
|
8
|
+
import "./chunk-MR57UIKC.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-7QBNU44L.js";
|
|
7
|
+
import "./chunk-4KQ7H7DY.js";
|
|
8
|
+
import "./chunk-MR57UIKC.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/te-engage/utils.ts
|
|
11
11
|
function buildMcpDryRun(ctx, serviceName44, toolName44, args) {
|
|
@@ -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-7QBNU44L.js";
|
|
6
|
+
import "./chunk-4KQ7H7DY.js";
|
|
7
|
+
import "./chunk-MR57UIKC.js";
|
|
8
8
|
|
|
9
9
|
// src/commands/te-meta/shared.ts
|
|
10
10
|
function createMcpCommand(config) {
|
|
@@ -380,12 +380,14 @@ var generateTrackProgram = createMcpCommand({
|
|
|
380
380
|
description: "Generate a tracking plan from structured business context (async)",
|
|
381
381
|
flags: [
|
|
382
382
|
{ name: "project_id", type: "number", required: true, alias: "p", desc: "Project ID" },
|
|
383
|
-
{ name: "
|
|
383
|
+
{ name: "language", type: "string", required: true, alias: "l", desc: "Language code (zh-CN, en-US, ja-JP, ko-KR)" },
|
|
384
|
+
{ name: "form_data", type: "json", required: true, desc: "Structured business context JSON object, optional fields for example: account_system, revenue_model, core_gameplay, currency_system, main_entries, predefinedEvent, developmentCarrier" }
|
|
384
385
|
],
|
|
385
386
|
risk: "write",
|
|
386
387
|
mcpService: "te_analysis_extend",
|
|
387
388
|
buildArgs: (ctx) => ({
|
|
388
389
|
projectId: ctx.num("project_id"),
|
|
390
|
+
language: ctx.str("language"),
|
|
389
391
|
formData: ctx.json("form_data")
|
|
390
392
|
})
|
|
391
393
|
});
|
package/package.json
CHANGED
|
@@ -52,6 +52,15 @@ Safety constraints:
|
|
|
52
52
|
- Write commands require explicit user intent and normally keep the confirmation prompt.
|
|
53
53
|
- Use `--dry-run` before risky or complex writes.
|
|
54
54
|
- Never invent command names, flags, JSON payloads, `project_id`, resource IDs, field names, event names, property names, metric definitions, or date formats. Read the matching command reference and discover real project metadata first.
|
|
55
|
+
- **NEVER fabricate or guess resource names** (reports, dashboards, events, properties, metrics, clusters, tags, alerts). Always use list commands to discover real resources first. If a resource is not found after fuzzy search and full list fallback, explicitly tell the user "resource not found" and stop - do not proceed with fabricated names.
|
|
56
|
+
|
|
57
|
+
Language consistency:
|
|
58
|
+
- **Input-output language matching**: Always respond in the same language as the user's input.
|
|
59
|
+
- User asks in Chinese → Respond in Chinese, including result interpretation and error messages
|
|
60
|
+
- User asks in English → Respond in English
|
|
61
|
+
- **CLI output handling**: CLI returns JSON in English, but your interpretation and summary MUST match user's language
|
|
62
|
+
- **Resource names**: Keep original resource names as-is (don't translate), but descriptions and explanations should match user's language
|
|
63
|
+
- **Error messages**: Translate CLI error messages to user's language when presenting results
|
|
55
64
|
|
|
56
65
|
## When to Use
|
|
57
66
|
|
|
@@ -109,6 +118,55 @@ Closed-loop check (must be explicit in result):
|
|
|
109
118
|
- `+get_resource_url` called or skipped (no ID)
|
|
110
119
|
- Link completion status
|
|
111
120
|
|
|
121
|
+
### C. FUZZY_SEARCH_FALLBACK
|
|
122
|
+
|
|
123
|
+
For list commands with `--query` parameter (list_reports, list_dashboards, list_events, list_clusters, list_tags, list_alerts, list_metrics):
|
|
124
|
+
|
|
125
|
+
1. **First attempt**: Use `--query` with user-provided keyword for fuzzy search
|
|
126
|
+
2. **If no results found**, retry up to 2 more times with:
|
|
127
|
+
- Broader keywords (remove modifiers, use root words)
|
|
128
|
+
- Alternative terms or synonyms
|
|
129
|
+
3. **After 3 failed fuzzy attempts**, fall back to full list (omit `--query`)
|
|
130
|
+
4. **Present full list** to user and ask them to identify the target resource
|
|
131
|
+
5. **Never proceed** with operations on non-existent resources
|
|
132
|
+
|
|
133
|
+
**Example workflow:**
|
|
134
|
+
- User asks: "Find active user report"
|
|
135
|
+
- Attempt 1: `--query "active user"` → no results
|
|
136
|
+
- Attempt 2: `--query "active"` → no results
|
|
137
|
+
- Attempt 3: `--query "user"` → no results
|
|
138
|
+
- Fallback: list all reports, show to user, ask for selection
|
|
139
|
+
|
|
140
|
+
### D. QUERY_EXISTING_FIRST
|
|
141
|
+
|
|
142
|
+
Before executing ad-hoc queries (`query_adhoc`), MUST check for existing reports/dashboards first:
|
|
143
|
+
|
|
144
|
+
**Mandatory workflow for data queries:**
|
|
145
|
+
|
|
146
|
+
1. **Identify user intent** - Extract what metrics/dimensions/filters the user wants
|
|
147
|
+
2. **Search existing reports** - Use `list_reports --query <keyword>` to find matching reports
|
|
148
|
+
3. **Search existing dashboards** - Use `list_dashboards --query <keyword>` to find matching dashboards
|
|
149
|
+
4. **If found** - Use `query_report_data` or `query_dashboard_report_data` to get data from existing assets
|
|
150
|
+
5. **If not found** - Only then use `query_adhoc` for ad-hoc analysis
|
|
151
|
+
|
|
152
|
+
**Rationale:**
|
|
153
|
+
- **Performance**: Existing reports are pre-computed and faster
|
|
154
|
+
- **Consistency**: Reports have business-defined metrics and calibrated logic
|
|
155
|
+
- **Resource efficiency**: Avoid redundant computation
|
|
156
|
+
- **Permissions**: Users may have report access but not ad-hoc query permissions
|
|
157
|
+
|
|
158
|
+
**Example:**
|
|
159
|
+
- User: "Query active users in last 7 days"
|
|
160
|
+
- Step 1: `list_reports --query "active user"` → found "DAU Active Users Report"
|
|
161
|
+
- Step 2: `query_report_data --report_id <id>` → return data
|
|
162
|
+
- ❌ WRONG: Directly use `query_adhoc` without checking existing reports
|
|
163
|
+
|
|
164
|
+
**Exceptions (when ad-hoc is acceptable):**
|
|
165
|
+
- User explicitly requests "ad-hoc query" or "ad-hoc analysis"
|
|
166
|
+
- User wants custom filters/groupings not available in existing reports
|
|
167
|
+
- User is exploring data for new insights (exploratory analysis)
|
|
168
|
+
- No matching reports found after search + fallback
|
|
169
|
+
|
|
112
170
|
## Tool Groups (69)
|
|
113
171
|
|
|
114
172
|
### analysis (31)
|
|
@@ -16,26 +16,26 @@ Domain: **Project Configuration**
|
|
|
16
16
|
|
|
17
17
|
## Commands
|
|
18
18
|
```bash
|
|
19
|
-
ae-cli analysis_meta +generate_track_program --project_id <project_id> --form_data '{}'
|
|
19
|
+
ae-cli analysis_meta +generate_track_program --project_id <project_id> --language <language> --form_data '{}'
|
|
20
20
|
ae-cli analysis_meta +generate_track_program --dry-run
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Parameters
|
|
24
|
-
| Parameter | Required | Description
|
|
25
|
-
|
|
26
|
-
| `--project_id` / `-p` | Yes | Project ID
|
|
27
|
-
| `--
|
|
24
|
+
| Parameter | Required | Description |
|
|
25
|
+
|-----------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
26
|
+
| `--project_id` / `-p` | Yes | Project ID |
|
|
27
|
+
| `--language` / `-l` | Yes | Language code. Supported values: `zh-CN`, `en-US`, `ja-JP`, `ko-KR` |
|
|
28
|
+
| `--form_data` | Yes | Structured business context JSON object. Optional fields for example: account_system, revenue_model, core_gameplay, currency_system, main_entries, predefinedEvent (array of event names like install, start, close), developmentCarrier (array of platforms like Android, iOS, Unity, Cocos, Douyin Mini Game, WeChat Mini Game). All fields can be customized based on business needs. |
|
|
28
29
|
|
|
29
30
|
## Decision Rules
|
|
30
31
|
- **CRITICAL: Always call `+get_track_program` first to check existing tracking plan before generating.**
|
|
31
|
-
- First run should only pass the required parameters (`--project_id`, `--form_data`).
|
|
32
|
+
- First run should only pass the required parameters (`--project_id`, `--language`, `--form_data`).
|
|
32
33
|
- Wrap JSON arguments in single quotes (for example `--form_data '{}'`) to avoid shell escaping issues.
|
|
33
34
|
- This is an asynchronous operation; check in-site message center for generation results.
|
|
34
35
|
- For cross-project troubleshooting, first confirm whether `--project_id` matches the current permissions and target environment.
|
|
35
36
|
|
|
36
37
|
## Next Steps After Failure
|
|
37
|
-
- If required parameters are missing, fall back to the smallest runnable command and fill them in (focus on `--project_id
|
|
38
|
-
- If `FORM_DATA_REQUIRED_FIELDS_MISSING` occurs, ensure all required fields are provided: account_system, revenue_model, core_gameplay, currency_system, main_entries, language.
|
|
38
|
+
- If required parameters are missing, fall back to the smallest runnable command and fill them in (focus on `--project_id`, `--language`, and `--form_data`).
|
|
39
39
|
- If `Invalid JSON` occurs, validate with the smallest JSON structure first.
|
|
40
40
|
|
|
41
41
|
## Agent Response Flow
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Metadata Lookup**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- List all alerts in the project. Supports keyword filtering by alert name. Returns a paginated list containing alerts array and pager result with total count.
|
|
9
13
|
- List all alerts in the project.
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Cluster Management**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- List cluster metadata accessible to the current user in the project.
|
|
9
13
|
- Supports payload governance parameters: `query`, `fields`, `limit`, `offset`.
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Dashboard management**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- List dashboard metadata accessible to the current user in the project. Supports keyword filtering and returns dashboard IDs, names, descriptions, and related metadata, but not dashboard configuration or report data.
|
|
9
13
|
- List dashboard metadata accessible to the current user in the project.
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Metadata Query**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- Read-only query for SYSTEM METADATA already effective in the project. Use for super events in production metadata. Do NOT use for tracking-plan metadata (bury/track program); that belongs to BuryProgramTool.
|
|
9
13
|
- Read-only query for SYSTEM METADATA already effective in the project.
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Metadata Query**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- List metric metadata in the project. Supports keyword filtering and returns metric IDs, names, display names, model types, remarks, and related metadata, but not metric calculation results.
|
|
9
13
|
- Supports pagination with fields/limit/offset for payload governance.
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Report management**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- List report metadata accessible to the current user in the project. Supports keyword filtering and returns report IDs, names, model types, update times, and related metadata, but not report definitions or analysis data.
|
|
9
13
|
- List report metadata accessible to the current user in the project.
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Tag Management**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**Fuzzy Search Fallback:** If `--query` returns no results, retry with broader keywords (max 3 attempts), then fall back to full list. See [SKILL.md § C. FUZZY_SEARCH_FALLBACK](../SKILL.md#c-fuzzy_search_fallback).
|
|
10
|
+
|
|
7
11
|
## Use Cases
|
|
8
12
|
- List tag metadata accessible to the current user in the project.
|
|
9
13
|
- Supports payload governance parameters: `query`, `fields`, `limit`, `offset`.
|
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
Domain: **Model analysis**
|
|
6
6
|
|
|
7
|
+
## Constraints
|
|
8
|
+
|
|
9
|
+
**⚠️ QUERY_EXISTING_FIRST:** Before using ad-hoc query, you MUST first check for existing reports/dashboards with `list_reports` and `list_dashboards`. Only use `query_adhoc` if no matching reports found. See [SKILL.md § D. QUERY_EXISTING_FIRST](../SKILL.md#d-query_existing_first).
|
|
10
|
+
|
|
11
|
+
**Quick check workflow:**
|
|
12
|
+
1. `list_reports --query <keyword>` - search matching reports
|
|
13
|
+
2. `list_dashboards --query <keyword>` - search matching dashboards
|
|
14
|
+
3. If found → use `query_report_data` or `query_dashboard_report_data`
|
|
15
|
+
4. If not found → only then use `query_adhoc`
|
|
16
|
+
|
|
7
17
|
## Use Cases
|
|
8
18
|
- Precondition helper: call `+get_analysis_query_schema` to get the structure before using this tool.
|
|
9
19
|
- When constructing a real `qp`, you must supplement it with real project metadata; first call `analysis_meta +list_events` and `analysis_meta +list_properties`.
|
package/dist/auth-U2GHFMFY.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
printError,
|
|
3
|
-
printOutput
|
|
4
|
-
} from "./chunk-KM57HI5B.js";
|
|
5
|
-
import {
|
|
6
|
-
clearToken,
|
|
7
|
-
getAuthStatus,
|
|
8
|
-
getToken,
|
|
9
|
-
resolveHost,
|
|
10
|
-
setTokenManual
|
|
11
|
-
} from "./chunk-UK6HO5O5.js";
|
|
12
|
-
import {
|
|
13
|
-
loadConfig,
|
|
14
|
-
saveConfig
|
|
15
|
-
} from "./chunk-EBFUVWIZ.js";
|
|
16
|
-
|
|
17
|
-
// src/commands/auth.ts
|
|
18
|
-
function registerAuth(program) {
|
|
19
|
-
const auth = program.command("auth").description("Authentication management");
|
|
20
|
-
auth.command("login").description("Login to AE (auto-extract token from Chrome on macOS)").action(async () => {
|
|
21
|
-
const host = resolveHost(program.opts().host);
|
|
22
|
-
if (!host) {
|
|
23
|
-
printError("config", "No AE host configured.", "Run: ae-cli config set-host");
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
const token = await getToken(host);
|
|
28
|
-
process.stderr.write(`[ae-cli] Authenticated to ${host}
|
|
29
|
-
`);
|
|
30
|
-
printOutput({ authenticated: true, host, token: token.slice(0, 8) + "..." }, program.opts().format || "json");
|
|
31
|
-
} catch (err) {
|
|
32
|
-
printError("auth", err.message);
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
auth.command("set-token <token>").description("Manually set authentication token for active host").action((token) => {
|
|
37
|
-
const host = resolveHost(program.opts().host);
|
|
38
|
-
if (!host) {
|
|
39
|
-
printError("config", "No AE host configured.", "Run: ae-cli config set-host");
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
const config = loadConfig();
|
|
43
|
-
if (!config.hosts[host]) {
|
|
44
|
-
config.hosts[host] = { label: host };
|
|
45
|
-
if (!config.activeHost) {
|
|
46
|
-
config.activeHost = host;
|
|
47
|
-
}
|
|
48
|
-
saveConfig(config);
|
|
49
|
-
process.stderr.write(`[ae-cli] Config saved for ${host}
|
|
50
|
-
`);
|
|
51
|
-
printOutput({ saved: true, config }, program.opts().format || "json");
|
|
52
|
-
}
|
|
53
|
-
setTokenManual(token, host);
|
|
54
|
-
process.stderr.write(`[ae-cli] Token saved for ${host}
|
|
55
|
-
`);
|
|
56
|
-
printOutput({ saved: true, host }, program.opts().format || "json");
|
|
57
|
-
});
|
|
58
|
-
auth.command("status").description("Show current authentication status").action(() => {
|
|
59
|
-
const host = resolveHost(program.opts().host);
|
|
60
|
-
if (!host) {
|
|
61
|
-
printOutput({ authenticated: false, host: "(none)", hint: "Run: ae-cli config set-host" }, program.opts().format || "json");
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const status = getAuthStatus(host);
|
|
65
|
-
printOutput(status, program.opts().format || "json");
|
|
66
|
-
});
|
|
67
|
-
auth.command("logout").description("Clear stored token for active host").action(() => {
|
|
68
|
-
const host = resolveHost(program.opts().host);
|
|
69
|
-
if (!host) {
|
|
70
|
-
printError("config", "No AE host configured.", "Run: ae-cli config set-host");
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
clearToken(host);
|
|
74
|
-
process.stderr.write(`[ae-cli] Token cleared for ${host}
|
|
75
|
-
`);
|
|
76
|
-
printOutput({ cleared: true, host }, program.opts().format || "json");
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
export {
|
|
80
|
-
registerAuth
|
|
81
|
-
};
|