@thinkingai/ae-cli 6.0.24 → 6.0.28

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 (185) hide show
  1. package/dist/{auth-A2XXG5K4.js → auth-7TQRGLBC.js} +10 -8
  2. package/dist/{auth-IDPKDFSY.js → auth-MEJ642P4.js} +2 -2
  3. package/dist/chunk-2NDGFQHW.js +190 -0
  4. package/dist/{chunk-NGJDCOYA.js → chunk-7QQ4233A.js} +3 -3
  5. package/dist/{chunk-PFJFZVCK.js → chunk-AJTH7LT3.js} +3 -2
  6. package/dist/{chunk-V5R5UIRM.js → chunk-BXMXMUD7.js} +65 -6
  7. package/dist/{chunk-AKORWVHJ.js → chunk-C4DH76LX.js} +1 -1
  8. package/dist/{chunk-NXJP4CES.js → chunk-GWZ5MYWE.js} +3 -3
  9. package/dist/{chunk-F3ZDMC2W.js → chunk-KCA6BA5D.js} +2 -2
  10. package/dist/{chunk-WXBCP6SD.js → chunk-KGJQCYVC.js} +1 -1
  11. package/dist/{chunk-FIT4CFIN.js → chunk-LG5YT7P7.js} +1 -1
  12. package/dist/{chunk-IDXW6MEJ.js → chunk-MDJGDI6K.js} +2 -2
  13. package/dist/{chunk-4FQ36OGO.js → chunk-R77JT7XD.js} +53 -6
  14. package/dist/{chunk-65DKFJZB.js → chunk-YCLVYFK7.js} +49 -6
  15. package/dist/{chunk-2OW2RENH.js → chunk-YNQFYBDB.js} +64 -6
  16. package/dist/{chunk-ONOA6DYB.js → chunk-ZAOL36CG.js} +1 -1
  17. package/dist/cli-token-TVQRSE46.js +18 -0
  18. package/dist/{client-7L735LVY.js → client-2643Z5AG.js} +3 -3
  19. package/dist/{config-SXD2JKSL.js → config-ZVPARN4R.js} +4 -9
  20. package/dist/index.js +24 -24
  21. package/dist/{metadata-QWUAX625.js → metadata-IPSPQBX3.js} +5 -5
  22. package/dist/{metadata-XWTEGEN2.js → metadata-N5REJ7R7.js} +5 -5
  23. package/dist/{model-3OVX42DA.js → model-T3KZJWLW.js} +2 -2
  24. package/dist/{raw-IANB4AV5.js → raw-OHSUK42D.js} +4 -4
  25. package/dist/{sync-4HQ3CXSK.js → sync-ULT5SECP.js} +3 -3
  26. package/dist/{te-agent-OYNNTJDU.js → te-agent-QLIVKRUN.js} +1146 -61
  27. package/dist/{te-analysis-JX3V76OI.js → te-analysis-5WZKVFHI.js} +1332 -338
  28. package/dist/{te-analysis-CRPFK3LX.js → te-analysis-KAEZXLNS.js} +1332 -338
  29. package/dist/{te-audience-RO2IZOUC.js → te-audience-PVMKQAFH.js} +5 -5
  30. package/dist/{te-audience-77FGNG5E.js → te-audience-XMRMVD2V.js} +5 -5
  31. package/dist/{te-common-4TRJPRC5.js → te-common-CFGQXTFV.js} +5 -5
  32. package/dist/{te-common-PUXBUPOL.js → te-common-SDB3O2QG.js} +5 -5
  33. package/dist/{te-community-XKE526DS.js → te-community-6A7LKYUH.js} +5 -5
  34. package/dist/{te-community-NPDZQKMY.js → te-community-GMWFGILT.js} +5 -5
  35. package/dist/{te-dataops-PW74WP76.js → te-dataops-6LIPYNGH.js} +90 -68
  36. package/dist/{te-dataops-6KWLFNV4.js → te-dataops-Z53CTG2U.js} +90 -68
  37. package/dist/{te-engage-HTLMUN7G.js → te-engage-AGREUOW7.js} +30 -15
  38. package/dist/{te-engage-YPQIVF5H.js → te-engage-MIIUKY6M.js} +30 -15
  39. package/dist/{te-kb-DOGDQIU4.js → te-kb-KQJ53M3A.js} +4 -4
  40. package/dist/{te-meta-5ESSQ5B3.js → te-meta-QLANJ4B4.js} +5 -5
  41. package/dist/{te-meta-Z47X4VT3.js → te-meta-TOA6FWDE.js} +5 -5
  42. package/dist/{te-team-SOVKZIDD.js → te-team-TQGMNHQQ.js} +5 -5
  43. package/package.json +3 -1
  44. package/skills/ae-agent/SKILL.md +158 -189
  45. package/skills/ae-agent/references/accept-skill-share.md +39 -0
  46. package/skills/ae-agent/references/add-attachment.md +57 -0
  47. package/skills/ae-agent/references/add-mcp.md +75 -0
  48. package/skills/ae-agent/references/add-model.md +70 -0
  49. package/skills/ae-agent/references/add-skill.md +71 -0
  50. package/skills/ae-agent/references/approve-skill.md +41 -0
  51. package/skills/ae-agent/references/attachment-stats.md +50 -0
  52. package/skills/ae-agent/references/auto-provision-mcp-credentials.md +57 -0
  53. package/skills/ae-agent/references/cancel-skill-submission.md +39 -0
  54. package/skills/ae-agent/references/copy-skill.md +53 -0
  55. package/skills/ae-agent/references/create-agent.md +71 -0
  56. package/skills/ae-agent/references/create-automation.md +99 -0
  57. package/skills/ae-agent/references/del-agent.md +38 -0
  58. package/skills/ae-agent/references/del-attachment.md +35 -0
  59. package/skills/ae-agent/references/del-mcp.md +35 -0
  60. package/skills/ae-agent/references/del-model.md +37 -0
  61. package/skills/ae-agent/references/del-skill-asset.md +41 -0
  62. package/skills/ae-agent/references/del-skill-reference.md +41 -0
  63. package/skills/ae-agent/references/del-skill-script.md +41 -0
  64. package/skills/ae-agent/references/del-skill.md +36 -0
  65. package/skills/ae-agent/references/edit-skill.md +64 -0
  66. package/skills/ae-agent/references/get-agent.md +37 -0
  67. package/skills/ae-agent/references/get-skill-content.md +36 -0
  68. package/skills/ae-agent/references/list-agents.md +40 -0
  69. package/skills/ae-agent/references/list-attachments.md +42 -0
  70. package/skills/ae-agent/references/list-automations.md +41 -0
  71. package/skills/ae-agent/references/list-mcp-credentials.md +65 -0
  72. package/skills/ae-agent/references/list-mcp-market.md +58 -0
  73. package/skills/ae-agent/references/list-mcps.md +37 -0
  74. package/skills/ae-agent/references/list-models.md +38 -0
  75. package/skills/ae-agent/references/list-skill-assets.md +35 -0
  76. package/skills/ae-agent/references/list-skill-market.md +59 -0
  77. package/skills/ae-agent/references/list-skill-references.md +36 -0
  78. package/skills/ae-agent/references/list-skill-scripts.md +35 -0
  79. package/skills/ae-agent/references/list-skill-shares.md +49 -0
  80. package/skills/ae-agent/references/list-skill-submissions.md +45 -0
  81. package/skills/ae-agent/references/list-skills.md +37 -0
  82. package/skills/ae-agent/references/mcp-auth-disconnect.md +50 -0
  83. package/skills/ae-agent/references/mcp-auth-start.md +61 -0
  84. package/skills/ae-agent/references/mcp-auth-status.md +56 -0
  85. package/skills/ae-agent/references/mcp-stats.md +68 -0
  86. package/skills/ae-agent/references/mcp-token.md +63 -0
  87. package/skills/ae-agent/references/mcp-tools.md +55 -0
  88. package/skills/ae-agent/references/read-skill-asset.md +51 -0
  89. package/skills/ae-agent/references/read-skill-reference.md +50 -0
  90. package/skills/ae-agent/references/read-skill-script.md +51 -0
  91. package/skills/ae-agent/references/reject-skill-share.md +37 -0
  92. package/skills/ae-agent/references/reject-skill.md +42 -0
  93. package/skills/ae-agent/references/rescan-skills.md +44 -0
  94. package/skills/ae-agent/references/set-mcp-credential.md +67 -0
  95. package/skills/ae-agent/references/set-mcp-meta.md +52 -0
  96. package/skills/ae-agent/references/set-skill-meta.md +51 -0
  97. package/skills/ae-agent/references/share-skill.md +50 -0
  98. package/skills/ae-agent/references/submit-skill.md +51 -0
  99. package/skills/ae-agent/references/test-model.md +61 -0
  100. package/skills/ae-agent/references/toggle-mcp.md +39 -0
  101. package/skills/ae-agent/references/toggle-model.md +37 -0
  102. package/skills/ae-agent/references/toggle-skill.md +37 -0
  103. package/skills/ae-agent/references/update-agent.md +71 -0
  104. package/skills/ae-agent/references/update-automation.md +83 -0
  105. package/skills/ae-agent/references/update-mcp.md +79 -0
  106. package/skills/ae-agent/references/update-model.md +77 -0
  107. package/skills/ae-agent/references/upload-skill-asset.md +49 -0
  108. package/skills/ae-agent/references/upload-skill-reference.md +51 -0
  109. package/skills/ae-agent/references/upload-skill-script.md +49 -0
  110. package/skills/ae-agent/references/upload-skill.md +89 -0
  111. package/skills/ae-analysis/SKILL.md +60 -6
  112. package/skills/ae-analysis/references/analysis_gateway_assets.md +27 -10
  113. package/skills/ae-analysis/references/artifact_download.md +17 -0
  114. package/skills/ae-analysis/references/asset_abnormal_get.md +27 -0
  115. package/skills/ae-analysis/references/asset_abnormal_list.md +24 -0
  116. package/skills/ae-analysis/references/asset_authentication_list.md +23 -0
  117. package/skills/ae-analysis/references/asset_authentication_update.md +24 -0
  118. package/skills/ae-analysis/references/asset_recent_list.md +24 -0
  119. package/skills/ae-analysis/references/asset_search.md +24 -0
  120. package/skills/ae-analysis/references/bi_panel_get.md +5 -0
  121. package/skills/ae-analysis/references/bi_panel_page_data_export.md +11 -1
  122. package/skills/ae-analysis/references/bi_panel_share.md +6 -0
  123. package/skills/ae-analysis/references/bi_panel_update.md +4 -1
  124. package/skills/ae-analysis/references/bi_panel_version_get.md +23 -0
  125. package/skills/ae-analysis/references/bi_panel_version_publish.md +20 -0
  126. package/skills/ae-analysis/references/dashboard_copy.md +3 -1
  127. package/skills/ae-analysis/references/dashboard_daily_report_send.md +9 -2
  128. package/skills/ae-analysis/references/dashboard_daily_report_update.md +3 -1
  129. package/skills/ae-analysis/references/dashboard_definition_export.md +21 -3
  130. package/skills/ae-analysis/references/dashboard_report_data_export.md +17 -1
  131. package/skills/ae-analysis/references/dashboard_report_data_run.md +6 -0
  132. package/skills/ae-analysis/references/datatable_columns_get.md +24 -0
  133. package/skills/ae-analysis/references/datatable_influence_list.md +24 -0
  134. package/skills/ae-analysis/references/datatable_version_get.md +24 -0
  135. package/skills/ae-analysis/references/datatable_version_list.md +24 -0
  136. package/skills/ae-analysis/references/event_changelog_list.md +24 -0
  137. package/skills/ae-analysis/references/event_create.md +24 -0
  138. package/skills/ae-analysis/references/event_delete.md +24 -0
  139. package/skills/ae-analysis/references/event_get.md +24 -0
  140. package/skills/ae-analysis/references/event_hide_update.md +25 -0
  141. package/skills/ae-analysis/references/event_influence_list.md +24 -0
  142. package/skills/ae-analysis/references/event_list.md +23 -0
  143. package/skills/ae-analysis/references/event_relation_update.md +24 -0
  144. package/skills/ae-analysis/references/event_update.md +26 -0
  145. package/skills/ae-analysis/references/exchange_config_update.md +24 -0
  146. package/skills/ae-analysis/references/exchange_rate_refresh.md +23 -0
  147. package/skills/ae-analysis/references/exchange_rule_list.md +23 -0
  148. package/skills/ae-analysis/references/exchange_rule_update.md +24 -0
  149. package/skills/ae-analysis/references/exchange_rule_validate.md +24 -0
  150. package/skills/ae-analysis/references/metric_create.md +24 -0
  151. package/skills/ae-analysis/references/metric_delete.md +24 -0
  152. package/skills/ae-analysis/references/metric_get.md +24 -0
  153. package/skills/ae-analysis/references/metric_list.md +24 -0
  154. package/skills/ae-analysis/references/metric_update.md +24 -0
  155. package/skills/ae-analysis/references/project_space_create.md +1 -1
  156. package/skills/ae-analysis/references/property_changelog_list.md +25 -0
  157. package/skills/ae-analysis/references/property_create.md +25 -0
  158. package/skills/ae-analysis/references/property_delete.md +25 -0
  159. package/skills/ae-analysis/references/property_get.md +25 -0
  160. package/skills/ae-analysis/references/property_hide_update.md +26 -0
  161. package/skills/ae-analysis/references/property_influence_list.md +25 -0
  162. package/skills/ae-analysis/references/property_list.md +24 -0
  163. package/skills/ae-analysis/references/property_related_events.md +24 -0
  164. package/skills/ae-analysis/references/property_relation_update.md +25 -0
  165. package/skills/ae-analysis/references/property_update.md +27 -0
  166. package/skills/ae-analysis/references/run_inspect.md +22 -0
  167. package/skills/ae-analysis/references/super_metadata_export.md +36 -0
  168. package/skills/ae-analysis/references/super_metadata_import.md +24 -0
  169. package/skills/ae-analysis/references/virtual_event_create.md +25 -0
  170. package/skills/ae-analysis/references/virtual_event_delete.md +24 -0
  171. package/skills/ae-analysis/references/virtual_event_get.md +24 -0
  172. package/skills/ae-analysis/references/virtual_property_create.md +24 -0
  173. package/skills/ae-analysis/references/virtual_property_sql_rule_delete.md +25 -0
  174. package/skills/ae-analysis/references/virtual_property_sql_rule_update.md +24 -0
  175. package/skills/ae-dataops/references/dataops-flow-create.md +2 -2
  176. package/skills/ae-dataops/references/dataops-flow-monitor.md +3 -3
  177. package/skills/ae-dataops/references/dataops-integration.md +1 -0
  178. package/skills/ae-engage/references/flow-node-config-schema.md +32 -8
  179. package/skills/ae-engage/references/save-flow.md +65 -29
  180. package/skills/ae-engage/references/validate-flow-node-config.md +28 -10
  181. package/skills/ae-generate-tracking-code/SKILL.md +16 -1
  182. package/skills/ae-generate-tracking-code/references/snippet-delivery.md +17 -1
  183. package/skills/ae-generate-tracking-plan/SKILL.md +36 -12
  184. package/dist/chunk-OCQPQYHZ.js +0 -105
  185. package/dist/cli-token-OZXHC3U2.js +0 -14
