@thinkingai/ae-cli 6.1.14 → 6.1.17

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 (94) hide show
  1. package/README.md +5 -2
  2. package/README.zh.md +5 -2
  3. package/dist/{auth-GBMV6TEJ.js → auth-2WTQOP77.js} +3 -3
  4. package/dist/{auth-NDSXE54J.js → auth-77BUFLGC.js} +57 -13
  5. package/dist/{capability-TAMDRZYV.js → capability-72DTW5M2.js} +9 -9
  6. package/dist/{capability-U7TDEEEG.js → capability-PJHNI4GJ.js} +9 -9
  7. package/dist/{chunk-AFXA7BRK.js → chunk-4KVPKXFX.js} +5 -5
  8. package/dist/chunk-4SGZG4XY.js +311 -0
  9. package/dist/chunk-6EIJSNBD.js +8 -0
  10. package/dist/chunk-C4MGVGJW.js +13 -0
  11. package/dist/{chunk-WZRX4KOH.js → chunk-GT46FPXN.js} +4 -6
  12. package/dist/{chunk-5XUSIK27.js → chunk-ILIU36SU.js} +10 -7
  13. package/dist/{chunk-JHENBQ5B.js → chunk-LYVNONC4.js} +0 -35
  14. package/dist/{chunk-JUW4AJXN.js → chunk-P3FGXJTU.js} +12 -7
  15. package/dist/chunk-QGM4M3NI.js +37 -0
  16. package/dist/{chunk-753BUTNZ.js → chunk-RGKJGKT7.js} +2 -2
  17. package/dist/{chunk-UIHQJK5E.js → chunk-SAU3QFIQ.js} +3 -3
  18. package/dist/{chunk-VLWOLBGZ.js → chunk-UOUS37JQ.js} +149 -161
  19. package/dist/{chunk-AXDXJTPC.js → chunk-UW5UN47B.js} +19 -2
  20. package/dist/chunk-VPKZ7I72.js +509 -0
  21. package/dist/{chunk-QATA32VR.js → chunk-VR3LCBHW.js} +2 -2
  22. package/dist/{chunk-IBH3LDAH.js → chunk-YA6SMTXG.js} +3 -3
  23. package/dist/chunk-ZZUOD757.js +598 -0
  24. package/dist/{client-L2YDMHQ6.js → client-TKG4WBHN.js} +4 -5
  25. package/dist/{community-report-client-M2RW4MXD.js → community-report-client-FI4LNVYS.js} +3 -2
  26. package/dist/{config-OL2LWGBV.js → config-RE6CMGPK.js} +7 -7
  27. package/dist/data-integration-XQYB4X4F.js +3503 -0
  28. package/dist/index.js +68 -34
  29. package/dist/local-data-upload-client-BWHSUQQK.js +167 -0
  30. package/dist/{memory-MUP7PPL7.js → memory-CHRU2F7W.js} +7 -6
  31. package/dist/{memory-U4O5PMXH.js → memory-YK33G4T7.js} +7 -6
  32. package/dist/{metadata-5MIMNIMT.js → metadata-UILXHBWF.js} +10 -9
  33. package/dist/{metadata-LERKDJN6.js → metadata-XXR34N5P.js} +10 -9
  34. package/dist/{model-JTUEO5M4.js → model-K3KLWIW6.js} +7 -3
  35. package/dist/model-NR3JHFSJ.js +139 -0
  36. package/dist/{sync-MOSFNBVR.js → sync-DAVKYVMW.js} +8 -6
  37. package/dist/sync-FCKOVWWS.js +10261 -0
  38. package/dist/{te-agent-IFKZDHZI.js → te-agent-4BKBODMF.js} +686 -71
  39. package/dist/te-agent-HLW4VTQK.js +3893 -0
  40. package/dist/{te-analysis-FCHRTNIY.js → te-analysis-O6DCO6BS.js} +36 -13
  41. package/dist/{te-analysis-QG7UKGDA.js → te-analysis-ZMNGOVNW.js} +36 -13
  42. package/dist/{te-community-HNKVTERD.js → te-community-6HPBWJUZ.js} +24 -19
  43. package/dist/{te-community-IWE5B7W6.js → te-community-HLC43QKH.js} +24 -20
  44. package/dist/{te-dataops-KXCEB4CS.js → te-dataops-EJP56W3K.js} +57 -34
  45. package/dist/{te-dataops-KQPYNAE3.js → te-dataops-HDRUXY4K.js} +59 -34
  46. package/dist/{te-engage-D6EG3NOR.js → te-engage-FGBGQ4IY.js} +9 -8
  47. package/dist/{te-engage-ZSMIJLUW.js → te-engage-RAK5PESW.js} +9 -8
  48. package/dist/{te-experiment-K5US7RMG.js → te-experiment-SO5MPDMJ.js} +9 -8
  49. package/dist/{te-experiment-WA7TFMEL.js → te-experiment-VZF7BT6G.js} +9 -8
  50. package/dist/{te-kb-OIH3T6CS.js → te-kb-SQCLHG6X.js} +250 -126
  51. package/dist/{te-system-AZ3URMUO.js → te-system-YARIK4S5.js} +7 -4
  52. package/dist/te-system-Z77IKZFN.js +2213 -0
  53. package/dist/{te-team-GZPU6UWA.js → te-team-EFKWYKMK.js} +7 -7
  54. package/dist/{update-TOBFXF2V.js → update-OGPSZM5A.js} +7 -7
  55. package/package.json +14 -3
  56. package/skills/ae-agent/SKILL.md +21 -11
  57. package/skills/ae-agent/references/approval-effect.md +44 -0
  58. package/skills/ae-agent/references/approval-request.md +46 -0
  59. package/skills/ae-agent/references/approval-task.md +45 -0
  60. package/skills/ae-agent/references/approval-type.md +32 -0
  61. package/skills/ae-agent/references/command_index.md +19 -0
  62. package/skills/ae-analysis/SKILL.md +11 -7
  63. package/skills/ae-analysis/references/adhoc_run.md +2 -0
  64. package/skills/ae-analysis/references/ai_models.md +27 -0
  65. package/skills/ae-analysis/references/analysis_gateway_assets.md +3 -2
  66. package/skills/ae-analysis/references/command_index.md +4 -1
  67. package/skills/ae-analysis/references/dashboard_get.md +8 -2
  68. package/skills/ae-analysis/references/dashboard_report_data_run.md +3 -1
  69. package/skills/ae-analysis/references/dashboard_update.md +4 -1
  70. package/skills/ae-analysis/references/project_space_business_filter_upsert.md +17 -0
  71. package/skills/ae-analysis/references/user_tag_models.md +4 -4
  72. package/skills/ae-data-integration/SKILL.md +54 -0
  73. package/skills/ae-data-integration/references/handoff.md +43 -0
  74. package/skills/ae-data-integration/references/local-analysis.md +27 -0
  75. package/skills/ae-data-integration/references/reuse.md +41 -0
  76. package/skills/ae-data-integration/references/sink-upload.md +58 -0
  77. package/skills/ae-data-integration/references/source-inspect.md +68 -0
  78. package/skills/ae-data-integration/references/sync-json-upload.md +60 -0
  79. package/skills/ae-data-integration/references/tracking-plan.md +35 -0
  80. package/skills/ae-data-integration/references/transform.md +65 -0
  81. package/skills/ae-data-integration/references/ue-mapping.md +142 -0
  82. package/skills/ae-data-integration/references/ue-routing.md +35 -0
  83. package/skills/ae-data-integration-helper/SKILL.md +1 -1
  84. package/skills/ae-dataops/SKILL.md +1 -1
  85. package/skills/ae-dataops/references/dataops-query.md +4 -4
  86. package/skills/ae-generate-tracking-plan/SKILL.md +54 -3
  87. package/skills/ae-kb/SKILL.md +55 -50
  88. package/skills/ae-kb/references/query-workflow.md +112 -0
  89. package/skills/ae-kb-discovery/SKILL.md +105 -0
  90. package/skills/ae-metadata/SKILL.md +0 -1
  91. package/dist/chunk-3FY3RJ26.js +0 -293
  92. package/dist/chunk-S5NTSDBS.js +0 -198
  93. package/dist/chunk-ZQKDZXDO.js +0 -317
  94. package/dist/cli-token-4UPER74P.js +0 -21
