@thinkingai/ae-cli 6.1.6 → 6.1.8

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 (142) hide show
  1. package/dist/{auth-UPGUOKTW.js → auth-B2BRSYMS.js} +1 -1
  2. package/dist/{capability-TQ5KU5Q6.js → capability-6KPXYNO7.js} +1 -1
  3. package/dist/{capability-AJC5CBRT.js → capability-ROKYESAP.js} +1 -1
  4. package/dist/{chunk-6CHYBI64.js → chunk-EBPXT3TN.js} +1 -1
  5. package/dist/{chunk-4Q5TNP4Q.js → chunk-J7MZHDHQ.js} +48 -24
  6. package/dist/{chunk-IMMGMU54.js → chunk-JTKMDN4A.js} +64 -166
  7. package/dist/{chunk-ISY6HMHM.js → chunk-RRFK2W7I.js} +1 -1
  8. package/dist/{config-RCCGHHYA.js → config-DDYJPJX3.js} +4 -4
  9. package/dist/index.js +63 -28
  10. package/dist/{metadata-3M5F2AED.js → metadata-2ZFRMVOL.js} +2 -55
  11. package/dist/{metadata-W2MEOI4Z.js → metadata-ABQCKU5P.js} +2 -55
  12. package/dist/{model-OYQLXCQY.js → model-JASQVOFD.js} +1 -1
  13. package/dist/{raw-TPB7KSZO.js → raw-6HXFFHLV.js} +1 -1
  14. package/dist/{sync-EFJKFZK2.js → sync-BF3IWYFC.js} +2 -2
  15. package/dist/{te-agent-K2OWMZXT.js → te-agent-3GJ5H2XF.js} +195 -2
  16. package/dist/{te-analysis-I73ZS4NK.js → te-analysis-DJ6KELTU.js} +636 -668
  17. package/dist/{te-analysis-Q7AZCDU4.js → te-analysis-PCGESPLW.js} +636 -668
  18. package/dist/{te-dataops-OA7I6HBG.js → te-dataops-LXL5YULV.js} +7 -7
  19. package/dist/{te-dataops-MJV54MNY.js → te-dataops-ROHUJOX5.js} +7 -7
  20. package/dist/{te-engage-2FSDUOIZ.js → te-engage-2YDCA552.js} +87 -4
  21. package/dist/{te-engage-BMJ6UOUU.js → te-engage-VW6NJZ5V.js} +87 -4
  22. package/dist/{te-experiment-4JC7WUKW.js → te-experiment-7JGJNDXO.js} +2 -2
  23. package/dist/{te-experiment-KYRWAUZY.js → te-experiment-OYK54B72.js} +2 -2
  24. package/dist/te-meta-GBDTMPEL.js +95 -0
  25. package/dist/te-meta-ZTLTSHXC.js +95 -0
  26. package/dist/te-system-AH7DMCAQ.js +1706 -0
  27. package/dist/{te-team-PDKKW7Q5.js → te-team-RRZI4WRI.js} +1 -1
  28. package/dist/update-ER7VFU55.js +101 -0
  29. package/package.json +9 -4
  30. package/skills/ae-agent/SKILL.md +5 -1
  31. package/skills/ae-agent/references/create-automation.md +1 -0
  32. package/skills/ae-agent/references/list-sandbox-tools.md +79 -0
  33. package/skills/ae-analysis/SKILL.md +8 -9
  34. package/skills/ae-analysis/references/adhoc_export.md +8 -0
  35. package/skills/ae-analysis/references/adhoc_run.md +9 -0
  36. package/skills/ae-analysis/references/ai_models.md +3 -1
  37. package/skills/ae-analysis/references/alert_create.md +2 -3
  38. package/skills/ae-analysis/references/alert_update.md +2 -3
  39. package/skills/ae-analysis/references/analysis_data_retrieval.md +2 -0
  40. package/skills/ae-analysis/references/analysis_drilldown_contract.md +2 -0
  41. package/skills/ae-analysis/references/analysis_gateway_assets.md +15 -11
  42. package/skills/ae-analysis/references/bi_panel_create.md +12 -4
  43. package/skills/ae-analysis/references/bi_panel_update.md +11 -8
  44. package/skills/ae-analysis/references/bi_panel_version_publish.md +3 -1
  45. package/skills/ae-analysis/references/command_index.md +28 -47
  46. package/skills/ae-analysis/references/dashboard_daily_report_get.md +18 -0
  47. package/skills/ae-analysis/references/dashboard_daily_report_send.md +12 -9
  48. package/skills/ae-analysis/references/dashboard_daily_report_send_status.md +22 -0
  49. package/skills/ae-analysis/references/dashboard_daily_report_update.md +13 -6
  50. package/skills/ae-analysis/references/dashboard_report_data_export.md +4 -2
  51. package/skills/ae-analysis/references/dashboard_report_data_run.md +5 -3
  52. package/skills/ae-analysis/references/drilldown_entities_export.md +3 -0
  53. package/skills/ae-analysis/references/drilldown_entities_run.md +2 -1
  54. package/skills/ae-analysis/references/drilldown_events_export.md +3 -0
  55. package/skills/ae-analysis/references/drilldown_events_run.md +2 -1
  56. package/skills/ae-analysis/references/drilldown_user_events_export.md +8 -0
  57. package/skills/ae-analysis/references/drilldown_user_events_run.md +8 -0
  58. package/skills/ae-analysis/references/entity_id_import_options.md +1 -1
  59. package/skills/ae-analysis/references/filter_value_list.md +47 -0
  60. package/skills/ae-analysis/references/project_space_get.md +3 -3
  61. package/skills/ae-analysis/references/project_space_list.md +6 -2
  62. package/skills/ae-analysis/references/query_cancel.md +3 -1
  63. package/skills/ae-analysis/references/query_cluster_list.md +34 -0
  64. package/skills/ae-analysis/references/query_create_result_cluster.md +2 -0
  65. package/skills/ae-analysis/references/report_create.md +5 -1
  66. package/skills/ae-analysis/references/report_data_export.md +9 -2
  67. package/skills/ae-analysis/references/report_data_run.md +8 -3
  68. package/skills/ae-analysis/references/report_get.md +3 -1
  69. package/skills/ae-analysis/references/report_update.md +4 -0
  70. package/skills/ae-analysis/references/super_metadata_batch_create.md +29 -0
  71. package/skills/ae-analysis/references/super_metadata_batch_edit.md +24 -0
  72. package/skills/ae-analysis/references/virtual_event_create.md +7 -6
  73. package/skills/ae-analysis-global/SKILL.md +15 -32
  74. package/skills/ae-community/SKILL.md +1 -1
  75. package/skills/ae-data-integration-helper/SKILL.md +3 -2
  76. package/skills/ae-data-integration-helper/references/sdk_usage_notes.md +1 -1
  77. package/skills/ae-dataops/SKILL.md +2 -1
  78. package/skills/ae-dataops/references/dataops-integration.md +75 -6
  79. package/skills/ae-engage/SKILL.md +32 -5
  80. package/skills/ae-engage/references/activity-topic.md +34 -1
  81. package/skills/ae-engage/references/add-channel.md +2 -3
  82. package/skills/ae-engage/references/build-task-save-guide.md +17 -3
  83. package/skills/ae-engage/references/channel-detail.md +2 -3
  84. package/skills/ae-engage/references/channel-list.md +2 -5
  85. package/skills/ae-engage/references/channel-mgmt.md +17 -2
  86. package/skills/ae-engage/references/channel-test-send.md +1 -1
  87. package/skills/ae-engage/references/channel-update-config.md +1 -1
  88. package/skills/ae-engage/references/delete-channel.md +2 -3
  89. package/skills/ae-engage/references/save-flow.md +6 -3
  90. package/skills/ae-engage/references/save-task.md +12 -15
  91. package/skills/ae-engage/references/scene-config-channel.md +28 -4
  92. package/skills/ae-engage/references/scene-config-group.md +1 -1
  93. package/skills/ae-engage/references/scene-config-item.md +1 -1
  94. package/skills/ae-engage/references/scene-config-metric.md +1 -1
  95. package/skills/ae-engage/references/scene-config-param.md +1 -1
  96. package/skills/ae-engage/references/scene-preset-metric.md +1 -1
  97. package/skills/ae-engage/references/scene-strategy-audience.md +680 -0
  98. package/skills/ae-engage/references/scene-strategy.md +16 -1
  99. package/skills/ae-engage/references/scene-template.md +1 -1
  100. package/skills/ae-engage/references/update-channel-status.md +2 -3
  101. package/skills/ae-generate-tracking-code/SKILL.md +4 -3
  102. package/skills/ae-generate-tracking-code/references/client-sdk-insert.md +1 -1
  103. package/skills/ae-generate-tracking-code/references/server-sdk-insert.md +1 -1
  104. package/skills/ae-generate-tracking-code/references/snippet-delivery.md +1 -1
  105. package/skills/ae-generate-tracking-plan/SKILL.md +6 -2
  106. package/skills/ae-metadata/SKILL.md +8 -15
  107. package/skills/ae-metadata/references/metadata_property_dimension_table_bind_existing.md +1 -1
  108. package/skills/ae-system/SKILL.md +357 -0
  109. package/dist/te-common-ST3QPSXJ.js +0 -61
  110. package/dist/te-common-WSLIKKPC.js +0 -61
  111. package/dist/te-meta-Q4L6EE3Q.js +0 -363
  112. package/dist/te-meta-VHCN4Q62.js +0 -363
  113. package/skills/ae-analysis/references/alert_definition_schema_get.md +0 -24
  114. package/skills/ae-analysis/references/batch_create_metadata.md +0 -41
  115. package/skills/ae-analysis/references/batch_edit_metadata.md +0 -39
  116. package/skills/ae-analysis/references/cancel_query.md +0 -38
  117. package/skills/ae-analysis/references/create_alert.md +0 -47
  118. package/skills/ae-analysis/references/create_entity.md +0 -39
  119. package/skills/ae-analysis/references/create_project_mark_time.md +0 -39
  120. package/skills/ae-analysis/references/delete_alert.md +0 -32
  121. package/skills/ae-analysis/references/delete_project_mark_times.md +0 -36
  122. package/skills/ae-analysis/references/delete_track_items.md +0 -36
  123. package/skills/ae-analysis/references/generate_track_program.md +0 -52
  124. package/skills/ae-analysis/references/generate_track_sdk_sample.md +0 -44
  125. package/skills/ae-analysis/references/get_alert.md +0 -35
  126. package/skills/ae-analysis/references/get_alert_definition_schema.md +0 -33
  127. package/skills/ae-analysis/references/get_project_config.md +0 -33
  128. package/skills/ae-analysis/references/get_track_program.md +0 -34
  129. package/skills/ae-analysis/references/list_alerts.md +0 -41
  130. package/skills/ae-analysis/references/list_entities.md +0 -42
  131. package/skills/ae-analysis/references/list_project_mark_times.md +0 -43
  132. package/skills/ae-analysis/references/list_project_users.md +0 -33
  133. package/skills/ae-analysis/references/list_projects.md +0 -39
  134. package/skills/ae-analysis/references/load_filters.md +0 -47
  135. package/skills/ae-analysis/references/save_track_items.md +0 -37
  136. package/skills/ae-analysis/references/update_alert.md +0 -49
  137. package/skills/ae-analysis/references/update_project_mark_time.md +0 -40
  138. package/skills/ae-analysis-global/references/list_query_clusters.md +0 -68
  139. package/skills/ae-metadata/references/metadata_event_get.md +0 -52
  140. package/skills/ae-metadata/references/metadata_property_get.md +0 -54
  141. package/dist/{te-community-WXGB6IOX.js → te-community-QOYIYEJI.js} +3 -3
  142. package/dist/{te-community-X2AHXGCA.js → te-community-UFKI6ONP.js} +3 -3