@@ -4,9 +4,9 @@ Create, edit, preview, or commit a flow canvas draft.
4
4
 
5
5
  Mapped command: `ae-cli engage +save_flow --project_id <projectId> --req '<req-json>'`
6
6
 
7
- > **Protocol v2 (current).** `save_flow` is now **operation-based**. The `--req` object must carry an `operation` of `build`, `preview`, or `commit`. Do **not** use the old `nodeList` / `edgeList` field names send `nodes` / `edges` instead. Posting a legacy `nodeList`/`edgeList` payload (or omitting `operation`) makes the backend reject the call with `Unsupported save_flow operation: null`.
7
+ > **Protocol v2 (current).** `save_flow` is now **operation-based**. The `--req` object must carry an `operation` of `build`, `preview`, or `commit`. Do **not** use the old `nodeList` / `edgeList` field names -- send `nodes` / `edges` instead. Posting a legacy `nodeList`/`edgeList` payload (or omitting `operation`) makes the backend reject the call with `Unsupported save_flow operation: null`.
8
8
 
9
- The CLI passes your `--req` straight through to the backend (it only injects `projectId`). So everything in this document is about building the correct `req` object.
9
+ The CLI injects `projectId` and rejects missing/unsupported `operation` values, legacy `nodeList`/`edgeList` fields, and the removed `sourceFlowUuid` clone mode; otherwise it passes your `--req` through to the backend. So everything in this document is about building the correct `req` object.
10
10
 
