@shiplens/cli 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -30
- package/docs/02_CLI_COMMAND_REFERENCE.md +195 -0
- package/lib/api.js +35 -55
- package/lib/assets/skill.js +137 -139
- package/lib/cli.js +59 -55
- package/lib/commands/auth.js +36 -41
- package/lib/commands/context.js +13 -18
- package/lib/commands/dashboards.js +16 -24
- package/lib/commands/doctor.js +43 -34
- package/lib/commands/heatmap.js +14 -9
- package/lib/commands/init.js +51 -51
- package/lib/commands/mcp.js +2 -2
- package/lib/commands/pages.js +19 -23
- package/lib/commands/projects.js +13 -13
- package/lib/commands/query.js +10 -12
- package/lib/commands/sql.js +4 -5
- package/lib/commands/summary.js +7 -7
- package/lib/injector.js +19 -22
- package/lib/mcp-config.js +5 -5
- package/lib/taxonomy.js +22 -25
- package/package.json +2 -2
- package/prompts/prompts_cli_en.md +743 -0
- package/docs/02_SHIPLENS_CLI_/345/205/250/345/221/275/344/273/244/345/217/202/350/200/203/346/211/213/345/206/214.md +0 -205
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🚀 Shiplens CLI
|
|
2
2
|
|
|
3
|
-
> **Shiplens
|
|
3
|
+
> **Official Shiplens CLI — Automated Web User Analytics & AI Agent Analysis Engine.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@shiplens/cli)
|
|
6
6
|
[](LICENSE)
|
|
@@ -8,64 +8,64 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
Shiplens CLI
|
|
11
|
+
Shiplens CLI is the official command-line tool for [shiplens.dev](https://shiplens.dev). It provides automated analytics instrumentation for modern web frontend applications and seamlessly pairs with AI coding agents (Cursor, Windsurf, Codex, Claude, Antigravity, etc.) for conversational data analysis and real-time dashboards.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
## 🌟
|
|
15
|
+
## 🌟 Key Features
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
- **AI Agent
|
|
20
|
-
- **AI
|
|
21
|
-
-
|
|
17
|
+
- **Automated Setup & Instrumentation**: Automatically detects frontend frameworks (Next.js, Vite, Vue, HTML, etc.) and injects `@shiplens/sdk` tracking code.
|
|
18
|
+
- **Web User Analytics**: Real-time traffic summaries, user journeys, retention cohorts, and click heatmaps.
|
|
19
|
+
- **AI Agent Intelligence**: Query and analyze product behavior data directly from AI coding assistants via CLI and local stdio MCP proxy (`shiplens mcp serve`).
|
|
20
|
+
- **AI-Powered Live Dashboards**: Assemble 12-column responsive analytics dashboards from natural language prompts.
|
|
21
|
+
- **Business Context & Adaptive Learning**: Automatically maps DOM hashes to real page names and remembers per-project analysis preferences.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
-
## ⚡
|
|
25
|
+
## ⚡ Quick Start
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Run the initialization command in the root directory of any frontend project:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
#
|
|
30
|
+
# General terminal
|
|
31
31
|
npx --yes @shiplens/cli init
|
|
32
32
|
|
|
33
33
|
# Windows PowerShell
|
|
34
34
|
npx.cmd --yes @shiplens/cli init
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# Backup mirror fallback
|
|
37
37
|
npx --yes --registry=https://registry.npmmirror.com @shiplens/cli init
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
-
## 📊
|
|
42
|
+
## 📊 Core Commands Reference
|
|
43
43
|
|
|
44
|
-
|
|
|
44
|
+
| Command | Description |
|
|
45
45
|
| :--- | :--- |
|
|
46
|
-
| `shiplens init` |
|
|
47
|
-
| `shiplens summary` |
|
|
48
|
-
| `shiplens query` |
|
|
49
|
-
| `shiplens sql` |
|
|
50
|
-
| `shiplens pages` |
|
|
51
|
-
| `shiplens heatmap` |
|
|
52
|
-
| `shiplens dashboards create` |
|
|
53
|
-
| `shiplens doctor` |
|
|
54
|
-
| `shiplens context show` |
|
|
55
|
-
| `shiplens auth bind` |
|
|
56
|
-
| `shiplens mcp serve` |
|
|
46
|
+
| `shiplens init` | Onboard project, instrument tracking SDK, and inject AI skill |
|
|
47
|
+
| `shiplens summary` | Macro traffic overview (PV, UV, dwell time, geos, devices) |
|
|
48
|
+
| `shiplens query` | Multi-dimensional metrics aggregation and conversion funnels |
|
|
49
|
+
| `shiplens sql` | Safe read-only custom SQL queries |
|
|
50
|
+
| `shiplens pages` | Page-level visits and average dwell times |
|
|
51
|
+
| `shiplens heatmap` | Visual click heatmaps and skeleton wireframe snapshots |
|
|
52
|
+
| `shiplens dashboards create` | Generate live AI dashboards from natural language |
|
|
53
|
+
| `shiplens doctor` | End-to-end diagnostics on SDK, network, and configuration |
|
|
54
|
+
| `shiplens context show` | Inspect business context and page semantic mappings |
|
|
55
|
+
| `shiplens auth bind` | Request Magic Link to activate authorization and event quota |
|
|
56
|
+
| `shiplens mcp serve` | Start local stdio MCP proxy for AI IDEs and Agents |
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
60
|
-
## 🔗
|
|
60
|
+
## 🔗 Resources
|
|
61
61
|
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
62
|
+
- Website: [https://shiplens.dev](https://shiplens.dev)
|
|
63
|
+
- Support & FAQ: [https://shiplens.dev/faq](https://shiplens.dev/faq)
|
|
64
|
+
- Command Reference: [`docs/02_CLI_COMMAND_REFERENCE.md`](./docs/02_CLI_COMMAND_REFERENCE.md)
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
-
## 📜
|
|
68
|
+
## 📜 License
|
|
69
69
|
|
|
70
70
|
Apache-2.0 © Shiplens Team
|
|
71
71
|
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Shiplens CLI Command Reference
|
|
2
|
+
|
|
3
|
+
> Complete documentation for all Shiplens CLI commands, flags, arguments, and sample outputs for AI Agent execution.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Global Flags
|
|
8
|
+
|
|
9
|
+
| Flag | Type | Description |
|
|
10
|
+
| :--- | :--- | :--- |
|
|
11
|
+
| `--json` | boolean | Output results in JSON format (required for AI Agents) |
|
|
12
|
+
| `--app-id <id>` | string | Explicitly specify target `app_id` (default: auto-read from `.shiplens.json`) |
|
|
13
|
+
| `--env <env>` | string | Target environment: `production` (default) or `staging` |
|
|
14
|
+
| `--secret <key>` | string | Explicitly pass Access Secret |
|
|
15
|
+
| `--api-url <url>` | string | Custom backend API base URL (default: `http://120.26.230.33`) |
|
|
16
|
+
| `--help`, `-h` | boolean | Display help information |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Project Onboarding (`init`)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
shiplens init [options]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Options:
|
|
27
|
+
- `--name <name>`: Project name (default: package.json name)
|
|
28
|
+
- `--description <desc>`: Project description
|
|
29
|
+
- `--industry <ind>`: Industry category
|
|
30
|
+
- `--genre <id>`: Level 1 Genre ID
|
|
31
|
+
- `--subgenre <id>`: Level 2 Sub-genre ID
|
|
32
|
+
- `--tags <tag1,tag2>`: Comma-separated feature tag IDs (max 10)
|
|
33
|
+
- `--email <email>`: Binding email (pass `auto` to use git config)
|
|
34
|
+
- `--framework <type>`: Override detected framework (`nextjs-app`, `nextjs-pages`, `vite`, `vue`, `html`)
|
|
35
|
+
- `--force`: Force overwrite existing local configuration
|
|
36
|
+
- `--no-install`: Skip package manager installation
|
|
37
|
+
- `--no-commit`: Skip automatic Git commit
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 2. Authentication (`auth`)
|
|
42
|
+
|
|
43
|
+
### Subcommands:
|
|
44
|
+
- `shiplens auth status`: Check credential validity
|
|
45
|
+
- `shiplens auth set [secret]`: Save Access Secret to `~/.shiplens/config.json`
|
|
46
|
+
- `shiplens auth whoami`: Display authenticated user details
|
|
47
|
+
- `shiplens auth logout`: Clear local credentials
|
|
48
|
+
- `shiplens auth bind --email <email>`: Request Magic Link activation email
|
|
49
|
+
- `shiplens auth mcp-config --client <client>`: Generate MCP client configuration
|
|
50
|
+
- `shiplens auth configure --client <client>`: Automatically write MCP configuration
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 3. Projects Management (`projects`)
|
|
55
|
+
|
|
56
|
+
### Subcommands:
|
|
57
|
+
- `shiplens projects list`: List all projects associated with current account
|
|
58
|
+
- `shiplens projects bind`: Bind current project to account
|
|
59
|
+
- `shiplens projects delete [--force]`: Delete project and its data
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 4. Multi-Dimensional Query (`query`)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
shiplens query [options]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Options:
|
|
70
|
+
- `--metric <name>` / `--metrics <m1,m2>`: Metric name(s)
|
|
71
|
+
- `--range <range>`: Time range (`24h`, `7d`, `14d`, `30d`, `90d`)
|
|
72
|
+
- `--grain <grain>`: Time grain (`hour`, `day`, `week`, `month`)
|
|
73
|
+
- `--group-by <dim>`: Group dimension (`path`, `template_id`, `country`, `browser`, `device_type`)
|
|
74
|
+
- `--filter <key=value>`: Filter condition (e.g. `--filter country=US`)
|
|
75
|
+
- `--limit <num>`: Result limit (default: 30)
|
|
76
|
+
- `--file <path>`: Load full `AnalyticsQueryRequest` from JSON file
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 5. Sandboxed SQL (`sql`)
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
shiplens sql --query "<sql>" [options]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Options:
|
|
87
|
+
- `--query "<sql>"` / `--sql "<sql>"`: SQL query string
|
|
88
|
+
- `--stdin`: Read SQL query from stdin stream
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 6. Product Summary (`summary`)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
shiplens summary [--range <range>]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Returns total PV, UV, average session duration, bounce rate, top countries, and top devices.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 7. Page Telemetry (`pages`, `paths`, `canvas`)
|
|
103
|
+
|
|
104
|
+
- `shiplens pages [--range 7d] [--limit 10]`: Page-level visits and dwell times
|
|
105
|
+
- `shiplens paths [--range 7d]`: Sankey user flow and transition paths
|
|
106
|
+
- `shiplens canvas [--range 7d]`: Behavioral canvas node-link topology
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 8. Click Heatmaps (`heatmap`)
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
shiplens heatmap --template <template_id> [--dom-hash <hash>]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Returns skeleton wireframe SVG URL, total clicks, and element click distribution.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 9. AI Dashboards (`dashboards`)
|
|
121
|
+
|
|
122
|
+
- `shiplens dashboards list`: List all dashboards for project
|
|
123
|
+
- `shiplens dashboards create --title "..." --prompt "..."`: Create responsive dashboard via prompt
|
|
124
|
+
- `shiplens dashboards create --ai --prompt "..."`: AI-driven dashboard generation
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 10. Environment Diagnostics (`doctor`)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
shiplens doctor [--json]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Performs health checks on:
|
|
135
|
+
1. `local_config`: `.shiplens.json` validity
|
|
136
|
+
2. `sdk_dependency`: `@shiplens/sdk` in `package.json`
|
|
137
|
+
3. `code_injection`: SDK import in entry files
|
|
138
|
+
4. `ingestion_connectivity`: Network latency to API
|
|
139
|
+
5. `auth_credential`: Access secret resolution
|
|
140
|
+
6. `email_binding`: Quota activation status
|
|
141
|
+
7. `schema_freshness`: Schema synchronization age
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## End-to-End System Topology
|
|
146
|
+
|
|
147
|
+
The full data flow from user action to analytics delivery:
|
|
148
|
+
|
|
149
|
+
```mermaid
|
|
150
|
+
sequenceDiagram
|
|
151
|
+
participant User as User / Agent
|
|
152
|
+
participant CLI as Shiplens CLI
|
|
153
|
+
participant Cloud as Cloud API
|
|
154
|
+
participant SDK as @shiplens/sdk
|
|
155
|
+
participant MCP as Local MCP Proxy
|
|
156
|
+
|
|
157
|
+
Note over User,MCP: Onboarding Flow (Steps 1-7)
|
|
158
|
+
User->>CLI: 1. npx @shiplens/cli init
|
|
159
|
+
CLI->>Cloud: 2. POST /api/connect (register project, 4-level taxonomy)
|
|
160
|
+
Cloud-->>CLI: app_id + dashboard_url
|
|
161
|
+
CLI->>CLI: 3. Inject SDK code into entry file
|
|
162
|
+
CLI->>CLI: 4. Install @shiplens/sdk dependency
|
|
163
|
+
CLI->>CLI: 5. Scan pages → .shiplens/contexts/<app_id>.md
|
|
164
|
+
User->>CLI: 6. shiplens auth bind --email <email>
|
|
165
|
+
CLI->>Cloud: POST /api/auth/start-email
|
|
166
|
+
Cloud-->>User: 7. Magic Link email → user clicks → project activated
|
|
167
|
+
Cloud-->>CLI: Device credentials → shiplens.env (0600)
|
|
168
|
+
|
|
169
|
+
Note over User,MCP: Analysis Flow (Steps 8-12)
|
|
170
|
+
User->>CLI: 8. shiplens summary / query / sql
|
|
171
|
+
CLI->>CLI: 9. Load shiplens.env credentials
|
|
172
|
+
CLI->>Cloud: 10. Authenticated API request
|
|
173
|
+
Cloud-->>CLI: 11. Analytics data response
|
|
174
|
+
CLI-->>User: 12. JSON output → Agent synthesizes insights
|
|
175
|
+
|
|
176
|
+
Note over User,MCP: MCP Integration (Alternative)
|
|
177
|
+
User->>MCP: shiplens mcp serve (stdio)
|
|
178
|
+
MCP->>Cloud: Proxied requests with shiplens.env credentials
|
|
179
|
+
Cloud-->>MCP: Data response
|
|
180
|
+
MCP-->>User: Structured tool results
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Component Roles
|
|
184
|
+
|
|
185
|
+
| Component | Responsibility |
|
|
186
|
+
|-----------|---------------|
|
|
187
|
+
| **CLI** (`npx @shiplens/cli`) | Onboarding, SDK injection, local config management, direct analytics queries |
|
|
188
|
+
| **Cloud API** | Project registration, authentication, data aggregation, dashboard hosting |
|
|
189
|
+
| **SDK** (`@shiplens/sdk`) | Client-side event capture (pageviews, clicks, custom events), DOM hashing |
|
|
190
|
+
| **shiplens.env** | Device-level credentials (Access Secret), file permission 0600, auto-gitignored |
|
|
191
|
+
| **Local MCP Proxy** (`shiplens mcp serve`) | stdio bridge for IDE/Agent integration, forwards requests with local credentials |
|
|
192
|
+
| **.shiplens.json** | Project metadata cache (app_id, project_name, schema timestamp) |
|
|
193
|
+
| **.shiplens/contexts/\<app_id\>.md** | Business context dictionary (page routes, button labels, feature descriptions) |
|
|
194
|
+
| **.shiplens/learnings.md** | User preference overrides (date range, metrics, filters) |
|
|
195
|
+
|
package/lib/api.js
CHANGED
|
@@ -24,25 +24,21 @@ class APIClient {
|
|
|
24
24
|
const fullURL = `${this.baseURL}${path}`;
|
|
25
25
|
const parsed = new URL(fullURL);
|
|
26
26
|
const isHttps = parsed.protocol === 'https:';
|
|
27
|
-
const
|
|
27
|
+
const lib = isHttps ? https : http;
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
const payload = body ? (typeof body === 'string' ? body : JSON.stringify(body)) : null;
|
|
30
|
+
let pkgVer = '1.3.0';
|
|
30
31
|
try {
|
|
31
32
|
pkgVer = require('../package.json').version || pkgVer;
|
|
32
33
|
} catch (e) {}
|
|
33
|
-
|
|
34
34
|
const headers = {
|
|
35
35
|
'Content-Type': 'application/json',
|
|
36
36
|
'User-Agent': `Shiplens-CLI/${pkgVer} (Node.js)`,
|
|
37
37
|
};
|
|
38
|
-
|
|
39
38
|
if (this.secret) {
|
|
40
39
|
headers['Authorization'] = `Bearer ${this.secret}`;
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
let payload = null;
|
|
44
|
-
if (body !== null && body !== undefined) {
|
|
45
|
-
payload = typeof body === 'string' ? body : JSON.stringify(body);
|
|
41
|
+
if (payload) {
|
|
46
42
|
headers['Content-Length'] = Buffer.byteLength(payload);
|
|
47
43
|
}
|
|
48
44
|
|
|
@@ -56,14 +52,16 @@ class APIClient {
|
|
|
56
52
|
};
|
|
57
53
|
|
|
58
54
|
return new Promise((resolve, reject) => {
|
|
59
|
-
const req =
|
|
60
|
-
let
|
|
61
|
-
res.on('data', (chunk) => {
|
|
55
|
+
const req = lib.request(options, (res) => {
|
|
56
|
+
let resData = '';
|
|
57
|
+
res.on('data', (chunk) => {
|
|
58
|
+
resData += chunk;
|
|
59
|
+
});
|
|
62
60
|
res.on('end', () => {
|
|
63
61
|
let json = null;
|
|
64
62
|
try {
|
|
65
|
-
json = JSON.parse(
|
|
66
|
-
} catch {
|
|
63
|
+
json = JSON.parse(resData);
|
|
64
|
+
} catch (e) {
|
|
67
65
|
json = null;
|
|
68
66
|
}
|
|
69
67
|
|
|
@@ -77,12 +75,12 @@ class APIClient {
|
|
|
77
75
|
case 429: code = ERROR_CODES.RATE_LIMITED; break;
|
|
78
76
|
case 400: case 422: code = ERROR_CODES.INVALID_SQL; break;
|
|
79
77
|
}
|
|
80
|
-
const msg = (json && (json.message || json.error || (json.detail && (typeof json.detail === 'string' ? json.detail : JSON.stringify(json.detail))))) ||
|
|
78
|
+
const msg = (json && (json.message || json.error || (json.detail && (typeof json.detail === 'string' ? json.detail : JSON.stringify(json.detail))))) || resData || `HTTP ${res.statusCode}`;
|
|
81
79
|
const err = new Error(msg);
|
|
82
80
|
err.code = (json && json.code) || code;
|
|
83
81
|
err.statusCode = res.statusCode;
|
|
84
82
|
err.status = res.statusCode;
|
|
85
|
-
err.response = json ||
|
|
83
|
+
err.response = json || resData;
|
|
86
84
|
err.ok = false;
|
|
87
85
|
return reject(err);
|
|
88
86
|
}
|
|
@@ -91,16 +89,16 @@ class APIClient {
|
|
|
91
89
|
});
|
|
92
90
|
});
|
|
93
91
|
|
|
94
|
-
req.on('
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
reject(err);
|
|
92
|
+
req.on('error', (err) => {
|
|
93
|
+
const error = new Error(`Network connection error: ${err.message}`);
|
|
94
|
+
error.code = ERROR_CODES.NETWORK_FAILED;
|
|
95
|
+
error.ok = false;
|
|
96
|
+
reject(error);
|
|
100
97
|
});
|
|
101
98
|
|
|
102
|
-
req.on('
|
|
103
|
-
|
|
99
|
+
req.on('timeout', () => {
|
|
100
|
+
req.destroy();
|
|
101
|
+
const error = new Error(`Request timed out (${options.timeout}ms)`);
|
|
104
102
|
error.code = ERROR_CODES.NETWORK_FAILED;
|
|
105
103
|
error.ok = false;
|
|
106
104
|
reject(error);
|
|
@@ -113,26 +111,26 @@ class APIClient {
|
|
|
113
111
|
});
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
// 15
|
|
114
|
+
// 15-second connect & project registration (POST /api/connect)
|
|
117
115
|
async connect(data) {
|
|
118
116
|
const res = await this.request('POST', '/api/connect', data);
|
|
119
117
|
if (typeof res === 'object') res.ok = true;
|
|
120
118
|
return res;
|
|
121
119
|
}
|
|
122
120
|
|
|
123
|
-
//
|
|
121
|
+
// Send Magic Link for email binding (POST /api/auth/email/start)
|
|
124
122
|
async startEmail(data) {
|
|
125
123
|
const res = await this.request('POST', '/api/auth/email/start', data);
|
|
126
124
|
if (typeof res === 'object') res.ok = true;
|
|
127
125
|
return res;
|
|
128
126
|
}
|
|
129
127
|
|
|
130
|
-
//
|
|
128
|
+
// Check email activation status (GET /api/auth/email-status?token=...)
|
|
131
129
|
async checkEmailStatus(token) {
|
|
132
130
|
return this.request('GET', `/api/auth/email-status?token=${encodeURIComponent(token)}`);
|
|
133
131
|
}
|
|
134
132
|
|
|
135
|
-
// startEmail
|
|
133
|
+
// Exponential backoff retry for startEmail
|
|
136
134
|
async startEmailWithRetry(data, retry = 2, baseMs = 500) {
|
|
137
135
|
let lastErr;
|
|
138
136
|
for (let i = 0; i <= retry; i++) {
|
|
@@ -149,60 +147,53 @@ class APIClient {
|
|
|
149
147
|
throw lastErr;
|
|
150
148
|
}
|
|
151
149
|
|
|
152
|
-
//
|
|
150
|
+
// List offline Access Secrets (GET /api/auth/api-keys)
|
|
153
151
|
async listAccessSecrets() {
|
|
154
152
|
return this.request('GET', '/api/auth/api-keys');
|
|
155
153
|
}
|
|
156
154
|
|
|
157
|
-
//
|
|
155
|
+
// Create offline Access Secret (POST /api/auth/api-keys)
|
|
158
156
|
async createAccessSecret(data) {
|
|
159
157
|
return this.request('POST', '/api/auth/api-keys', data);
|
|
160
158
|
}
|
|
161
159
|
|
|
162
|
-
//
|
|
160
|
+
// Revoke offline Access Secret (DELETE /api/auth/api-keys/:keyId)
|
|
163
161
|
async revokeAccessSecret(apiKeyId) {
|
|
164
162
|
return this.request('DELETE', `/api/auth/api-keys/${encodeURIComponent(apiKeyId)}`);
|
|
165
163
|
}
|
|
166
164
|
|
|
167
|
-
// 获取当前登录用户信息 (GET /api/me)
|
|
168
165
|
async me() {
|
|
169
166
|
const res = await this.request('GET', '/api/me');
|
|
170
167
|
if (typeof res === 'object') res.ok = true;
|
|
171
168
|
return res;
|
|
172
169
|
}
|
|
173
170
|
|
|
174
|
-
// 获取用户项目列表 (GET /api/apps)
|
|
175
171
|
async listProjects() {
|
|
176
172
|
const res = await this.request('GET', '/api/apps');
|
|
177
173
|
if (typeof res === 'object') res.ok = true;
|
|
178
174
|
return res;
|
|
179
175
|
}
|
|
180
176
|
|
|
181
|
-
// 绑定项目到当前登录账号 (POST /api/projects/bind)
|
|
182
177
|
async bindProject(appId, projectName = '') {
|
|
183
178
|
return this.request('POST', '/api/projects/bind', { app_id: appId, project_name: projectName });
|
|
184
179
|
}
|
|
185
180
|
|
|
186
|
-
// 更新项目分类法配置 (PUT /api/apps/:appId/taxonomy)
|
|
187
181
|
async updateTaxonomy(appId, data) {
|
|
188
182
|
const res = await this.request('PUT', `/api/apps/${encodeURIComponent(appId)}/taxonomy`, data);
|
|
189
183
|
if (typeof res === 'object') res.ok = true;
|
|
190
184
|
return res;
|
|
191
185
|
}
|
|
192
186
|
|
|
193
|
-
// 获取项目分类法配置 (GET /api/apps/:appId/taxonomy)
|
|
194
187
|
async getTaxonomy(appId) {
|
|
195
188
|
const res = await this.request('GET', `/api/apps/${encodeURIComponent(appId)}/taxonomy`);
|
|
196
189
|
if (typeof res === 'object') res.ok = true;
|
|
197
190
|
return res;
|
|
198
191
|
}
|
|
199
192
|
|
|
200
|
-
// 删除项目 (DELETE /api/apps/:appId)
|
|
201
193
|
async deleteProject(appId) {
|
|
202
194
|
return this.request('DELETE', `/api/apps/${encodeURIComponent(appId)}`);
|
|
203
195
|
}
|
|
204
196
|
|
|
205
|
-
// 综合指标分析查询 (POST /api/ai/apps/:appId/analytics/query)
|
|
206
197
|
async queryAnalytics(appId, queryReq) {
|
|
207
198
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
208
199
|
const actualReq = typeof appId === 'object' ? appId : queryReq;
|
|
@@ -218,7 +209,7 @@ class APIClient {
|
|
|
218
209
|
return this.queryAnalytics(appId, queryReq);
|
|
219
210
|
}
|
|
220
211
|
|
|
221
|
-
//
|
|
212
|
+
// executeSQL (POST /api/mcp/apps/:appId/sql, payload: { sql: queryStr })
|
|
222
213
|
async executeSQL(appId, queryStr) {
|
|
223
214
|
const start = Date.now();
|
|
224
215
|
let actualAppId = appId;
|
|
@@ -237,7 +228,6 @@ class APIClient {
|
|
|
237
228
|
return res;
|
|
238
229
|
}
|
|
239
230
|
|
|
240
|
-
// 产品概览数据 (GET /api/ai/apps/:appId/summary)
|
|
241
231
|
async summary(appId, range = '7d', env = 'production') {
|
|
242
232
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
243
233
|
const actualRange = typeof appId === 'object' ? (appId.range || range) : range;
|
|
@@ -248,7 +238,6 @@ class APIClient {
|
|
|
248
238
|
return res;
|
|
249
239
|
}
|
|
250
240
|
|
|
251
|
-
// 页面访问与停留时长统计 (GET /api/ai/apps/:appId/pages)
|
|
252
241
|
async pages(appId, range = '7d', env = 'production', limit = 10) {
|
|
253
242
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
254
243
|
const actualRange = typeof appId === 'object' ? (appId.range || range) : range;
|
|
@@ -264,7 +253,6 @@ class APIClient {
|
|
|
264
253
|
return this.pages(data);
|
|
265
254
|
}
|
|
266
255
|
|
|
267
|
-
// 用户行为路径/流转分析 (GET /api/ai/apps/:appId/paths)
|
|
268
256
|
async paths(appId, range = '7d', env = 'production') {
|
|
269
257
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
270
258
|
const actualRange = typeof appId === 'object' ? (appId.range || range) : range;
|
|
@@ -282,7 +270,6 @@ class APIClient {
|
|
|
282
270
|
return this.paths(data);
|
|
283
271
|
}
|
|
284
272
|
|
|
285
|
-
// 全局行为画布拓扑 (GET /api/ai/apps/:appId/behavior-canvas)
|
|
286
273
|
async behaviorCanvas(appId, range = '7d', env = 'production') {
|
|
287
274
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
288
275
|
const actualRange = typeof appId === 'object' ? (appId.range || range) : range;
|
|
@@ -293,7 +280,6 @@ class APIClient {
|
|
|
293
280
|
return res;
|
|
294
281
|
}
|
|
295
282
|
|
|
296
|
-
// 点击热力图与骨架图 (GET /api/ai/apps/:appId/pages/:templateId/heatmap)
|
|
297
283
|
async heatmap(appId, templateId, env = 'production', domHash = '') {
|
|
298
284
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
299
285
|
const actualTemplateId = typeof appId === 'object' ? appId.template_id : templateId;
|
|
@@ -314,14 +300,12 @@ class APIClient {
|
|
|
314
300
|
return this.heatmap(data);
|
|
315
301
|
}
|
|
316
302
|
|
|
317
|
-
// 查询仪表盘列表 (GET /api/apps/:appId/dashboards)
|
|
318
303
|
async listDashboards(appId) {
|
|
319
304
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
320
305
|
const res = await this.request('GET', `/api/apps/${encodeURIComponent(actualAppId)}/dashboards`);
|
|
321
306
|
return Array.isArray(res) ? res : (res.dashboards || []);
|
|
322
307
|
}
|
|
323
308
|
|
|
324
|
-
// 创建自定义仪表盘 (POST /api/apps/:appId/dashboards)
|
|
325
309
|
async createDashboard(appId, data) {
|
|
326
310
|
const actualAppId = typeof appId === 'object' ? (appId.app_id || '') : appId;
|
|
327
311
|
const actualData = typeof appId === 'object' ? appId : data;
|
|
@@ -330,14 +314,12 @@ class APIClient {
|
|
|
330
314
|
return res;
|
|
331
315
|
}
|
|
332
316
|
|
|
333
|
-
// 测试网络连接与服务端连通性
|
|
334
317
|
async testConnectivity() {
|
|
335
318
|
const start = Date.now();
|
|
336
319
|
await this.request('GET', '/api/ai/tools');
|
|
337
320
|
return Date.now() - start;
|
|
338
321
|
}
|
|
339
322
|
|
|
340
|
-
// 获取指标元数据 Schema (GET /api/ai/apps/:appId/analytics/schema)
|
|
341
323
|
async getAnalyticsSchema(appId) {
|
|
342
324
|
const actualAppId = typeof appId === 'object' ? appId.app_id : appId;
|
|
343
325
|
const res = await this.request('GET', `/api/ai/apps/${encodeURIComponent(actualAppId)}/analytics/schema`);
|
|
@@ -345,35 +327,33 @@ class APIClient {
|
|
|
345
327
|
return res;
|
|
346
328
|
}
|
|
347
329
|
|
|
348
|
-
//
|
|
330
|
+
// Natural language AI dashboard creation (POST /api/dashboard)
|
|
349
331
|
async createAIDashboard(data) {
|
|
350
332
|
const res = await this.request('POST', '/api/dashboard', data);
|
|
351
333
|
if (typeof res === 'object') res.ok = true;
|
|
352
334
|
return res;
|
|
353
335
|
}
|
|
354
336
|
|
|
355
|
-
//
|
|
337
|
+
// Retrieve project business context (GET /api/apps/:appId/context) - 5s timeout
|
|
356
338
|
async getProjectContext(appId) {
|
|
357
339
|
const res = await this.request('GET', `/api/apps/${encodeURIComponent(appId)}/context`, null, { timeout: 5000 });
|
|
358
340
|
if (typeof res === 'object') res.ok = true;
|
|
359
341
|
return res;
|
|
360
342
|
}
|
|
361
343
|
|
|
362
|
-
//
|
|
344
|
+
// Upload/sync project business context (PUT /api/apps/:appId/context) - 5s timeout
|
|
363
345
|
async uploadProjectContext(appId, data) {
|
|
364
346
|
const res = await this.request('PUT', `/api/apps/${encodeURIComponent(appId)}/context`, data, { timeout: 5000 });
|
|
365
347
|
if (typeof res === 'object') res.ok = true;
|
|
366
348
|
return res;
|
|
367
349
|
}
|
|
368
350
|
|
|
369
|
-
//
|
|
351
|
+
// Delete project business context (DELETE /api/apps/:appId/context) - 5s timeout
|
|
370
352
|
async deleteProjectContext(appId) {
|
|
371
|
-
|
|
372
|
-
if (typeof res === 'object') res.ok = true;
|
|
373
|
-
return res;
|
|
353
|
+
return this.request('DELETE', `/api/apps/${encodeURIComponent(appId)}/context`, null, { timeout: 5000 });
|
|
374
354
|
}
|
|
375
355
|
|
|
376
|
-
//
|
|
356
|
+
// Request with exponential backoff retry for general methods
|
|
377
357
|
async requestWithRetry(method, path, body = null, maxRetries = 2) {
|
|
378
358
|
let lastErr = null;
|
|
379
359
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|