@thinkingai/ae-cli 1.0.1 → 1.0.15
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 +38 -64
- package/README.zh.md +203 -0
- package/dist/{auth-JXELJNDS.js → auth-4GAHTBVH.js} +2 -2
- package/dist/{auth-L3G3A74I.js → auth-U2GHFMFY.js} +20 -6
- package/dist/{chunk-OVQOK35G.js → chunk-EBFUVWIZ.js} +25 -6
- package/dist/{chunk-3GM5LJZR.js → chunk-OQ4XEG77.js} +7 -4
- package/dist/{chunk-JD5DXMKL.js → chunk-TJIMDNAU.js} +10 -8
- package/dist/{chunk-RJNLN3KQ.js → chunk-UK6HO5O5.js} +7 -6
- package/dist/{client-5QSQBBDB.js → client-HU63573O.js} +3 -3
- package/dist/{config-Q7J3Z7Z2.js → config-OLF7RBPM.js} +5 -5
- package/dist/index.js +18 -17
- package/dist/{raw-ZNVURYMR.js → raw-GDO4IWNW.js} +8 -6
- package/dist/{te-analysis-7NN3SY3I.js → te-analysis-ZDJXMWZY.js} +64 -26
- package/dist/{te-audience-P43BWMHM.js → te-audience-T5B52EEB.js} +65 -25
- package/dist/{te-common-H3IPTI2I.js → te-common-BPTXXTHQ.js} +11 -38
- package/dist/{community-GMALVSRF.js → te-community-FPB5LH56.js} +59 -59
- package/dist/{te-dataops-WCGDBJLF.js → te-dataops-2NUJVG47.js} +3 -28
- package/dist/{te-engage-UTRVNTGU.js → te-engage-K3EANZ5P.js} +502 -520
- package/dist/{te-meta-HGYNXVGF.js → te-meta-JJMV75KB.js} +88 -20
- package/package.json +9 -7
- package/skills/ae-analysis/SKILL.md +229 -0
- package/skills/{te-meta/references/batch-create-metadata.md → ae-analysis/references/batch_create_metadata.md} +5 -5
- package/skills/{te-meta/references/batch-edit-metadata.md → ae-analysis/references/batch_edit_metadata.md} +4 -4
- package/skills/{te-analysis/references/build-entity-details-sql.md → ae-analysis/references/build_entity_details_sql.md} +14 -14
- package/skills/{te-analysis/references/build-event-details-sql.md → ae-analysis/references/build_event_details_sql.md} +14 -14
- package/skills/{te-analysis/references/create-alert.md → ae-analysis/references/create_alert.md} +7 -7
- package/skills/{te-audience/references/create-cluster.md → ae-analysis/references/create_cluster.md} +26 -22
- package/skills/{te-analysis/references/create-dashboard.md → ae-analysis/references/create_dashboard.md} +5 -5
- package/skills/{te-meta/references/create-metric.md → ae-analysis/references/create_metric.md} +16 -16
- package/skills/{te-analysis/references/create-or-update-dashboard-note.md → ae-analysis/references/create_or_update_dashboard_note.md} +5 -5
- package/skills/{te-meta/references/create-project-mark-time.md → ae-analysis/references/create_project_mark_time.md} +5 -5
- package/skills/{te-analysis/references/create-public-access-link.md → ae-analysis/references/create_public_access_link.md} +5 -5
- package/skills/{te-analysis/references/create-report.md → ae-analysis/references/create_report.md} +14 -14
- package/skills/{te-analysis/references/create-result-cluster.md → ae-analysis/references/create_result_cluster.md} +8 -8
- package/skills/{te-audience/references/create-tag.md → ae-analysis/references/create_tag.md} +18 -17
- package/skills/{te-meta/references/create-virtual-event.md → ae-analysis/references/create_virtual_event.md} +14 -14
- package/skills/{te-meta/references/create-virtual-property.md → ae-analysis/references/create_virtual_property.md} +11 -11
- package/skills/{te-meta/references/delete-project-mark-times.md → ae-analysis/references/delete_project_mark_times.md} +4 -4
- package/skills/{te-meta/references/delete-track-items.md → ae-analysis/references/delete_track_items.md} +4 -4
- package/skills/{te-analysis/references/drilldown-user-events.md → ae-analysis/references/drilldown_user_events.md} +11 -11
- package/skills/{te-analysis/references/drilldown-users.md → ae-analysis/references/drilldown_users.md} +12 -9
- package/skills/ae-analysis/references/generate_track_program.md +51 -0
- package/skills/ae-analysis/references/generate_track_sdk_sample.md +43 -0
- package/skills/{te-analysis/references/get-alert.md → ae-analysis/references/get_alert.md} +4 -4
- package/skills/{te-analysis/references/get-alert-definition-schema.md → ae-analysis/references/get_alert_definition_schema.md} +4 -4
- package/skills/ae-analysis/references/get_analysis_query_schema.md +61 -0
- package/skills/ae-analysis/references/get_cluster_definition_schema.md +53 -0
- package/skills/ae-analysis/references/get_clusters_by_name.md +69 -0
- package/skills/{te-analysis/references/get-filter-schema.md → ae-analysis/references/get_filter_schema.md} +4 -4
- package/skills/{te-analysis/references/get-groupby-schema.md → ae-analysis/references/get_groupby_schema.md} +4 -4
- package/skills/{te-meta/references/get-metric.md → ae-analysis/references/get_metric.md} +4 -4
- package/skills/{te-meta/references/get-project-config.md → ae-analysis/references/get_project_config.md} +4 -4
- package/skills/{te-analysis/references/get-report-definition.md → ae-analysis/references/get_report_definition.md} +4 -4
- package/skills/{te-common/references/get-resource-url.md → ae-analysis/references/get_resource_url.md} +7 -7
- package/skills/{te-analysis/references/get-table-columns.md → ae-analysis/references/get_table_columns.md} +4 -4
- package/skills/ae-analysis/references/get_tag_definition_schema.md +49 -0
- package/skills/ae-analysis/references/get_tags_by_name.md +69 -0
- package/skills/{te-meta/references/get-track-program.md → ae-analysis/references/get_track_program.md} +4 -4
- package/skills/{te-analysis/references/list-alerts.md → ae-analysis/references/list_alerts.md} +8 -5
- package/skills/{te-audience/references/list-cluster-members.md → ae-analysis/references/list_cluster_members.md} +13 -6
- package/skills/{te-audience/references/list-clusters.md → ae-analysis/references/list_clusters.md} +12 -6
- package/skills/{te-analysis/references/list-dashboards.md → ae-analysis/references/list_dashboards.md} +10 -6
- package/skills/{te-meta/references/list-entities.md → ae-analysis/references/list_entities.md} +12 -5
- package/skills/{te-meta/references/list-events.md → ae-analysis/references/list_events.md} +10 -7
- package/skills/ae-analysis/references/list_metrics.md +41 -0
- package/skills/ae-analysis/references/list_project_mark_times.md +42 -0
- package/skills/{te-meta/references/list-project-users.md → ae-analysis/references/list_project_users.md} +4 -4
- package/skills/{te-common/references/list-projects.md → ae-analysis/references/list_projects.md} +9 -7
- package/skills/{te-meta/references/list-properties.md → ae-analysis/references/list_properties.md} +11 -6
- package/skills/ae-analysis/references/list_public_access_links.md +41 -0
- package/skills/{te-analysis/references/list-reports.md → ae-analysis/references/list_reports.md} +10 -6
- package/skills/{te-audience/references/list-tag-members.md → ae-analysis/references/list_tag_members.md} +13 -6
- package/skills/{te-audience/references/list-tags.md → ae-analysis/references/list_tags.md} +12 -6
- package/skills/{te-analysis/references/load-filters.md → ae-analysis/references/load_filters.md} +5 -5
- package/skills/{te-analysis/references/query-adhoc.md → ae-analysis/references/query_adhoc.md} +19 -14
- package/skills/{te-analysis/references/query-dashboard-detail.md → ae-analysis/references/query_dashboard_detail.md} +4 -4
- package/skills/{te-analysis/references/query-dashboard-report-data.md → ae-analysis/references/query_dashboard_report_data.md} +13 -13
- package/skills/{te-analysis/references/query-entity-details.md → ae-analysis/references/query_entity_details.md} +15 -15
- package/skills/{te-analysis/references/query-event-details.md → ae-analysis/references/query_event_details.md} +17 -17
- package/skills/{te-analysis/references/query-report-data.md → ae-analysis/references/query_report_data.md} +16 -16
- package/skills/{te-audience/references/refresh-cluster.md → ae-analysis/references/refresh_cluster.md} +4 -4
- package/skills/{te-audience/references/refresh-tag.md → ae-analysis/references/refresh_tag.md} +4 -4
- package/skills/{te-meta/references/save-track-items.md → ae-analysis/references/save_track_items.md} +4 -4
- package/skills/{te-analysis/references/update-alert.md → ae-analysis/references/update_alert.md} +7 -7
- package/skills/{te-audience/references/update-cluster.md → ae-analysis/references/update_cluster.md} +17 -15
- package/skills/{te-analysis/references/update-dashboard.md → ae-analysis/references/update_dashboard.md} +5 -5
- package/skills/{te-meta/references/update-metric.md → ae-analysis/references/update_metric.md} +14 -14
- package/skills/{te-meta/references/update-project-mark-time.md → ae-analysis/references/update_project_mark_time.md} +5 -5
- package/skills/{te-analysis/references/update-public-access-link.md → ae-analysis/references/update_public_access_link.md} +5 -5
- package/skills/{te-audience/references/update-tag.md → ae-analysis/references/update_tag.md} +17 -16
- package/skills/ae-community/SKILL.md +305 -0
- package/skills/ae-community/references/community-activity-analysis.md +67 -0
- package/skills/ae-community/references/community-analyzing-official-content.md +71 -0
- package/skills/ae-community/references/community-analyzing-theme-comment.md +123 -0
- package/skills/ae-community/references/community-character-analysis.md +70 -0
- package/skills/ae-community/references/community-daily-report.md +84 -0
- package/skills/ae-community/references/community-hottopic-insight.md +113 -0
- package/skills/ae-community/references/community-weekly-report.md +84 -0
- package/skills/ae-community/references/get_channel_info.md +20 -0
- package/skills/ae-community/references/get_comment_tag_analysis.md +29 -0
- package/skills/ae-community/references/get_comments_summary.md +32 -0
- package/skills/ae-community/references/get_corpus_tags.md +20 -0
- package/skills/ae-community/references/get_daily_summary.md +22 -0
- package/skills/ae-community/references/get_hot_topics.md +25 -0
- package/skills/ae-community/references/get_livestream_analysis.md +22 -0
- package/skills/ae-community/references/get_livestream_detail.md +33 -0
- package/skills/ae-community/references/get_livestream_list.md +25 -0
- package/skills/ae-community/references/get_livestream_overview.md +24 -0
- package/skills/ae-community/references/get_livestream_room_metrics.md +25 -0
- package/skills/ae-community/references/get_livestream_rooms.md +25 -0
- package/skills/ae-community/references/get_overview_metrics.md +25 -0
- package/skills/ae-community/references/get_post_detail.md +37 -0
- package/skills/ae-community/references/get_risk_content.md +42 -0
- package/skills/ae-community/references/get_sentiment_overview.md +33 -0
- package/skills/ae-community/references/get_tag_trends.md +27 -0
- package/skills/ae-community/references/get_topic_detail.md +26 -0
- package/skills/ae-community/references/search_posts.md +47 -0
- package/skills/ae-dataops/SKILL.md +706 -0
- package/skills/ae-dataops/references/dataops-flow-create.md +163 -0
- package/skills/ae-dataops/references/dataops-flow-monitor.md +118 -0
- package/skills/ae-dataops/references/dataops-integration.md +251 -0
- package/skills/ae-dataops/references/dataops-query.md +111 -0
- package/skills/ae-dataops/references/dataops-table.md +122 -0
- package/skills/ae-engage/SKILL.md +311 -0
- package/skills/ae-engage/references/add-approver.md +24 -0
- package/skills/ae-engage/references/add-channel.md +74 -0
- package/skills/ae-engage/references/approver-list.md +19 -0
- package/skills/ae-engage/references/cancel-query-by-request-id.md +23 -0
- package/skills/ae-engage/references/channel-detail.md +52 -0
- package/skills/ae-engage/references/channel-list.md +41 -0
- package/skills/ae-engage/references/config-channel-detail.md +32 -0
- package/skills/ae-engage/references/config-channel-list.md +27 -0
- package/skills/ae-engage/references/config-item-analysis-report.md +34 -0
- package/skills/ae-engage/references/config-item-detail.md +30 -0
- package/skills/ae-engage/references/config-item-list.md +19 -0
- package/skills/ae-engage/references/config-item-strategy-comparison.md +25 -0
- package/skills/ae-engage/references/config-item-trigger-report.md +42 -0
- package/skills/ae-engage/references/copy-config-template.md +29 -0
- package/skills/ae-engage/references/delete-channel.md +24 -0
- package/skills/ae-engage/references/delete-config-channel.md +24 -0
- package/skills/ae-engage/references/delete-config-item.md +25 -0
- package/skills/ae-engage/references/delete-flow.md +24 -0
- package/skills/ae-engage/references/flow-ab-split-node-report.md +54 -0
- package/skills/ae-engage/references/flow-detail.md +79 -0
- package/skills/ae-engage/references/flow-list.md +19 -0
- package/skills/ae-engage/references/flow-node-config-schema.md +44 -0
- package/skills/ae-engage/references/flow-node-detail-report.md +55 -0
- package/skills/ae-engage/references/flow-node-overview-report.md +52 -0
- package/skills/ae-engage/references/flow-process-report.md +59 -0
- package/skills/ae-engage/references/manage-flow.md +94 -0
- package/skills/ae-engage/references/manage-strategy.md +74 -0
- package/skills/ae-engage/references/manage-task.md +37 -0
- package/skills/ae-engage/references/modify-flow-base-info.md +27 -0
- package/skills/ae-engage/references/save-flow.md +871 -0
- package/skills/ae-engage/references/strategy-detail.md +73 -0
- package/skills/ae-engage/references/strategy-list.md +21 -0
- package/skills/ae-engage/references/task-data-detail.md +74 -0
- package/skills/ae-engage/references/task-data-overview.md +42 -0
- package/skills/ae-engage/references/task-detail.md +61 -0
- package/skills/ae-engage/references/task-experiment-report.md +45 -0
- package/skills/ae-engage/references/task-list.md +91 -0
- package/skills/ae-engage/references/task-metric-detail.md +50 -0
- package/skills/ae-engage/references/task-stats.md +89 -0
- package/skills/ae-engage/references/update-channel-status.md +32 -0
- package/skills/ae-engage/references/update-config-channel-status.md +32 -0
- package/skills/ae-engage/references/validate-flow-node-config.md +52 -0
- package/skills/ae-engage/references/whitelist-list.md +19 -0
- package/skills/te-analysis/SKILL.md +0 -107
- package/skills/te-analysis/references/get-analysis-query-schema.md +0 -36
- package/skills/te-analysis/references/list-public-access-links.md +0 -31
- package/skills/te-audience/SKILL.md +0 -63
- package/skills/te-audience/references/get-cluster-definition-schema.md +0 -37
- package/skills/te-audience/references/get-clusters-by-name.md +0 -32
- package/skills/te-audience/references/get-tag-definition-schema.md +0 -32
- package/skills/te-audience/references/get-tags-by-name.md +0 -32
- package/skills/te-common/SKILL.md +0 -135
- package/skills/te-community/SKILL.md +0 -133
- package/skills/te-community/references/community-activity-analysis.md +0 -68
- package/skills/te-community/references/community-analyzing-official-content.md +0 -72
- package/skills/te-community/references/community-analyzing-theme-comment.md +0 -124
- package/skills/te-community/references/community-character-analysis.md +0 -71
- package/skills/te-community/references/community-daily-report.md +0 -82
- package/skills/te-community/references/community-hottopic-insight.md +0 -120
- package/skills/te-community/references/community-release-analysis.md +0 -79
- package/skills/te-community/references/community-weekly-report.md +0 -84
- package/skills/te-community/references/get_channel_info.md +0 -21
- package/skills/te-community/references/get_comment_tag_analysis.md +0 -30
- package/skills/te-community/references/get_comments_summary.md +0 -33
- package/skills/te-community/references/get_corpus_tags.md +0 -21
- package/skills/te-community/references/get_daily_summary.md +0 -23
- package/skills/te-community/references/get_hot_topics.md +0 -26
- package/skills/te-community/references/get_livestream_analysis.md +0 -23
- package/skills/te-community/references/get_livestream_detail.md +0 -34
- package/skills/te-community/references/get_livestream_list.md +0 -26
- package/skills/te-community/references/get_livestream_overview.md +0 -25
- package/skills/te-community/references/get_livestream_room_metrics.md +0 -26
- package/skills/te-community/references/get_livestream_rooms.md +0 -26
- package/skills/te-community/references/get_overview_metrics.md +0 -26
- package/skills/te-community/references/get_post_detail.md +0 -38
- package/skills/te-community/references/get_risk_content.md +0 -43
- package/skills/te-community/references/get_sentiment_overview.md +0 -34
- package/skills/te-community/references/get_tag_trends.md +0 -28
- package/skills/te-community/references/get_topic_detail.md +0 -27
- package/skills/te-community/references/search_posts.md +0 -48
- package/skills/te-dataops/SKILL.md +0 -645
- package/skills/te-dataops/references/dataops-flow-create.md +0 -163
- package/skills/te-dataops/references/dataops-flow-monitor.md +0 -118
- package/skills/te-dataops/references/dataops-integration.md +0 -246
- package/skills/te-dataops/references/dataops-operations.md +0 -107
- package/skills/te-dataops/references/dataops-query.md +0 -111
- package/skills/te-dataops/references/dataops-table.md +0 -122
- package/skills/te-engage/SKILL.md +0 -211
- package/skills/te-engage/references/add-approver.md +0 -24
- package/skills/te-engage/references/add-channel.md +0 -74
- package/skills/te-engage/references/approver-list.md +0 -19
- package/skills/te-engage/references/cancel-query-by-request-id.md +0 -23
- package/skills/te-engage/references/channel-detail.md +0 -52
- package/skills/te-engage/references/channel-list.md +0 -41
- package/skills/te-engage/references/config-channel-detail.md +0 -32
- package/skills/te-engage/references/config-channel-list.md +0 -27
- package/skills/te-engage/references/config-item-analysis-report.md +0 -34
- package/skills/te-engage/references/config-item-detail.md +0 -30
- package/skills/te-engage/references/config-item-list.md +0 -19
- package/skills/te-engage/references/config-item-strategy-comparison.md +0 -25
- package/skills/te-engage/references/config-item-trigger-report.md +0 -42
- package/skills/te-engage/references/copy-config-template.md +0 -29
- package/skills/te-engage/references/delete-channel.md +0 -24
- package/skills/te-engage/references/delete-config-channel.md +0 -24
- package/skills/te-engage/references/delete-config-item.md +0 -25
- package/skills/te-engage/references/delete-flow.md +0 -24
- package/skills/te-engage/references/flow-ab-split-node-report.md +0 -54
- package/skills/te-engage/references/flow-detail.md +0 -79
- package/skills/te-engage/references/flow-list.md +0 -19
- package/skills/te-engage/references/flow-node-config-schema.md +0 -44
- package/skills/te-engage/references/flow-node-detail-report.md +0 -55
- package/skills/te-engage/references/flow-node-overview-report.md +0 -52
- package/skills/te-engage/references/flow-process-report.md +0 -59
- package/skills/te-engage/references/manage-flow.md +0 -94
- package/skills/te-engage/references/manage-strategy.md +0 -74
- package/skills/te-engage/references/manage-task.md +0 -37
- package/skills/te-engage/references/modify-flow-base-info.md +0 -27
- package/skills/te-engage/references/save-flow.md +0 -870
- package/skills/te-engage/references/strategy-detail.md +0 -73
- package/skills/te-engage/references/strategy-list.md +0 -21
- package/skills/te-engage/references/task-data-detail.md +0 -81
- package/skills/te-engage/references/task-data-overview.md +0 -48
- package/skills/te-engage/references/task-detail.md +0 -61
- package/skills/te-engage/references/task-experiment-report.md +0 -51
- package/skills/te-engage/references/task-list.md +0 -91
- package/skills/te-engage/references/task-metric-detail.md +0 -56
- package/skills/te-engage/references/task-stats.md +0 -89
- package/skills/te-engage/references/update-channel-status.md +0 -32
- package/skills/te-engage/references/update-config-channel-status.md +0 -32
- package/skills/te-engage/references/validate-flow-node-config.md +0 -52
- package/skills/te-engage/references/whitelist-list.md +0 -19
- package/skills/te-meta/SKILL.md +0 -71
- package/skills/te-meta/references/list-metrics.md +0 -33
- package/skills/te-meta/references/list-project-mark-times.md +0 -33
- package/skills/te-shared/SKILL.md +0 -115
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
# ae-engage `+save_flow`
|
|
2
|
+
|
|
3
|
+
Create or update a flow canvas draft.
|
|
4
|
+
|
|
5
|
+
Mapped command: `ae-cli engage +save_flow`
|
|
6
|
+
|
|
7
|
+
This document is not only meant to explain the `save_flow` interface itself. It provides a complete path **from user requirements to CLI arguments**:
|
|
8
|
+
|
|
9
|
+
1. Identify intent first
|
|
10
|
+
2. Then map the intent to the flow canvas `req`
|
|
11
|
+
3. Finally submit through the CLI
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. General Principles
|
|
16
|
+
|
|
17
|
+
`+save_flow` does not accept natural language or vague business descriptions directly. It accepts the **final flow canvas request payload that is ready to submit**.
|
|
18
|
+
|
|
19
|
+
Therefore, you must first organize user requirements into a unified intermediate intent structure, and then generate the payload according to the mapping rules:
|
|
20
|
+
|
|
21
|
+
- `flowName`
|
|
22
|
+
- `flowDesc`
|
|
23
|
+
- `nodeList`
|
|
24
|
+
- `edgeList`
|
|
25
|
+
- and optional `groupId`、`tzOffset`、`flowUuid`、`parentFlowUuid`、`versionType`
|
|
26
|
+
|
|
27
|
+
Then call the CLI:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ae-cli engage +save_flow --project_id <projectId> --req '<req-json>'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 2. Workflow
|
|
36
|
+
|
|
37
|
+
Use the following five-step workflow:
|
|
38
|
+
|
|
39
|
+
1. Identify the flow intent from the user input and produce a unified intent JSON.
|
|
40
|
+
2. Run `ae-cli analysis_audience +get_cluster_definition_schema --cluster_type condition` to obtain the condition cluster definition schema for assembling condition-related fields later.
|
|
41
|
+
3. Run `ae-cli engage +channel_list --project_id <projectId>` to get the available channels in the project and match real `channelId` values for touchpoint nodes.
|
|
42
|
+
4. Map the intent JSON to the final `req`: `flowName`, `flowDesc`, `nodeList`, and `edgeList`.
|
|
43
|
+
5. Run `ae-cli engage +save_flow --project_id <projectId> --req '<req-json>'` to submit.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. Step One: Intent Identification
|
|
48
|
+
|
|
49
|
+
### 3.1 Information That Must Be Confirmed First
|
|
50
|
+
|
|
51
|
+
Before generating any `req`, confirm at least these four categories of information:
|
|
52
|
+
|
|
53
|
+
| Item | Description |
|
|
54
|
+
|---|---|
|
|
55
|
+
| business scenario | What kind of flow this is, for example new-user activation, churn win-back, or paid conversion |
|
|
56
|
+
| target users | Who can enter the flow, for example users inactive for the last 14 days or users registered today |
|
|
57
|
+
| touchpoint method | Which channel will be used for outreach, for example Push, WeChat subscription, or Webhook |
|
|
58
|
+
| branching conditions | Whether grouped handling is needed; if so, which conditions define the groups |
|
|
59
|
+
|
|
60
|
+
If any of these four categories is missing, do not build `req` directly.
|
|
61
|
+
|
|
62
|
+
### 3.2 Intent Output Format
|
|
63
|
+
|
|
64
|
+
First organize the user requirement into the following intent JSON. This JSON is an intermediate representation, not the final `save_flow.req`.
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"flow_type": "<string>",
|
|
69
|
+
"flow_name": "<string>",
|
|
70
|
+
"flow_desc": "<string>",
|
|
71
|
+
"entry": {
|
|
72
|
+
"type": "<single_trigger|repeat_trigger|event_trigger>",
|
|
73
|
+
"segment": "<string|null>",
|
|
74
|
+
"schedule": "<string|null>",
|
|
75
|
+
"start_date": "<YYYY-MM-DD|YYYY-MM-DD HH:mm|null>",
|
|
76
|
+
"end_date": "<YYYY-MM-DD|YYYY-MM-DD HH:mm|null>",
|
|
77
|
+
"trigger_event": {
|
|
78
|
+
"event": "<string|null>",
|
|
79
|
+
"op": "<string|null>",
|
|
80
|
+
"count": "<number|null>",
|
|
81
|
+
"property_filter": "<object|null>",
|
|
82
|
+
"time_window": "<string|null>"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"nodes": [
|
|
86
|
+
{
|
|
87
|
+
"nid": "n1",
|
|
88
|
+
"node_type": "<split|judge|action|wait|end>",
|
|
89
|
+
"type": "<specific semantic node type>",
|
|
90
|
+
"name": "<string|null>",
|
|
91
|
+
"content": "<string|null>",
|
|
92
|
+
"channel_name": "<string|null>",
|
|
93
|
+
"languages": ["default"],
|
|
94
|
+
"condition": "<object|null>",
|
|
95
|
+
"event": "<object|null>",
|
|
96
|
+
"wait_time": "<string|null>",
|
|
97
|
+
"duration": "<string|null>",
|
|
98
|
+
"split_flow_type": "<1|2|null>",
|
|
99
|
+
"branches": [
|
|
100
|
+
{
|
|
101
|
+
"bid": "b1",
|
|
102
|
+
"label": "<string>",
|
|
103
|
+
"condition": "<object|null>",
|
|
104
|
+
"time_limit": "<string|null>",
|
|
105
|
+
"percentage": "<number|null>"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"edges": [
|
|
111
|
+
{
|
|
112
|
+
"source": "n1",
|
|
113
|
+
"target": "n2",
|
|
114
|
+
"branch": "<branch label|null>"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3.3 Field Meaning
|
|
121
|
+
|
|
122
|
+
- `entry`
|
|
123
|
+
Describes how users enter the flow.
|
|
124
|
+
- `nodes`
|
|
125
|
+
Describes business-semantic nodes; they are not yet final canvas nodes.
|
|
126
|
+
- `edges`
|
|
127
|
+
Describes the connection relationships at the business-semantics level.
|
|
128
|
+
- `channel_name`
|
|
129
|
+
Keep it as a semantic field first, then match a real `channelId` from the project channel list later.
|
|
130
|
+
- `branches`
|
|
131
|
+
Only describes branch semantics; later it will be materialized into `node.config.branchList` and `edge.sourceBranchId`.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 4. Step Two: Required CLI Queries
|
|
136
|
+
|
|
137
|
+
### 4.1 Query the Cluster Definition Schema
|
|
138
|
+
|
|
139
|
+
Run:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
ae-cli analysis_audience +get_cluster_definition_schema --cluster_type condition
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Purpose:
|
|
146
|
+
- Prepare the basis for building QP for condition nodes, audience nodes, and entry nodes
|
|
147
|
+
- Help generate `targetClusterQp`
|
|
148
|
+
- Help generate `triggerRule.events`
|
|
149
|
+
|
|
150
|
+
This step does not return final nodes directly. It provides the rule foundation for expressing conditions as QP or event conditions.
|
|
151
|
+
|
|
152
|
+
### 4.2 Query Project Channels
|
|
153
|
+
|
|
154
|
+
Run:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
ae-cli engage +channel_list --project_id <projectId>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Purpose:
|
|
161
|
+
- Get the available channels in the project
|
|
162
|
+
- Match a real `channelId` for touchpoint nodes based on `channel_name` in the intent
|
|
163
|
+
- Determine whether the node should be `message_push`, `wechat_push`, or `webhook_push` based on the channel type
|
|
164
|
+
|
|
165
|
+
If `channel_name` does not have an exact match, use this priority:
|
|
166
|
+
|
|
167
|
+
1. exact name match
|
|
168
|
+
2. name keyword match
|
|
169
|
+
3. fallback match by node type and channel type
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 5. Step Three: Map the Intent to `req`
|
|
174
|
+
|
|
175
|
+
### 5.1 Top-Level `req` Structure
|
|
176
|
+
|
|
177
|
+
The object passed to `--req` should have the following structure:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"flowName": "<string>",
|
|
182
|
+
"flowDesc": "<string>",
|
|
183
|
+
"groupId": 0,
|
|
184
|
+
"tzOffset": 8,
|
|
185
|
+
"flowUuid": "<string, optional>",
|
|
186
|
+
"parentFlowUuid": "<string, optional>",
|
|
187
|
+
"versionType": 1,
|
|
188
|
+
"nodeList": [],
|
|
189
|
+
"edgeList": []
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Notes:
|
|
194
|
+
- `projectId` does not need to be written into `--req` manually; the CLI injects it from `--project_id`
|
|
195
|
+
- `flowUuid` and `parentFlowUuid` are mutually exclusive
|
|
196
|
+
- When creating a new draft, neither of these fields should be provided
|
|
197
|
+
|
|
198
|
+
### 5.2 Sources of Top-Level Fields
|
|
199
|
+
|
|
200
|
+
| `req` Field | Source |
|
|
201
|
+
|---|---|
|
|
202
|
+
| `flowName` | Intent field `flow_name` |
|
|
203
|
+
| `flowDesc` | Intent field `flow_desc`; use an empty string or a short description if absent |
|
|
204
|
+
| `groupId` | Default `0`, unless the business requirement specifies a group |
|
|
205
|
+
| `tzOffset` | User timezone or project default timezone; a common value is `8` |
|
|
206
|
+
| `nodeList` | Generated from intent `entry` plus `nodes` |
|
|
207
|
+
| `edgeList` | Generated from intent `edges` and branch structure |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 6. Step Four: Map Intent Nodes to Canvas Nodes
|
|
212
|
+
|
|
213
|
+
### 6.1 Entry Node Mapping
|
|
214
|
+
|
|
215
|
+
| Intent `entry.type` | Canvas node `type` |
|
|
216
|
+
|---|---|
|
|
217
|
+
| `single_trigger` | `single_trigger` |
|
|
218
|
+
| `repeat_trigger` | `repeat_trigger` |
|
|
219
|
+
| `event_trigger` | `event_trigger` |
|
|
220
|
+
|
|
221
|
+
The entry node must always be the only entry node in `nodeList`.
|
|
222
|
+
|
|
223
|
+
### 6.2 Business Node Mapping
|
|
224
|
+
|
|
225
|
+
| Intent-node semantic meaning | Canvas node `type` |
|
|
226
|
+
|---|---|
|
|
227
|
+
| Behavioral split | `event_split_flow` |
|
|
228
|
+
| Feature split | `feature_split_flow` |
|
|
229
|
+
| A/B split | `ab_split_flow` |
|
|
230
|
+
| Behavioral judgment | `event_judge` |
|
|
231
|
+
| Feature judgment | `feature_judge` |
|
|
232
|
+
| Push touchpoint | `message_push` |
|
|
233
|
+
| WeChat touchpoint | `wechat_push` |
|
|
234
|
+
| Webhook / other external touchpoint | `webhook_push` |
|
|
235
|
+
| Wait | `time_control` |
|
|
236
|
+
| End | `exit_flow` |
|
|
237
|
+
|
|
238
|
+
### 6.3 Condition Field Mapping
|
|
239
|
+
|
|
240
|
+
Condition-related semantics cannot be copied into `req` as-is. They must be materialized in the following way:
|
|
241
|
+
|
|
242
|
+
| Semantic type | Target field |
|
|
243
|
+
|---|---|
|
|
244
|
+
| Audience segmentation condition | `targetClusterQp` |
|
|
245
|
+
| Feature judgment condition | `targetClusterQp` |
|
|
246
|
+
| Feature split branch condition | `targetClusterQp` |
|
|
247
|
+
| Event trigger condition | `triggerRule[].events[]` |
|
|
248
|
+
| Behavioral judgment condition | `triggerRule[].events[]` |
|
|
249
|
+
| Behavioral split branch condition | `triggerRule[].events[]` |
|
|
250
|
+
|
|
251
|
+
In short:
|
|
252
|
+
- Conditions that judge by audience or property usually map to `targetClusterQp`
|
|
253
|
+
- Conditions that judge whether an event happened, or how many times it happened, usually map to `triggerRule.events`
|
|
254
|
+
|
|
255
|
+
### 6.4 Touchpoint Node Mapping
|
|
256
|
+
|
|
257
|
+
These fields inside action-semantic nodes:
|
|
258
|
+
|
|
259
|
+
- `channel_name`
|
|
260
|
+
- `content`
|
|
261
|
+
- `languages`
|
|
262
|
+
|
|
263
|
+
need to be materialized into the push-node `config`:
|
|
264
|
+
|
|
265
|
+
- `channel_name` -> match to a real `channelId`
|
|
266
|
+
- `content` -> place into `contentList`
|
|
267
|
+
- `languages` -> determine whether multilingual `contentList` entries should be generated
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 7. Step Five: How to Build `nodeList`
|
|
272
|
+
|
|
273
|
+
Each item in `nodeList` has the following structure:
|
|
274
|
+
|
|
275
|
+
| Field | Type | Required | Description |
|
|
276
|
+
|---|---|---|---|
|
|
277
|
+
| `id` | string | Yes | Unique node ID within the request |
|
|
278
|
+
| `name` | string | Yes | Display name of the node |
|
|
279
|
+
| `type` | string | Yes | Node type |
|
|
280
|
+
| `config` | string | Yes | **JSON string** whose top level must be a JSON object |
|
|
281
|
+
| `desc` | string | No | Node description |
|
|
282
|
+
|
|
283
|
+
### 7.1 Most Important Rules
|
|
284
|
+
|
|
285
|
+
1. `config` must be a string, not an object.
|
|
286
|
+
2. `node.id` must be unique.
|
|
287
|
+
3. Any `branchId` later referenced by `edge.sourceBranchId` in split or judgment nodes must be defined in `config` first.
|
|
288
|
+
4. Every path must eventually end at `exit_flow`.
|
|
289
|
+
|
|
290
|
+
### 7.2 Common Node Types
|
|
291
|
+
|
|
292
|
+
- `single_trigger`
|
|
293
|
+
- `repeat_trigger`
|
|
294
|
+
- `event_trigger`
|
|
295
|
+
- `event_split_flow`
|
|
296
|
+
- `feature_split_flow`
|
|
297
|
+
- `ab_split_flow`
|
|
298
|
+
- `event_judge`
|
|
299
|
+
- `feature_judge`
|
|
300
|
+
- `message_push`
|
|
301
|
+
- `wechat_push`
|
|
302
|
+
- `webhook_push`
|
|
303
|
+
- `time_control`
|
|
304
|
+
- `exit_flow`
|
|
305
|
+
|
|
306
|
+
### 7.3 Example: Simplest Node
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"id": "node_1",
|
|
311
|
+
"name": "One-Time Scheduled Entry",
|
|
312
|
+
"type": "single_trigger",
|
|
313
|
+
"config": {
|
|
314
|
+
"triggerTime": "2026-04-10 06:35",
|
|
315
|
+
"flowEndDate": "2026-04-11 06:35"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 7.4 Common `config` Templates
|
|
321
|
+
|
|
322
|
+
The templates below are the most important references when you assemble `req` directly. Build them as objects first, then wrap them with `JSON.stringify` before placing them into `nodeList[].config`.
|
|
323
|
+
|
|
324
|
+
#### `repeat_trigger`
|
|
325
|
+
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"targetUserType": 1,
|
|
329
|
+
"startDate": "<YYYY-MM-DD>",
|
|
330
|
+
"endDate": "<YYYY-MM-DD>",
|
|
331
|
+
"flowEndDate": "<YYYY-MM-DD HH:mm>",
|
|
332
|
+
"crontab": "0 00 09 * * ?",
|
|
333
|
+
"entryControlLimits": {
|
|
334
|
+
"enableMultEntry": false,
|
|
335
|
+
"disableConcurrentEntry": false
|
|
336
|
+
},
|
|
337
|
+
"targetClusterName": null,
|
|
338
|
+
"clusterPredictCount": null,
|
|
339
|
+
"clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>",
|
|
340
|
+
"targetClusterQp": "<JSON.stringify(qp)>"
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Rules:
|
|
345
|
+
- `entry.segment` -> `targetClusterQp`
|
|
346
|
+
- `entry.schedule` -> `crontab`
|
|
347
|
+
- Common default value: `0 00 09 * * ?`
|
|
348
|
+
|
|
349
|
+
#### `event_trigger`
|
|
350
|
+
|
|
351
|
+
```json
|
|
352
|
+
{
|
|
353
|
+
"triggerType": 3,
|
|
354
|
+
"targetUserType": 1,
|
|
355
|
+
"realtime": 0,
|
|
356
|
+
"clusterRefresh": 12,
|
|
357
|
+
"clusterRefreshTime": null,
|
|
358
|
+
"startDate": "<YYYY-MM-DD HH:mm>",
|
|
359
|
+
"endDate": "<YYYY-MM-DD HH:mm>",
|
|
360
|
+
"flowEndDate": "<YYYY-MM-DD HH:mm>",
|
|
361
|
+
"clusterPredictCount": null,
|
|
362
|
+
"clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>",
|
|
363
|
+
"triggerRule": [
|
|
364
|
+
{
|
|
365
|
+
"periodStart": "<startDate>",
|
|
366
|
+
"periodEnd": "<endDate>",
|
|
367
|
+
"periodTimeSymbol": "TS02",
|
|
368
|
+
"dayStartTime": null,
|
|
369
|
+
"startDay": null,
|
|
370
|
+
"eventTriggerType": 0,
|
|
371
|
+
"zoneoffset": 8,
|
|
372
|
+
"events": []
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
"entryControlLimits": {
|
|
376
|
+
"enableMultEntry": false,
|
|
377
|
+
"disableConcurrentEntry": false
|
|
378
|
+
},
|
|
379
|
+
"targetClusterQp": "<JSON.stringify(qp) or null>"
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Rules:
|
|
384
|
+
- `entry.trigger_event` -> `triggerRule[0].events`
|
|
385
|
+
- Generate `targetClusterQp` only when `entry.segment` exists
|
|
386
|
+
- When `segment` is absent, `targetClusterQp` may be `null`
|
|
387
|
+
|
|
388
|
+
#### `event_split_flow`
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"splitFlowType": 1,
|
|
393
|
+
"branchList": [
|
|
394
|
+
{
|
|
395
|
+
"branchId": "<branchId>",
|
|
396
|
+
"branchName": "<label>",
|
|
397
|
+
"branchType": 1,
|
|
398
|
+
"triggerRule": [
|
|
399
|
+
{
|
|
400
|
+
"delayTimeSymbol": "<minute|hour|day>",
|
|
401
|
+
"delayTime": "<number>",
|
|
402
|
+
"eventTriggerType": "<0 or -1>",
|
|
403
|
+
"zoneoffset": 8,
|
|
404
|
+
"events": []
|
|
405
|
+
}
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Rules:
|
|
413
|
+
- When `branch.condition` is an event condition, map it to `triggerRule[].events[]`
|
|
414
|
+
- `time_limit` -> `delayTimeSymbol` + `delayTime`
|
|
415
|
+
- Use `0` for happened and `-1` for not happened
|
|
416
|
+
- For the fallback branch, keep only:
|
|
417
|
+
|
|
418
|
+
```json
|
|
419
|
+
{
|
|
420
|
+
"branchId": "<branchId>",
|
|
421
|
+
"branchType": 2
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
#### `feature_split_flow`
|
|
426
|
+
|
|
427
|
+
```json
|
|
428
|
+
{
|
|
429
|
+
"splitFlowType": 1,
|
|
430
|
+
"branchList": [
|
|
431
|
+
{
|
|
432
|
+
"branchId": "<branchId>",
|
|
433
|
+
"branchName": "<label>",
|
|
434
|
+
"branchType": 1,
|
|
435
|
+
"realtime": 0,
|
|
436
|
+
"clusterRefresh": 12,
|
|
437
|
+
"clusterPredictCount": null,
|
|
438
|
+
"clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>",
|
|
439
|
+
"targetClusterQp": "<JSON.stringify(qp)>"
|
|
440
|
+
}
|
|
441
|
+
]
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Rules:
|
|
446
|
+
- Property or tag condition -> `targetClusterQp`
|
|
447
|
+
- For the fallback branch, also keep only `branchId` plus `branchType: 2`
|
|
448
|
+
|
|
449
|
+
#### `ab_split_flow`
|
|
450
|
+
|
|
451
|
+
```json
|
|
452
|
+
{
|
|
453
|
+
"branchList": [
|
|
454
|
+
{
|
|
455
|
+
"branchId": "<branchId>",
|
|
456
|
+
"branchName": "Control Group",
|
|
457
|
+
"branchType": 1,
|
|
458
|
+
"order": 1,
|
|
459
|
+
"percentageInExperiment": 34
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"branchId": "<branchId>",
|
|
463
|
+
"branchName": "Experiment Group A",
|
|
464
|
+
"branchType": 2,
|
|
465
|
+
"order": 2,
|
|
466
|
+
"percentageInExperiment": 33
|
|
467
|
+
}
|
|
468
|
+
],
|
|
469
|
+
"indicatorsDef": [],
|
|
470
|
+
"activateIndicatorsDef": null
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Rules:
|
|
475
|
+
- If the user does not provide percentages, you may split them evenly
|
|
476
|
+
- For three groups, you can use `34/33/33`
|
|
477
|
+
|
|
478
|
+
#### `event_judge`
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"transferType": 1,
|
|
483
|
+
"meetBranchId": "<meetBranchId>",
|
|
484
|
+
"notMeetBranchId": "<notMeetBranchId>",
|
|
485
|
+
"triggerRule": [
|
|
486
|
+
{
|
|
487
|
+
"delayTimeSymbol": "<minute|hour|day>",
|
|
488
|
+
"delayTime": "<number>",
|
|
489
|
+
"eventTriggerType": 0,
|
|
490
|
+
"zoneoffset": 8,
|
|
491
|
+
"events": []
|
|
492
|
+
}
|
|
493
|
+
]
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Rules:
|
|
498
|
+
- `node.event` -> `triggerRule[].events[]`
|
|
499
|
+
- `wait_time` -> `delayTimeSymbol` + `delayTime`
|
|
500
|
+
- If no wait duration is specified, you may default to `30 minute`
|
|
501
|
+
|
|
502
|
+
#### `feature_judge`
|
|
503
|
+
|
|
504
|
+
```json
|
|
505
|
+
{
|
|
506
|
+
"transferType": 1,
|
|
507
|
+
"meetBranchId": "<meetBranchId>",
|
|
508
|
+
"notMeetBranchId": "<notMeetBranchId>",
|
|
509
|
+
"clusterPredictCount": null,
|
|
510
|
+
"clusterPredictTime": "",
|
|
511
|
+
"targetClusterQp": "<JSON.stringify(qp)>"
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
#### `message_push` / `webhook_push`
|
|
516
|
+
|
|
517
|
+
```json
|
|
518
|
+
{
|
|
519
|
+
"channelId": "<matched channelId>",
|
|
520
|
+
"channelType": "<matched channelType>",
|
|
521
|
+
"enableChannelTouchLimits": false,
|
|
522
|
+
"isOccasionUp": false,
|
|
523
|
+
"contentList": [
|
|
524
|
+
{
|
|
525
|
+
"pushLanguageCode": "default",
|
|
526
|
+
"content": []
|
|
527
|
+
}
|
|
528
|
+
],
|
|
529
|
+
"processType": 1
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Rules:
|
|
534
|
+
- `channel_name` -> match a real `channelId`
|
|
535
|
+
- `content` -> fill the parameter that best matches body text, content, or message
|
|
536
|
+
- When the parameter `type = TEXT`, also add:
|
|
537
|
+
|
|
538
|
+
```json
|
|
539
|
+
{
|
|
540
|
+
"config": "[{\"type\":\"paragraph\",\"children\":[{\"text\":\"<same as value>\"}]}]"
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
Multilingual Rules:
|
|
545
|
+
- The first entry must always use `"pushLanguageCode": "default"`
|
|
546
|
+
- Generate additional language versions according to `languages`
|
|
547
|
+
- Each language uses the same `content[]` structure; only `value` changes
|
|
548
|
+
|
|
549
|
+
#### `wechat_push`
|
|
550
|
+
|
|
551
|
+
```json
|
|
552
|
+
{
|
|
553
|
+
"channelId": "<matched channelId>",
|
|
554
|
+
"enableChannelTouchLimits": false,
|
|
555
|
+
"isOccasionUp": false,
|
|
556
|
+
"contentList": [
|
|
557
|
+
{
|
|
558
|
+
"pushLanguageCode": "default",
|
|
559
|
+
"content": [
|
|
560
|
+
{
|
|
561
|
+
"key": "lang",
|
|
562
|
+
"type": "STRING",
|
|
563
|
+
"required": true,
|
|
564
|
+
"paramType": 2,
|
|
565
|
+
"name": "Language",
|
|
566
|
+
"value": "default"
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
"key": "page",
|
|
570
|
+
"type": "STRING",
|
|
571
|
+
"required": true,
|
|
572
|
+
"paramType": 2,
|
|
573
|
+
"name": "Destination Page",
|
|
574
|
+
"value": ""
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
"key": "miniprogramState",
|
|
578
|
+
"type": "STRING",
|
|
579
|
+
"required": true,
|
|
580
|
+
"paramType": 2,
|
|
581
|
+
"name": "Version",
|
|
582
|
+
"value": ""
|
|
583
|
+
}
|
|
584
|
+
]
|
|
585
|
+
}
|
|
586
|
+
],
|
|
587
|
+
"processType": 1
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
#### `time_control`
|
|
592
|
+
|
|
593
|
+
```json
|
|
594
|
+
{
|
|
595
|
+
"controlType": 1,
|
|
596
|
+
"timeUnit": "<minute|hour|day>",
|
|
597
|
+
"timeUnitNum": "<number>"
|
|
598
|
+
}
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
Common parsing examples:
|
|
602
|
+
- `30 minutes` -> `minute` + `30`
|
|
603
|
+
- `2 hours` -> `hour` + `2`
|
|
604
|
+
- `1 day` -> `day` + `1`
|
|
605
|
+
|
|
606
|
+
#### `exit_flow`
|
|
607
|
+
|
|
608
|
+
Minimum usable `config`:
|
|
609
|
+
|
|
610
|
+
```json
|
|
611
|
+
{}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
## 8. Step Six: How to Build `edgeList`
|
|
617
|
+
|
|
618
|
+
Each item in `edgeList` has the following structure:
|
|
619
|
+
|
|
620
|
+
| Field | Type | Required | Description |
|
|
621
|
+
|---|---|---|---|
|
|
622
|
+
| `source` | string | Yes | upstream node ID |
|
|
623
|
+
| `target` | string | Yes | downstream node ID |
|
|
624
|
+
| `edgeId` | string | No | edge ID |
|
|
625
|
+
| `sourceBranchId` | string | No | used for edges leaving split or judgment nodes |
|
|
626
|
+
| `config` | string | No | JSON string |
|
|
627
|
+
|
|
628
|
+
### 8.1 Regular Edges
|
|
629
|
+
|
|
630
|
+
```json
|
|
631
|
+
{
|
|
632
|
+
"source": "node_1",
|
|
633
|
+
"target": "node_2"
|
|
634
|
+
}
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### 8.2 Branch Edges
|
|
638
|
+
|
|
639
|
+
```json
|
|
640
|
+
{
|
|
641
|
+
"source": "node_split",
|
|
642
|
+
"target": "node_a",
|
|
643
|
+
"sourceBranchId": "branch_a"
|
|
644
|
+
}
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### 8.3 Most Important Rules
|
|
648
|
+
|
|
649
|
+
1. `source` and `target` must reference existing `node.id` values
|
|
650
|
+
2. Only edges leaving split or judgment nodes need `sourceBranchId`
|
|
651
|
+
3. The graph must be a DAG and cannot contain cycles
|
|
652
|
+
4. For split nodes, `sourceBranchId` must come from a branchId already declared in the corresponding node `config`
|
|
653
|
+
|
|
654
|
+
### 8.4 Standard Outgoing-Edge Rules
|
|
655
|
+
|
|
656
|
+
| node type | Number of outgoing edges | `sourceBranchId` rule |
|
|
657
|
+
|---|---|---|
|
|
658
|
+
| `single_trigger` / `repeat_trigger` / `event_trigger` | 1 | do not provide |
|
|
659
|
+
| `event_split_flow` / `feature_split_flow` / `ab_split_flow` | one per branch | use the corresponding `branchList[].branchId` |
|
|
660
|
+
| `event_judge` / `feature_judge` | 2 | use `meetBranchId` and `notMeetBranchId` respectively |
|
|
661
|
+
| `message_push` / `wechat_push` / `webhook_push` / `time_control` | 1 | do not provide |
|
|
662
|
+
| `exit_flow` | 0 | do not provide |
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## 9. Step Seven: Graph Constraint Checks
|
|
667
|
+
|
|
668
|
+
Before submitting, you must self-check:
|
|
669
|
+
|
|
670
|
+
1. `nodeList` is not empty
|
|
671
|
+
2. There must be exactly one entry node
|
|
672
|
+
3. There must be at least one `exit_flow`
|
|
673
|
+
4. Each `exit_flow` must have exactly one incoming edge and no outgoing edges
|
|
674
|
+
5. Each `node.id` must be unique
|
|
675
|
+
6. Every edge must reference existing nodes
|
|
676
|
+
7. The entire graph must be acyclic
|
|
677
|
+
|
|
678
|
+
If a split node uses `splitFlowType = 2`, also ensure:
|
|
679
|
+
- Paths from different branches must not converge again into the same node
|
|
680
|
+
- Each branch should independently lead to its own `exit_flow`
|
|
681
|
+
|
|
682
|
+
---
|
|
683
|
+
|
|
684
|
+
## 10. Step Eight: CLI Submission
|
|
685
|
+
|
|
686
|
+
### 10.1 Top-Level Flags
|
|
687
|
+
|
|
688
|
+
| Flag | Type | Required | Description |
|
|
689
|
+
|---|---|---|---|
|
|
690
|
+
| `--project_id` / `-p` | number | Yes | Project ID |
|
|
691
|
+
| `--req` | json | Yes | final request-body object |
|
|
692
|
+
|
|
693
|
+
### 10.2 Actual CLI Submission Structure
|
|
694
|
+
|
|
695
|
+
The CLI will organize the input as:
|
|
696
|
+
|
|
697
|
+
```json
|
|
698
|
+
{
|
|
699
|
+
"projectId": 1,
|
|
700
|
+
"req": {
|
|
701
|
+
"projectId": 1,
|
|
702
|
+
"...": "..."
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
In other words:
|
|
708
|
+
- The top-level `projectId` comes from `--project_id`
|
|
709
|
+
- `req.projectId` is also injected automatically by the CLI
|
|
710
|
+
|
|
711
|
+
### 10.3 Minimum Working Example
|
|
712
|
+
|
|
713
|
+
```bash
|
|
714
|
+
ae-cli engage +save_flow \
|
|
715
|
+
--project_id 1 \
|
|
716
|
+
--req '{
|
|
717
|
+
"flowName": "Welcome Flow",
|
|
718
|
+
"flowDesc": "New user welcome flow",
|
|
719
|
+
"groupId": 0,
|
|
720
|
+
"tzOffset": 8,
|
|
721
|
+
"nodeList": [
|
|
722
|
+
{
|
|
723
|
+
"id": "node_1",
|
|
724
|
+
"name": "Enter Flow",
|
|
725
|
+
"type": "single_trigger",
|
|
726
|
+
"config": "{}"
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
"id": "node_2",
|
|
730
|
+
"name": "End",
|
|
731
|
+
"type": "exit_flow",
|
|
732
|
+
"config": "{}"
|
|
733
|
+
}
|
|
734
|
+
],
|
|
735
|
+
"edgeList": [
|
|
736
|
+
{
|
|
737
|
+
"source": "node_1",
|
|
738
|
+
"target": "node_2"
|
|
739
|
+
}
|
|
740
|
+
]
|
|
741
|
+
}'
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### 10.4 Output Requirements After Successful Creation
|
|
745
|
+
|
|
746
|
+
Prerequisite:
|
|
747
|
+
- The flow canvas was created successfully and returned the new canvas `flowUuid`
|
|
748
|
+
|
|
749
|
+
On success, you must:
|
|
750
|
+
- Show the creation result to the user, including at least key information such as the canvas name
|
|
751
|
+
- Output a **clickable Markdown link**
|
|
752
|
+
|
|
753
|
+
Link-generation Rules:
|
|
754
|
+
- Use standard Markdown link syntax and do not place it inside a code block
|
|
755
|
+
- The URL must start with `/#/`
|
|
756
|
+
- Do not add a domain name or any domain placeholder
|
|
757
|
+
- Replace the `flowUuid` returned by `save_flow` and the `projectId` used for this creation into the URL
|
|
758
|
+
|
|
759
|
+
Output template:
|
|
760
|
+
|
|
761
|
+
[Open Canvas](/#/hermes/flow/detail?flowUuid=<replace-with-actual-flowUuid>¤tProjectId=<replace-with-actual-projectId>)
|
|
762
|
+
|
|
763
|
+
Correct example:
|
|
764
|
+
|
|
765
|
+
[Open Canvas](/#/hermes/flow/detail?flowUuid=0006_831135755¤tProjectId=1)
|
|
766
|
+
|
|
767
|
+
Common mistakes:
|
|
768
|
+
- `❌ {domain}/#/hermes/flow/...`: do not add a domain placeholder
|
|
769
|
+
- `❌` putting the link inside a code block ````` : links inside code blocks are not clickable
|
|
770
|
+
- `❌ /#/hermes/flow/detail?flowUuid=...`: do not output a plain-text URL; you must use the `[text](URL)` format
|
|
771
|
+
|
|
772
|
+
### 10.5 Output Requirements After Failed Creation
|
|
773
|
+
|
|
774
|
+
On failure, you must:
|
|
775
|
+
- Output the complete request-body JSON for debugging
|
|
776
|
+
- Clearly describe the failure reason
|
|
777
|
+
|
|
778
|
+
Suggested output structure:
|
|
779
|
+
|
|
780
|
+
```json
|
|
781
|
+
{
|
|
782
|
+
"projectId": "<actual projectId>",
|
|
783
|
+
"req": {
|
|
784
|
+
"...": "complete save_flow request body"
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## 11. Most Common Mistakes
|
|
792
|
+
|
|
793
|
+
### 11.1 `--req` Is an Object, but `node.config` / `edge.config` Are Strings
|
|
794
|
+
|
|
795
|
+
Correct:
|
|
796
|
+
|
|
797
|
+
```json
|
|
798
|
+
{
|
|
799
|
+
"id": "node_1",
|
|
800
|
+
"name": "entry",
|
|
801
|
+
"type": "single_trigger",
|
|
802
|
+
"config": "{}"
|
|
803
|
+
}
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
Incorrect:
|
|
807
|
+
|
|
808
|
+
```json
|
|
809
|
+
{
|
|
810
|
+
"id": "node_1",
|
|
811
|
+
"name": "entry",
|
|
812
|
+
"type": "single_trigger",
|
|
813
|
+
"config": {}
|
|
814
|
+
}
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### 11.2 Time Units Must Be Lowercase
|
|
818
|
+
|
|
819
|
+
Inside `time_control`, use:
|
|
820
|
+
|
|
821
|
+
- `day`
|
|
822
|
+
- `hour`
|
|
823
|
+
- `minute`
|
|
824
|
+
- `week`
|
|
825
|
+
- `month`
|
|
826
|
+
|
|
827
|
+
Do not write `DAY`, `HOUR`, or `MINUTE`.
|
|
828
|
+
|
|
829
|
+
### 11.3 Do Not Invent `channelId`
|
|
830
|
+
|
|
831
|
+
For node types such as `message_push`, `wechat_push`, and `webhook_push`, `channelId` must come from:
|
|
832
|
+
|
|
833
|
+
```bash
|
|
834
|
+
ae-cli engage +channel_list --project_id <projectId>
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### 11.4 Define branch IDs Before Referencing Them
|
|
838
|
+
|
|
839
|
+
If an edge uses:
|
|
840
|
+
|
|
841
|
+
```json
|
|
842
|
+
{ "sourceBranchId": "branch_a" }
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
then `"branch_a"` must already exist in the corresponding upstream node `config`.
|
|
846
|
+
|
|
847
|
+
### 11.5 `targetClusterQp` Is Usually Also a String
|
|
848
|
+
|
|
849
|
+
Although `targetClusterQp` appears inside the JSON object of node `config`, its value is usually not a raw object. It is typically the QP object converted into a string with `JSON.stringify`.
|
|
850
|
+
|
|
851
|
+
Illustration:
|
|
852
|
+
|
|
853
|
+
```json
|
|
854
|
+
{ "targetClusterQp": "{\"totalCFilter\":{\"relation\":\"1\",\"filts\":[]}}" }
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
### 11.6 Rich-Text `config` for `TEXT` Parameters Must Also Be a String
|
|
858
|
+
|
|
859
|
+
If a push parameter uses `TEXT`, the inner rich-text `config` must not be an object. It must be stringified JSON. This is easy to miss.
|
|
860
|
+
|
|
861
|
+
### 11.7 Do Not Merge Branches Again When `splitFlowType = 2`
|
|
862
|
+
|
|
863
|
+
"Enter whenever conditions are met" means users may enter multiple branches at the same time. In that case, later paths should not share the same downstream node, otherwise the semantics easily conflict.
|
|
864
|
+
|
|
865
|
+
---
|
|
866
|
+
|
|
867
|
+
## 12. One-Sentence Summary
|
|
868
|
+
|
|
869
|
+
To build `+save_flow` input parameters reliably, do not jump directly from natural language to `req`. Follow this path instead:
|
|
870
|
+
|
|
871
|
+
**User requirement -> intent JSON -> schema and channel completion -> `nodeList` / `edgeList` -> `ae-cli engage +save_flow`.**
|