11
11
  ---
12
12
 
@@ -22,10 +22,11 @@ build ──► status = ready_to_preview ──► preview ──► commit
22
22
 
23
23
  You still organize user requirements into an intermediate intent first, then map the intent to `nodes` / `edges`, then run the lifecycle.
24
24
 
25
- - `build`: assemble/edit a draft from `nodes` + `edges` (or `dsl`, or clone). Returns `ready_to_preview` (with `draftId`, `draftVersion`, `confirmToken`, `preview.mainPath`) or `need_input` (one more slot required).
25
+ - `build`: assemble/edit a draft from `nodes` + `edges` (or topology-only `dsl`). Returns `ready_to_preview` (with `draftId`, `draftVersion`, `confirmToken`, `preview.mainPath`) or `need_input` (one more slot required).
26
26
  - `preview`: validate the draft; **re-issues** a fresh `draftVersion` + `confirmToken`.
27
27
  - `commit`: finalize the draft into a flow version using the **preview** `draftVersion` + `confirmToken`; returns the final `flowUuid`.
28
28
  - Always verify with `ae-cli engage +flow_detail --project_id <projectId> --flow_uuid <flowUuid>`.
29
+ - To copy an existing flow, first call `+flow_detail`, convert the returned `nodeList` / `edgeList` into compact `nodes` / `edges`, then call `operation=build` as normal creation input. Do not pass `sourceFlowUuid`.
29
30
 
30
31
  ---
31
32
 
@@ -34,8 +35,9 @@ You still organize user requirements into an intermediate intent first, then map
34
35
  1. Identify the flow intent from the user input and produce a unified intent JSON.
35
36
  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.
36
37
  3. Run `ae-cli engage +channel_list --project_id <projectId>` to get the available channels and match real `channelId` values for touchpoint nodes. For `webhook_push`, also run `ae-cli engage +channel_detail` and use `data.config.paramsList` to build `contentList`.
37
- 4. Map the intent JSON to `nodes` and `edges` (compact form, see §7 / §8).
38
- 5. `build` resolve any `need_input` slot `preview` `commit`, then verify with `+flow_detail`.
38
+ 4. Query `ae-cli engage +flow_node_config_schema --node_type <type>` before constructing each non-trivial node config, then run `ae-cli engage +validate_flow_node_config --node_type <type> --operation_mode save_flow --config '<config-json-string>'` before placing the config into `nodes` or `nodeConfigs`.
39
+ 5. Map the intent JSON to `nodes` and `edges` (compact form, see §7 / §8).
40
+ 6. `build` → resolve any `need_input` slot → `preview` → `commit`, then verify with `+flow_detail`.
39
41
 
40
42
  ---
41
43
 
@@ -54,7 +56,6 @@ You still organize user requirements into an intermediate intent first, then map
54
56
  | `nodes` | array | build | Compact nodes for structured build (see §7) |
55
57
  | `edges` | array | build | Compact edges for structured build (see §8) |
56
58
  | `dsl` | string | build | Topology-only: lines `node <id> <type>` and `edge <source> -> <target>` |
57
- | `sourceFlowUuid` | string | build | Clone an existing flow into a new draft |
58
59
  | `flowUuid` | string | build | Draft flow UUID for update-draft mode |
59
60
  | `parentFlowUuid` | string | build | Base version flow UUID for new-version mode |
60
61
  | `userIntent` | string | build | Natural-language intent (optional) |
@@ -69,6 +70,23 @@ You still organize user requirements into an intermediate intent first, then map
69
70
 
70
71
  `flowUuid` and `parentFlowUuid` are mutually exclusive; when creating a brand-new draft, provide neither.
71
72
 
73
+ ### Response Fields
74
+
75
+ Common response fields include:
76
+
77
+ | Field | Meaning |
78
+ |---|---|
79
+ | `status` | Draft state, such as `need_input`, `ready_to_preview`, `previewed`, or `committed` |
80
+ | `draftId` / `draftVersion` | Server draft identity and version |
81
+ | `selectedMode` | Server-selected authoring mode, such as structured build, wizard, or draft edit |
82
+ | `confidence` / `reason` | Router confidence and explanation for the selected mode |
83
+ | `nextSlot` | One missing slot to answer when `status=need_input` |
84
+ | `preview` | Human-readable preview; use it for user confirmation |
85
+ | `confirmToken` | Token returned by `preview`; required for `commit` |
86
+ | `warnings` / `errors` | Soft warnings and hard validation failures |
87
+ | `supportedOperations` | Server-advertised `build`, `preview`, and `commit` contract |
88
+ | `result` | Commit result, including the final `flowUuid` when committed |
89
+
72
90
  ### Compact node (`nodes[]`)
73
91
 
74
92
  | Field | Required | Description |
@@ -86,7 +104,7 @@ You still organize user requirements into an intermediate intent first, then map
86
104
  | `source` | Yes | Upstream node ID |
87
105
  | `target` | Yes | Downstream node ID |
88
106
  | `edgeId` | No | Edge ID, unique within the canvas |
89
- | `sourceBranchId` | No | Branch ID for edges leaving a split/judge node |
107
+ | `sourceBranchId` | No | Branch ID for edges leaving a split/judge node, or a push action node with two branch outgoing edges |
90
108
  | `config` | No | Edge business config as JSON string |
91
109
 
92
110
  ---
