@traisetech/autopilot 2.2.0 → 2.4.0
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/CHANGELOG.md +64 -31
- package/README.md +60 -156
- package/bin/autopilot.js +8 -1
- package/package.json +2 -2
- package/src/commands/guide.js +63 -0
- package/src/commands/leaderboard.js +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,36 +1,69 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [2.
|
|
4
|
-
|
|
5
|
-
### Added
|
|
6
|
-
- **
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- **
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
###
|
|
24
|
-
- **
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- **
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
3
|
+
## [2.4.0] - 2026-02-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Intelligent Guide System**: New `autopilot guide` command for interactive onboarding and documentation.
|
|
7
|
+
- **Enhanced Visual Identity**: Modernized branding and professional documentation aesthetics.
|
|
8
|
+
- **Premium Command Reference**: Redesigned website command library with grouped categories and interactive cards.
|
|
9
|
+
|
|
10
|
+
### Improved
|
|
11
|
+
- **Developer Experience**: Added explicit guide callouts in the documentation hero section.
|
|
12
|
+
- **Onboarding Flow**: Simplified the initial setup path for new users.
|
|
13
|
+
|
|
14
|
+
## [2.3.0] - 2026-02-18
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Production-Ready Leaderboard**:
|
|
18
|
+
- Implemented secure Row-Level Security (RLS) policies for anonymized stat synchronization.
|
|
19
|
+
- Enhanced API response to include real-time global ranking.
|
|
20
|
+
- **Searchable Documentation**:
|
|
21
|
+
- Added full-text search capability to the documentation portal using a pre-built static index.
|
|
22
|
+
|
|
23
|
+
### Improved
|
|
24
|
+
- **Error Diagnostics**:
|
|
25
|
+
- CLI now provides detailed feedback for server-side errors during sync (no more generic 500 errors).
|
|
26
|
+
- Synchronous environment validation for Supabase credentials on the server.
|
|
27
|
+
- **AI Reliability**:
|
|
28
|
+
- Improved Grok API error parsing for rate limits and invalid tokens.
|
|
29
|
+
- Optimized fetch timeouts for better responsiveness in low-bandwidth environments.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- **CLI Stability**:
|
|
33
|
+
- Fixed sync failures caused by rigid database permission checks.
|
|
34
|
+
- Resolved potential crashes when parsing malformed `autopilot.log` entries.
|
|
35
|
+
|
|
36
|
+
## [2.2.0] - 2026-02-14
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- **Automatic Leaderboard Sync**:
|
|
40
|
+
- Watcher auto-syncs stats after commit or push.
|
|
41
|
+
- Uses site API with anonymized ID and metrics only.
|
|
42
|
+
- **Durable Backend Storage**:
|
|
43
|
+
- Website API backed by Supabase for persistent leaderboard and event telemetry.
|
|
44
|
+
- **Events API**:
|
|
45
|
+
- CLI emits `push_success` events with commit hash and identity.
|
|
46
|
+
- Website ingests and stores normalized payloads.
|
|
47
|
+
|
|
48
|
+
### Improved
|
|
49
|
+
- **Config Consistency**:
|
|
50
|
+
- Standardized `blockedBranches` with backward-compat mapping.
|
|
51
|
+
- **AI Network Resilience**:
|
|
52
|
+
- Added request timeouts to Gemini/Grok; doctor validates connectivity.
|
|
53
|
+
- **Programmatic Imports**:
|
|
54
|
+
- Fixed command imports wiring in `src/index.js`.
|
|
55
|
+
|
|
56
|
+
### Docs/Website
|
|
57
|
+
- **OG Image & Favicon**:
|
|
58
|
+
- Added `public/og-image.svg` and `public/favicon.svg`.
|
|
59
|
+
- Corrected manifest path to `/manifest.webmanifest`.
|
|
60
|
+
- **Foreground Watcher Wording**:
|
|
61
|
+
- Updated homepage and commands to reflect foreground behavior.
|
|
62
|
+
|
|
63
|
+
### Tests
|
|
64
|
+
- **Grok Test Coverage**:
|
|
65
|
+
- Added parity tests mirroring Gemini scenarios.
|
|
66
|
+
|
|
34
67
|
All notable changes to this project will be documented in this file.
|
|
35
68
|
This project follows [Semantic Versioning](https://semver.org).
|
|
36
69
|
|
package/README.md
CHANGED
|
@@ -2,201 +2,105 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<img src="https://autopilot-cli.vercel.app/favicon.svg" width="120" height="120" alt="Autopilot Logo" />
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# Autopilot CLI v2.4.0
|
|
8
|
+
**The Intelligent Git Engine That Respects Your Flow.**
|
|
8
9
|
|
|
9
|
-
[](https://github.com/PraiseTechzw/autopilot-cli/stargazers)
|
|
14
|
-
[](https://github.com/PraiseTechzw/autopilot-cli/actions)
|
|
15
|
-
[](http://makeapullrequest.com)
|
|
10
|
+
[](https://www.npmjs.com/package/@traisetech/autopilot)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
[](https://www.npmjs.com/package/@traisetech/autopilot)
|
|
13
|
+
[](https://github.com/PraiseTechzw/autopilot-cli/stargazers)
|
|
16
14
|
|
|
17
|
-
**
|
|
18
|
-
|
|
19
|
-
[Features](#-features) • [Installation](#-installation) • [How It Works](#-how-autopilot-works) • [Safety & Guarantees](#-safety--guarantees) • [Commands](#-commands)
|
|
15
|
+
[**Explore Documentation**](https://autopilot-cli.vercel.app) • [**View Leaderboard**](https://autopilot-cli.vercel.app/leaderboard) • [**Report Bug**](https://github.com/PraiseTechzw/autopilot-cli/issues)
|
|
20
16
|
|
|
21
17
|
</div>
|
|
22
18
|
|
|
23
19
|
---
|
|
24
20
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
- [How Autopilot Works](#-how-autopilot-works)
|
|
28
|
-
- [Safety & Guarantees](#-safety--guarantees)
|
|
29
|
-
- [Failure & Recovery](#-failure--recovery)
|
|
30
|
-
- [AI & Privacy](#-ai--privacy)
|
|
31
|
-
- [Leaderboard & Metrics](#-leaderboard--metrics)
|
|
32
|
-
- [Installation](#-installation)
|
|
33
|
-
- [Quick Start](#-quick-start)
|
|
34
|
-
- [Commands](#-commands)
|
|
35
|
-
- [Configuration](#-configuration)
|
|
36
|
-
- [Contributing](#-contributing)
|
|
37
|
-
- [License](#-license)
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## 🔍 How Autopilot Works
|
|
42
|
-
|
|
43
|
-
Autopilot is a local CLI tool that runs in the background of your terminal. It watches your file system for changes and automates the Git workflow based on your configuration.
|
|
21
|
+
## 💎 Why Autopilot?
|
|
44
22
|
|
|
45
|
-
|
|
23
|
+
Autopilot isn't just a "git commit" wrapper. It's a **flow-state companion** designed for high-velocity developers who don't want to break their concentration for repetitive git operations.
|
|
46
24
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
You can stop, pause, or undo Autopilot at any time.
|
|
25
|
+
- **Intelligent Sync**: Automates the commit-push cycle with smart debouncing that respects your typing patterns.
|
|
26
|
+
- **Local-First Architecture**: Your code NEVER leaves your machine. Automation is 100% local.
|
|
27
|
+
- **Zero-Config Simplicity**: Works out of the box with `autopilot init`, but offers surgical control for power users.
|
|
28
|
+
- **AI-Assisted Clarity**: Optional integration with Gemini or Grok to generate meaningful, human-readable commit messages.
|
|
29
|
+
- **Focus Engine**: Track your coding streaks and focus minutes without external time trackers.
|
|
54
30
|
|
|
55
31
|
---
|
|
56
32
|
|
|
57
|
-
##
|
|
58
|
-
|
|
59
|
-
We prioritize the safety of your code above all else. Autopilot follows strict rules to ensure your work is never lost or corrupted.
|
|
33
|
+
## 🛠️ Performance & Safety Rails
|
|
60
34
|
|
|
61
|
-
|
|
35
|
+
We built Autopilot with a **"Trust First"** philosophy. It includes hard-coded safety guarantees that make it impossible to break your repository history.
|
|
62
36
|
|
|
63
|
-
|
|
64
|
-
- **
|
|
65
|
-
- **
|
|
66
|
-
- **
|
|
67
|
-
- **
|
|
68
|
-
- **Allows all actions to be undone**: The `autopilot undo` command safely reverts the last automated commit without losing your file changes.
|
|
37
|
+
### 🛡️ Non-Negotiable Guarantees
|
|
38
|
+
- **No Force-Pushes**: Autopilot will never overwrite remote history.
|
|
39
|
+
- **Conflict Awareness**: Automatically pauses if a merge conflict is detected.
|
|
40
|
+
- **Secret Prevention**: Scans and blocks commits containing `.env` files or potential API keys.
|
|
41
|
+
- **Implicit Reversibility**: Every automated action can be reverted instantly with `autopilot undo`.
|
|
69
42
|
|
|
70
43
|
---
|
|
71
44
|
|
|
72
|
-
##
|
|
73
|
-
|
|
74
|
-
What happens when things go wrong? Autopilot is designed to fail safely.
|
|
75
|
-
|
|
76
|
-
- **Merge Conflicts**: If a `git pull` results in a conflict, Autopilot aborts the operation and notifies you. It will not attempt to resolve conflicts automatically.
|
|
77
|
-
- **Network Issues**: If the internet disconnects, Autopilot will queue commits locally and attempt to push when connectivity is restored (if auto-push is enabled).
|
|
78
|
-
- **Accidental Commits**: If Autopilot commits something you didn't intend, simply run `autopilot undo`. Your files will remain modified in your working directory, but the commit will be removed.
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## 🤖 AI & Privacy
|
|
83
|
-
|
|
84
|
-
Autopilot offers **optional** AI integration (Google Gemini or xAI Grok) to generate context-aware commit messages.
|
|
85
|
-
|
|
86
|
-
- **Opt-In Only**: AI features are disabled by default. You must enable them and provide your own API key.
|
|
87
|
-
- **Data Usage**: When enabled, only the `git diff` (text changes) is sent to the AI provider to generate the message.
|
|
88
|
-
- **Privacy**: Your code is not trained on by Autopilot. We do not store or proxy your code. Interactions are directly between your machine and the AI provider.
|
|
89
|
-
- **Ranking**: AI usage does not affect your position on the Leaderboard.
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## 🏆 Leaderboard & Metrics
|
|
94
|
-
|
|
95
|
-
Autopilot includes a Focus Engine that tracks your local productivity (coding time, commit streaks). You can optionally sync this data to the global Leaderboard.
|
|
96
|
-
|
|
97
|
-
- **Participation is Opt-In**: You must explicitly enable syncing with `autopilot config set leaderboard.sync true`.
|
|
98
|
-
- **Privacy-Safe**: We do not send your email or username directly. IDs are hashed/anonymized.
|
|
99
|
-
- **No Code Collected**: The leaderboard tracks *metrics* (time, counts), not code. No file contents are ever synced.
|
|
100
|
-
- **Insight over Competition**: The goal is to help you understand your habits, not to gamify commit spam. Rankings favor consistency and quality.
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## ⬇️ Installation
|
|
105
|
-
|
|
106
|
-
Install Autopilot globally using npm:
|
|
45
|
+
## 🚀 Getting Started
|
|
107
46
|
|
|
47
|
+
### 1. Installation
|
|
108
48
|
```bash
|
|
109
49
|
npm install -g @traisetech/autopilot
|
|
110
50
|
```
|
|
111
51
|
|
|
112
|
-
|
|
113
|
-
|
|
52
|
+
### 2. Quick Setup
|
|
53
|
+
Run the interactive guide to learn the ropes:
|
|
114
54
|
```bash
|
|
115
|
-
|
|
55
|
+
autopilot guide
|
|
116
56
|
```
|
|
117
57
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
cd /path/to/my-project
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
2. **Initialize Autopilot:**
|
|
128
|
-
```bash
|
|
129
|
-
autopilot init
|
|
130
|
-
```
|
|
131
|
-
Follow the interactive prompts to configure settings (or accept defaults).
|
|
132
|
-
|
|
133
|
-
3. **Start the watcher:**
|
|
134
|
-
```bash
|
|
135
|
-
autopilot start
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
**Autopilot is now running!** It will monitor file changes and automatically commit/push them based on your configuration.
|
|
58
|
+
### 3. Initialize Your Repo
|
|
59
|
+
```bash
|
|
60
|
+
cd /path/to/project
|
|
61
|
+
autopilot init
|
|
62
|
+
```
|
|
139
63
|
|
|
140
|
-
4.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
```
|
|
64
|
+
### 4. Lift Off
|
|
65
|
+
```bash
|
|
66
|
+
autopilot start
|
|
67
|
+
```
|
|
145
68
|
|
|
146
69
|
---
|
|
147
70
|
|
|
148
|
-
##
|
|
149
|
-
|
|
150
|
-
| Command |
|
|
151
|
-
|
|
152
|
-
| `autopilot
|
|
153
|
-
| `autopilot
|
|
154
|
-
| `autopilot
|
|
155
|
-
| `autopilot
|
|
156
|
-
| `autopilot
|
|
157
|
-
| `autopilot
|
|
158
|
-
| `autopilot
|
|
159
|
-
| `autopilot resume` | Resume automation. |
|
|
160
|
-
| `autopilot insights` | View productivity stats and analytics. |
|
|
161
|
-
| `autopilot doctor` | Diagnose configuration and environment issues. |
|
|
71
|
+
## 📊 The Command Suite
|
|
72
|
+
|
|
73
|
+
| Command | Purpose |
|
|
74
|
+
| :--- | :--- |
|
|
75
|
+
| `autopilot start` | Launch the intelligent background watcher. |
|
|
76
|
+
| `autopilot dashboard` | View real-time activity in a high-fidelity TUI. |
|
|
77
|
+
| `autopilot insights` | Deep-dive into your productivity and streak data. |
|
|
78
|
+
| `autopilot undo` | Roll back the last automated commit & preserve changes. |
|
|
79
|
+
| `autopilot guide` | **(NEW)** Interactive walkthrough and onboarding. |
|
|
80
|
+
| `autopilot doctor` | Validate your environment and diagnostic health. |
|
|
81
|
+
| `autopilot status` | Instant pulse-check on the automation engine. |
|
|
162
82
|
|
|
163
83
|
---
|
|
164
84
|
|
|
165
|
-
##
|
|
166
|
-
|
|
167
|
-
Autopilot uses an `.autopilotrc.json` file in your project root.
|
|
168
|
-
|
|
169
|
-
```json
|
|
170
|
-
{
|
|
171
|
-
"debounceSeconds": 20,
|
|
172
|
-
"minSecondsBetweenCommits": 180,
|
|
173
|
-
"autoPush": true,
|
|
174
|
-
"blockBranches": ["main", "master"],
|
|
175
|
-
"teamMode": true,
|
|
176
|
-
"preventSecrets": true,
|
|
177
|
-
"ai": {
|
|
178
|
-
"enabled": true,
|
|
179
|
-
"provider": "gemini"
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
```
|
|
85
|
+
## 🔒 Privacy & AI Transparency
|
|
183
86
|
|
|
184
|
-
|
|
87
|
+
- **Opt-In AI**: AI features are strictly disabled by default. You provide your own keys; we never see them.
|
|
88
|
+
- **No Code Collection**: We do not store, proxy, or train on your source code.
|
|
89
|
+
- **Anonymized Metrics**: Leaderboard data uses cryptographic hashes to preserve your identity while celebrating your progress.
|
|
185
90
|
|
|
186
91
|
---
|
|
187
92
|
|
|
188
93
|
## 🤝 Contributing
|
|
189
94
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
195
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
196
|
-
5. Open a Pull Request
|
|
95
|
+
Autopilot is built by the community. Want to help?
|
|
96
|
+
1. Check out our [Architecture Overview](docs/ARCHITECTURE.md).
|
|
97
|
+
2. Look for `good-first-issue` labels.
|
|
98
|
+
3. Join the mission to automate developer productivity.
|
|
197
99
|
|
|
198
100
|
---
|
|
199
101
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
102
|
+
<div align="center">
|
|
103
|
+
Built with ❤️ by <b>Praise Masunga (PraiseTechzw)</b>
|
|
104
|
+
<br/>
|
|
105
|
+
<i>Git automation that respects your control.</i>
|
|
106
|
+
</div>
|
package/bin/autopilot.js
CHANGED
|
@@ -14,6 +14,7 @@ const doctor = require('../src/commands/doctor');
|
|
|
14
14
|
const presetCommand = require('../src/commands/preset');
|
|
15
15
|
const configCommand = require('../src/commands/config');
|
|
16
16
|
const interactiveCommand = require('../src/commands/interactive');
|
|
17
|
+
const guideCommand = require('../src/commands/guide');
|
|
17
18
|
const pkg = require('../package.json');
|
|
18
19
|
const logger = require('../src/utils/logger');
|
|
19
20
|
const { checkForUpdate } = require('../src/utils/update-check');
|
|
@@ -32,7 +33,8 @@ const commands = {
|
|
|
32
33
|
doctor: doctor,
|
|
33
34
|
preset: presetCommand,
|
|
34
35
|
config: configCommand,
|
|
35
|
-
interactive: interactiveCommand
|
|
36
|
+
interactive: interactiveCommand,
|
|
37
|
+
guide: guideCommand
|
|
36
38
|
};
|
|
37
39
|
|
|
38
40
|
// Runtime assertion to prevent wiring errors
|
|
@@ -130,6 +132,11 @@ program
|
|
|
130
132
|
.option('-g, --global', 'Set the preference globally')
|
|
131
133
|
.action(interactiveCommand);
|
|
132
134
|
|
|
135
|
+
program
|
|
136
|
+
.command('guide')
|
|
137
|
+
.description('Interactive guide to using Autopilot')
|
|
138
|
+
.action(guideCommand);
|
|
139
|
+
|
|
133
140
|
program
|
|
134
141
|
.command('doctor')
|
|
135
142
|
.description('Diagnose and validate autopilot setup')
|
package/package.json
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const logger = require('../utils/logger');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
|
|
5
|
+
async function guide() {
|
|
6
|
+
const { default: chalk } = await import('chalk');
|
|
7
|
+
|
|
8
|
+
console.log('\n');
|
|
9
|
+
logger.section('🚀 Autopilot Intelligent Guide');
|
|
10
|
+
console.log(chalk.gray('Welcome! Let\'s get you up to speed with Autopilot CLI.\n'));
|
|
11
|
+
|
|
12
|
+
const steps = [
|
|
13
|
+
{
|
|
14
|
+
title: '1. Initialization',
|
|
15
|
+
desc: 'Set up your project with safety rails.',
|
|
16
|
+
cmd: 'autopilot init',
|
|
17
|
+
tip: 'This creates .autopilotrc.json and .autopilotignore.'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
title: '2. The Watcher',
|
|
21
|
+
desc: 'Start the automation engine.',
|
|
22
|
+
cmd: 'autopilot start',
|
|
23
|
+
tip: 'Runs in the foreground. Press Ctrl+C to stop.'
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
title: '3. Real-time Dashboard',
|
|
27
|
+
desc: 'See exactly what Autopilot is doing.',
|
|
28
|
+
cmd: 'autopilot dashboard',
|
|
29
|
+
tip: 'Run this in a separate terminal split for the best experience.'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title: '4. Productivity Insights',
|
|
33
|
+
desc: 'Analyze your coding habits and quality.',
|
|
34
|
+
cmd: 'autopilot insights',
|
|
35
|
+
tip: 'Try "autopilot insights --export csv" for a detailed report.'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: '5. Global Leaderboard',
|
|
39
|
+
desc: 'See where you rank among other developers.',
|
|
40
|
+
cmd: 'autopilot leaderboard --sync',
|
|
41
|
+
tip: 'Participation is opt-in and anonymized.'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
title: '6. Safety First: Undoing',
|
|
45
|
+
desc: 'Made a mistake? Revert it instantly.',
|
|
46
|
+
cmd: 'autopilot undo',
|
|
47
|
+
tip: 'Keeps your file changes but removes the git commit.'
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
for (const step of steps) {
|
|
52
|
+
console.log(chalk.bold.blue(`\n ${step.title}`));
|
|
53
|
+
console.log(` ${chalk.white(step.desc)}`);
|
|
54
|
+
console.log(` ${chalk.bgBlack.green(' $ ' + step.cmd)}`);
|
|
55
|
+
console.log(` ${chalk.italic.gray(' Tip: ' + step.tip)}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log('\n');
|
|
59
|
+
logger.info('Pro Tip: Run "autopilot doctor" if you encounter any environment issues.');
|
|
60
|
+
console.log('\n');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = guide;
|
|
@@ -94,7 +94,14 @@ async function syncLeaderboard(apiUrl, options) {
|
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
if (!response.ok) {
|
|
97
|
-
|
|
97
|
+
let errorDetail = '';
|
|
98
|
+
try {
|
|
99
|
+
const errJson = await response.json();
|
|
100
|
+
errorDetail = errJson.details || errJson.error || '';
|
|
101
|
+
} catch (e) {
|
|
102
|
+
// Not a JSON error
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`Server responded with ${response.status}${errorDetail ? ': ' + errorDetail : ''}`);
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
const data = await response.json();
|