@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.
Files changed (126) hide show
  1. package/README.md +2 -0
  2. package/README.zh.md +6 -0
  3. package/dist/{auth-77BUFLGC.js → auth-QPEVVBKT.js} +20 -15
  4. package/dist/auth-UMJAA72O.js +15 -0
  5. package/dist/{capability-72DTW5M2.js → capability-ASI62I4A.js} +53 -15
  6. package/dist/{chunk-UW5UN47B.js → chunk-533JK3YX.js} +2 -0
  7. package/dist/{chunk-UOUS37JQ.js → chunk-6QK7SYYY.js} +5 -4
  8. package/dist/{chunk-TUKQZTMI.js → chunk-7K24F7T2.js} +2 -0
  9. package/dist/{chunk-OO6XR6LK.js → chunk-AMBFK2K3.js} +2 -0
  10. package/dist/{sync-DAVKYVMW.js → chunk-B5HMQAOM.js} +31 -540
  11. package/dist/{chunk-VR3LCBHW.js → chunk-DKEXH6Q5.js} +6 -5
  12. package/dist/{chunk-VTWMIC5L.js → chunk-E2JKXMVO.js} +2 -0
  13. package/dist/{chunk-LYVNONC4.js → chunk-FR2EDAQM.js} +36 -0
  14. package/dist/{chunk-ILIU36SU.js → chunk-GJXRF7Y6.js} +6 -5
  15. package/dist/{chunk-DWO43OIB.js → chunk-JQ3ENZZH.js} +2 -0
  16. package/dist/chunk-JYMGHGCE.js +191 -0
  17. package/dist/{chunk-GT46FPXN.js → chunk-KEWVSO64.js} +18 -8
  18. package/dist/chunk-KZ6ZHF5J.js +294 -0
  19. package/dist/chunk-O6K2ODUE.js +318 -0
  20. package/dist/chunk-QL6R6TSK.js +25215 -0
  21. package/dist/{chunk-4SGZG4XY.js → chunk-RWXIXOZG.js} +28 -13
  22. package/dist/{chunk-YA6SMTXG.js → chunk-S5PONFBM.js} +5 -4
  23. package/dist/{chunk-4NN5IWVN.js → chunk-T6OSFQZD.js} +2 -0
  24. package/dist/{chunk-PTE56QPL.js → chunk-TKHSULJT.js} +6 -0
  25. package/dist/{chunk-6EIJSNBD.js → chunk-Y74WTIKJ.js} +2 -0
  26. package/dist/{client-TKG4WBHN.js → client-N7NGZUNI.js} +6 -4
  27. package/dist/{community-report-client-FI4LNVYS.js → community-report-client-6OL6GBQW.js} +3 -3
  28. package/dist/{config-RE6CMGPK.js → config-XNMACCKX.js} +10 -8
  29. package/dist/{data-integration-XQYB4X4F.js → data-integration-4NZGZ45E.js} +2502 -272
  30. package/dist/index.js +137 -1245
  31. package/dist/{local-data-upload-client-BWHSUQQK.js → local-data-upload-client-EFHDLXFG.js} +3 -3
  32. package/dist/{memory-YK33G4T7.js → memory-HBJQ2GC5.js} +8 -7
  33. package/dist/{metadata-UILXHBWF.js → metadata-62EWBEIG.js} +12 -11
  34. package/dist/{model-NR3JHFSJ.js → model-BHLJ2QMT.js} +10 -9
  35. package/dist/personal-semantic-preference-JBVMAI7L.js +240 -0
  36. package/dist/project-semantic-BQ4MPUS5.js +1115 -0
  37. package/dist/sync-MUWPRM5I.js +522 -0
  38. package/dist/{te-agent-4BKBODMF.js → te-agent-WQZTMEK4.js} +12 -10
  39. package/dist/{te-analysis-O6DCO6BS.js → te-analysis-MNCG65LU.js} +534 -48
  40. package/dist/{te-community-HLC43QKH.js → te-community-BNE6KREL.js} +8 -7
  41. package/dist/{te-dataops-EJP56W3K.js → te-dataops-TXLKM2W6.js} +469 -68
  42. package/dist/{te-engage-FGBGQ4IY.js → te-engage-TPKLRVTL.js} +84 -10
  43. package/dist/{te-experiment-SO5MPDMJ.js → te-experiment-6BYKTCY7.js} +303 -12
  44. package/dist/{te-kb-SQCLHG6X.js → te-kb-BUD6N3NI.js} +312 -25
  45. package/dist/{te-system-YARIK4S5.js → te-system-44LZJDTQ.js} +573 -37
  46. package/dist/{te-team-EFKWYKMK.js → te-team-XMP47YXE.js} +10 -7
  47. package/dist/{update-OGPSZM5A.js → update-UODFOZ4P.js} +9 -7
  48. package/package.json +18 -9
  49. package/skills/ae-agent/SKILL.md +3 -4
  50. package/skills/ae-agent/references/edit-skill.md +3 -0
  51. package/skills/ae-agent/references/get-skill-content.md +1 -1
  52. package/skills/ae-agent/references/rescan-skills.md +15 -13
  53. package/skills/ae-agent/references/upload-skill.md +7 -4
  54. package/skills/ae-analysis/SKILL.md +45 -4
  55. package/skills/ae-analysis/metadata_resolution.md +38 -4
  56. package/skills/ae-analysis/references/analysis_data_retrieval.md +29 -0
  57. package/skills/ae-analysis/references/analysis_gateway_assets.md +1 -1
  58. package/skills/ae-analysis/references/asset_authentication_export.md +22 -0
  59. package/skills/ae-analysis/references/asset_authentication_list.md +18 -14
  60. package/skills/ae-analysis/references/asset_authentication_update.md +29 -14
  61. package/skills/ae-analysis/references/audience_models.md +18 -0
  62. package/skills/ae-analysis/references/command_index.md +19 -11
  63. package/skills/ae-analysis/references/dashboard_get.md +18 -1
  64. package/skills/ae-analysis/references/dashboard_update.md +3 -0
  65. package/skills/ae-analysis/references/personal_semantic_preference_add.md +23 -0
  66. package/skills/ae-analysis/references/personal_semantic_preference_delete.md +17 -0
  67. package/skills/ae-analysis/references/personal_semantic_preference_get.md +19 -0
  68. package/skills/ae-analysis/references/personal_semantic_preference_list.md +21 -0
  69. package/skills/ae-analysis/references/personal_semantic_preference_update.md +19 -0
  70. package/skills/ae-analysis/references/project_timezone_update.md +13 -4
  71. package/skills/ae-analysis/references/property_create.md +2 -0
  72. package/skills/ae-analysis/references/super_metadata_batch_create.md +2 -0
  73. package/skills/ae-analysis/references/user_cluster_models.md +2 -0
  74. package/skills/ae-analysis/references/user_cluster_update.md +8 -4
  75. package/skills/ae-analysis/references/user_tag_create.md +7 -1
  76. package/skills/ae-analysis/references/user_tag_models.md +8 -2
  77. package/skills/ae-data-integration/SKILL.md +24 -4
  78. package/skills/ae-data-integration/references/custom-layer.md +93 -0
  79. package/skills/ae-data-integration/references/error-handling.md +145 -0
  80. package/skills/ae-data-integration/references/handoff.md +77 -18
  81. package/skills/ae-data-integration/references/local-analysis.md +1 -1
  82. package/skills/ae-data-integration/references/reuse.md +9 -5
  83. package/skills/ae-data-integration/references/sink-upload.md +1 -1
  84. package/skills/ae-data-integration/references/source-inspect.md +35 -13
  85. package/skills/ae-data-integration/references/tracking-plan.md +7 -5
  86. package/skills/ae-data-integration/references/transform.md +12 -10
  87. package/skills/ae-data-integration/references/ue-mapping.md +33 -11
  88. package/skills/ae-data-integration/references/ue-routing.md +23 -0
  89. package/skills/ae-dataops/SKILL.md +11 -1
  90. package/skills/ae-dataops/references/dataops-backfill.md +135 -0
  91. package/skills/ae-engage/SKILL.md +5 -0
  92. package/skills/ae-engage/references/build-task-save-guide.md +14 -1
  93. package/skills/ae-engage/references/save-flow.md +37 -1
  94. package/skills/ae-engage/references/save-task.md +88 -0
  95. package/skills/ae-experiment/SKILL.md +14 -4
  96. package/skills/ae-experiment/references/manage_feature_whitelist.md +66 -0
  97. package/skills/ae-experiment/references/manage_guardrail_metrics.md +26 -0
  98. package/skills/ae-experiment/references/save_experiment.md +1 -1
  99. package/skills/ae-experiment/references/save_metric.md +20 -8
  100. package/skills/ae-kb/SKILL.md +121 -10
  101. package/skills/ae-project-semantic/SKILL.md +193 -0
  102. package/skills/ae-project-semantic/references/query-routing-v5.md +165 -0
  103. package/skills/ae-project-semantic/references/recommendation-quality.md +68 -0
  104. package/skills/ae-system/SKILL.md +28 -30
  105. package/skills/ae-system/references/channel-management.md +303 -0
  106. package/dist/auth-2WTQOP77.js +0 -14
  107. package/dist/capability-PJHNI4GJ.js +0 -315
  108. package/dist/chunk-4KVPKXFX.js +0 -98
  109. package/dist/chunk-C4MGVGJW.js +0 -13
  110. package/dist/chunk-P3FGXJTU.js +0 -349
  111. package/dist/chunk-QGM4M3NI.js +0 -37
  112. package/dist/chunk-RGKJGKT7.js +0 -71
  113. package/dist/chunk-SAU3QFIQ.js +0 -556
  114. package/dist/chunk-VPKZ7I72.js +0 -509
  115. package/dist/chunk-ZZUOD757.js +0 -598
  116. package/dist/memory-CHRU2F7W.js +0 -893
  117. package/dist/metadata-XXR34N5P.js +0 -339
  118. package/dist/model-K3KLWIW6.js +0 -139
  119. package/dist/sync-FCKOVWWS.js +0 -10261
  120. package/dist/te-agent-HLW4VTQK.js +0 -3893
  121. package/dist/te-analysis-ZMNGOVNW.js +0 -8958
  122. package/dist/te-community-6HPBWJUZ.js +0 -1859
  123. package/dist/te-dataops-HDRUXY4K.js +0 -2208
  124. package/dist/te-engage-RAK5PESW.js +0 -4898
  125. package/dist/te-experiment-VZF7BT6G.js +0 -770
  126. 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-VR3LCBHW.js";