@@ -217,36 +235,47 @@ Inside action nodes: `channel_name` → real `channelId`; `content` → `content
217
235
  2. Any `branchId` later referenced by `edge.sourceBranchId` must be declared in that node's `config` first.
218
236
  3. Every path must eventually end at `exit_flow`.
219
237
  4. `config` may be a JSON object or a JSON string. (`targetClusterQp` inside it is usually a `JSON.stringify`'d string — see §9.)
238
+ 5. The backend normalizes some compatible input forms before validation: leading apostrophes on field names are stripped, property names are matched case-insensitively when unambiguous, `enableChannelTouchLimits` booleans become `1`/`0`, `targetClusterQp` relation strings `"0"`/`"1"` become numeric values inside the JSON string, and `clusterPredictCount: null` becomes `0`.
220
239
 
221
240
  ### 7.2 Common Node Types
222
241
 
223
242
  `single_trigger`, `repeat_trigger`, `event_trigger`, `event_split_flow`, `feature_split_flow`, `ab_split_flow`, `event_judge`, `feature_judge`, `message_push`, `wechat_push`, `webhook_push`, `time_control`, `exit_flow`.
224
243
 
244
+ Before writing any config below, call `+flow_node_config_schema` for the exact node type. The backend schema is the source of truth for required fields, defaults, allowed enum values, submit-time requirements, and examples.
245
+
225
246
  ### 7.3 Common `config` Templates
226
247
 
248
+ #### `single_trigger`
249
+
250
+ ```json
251
+ { "targetUserType": 2, "triggerTime": "<YYYY-MM-DD HH:mm>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "targetClusterName": "<existing clusterName>" }
252
+ ```
253
+
254
+ For custom users, use `targetUserType=1` and fill `targetClusterQp` with the QP JSON string returned by the cluster QP workflow. For existing clusters (`targetUserType=2`), fill `targetClusterName` from a real current-project cluster list queried with the flow `tzOffset`; do not fill `targetClusterQp`. `clusterPredictCount` defaults to `0` and `clusterPredictTime` defaults to `""` when omitted.
255
+
227
256
  #### `repeat_trigger`
228
257
 
229
258
  ```json
230
- { "targetUserType": 1, "startDate": "<YYYY-MM-DD>", "endDate": "<YYYY-MM-DD>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "crontab": "0 00 09 * * ?", "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterName": null, "clusterPredictCount": null, "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>", "targetClusterQp": "<JSON.stringify(qp)>" }
259
+ { "targetUserType": 1, "startDate": "<YYYY-MM-DD>", "endDate": "<YYYY-MM-DD>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "crontab": "0 00 09 * * ?", "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterName": null, "targetClusterQp": "<JSON.stringify(qp)>" }
231
260
  ```
232
261
 
233
- `entry.segment` → `targetClusterQp`; `entry.schedule` → `crontab` (common default `0 00 09 * * ?`).
262
+ `entry.segment` → `targetClusterQp`; `entry.schedule` → `crontab` (common default `0 00 09 * * ?`). `clusterPredictCount` defaults to `0` and `clusterPredictTime` defaults to `""` when omitted. For existing clusters (`targetUserType=2`), fill `targetClusterName` from a real current-project cluster list queried with the flow `tzOffset`; do not fill `targetClusterQp`.
234
263
 
235
264
  #### `event_trigger`
236
265
 
237
266
  ```json
238
- { "triggerType": 3, "targetUserType": 1, "realtime": 0, "clusterRefresh": 12, "clusterRefreshTime": null, "startDate": "<YYYY-MM-DD HH:mm>", "endDate": "<YYYY-MM-DD HH:mm>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "clusterPredictCount": null, "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>", "triggerRule": [ { "periodStart": "<startDate>", "periodEnd": "<endDate>", "periodTimeSymbol": "TS02", "dayStartTime": null, "startDay": null, "eventTriggerType": 0, "zoneoffset": 8, "events": [] } ], "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterQp": "<JSON.stringify(qp) or null>" }
267
+ { "triggerType": 3, "targetUserType": 1, "startDate": "<YYYY-MM-DD HH:mm>", "endDate": "<YYYY-MM-DD HH:mm>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "triggerRule": [ { "periodStart": "<startDate>", "periodEnd": "<endDate>", "periodTimeSymbol": "TS02", "eventTriggerType": 0, "events": [] } ], "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterQp": "<JSON.stringify(qp) or null>" }
239
268
  ```
240
269
 
241
- `entry.trigger_event` → `triggerRule[0].events`; generate `targetClusterQp` only when `entry.segment` exists.
270
+ `entry.trigger_event` → `triggerRule[0].events`; generate `targetClusterQp` only when `entry.segment` exists. `triggerType` supports `3`, `4`, and `5`; `targetUserType=2` existing cluster is not supported for `event_trigger`; use `1` custom or `3` all users. For non-branch trigger rules, use `periodStart` / `periodEnd` / `periodTimeSymbol`. `realtime`, `clusterRefresh`, `clusterRefreshTime`, `clusterPredictTime`, and `triggerRule[].zoneoffset` can be omitted and are defaulted by the backend.
242
271
 
243
272
  #### `event_split_flow`
244
273
 
245
274
  ```json
246
- { "splitFlowType": 1, "branchList": [ { "branchId": "<branchId>", "branchName": "<label>", "branchType": 1, "triggerRule": [ { "delayTimeSymbol": "<minute|hour|day>", "delayTime": "<number>", "eventTriggerType": "<0 or -1>", "zoneoffset": 8, "events": [] } ] } ] }
275
+ { "splitFlowType": 1, "branchList": [ { "branchId": "<branchId>", "branchName": "<label>", "branchType": 1, "targetClusterType": 3, "triggerRule": [ { "delayTimeSymbol": "<minute|hour|day>", "delayTime": "<number>", "eventTriggerType": "<0|-1|1|2>", "events": [] } ] } ] }
247
276
  ```
248
277
 
249
- `time_limit` → `delayTimeSymbol` + `delayTime`; `0` = happened, `-1` = not happened. Fallback branch keeps only `{ "branchId": "<branchId>", "branchType": 2 }`.
278
+ `time_limit` → `delayTimeSymbol` + `delayTime`; `0` = happened, `-1` = not happened. For `branchType=1`, fill `targetClusterType`; use `3` for all users. If `targetClusterType` is not `3`, fill `clusterKey`. `occasionKeys` is optional, but each item must contain at least four colon-separated parts. Fallback branch keeps only `{ "branchId": "<branchId>", "branchType": 2 }` and must omit `triggerRule`.
250
279
 
251
280
  #### `feature_split_flow`
252
281
 
@@ -265,10 +294,10 @@ Fallback branch keeps only `branchId` + `branchType: 2`.
265
294
  #### `event_judge`
266
295
 
267
296
  ```json
268
- { "transferType": 1, "meetBranchId": "<meetBranchId>", "notMeetBranchId": "<notMeetBranchId>", "triggerRule": [ { "delayTimeSymbol": "<minute|hour|day>", "delayTime": "<number>", "eventTriggerType": 0, "zoneoffset": 8, "events": [] } ] }
297
+ { "transferType": 1, "meetBranchId": "<meetBranchId>", "notMeetBranchId": "<notMeetBranchId>", "triggerRule": [ { "periodStart": "<YYYY-MM-DD HH:mm>", "periodEnd": "<YYYY-MM-DD HH:mm>", "periodTimeSymbol": "TS02", "eventTriggerType": 0, "events": [] } ] }
269
298
  ```
270
299
 
271
- `wait_time` `delayTimeSymbol` + `delayTime` (default `30 minute` if unspecified).
300
+ `event_judge` is a non-branch flow task. Use `periodStart`, `periodEnd`, and `periodTimeSymbol` in the A segment; use `delayTime` / `delayTimeSymbol` only for a B segment when the schema/example requires it. `eventTriggerType` supports `0`, `1`, and `2`.
272
301
 
273
302
  #### `feature_judge`
274
303
 
@@ -279,10 +308,10 @@ Fallback branch keeps only `branchId` + `branchType: 2`.
279
308
  #### `message_push` / `webhook_push`
280
309
 
281
310
  ```json
282
- { "channelId": "<matched channelId>", "channelType": "<matched channelType>", "enableChannelTouchLimits": false, "isOccasionUp": false, "contentList": [ { "pushLanguageCode": "default", "content": [] } ], "processType": 1 }
311
+ { "channelId": "<matched channelId>", "channelType": "<matched channelType>", "contentList": [ { "pushLanguageCode": "default", "content": [] } ] }
283
312
  ```
284
313
 
285
- `channel_name` → real `channelId`; `content` → the param that best matches body text. When the param `type = TEXT`, also add `{ "config": "[{\"type\":\"paragraph\",\"children\":[{\"text\":\"<same as value>\"}]}]" }`. First `contentList` entry must use `"pushLanguageCode": "default"`; generate extra languages per `languages`.
314
+ `channel_name` → real `channelId`; `content` → the param that best matches body text. `processType` defaults to `1`, `enableChannelTouchLimits` defaults to `0`, and `isOccasionUp` defaults to `false`. `enableChannelTouchLimits` may be supplied as a boolean for compatibility, but `normalizedConfigObject` will convert it to `1` or `0`. When the param `type = TEXT`, also add `{ "config": "[{\"type\":\"paragraph\",\"children\":[{\"text\":\"<same as value>\"}]}]" }`. `contentList[].content` should be a JSON array; validation also accepts a JSON-stringified array for compatibility. When the param `type = OBJ_ARRAY`, `value` must be a JSON array, and the item must copy the complete child field definition from `query_channel_detail data.config.paramsList[].objArray`. First `contentList` entry must use `"pushLanguageCode": "default"`; generate extra languages per `languages`.
286
315
 
287
316
  #### `wechat_push`
288
317
 
@@ -296,6 +325,8 @@ Fallback branch keeps only `branchId` + `branchType: 2`.
296
325
  { "controlType": 1, "timeUnit": "<minute|hour|day>", "timeUnitNum": "<number>" }
297
326
  ```
298
327
 
328
+ `controlType=1` requires `timeUnit` + `timeUnitNum`; `2` requires `timePointStr`; `3` requires `rollTimeDayNum` + `timePointStr`; `4` requires `fixedDay` + `timePointStr`; `5` requires `relativeMonthLastDayNum` + `timePointStr`.
329
+
299
330
  `30 minutes` → `minute`+`30`; `2 hours` → `hour`+`2`; `1 day` → `day`+`1`.
300
331
 
301
332
  #### `exit_flow`
@@ -325,14 +356,17 @@ Minimum usable `config`: `{}`.
325
356
  | `single_trigger` / `repeat_trigger` / `event_trigger` | 1 | do not provide |
326
357
  | `event_split_flow` / `feature_split_flow` / `ab_split_flow` | one per branch | the corresponding `branchList[].branchId` |
327
358
  | `event_judge` / `feature_judge` | 2 | `meetBranchId` and `notMeetBranchId` |
328
- | `message_push` / `wechat_push` / `webhook_push` / `time_control` | 1 | do not provide |
359
+ | `message_push` / `wechat_push` / `webhook_push` | 1 or 2 | omit for 1 outgoing edge; for 2 outgoing edges, use the node config's `meetBranchId` and `notMeetBranchId` |
360
+ | `time_control` | 1 | do not provide |
329
361
  | `exit_flow` | 0 | do not provide |
330
362
 
331
363
  ### 8.4 Rules
332
364
 
333
365
  1. `source` / `target` must reference existing `node.id` values.
334
- 2. Only edges leaving split/judge nodes carry `sourceBranchId`, and it must be a `branchId` already declared in the upstream node `config`.
335
- 3. The graph must be a DAG (no cycles).
366
+ 2. Edges leaving split/judge nodes carry `sourceBranchId`. Push action nodes (`message_push`, `wechat_push`, `webhook_push`) may also carry `sourceBranchId` when they have exactly two outgoing edges.
367
+ 3. For push action nodes with one outgoing edge, omit `meetBranchId` / `notMeetBranchId`; if present, the backend ignores them.
368
+ 4. For push action nodes with two outgoing edges, set both `config.meetBranchId` and `config.notMeetBranchId`, and make the two `edge.sourceBranchId` values match them.
369
+ 5. The graph must be a DAG (no cycles).
336
370
 
337
371
  ---
338
372
 
@@ -436,7 +470,7 @@ ae-cli engage +save_flow --project_id 1 --req '{
436
470
  "flowDesc": "New user welcome flow",
437
471
  "groupId": 0, "tzOffset": 8, "versionType": 1,
438
472
  "nodes": [
439
- { "id": "n1", "type": "single_trigger", "name": "Enter", "config": {} },
473
+ { "id": "n1", "type": "single_trigger", "name": "Enter", "config": { "targetUserType": 2, "triggerTime": "2026-03-31 19:00", "flowEndDate": "2026-04-04 18:00", "targetClusterName": "cohort_20260331_182643" } },
440
474
  { "id": "n2", "type": "exit_flow", "name": "End", "config": {} }
441
475
  ],
442
476
  "edges": [ { "source": "n1", "target": "n2" } ]
@@ -483,6 +517,7 @@ Output the complete `req` JSON for debugging plus a clear failure reason.
483
517
  | Symptom | Cause | Fix |
484
518
  |---|---|---|
485
519
  | `Unsupported save_flow operation: null` | Legacy `nodeList`/`edgeList` payload, or `operation` missing | Put `operation` = `build`/`preview`/`commit` in `req`, use `nodes`/`edges` |
520
+ | `Flag --req.sourceFlowUuid is no longer supported` | Removed clone mode from an older protocol | Call `+flow_detail`, convert detail `nodeList`/`edgeList` into compact `nodes`/`edges`, then create with `operation=build` |
486
521
  | operation rejected (`SAVE`/`DRAFT`/`SUBMIT`/`mode`/`action`…) | Wrong field or wrong enum | `operation` is at `req.operation`; enum is only `build`/`preview`/`commit` |
487
522
  | `invalid_qp_relation: QP relation must be number 0 or 1` | `relation` sent as string | Use integer `0`/`1` |
488
523
  | `invalid_qp_leaf: QP property leaf must contain columnType/columnDesc` | userCondition leaf missing fields | Add `columnType` + `columnDesc` |
@@ -499,16 +534,17 @@ Output the complete `req` JSON for debugging plus a clear failure reason.
499
534
  ## 13. Most Common Mistakes
500
535
 
501
536
  1. **Legacy `nodeList`/`edgeList`** — use `nodes`/`edges` with `operation=build`.
502
- 2. **Time units must be lowercase** — `day`, `hour`, `minute`, `week`, `month` (not `DAY`/`HOUR`).
503
- 3. **Do not invent `channelId`**get it from `ae-cli engage +channel_list`.
504
- 4. **Define branch IDs before referencing them** `edge.sourceBranchId` must already exist in the upstream node `config`.
505
- 5. **`targetClusterQp` is usually a string** — `JSON.stringify` the QP object.
506
- 6. **TEXT rich-text `config` must also be a string** — not an object.
507
- 7. **`commit` uses preview's token/version** — not build's.
508
- 8. **Do not merge branches again when `splitFlowType = 2`**.
537
+ 2. **Removed clone mode** — do not pass `sourceFlowUuid`; copy flows via `+flow_detail` and a fresh `operation=build` request.
538
+ 3. **Time units must be lowercase** `day`, `hour`, `minute`, `week`, `month` (not `DAY`/`HOUR`).
539
+ 4. **Do not invent `channelId`**get it from `ae-cli engage +channel_list`.
540
+ 5. **Define branch IDs before referencing them** — `edge.sourceBranchId` must already exist in the upstream node `config`; for two-edge push action nodes, use `meetBranchId` and `notMeetBranchId`.
541
+ 6. **`targetClusterQp` is usually a string** — `JSON.stringify` the QP object.
542
+ 7. **TEXT rich-text `config` must also be a string** — not an object.
543
+ 8. **`commit` uses preview's token/version** not build's.
544
+ 9. **Do not merge branches again when `splitFlowType = 2`**.
509
545
 
510
546
  ---
511
547
 
512
548
  ## 14. One-Sentence Summary
513
549
 
514
- Drive `+save_flow` as a state machine — `build` (`nodes`/`edges`, not `nodeList`/`edgeList`) → resolve any `need_input` slots → `preview` (take its fresh `draftVersion` + `confirmToken`) → `commit` → verify with `+flow_detail`; keep QP `relation` integer, fill `columnType`/`columnDesc` on userCondition leaves and `quotaDesc`/`quota`/`analysisParams` on `taPropQuota`, and ensure touchpoint channels are enabled before referencing them.
550
+ Drive `+save_flow` as a state machine — `build` (`nodes`/`edges`, not `nodeList`/`edgeList` or `sourceFlowUuid`) → resolve any `need_input` slots → `preview` (take its fresh `draftVersion` + `confirmToken`) → `commit` → verify with `+flow_detail`; keep QP `relation` integer, fill `columnType`/`columnDesc` on userCondition leaves and `quotaDesc`/`quota`/`analysisParams` on `taPropQuota`, and ensure touchpoint channels are enabled before referencing them.
@@ -1,7 +1,7 @@
1
1
  # ae-engage +validate_flow_node_config
2
2
 
3
3
 
4
- Validate a single node configuration before saving a flow.
4
+ Validate and normalize a single node configuration before placing it into a `save_flow` request.
5
5
 
6
6
  Mapped command: `ae-cli engage +validate_flow_node_config`
7
7
 
@@ -9,15 +9,38 @@ Mapped command: `ae-cli engage +validate_flow_node_config`
9
9
 
10
10
  | Flag | Type | Required | Description |
11
11
  |------|------|------|------|
12
- | `--node_type` | string | Yes | node type |
13
- | `--config` | string | Yes | node config JSON string |
14
- | `--operation_mode` | string | Yes | validation mode |
12
+ | `--node_type` | string | Yes | Flow node type |
13
+ | `--config` | string | Yes | Node config JSON object encoded as a string |
14
+ | `--operation_mode` | string | Yes | Validation mode |
15
+
16
+ ## When To Use
17
+
18
+ Use this after `+flow_node_config_schema` and before passing a config into `+save_flow`.
19
+
20
+ The command validates one node config only; it does not validate the full canvas topology. It returns:
21
+
22
+ - `valid`: whether the candidate config passed validation
23
+ - `normalizedConfigObject`: backend-normalized config with defaulted fields
24
+ - `errors`: hard validation failures to fix before calling `+save_flow`
25
+ - `warnings`: issues that depend on live channel/template/config data
26
+
27
+ Use `--operation_mode save_flow` for the current exposed MCP protocol. Use `save_submit_flow` only when you intentionally want stricter submit-time checks.
28
+
29
+ Important current rules:
30
+
31
+ - `event_trigger` / `event_judge` A segment: use `periodStart`, `periodEnd`, `periodTimeSymbol`; do not use branch-style `delayTime`.
32
+ - `event_split_flow` branch segment: use `delayTime`, `delayTimeSymbol`, `targetClusterType`; omit `triggerRule` on default branches.
33
+ - `event_trigger targetUserType=2` is invalid.
34
+ - Push `OBJ_ARRAY.value` must be a JSON array, not a stringified array.
35
+ - Push `contentList[].content` should be a JSON array, but a JSON-stringified array is accepted for compatibility.
36
+ - Compatible inputs are normalized before validation: apostrophe-prefixed field aliases, case-insensitive property aliases, `enableChannelTouchLimits` booleans, string `"0"`/`"1"` QP relations inside `targetClusterQp`, and `clusterPredictCount: null`.
37
+ - Missing defaults such as `clusterPredictCount`, `clusterPredictTime`, `processType`, and `zoneoffset` may be filled in `normalizedConfigObject`.
15
38
 
16
39
  ## Enum Notes
17
40
 
18
41
  ### `--node_type`
19
42
 
20
- Common node types include:
43
+ Schema-backed node types include:
21
44
 
22
45
  - `single_trigger`
23
46
  - `repeat_trigger`
@@ -27,15 +50,10 @@ Common node types include:
27
50
  - `message_push`
28
51
  - `wechat_push`
29
52
  - `webhook_push`
30
- - `config_push`
31
- - `tag`
32
53
  - `time_control`
33
54
  - `feature_split_flow`
34
55
  - `event_split_flow`
35
- - `trigger_prop_split_flow`
36
- - `percent_split_flow`
37
56
  - `ab_split_flow`
38
- - `race_split_flow`
39
57
  - `exit_flow`
40
58
 
41
59
  ### `--operation_mode`
@@ -97,7 +97,8 @@ First, check if `.ae-cli/draft.json` exists and read existing configuration:
97
97
  - If the project is missing, ambiguous, or has no `appId`, ask the user to copy APP_ID from AE Admin → "Project Settings" → "Integration Config".
98
98
  2. **SERVER_URL** — Data ingestion endpoint (**different from web URL**; go to AE Admin → "Project Settings" → "Integration Config" → fill in "Public URL")
99
99
  - If `meta.project_id` is known, you may try `ae-cli analysis_meta +get_project_config --project_id <project_id>` once.
100
- - Use the returned value only if the response explicitly contains a receiver URL field such as `serverUrl`, `pushUrl`, `push_url`, `receiverUrl`, `publicUrl`, or equivalent ingestion endpoint field.
100
+ - Use the returned value only if the response explicitly contains a receiver URL field such as `serverUrl`, `pushUrl`, `push_url`, `receiverUrl`, `publicUrl`, `publicReceiverAddress`, `privateReceiverAddress`, or equivalent ingestion endpoint field.
101
+ - If both `publicReceiverAddress` and `privateReceiverAddress` are present, prefer `publicReceiverAddress` as `SERVER_URL` for generated snippets unless the user explicitly needs an internal/private-network receiver.
101
102
  - If a value is found, ask: **"I found SERVER_URL `<url>` for project `<projectId>`. Use it? yes / enter new value"**
102
103
  - ⚠️ "Public URL" only shows if previously filled in; if empty, this field won't display
103
104
  - Solution: ask ops for the URL, or **skip this step** (use `SERVER_URL` or `PUSH_URL` placeholder in code)
@@ -507,6 +508,20 @@ Upload list rules:
507
508
  - Include generated debug scripts if the user selected the debug option.
508
509
  - Do not upload files inserted directly into the user's project; only upload generated output artifacts.
509
510
 
511
+ ### Attachment upload compatibility
512
+
513
+ The Agent attachment backend accepts a limited document MIME set. Code/config artifacts such as `.java`, `.kt`, `.swift`, `.m`, `.ets`, `.cs`, `.py`, `.go`, `.ts`, `.js`, `.php`, and `.json` may be rejected if uploaded directly.
514
+
515
+ Before running `ae-cli agent +add-attachment`, prepare the upload list as follows:
516
+ - Keep every original generated file unchanged under `.ae-cli/output/`.
517
+ - For each generated text artifact whose extension may be unsupported by the attachment backend, create an upload-only sibling copy by appending `.txt` to the filename.
518
+ - Example: `.ae-cli/output/java-sdk.java` → `.ae-cli/output/java-sdk.java.txt`
519
+ - Example: `.ae-cli/output/daemon.json` → `.ae-cli/output/daemon.json.txt`
520
+ - The `.txt` copy must have identical content to the original file. Do not wrap it in markdown fences, do not add headers, and do not change line endings intentionally.
521
+ - Upload the `.txt` compatibility copies instead of the unsupported originals.
522
+ - Keep `.md`, `.txt`, and `.csv` artifacts in the upload list as-is.
523
+ - In the final response, list the original deliverable paths first, then mention any `.txt` compatibility copies used only for attachment upload.
524
+
510
525
  If upload succeeds, include the attachment upload result in the final response and tell the user the files are available from the file/attachment management entry. If upload fails because Agent attachment credentials are unavailable, keep the local `.ae-cli/output/` files and tell the user the upload did not complete.
511
526
 
512
527
  ### All snippets
@@ -247,6 +247,22 @@ Upload list must include:
247
247
 
248
248
  Only upload generated output artifacts. Do not upload files inserted directly into the user's project.
249
249
 
250
+ ### Upload Compatibility for Code and Config Files
251
+
252
+ The attachment upload endpoint accepts a limited document MIME set. Many generated tracking artifacts are valid text files but have extensions that may be rejected by the backend when uploaded directly, including `.java`, `.kt`, `.swift`, `.m`, `.ets`, `.cs`, `.py`, `.go`, `.ts`, `.js`, `.php`, and `.json`.
253
+
254
+ Before calling `ae-cli agent +add-attachment`, build an upload-safe file list:
255
+
256
+ 1. Keep the original generated files unchanged in `.ae-cli/output/`.
257
+ 2. For each unsupported text artifact, create a sibling upload-only copy with `.txt` appended to the original filename.
258
+ - `.ae-cli/output/android-sdk-java.java` → `.ae-cli/output/android-sdk-java.java.txt`
259
+ - `.ae-cli/output/daemon.json` → `.ae-cli/output/daemon.json.txt`
260
+ 3. Copy the content exactly. Do not add markdown fences, comments, titles, or any extra bytes beyond the original text content.
261
+ 4. Upload the `.txt` compatibility copies instead of the unsupported originals.
262
+ 5. Upload already-supported text artifacts such as `.md`, `.txt`, and `.csv` directly.
263
+
264
+ The final deliverable list should still point users to the original generated files. Mention the `.txt` files only as attachment-upload compatibility copies.
265
+
250
266
  If upload succeeds, report that the files are available from the file/attachment management entry. If upload fails because Agent attachment credentials are unavailable, preserve the local output files and report the upload failure separately.
251
267
 
252
268
  ---
@@ -325,7 +341,7 @@ After generation, perform language style checks on each output file:
325
341
 
326
342
  #### Step 5: Upload Generated Artifacts
327
343
 
328
- Upload all generated `.ae-cli/output/` artifacts to the Agent attachment library using `ae-cli agent +add-attachment --yes --files '<json-array>'`.
344
+ Prepare upload compatibility copies for unsupported code/config extensions, then upload the safe file list to the Agent attachment library using `ae-cli agent +add-attachment --yes --files '<json-array>'`.
329
345
 
330
346
  ---
331
347
 
@@ -82,7 +82,7 @@ Phase 0 → 1 → 2 → 3 → 4, do not skip steps.
82
82
  > Determine `<user_lang>` from user's input language: Chinese→`zh`, English→`en`, Japanese→`ja`, Korean→`ko`. Other languages default to `en`.
83
83
  > All subsequent CLI commands must be prefixed with `AE_LANG=<user_lang>` to ensure CLI output and generated xlsx headers match the user's language.
84
84
 
85
- Collect the following **5 items** sequentially, **do NOT ask all at once**:
85
+ Collect the following **4 items** sequentially, **do NOT ask all at once**:
86
86
 
87
87
  ### Item 1 — Application Scenario
88
88
 
@@ -94,14 +94,14 @@ After user responds, record to `meta.scenario` and generate `meta.plan_name`.
94
94
 
95
95
  Before asking, decide whether the current runtime is an agent sandbox. The agent may judge this from runtime context such as sandbox-provisioned `cli-token.json`, restricted filesystem access, or absence of the user's local files. Do not ask the user just to decide sandbox visibility.
96
96
 
97
- Product document and Codebase are local-material options. **Hide both options in sandbox environments**. When options are hidden, renumber the visible list contiguously from 1; never show skipped numbers.
97
+ Product document is available in sandbox environments **only for files that are readable inside the sandbox workspace**, including files the user attaches/uploads into the conversation workspace. It cannot read arbitrary local paths outside the sandbox unless those files are mounted or attached. Codebase is a local-material option and must be hidden in sandbox environments unless the codebase is already present in the readable workspace. When options are hidden, renumber the visible list contiguously from 1; never show skipped numbers.
98
98
 
99
99
  If **not** in a sandbox environment, ask exactly:
100
100
 
101
101
  ```text
102
102
  Choose your source material (up to 2):
103
103
 
104
- 1 - Product document (local path, image file, or folder; hidden in sandbox) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp)
104
+ 1 - Product document (local path, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp)
105
105
  2 - Detailed description (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
106
106
  3 - Codebase (local project path; hidden in sandbox) — Analyze source code to extract events and properties
107
107
  4 - Pre-built template (built-in industry and game genre templates) — Select a built-in template
@@ -114,22 +114,24 @@ If in a sandbox environment, ask exactly:
114
114
  ```text
115
115
  Choose your source material (up to 2):
116
116
 
117
- 1 - Detailed description (conversational) Describe app business flow, core features, user behaviors, monetization model, etc.
118
- 2 - Pre-built template (built-in industry and game genre templates) Select a built-in template
117
+ 1 - Product document (sandbox workspace path, uploaded attachment, URL, image file, or folder) Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp). You can attach/upload relevant files here.
118
+ 2 - Detailed description (conversational) Describe app business flow, core features, user behaviors, monetization model, etc.
119
+ 3 - Pre-built template (built-in industry and game genre templates) — Select a built-in template
119
120
 
120
- Reply with number(s), e.g. 1 or 1,2. Select up to 2.
121
+ Reply with number(s), e.g. 1 or 1,3. Select up to 2.
121
122
  ```
122
123
 
123
124
  Do not rewrite this source material list as unnumbered bullets, cards, or prose. The user must be able to reply with the visible numbers.
125
+ When translating this prompt, preserve the numeric prefixes and line breaks exactly. Every visible option MUST be on its own line and MUST begin with `1 -`, `2 -`, `3 -`, etc. Never place two numbered options in the same paragraph or visual line. If a Markdown renderer may collapse soft line breaks, use Markdown hard line breaks (two trailing spaces before newline) rather than blank lines. Translation may change only the option text, not the numbering prefix or one-option-per-line structure.
124
126
 
125
127
  User can multi-select (max 2). Interpret numbers by the **visible list shown to the user**, not by the non-sandbox canonical list.
126
128
 
127
- Canonical source material options:
129
+ Canonical source material options (non-sandbox numbering):
128
130
 
129
- - **Product document** (local path, image file, or folder; hidden in sandbox) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp)
130
- - **Detailed description** (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
131
- - **Codebase** (local project path; hidden in sandbox) — Analyze source code to extract events and properties
132
- - **Pre-built template** (built-in industry and game genre templates) — Select a built-in template (run `AE_LANG=<user_lang> ae-cli tracking plan list-templates --json` to see available templates)
131
+ 1. **Product document** ****(****local path, sandbox workspace path, uploaded attachment, URL, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp)
132
+ 2. **Detailed description** (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
133
+ 3. **Codebase** (local project path; hidden in sandbox) — Analyze source code to extract events and properties
134
+ 4. **Pre-built template** (built-in industry and game genre templates) — Select a built-in template (run `AE_LANG=<user_lang> ae-cli tracking plan list-templates --json` to see available templates)
133
135
 
134
136
  Based on user selection, determine source material type and record to `meta.source_type`:
135
137
 
@@ -142,7 +144,29 @@ Based on user selection, determine source material type and record to `meta.sour
142
144
  | Any two-item combo | Join two types with `_` | First as baseline, second as supplement (priority: template → codebase → prd → chat) |
143
145
 
144
146
  **Follow-up questions** (ask in selection order):
145
- - Product doc → ask **"What is the product document path? You can provide one or more paths, separated by commas or newlines (local paths, URLs, image files, or folders)"**
147
+ - Product doc → if not in a sandbox environment, ask exactly:
148
+ ```text
149
+ What is the product document path?
150
+
151
+ You can provide one or more items, separated by commas or newlines:
152
+ 1. Local file path
153
+ 2. URL
154
+ 3. Image file path
155
+ 4. Folder path
156
+ ```
157
+ - Product doc → if in a sandbox environment, ask exactly:
158
+ ```text
159
+ What is the product document path?
160
+
161
+ You can provide one or more items, separated by commas or newlines:
162
+ 1. Sandbox workspace path
163
+ 2. Uploaded attachment path
164
+ 3. URL
165
+ 4. Image file path
166
+ 5. Folder path
167
+
168
+ You can also attach/upload relevant files here, and I will read them from the sandbox workspace if available.
169
+ ```
146
170
  - Detailed description → If too vague, follow up on core features, user behaviors, business flows, monetization
147
171
  - Codebase → ask **"What is the project directory path?"**, then scan source to extract business logic
148
172
  - Pre-built template → display matching templates for user confirmation
@@ -1,105 +0,0 @@
1
- import {
2
- getToken,
3
- load,
4
- loadCliToken,
5
- save
6
- } from "./chunk-PFJFZVCK.js";
7
- import {
8
- getActiveHost,
9
- getFallbackCliToken,
10
- listHosts,
11
- logger,
12
- safeJsonParse
13
- } from "./chunk-65DKFJZB.js";
14
-
15
- // src/core/cli-token.ts
16
- var CLI_TOKEN_GENERATE_PATH = "/v1/ta/cli/token/generate";
17
- var _cliTokenCache = /* @__PURE__ */ new Map();
18
- async function generateCliToken(hostUrl) {
19
- const accessToken = await getToken(hostUrl);
20
- const base = hostUrl.replace(/\/+$/, "");
21
- const url = `${base}${CLI_TOKEN_GENERATE_PATH}`;
22
- const resp = await fetch(url, {
23
- method: "GET",
24
- headers: {
25
- "Authorization": `bearer ${accessToken}`
26
- }
27
- });
28
- if (!resp.ok) {
29
- throw new Error(`CLI token generate HTTP error: ${resp.status} ${resp.statusText}`);
30
- }
31
- const data = safeJsonParse(await resp.text());
32
- if (data.return_code !== 0) {
33
- throw new Error(`CLI token generate error: ${data.return_message || "unknown"} (code: ${data.return_code})`);
34
- }
35
- const cliToken = data.data?.userSecret;
36
- if (!cliToken) {
37
- throw new Error("CLI token generate error: empty userSecret in response");
38
- }
39
- return cliToken;
40
- }
41
- function persistCliTokenIfPossible(hostUrl, cliToken) {
42
- const existing = load(hostUrl);
43
- if (!existing) {
44
- logger.info(`cli-token: no secure-store session for ${hostUrl}, keeping token in-process only`);
45
- return;
46
- }
47
- save(hostUrl, { ...existing, cliToken });
48
- }
49
- function clearPersistedCliToken(hostUrl) {
50
- const existing = load(hostUrl);
51
- if (existing?.cliToken) {
52
- save(hostUrl, { ...existing, cliToken: void 0 });
53
- }
54
- }
55
- async function getCliToken(hostOverride) {
56
- const hostUrl = hostOverride || getActiveHost();
57
- const cached = _cliTokenCache.get(hostUrl);
58
- if (cached) {
59
- return cached;
60
- }
61
- const storedToken = loadCliToken(hostUrl);
62
- if (storedToken) {
63
- _cliTokenCache.set(hostUrl, storedToken);
64
- logger.info(`Using persisted CLI token (secure-store) for ${hostUrl}`);
65
- return storedToken;
66
- }
67
- const fallbackToken = getFallbackCliToken(hostUrl);
68
- if (fallbackToken) {
69
- _cliTokenCache.set(hostUrl, fallbackToken);
70
- logger.info(`Using sandbox-provisioned CLI token (fallback file) for ${hostUrl}`);
71
- return fallbackToken;
72
- }
73
- return mintCliToken(hostUrl);
74
- }
75
- async function mintCliToken(hostUrl) {
76
- logger.info(`Generating CLI token for ${hostUrl}`);
77
- const cliToken = await generateCliToken(hostUrl);
78
- _cliTokenCache.set(hostUrl, cliToken);
79
- persistCliTokenIfPossible(hostUrl, cliToken);
80
- logger.info(`CLI token generated, cached, and persisted for ${hostUrl}`);
81
- return cliToken;
82
- }
83
- function clearCliToken(hostUrl) {
84
- if (hostUrl) {
85
- _cliTokenCache.delete(hostUrl);
86
- clearPersistedCliToken(hostUrl);
87
- return;
88
- }
89
- _cliTokenCache.clear();
90
- for (const { url } of listHosts()) {
91
- clearPersistedCliToken(url);
92
- }
93
- }
94
- function setCliTokenManual(token, hostUrl) {
95
- _cliTokenCache.set(hostUrl, token);
96
- persistCliTokenIfPossible(hostUrl, token);
97
- logger.info(`CLI token set for ${hostUrl}`);
98
- }
99
-
100
- export {
101
- getCliToken,
102
- mintCliToken,
103
- clearCliToken,
104
- setCliTokenManual
105
- };
@@ -1,14 +0,0 @@
1
- import {
2
- clearCliToken,
3
- getCliToken,
4
- mintCliToken,
5
- setCliTokenManual
6
- } from "./chunk-OCQPQYHZ.js";
7
- import "./chunk-PFJFZVCK.js";
8
- import "./chunk-65DKFJZB.js";
9
- export {
10
- clearCliToken,
11
- getCliToken,
12
- mintCliToken,
13
- setCliTokenManual
14
- };