@@ -0,0 +1,142 @@
1
+ # UE mapping contract
2
+
3
+ The mapping version is `ae-local-data-mapping/v1`.
4
+
5
+ Required structure:
6
+
7
+ ```json
8
+ {
9
+ "version": "ae-local-data-mapping/v1",
10
+ "source": {
11
+ "sha256": "<source-sha256>",
12
+ "format": "csv",
13
+ "data_set": "$"
14
+ },
15
+ "mode": "track",
16
+ "confidence": "high",
17
+ "account_id_field": "user_id",
18
+ "time": {
19
+ "field": "event_time",
20
+ "format": "auto",
21
+ "source_timezone": "Asia/Shanghai"
22
+ },
23
+ "event_name_field": "event_name",
24
+ "properties": [
25
+ { "source": "amount", "target": "amount", "type": "number" }
26
+ ]
27
+ }
28
+ ```
29
+
30
+ Use `distinct_id_field` when no account field exists. `mixed` requires `record_type_field`. Track requires `event_name_field` or a reviewed `default_event_name`. `source.format` is one of `csv`, `tsv`, `json`, `jsonl`, `xls`, `xlsx`. For a multi-file template mapping, `source.sha256` may be the wildcard `*`.
31
+
32
+ ## Record types
33
+
34
+ Every record carries a `#type`. `mode: 'mixed'` resolves the type per row via `record_type_field`; otherwise the mode fixes it (`track` or `user_set`). The `record_type_field` values are normalized case- and underscore-insensitively, with `event`→`track` and `user`/`userset`→`user_set` aliases.
35
+
36
+ | `#type` | Meaning | Requires `#event_name` |
37
+ | --- | --- | :---: |
38
+ | `track` | Report an event into the event table | Yes |
39
+ | `user_set` | Overwrite user properties (create if missing) | No |
40
+ | `user_setOnce` | Initialize a property only when empty | No |
41
+ | `user_add` | Increment numeric user properties | No |
42
+ | `user_unset` | Clear user property values | No |
43
+ | `user_del` | Delete the user from the user table | No |
44
+ | `user_append` | Append elements to list properties | No |
45
+ | `user_uniq_append` | Append elements with deduplication | No |
46
+
47
+ ## System fields
48
+
49
+ Top-level `#` fields map from named source columns. The user confirms each mapping; never infer it from a column name alone — a `user_id` column can be either an anonymous or a login ID, and only the user knows which.
50
+
51
+ | Field | Plain-language meaning | Required |
52
+ | --- | --- | :---: |
53
+ | `#distinct_id` | Anonymous visitor ID (device/cookie/visitor) — identifies unauthenticated traffic | At least one of `#distinct_id` / `#account_id` |
54
+ | `#account_id` | Login/account ID (database `user_id`, phone, member ID) — identifies authenticated users | At least one of `#distinct_id` / `#account_id` |
55
+ | `#time` | Event/profile occurrence time; AE bins data by it | Yes |
56
+ | `#event_name` | What the user did (`purchase`, `login`) | Only for `track` |
57
+ | `#ip` | Client IP; AE resolves geo from it | No |
58
+ | `#uuid` | Short-window deduplication ID | No |
59
+
60
+ `#zone_offset` is a preset property that tells AE the data's UTC offset (whole hours, -12..14) so `#time` is interpreted correctly. Unlike the fields above it lives **inside `properties`**, not at the top level. Provide it via `zone_offset_value` (a whole-hour integer such as `8` for UTC+8; an IANA name is also accepted and resolved to its offset at conversion time — sub-hour zones round to the nearest whole hour and DST zones reflect the offset then in effect, so historical data crossing a DST boundary should use `zone_offset_field`) or `zone_offset_field` (a source column carrying the offset per row); the two are mutually exclusive. Rows whose `zone_offset_field` value is missing or not an integer in -12..14 are quarantined.
61
+
62
+ Mapping keys: `account_id_field`, `distinct_id_field`, `time.field`, `event_name_field` (or a reviewed `default_event_name`), `ip_field`, `uuid_field`. Inspect surfaces every identity-shaped column in `identity_candidates` (name, `account`/`distinct` kind, unique and missing ratios) so the agent can present all candidates for confirmation. When the required identity column is absent, use an explicit `account_id_value`/`distinct_id_value` placeholder or `random_pool` — a user decision, never invented.
63
+
64
+ ## Output record shape
65
+
66
+ System fields sit at the top level; every mapped property is nested under `properties`.
67
+
68
+ ```json
69
+ { "#type": "track", "#time": "2026-08-10 10:00:00.000", "#account_id": "u-1", "#event_name": "purchase", "properties": { "amount": 99.9, "channel": "app" } }
70
+ ```
71
+
72
+ ```json
73
+ { "#type": "user_set", "#time": "2026-08-10 10:00:00.000", "#distinct_id": "d-1", "properties": { "user_level": 5, "user_tag": "vip" } }
74
+ ```
75
+
76
+ `track` requires `#event_name`; user-profile types (`user_set`, `user_add`, …) do not.
77
+
78
+ ## Optional overlay fields
79
+
80
+ All fields below are optional and are explicit user decisions — never invent them.
81
+
82
+ | Field | Shape | Effect |
83
+ | --- | --- | --- |
84
+ | `time_format` | `string` (strptime pattern) | Overrides auto-detection for `time.field`; used for ambiguous US/EU dates |
85
+ | `value_mapping` | `{ account_id? / distinct_id? / event_name? / record_type?: {original: replacement} }` | Exact-key replacement per system field (business-data keys map to AE-name values). A value with no matching key keeps its original text and fails validation, so confirm every distinct value is covered or excluded |
86
+ | `account_id_value` / `distinct_id_value` | `string` | Fixed placeholder identity (≤128 chars). Applies to every row when the corresponding `*_field` is absent; when the field exists, fills only the rows whose column is empty |
87
+ | `random_pool` | `{ account_ids?: string[], distinct_ids?: string[] }` | Synthesizes a random identity when the source field is absent |
88
+ | `exclude_columns` | `string[]` | Source columns skipped when building properties |
89
+ | `flatten_rules` | `{ outColumn: 'dot.path' }` | Nested flatten map. NDJSON/JSON paths are from the record root (`user_info.name`); CSV/TSV paths are `<column>.<cell-relative path>` into a JSON-encoded object cell (`user_profile.name`) — add the source column to `exclude_columns` when flattening it |
90
+ | `headers` | `string[]` | User-confirmed column names for a headerless file; presence means the first row is data. Never use inspect's `col_1..col_N` placeholders — infer names from each column's values, confirm them with the user, then write them here |
91
+ | `missing_time` | `'now'` | Fill a missing/empty `#time` with the current time, for user-profile rows only (explicit user decision; track rows are never filled) |
92
+ | `ip_field` | `string` | Source column emitted as the top-level `#ip` system field (client IP; AE resolves geo) |
93
+ | `uuid_field` | `string` | Source column emitted as the top-level `#uuid` system field (short-window deduplication ID) |
94
+ | `zone_offset_value` | `number` (integer -12..14) or IANA `string` | Emits the fixed `#zone_offset` preset property inside `properties`. An IANA name resolves to its integer UTC offset |
95
+ | `zone_offset_field` | `string` | Source column whose per-row integer value (-12..14) is emitted as `#zone_offset`; missing/non-integer rows are quarantined. Mutually exclusive with `zone_offset_value` |
96
+ | `event_meta` | `{ <event-name>: { desc?: string, tag?: string } }` | Per-event business description and `event_tag` for the tracking plan, keyed by AE event name. Inferred from the data and user context; the user supplies anything not inferable — never leave them empty |
97
+
98
+ Each `properties` entry may also carry `value_mapping` (per-property exact-key replacement), `transform` (one of `stringify`, `number`, `boolean`, `json`), `time_format` (only meaningful for `type: 'datetime'`), and `desc` (business description for the tracking plan; inferred, or user-provided when not inferable). Container columns (`object`/`list`) whose values arrive as JSON text — JSON-encoded CSV cells, or flattened NDJSON leaves — must set `transform: 'json'` so conversion parses the text back into a native object/array; it is a safe no-op when the value already arrived native.
99
+
100
+ ## Time formats
101
+
102
+ Values with an explicit offset or `Z` are parsed by the JavaScript `Date` constructor (authoritative). Other values are matched against 21 formats; a `time_format` field overrides the match.
103
+
104
+ | Category | Example | Auto-detected |
105
+ | --- | --- | :---: |
106
+ | Standard AE | `2024-01-15 10:30:00.123` / `2024-01-15 10:30:00` | Yes |
107
+ | ISO 8601 | `2024-01-15T10:30:00` / with `.SSS` / with offset | Yes |
108
+ | Unix epoch | `1705314600` (seconds) / `1705314600000` (milliseconds) | Yes |
109
+ | Slash-separated | `2024/01/15 10:30:00` / `2024/01/15` | Yes |
110
+ | Dot-separated | `2024.01.15 10:30:00` / `2024.01.15` | Yes |
111
+ | Compact digits | `20240115103000` / `202401151030` / `20240115` | Yes |
112
+ | English month names | `15 Jan 2024 10:30:00` / `January 15 2024 10:30:00` / `Jan 15 2024 10:30:00` | Yes |
113
+ | Chinese date | `2024年1月15日` / `2024年1月15日 10:30:00` / `2024年1月15日 10时30分00秒` | Yes |
114
+ | US format | `01/15/2024 10:30:00` (MM/DD/YYYY) | No — use `time_format` |
115
+ | EU format | `15/01/2024 10:30:00` (DD/MM/YYYY) | No — use `time_format` |
116
+
117
+ ## Data rules
118
+
119
+ - **Ingestion time window.** The receiver accepts event/profile times from 3 years before to 3 days after the server time; the CLI enforces this range. Client-side reporting has a tighter window (10 days before to 3 days after); historical data beyond the window needs AE support to extend it.
120
+ - **Property type locking.** A property's type is locked on first receipt, and properties sharing a name across events are one property — later reports must use the same type. Values whose type mismatches the locked type are dropped silently, so review an inferred type before committing it.
121
+ - **Quote stripping.** Paired single or double quotes around a cell value are stripped (`'user_001'` → `user_001`); a single-sided quote is kept as data (SQL exports often quote every value).
122
+ - **Column name sanitization.** Recommended mapping auto-names properties: accents are stripped, camelCase is split to snake_case, everything is lowercased, and illegal characters become `_`; a digit-leading name is prefixed `field_`, and a name with nothing recognizable falls back to `field_N`. Review these targets — especially the `field_N` fallbacks — and rename before converting.
123
+ - **Object sub-property keys.** Object and list-of-object keys follow the same naming rules as property names (lowercase snake_case, letter-leading, at most 50 chars, no `#`). A key that does not — for example a Chinese key inside a JSON cell such as `{"等级":"金牌"}` — quarantines the whole row, so confirm object keys before converting.
124
+
125
+ ## Review checklist
126
+
127
+ - Source SHA-256 and data-set ID match the inspection result (or the mapping uses the `*` wildcard for multi-file).
128
+ - Identity values remain strings and are at most 128 characters.
129
+ - Source timezone is an IANA name derived from user/project context.
130
+ - `#zone_offset`, when set, is a whole-hour integer in -12..14 (or an IANA name/column that resolves to one) and is emitted inside `properties`, never at the top level.
131
+ - Event/property names are lowercase snake_case, begin with a letter, and are at most 50 characters.
132
+ - Target property names are unique and do not collide with UE system fields.
133
+ - Types are one of `string`, `number`, `boolean`, `datetime`, `list`, or `object`.
134
+ - Text is at most 2 KB; numbers stay within -9E15..9E15.
135
+ - Lists contain at most 500 strings (255 bytes each) or 500 objects.
136
+ - Objects contain at most 100 legal sub-properties; nested values follow the same type limits.
137
+ - A conversion rule does not hide a real type conflict.
138
+ - Event/profile times fall within the receiver window: previous 3 years through next 3 days.
139
+ - Do not fabricate UUIDs, identities, times, or events; `#ip`/`#uuid` map from named source columns only (`ip_field`/`uuid_field`).
140
+ - `value_mapping`, `random_pool`, and fixed `account_id_value`/`distinct_id_value` came from an explicit user decision and match the actual distinct values/columns.
141
+
142
+ `user_set` output for the same identity is ordered by time so receiver application order is deterministic. Conversion applies whole-row quarantine: any error on a row — identity, time, event, record type, or a single property (type coercion, size/limit) — drops the entire row. The row is written to `invalid.rows.jsonl` with its error codes, counted in `manifest.output.invalid_records`, and the manifest is blocked until reviewed. The failed rows are re-reportable without re-sending valid rows: fix the mapping, then run `convert --input-file <same-source> --mapping <fixed-mapping> --salvage-from <invalid.rows.jsonl>`. The salvage run re-processes only the listed row numbers against the same source, emits a `valid.ue.jsonl` containing only the newly fixed rows, and writes a new `invalid.rows.jsonl` with whatever still fails — so the loop repeats (feeding each round's `invalid.rows.jsonl` into the next `--salvage-from`) until no rows fail or the user stops.
@@ -0,0 +1,35 @@
1
+ # UE routing
2
+
3
+ Use this reference after `data-integration inspect`.
4
+
5
+ ## Route to UE ingestion
6
+
7
+ All of these must hold:
8
+
9
+ - A real `#account_id` or `#distinct_id` source is present.
10
+ - A real time column is parseable; no synthetic time is permitted.
11
+ - The records are event facts or user-property snapshots rather than aggregates.
12
+ - Field-level records can be represented without losing essential meaning.
13
+
14
+ Classification order:
15
+
16
+ 1. A legal explicit `#type` wins (all eight record types — `track`, `user_set`, `user_setOnce`, `user_add`, `user_unset`, `user_del`, `user_append`, `user_uniq_append`).
17
+ 2. An event/action field implies `track`.
18
+ 3. Repeated users across a time series imply `track`; without an event field, propose a normalized file/Sheet name and require review.
19
+ 4. One row per user with snapshot-like fields implies `user_set`.
20
+ 5. Rows that mix track and user-profile facts in one file use `mixed` with a `record_type_field`; require explicit review.
21
+ 6. Low-confidence output is a proposal, never silent approval.
22
+
23
+ Aggregated metrics, pivot tables, cross-tabs, model outputs, free-form documents, and records without real identity/time should normally use local analysis.
24
+
25
+ ## Route to local analysis
26
+
27
+ Choose local analysis when:
28
+
29
+ - The user wants insights, not project ingestion.
30
+ - UE identity or time prerequisites are missing.
31
+ - Each row is an aggregate rather than a user/event record.
32
+ - Conversion would invent semantics or discard important structure.
33
+ - The user declines an uncertain mapping or destination.
34
+
35
+ Explain the reason briefly. Do not frame local analysis as an error.
@@ -62,7 +62,7 @@ Trigger when a user asks about:
62
62
  - **Configuration**: Debug mode / data validation / retry strategy
63
63
  - **Troubleshooting**: Upload failures / missing data / format errors
64
64
 
65
- **Do NOT trigger**: Inline Q&A within `ae-generate-tracking-plan` or `ae-generate-tracking-code` sessions (those skills have their own workflows).
65
+ **Do NOT trigger**: Inline Q&A within `ae-generate-tracking-plan` or `ae-generate-tracking-code` sessions (those skills have their own workflows). Offline local-file import (CSV / Excel / JSONL → AE) is owned by the `ae-data-integration` skill — route those requests there instead of answering with LogBus / RESTful guidance.
66
66
 
67
67
  ## Workflow
68
68
 
@@ -173,7 +173,7 @@ Detailed metadata browsing, SQL query, async download, and cancel workflows live
173
173
  Key constraints:
174
174
  - IDE is query-only; create/modify/delete tables with `dataops_datatable`.
175
175
  - Prefer `dataops_datatable +dict_search_tables` for table discovery unless raw engine metadata or schema browsing is required.
176
- - SQL query submission creates a download task; rows are not returned inline.
176
+ - Submit exactly one read-only SQL query. It creates a platform-bounded download task; rows are not returned inline and the result is not an unlimited or full export.
177
177
 
178
178
  ---
179
179
 
@@ -61,7 +61,7 @@ ae-cli dataops_ide +search_tables --spaceCode "${spaceCode}" --searchKey "user"
61
61
 
62
62
  ## Workflow C: Execute SQL Query (Download-Centered Async Flow)
63
63
 
64
- Use this flow for SQL query execution. Result rows are not returned through MCP/CLI; submit creates a Gaia download-center task directly.
64
+ Use this flow for exactly one read-only SQL query. Result rows are not returned through MCP/CLI; submit creates a Gaia download-center task directly. The query semantics are preserved, but the result remains platform-bounded; when present, `downloadRowLimit` reports that cap. This is not an unlimited or full export.
65
65
 
66
66
  ```bash
67
67
  # Step 1: Submit SQL and create a download task. Defaults: repoCode=te_etl, engineType=TASK_ENGINE_TRINO.
@@ -72,7 +72,7 @@ ae-cli dataops_ide +submit_sql_query --spaceCode "${spaceCode}" --repoCode "te_e
72
72
  # Step 2: Poll the download task status by spaceCode/downloadTaskId. Rows are not returned through MCP/CLI.
73
73
  ae-cli dataops_ide +get_sql_query_status --spaceCode "${spaceCode}" --downloadTaskId ${downloadTaskId}
74
74
 
75
- # Step 3: CLI-only local save after downloadStatus=SUCCESS. Use a .zip suffix.
75
+ # Step 3: CLI-only streaming save after downloadStatus=SUCCESS. The target is replaced only after the stream completes.
76
76
  ae-cli dataops_ide +get_sql_query_status --spaceCode "${spaceCode}" --downloadTaskId ${downloadTaskId} --downloadTo "./result.zip"
77
77
 
78
78
  # (Optional) Cancel the download task.
@@ -104,8 +104,8 @@ ae-cli dataops_ide +cancel_sql_query --spaceCode "${spaceCode}" --downloadTaskId
104
104
  - **Table search**: `+search_tables` requires `--spaceCode` and `--searchKey`. `--connType`, `--repoCode`, and `--size` are optional and default to `SPACE`, `te_etl`, and `20`. It returns `items`, `searchKey`, `size`, `totalCount`, `tableCount`, `viewCount`, `returnedCount`, `hasMore`, and `nextAction`.
105
105
  - **Table detail**: `+ide_get_table_detail` requires `--spaceCode`, `--catalog`, `--schema`, and `--tableName`. `--connType`, `--repoCode`, `--engineType`, `--entityType`, and `--includeDdl` are optional and default to `SPACE`, `te_etl`, `TASK_ENGINE_TRINO`, auto-detect, and `false`. It returns identity, storage metadata, columns, partitions, partition keys, optional layout fields, and `tableDdl` only when requested.
106
106
  - **Schema info**: `+get_schema_info` requires `--spaceCode`, `--catalog`, and `--schema`. `--connType` and `--repoCode` are optional and default to `SPACE` and `te_etl`. It returns only `schema`, `tableNum`, and `viewNum`.
107
- - **SQL submit**: `+submit_sql_query` requires `--spaceCode` and `--sql`. `--repoCode` and `--engineType` are optional and default to `te_etl` and `TASK_ENGINE_TRINO`. On success it returns `requestId`, `spaceCode`, `repoCode`, `downloadTaskId`, `downloadStatus`, `downloadApi`, `downloadParams`, and `nextAction`; rows are never returned.
108
- - **SQL status**: `+get_sql_query_status` requires `--spaceCode` and `--downloadTaskId`. `--requestId` is optional trace-only. `--downloadTo` is CLI-only; after `downloadStatus=SUCCESS` it saves the result zip and adds `localFile`. It returns status/progress metadata, `nextAction`, `downloadApi`, and `downloadParams`; rows are never returned.
107
+ - **SQL submit**: `+submit_sql_query` requires `--spaceCode` and exactly one read-only query in `--sql`. `--repoCode` and `--engineType` are optional and default to `te_etl` and `TASK_ENGINE_TRINO`. On success it returns task metadata and, when exposed by Gaia, `downloadRowLimit`; rows are never returned and the result remains platform-bounded.
108
+ - **SQL status**: `+get_sql_query_status` requires `--spaceCode` and `--downloadTaskId`. `--requestId` is optional trace-only. `--downloadTo` is CLI-only; after `downloadStatus=SUCCESS` it streams the result zip to a temporary sibling file, publishes it only after completion, and adds `localFile`. It returns status/progress metadata, `nextAction`, `downloadApi`, and `downloadParams`; rows are never returned.
109
109
  - **SQL cancel**: `+cancel_sql_query` requires `--spaceCode` and `--downloadTaskId`. `--requestId` is optional trace-only. It returns cancellation request metadata such as `downloadCancelStatus`.
110
110
  - **engineType**: `TASK_ENGINE_TRINO` (default, interactive queries) | `TASK_ENGINE_STARROCKS` (high-concurrency analytics)
111
111
  - **entityType**: optional `TABLE` or `VIEW` hint. Omit it unless the target type must be forced.
@@ -21,7 +21,8 @@ description: "Interactive generation of an AE tracking plan and upload. Trigger
21
21
  | 埋点模板 | Tracking Plan Template | Pre-built industry/genre xlsx templates |
22
22
  | 方案名称 | Plan Name | User-facing plan identifier |
23
23
  | 应用场景 | Application Scenario | One-sentence description of what the app does |
24
- | 素材来源 | Source Material Type | prd / chat / codebase / template |
24
+ | 素材来源 | Source Material Type | prd / chat / codebase / template / data |
25
+ | 数据样本 / 文件画像 | Data Sample / File Profile | Column→property mapping source from an `ae-data-integration` inspect profile (`source_type: data`) |
25
26
  | 业务维度 | Business Dimension | Revenue model, core loop, functional entries, currency system |
26
27
  | 收入模型 | Revenue Model | IAA / IAP / mixed / subscription / commission |
27
28
  | 核心循环 | Core Loop | Core gameplay loop (e.g. "grind stages → earn coins → gacha for heroes") |
@@ -115,8 +116,9 @@ Choose your source material (up to 2):
115
116
  3 - Codebase (local project path; hidden in sandbox) — Analyze source code to extract events and properties
116
117
  4 - Pre-built template (built-in industry and game genre templates) — Select a built-in template
117
118
  5 - Modify existing tracking plan (local AE format xlsx file) — Import an existing tracking plan xlsx as baseline for modification; can be combined with Product doc / Description / Codebase, but NOT with Pre-built template
119
+ 6 - Data sample / file profile (from ae-data-integration inspect) — Map data columns (CSV/Excel/JSONL) to events & properties from an inspect profile; single-source path, not combinable with other options
118
120
 
119
- Reply with number(s), e.g. 1,5 or 4. Select up to 2.
121
+ Reply with number(s), e.g. 1,5 or 4. Select up to 2 (option 6 is single-source).
120
122
  ```
121
123
 
122
124
  If in a sandbox environment, ask exactly:
@@ -128,8 +130,9 @@ Choose your source material (up to 2):
128
130
  2 - Detailed description (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
129
131
  3 - Pre-built template (built-in industry and game genre templates) — Select a built-in template
130
132
  4 - Modify existing tracking plan (sandbox workspace path) — Import an existing tracking plan xlsx as baseline for modification; can be combined with Product doc / Description, but NOT with Pre-built template
133
+ 5 - Data sample / file profile (from ae-data-integration inspect) — Map data columns (CSV/Excel/JSONL) to events & properties from an inspect profile; single-source path, not combinable with other options
131
134
 
132
- Reply with number(s), e.g. 1,4 or 3. Select up to 2.
135
+ Reply with number(s), e.g. 1,4 or 3. Select up to 2 (option 5 is single-source).
133
136
  ```
134
137
 
135
138
  Do not rewrite this source material list as unnumbered bullets, cards, or prose. The user must be able to reply with the visible numbers.
@@ -153,8 +156,10 @@ Based on user selection, determine source material type and record to `meta.sour
153
156
  | Codebase only | `codebase` | Scan source code, extract events/properties from business logic |
154
157
  | Template only | `template` | Provide built-in template selection |
155
158
  | Existing plan only | `existing_plan` | Import xlsx as baseline (see "Modify Existing Tracking Plan Flow" below) |
159
+ | Data sample only | `data` | Read the inspect profile (`ae-local-data-profile/v1`), map columns → events/properties (see "Data-path (source_type = data)" below) |
156
160
  | Any two-item combo | Join two types with `_` | First as baseline, second as supplement (priority: existing_plan → template → codebase → prd → chat) |
157
161
  | Existing plan + Pre-built template | **NOT allowed** | Both provide event baselines; semantic conflict |
162
+ | Data sample + any other | **NOT allowed** | Data sample is a standalone single-source path |
158
163
 
159
164
  **Follow-up questions** (ask in follow-up order defined in Multi-Source Combination Rules below):
160
165
  - Product doc → if not in a sandbox environment, ask exactly:
@@ -184,6 +189,7 @@ Based on user selection, determine source material type and record to `meta.sour
184
189
  - Codebase → ask **"What is the project directory path?"**, then scan source to extract business logic
185
190
  - Pre-built template → display matching templates for user confirmation
186
191
  - Modify existing tracking plan → ask **"Please provide the xlsx file path of your existing tracking plan"**, then follow the flow below
192
+ - Data sample → ask **"Please provide the path of the inspect profile JSON (or the run directory containing it)"**, then read the `ae-local-data-profile/v1` product and follow the "Data-path (source_type = data)" flow below
187
193
 
188
194
  **Modify Existing Tracking Plan Flow** (when user selects this option):
189
195
 
@@ -363,6 +369,49 @@ Use the baseline source's inference method as primary. Supplementary sources (es
363
369
  }
364
370
  ```
365
371
 
372
+ ### Data-path (source_type = data) — condensed single-gate flow
373
+
374
+ When the user selects the **Data sample / file profile** option (`source_type = data`), the flow diverges from the standard 5-item anchor. This path **maps table columns → events/properties** instead of inventing events from business understanding, and uses a **single confirmation gate** instead of the 5-segment Refine loop.
375
+
376
+ **What to skip** (only Item 1 — Application Scenario and Item 2 — Data sample are collected):
377
+
378
+ - **Item 3 (SDK Integration Config)** → skip. `meta.sdk_integration_mode = "none"` (data ingested via RESTful / LogBus / DataX, no SDK). No SDK auto-track events are injected (Phase 1.4 already skips `none`).
379
+ - **Item 4 (User Identity System)** → skip the visitor-ID strategy question. Derive `meta.user_identity` from the inspect profile's `identity_candidates` instead (e.g. a `distinct_id` / `account_id` column), `account_id_source: "user_account"` when an account column exists, otherwise `"none"`.
380
+ - **Business Dimension confirmation** → skip. Mapping is driven by columns, not by revenue model / core loop. `meta.business_dimension` stays empty.
381
+
382
+ **Draft construction (replaces Phase 1.1/1.2/1.3 for the data path)**:
383
+
384
+ 1. **Read the inspect profile**: the `ae-local-data-profile/v1` JSON product (columns / types / samples / UE eligibility / mapping confidence). If it is not present or is stale, re-run `ae-cli data-integration inspect` for the source file first.
385
+ 2. **Event model determination** (reuse UE routing): single-table single-event `track` / single-table multi-event (event-name column) / single-table `user_set` / mixed. The agent may propose **splitting one table into multiple events** (e.g. an ad table split by `campaign_type` into `ad_show` / `ad_click`); such proposals MUST be confirmed in the gate.
386
+ 3. **Column → property mapping draft**:
387
+ - Identify system columns first: time field, `distinct_id` / `account_id`, event-name column, user-property-name column.
388
+ - Map the remaining columns to event properties / user properties / super properties.
389
+ - Naming: `snake_case` event/property names + `display_name` + `desc` + `event_tag` (language follows the user's input).
390
+ - Type inference: CSV columns default to `string`; infer `number` / `bool` / `datetime` / enum from field name + value distribution + business doc/prompt priors. **Uncertain or conflicting columns are marked "to-confirm" and asked only inside the gate** (do not ask column-by-column beforehand).
391
+ 4. **Single confirmation gate** (replaces Phase 2, see below).
392
+ 5. **Merge with existing plan** (reuse Phase 4.1/4.2 conflict detection).
393
+ 6. **Persist**: `.ae-cli/draft.json` → xlsx → upload (`sdk_integration_mode = none`).
394
+
395
+ **Single confirmation gate (one round, one summary table)**:
396
+
397
+ Present ONE merged table covering all of the following in a single message, then wait for a single reply:
398
+
399
+ - **Event list**: `event_name` / `display_name` / `desc` / `event_tag` / `platform`.
400
+ - **Property list**: `name` / `display_name` / `type` / `desc` / `source`, with uncertain types highlighted (marked "to-confirm").
401
+ - **Field scope**: default to plan-internal fields only; include a **full-import switch** for bringing all source columns in.
402
+ - **Unrecognized / dirty data handling**: how unmapped columns, null values, and unparseable rows are treated.
403
+ - **Same-name property type conflicts**: flagged inline in the gate (see Phase 4.2 Type A).
404
+
405
+ User replies once: `ok` (accept all), or targeted edits — rename / retype / add / remove individual columns or events. After the gate is confirmed, jump to Phase 3 (project token) then Phase 4 (merge + upload); do NOT enter the 5-segment Refine loop.
406
+
407
+ **dry-run mode**:
408
+
409
+ When the user requests dry-run (or the caller passes `data-integration plan --dry-run`), produce the draft preview + column→property mapping summary ONLY:
410
+
411
+ - Show the single confirmation gate table (events + properties + field scope + unrecognized-data handling) and the mapping result, but do NOT write `.ae-cli/draft.json`.
412
+ - Do NOT generate xlsx, do NOT archive to `plans/`, do NOT upload to AE.
413
+ - State explicitly that nothing was persisted; the user can approve a real run afterwards.
414
+
366
415
  ### Item 3 — SDK Integration Config (client + server combined)
367
416
 
368
417
  Ask: **"What is your client platform? (multi-select OK, e.g. Android + iOS) Will you integrate a server-side SDK?"**
@@ -822,6 +871,8 @@ AE_LANG=<user_lang> ae-cli tracking code import-template --template-name "<templ
822
871
 
823
872
  ## Phase 2 — Refine (5-segment loop)
824
873
 
874
+ > **Data path (`source_type = data`)**: skip this 5-segment loop entirely — use the single confirmation gate defined in "Data-path (source_type = data)" instead.
875
+
825
876
  In order, one conversation round per segment:
826
877
 
827
878
  1. **sdk_config (SDK config + User identity, combined)** — Show SDK integration mode, platform/language, visitor ID strategy, account ID source, corresponding SDK calls
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ae-kb
3
3
  version: 1.0.0
4
- description: "AE/TE knowledge base CLI manual for creating, querying, LLM-powered ask, listing accessible knowledge bases, deterministic index/grep/read retrieval, checking status, uploading, compiling, schema generation, URL sources, source deletion, and knowledge base deletion. Use when the user asks to manage TE/AE/ThinkingEngine knowledge bases, upload documents or URLs to a knowledge base, query knowledge, ask knowledge bases with an LLM, list accessible knowledge bases, inspect knowledge base indexes, search knowledge base pages, read a specific knowledge base page, check knowledge base status, generate schemas, compile knowledge, remove sources, or delete a knowledge base. Must use ae-cli kb commands and must not guess knowledge base names, scopes, page paths, source display names, JSON payload shapes, or URL formats."
4
+ description: "AE/TE knowledge base CLI manual for creating, querying, LLM-powered ask, listing accessible knowledge bases, deterministic index/grep/read retrieval, checking status, uploading, compiling, schema generation, URL sources, source deletion, and knowledge base deletion. Use when the user asks to manage TE/AE/ThinkingEngine knowledge bases, upload documents or URLs to a knowledge base, query knowledge, ask knowledge bases with an LLM, list accessible knowledge bases, inspect knowledge base indexes, search knowledge base pages, read a specific knowledge base page, check knowledge base status, generate schemas, compile knowledge, remove sources, or delete a knowledge base. To choose which knowledge base is worth searching, use the ae-kb-discovery skill first; this skill runs the retrieval once a target is chosen. Must use ae-cli kb commands and must not guess knowledge base names, scopes, page paths, source display names, JSON payload shapes, or URL formats."
5
5
  ---
6
6
 
7
7
  # ae-kb
@@ -15,25 +15,27 @@ ae-cli kb +<command> [options]
15
15
  ## Global Rules
16
16
 
17
17
  - Use this skill for TE/AE knowledge base tasks: create, query, ask with LLM, list accessible knowledge bases, inspect indexes, grep pages, read pages, check status, upload sources, add URL sources, generate schema, compile, remove source files, and delete knowledge bases.
18
+ - **Searching a knowledge base for an answer is the most common task. If that is what you are doing, go straight to [Explore Knowledge Base Pages](#explore-knowledge-base-pages) and read [`references/query-workflow.md`](references/query-workflow.md) first — it is the retrieval procedure. The other commands below are for managing knowledge bases, not answering from them.**
18
19
  - Read operations can run directly after required inputs are known. Write operations require explicit user intent and normally keep the confirmation prompt unless the user asks to bypass it.
19
20
  - Prefer `--dry-run` before destructive or broad writes when the user has not already validated the target.
20
21
  - Do not invent knowledge base names, scopes, source display names, or JSON payloads. Ask the user or query known context when values are missing.
22
+ - When building a `--sources` ref (or `+read --source`), copy the exact `scope` and `name` from `+list` output — run `ae-cli kb +list` first when the scope of a named knowledge base is unknown.
21
23
  - JSON flags must be valid JSON strings, usually wrapped in single quotes in shell commands.
22
24
  - Successful commands return JSON by default. Use `--format table` only when a table is easier for a human to scan. Envelope may include optional `_notice.host_compat`.
23
25
  - `--host <url>` overrides the active AE host. It is available on every command and may be placed after the subcommand, e.g. `ae-cli kb +<command> --host <url>`.
24
26
  - **CRITICAL — Host compat (do this first):** After each `ae-cli` run, check stderr and `_notice.host_compat`. If either is present, open the user reply with a short ⚠️ version warning and **quote the `npm i -g` / `npx skills add` (or update-cluster) lines verbatim**, then present the business result. Soft tip; `ok: true` can still carry the notice.
25
- - For external-agent retrieval, prefer the deterministic flow `+index` -> `+grep` -> `+read`: inspect navigation, locate candidate pages, then open the exact page or line window. Use `+ask` only when the user wants an LLM-synthesized answer and accepts token consumption.
27
+ - Retrieval (`+index` / `+grep` / `+read`) is deterministic and server-side LLM-free; use it for simple factual lookups. Use `+ask` when the question requires synthesizing across multiple pages or multi-hop reasoning.
26
28
 
27
29
  ## Commands
28
30
 
29
31
  | Command | Risk | Purpose |
30
32
  |---|---:|---|
31
- | `+query` | read | Query one or more knowledge bases with a natural-language question. |
32
- | `+ask` | read | LLM-powered Q&A over knowledge bases. Consumes platform tokens. |
33
+ | `+ask` | read | LLM-powered Q&A over knowledge bases; for multi-page synthesis or multi-hop questions. |
34
+ | `+ask-status` | read | Query the current status of an ask execution by `--execution-id` without polling. |
33
35
  | `+list` | read | List accessible knowledge bases filtered by buildStatus (default: compiled). |
34
36
  | `+index` | read | List accessible knowledge bases and their `index.md` navigation maps. |
35
37
  | `+grep` | read | Keyword-search knowledge base pages and return matched lines with context. |
36
- | `+read` | read | Read a full knowledge base page or a line window. |
38
+ | `+read` | read | Read a full knowledge base page, a line window, or (with `--outline`) only the page heading tree. |
37
39
  | `+new` | write | Create a new personal or company knowledge base. |
38
40
  | `+add` | write | Upload local files, a non-recursive directory, or HTTP(S) pages converted to markdown. |
39
41
  | `+url` | write | Upload a URL source directly with optional display name and parsing instruction. |
@@ -123,34 +125,26 @@ Use `+status` to inspect the current status of a knowledge base.
123
125
  ae-cli kb +status --name engineering-handbook
124
126
  ```
125
127
 
126
- ### Query Knowledge
127
-
128
- Use `+query` with a natural-language question. Optionally scope to specific knowledge bases or tune result count and locale.
129
-
130
- ```bash
131
- ae-cli kb +query \
132
- --query "How do we release a dashboard?" \
133
- --sources '[{"scope":"company","name":"engineering-handbook"}]' \
134
- --top-k 10 \
135
- --locale zh
136
- ```
137
-
138
- When `--sources` is provided, each entry requires:
139
-
140
- - `scope`: knowledge base scope such as `personal` or `company`.
141
- - `name`: knowledge base name.
142
-
143
128
  ### Ask Knowledge (LLM)
144
129
 
145
- Use `+ask` when the user wants an LLM-synthesized answer. This endpoint calls a large language model and **consumes platform tokens**. Prefer `+index` -> `+grep` -> `+read` when deterministic retrieval is enough.
130
+ Use `+ask` when the question requires synthesizing across multiple pages or multi-hop reasoning — a server-side agent runs the full retrieval loop and returns a synthesized answer with its source paths. Prefer `+index` -> `+grep` -> `+read` when deterministic retrieval is enough.
131
+
132
+ The `+ask` command uses asynchronous submit/poll: by default, it automatically polls for completion (every 5s, up to 10 minutes) and prints the final answer. The output JSON is isomorphic to the previous synchronous response, so consumers require no changes.
146
133
 
147
134
  ```bash
135
+ # Default: submit and poll for completion
148
136
  ae-cli kb +ask \
149
137
  --question "How do we troubleshoot payment alerts?" \
150
138
  --sources '[{"scope":"company","name":"engineering-handbook"}]' \
151
139
  --model-id claude-sonnet-4-6 \
152
140
  --max-turns 50 \
153
141
  --locale zh
142
+
143
+ # Submit only, return executionId immediately (for batch processing)
144
+ ae-cli kb +ask --question "..." --no-wait
145
+
146
+ # Query execution status later
147
+ ae-cli kb +ask-status --execution-id <id>
154
148
  ```
155
149
 
156
150
  - `--question`, alias `-q`: required natural-language question (1-2000 characters).
@@ -158,10 +152,12 @@ ae-cli kb +ask \
158
152
  - `--model-id`: optional LLM model ID. Omit to use the platform default.
159
153
  - `--max-turns`: optional agent turn limit (1-100, server default 50).
160
154
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
155
+ - `--no-wait`: optional boolean flag. Return immediately after submission with `{executionId, status}`, without polling.
156
+ - **Failure handling**: If execution fails, the command exits non-zero and prints an error message on stderr prefixed with the typed error code, e.g. `[timeout] ...` / `[model_error] ...` / `[invalid_sources] ...` (followed by the executionId). Treat the bracketed code as the machine-readable failure type.
161
157
 
162
158
  ### List Accessible Knowledge Bases
163
159
 
164
- Use `+list` when you only need accessible knowledge base metadata without loading `index.md` navigation maps. By default it returns knowledge bases with `buildStatus: compiled`:
160
+ Use `+list` when you only need accessible knowledge base metadata without loading `index.md` navigation maps. Omit `--build-status` to default to `compiled`; pass `idle` / `pending` / `compiling` / `compiled` / `failed` to filter by a specific status (system knowledge bases are always listed regardless of status):
165
161
 
166
162
  ```bash
167
163
  ae-cli kb +list
@@ -173,6 +169,8 @@ ae-cli kb +list --build-status compiled
173
169
 
174
170
  Use the deterministic retrieval primitives when an agent needs to explore knowledge base content like a code repository. These endpoints do not call an LLM on the server side.
175
171
 
172
+ **Before running a real query, read [`references/query-workflow.md`](references/query-workflow.md)** — it is the step-by-step procedure for turning a question into an answer without crawling. It covers candidate indexing, copied-path grep, same-page read windows, linked-page re-grep, outline-derived ranges, and coverage assessment. This section below is the per-command reference the workflow draws on.
173
+
176
174
  Start with `+list` or `+index` to discover accessible knowledge bases. Use `+index` when you also need navigation maps:
177
175
 
178
176
  ```bash
@@ -190,26 +188,30 @@ Then use `+grep` to locate likely pages and line numbers:
190
188
  ae-cli kb +grep \
191
189
  --query "sandbox configuration" \
192
190
  --sources '[{"scope":"company","name":"engineering-handbook"}]' \
191
+ --paths '["wiki/sandbox.md"]' \
193
192
  --top-k 10
194
193
  ```
195
194
 
196
- Finally use `+read` to open the exact page, optionally with a line window:
195
+ Each grep hit carries `path`, `line`, `breadcrumb`, a context snippet, and the section range of the matched line (`sectionStartLine` / `sectionEndLine`). `line` is the hit anchor; `sectionStartLine` / `sectionEndLine` are the enclosing heading-section boundaries. Choose the smallest reliable `--offset` / `--limit` window that preserves the needed evidence; use the section range when the answer needs whole-section context.
196
+
197
+ Use `+read --outline` when the current target page has no reliable grep range and headings are needed to choose a section:
197
198
 
198
199
  ```bash
199
200
  ae-cli kb +read \
200
201
  --source '{"scope":"company","name":"engineering-handbook"}' \
201
202
  --path "wiki/sandbox.md" \
202
- --offset 1 \
203
- --limit 200
203
+ --outline
204
204
  ```
205
205
 
206
- Retrieval rules:
206
+ Then use `+read` to open the selected window, using the hit anchor, a section boundary from same-page or linked-page grep, or two adjacent outline headings:
207
207
 
208
- - `+list` accepts optional `--build-status` (default `compiled`) and `--locale`. Returns accessible knowledge base metadata including `buildStatus`, without `index.md` navigation maps.
209
- - `+index` accepts optional `--sources` and `--locale`; omit `--sources` to list all accessible knowledge bases.
210
- - `+grep` requires `--query` / `-q`; optional `--sources`, `--top-k` (1-50, default 10), and `--locale`.
211
- - `+read` requires `--source` pointing to exactly one knowledge base and `--path` relative to the knowledge base root; optional `--offset`, `--limit` (1-10000), and `--locale`.
212
- - Do not guess a `--path`; get it from `+index` or `+grep` results.
208
+ ```bash
209
+ ae-cli kb +read \
210
+ --source '{"scope":"company","name":"engineering-handbook"}' \
211
+ --path "wiki/sandbox.md" \
212
+ --offset 42 \
213
+ --limit 60
214
+ ```
213
215
 
214
216
  ### Remove One Source
215
217
 
@@ -233,29 +235,29 @@ ae-cli kb +remove --name engineering-handbook
233
235
 
234
236
  ## Command Reference
235
237
 
236
- ### `+query`
238
+ ### `+ask`
237
239
 
238
240
  ```bash
239
- ae-cli kb +query --query "<question>" [--sources '[{"scope":"company","name":"kb-name"}]'] [--top-k 10] [--locale zh|en|ja|ko]
241
+ ae-cli kb +ask --question "<question>" [--sources '[{"scope":"company","name":"kb-name"}]'] [--model-id claude-sonnet-4-6] [--max-turns 50] [--locale zh|en|ja|ko] [--no-wait]
240
242
  ```
241
243
 
242
- - `--query`, alias `-q`: required natural-language question.
244
+ - `--question`, alias `-q`: required natural-language question (1-2000 characters).
243
245
  - `--sources`: optional JSON array of knowledge base refs. Omit to search all accessible knowledge bases.
244
- - `--top-k`: optional max number of hits, 1-50, default 10.
246
+ - `--model-id`: optional LLM model ID. Omit to use the platform default.
247
+ - `--max-turns`: optional agent turn limit (1-100, server default 50).
245
248
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
249
+ - `--no-wait`: optional. Return immediately with `{executionId, status}` instead of polling.
250
+ - When to use: multi-page synthesis or multi-hop questions. For simple factual lookups, prefer `+index` / `+grep` / `+read`.
251
+ - Output: By default, polls and returns `{executionId, answer, sources, modelUsage, toolCallCount, maxTurns, modelId}` (same fields as the previous synchronous response, plus `executionId`). With `--no-wait`, returns `{executionId, status}` immediately. On failure, exits non-zero with a stderr message prefixed by the typed error code (`[timeout]`, `[model_error]`, `[invalid_sources]`, `[process_restart]`).
246
252
 
247
- ### `+ask`
253
+ ### `+ask-status`
248
254
 
249
255
  ```bash
250
- ae-cli kb +ask --question "<question>" [--sources '[{"scope":"company","name":"kb-name"}]'] [--model-id claude-sonnet-4-6] [--max-turns 50] [--locale zh|en|ja|ko]
256
+ ae-cli kb +ask-status --execution-id <id>
251
257
  ```
252
258
 
253
- - `--question`, alias `-q`: required natural-language question (1-2000 characters).
254
- - `--sources`: optional JSON array of knowledge base refs. Omit to search all accessible knowledge bases.
255
- - `--model-id`: optional LLM model ID. Omit to use the platform default.
256
- - `--max-turns`: optional agent turn limit (1-100, server default 50).
257
- - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
258
- - **Token cost**: this command invokes an LLM on the server and consumes platform tokens. Prefer `+index` -> `+grep` -> `+read` for token-free deterministic retrieval.
259
+ - `--execution-id`: required. The execution ID returned by `+ask` submission.
260
+ - Output: Returns the current execution state: `{executionId, status, elapsedMs?, answer?, sources?, modelUsage?, toolCallCount?, error?}`. Does not poll; returns a single snapshot.
259
261
 
260
262
  ### `+list`
261
263
 
@@ -263,7 +265,7 @@ ae-cli kb +ask --question "<question>" [--sources '[{"scope":"company","name":"k
263
265
  ae-cli kb +list [--build-status compiled] [--locale zh|en|ja|ko]
264
266
  ```
265
267
 
266
- - `--build-status`: optional build status filter (default: `compiled`).
268
+ - `--build-status`: optional; one of `idle` / `pending` / `compiling` / `compiled` / `failed`. Omit to default to `compiled` (system knowledge bases are always listed regardless of status).
267
269
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
268
270
  - Response items include `buildStatus`.
269
271
 
@@ -279,24 +281,27 @@ ae-cli kb +index [--sources '[{"scope":"company","name":"kb-name"}]'] [--locale
279
281
  ### `+grep`
280
282
 
281
283
  ```bash
282
- ae-cli kb +grep --query "<keywords>" [--sources '[{"scope":"company","name":"kb-name"}]'] [--top-k 10] [--locale zh|en|ja|ko]
284
+ ae-cli kb +grep --query "<keywords>" --sources '[{"scope":"company","name":"kb-name"}]' --paths '["wiki/page.md"]' [--top-k 10] [--locale zh|en|ja|ko]
283
285
  ```
284
286
 
285
- - `--query`, alias `-q`: required keywords to search across knowledge bases.
286
- - `--sources`: optional JSON array of knowledge base refs. Omit to search all accessible knowledge bases.
287
+ - `--query`, alias `-q`: required keywords to search.
288
+ - `--sources`: required JSON array of knowledge base refs.
289
+ - `--paths`: required JSON array of wiki pages or subdirectories **copied** from `+index`. A single page is still an array, e.g. `["wiki/sandbox.md"]`. Distinct from `+read --path` (one string).
287
290
  - `--top-k`: optional max number of hits, 1-50, default 10.
288
291
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
292
+ - Each hit includes `sectionStartLine` / `sectionEndLine`: the line range of the section (bounded by the nearest headings) containing the matched line. Use it as the `+read` window.
289
293
 
290
294
  ### `+read`
291
295
 
292
296
  ```bash
293
- ae-cli kb +read --source '{"scope":"company","name":"kb-name"}' --path "index.md" [--offset 1] [--limit 200] [--locale zh|en|ja|ko]
297
+ ae-cli kb +read --source '{"scope":"company","name":"kb-name"}' --path "index.md" [--offset 1] [--limit 200] [--outline] [--locale zh|en|ja|ko]
294
298
  ```
295
299
 
296
300
  - `--source`: required JSON object pointing to exactly one knowledge base.
297
301
  - `--path`: required page path relative to the knowledge base root, such as `index.md` or `wiki/concepts/data-model.md`.
298
302
  - `--offset`: optional 1-based start line.
299
303
  - `--limit`: optional max line count, 1-10000.
304
+ - `--outline`: optional. Return only the whole-page heading tree (`{level, heading, line}`) with empty content, independent of `--offset` / `--limit`. Use it on long pages to choose which section to read.
300
305
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
301
306
 
302
307
  ### `+new`