@thinkingai/ae-cli 6.0.33 → 6.1.5
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/dist/index.js +8 -3
- package/dist/te-experiment-JKX4FH6D.js +607 -0
- package/dist/te-experiment-UMSHBBKI.js +607 -0
- package/package.json +2 -1
- package/skills/ae-experiment/SKILL.md +64 -0
- package/skills/ae-experiment/references/batch_delete_experiment.md +11 -0
- package/skills/ae-experiment/references/batch_delete_feature.md +11 -0
- package/skills/ae-experiment/references/batch_delete_traffic_layer.md +11 -0
- package/skills/ae-experiment/references/cancel_experiment_query_by_request_id.md +10 -0
- package/skills/ae-experiment/references/check_experiment_ready.md +13 -0
- package/skills/ae-experiment/references/delete_metric.md +11 -0
- package/skills/ae-experiment/references/manage_experiment.md +15 -0
- package/skills/ae-experiment/references/manage_feature_status.md +11 -0
- package/skills/ae-experiment/references/query_bucket_list.md +10 -0
- package/skills/ae-experiment/references/query_experiment_detail.md +11 -0
- package/skills/ae-experiment/references/query_experiment_list.md +10 -0
- package/skills/ae-experiment/references/query_experiment_metric_trend.md +16 -0
- package/skills/ae-experiment/references/query_experiment_report_summary.md +12 -0
- package/skills/ae-experiment/references/query_experiment_sample_size_report.md +16 -0
- package/skills/ae-experiment/references/query_feature_detail.md +12 -0
- package/skills/ae-experiment/references/query_feature_list.md +10 -0
- package/skills/ae-experiment/references/query_metric_detail.md +11 -0
- package/skills/ae-experiment/references/query_metric_list.md +10 -0
- package/skills/ae-experiment/references/query_traffic_layer_detail.md +11 -0
- package/skills/ae-experiment/references/query_traffic_layer_list.md +10 -0
- package/skills/ae-experiment/references/save_experiment.md +17 -0
- package/skills/ae-experiment/references/save_feature.md +13 -0
- package/skills/ae-experiment/references/save_metric.md +13 -0
- package/skills/ae-experiment/references/save_submit_experiment.md +13 -0
- package/skills/ae-experiment/references/save_traffic_layer.md +13 -0
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
import {
|
|
2
|
+
callMcpTool,
|
|
3
|
+
parseMcpResult,
|
|
4
|
+
registerMcpMappings,
|
|
5
|
+
resolveMcpUrl
|
|
6
|
+
} from "./chunk-CPVTECJ3.js";
|
|
7
|
+
import "./chunk-LCXU3AAT.js";
|
|
8
|
+
import "./chunk-E7UXXHO3.js";
|
|
9
|
+
import "./chunk-IR4ZLVPW.js";
|
|
10
|
+
import "./chunk-V6FR6WTW.js";
|
|
11
|
+
import "./chunk-24BAVOX3.js";
|
|
12
|
+
import "./chunk-LYVNONC4.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/te-experiment/shared.ts
|
|
15
|
+
var EXPERIMENT_CLI_SERVICE = "experiment";
|
|
16
|
+
var EXPERIMENT_MCP_SERVICE = "experiment";
|
|
17
|
+
var PROJECT_ID_FLAG = {
|
|
18
|
+
name: "project_id",
|
|
19
|
+
type: "number",
|
|
20
|
+
required: true,
|
|
21
|
+
alias: "p",
|
|
22
|
+
desc: "Project ID"
|
|
23
|
+
};
|
|
24
|
+
function createExperimentCommand(config) {
|
|
25
|
+
const mcpService = config.mcpService || EXPERIMENT_MCP_SERVICE;
|
|
26
|
+
const toolName = config.toolName || config.command.slice(1);
|
|
27
|
+
return {
|
|
28
|
+
service: EXPERIMENT_CLI_SERVICE,
|
|
29
|
+
command: config.command,
|
|
30
|
+
description: config.description,
|
|
31
|
+
flags: config.flags,
|
|
32
|
+
risk: config.risk,
|
|
33
|
+
validate: config.validate,
|
|
34
|
+
dryRun: (ctx) => buildMcpDryRun(ctx, mcpService, toolName, config.buildArgs(ctx)),
|
|
35
|
+
execute: async (ctx) => executeMcpCommand(ctx, mcpService, toolName, config.buildArgs(ctx))
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function buildMcpDryRun(ctx, serviceName, toolName, args) {
|
|
39
|
+
const host = ctx.host();
|
|
40
|
+
return {
|
|
41
|
+
method: "MCP tools/call",
|
|
42
|
+
url: resolveMcpUrl(ctx.mcpUrl(), host, serviceName),
|
|
43
|
+
body: {
|
|
44
|
+
serviceName,
|
|
45
|
+
toolName,
|
|
46
|
+
arguments: args
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function executeMcpCommand(ctx, serviceName, toolName, args) {
|
|
51
|
+
const host = ctx.host();
|
|
52
|
+
const mcpUrl = resolveMcpUrl(ctx.mcpUrl(), host, serviceName);
|
|
53
|
+
const result = await callMcpTool(mcpUrl, toolName, args, host);
|
|
54
|
+
return parseMcpResult(result);
|
|
55
|
+
}
|
|
56
|
+
function reqFlag(desc) {
|
|
57
|
+
return { name: "req", type: "json", required: true, desc };
|
|
58
|
+
}
|
|
59
|
+
function hasFlag(ctx, name) {
|
|
60
|
+
return ctx.str(name) !== "";
|
|
61
|
+
}
|
|
62
|
+
function readOptionalString(ctx, name) {
|
|
63
|
+
const value = ctx.str(name);
|
|
64
|
+
return value === "" ? void 0 : value;
|
|
65
|
+
}
|
|
66
|
+
function readOptionalBoolean(ctx, name) {
|
|
67
|
+
return hasFlag(ctx, name) ? ctx.bool(name) : void 0;
|
|
68
|
+
}
|
|
69
|
+
function readOptionalJsonArray(ctx, name) {
|
|
70
|
+
const value = ctx.json(name);
|
|
71
|
+
if (value === void 0) return void 0;
|
|
72
|
+
if (!Array.isArray(value)) {
|
|
73
|
+
throw new Error(`Flag --${name} must be a JSON array`);
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
function readRequiredJsonArray(ctx, name, minLength = 1) {
|
|
78
|
+
const value = readOptionalJsonArray(ctx, name);
|
|
79
|
+
if (!value || value.length < minLength) {
|
|
80
|
+
throw new Error(`Flag --${name} must be a JSON array with at least ${minLength} item(s)`);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
function readRequiredStringArray(ctx, name) {
|
|
85
|
+
const value = readRequiredJsonArray(ctx, name);
|
|
86
|
+
if (!value.every((item) => typeof item === "string" && item.length > 0)) {
|
|
87
|
+
throw new Error(`Flag --${name} must be a JSON array of non-empty strings`);
|
|
88
|
+
}
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
function readRequiredJsonObject(ctx, name) {
|
|
92
|
+
const value = ctx.json(name);
|
|
93
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
94
|
+
throw new Error(`Flag --${name} must be a JSON object`);
|
|
95
|
+
}
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
function projectArgs(ctx) {
|
|
99
|
+
return { projectId: ctx.num("project_id") };
|
|
100
|
+
}
|
|
101
|
+
function projectReqArgs(ctx) {
|
|
102
|
+
const projectId = ctx.num("project_id");
|
|
103
|
+
return {
|
|
104
|
+
projectId,
|
|
105
|
+
req: {
|
|
106
|
+
...readRequiredJsonObject(ctx, "req"),
|
|
107
|
+
projectId
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function addOptionalString(args, ctx, flagName, argName) {
|
|
112
|
+
const value = readOptionalString(ctx, flagName);
|
|
113
|
+
if (value !== void 0) args[argName] = value;
|
|
114
|
+
}
|
|
115
|
+
function addOptionalBoolean(args, ctx, flagName, argName) {
|
|
116
|
+
const value = readOptionalBoolean(ctx, flagName);
|
|
117
|
+
if (value !== void 0) args[argName] = value;
|
|
118
|
+
}
|
|
119
|
+
function requireAllowedValue(value, allowed, flagName) {
|
|
120
|
+
if (!allowed.includes(value)) {
|
|
121
|
+
throw new Error(`Flag --${flagName} must be one of: ${allowed.join(", ")}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/commands/te-experiment/batch-delete-experiment.ts
|
|
126
|
+
function buildArgs(ctx) {
|
|
127
|
+
return {
|
|
128
|
+
projectId: ctx.num("project_id"),
|
|
129
|
+
expIds: readRequiredStringArray(ctx, "exp_ids")
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
var batchDeleteExperiment = createExperimentCommand({
|
|
133
|
+
command: "+batch_delete_experiment",
|
|
134
|
+
description: "Batch delete experiments.",
|
|
135
|
+
flags: [
|
|
136
|
+
PROJECT_ID_FLAG,
|
|
137
|
+
{ name: "exp_ids", type: "json", required: true, desc: "Experiment ID list as JSON array" }
|
|
138
|
+
],
|
|
139
|
+
risk: "write",
|
|
140
|
+
validate: (ctx) => {
|
|
141
|
+
readRequiredStringArray(ctx, "exp_ids");
|
|
142
|
+
},
|
|
143
|
+
buildArgs
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// src/commands/te-experiment/batch-delete-feature.ts
|
|
147
|
+
var batchDeleteFeature = createExperimentCommand({
|
|
148
|
+
command: "+batch_delete_feature",
|
|
149
|
+
description: "Batch delete Features.",
|
|
150
|
+
flags: [
|
|
151
|
+
PROJECT_ID_FLAG,
|
|
152
|
+
reqFlag("Feature delete request as JSON object")
|
|
153
|
+
],
|
|
154
|
+
risk: "write",
|
|
155
|
+
validate: (ctx) => {
|
|
156
|
+
readRequiredJsonObject(ctx, "req");
|
|
157
|
+
},
|
|
158
|
+
buildArgs: projectReqArgs
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// src/commands/te-experiment/batch-delete-traffic-layer.ts
|
|
162
|
+
function buildArgs2(ctx) {
|
|
163
|
+
return {
|
|
164
|
+
projectId: ctx.num("project_id"),
|
|
165
|
+
layerIds: readRequiredStringArray(ctx, "layer_ids")
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
var batchDeleteTrafficLayer = createExperimentCommand({
|
|
169
|
+
command: "+batch_delete_traffic_layer",
|
|
170
|
+
description: "Batch delete traffic layers.",
|
|
171
|
+
flags: [
|
|
172
|
+
PROJECT_ID_FLAG,
|
|
173
|
+
{ name: "layer_ids", type: "json", required: true, desc: "Traffic layer ID list as JSON array" }
|
|
174
|
+
],
|
|
175
|
+
risk: "write",
|
|
176
|
+
validate: (ctx) => {
|
|
177
|
+
readRequiredStringArray(ctx, "layer_ids");
|
|
178
|
+
},
|
|
179
|
+
buildArgs: buildArgs2
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// src/commands/te-experiment/cancel-experiment-query-by-request-id.ts
|
|
183
|
+
function buildArgs3(ctx) {
|
|
184
|
+
return { requestId: ctx.str("request_id") };
|
|
185
|
+
}
|
|
186
|
+
var cancelExperimentQueryByRequestId = createExperimentCommand({
|
|
187
|
+
command: "+cancel_experiment_query_by_request_id",
|
|
188
|
+
description: "Cancel a running experiment report query by request ID.",
|
|
189
|
+
flags: [
|
|
190
|
+
{ name: "request_id", type: "string", required: true, desc: "Request ID to cancel" }
|
|
191
|
+
],
|
|
192
|
+
risk: "write",
|
|
193
|
+
buildArgs: buildArgs3
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// src/commands/te-experiment/check-experiment-ready.ts
|
|
197
|
+
function buildArgs4(ctx) {
|
|
198
|
+
return {
|
|
199
|
+
projectId: ctx.num("project_id"),
|
|
200
|
+
expId: ctx.str("exp_id")
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
var checkExperimentReady = createExperimentCommand({
|
|
204
|
+
command: "+check_experiment_ready",
|
|
205
|
+
description: "Check whether an experiment is ready for online status transitions.",
|
|
206
|
+
flags: [
|
|
207
|
+
PROJECT_ID_FLAG,
|
|
208
|
+
{ name: "exp_id", type: "string", required: true, desc: "Experiment ID" }
|
|
209
|
+
],
|
|
210
|
+
risk: "read",
|
|
211
|
+
buildArgs: buildArgs4
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// src/commands/te-experiment/delete-metric.ts
|
|
215
|
+
function buildArgs5(ctx) {
|
|
216
|
+
return {
|
|
217
|
+
projectId: ctx.num("project_id"),
|
|
218
|
+
metricId: ctx.str("metric_id")
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
var deleteMetric = createExperimentCommand({
|
|
222
|
+
command: "+delete_metric",
|
|
223
|
+
description: "Delete a metric.",
|
|
224
|
+
flags: [
|
|
225
|
+
PROJECT_ID_FLAG,
|
|
226
|
+
{ name: "metric_id", type: "string", required: true, desc: "Metric ID" }
|
|
227
|
+
],
|
|
228
|
+
risk: "write",
|
|
229
|
+
buildArgs: buildArgs5
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// src/commands/te-experiment/manage-experiment.ts
|
|
233
|
+
var TARGET_STATUSES = ["draft", "testing", "pending", "running", "paused", "ended", "archive"];
|
|
234
|
+
function buildArgs6(ctx) {
|
|
235
|
+
const args = {
|
|
236
|
+
projectId: ctx.num("project_id"),
|
|
237
|
+
expId: ctx.str("exp_id"),
|
|
238
|
+
targetStatus: ctx.str("target_status")
|
|
239
|
+
};
|
|
240
|
+
addOptionalString(args, ctx, "remark", "remark");
|
|
241
|
+
return args;
|
|
242
|
+
}
|
|
243
|
+
var manageExperiment = createExperimentCommand({
|
|
244
|
+
command: "+manage_experiment",
|
|
245
|
+
description: "Manage experiment status.",
|
|
246
|
+
flags: [
|
|
247
|
+
PROJECT_ID_FLAG,
|
|
248
|
+
{ name: "exp_id", type: "string", required: true, desc: "Experiment ID" },
|
|
249
|
+
{ name: "target_status", type: "string", required: true, desc: "Target status: draft, testing, pending, running, paused, ended, or archive" },
|
|
250
|
+
{ name: "remark", type: "string", required: false, desc: "Operation remark" }
|
|
251
|
+
],
|
|
252
|
+
risk: "write",
|
|
253
|
+
validate: (ctx) => {
|
|
254
|
+
requireAllowedValue(ctx.str("target_status"), TARGET_STATUSES, "target_status");
|
|
255
|
+
},
|
|
256
|
+
buildArgs: buildArgs6
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// src/commands/te-experiment/manage-feature-status.ts
|
|
260
|
+
var manageFeatureStatus = createExperimentCommand({
|
|
261
|
+
command: "+manage_feature_status",
|
|
262
|
+
description: "Update Feature status.",
|
|
263
|
+
flags: [
|
|
264
|
+
PROJECT_ID_FLAG,
|
|
265
|
+
reqFlag("Feature status request as JSON object")
|
|
266
|
+
],
|
|
267
|
+
risk: "write",
|
|
268
|
+
validate: (ctx) => {
|
|
269
|
+
readRequiredJsonObject(ctx, "req");
|
|
270
|
+
},
|
|
271
|
+
buildArgs: projectReqArgs
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// src/commands/te-experiment/query-bucket-list.ts
|
|
275
|
+
var queryBucketList = createExperimentCommand({
|
|
276
|
+
command: "+query_bucket_list",
|
|
277
|
+
description: "Query the split bucket list for a project.",
|
|
278
|
+
flags: [PROJECT_ID_FLAG],
|
|
279
|
+
risk: "read",
|
|
280
|
+
buildArgs: projectArgs
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// src/commands/te-experiment/query-experiment-detail.ts
|
|
284
|
+
function buildArgs7(ctx) {
|
|
285
|
+
return {
|
|
286
|
+
projectId: ctx.num("project_id"),
|
|
287
|
+
expId: ctx.str("exp_id")
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
var queryExperimentDetail = createExperimentCommand({
|
|
291
|
+
command: "+query_experiment_detail",
|
|
292
|
+
description: "Query full experiment detail.",
|
|
293
|
+
flags: [
|
|
294
|
+
PROJECT_ID_FLAG,
|
|
295
|
+
{ name: "exp_id", type: "string", required: true, desc: "Experiment ID" }
|
|
296
|
+
],
|
|
297
|
+
risk: "read",
|
|
298
|
+
buildArgs: buildArgs7
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// src/commands/te-experiment/query-experiment-list.ts
|
|
302
|
+
var queryExperimentList = createExperimentCommand({
|
|
303
|
+
command: "+query_experiment_list",
|
|
304
|
+
description: "Query the experiment list for a project.",
|
|
305
|
+
flags: [PROJECT_ID_FLAG],
|
|
306
|
+
risk: "read",
|
|
307
|
+
buildArgs: projectArgs
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// src/commands/te-experiment/query-experiment-metric-trend.ts
|
|
311
|
+
function buildArgs8(ctx) {
|
|
312
|
+
const args = {
|
|
313
|
+
projectId: ctx.num("project_id"),
|
|
314
|
+
expId: ctx.str("exp_id"),
|
|
315
|
+
metricId: ctx.str("metric_id"),
|
|
316
|
+
startTime: ctx.str("start_time"),
|
|
317
|
+
endTime: ctx.str("end_time")
|
|
318
|
+
};
|
|
319
|
+
addOptionalString(args, ctx, "request_id", "requestId");
|
|
320
|
+
addOptionalBoolean(args, ctx, "force_refresh", "forceRefresh");
|
|
321
|
+
return args;
|
|
322
|
+
}
|
|
323
|
+
var queryExperimentMetricTrend = createExperimentCommand({
|
|
324
|
+
command: "+query_experiment_metric_trend",
|
|
325
|
+
description: "Query an experiment metric trend report.",
|
|
326
|
+
flags: [
|
|
327
|
+
PROJECT_ID_FLAG,
|
|
328
|
+
{ name: "exp_id", type: "string", required: true, desc: "Experiment ID" },
|
|
329
|
+
{ name: "metric_id", type: "string", required: true, desc: "Metric ID" },
|
|
330
|
+
{ name: "start_time", type: "string", required: true, desc: "Start date, yyyy-MM-dd" },
|
|
331
|
+
{ name: "end_time", type: "string", required: true, desc: "End date, yyyy-MM-dd" },
|
|
332
|
+
{ name: "request_id", type: "string", required: false, desc: "Request ID for query tracking" },
|
|
333
|
+
{ name: "force_refresh", type: "boolean", required: false, desc: "Whether to force refresh report data" }
|
|
334
|
+
],
|
|
335
|
+
risk: "read",
|
|
336
|
+
buildArgs: buildArgs8
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// src/commands/te-experiment/query-experiment-report-summary.ts
|
|
340
|
+
function buildArgs9(ctx) {
|
|
341
|
+
const args = {
|
|
342
|
+
projectId: ctx.num("project_id"),
|
|
343
|
+
expId: ctx.str("exp_id")
|
|
344
|
+
};
|
|
345
|
+
addOptionalBoolean(args, ctx, "force_refresh", "forceRefresh");
|
|
346
|
+
return args;
|
|
347
|
+
}
|
|
348
|
+
var queryExperimentReportSummary = createExperimentCommand({
|
|
349
|
+
command: "+query_experiment_report_summary",
|
|
350
|
+
description: "Query an experiment report summary.",
|
|
351
|
+
flags: [
|
|
352
|
+
PROJECT_ID_FLAG,
|
|
353
|
+
{ name: "exp_id", type: "string", required: true, desc: "Experiment ID" },
|
|
354
|
+
{ name: "force_refresh", type: "boolean", required: false, desc: "Whether to force refresh report data" }
|
|
355
|
+
],
|
|
356
|
+
risk: "read",
|
|
357
|
+
buildArgs: buildArgs9
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// src/commands/te-experiment/query-experiment-sample-size-report.ts
|
|
361
|
+
function buildArgs10(ctx) {
|
|
362
|
+
const args = {
|
|
363
|
+
projectId: ctx.num("project_id"),
|
|
364
|
+
expId: ctx.str("exp_id"),
|
|
365
|
+
startTime: ctx.str("start_time"),
|
|
366
|
+
endTime: ctx.str("end_time")
|
|
367
|
+
};
|
|
368
|
+
addOptionalString(args, ctx, "request_id", "requestId");
|
|
369
|
+
addOptionalBoolean(args, ctx, "force_refresh", "forceRefresh");
|
|
370
|
+
addOptionalBoolean(args, ctx, "by_hour", "byHour");
|
|
371
|
+
return args;
|
|
372
|
+
}
|
|
373
|
+
var queryExperimentSampleSizeReport = createExperimentCommand({
|
|
374
|
+
command: "+query_experiment_sample_size_report",
|
|
375
|
+
description: "Query an experiment sample-size report.",
|
|
376
|
+
flags: [
|
|
377
|
+
PROJECT_ID_FLAG,
|
|
378
|
+
{ name: "exp_id", type: "string", required: true, desc: "Experiment ID" },
|
|
379
|
+
{ name: "start_time", type: "string", required: true, desc: "Start date, yyyy-MM-dd" },
|
|
380
|
+
{ name: "end_time", type: "string", required: true, desc: "End date, yyyy-MM-dd" },
|
|
381
|
+
{ name: "request_id", type: "string", required: false, desc: "Request ID for query tracking" },
|
|
382
|
+
{ name: "force_refresh", type: "boolean", required: false, desc: "Whether to force refresh report data" },
|
|
383
|
+
{ name: "by_hour", type: "boolean", required: false, desc: "Whether to show results by hour" }
|
|
384
|
+
],
|
|
385
|
+
risk: "read",
|
|
386
|
+
buildArgs: buildArgs10
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// src/commands/te-experiment/query-feature-detail.ts
|
|
390
|
+
function buildArgs11(ctx) {
|
|
391
|
+
const args = {
|
|
392
|
+
projectId: ctx.num("project_id"),
|
|
393
|
+
featureKey: ctx.str("feature_key")
|
|
394
|
+
};
|
|
395
|
+
addOptionalString(args, ctx, "version", "version");
|
|
396
|
+
return args;
|
|
397
|
+
}
|
|
398
|
+
var queryFeatureDetail = createExperimentCommand({
|
|
399
|
+
command: "+query_feature_detail",
|
|
400
|
+
description: "Query Feature detail by key and optional version.",
|
|
401
|
+
flags: [
|
|
402
|
+
PROJECT_ID_FLAG,
|
|
403
|
+
{ name: "feature_key", type: "string", required: true, desc: "Feature key" },
|
|
404
|
+
{ name: "version", type: "string", required: false, desc: "Feature version ID" }
|
|
405
|
+
],
|
|
406
|
+
risk: "read",
|
|
407
|
+
buildArgs: buildArgs11
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// src/commands/te-experiment/query-feature-list.ts
|
|
411
|
+
var queryFeatureList = createExperimentCommand({
|
|
412
|
+
command: "+query_feature_list",
|
|
413
|
+
description: "Query the Feature list for a project.",
|
|
414
|
+
flags: [PROJECT_ID_FLAG],
|
|
415
|
+
risk: "read",
|
|
416
|
+
buildArgs: projectArgs
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// src/commands/te-experiment/query-metric-detail.ts
|
|
420
|
+
function buildArgs12(ctx) {
|
|
421
|
+
return {
|
|
422
|
+
projectId: ctx.num("project_id"),
|
|
423
|
+
metricId: ctx.str("metric_id")
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
var queryMetricDetail = createExperimentCommand({
|
|
427
|
+
command: "+query_metric_detail",
|
|
428
|
+
description: "Query metric detail.",
|
|
429
|
+
flags: [
|
|
430
|
+
PROJECT_ID_FLAG,
|
|
431
|
+
{ name: "metric_id", type: "string", required: true, desc: "Metric ID" }
|
|
432
|
+
],
|
|
433
|
+
risk: "read",
|
|
434
|
+
buildArgs: buildArgs12
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// src/commands/te-experiment/query-metric-list.ts
|
|
438
|
+
var queryMetricList = createExperimentCommand({
|
|
439
|
+
command: "+query_metric_list",
|
|
440
|
+
description: "Query the metric list for a project.",
|
|
441
|
+
flags: [PROJECT_ID_FLAG],
|
|
442
|
+
risk: "read",
|
|
443
|
+
buildArgs: projectArgs
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// src/commands/te-experiment/query-traffic-layer-detail.ts
|
|
447
|
+
function buildArgs13(ctx) {
|
|
448
|
+
return {
|
|
449
|
+
projectId: ctx.num("project_id"),
|
|
450
|
+
layerId: ctx.str("layer_id")
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
var queryTrafficLayerDetail = createExperimentCommand({
|
|
454
|
+
command: "+query_traffic_layer_detail",
|
|
455
|
+
description: "Query traffic layer detail.",
|
|
456
|
+
flags: [
|
|
457
|
+
PROJECT_ID_FLAG,
|
|
458
|
+
{ name: "layer_id", type: "string", required: true, desc: "Traffic layer ID" }
|
|
459
|
+
],
|
|
460
|
+
risk: "read",
|
|
461
|
+
buildArgs: buildArgs13
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
// src/commands/te-experiment/query-traffic-layer-list.ts
|
|
465
|
+
var queryTrafficLayerList = createExperimentCommand({
|
|
466
|
+
command: "+query_traffic_layer_list",
|
|
467
|
+
description: "Query the traffic layer list for a project.",
|
|
468
|
+
flags: [PROJECT_ID_FLAG],
|
|
469
|
+
risk: "read",
|
|
470
|
+
buildArgs: projectArgs
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// src/commands/te-experiment/save-experiment.ts
|
|
474
|
+
var saveExperiment = createExperimentCommand({
|
|
475
|
+
command: "+save_experiment",
|
|
476
|
+
description: "Create or update an experiment draft.",
|
|
477
|
+
flags: [
|
|
478
|
+
PROJECT_ID_FLAG,
|
|
479
|
+
reqFlag("Experiment save request as JSON object")
|
|
480
|
+
],
|
|
481
|
+
risk: "write",
|
|
482
|
+
validate: (ctx) => {
|
|
483
|
+
readRequiredJsonObject(ctx, "req");
|
|
484
|
+
},
|
|
485
|
+
buildArgs: projectReqArgs
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// src/commands/te-experiment/save-feature.ts
|
|
489
|
+
var saveFeature = createExperimentCommand({
|
|
490
|
+
command: "+save_feature",
|
|
491
|
+
description: "Create or update a Feature.",
|
|
492
|
+
flags: [
|
|
493
|
+
PROJECT_ID_FLAG,
|
|
494
|
+
reqFlag("Feature save request as JSON object")
|
|
495
|
+
],
|
|
496
|
+
risk: "write",
|
|
497
|
+
validate: (ctx) => {
|
|
498
|
+
readRequiredJsonObject(ctx, "req");
|
|
499
|
+
},
|
|
500
|
+
buildArgs: projectReqArgs
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
// src/commands/te-experiment/save-metric.ts
|
|
504
|
+
var saveMetric = createExperimentCommand({
|
|
505
|
+
command: "+save_metric",
|
|
506
|
+
description: "Create or update a metric.",
|
|
507
|
+
flags: [
|
|
508
|
+
PROJECT_ID_FLAG,
|
|
509
|
+
reqFlag("Metric save request as JSON object")
|
|
510
|
+
],
|
|
511
|
+
risk: "write",
|
|
512
|
+
validate: (ctx) => {
|
|
513
|
+
readRequiredJsonObject(ctx, "req");
|
|
514
|
+
},
|
|
515
|
+
buildArgs: projectReqArgs
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
// src/commands/te-experiment/save-submit-experiment.ts
|
|
519
|
+
var saveSubmitExperiment = createExperimentCommand({
|
|
520
|
+
command: "+save_submit_experiment",
|
|
521
|
+
description: "Create or update a complete experiment and submit it.",
|
|
522
|
+
flags: [
|
|
523
|
+
PROJECT_ID_FLAG,
|
|
524
|
+
reqFlag("Experiment save-and-submit request as JSON object")
|
|
525
|
+
],
|
|
526
|
+
risk: "write",
|
|
527
|
+
validate: (ctx) => {
|
|
528
|
+
readRequiredJsonObject(ctx, "req");
|
|
529
|
+
},
|
|
530
|
+
buildArgs: projectReqArgs
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
// src/commands/te-experiment/save-traffic-layer.ts
|
|
534
|
+
var saveTrafficLayer = createExperimentCommand({
|
|
535
|
+
command: "+save_traffic_layer",
|
|
536
|
+
description: "Create or update a traffic layer.",
|
|
537
|
+
flags: [
|
|
538
|
+
PROJECT_ID_FLAG,
|
|
539
|
+
reqFlag("Traffic layer save request as JSON object")
|
|
540
|
+
],
|
|
541
|
+
risk: "write",
|
|
542
|
+
validate: (ctx) => {
|
|
543
|
+
readRequiredJsonObject(ctx, "req");
|
|
544
|
+
},
|
|
545
|
+
buildArgs: projectReqArgs
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// src/commands/te-experiment/index.ts
|
|
549
|
+
registerMcpMappings({
|
|
550
|
+
"experiment": { componentName: "engage", mappingPath: "experiment" }
|
|
551
|
+
});
|
|
552
|
+
var commands = [
|
|
553
|
+
saveExperiment,
|
|
554
|
+
saveSubmitExperiment,
|
|
555
|
+
queryExperimentList,
|
|
556
|
+
queryExperimentDetail,
|
|
557
|
+
checkExperimentReady,
|
|
558
|
+
manageExperiment,
|
|
559
|
+
batchDeleteExperiment,
|
|
560
|
+
saveTrafficLayer,
|
|
561
|
+
queryTrafficLayerDetail,
|
|
562
|
+
queryTrafficLayerList,
|
|
563
|
+
batchDeleteTrafficLayer,
|
|
564
|
+
queryExperimentReportSummary,
|
|
565
|
+
queryExperimentSampleSizeReport,
|
|
566
|
+
queryExperimentMetricTrend,
|
|
567
|
+
cancelExperimentQueryByRequestId,
|
|
568
|
+
saveMetric,
|
|
569
|
+
queryMetricDetail,
|
|
570
|
+
queryMetricList,
|
|
571
|
+
deleteMetric,
|
|
572
|
+
saveFeature,
|
|
573
|
+
manageFeatureStatus,
|
|
574
|
+
queryFeatureDetail,
|
|
575
|
+
queryFeatureList,
|
|
576
|
+
batchDeleteFeature,
|
|
577
|
+
queryBucketList
|
|
578
|
+
];
|
|
579
|
+
var te_experiment_default = commands;
|
|
580
|
+
export {
|
|
581
|
+
batchDeleteExperiment,
|
|
582
|
+
batchDeleteFeature,
|
|
583
|
+
batchDeleteTrafficLayer,
|
|
584
|
+
cancelExperimentQueryByRequestId,
|
|
585
|
+
checkExperimentReady,
|
|
586
|
+
te_experiment_default as default,
|
|
587
|
+
deleteMetric,
|
|
588
|
+
manageExperiment,
|
|
589
|
+
manageFeatureStatus,
|
|
590
|
+
queryBucketList,
|
|
591
|
+
queryExperimentDetail,
|
|
592
|
+
queryExperimentList,
|
|
593
|
+
queryExperimentMetricTrend,
|
|
594
|
+
queryExperimentReportSummary,
|
|
595
|
+
queryExperimentSampleSizeReport,
|
|
596
|
+
queryFeatureDetail,
|
|
597
|
+
queryFeatureList,
|
|
598
|
+
queryMetricDetail,
|
|
599
|
+
queryMetricList,
|
|
600
|
+
queryTrafficLayerDetail,
|
|
601
|
+
queryTrafficLayerList,
|
|
602
|
+
saveExperiment,
|
|
603
|
+
saveFeature,
|
|
604
|
+
saveMetric,
|
|
605
|
+
saveSubmitExperiment,
|
|
606
|
+
saveTrafficLayer
|
|
607
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thinkingai/ae-cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.5",
|
|
4
4
|
"description": "CLI tool for ThinkingAI (AE) analytics platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"verify:retired-analysis-commands": "node --test test/retired-analysis-commands.test.mjs",
|
|
38
38
|
"verify:analysis-meta-tools": "node scripts/verify-te-meta-tools.mjs",
|
|
39
39
|
"verify:analysis-common-tools": "node scripts/verify-te-common-tools.mjs",
|
|
40
|
+
"verify:experiment-tools": "node scripts/verify-te-experiment-tools.mjs",
|
|
40
41
|
"verify:team-tools": "node scripts/verify-te-team-tools.mjs",
|
|
41
42
|
"verify:agent-tools": "node scripts/verify-agent-tools.mjs",
|
|
42
43
|
"verify:tracking-tools": "tsx test/tracking-client.test.mjs && node test/tracking-skill-flow.test.mjs && node test/tracking-commands.test.mjs",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ae-experiment
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "Use when managing Atlas AB experiments, traffic layers, Features, metrics, buckets, and experiment reports through ae-cli"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ae-experiment
|
|
8
|
+
|
|
9
|
+
AE CLI (`ae-cli`) exposes Atlas AB Experiment MCP capabilities through the `experiment` domain.
|
|
10
|
+
|
|
11
|
+
## Global Rules
|
|
12
|
+
|
|
13
|
+
- Prefer `ae-cli experiment <command>` for Atlas AB Experiment work.
|
|
14
|
+
- Use `--project_id` / `-p` for project-scoped commands.
|
|
15
|
+
- Use `--req` JSON for complex save, status, and delete DTOs.
|
|
16
|
+
- Do not invent experiment IDs, traffic layer IDs, bucket IDs, Feature keys, metric IDs, or payload field names.
|
|
17
|
+
- Read commands can run directly after IDs are verified.
|
|
18
|
+
- Write commands require explicit user intent and normally keep the confirmation prompt. Use `--dry-run` before write calls when composing JSON.
|
|
19
|
+
|
|
20
|
+
## Typical Workflow
|
|
21
|
+
|
|
22
|
+
1. Discover reusable assets:
|
|
23
|
+
- `+query_bucket_list`
|
|
24
|
+
- `+query_traffic_layer_list`
|
|
25
|
+
- `+query_feature_list`
|
|
26
|
+
- `+query_metric_list`
|
|
27
|
+
2. Create missing assets if needed:
|
|
28
|
+
- `+save_traffic_layer`
|
|
29
|
+
- `+save_feature`
|
|
30
|
+
- `+save_metric`
|
|
31
|
+
3. Create or patch the experiment draft with `+save_experiment`.
|
|
32
|
+
4. Check readiness with `+check_experiment_ready`.
|
|
33
|
+
5. Move status with `+manage_experiment`.
|
|
34
|
+
6. Query reports with summary, sample-size, and metric-trend commands.
|
|
35
|
+
|
|
36
|
+
## Parameter Conventions
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
ae-cli experiment +query_experiment_detail --project_id 1 --exp_id exp_123
|
|
40
|
+
ae-cli --dry-run experiment +save_experiment --project_id 1 --req '{"expName":"Demo"}'
|
|
41
|
+
ae-cli experiment +query_experiment_metric_trend --project_id 1 --exp_id exp_123 --metric_id metric_1 --start_time 2026-07-01 --end_time 2026-07-07
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Optional global parameters work as in other domains: `--host`, `--mcp-url`, `--format`, `--jq`, `--dry-run`, and `--yes`.
|
|
45
|
+
|
|
46
|
+
## References
|
|
47
|
+
|
|
48
|
+
Open the matching file in `references/` before using a command, especially for write operations and JSON payloads.
|
|
49
|
+
|
|
50
|
+
### Experiment
|
|
51
|
+
|
|
52
|
+
`+save_experiment`, `+save_submit_experiment`, `+query_experiment_list`, `+query_experiment_detail`, `+check_experiment_ready`, `+manage_experiment`, `+batch_delete_experiment`
|
|
53
|
+
|
|
54
|
+
### Traffic Layer and Buckets
|
|
55
|
+
|
|
56
|
+
`+save_traffic_layer`, `+query_traffic_layer_detail`, `+query_traffic_layer_list`, `+batch_delete_traffic_layer`, `+query_bucket_list`
|
|
57
|
+
|
|
58
|
+
### Reports
|
|
59
|
+
|
|
60
|
+
`+query_experiment_report_summary`, `+query_experiment_sample_size_report`, `+query_experiment_metric_trend`, `+cancel_experiment_query_by_request_id`
|
|
61
|
+
|
|
62
|
+
### Metric and Feature
|
|
63
|
+
|
|
64
|
+
`+save_metric`, `+query_metric_detail`, `+query_metric_list`, `+delete_metric`, `+save_feature`, `+manage_feature_status`, `+query_feature_detail`, `+query_feature_list`, `+batch_delete_feature`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# +batch_delete_experiment
|
|
2
|
+
|
|
3
|
+
Batch delete experiments.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
ae-cli experiment +batch_delete_experiment --project_id <id> --exp_ids '["exp_1","exp_2"]' [--yes]
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Flags:
|
|
10
|
+
- `--project_id`, `-p`: Project ID.
|
|
11
|
+
- `--exp_ids`: Experiment ID list as JSON array.
|