4
+ } from "./chunk-DKEXH6Q5.js";
4
5
  import {
5
6
  registerCapabilityGatewayRoute,
6
7
  resolveGatewayDomain
7
- } from "./chunk-PTE56QPL.js";
8
+ } from "./chunk-TKHSULJT.js";
8
9
  import {
9
10
  printError,
10
11
  withOutputMetadata
11
- } from "./chunk-GT46FPXN.js";
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-ILIU36SU.js";
19
- import "./chunk-6EIJSNBD.js";
20
- import "./chunk-4SGZG4XY.js";
21
- import "./chunk-ZZUOD757.js";
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-UW5UN47B.js";
25
- import "./chunk-LYVNONC4.js";
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-VR3LCBHW.js";
4
+ } from "./chunk-DKEXH6Q5.js";
4
5
  import {
5
6
  registerCapabilityGatewayRoute
6
- } from "./chunk-PTE56QPL.js";
7
- import "./chunk-GT46FPXN.js";
8
- import "./chunk-ILIU36SU.js";
9
- import "./chunk-6EIJSNBD.js";
10
- import "./chunk-4SGZG4XY.js";
11
- import "./chunk-ZZUOD757.js";
12
- import "./chunk-UW5UN47B.js";
13
- import "./chunk-LYVNONC4.js";
14
- import "./chunk-QGM4M3NI.js";
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; use metricDefinition, never metricConfig or calcType."
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,