@@ -0,0 +1,680 @@
1
+ # Config strategy audience (custom cluster)
2
+
3
+ > Applies to: **配置中心 → 运营策略 → 目标受众 → 目标用户 → 自定义人群**.
4
+ > Strategy payload: [`scene-strategy.md`](scene-strategy.md).
5
+ > Audience **logic** uses the same semantic model as ae-analysis [`user_cluster_models.md`](../../ae-analysis/references/user_cluster_models.md) + [`audience_models.md`](../../ae-analysis/references/audience_models.md).
6
+
7
+ Webhook / client config strategies store audience on `ConfigStrategyAddDTO`:
8
+
9
+ | UI | Payload field | Notes |
10
+ |---|---|---|
11
+ | 全部用户 | `targetClusterType: 0` | `targetClusterQp: null` |
12
+ | 自定义人群 | `targetClusterType: 1` | `targetClusterQp`: **JSON string** (mix QP) |
13
+ | 目标环境 (Webhook) | `envConfig` | Mutually exclusive with user audience on Webhook |
14
+
15
+ ## Default workflow (Agent) — direct strategy, no new cluster
16
+
17
+ **Unless the user explicitly asks to use an existing / named user cluster**, do **not** call `analysis user-cluster create`. Create the strategy directly:
18
+
19
+ 1. **Preflight** — verify every user/event property and enum value exists (see [Preflight](#preflight--mandatory-stop)).
20
+ 2. **Design** — express audience in natural language: **用户满足** block + optional **用户行为** block + relation between them.
21
+ 3. **Assemble** — build mix QP (`totalCFilter`, optional `totalOutCFilter`) per [QP shape](#mix-qp-shape-ui--backend) below; `JSON.stringify` into `targetClusterQp`.
22
+ 4. **Create / update** — `engage-scene strategy create|update`.
23
+
24
+ ```bash
25
+ # Preflight
26
+ ae-cli analysis-meta property list --project-id <pid> --table-type user
27
+ ae-cli analysis-meta property get --project-id <pid> --table-type user --prop-name <prop>
28
+ ae-cli analysis-meta event list --project-id <pid>
29
+ ae-cli analysis-meta event get --project-id <pid> --event-name <event>
30
+ ae-cli analysis +load_filters --project_id <pid> --table_type user --quot <prop>
31
+
32
+ # Create / update
33
+ ae-cli engage-scene strategy create --project-id <pid> --payload '{
34
+ "configId":"<config_id>",
35
+ "templateId":"<enabled_template_id>",
36
+ "strategyName":"<name>",
37
+ "tzOffset":8.0,
38
+ "targetClusterType":1,
39
+ "targetClusterQp":"<stringified mix QP>",
40
+ "envConfig":null,
41
+ "templateParamConfig":"[...]",
42
+ "content":"{...}",
43
+ "triggerType":0,
44
+ "onlineTime":"1",
45
+ "offlineTime":"1"
46
+ }'
47
+ ```
48
+
49
+ Align `tzOffset` with the strategy timezone.
50
+
51
+ ---
52
+
53
+ ## Mix QP shape (UI ↔ backend)
54
+
55
+ Config-strategy custom audience uses **mix QP** (same as Hermes `formatTriggerConditionForBack` / `formatTriggerConditionFromQp`, mix version `4.3`).
56
+
57
+ ### Top-level object
58
+
59
+ ```json
60
+ {
61
+ "totalCFilter": { "relation": "<userEventRelation>", "filts": [ /* block 0 */, /* block 1 */ ] },
62
+ "totalOutCFilter": { "relation": "0", "filts": [] }
63
+ }
64
+ ```
65
+
66
+ | Field | UI label | Meaning |
67
+ |---|---|---|
68
+ | `totalCFilter.relation` | 用户满足 **与/或** 用户行为 | `"1"` = 且, `"0"` = 或 (`userEventRelation`) |
69
+ | `totalCFilter.filts[0]` | **用户满足** | User/tag/cluster conditions only |
70
+ | `totalCFilter.filts[1]` | **用户行为** | Event / behavior-sequence conditions only (omit block if no events) |
71
+ | `totalOutCFilter` | **排除用户** | Optional exclude block; empty `filts` when unused |
72
+
73
+ ### Hard structural rules
74
+
75
+ 1. **Two-block layout** — when both user attrs and events exist, `totalCFilter.filts` has **exactly two** group objects:
76
+ - `[0]` = 用户满足 (`filts[].conditionType` is `user` / `tag` / `cluster`, or nested `filterType:"COMPOUND"`)
77
+ - `[1]` = 用户行为 (`filts[].conditionType` is `event` / `behaviorSeq`)
78
+ 2. **Never nest `event` inside 用户满足** — do not put `conditionType:"event"` under user-side `filterType:"COMPOUND"`. The UI cannot parse that shape.
79
+ 3. **Group vs leaf** — compound groups use `{ "relation": 0|1, "filts": [...] }` or `{ "filterType": "COMPOUND", "relation": 0|1, "filts": [...] }` inside 用户满足. Event block uses `{ "relation": 0|1, "filts": [ event leaves ] }` without `filterType`.
80
+ 4. **`relation` values** — `"1"` = 且, `"0"` = 或 (string at group level is accepted; backend may normalize to number).
81
+
82
+ ### ASCII layout (typical case: 用户满足 且 用户行为)
83
+
84
+ ```
85
+ totalCFilter
86
+ ├── relation: "1" ← userEventRelation (且)
87
+ ├── filts[0] 用户满足
88
+ │ ├── relation: "0"|"1" ← OR/AND among user conditions
89
+ │ └── filts[]
90
+ │ ├── filterType:"COMPOUND" … ← nested AND/OR groups
91
+ │ └── conditionType:"user" … ← leaf
92
+ └── filts[1] 用户行为
93
+ ├── relation: "0"|"1" ← OR/AND among events
94
+ └── filts[]
95
+ └── conditionType:"event" …
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 用户满足 — QP definition
101
+
102
+ **UI:** 目标受众 → 自定义人群 → **用户满足**
103
+ **JSON:** `totalCFilter.filts[0]`
104
+
105
+ ### Group
106
+
107
+ ```json
108
+ {
109
+ "relation": "0",
110
+ "filts": [ /* leaves and COMPOUND groups */ ]
111
+ }
112
+ ```
113
+
114
+ - `relation: "0"` — 或 (any branch matches)
115
+ - `relation: "1"` — 且 (all branches match)
116
+
117
+ ### Nested AND/OR (COMPOUND)
118
+
119
+ Use inside `filts[0].filts` when one OR branch is itself an AND (or deeper nesting):
120
+
121
+ ```json
122
+ {
123
+ "filterType": "COMPOUND",
124
+ "relation": 1,
125
+ "filts": [
126
+ { "conditionType": "user", "userCondition": { /* leaf A */ } },
127
+ { "conditionType": "user", "userCondition": { /* leaf B */ } }
128
+ ]
129
+ }
130
+ ```
131
+
132
+ ### User property leaf (`userCondition`)
133
+
134
+ Every leaf must use fields from **`analysis-meta property get`** — never guess names or enum values.
135
+
136
+ | Semantic operator | `calcuSymbol` |
137
+ |---|---|
138
+ | equals | `C00` |
139
+ | not equals | `C01` |
140
+ | less than / ≤ | `C02` / `C020` |
141
+ | greater than / ≥ | `C03` / `C030` |
142
+ | contains / not contains | `C07` / `C08` |
143
+ | regex / not regex | `C11` / `C12` |
144
+
145
+ Minimal string leaf:
146
+
147
+ ```json
148
+ {
149
+ "conditionType": "user",
150
+ "userCondition": {
151
+ "calcuSymbol": "C00",
152
+ "columnName": "device_brand",
153
+ "columnDesc": "device_brand",
154
+ "columnType": "string",
155
+ "selectType": "string",
156
+ "tableType": "1",
157
+ "ftv": ["苹果"],
158
+ "timeRelative": "",
159
+ "timeUnit": ""
160
+ }
161
+ }
162
+ ```
163
+
164
+ Datetime leaf (e.g. birth date after a year — confirm `columnType`/`selectType` from property get):
165
+
166
+ ```json
167
+ {
168
+ "conditionType": "user",
169
+ "userCondition": {
170
+ "calcuSymbol": "C030",
171
+ "columnName": "birthdate",
172
+ "columnDesc": "birthdate",
173
+ "columnType": "timestamp",
174
+ "selectType": "datetime",
175
+ "tableType": "1",
176
+ "ftv": ["2001-01-01 00:00:00"],
177
+ "timeRelative": "",
178
+ "timeUnit": ""
179
+ }
180
+ }
181
+ ```
182
+
183
+ ### 用户满足-only audience
184
+
185
+ When there is **no** 用户行为, `totalCFilter.filts` has **one** block (用户满足 only). Set `totalCFilter.relation` to `"1"` (default 且 with empty event side is not used — simply omit `filts[1]`).
186
+
187
+ ---
188
+
189
+ ## 用户行为 — QP definition
190
+
191
+ **UI:** 目标受众 → 自定义人群 → **用户行为**
192
+ **JSON:** `totalCFilter.filts[1]`
193
+
194
+ ### Group
195
+
196
+ ```json
197
+ {
198
+ "relation": "1",
199
+ "filts": [
200
+ { "conditionType": "event", "eventCondition": { /* … */ } }
201
+ ]
202
+ }
203
+ ```
204
+
205
+ - Multiple events: `relation: "1"` = 且 (all), `"0"` = 或 (any).
206
+
207
+ ### Event count leaf (`eventCondition`)
208
+
209
+ Preset **总次数** (empty `taPropQuota.quota`) rules — see [`save-flow.md`](save-flow.md) §9.2:
210
+
211
+ | Meaning | `uceCalcuSymbol` | `num` (string) |
212
+ |---|---|---|
213
+ | at least once (≥ 1) | `C030` | `"1"` |
214
+ | at least N times (≥ N) | `C030` | `"N"` |
215
+ | greater than N (> N) | `C03` | `"N"` |
216
+
217
+ Always include full `taPropQuota`:
218
+
219
+ ```json
220
+ "taPropQuota": {
221
+ "analysis": "A200",
222
+ "analysisDesc": "Count",
223
+ "quota": "",
224
+ "quotaDesc": "",
225
+ "analysisParams": ""
226
+ }
227
+ ```
228
+
229
+ ### Time window (`recentDay`)
230
+
231
+ | UI wording | Typical `recentDay` |
232
+ |---|---|
233
+ | 最近 N 天(含今天) | `"0-N"` |
234
+ | 过去 N 天(不含今天) | `"1-N"` |
235
+
236
+ Confirm against project convention if validation fails.
237
+
238
+ ### Event leaf template
239
+
240
+ ```json
241
+ {
242
+ "conditionType": "event",
243
+ "eventCondition": {
244
+ "eventName": "login",
245
+ "eventDesc": "login",
246
+ "eventType": "event",
247
+ "uceCalcuSymbol": "C030",
248
+ "num": "2",
249
+ "recentDay": "0-3",
250
+ "startTime": "",
251
+ "endTime": "",
252
+ "taPropQuota": {
253
+ "analysis": "A200",
254
+ "analysisDesc": "Count",
255
+ "quota": "",
256
+ "quotaDesc": "",
257
+ "analysisParams": ""
258
+ },
259
+ "filts": [],
260
+ "relation": 1
261
+ }
262
+ }
263
+ ```
264
+
265
+ ### Event property filters
266
+
267
+ Put filters on the event inside `eventCondition.filts[]` (`tableType: "0"`). Preflight with `analysis-meta event get` + event-scoped property list. Example: `os_version` regex on `login` — see worked example B below.
268
+
269
+ ---
270
+
271
+ ## Preflight — mandatory stop
272
+
273
+ ### 用户满足 (user-table properties)
274
+
275
+ 1. **`analysis-meta property get`** for each `columnName` — exact match required.
276
+ 2. **Never invent** — do not map natural language to property names without confirmation (e.g. “在中国” → `country`, not `nation`, until verified).
277
+ 3. **Never silently drop** — missing property → stop; do not create/update strategy.
278
+ 4. **Report** — name missing fields; run **`analysis-meta property list --table-type user`** and present available properties (`prop_name`, `prop_desc`, `select_type`); ask user to choose.
279
+
280
+ ```bash
281
+ ae-cli analysis-meta property get --project-id <pid> --table-type user --prop-name <prop_name>
282
+ ae-cli analysis-meta property list --project-id <pid> --table-type user
283
+ ae-cli analysis +load_filters --project_id <pid> --table_type user --quot <prop_name>
284
+ ```
285
+
286
+ Enum/`ftv` values must come from `+load_filters` or property metadata — never invent labels.
287
+
288
+ ### 用户行为 (events)
289
+
290
+ ```bash
291
+ ae-cli analysis-meta event list --project-id <pid>
292
+ ae-cli analysis-meta event get --project-id <pid> --event-name <event_name>
293
+ ```
294
+
295
+ Same stop/report rules if event name or event property is missing.
296
+
297
+ ---
298
+
299
+ ## Worked example A — 用户满足 + 用户行为 (full strategy)
300
+
301
+ **Natural language:**
302
+
303
+ - **用户满足:** (苹果用户 且 在中国) **或** (出生日期在 2000 年之后)
304
+ - **用户行为:** 最近 3 天登录 ≥ 2 次 **且** 最近 1 天购买 > 1 次
305
+ - **Relation:** 用户满足 **且** 用户行为
306
+
307
+ **Preflight (example project):** `device_brand`/`country`/`birthdate` exist; `device_brand` enum has `"苹果"`; `country` enum has `"中国"`; events `login`, `purchase` exist.
308
+
309
+ **UI mapping:**
310
+
311
+ ```
312
+ 用户满足 OR [ AND(苹果, 中国), birthdate≥2001-01-01 ]
313
+
314
+ 用户行为 AND [ login≥2 / 最近3天, purchase>1 / 最近1天 ]
315
+ ```
316
+
317
+ **`targetClusterQp`** (stringify for payload):
318
+
319
+ ```json
320
+ {
321
+ "totalCFilter": {
322
+ "relation": "1",
323
+ "filts": [
324
+ {
325
+ "relation": "0",
326
+ "filts": [
327
+ {
328
+ "filterType": "COMPOUND",
329
+ "relation": 1,
330
+ "filts": [
331
+ {
332
+ "conditionType": "user",
333
+ "userCondition": {
334
+ "calcuSymbol": "C00",
335
+ "columnName": "device_brand",
336
+ "columnDesc": "device_brand",
337
+ "columnType": "string",
338
+ "selectType": "string",
339
+ "tableType": "1",
340
+ "ftv": ["苹果"],
341
+ "timeRelative": "",
342
+ "timeUnit": ""
343
+ }
344
+ },
345
+ {
346
+ "conditionType": "user",
347
+ "userCondition": {
348
+ "calcuSymbol": "C00",
349
+ "columnName": "country",
350
+ "columnDesc": "country",
351
+ "columnType": "string",
352
+ "selectType": "string",
353
+ "tableType": "1",
354
+ "ftv": ["中国"],
355
+ "timeRelative": "",
356
+ "timeUnit": ""
357
+ }
358
+ }
359
+ ]
360
+ },
361
+ {
362
+ "conditionType": "user",
363
+ "userCondition": {
364
+ "calcuSymbol": "C030",
365
+ "columnName": "birthdate",
366
+ "columnDesc": "birthdate",
367
+ "columnType": "timestamp",
368
+ "selectType": "datetime",
369
+ "tableType": "1",
370
+ "ftv": ["2001-01-01 00:00:00"],
371
+ "timeRelative": "",
372
+ "timeUnit": ""
373
+ }
374
+ }
375
+ ]
376
+ },
377
+ {
378
+ "relation": "1",
379
+ "filts": [
380
+ {
381
+ "conditionType": "event",
382
+ "eventCondition": {
383
+ "eventName": "login",
384
+ "eventDesc": "login",
385
+ "eventType": "event",
386
+ "uceCalcuSymbol": "C030",
387
+ "num": "2",
388
+ "recentDay": "0-3",
389
+ "startTime": "",
390
+ "endTime": "",
391
+ "taPropQuota": {
392
+ "analysis": "A200",
393
+ "analysisDesc": "Count",
394
+ "quota": "",
395
+ "quotaDesc": "",
396
+ "analysisParams": ""
397
+ },
398
+ "filts": [],
399
+ "relation": 1
400
+ }
401
+ },
402
+ {
403
+ "conditionType": "event",
404
+ "eventCondition": {
405
+ "eventName": "purchase",
406
+ "eventDesc": "purchase",
407
+ "eventType": "event",
408
+ "uceCalcuSymbol": "C03",
409
+ "num": "1",
410
+ "recentDay": "0-1",
411
+ "startTime": "",
412
+ "endTime": "",
413
+ "taPropQuota": {
414
+ "analysis": "A200",
415
+ "analysisDesc": "Count",
416
+ "quota": "",
417
+ "quotaDesc": "",
418
+ "analysisParams": ""
419
+ },
420
+ "filts": [],
421
+ "relation": 1
422
+ }
423
+ }
424
+ ]
425
+ }
426
+ ]
427
+ },
428
+ "totalOutCFilter": {
429
+ "relation": "0",
430
+ "filts": []
431
+ }
432
+ }
433
+ ```
434
+
435
+ Notes:
436
+
437
+ - `"2000年之后"` interpreted as `birthdate >= 2001-01-01`; confirm with user if they mean inclusive of year 2000.
438
+ - `purchase > 1` → `C03` + `num: "1"`; `login ≥ 2` → `C030` + `num: "2"`.
439
+
440
+ ---
441
+
442
+ ## Worked example B — 用户满足 OR + 用户行为 with event filter
443
+
444
+ **Natural language:** (苹果设备 且 login 的 iOS>26) **或** 非苹果设备 — with login/iOS on **用户行为**.
445
+
446
+ **UI mapping:**
447
+
448
+ ```
449
+ 用户满足 OR [ AND(苹果), 非苹果 ]
450
+
451
+ 用户行为 login (os_version 匹配 iOS 主版本 > 26)
452
+ ```
453
+
454
+ Only **`filts[0]`** carries user attrs; **`filts[1]`** carries the event (with `eventCondition.filts[]` for `os_version`):
455
+
456
+ ```json
457
+ {
458
+ "totalCFilter": {
459
+ "relation": "1",
460
+ "filts": [
461
+ {
462
+ "relation": "0",
463
+ "filts": [
464
+ {
465
+ "filterType": "COMPOUND",
466
+ "relation": 1,
467
+ "filts": [
468
+ {
469
+ "conditionType": "user",
470
+ "userCondition": {
471
+ "calcuSymbol": "C00",
472
+ "columnName": "device_brand",
473
+ "columnDesc": "device_brand",
474
+ "columnType": "string",
475
+ "selectType": "string",
476
+ "tableType": "1",
477
+ "ftv": ["苹果"]
478
+ }
479
+ }
480
+ ]
481
+ },
482
+ {
483
+ "conditionType": "user",
484
+ "userCondition": {
485
+ "calcuSymbol": "C01",
486
+ "columnName": "device_brand",
487
+ "columnDesc": "device_brand",
488
+ "columnType": "string",
489
+ "selectType": "string",
490
+ "tableType": "1",
491
+ "ftv": ["苹果"]
492
+ }
493
+ }
494
+ ]
495
+ },
496
+ {
497
+ "relation": "1",
498
+ "filts": [
499
+ {
500
+ "conditionType": "event",
501
+ "eventCondition": {
502
+ "eventName": "login",
503
+ "eventDesc": "login",
504
+ "eventType": "event",
505
+ "uceCalcuSymbol": "C030",
506
+ "num": "1",
507
+ "recentDay": "0-3650",
508
+ "taPropQuota": {
509
+ "analysis": "A200",
510
+ "analysisDesc": "Count",
511
+ "quota": "",
512
+ "quotaDesc": "",
513
+ "analysisParams": ""
514
+ },
515
+ "filts": [
516
+ {
517
+ "calcuSymbol": "C11",
518
+ "columnName": "os_version",
519
+ "columnDesc": "os_version",
520
+ "columnType": "string",
521
+ "selectType": "string",
522
+ "tableType": "0",
523
+ "ftv": ["^(iOS )?(2[7-9]|[3-9][0-9])(\\.[0-9]+)*$"]
524
+ }
525
+ ],
526
+ "relation": 1
527
+ }
528
+ }
529
+ ]
530
+ }
531
+ ]
532
+ },
533
+ "totalOutCFilter": { "relation": "0", "filts": [] }
534
+ }
535
+ ```
536
+
537
+ ---
538
+
539
+ ## Worked example C — 用户满足 only
540
+
541
+ **Natural language:** `country = 中国`
542
+
543
+ ```json
544
+ {
545
+ "totalCFilter": {
546
+ "relation": "1",
547
+ "filts": [
548
+ {
549
+ "relation": "1",
550
+ "filts": [
551
+ {
552
+ "conditionType": "user",
553
+ "userCondition": {
554
+ "calcuSymbol": "C00",
555
+ "columnName": "country",
556
+ "columnDesc": "country",
557
+ "columnType": "string",
558
+ "selectType": "string",
559
+ "tableType": "1",
560
+ "ftv": ["中国"]
561
+ }
562
+ }
563
+ ]
564
+ }
565
+ ]
566
+ },
567
+ "totalOutCFilter": { "relation": "0", "filts": [] }
568
+ }
569
+ ```
570
+
571
+ ---
572
+
573
+ ## Common pitfalls
574
+
575
+ | Mistake | Why it fails |
576
+ |---|---|
577
+ | Put `conditionType:"event"` inside 用户满足 `COMPOUND` | UI/backend expect events only in `filts[1]`; structure breaks in editor |
578
+ | Only one top-level `filts` block when both user + event exist | `formatTriggerConditionFromQp` mis-parses user vs event |
579
+ | Guess `columnName` from Chinese description | Property may not exist; must preflight and list available props |
580
+ | Drop missing condition and continue | Violates mandatory stop; audience silently wrong |
581
+ | `A200` empty quota with `uceCalcuSymbol` other than `C030`/`C03` rules | Backend `invalid_preset_count_expression` |
582
+ | Invent enum values (`"Apple"` vs `"苹果"`) | Filter never matches real data |
583
+
584
+ ---
585
+
586
+ ## Existing cluster reference (exception path)
587
+
588
+ When the user supplies an existing `cluster_name`:
589
+
590
+ ```json
591
+ "targetClusterQp": "{\"totalCFilter\":{\"relation\":\"1\",\"filts\":[{\"relation\":\"1\",\"filts\":[{\"conditionType\":\"cluster\",\"clusterCondition\":{\"calcuSymbol\":\"C20\",\"columnName\":\"<existing_cluster_name>\",\"columnDesc\":\"<existing_cluster_name>\",\"columnType\":\"boolean\",\"selectType\":\"bool-s\",\"tableType\":\"2\",\"subTableType\":\"cluster_by_result\",\"specifiedClusterDate\":\"<YYYY-MM-DD>\",\"ftv\":[]}}]}]}}"
592
+ ```
593
+
594
+ Discover names: `ae-cli analysis user-cluster list --project-id <pid>`.
595
+
596
+ ---
597
+
598
+ ## Webhook constraints
599
+
600
+ - **Cannot** set both `envConfig` and `targetClusterType` on Webhook channels.
601
+ - Must set one of: user audience (`targetClusterType`) or environment audience (`envConfig`).
602
+ - Client channel may combine `envConfig` + user audience.
603
+
604
+ ---
605
+
606
+ ## Related surfaces (different rules)
607
+
608
+ | Surface | Default audience path |
609
+ |---|---|
610
+ | **Config strategy** (this doc) | Direct `targetClusterQp`; **no** new `user-cluster create` unless user asks for existing cluster |
611
+ | Task `save` | [`save-task.md`](save-task.md) |
612
+ | Flow `save` | [`save-flow.md`](save-flow.md) |
613
+ | Activity topic | [`activity-topic.md`](activity-topic.md) |
614
+
615
+ For reusable Analysis clusters, use ae-analysis [`user_cluster_create.md`](../../ae-analysis/references/user_cluster_create.md).
616
+
617
+ ---
618
+
619
+ ## Audience size estimate (预估人数)
620
+
621
+ **UI:** 策略编辑 → 目标受众 → **重新预估**
622
+ **Backend:** `POST /v1/hermes/config/strategy/predictEntityCount?projectId=<pid>`
623
+
624
+ Request body (`ConfigClusterPredictEntityReqDTO`):
625
+
626
+ | Field | Required | Notes |
627
+ |---|---|---|
628
+ | `requestId` | Yes | Client-generated UUID (UI uses `getUuid()`) |
629
+ | `zoneOffset` | Yes | Strategy timezone, e.g. `8.0` |
630
+ | `qp` | Yes | **`targetClusterQp` string** (mix QP JSON string, same as saved on strategy) |
631
+ | `strategyUuid` | No | Pass when refreshing an existing strategy; server persists `clusterUserNum` on strategy |
632
+
633
+ Response (`ConfigClusterPredictEntityResDTO`):
634
+
635
+ - `predictNumList[0].entityNum` — estimated user count
636
+ - `predictNumList[0].realAvailable` — whether count is within realtime/scheduled limits
637
+ - `refreshTime` — estimate timestamp
638
+
639
+ The UI formats the saved QP with `formatTriggerConditionForBack` before sending; when calling the API directly, pass the **same mix QP string** already stored in `targetClusterQp` (the backend shape in examples A/B/C above).
640
+
641
+ ### CLI
642
+
643
+ ```bash
644
+ ae-cli engage-scene strategy predict \
645
+ --project-id <pid> \
646
+ --qp '<targetClusterQp mix QP string>' \
647
+ --zone-offset 8 \
648
+ --strategy-uuid <optional_strategy_uuid>
649
+ ```
650
+
651
+ - `--qp`: same mix QP JSON string stored in `targetClusterQp` (see examples A/B/C above).
652
+ - `--zone-offset`: strategy timezone (match `tzOffset` on the strategy).
653
+ - `--strategy-uuid`: optional; when set, server persists `clusterUserNum` on the strategy (same as UI re-estimate on a saved draft).
654
+ - `--request-id`: optional; auto-generated when omitted.
655
+
656
+ Response: `data.entity_num` (count), `data.real_available`, `data.predict_num_list`, `data.refresh_time`.
657
+
658
+ Example using an existing strategy's saved QP:
659
+
660
+ ```bash
661
+ QP=$(ae-cli engage-scene strategy get --project-id 1 --config-id yx_0723_01 \
662
+ --strategy-uuid 4028f0716dfe0b3e5f992f82e19c3e74 \
663
+ --jq '.data.item.target_cluster_qp')
664
+
665
+ ae-cli engage-scene strategy predict \
666
+ --project-id 1 \
667
+ --qp "$QP" \
668
+ --zone-offset 8 \
669
+ --strategy-uuid 4028f0716dfe0b3e5f992f82e19c3e74
670
+ ```
671
+
672
+ Capability id: `engage-scene.strategy.predict` (gateway → `HermesConfigStrategyService.predictEntity`).
673
+
674
+ ### UI alternative
675
+
676
+ **UI:** 策略编辑 → 目标受众 → **重新预估** (same backend endpoint).
677
+
678
+ After UI or CLI predict with `--strategy-uuid`, `strategy get` returns `cluster_user_num` / `cluster_user_refresh_time`.
679
+
680
+ Do **not** guess counts from QP semantics alone — always run predict or read a prior `cluster_user_num`.