@thinkingai/ae-cli 6.1.17 → 6.1.19
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 +2 -0
- package/README.zh.md +6 -0
- package/dist/{auth-77BUFLGC.js → auth-QPEVVBKT.js} +20 -15
- package/dist/auth-UMJAA72O.js +15 -0
- package/dist/{capability-72DTW5M2.js → capability-ASI62I4A.js} +53 -15
- package/dist/{chunk-UW5UN47B.js → chunk-533JK3YX.js} +2 -0
- package/dist/{chunk-UOUS37JQ.js → chunk-6QK7SYYY.js} +5 -4
- package/dist/{chunk-TUKQZTMI.js → chunk-7K24F7T2.js} +2 -0
- package/dist/{chunk-OO6XR6LK.js → chunk-AMBFK2K3.js} +2 -0
- package/dist/{sync-DAVKYVMW.js → chunk-B5HMQAOM.js} +31 -540
- package/dist/{chunk-VR3LCBHW.js → chunk-DKEXH6Q5.js} +6 -5
- package/dist/{chunk-VTWMIC5L.js → chunk-E2JKXMVO.js} +2 -0
- package/dist/{chunk-LYVNONC4.js → chunk-FR2EDAQM.js} +36 -0
- package/dist/{chunk-ILIU36SU.js → chunk-GJXRF7Y6.js} +6 -5
- package/dist/{chunk-DWO43OIB.js → chunk-JQ3ENZZH.js} +2 -0
- package/dist/chunk-JYMGHGCE.js +191 -0
- package/dist/{chunk-GT46FPXN.js → chunk-KEWVSO64.js} +18 -8
- package/dist/chunk-KZ6ZHF5J.js +294 -0
- package/dist/chunk-O6K2ODUE.js +318 -0
- package/dist/chunk-QL6R6TSK.js +25215 -0
- package/dist/{chunk-4SGZG4XY.js → chunk-RWXIXOZG.js} +28 -13
- package/dist/{chunk-YA6SMTXG.js → chunk-S5PONFBM.js} +5 -4
- package/dist/{chunk-4NN5IWVN.js → chunk-T6OSFQZD.js} +2 -0
- package/dist/{chunk-PTE56QPL.js → chunk-TKHSULJT.js} +6 -0
- package/dist/{chunk-6EIJSNBD.js → chunk-Y74WTIKJ.js} +2 -0
- package/dist/{client-TKG4WBHN.js → client-N7NGZUNI.js} +6 -4
- package/dist/{community-report-client-FI4LNVYS.js → community-report-client-6OL6GBQW.js} +3 -3
- package/dist/{config-RE6CMGPK.js → config-XNMACCKX.js} +10 -8
- package/dist/{data-integration-XQYB4X4F.js → data-integration-4NZGZ45E.js} +2502 -272
- package/dist/index.js +137 -1245
- package/dist/{local-data-upload-client-BWHSUQQK.js → local-data-upload-client-EFHDLXFG.js} +3 -3
- package/dist/{memory-YK33G4T7.js → memory-HBJQ2GC5.js} +8 -7
- package/dist/{metadata-UILXHBWF.js → metadata-62EWBEIG.js} +12 -11
- package/dist/{model-NR3JHFSJ.js → model-BHLJ2QMT.js} +10 -9
- package/dist/personal-semantic-preference-JBVMAI7L.js +240 -0
- package/dist/project-semantic-BQ4MPUS5.js +1115 -0
- package/dist/sync-MUWPRM5I.js +522 -0
- package/dist/{te-agent-4BKBODMF.js → te-agent-WQZTMEK4.js} +12 -10
- package/dist/{te-analysis-O6DCO6BS.js → te-analysis-MNCG65LU.js} +534 -48
- package/dist/{te-community-HLC43QKH.js → te-community-BNE6KREL.js} +8 -7
- package/dist/{te-dataops-EJP56W3K.js → te-dataops-TXLKM2W6.js} +469 -68
- package/dist/{te-engage-FGBGQ4IY.js → te-engage-TPKLRVTL.js} +84 -10
- package/dist/{te-experiment-SO5MPDMJ.js → te-experiment-6BYKTCY7.js} +303 -12
- package/dist/{te-kb-SQCLHG6X.js → te-kb-BUD6N3NI.js} +312 -25
- package/dist/{te-system-YARIK4S5.js → te-system-44LZJDTQ.js} +573 -37
- package/dist/{te-team-EFKWYKMK.js → te-team-XMP47YXE.js} +10 -7
- package/dist/{update-OGPSZM5A.js → update-UODFOZ4P.js} +9 -7
- package/package.json +18 -9
- package/skills/ae-agent/SKILL.md +3 -4
- package/skills/ae-agent/references/edit-skill.md +3 -0
- package/skills/ae-agent/references/get-skill-content.md +1 -1
- package/skills/ae-agent/references/rescan-skills.md +15 -13
- package/skills/ae-agent/references/upload-skill.md +7 -4
- package/skills/ae-analysis/SKILL.md +45 -4
- package/skills/ae-analysis/metadata_resolution.md +38 -4
- package/skills/ae-analysis/references/analysis_data_retrieval.md +29 -0
- package/skills/ae-analysis/references/analysis_gateway_assets.md +1 -1
- package/skills/ae-analysis/references/asset_authentication_export.md +22 -0
- package/skills/ae-analysis/references/asset_authentication_list.md +18 -14
- package/skills/ae-analysis/references/asset_authentication_update.md +29 -14
- package/skills/ae-analysis/references/audience_models.md +18 -0
- package/skills/ae-analysis/references/command_index.md +19 -11
- package/skills/ae-analysis/references/dashboard_get.md +18 -1
- package/skills/ae-analysis/references/dashboard_update.md +3 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +23 -0
- package/skills/ae-analysis/references/personal_semantic_preference_delete.md +17 -0
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +19 -0
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +21 -0
- package/skills/ae-analysis/references/personal_semantic_preference_update.md +19 -0
- package/skills/ae-analysis/references/project_timezone_update.md +13 -4
- package/skills/ae-analysis/references/property_create.md +2 -0
- package/skills/ae-analysis/references/super_metadata_batch_create.md +2 -0
- package/skills/ae-analysis/references/user_cluster_models.md +2 -0
- package/skills/ae-analysis/references/user_cluster_update.md +8 -4
- package/skills/ae-analysis/references/user_tag_create.md +7 -1
- package/skills/ae-analysis/references/user_tag_models.md +8 -2
- package/skills/ae-data-integration/SKILL.md +24 -4
- package/skills/ae-data-integration/references/custom-layer.md +93 -0
- package/skills/ae-data-integration/references/error-handling.md +145 -0
- package/skills/ae-data-integration/references/handoff.md +77 -18
- package/skills/ae-data-integration/references/local-analysis.md +1 -1
- package/skills/ae-data-integration/references/reuse.md +9 -5
- package/skills/ae-data-integration/references/sink-upload.md +1 -1
- package/skills/ae-data-integration/references/source-inspect.md +35 -13
- package/skills/ae-data-integration/references/tracking-plan.md +7 -5
- package/skills/ae-data-integration/references/transform.md +12 -10
- package/skills/ae-data-integration/references/ue-mapping.md +33 -11
- package/skills/ae-data-integration/references/ue-routing.md +23 -0
- package/skills/ae-dataops/SKILL.md +11 -1
- package/skills/ae-dataops/references/dataops-backfill.md +135 -0
- package/skills/ae-engage/SKILL.md +5 -0
- package/skills/ae-engage/references/build-task-save-guide.md +14 -1
- package/skills/ae-engage/references/save-flow.md +37 -1
- package/skills/ae-engage/references/save-task.md +88 -0
- package/skills/ae-experiment/SKILL.md +14 -4
- package/skills/ae-experiment/references/manage_feature_whitelist.md +66 -0
- package/skills/ae-experiment/references/manage_guardrail_metrics.md +26 -0
- package/skills/ae-experiment/references/save_experiment.md +1 -1
- package/skills/ae-experiment/references/save_metric.md +20 -8
- package/skills/ae-kb/SKILL.md +121 -10
- package/skills/ae-project-semantic/SKILL.md +193 -0
- package/skills/ae-project-semantic/references/query-routing-v5.md +165 -0
- package/skills/ae-project-semantic/references/recommendation-quality.md +68 -0
- package/skills/ae-system/SKILL.md +28 -30
- package/skills/ae-system/references/channel-management.md +303 -0
- package/dist/auth-2WTQOP77.js +0 -14
- package/dist/capability-PJHNI4GJ.js +0 -315
- package/dist/chunk-4KVPKXFX.js +0 -98
- package/dist/chunk-C4MGVGJW.js +0 -13
- package/dist/chunk-P3FGXJTU.js +0 -349
- package/dist/chunk-QGM4M3NI.js +0 -37
- package/dist/chunk-RGKJGKT7.js +0 -71
- package/dist/chunk-SAU3QFIQ.js +0 -556
- package/dist/chunk-VPKZ7I72.js +0 -509
- package/dist/chunk-ZZUOD757.js +0 -598
- package/dist/memory-CHRU2F7W.js +0 -893
- package/dist/metadata-XXR34N5P.js +0 -339
- package/dist/model-K3KLWIW6.js +0 -139
- package/dist/sync-FCKOVWWS.js +0 -10261
- package/dist/te-agent-HLW4VTQK.js +0 -3893
- package/dist/te-analysis-ZMNGOVNW.js +0 -8958
- package/dist/te-community-6HPBWJUZ.js +0 -1859
- package/dist/te-dataops-HDRUXY4K.js +0 -2208
- package/dist/te-engage-RAK5PESW.js +0 -4898
- package/dist/te-experiment-VZF7BT6G.js +0 -770
- package/dist/te-system-Z77IKZFN.js +0 -2213
|
@@ -1,29 +1,30 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
1
2
|
import {
|
|
2
3
|
createCapabilityCommand
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DKEXH6Q5.js";
|
|
4
5
|
import {
|
|
5
6
|
registerCapabilityGatewayRoute,
|
|
6
7
|
resolveGatewayDomain
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TKHSULJT.js";
|
|
8
9
|
import {
|
|
9
10
|
printError,
|
|
10
11
|
withOutputMetadata
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KEWVSO64.js";
|
|
12
13
|
import {
|
|
13
14
|
CapabilityGatewayError,
|
|
14
15
|
buildCapabilityGatewayUrl,
|
|
15
16
|
fetchCapabilityGateway,
|
|
16
17
|
requestCapabilityGateway,
|
|
17
18
|
requestCapabilityGatewayWithEnvelope
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-GJXRF7Y6.js";
|
|
20
|
+
import "./chunk-Y74WTIKJ.js";
|
|
21
|
+
import "./chunk-RWXIXOZG.js";
|
|
22
|
+
import "./chunk-O6K2ODUE.js";
|
|
23
|
+
import "./chunk-KZ6ZHF5J.js";
|
|
22
24
|
import {
|
|
23
25
|
CliValidationError
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-QGM4M3NI.js";
|
|
26
|
+
} from "./chunk-533JK3YX.js";
|
|
27
|
+
import "./chunk-FR2EDAQM.js";
|
|
27
28
|
|
|
28
29
|
// src/commands/te-engage/shared.ts
|
|
29
30
|
function createEngageCapabilityCommand(cliService, config) {
|
|
@@ -323,6 +324,9 @@ function validateSemanticMetricDefinition(value, path) {
|
|
|
323
324
|
function validateEmbeddedSemanticDefinitions(value, path) {
|
|
324
325
|
walk(value, path);
|
|
325
326
|
}
|
|
327
|
+
function validateFlowAbIndicatorDefinitions(value, path) {
|
|
328
|
+
walkFlowAbIndicators(value, path);
|
|
329
|
+
}
|
|
326
330
|
function validateTaskTriggerPeriodDefinition(value, path) {
|
|
327
331
|
const request = object(value, path);
|
|
328
332
|
if (!isObject(request.triggerConfig)) return;
|
|
@@ -335,6 +339,20 @@ function validateTaskTriggerPeriodDefinition(value, path) {
|
|
|
335
339
|
required(primaryRule.periodTimeSymbol, symbolPath);
|
|
336
340
|
enumValue(primaryRule.periodTimeSymbol, TASK_TRIGGER_PERIOD_SYMBOLS, symbolPath);
|
|
337
341
|
}
|
|
342
|
+
function validateTaskAudienceChannelCompatibility(value, path) {
|
|
343
|
+
const request = object(value, path);
|
|
344
|
+
if (!isObject(request.channelConfig) || !isObject(request.targetConfig)) return;
|
|
345
|
+
const channelType = request.channelConfig.channelType;
|
|
346
|
+
const targetClusterType = request.targetConfig.targetClusterType;
|
|
347
|
+
if (typeof channelType !== "number" || typeof targetClusterType !== "number") return;
|
|
348
|
+
const clientSide = channelType === 3;
|
|
349
|
+
if (clientSide && targetClusterType === 2) {
|
|
350
|
+
invalid(`${path}.targetConfig.targetClusterType=2 (existing cluster) is not supported for client-side delivery; use 1 or 3.`);
|
|
351
|
+
}
|
|
352
|
+
if (!clientSide && targetClusterType === 3) {
|
|
353
|
+
invalid(`${path}.targetConfig.targetClusterType=3 (all users) is not supported for server-side delivery; use 1 or 2.`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
338
356
|
function walk(value, path) {
|
|
339
357
|
if (Array.isArray(value)) {
|
|
340
358
|
value.forEach((item, index) => walk(item, `${path}[${index}]`));
|
|
@@ -357,6 +375,60 @@ function walk(value, path) {
|
|
|
357
375
|
}
|
|
358
376
|
}
|
|
359
377
|
}
|
|
378
|
+
function walkFlowAbIndicators(value, path) {
|
|
379
|
+
if (Array.isArray(value)) {
|
|
380
|
+
value.forEach((item, index) => walkFlowAbIndicators(item, `${path}[${index}]`));
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (!isObject(value)) return;
|
|
384
|
+
if (value.indicatorsDef !== void 0 && value.indicatorsDef !== null) {
|
|
385
|
+
array(value.indicatorsDef, `${path}.indicatorsDef`).forEach((item, index) => {
|
|
386
|
+
const indicatorPath = `${path}.indicatorsDef[${index}]`;
|
|
387
|
+
const indicator = object(item, indicatorPath);
|
|
388
|
+
const hasDefinition = indicator.eventDefinition !== void 0 && indicator.eventDefinition !== null;
|
|
389
|
+
const hasLegacyEvent = indicator.event !== void 0 && indicator.event !== null;
|
|
390
|
+
if (hasDefinition && hasLegacyEvent) {
|
|
391
|
+
invalid(`${indicatorPath} cannot contain both event and eventDefinition.`);
|
|
392
|
+
}
|
|
393
|
+
if (!hasDefinition && !hasLegacyEvent) {
|
|
394
|
+
invalid(`${indicatorPath} must contain eventDefinition or legacy event.`);
|
|
395
|
+
}
|
|
396
|
+
if (hasDefinition) validateFlowAbIndicatorEvent(indicator.eventDefinition, `${indicatorPath}.eventDefinition`);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
for (const [key, item] of Object.entries(value)) {
|
|
400
|
+
const itemPath = `${path}.${key}`;
|
|
401
|
+
if (key === "config" && typeof item === "string") {
|
|
402
|
+
try {
|
|
403
|
+
walkFlowAbIndicators(JSON.parse(item), itemPath);
|
|
404
|
+
} catch (error) {
|
|
405
|
+
if (error instanceof SyntaxError) invalid(`${itemPath} must contain valid JSON.`);
|
|
406
|
+
throw error;
|
|
407
|
+
}
|
|
408
|
+
} else {
|
|
409
|
+
walkFlowAbIndicators(item, itemPath);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
function validateFlowAbIndicatorEvent(value, path) {
|
|
414
|
+
validateSemanticEventDefinition(value, path);
|
|
415
|
+
const event = object(value, path);
|
|
416
|
+
enumValue(event.aggregation, AUDIENCE_AGGREGATIONS, `${path}.aggregation`);
|
|
417
|
+
enumValue(event.operator, /* @__PURE__ */ new Set(["eq", "neq", "lt", "lte", "gt", "gte"]), `${path}.operator`);
|
|
418
|
+
required(event.value, `${path}.value`);
|
|
419
|
+
optionalNumber(event.value, `${path}.value`);
|
|
420
|
+
if (["sum", "avg", "max", "min", "distinct_count"].includes(String(event.aggregation))) {
|
|
421
|
+
nonBlankString(event.property, `${path}.property`);
|
|
422
|
+
}
|
|
423
|
+
if (isObject(event.filters)) {
|
|
424
|
+
array(event.filters.items, `${path}.filters.items`, 1).forEach((filterValue, index) => {
|
|
425
|
+
const filter = object(filterValue, `${path}.filters.items[${index}]`);
|
|
426
|
+
if (!["exists", "not_exists", "is_true", "is_false"].includes(String(filter.operator))) {
|
|
427
|
+
array(filter.values, `${path}.filters.items[${index}].values`, 1);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
360
432
|
function validateTriggerDefinition(value, path) {
|
|
361
433
|
const definition = object(value, path);
|
|
362
434
|
rejectUnknown(definition, ["rules"], path);
|
|
@@ -608,6 +680,7 @@ function readRequest(ctx) {
|
|
|
608
680
|
throw new Error("Flag --req.sourceFlowUuid is unsupported; get the source flow and build nodes/edges instead");
|
|
609
681
|
}
|
|
610
682
|
validateEmbeddedSemanticDefinitions(req, "--req");
|
|
683
|
+
validateFlowAbIndicatorDefinitions(req, "--req");
|
|
611
684
|
return req;
|
|
612
685
|
}
|
|
613
686
|
var flowSave = createEngageFlowCapabilityCommand({
|
|
@@ -4609,6 +4682,7 @@ var taskSave = createEngageTaskCapabilityCommand({
|
|
|
4609
4682
|
validate: (ctx) => {
|
|
4610
4683
|
const req = readRequiredJsonObject(ctx, "req");
|
|
4611
4684
|
validateEmbeddedSemanticDefinitions(req, "--req");
|
|
4685
|
+
validateTaskAudienceChannelCompatibility(req, "--req");
|
|
4612
4686
|
validateTaskTriggerPeriodDefinition(req, "--req");
|
|
4613
4687
|
},
|
|
4614
4688
|
buildInput: (ctx) => ({ project_id: ctx.num("project-id"), req: readRequiredJsonObject(ctx, "req") })
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
1
2
|
import {
|
|
2
3
|
createCapabilityCommand
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DKEXH6Q5.js";
|
|
4
5
|
import {
|
|
5
6
|
registerCapabilityGatewayRoute
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-TKHSULJT.js";
|
|
8
|
+
import "./chunk-KEWVSO64.js";
|
|
9
|
+
import "./chunk-GJXRF7Y6.js";
|
|
10
|
+
import "./chunk-Y74WTIKJ.js";
|
|
11
|
+
import "./chunk-RWXIXOZG.js";
|
|
12
|
+
import "./chunk-O6K2ODUE.js";
|
|
13
|
+
import "./chunk-KZ6ZHF5J.js";
|
|
14
|
+
import "./chunk-533JK3YX.js";
|
|
15
|
+
import "./chunk-FR2EDAQM.js";
|
|
15
16
|
|
|
16
17
|
// src/commands/te-experiment/capability-shared.ts
|
|
17
18
|
function createExperimentCapabilityCommand(config) {
|
|
@@ -283,6 +284,54 @@ var experimentUpdateGroup = createExperimentCapabilityCommand({
|
|
|
283
284
|
})
|
|
284
285
|
});
|
|
285
286
|
|
|
287
|
+
// src/commands/te-experiment/experiment/update-metrics.ts
|
|
288
|
+
var METRIC_ROLES = /* @__PURE__ */ new Set(["primary", "secondary", "guardrail"]);
|
|
289
|
+
function readMetricBindings(ctx) {
|
|
290
|
+
const value = ctx.json("metrics");
|
|
291
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
292
|
+
throw new Error("Flag --metrics must be a non-empty JSON array");
|
|
293
|
+
}
|
|
294
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
295
|
+
const item = value[index];
|
|
296
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
297
|
+
throw new Error(`Flag --metrics[${index}] must be a JSON object`);
|
|
298
|
+
}
|
|
299
|
+
const metricId = item.metricId;
|
|
300
|
+
const metricRole = item.metricRole;
|
|
301
|
+
if (typeof metricId !== "string" || metricId.trim() === "") {
|
|
302
|
+
throw new Error(`Flag --metrics[${index}].metricId must be a non-empty string`);
|
|
303
|
+
}
|
|
304
|
+
if (typeof metricRole !== "string" || !METRIC_ROLES.has(metricRole)) {
|
|
305
|
+
throw new Error(`Flag --metrics[${index}].metricRole must be one of primary, secondary, guardrail`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return value;
|
|
309
|
+
}
|
|
310
|
+
var experimentUpdateMetrics = createExperimentCapabilityCommand({
|
|
311
|
+
resource: "experiment",
|
|
312
|
+
command: "update-metrics",
|
|
313
|
+
capabilityId: "experiment.experiment.save",
|
|
314
|
+
description: "Replace experiment metric bindings and assign primary, secondary, or guardrail roles.",
|
|
315
|
+
flags: [
|
|
316
|
+
{ name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
|
|
317
|
+
{ name: "exp-id", type: "string", required: true, desc: "Experiment draft ID." },
|
|
318
|
+
{
|
|
319
|
+
name: "metrics",
|
|
320
|
+
type: "json",
|
|
321
|
+
required: true,
|
|
322
|
+
desc: "Non-empty metric binding array with camelCase metricId and metricRole fields; replaces all saved bindings."
|
|
323
|
+
}
|
|
324
|
+
],
|
|
325
|
+
risk: "write",
|
|
326
|
+
validate: (ctx) => {
|
|
327
|
+
readMetricBindings(ctx);
|
|
328
|
+
},
|
|
329
|
+
buildInput: (ctx) => ({
|
|
330
|
+
project_id: ctx.num("project-id"),
|
|
331
|
+
req: { expId: ctx.str("exp-id"), metrics: readMetricBindings(ctx) }
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
|
|
286
335
|
// src/commands/te-experiment/feature/batch-delete.ts
|
|
287
336
|
var featureBatchDelete = createExperimentCapabilityCommand({
|
|
288
337
|
resource: "feature",
|
|
@@ -402,6 +451,166 @@ var featureOperationLogQuery = createExperimentCapabilityCommand({
|
|
|
402
451
|
})
|
|
403
452
|
});
|
|
404
453
|
|
|
454
|
+
// src/commands/te-experiment/feature-whitelist/shared.ts
|
|
455
|
+
function readRuleIds(ctx) {
|
|
456
|
+
const value = ctx.json("rule-ids");
|
|
457
|
+
if (!Array.isArray(value) || value.length === 0 || !value.every((item) => typeof item === "string" && item.trim() !== "")) {
|
|
458
|
+
throw new Error("Flag --rule-ids must be a non-empty JSON array of strings");
|
|
459
|
+
}
|
|
460
|
+
return value;
|
|
461
|
+
}
|
|
462
|
+
function readWhitelist(ctx) {
|
|
463
|
+
const value = ctx.json("whitelist");
|
|
464
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
465
|
+
throw new Error("Flag --whitelist must be a non-empty JSON array");
|
|
466
|
+
}
|
|
467
|
+
const bucketIds = /* @__PURE__ */ new Set();
|
|
468
|
+
value.forEach((bucket, bucketIndex) => {
|
|
469
|
+
if (!bucket || typeof bucket !== "object" || Array.isArray(bucket)) {
|
|
470
|
+
throw new Error(`Flag --whitelist[${bucketIndex}] must be a JSON object`);
|
|
471
|
+
}
|
|
472
|
+
const item = bucket;
|
|
473
|
+
if (typeof item.bucket_id !== "string" || item.bucket_id.trim() === "") {
|
|
474
|
+
throw new Error(`Flag --whitelist[${bucketIndex}].bucket_id must be a non-empty string`);
|
|
475
|
+
}
|
|
476
|
+
if (bucketIds.has(item.bucket_id)) {
|
|
477
|
+
throw new Error(`Flag --whitelist contains duplicate bucket_id: ${item.bucket_id}`);
|
|
478
|
+
}
|
|
479
|
+
bucketIds.add(item.bucket_id);
|
|
480
|
+
if (!Array.isArray(item.rules) || item.rules.length === 0) {
|
|
481
|
+
throw new Error(`Flag --whitelist[${bucketIndex}].rules must be a non-empty array`);
|
|
482
|
+
}
|
|
483
|
+
const bucketValueIds = /* @__PURE__ */ new Set();
|
|
484
|
+
item.rules.forEach((rule, ruleIndex) => {
|
|
485
|
+
if (!rule || typeof rule !== "object" || Array.isArray(rule)) {
|
|
486
|
+
throw new Error(`Flag --whitelist[${bucketIndex}].rules[${ruleIndex}] must be a JSON object`);
|
|
487
|
+
}
|
|
488
|
+
const row = rule;
|
|
489
|
+
if (!Array.isArray(row.ids) || row.ids.length === 0 || !row.ids.every((id) => typeof id === "string" && id.trim() !== "")) {
|
|
490
|
+
throw new Error(`Flag --whitelist[${bucketIndex}].rules[${ruleIndex}].ids must be a non-empty string array`);
|
|
491
|
+
}
|
|
492
|
+
row.ids.forEach((id) => {
|
|
493
|
+
if (bucketValueIds.has(id)) {
|
|
494
|
+
throw new Error(`Flag --whitelist bucket ${item.bucket_id} contains duplicate ID: ${id}`);
|
|
495
|
+
}
|
|
496
|
+
bucketValueIds.add(id);
|
|
497
|
+
});
|
|
498
|
+
if (typeof row.value !== "string") {
|
|
499
|
+
throw new Error(`Flag --whitelist[${bucketIndex}].rules[${ruleIndex}].value must be a string`);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
return value;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/commands/te-experiment/feature-whitelist/batch-delete.ts
|
|
507
|
+
function buildBody(ctx) {
|
|
508
|
+
return { project_id: ctx.num("project-id"), rule_ids: readRuleIds(ctx) };
|
|
509
|
+
}
|
|
510
|
+
var featureWhitelistBatchDelete = createExperimentCapabilityCommand({
|
|
511
|
+
resource: "feature whitelist",
|
|
512
|
+
command: "batch-delete",
|
|
513
|
+
capabilityId: "experiment.feature_whitelist.batch_delete",
|
|
514
|
+
description: "Delete Feature whitelist rules; enabled whitelist rules are allowed and trigger RCC resync.",
|
|
515
|
+
flags: [
|
|
516
|
+
{ name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
|
|
517
|
+
{ name: "rule-ids", type: "json", required: true, desc: "Non-empty JSON array of whitelist rule IDs." }
|
|
518
|
+
],
|
|
519
|
+
risk: "high-risk-write",
|
|
520
|
+
validate: (ctx) => {
|
|
521
|
+
buildBody(ctx);
|
|
522
|
+
},
|
|
523
|
+
buildInput: buildBody
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
// src/commands/te-experiment/feature-whitelist/list.ts
|
|
527
|
+
function buildInput5(ctx) {
|
|
528
|
+
return {
|
|
529
|
+
project_id: ctx.num("project-id"),
|
|
530
|
+
feature_key: ctx.str("feature-key")
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
var featureWhitelistList = createExperimentCapabilityCommand({
|
|
534
|
+
resource: "feature whitelist",
|
|
535
|
+
command: "list",
|
|
536
|
+
capabilityId: "experiment.feature_whitelist.list",
|
|
537
|
+
description: "List explicit whitelist rules for one Feature.",
|
|
538
|
+
flags: [
|
|
539
|
+
{ name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
|
|
540
|
+
{ name: "feature-key", type: "string", required: true, desc: "Existing Feature key." }
|
|
541
|
+
],
|
|
542
|
+
risk: "read",
|
|
543
|
+
buildInput: buildInput5
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// src/commands/te-experiment/feature-whitelist/save.ts
|
|
547
|
+
function buildInput6(ctx) {
|
|
548
|
+
const ruleId = ctx.str("rule-id").trim();
|
|
549
|
+
const status = ctx.str("status").trim() || "draft";
|
|
550
|
+
if (!["draft", "enable", "disable"].includes(status)) {
|
|
551
|
+
throw new Error("Flag --status must be one of draft, enable, disable");
|
|
552
|
+
}
|
|
553
|
+
const input = {
|
|
554
|
+
project_id: ctx.num("project-id"),
|
|
555
|
+
feature_key: ctx.str("feature-key"),
|
|
556
|
+
whitelist: readWhitelist(ctx),
|
|
557
|
+
status
|
|
558
|
+
};
|
|
559
|
+
if (ruleId) input.rule_id = ruleId;
|
|
560
|
+
const priority = ctx.str("priority");
|
|
561
|
+
if (priority !== "") input.priority = ctx.num("priority");
|
|
562
|
+
return input;
|
|
563
|
+
}
|
|
564
|
+
var featureWhitelistSave = createExperimentCapabilityCommand({
|
|
565
|
+
resource: "feature whitelist",
|
|
566
|
+
command: "save",
|
|
567
|
+
capabilityId: "experiment.feature_whitelist.save",
|
|
568
|
+
description: "Create or modify a Feature whitelist rule and optionally enable it.",
|
|
569
|
+
flags: [
|
|
570
|
+
{ name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
|
|
571
|
+
{ name: "feature-key", type: "string", required: true, desc: "Existing Feature key." },
|
|
572
|
+
{ name: "rule-id", type: "string", desc: "Existing whitelist rule ID; omit to create a new rule." },
|
|
573
|
+
{ name: "priority", type: "number", desc: "Rule priority; omitted create requests use the server-assigned next priority." },
|
|
574
|
+
{ name: "status", type: "string", default: "draft", desc: "Rule status: draft, enable, or disable." },
|
|
575
|
+
{
|
|
576
|
+
name: "whitelist",
|
|
577
|
+
type: "json",
|
|
578
|
+
required: true,
|
|
579
|
+
desc: 'Whitelist bucket array: [{"bucket_id":"#user_id","rules":[{"ids":["u1"],"value":"on"}]}].'
|
|
580
|
+
}
|
|
581
|
+
],
|
|
582
|
+
risk: "write",
|
|
583
|
+
validate: (ctx) => {
|
|
584
|
+
buildInput6(ctx);
|
|
585
|
+
},
|
|
586
|
+
buildInput: buildInput6
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// src/commands/te-experiment/feature-whitelist/update-status.ts
|
|
590
|
+
function buildBody2(ctx) {
|
|
591
|
+
const status = ctx.str("status");
|
|
592
|
+
if (!["enable", "disable"].includes(status)) {
|
|
593
|
+
throw new Error("Flag --status must be one of enable, disable");
|
|
594
|
+
}
|
|
595
|
+
return { project_id: ctx.num("project-id"), rule_id: ctx.str("rule-id"), status };
|
|
596
|
+
}
|
|
597
|
+
var featureWhitelistUpdateStatus = createExperimentCapabilityCommand({
|
|
598
|
+
resource: "feature whitelist",
|
|
599
|
+
command: "update-status",
|
|
600
|
+
capabilityId: "experiment.feature_whitelist.update_status",
|
|
601
|
+
description: "Enable or disable a Feature whitelist rule; enabled rules sync an online Feature to RCC.",
|
|
602
|
+
flags: [
|
|
603
|
+
{ name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
|
|
604
|
+
{ name: "rule-id", type: "string", required: true, desc: "Whitelist rule ID." },
|
|
605
|
+
{ name: "status", type: "string", required: true, desc: "Target status: enable or disable." }
|
|
606
|
+
],
|
|
607
|
+
risk: "write",
|
|
608
|
+
validate: (ctx) => {
|
|
609
|
+
buildBody2(ctx);
|
|
610
|
+
},
|
|
611
|
+
buildInput: buildBody2
|
|
612
|
+
});
|
|
613
|
+
|
|
405
614
|
// src/commands/te-experiment/metric/delete.ts
|
|
406
615
|
var metricDelete = createExperimentCapabilityCommand({
|
|
407
616
|
resource: "metric",
|
|
@@ -442,6 +651,78 @@ var metricList = createExperimentCapabilityCommand({
|
|
|
442
651
|
});
|
|
443
652
|
|
|
444
653
|
// src/commands/te-experiment/metric/save.ts
|
|
654
|
+
var aggregations = /* @__PURE__ */ new Set([
|
|
655
|
+
"total_count",
|
|
656
|
+
"user_count",
|
|
657
|
+
"active_days",
|
|
658
|
+
"sum",
|
|
659
|
+
"avg",
|
|
660
|
+
"max",
|
|
661
|
+
"distinct_count"
|
|
662
|
+
]);
|
|
663
|
+
var propertyAggregations = /* @__PURE__ */ new Set(["sum", "avg", "max", "distinct_count"]);
|
|
664
|
+
var metricDefinitionFields = /* @__PURE__ */ new Set([
|
|
665
|
+
"type",
|
|
666
|
+
"event",
|
|
667
|
+
"aggregation",
|
|
668
|
+
"property",
|
|
669
|
+
"filters"
|
|
670
|
+
]);
|
|
671
|
+
function validateMetricFilters(rawFilters) {
|
|
672
|
+
if (rawFilters === void 0) return;
|
|
673
|
+
if (!rawFilters || typeof rawFilters !== "object" || Array.isArray(rawFilters)) {
|
|
674
|
+
throw new Error("Flag --req.metricDefinition.filters must be a JSON object");
|
|
675
|
+
}
|
|
676
|
+
const filters = rawFilters;
|
|
677
|
+
if (!["and", "or"].includes(String(filters.relation))) {
|
|
678
|
+
throw new Error("Flag --req.metricDefinition.filters.relation must be one of: and, or");
|
|
679
|
+
}
|
|
680
|
+
if (!Array.isArray(filters.items) || filters.items.length === 0) {
|
|
681
|
+
throw new Error("Flag --req.metricDefinition.filters.items must be a non-empty array");
|
|
682
|
+
}
|
|
683
|
+
filters.items.forEach((rawItem, index) => {
|
|
684
|
+
const path = `Flag --req.metricDefinition.filters.items[${index}]`;
|
|
685
|
+
if (!rawItem || typeof rawItem !== "object" || Array.isArray(rawItem)) {
|
|
686
|
+
throw new Error(`${path} must be a JSON object`);
|
|
687
|
+
}
|
|
688
|
+
const item = rawItem;
|
|
689
|
+
const field = item.field;
|
|
690
|
+
const validField = typeof field === "string" && field.trim() !== "" || Boolean(field && typeof field === "object" && !Array.isArray(field) && typeof field.name === "string" && String(field.name).trim() !== "");
|
|
691
|
+
if (!validField) throw new Error(`${path}.field is required`);
|
|
692
|
+
if (typeof item.operator !== "string" || item.operator.trim() === "") {
|
|
693
|
+
throw new Error(`${path}.operator is required and expresses the property comparison`);
|
|
694
|
+
}
|
|
695
|
+
if (!Array.isArray(item.values)) {
|
|
696
|
+
throw new Error(`${path}.values must be an array containing the comparison value(s)`);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
function validateMetricSaveRequest(req) {
|
|
701
|
+
const rawDefinition = req.metricDefinition;
|
|
702
|
+
if (rawDefinition === void 0 && req.update === true) return;
|
|
703
|
+
if (!rawDefinition || typeof rawDefinition !== "object" || Array.isArray(rawDefinition)) {
|
|
704
|
+
throw new Error("Flag --req.metricDefinition must be a JSON object");
|
|
705
|
+
}
|
|
706
|
+
const definition = rawDefinition;
|
|
707
|
+
for (const field of Object.keys(definition)) {
|
|
708
|
+
if (!metricDefinitionFields.has(field)) {
|
|
709
|
+
throw new Error(`Flag --req.metricDefinition.${field} is not supported`);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (definition.type !== "event") {
|
|
713
|
+
throw new Error("Flag --req.metricDefinition.type must be event");
|
|
714
|
+
}
|
|
715
|
+
if (typeof definition.event !== "string" || definition.event.trim() === "") {
|
|
716
|
+
throw new Error("Flag --req.metricDefinition.event is required");
|
|
717
|
+
}
|
|
718
|
+
if (typeof definition.aggregation !== "string" || !aggregations.has(definition.aggregation)) {
|
|
719
|
+
throw new Error(`Flag --req.metricDefinition.aggregation must be one of: ${[...aggregations].join(", ")}`);
|
|
720
|
+
}
|
|
721
|
+
if (propertyAggregations.has(definition.aggregation) && (typeof definition.property !== "string" || definition.property.trim() === "")) {
|
|
722
|
+
throw new Error(`Flag --req.metricDefinition.property is required for ${definition.aggregation}`);
|
|
723
|
+
}
|
|
724
|
+
validateMetricFilters(definition.filters);
|
|
725
|
+
}
|
|
445
726
|
var metricSave = createExperimentCapabilityCommand({
|
|
446
727
|
resource: "metric",
|
|
447
728
|
command: "save",
|
|
@@ -453,12 +734,12 @@ var metricSave = createExperimentCapabilityCommand({
|
|
|
453
734
|
name: "req",
|
|
454
735
|
type: "json",
|
|
455
736
|
required: true,
|
|
456
|
-
desc: "Native camelCase request
|
|
737
|
+
desc: "Native camelCase request. Property comparisons use metricDefinition.filters={relation,items:[{field,operator,values}]}. Never use metricConfig, calcType, or raw filts."
|
|
457
738
|
}
|
|
458
739
|
],
|
|
459
740
|
risk: "write",
|
|
460
741
|
validate: (ctx) => {
|
|
461
|
-
readRequiredObject(ctx, "req");
|
|
742
|
+
validateMetricSaveRequest(readRequiredObject(ctx, "req"));
|
|
462
743
|
},
|
|
463
744
|
buildInput: (ctx) => ({ project_id: ctx.num("project-id"), req: readRequiredObject(ctx, "req") })
|
|
464
745
|
});
|
|
@@ -709,6 +990,7 @@ var commands = [
|
|
|
709
990
|
experimentConflictCheck,
|
|
710
991
|
experimentManage,
|
|
711
992
|
experimentUpdateGroup,
|
|
993
|
+
experimentUpdateMetrics,
|
|
712
994
|
experimentBatchDelete,
|
|
713
995
|
operationLogQuery,
|
|
714
996
|
saveBuildGuide,
|
|
@@ -731,6 +1013,10 @@ var commands = [
|
|
|
731
1013
|
featureVersionList,
|
|
732
1014
|
featureOperationLogQuery,
|
|
733
1015
|
featureBatchDelete,
|
|
1016
|
+
featureWhitelistList,
|
|
1017
|
+
featureWhitelistSave,
|
|
1018
|
+
featureWhitelistUpdateStatus,
|
|
1019
|
+
featureWhitelistBatchDelete,
|
|
734
1020
|
bucketList
|
|
735
1021
|
];
|
|
736
1022
|
var te_experiment_default = commands;
|
|
@@ -746,6 +1032,7 @@ export {
|
|
|
746
1032
|
experimentReadyCheck,
|
|
747
1033
|
experimentSave,
|
|
748
1034
|
experimentUpdateGroup,
|
|
1035
|
+
experimentUpdateMetrics,
|
|
749
1036
|
featureBatchDelete,
|
|
750
1037
|
featureGet,
|
|
751
1038
|
featureList,
|
|
@@ -753,6 +1040,10 @@ export {
|
|
|
753
1040
|
featureSave,
|
|
754
1041
|
featureUpdateStatus,
|
|
755
1042
|
featureVersionList,
|
|
1043
|
+
featureWhitelistBatchDelete,
|
|
1044
|
+
featureWhitelistList,
|
|
1045
|
+
featureWhitelistSave,
|
|
1046
|
+
featureWhitelistUpdateStatus,
|
|
756
1047
|
metricDelete,
|
|
757
1048
|
metricGet,
|
|
758
1049
|
metricList,
|