gastown-gui 0.9.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/LICENSE +21 -0
- package/README.md +303 -0
- package/assets/apple-touch-icon.png +0 -0
- package/assets/favicon-16.png +0 -0
- package/assets/favicon-192.png +0 -0
- package/assets/favicon-32.png +0 -0
- package/assets/favicon-final.png +0 -0
- package/assets/favicon.ico +0 -0
- package/assets/loading-background.jpeg +0 -0
- package/assets/screenshot.png +0 -0
- package/bin/cli.js +279 -0
- package/css/animations.css +665 -0
- package/css/components.css +7405 -0
- package/css/layout.css +720 -0
- package/css/reset.css +55 -0
- package/css/variables.css +156 -0
- package/index.html +938 -0
- package/js/api.js +415 -0
- package/js/app.js +1097 -0
- package/js/components/activity-feed.js +244 -0
- package/js/components/agent-grid.js +296 -0
- package/js/components/autocomplete.js +213 -0
- package/js/components/convoy-list.js +535 -0
- package/js/components/crew-list.js +300 -0
- package/js/components/dashboard.js +610 -0
- package/js/components/formula-list.js +459 -0
- package/js/components/health-check.js +307 -0
- package/js/components/issue-list.js +187 -0
- package/js/components/mail-list.js +413 -0
- package/js/components/modals.js +1838 -0
- package/js/components/onboarding.js +714 -0
- package/js/components/pr-list.js +217 -0
- package/js/components/rig-list.js +347 -0
- package/js/components/sidebar.js +489 -0
- package/js/components/toast.js +193 -0
- package/js/components/tutorial.js +426 -0
- package/js/components/work-list.js +373 -0
- package/js/shared/agent-types.js +121 -0
- package/js/shared/events.js +57 -0
- package/js/state.js +138 -0
- package/js/utils/formatting.js +64 -0
- package/js/utils/html.js +88 -0
- package/js/utils/performance.js +304 -0
- package/js/utils/tooltip.js +144 -0
- package/package.json +70 -0
- package/server.js +2542 -0
- package/start.sh +84 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 web3dev1337
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Gas Town GUI
|
|
2
|
+
|
|
3
|
+
A standalone web GUI for [Gas Town](https://github.com/steveyegge/gastown) - the multi-agent orchestration system for Claude Code.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
> **Note:** This is an independent companion project, not part of the official Gas Town repository. Originally submitted as [PR #212](https://github.com/steveyegge/gastown/pull/212), now maintained as a standalone package per Steve's recommendation.
|
|
10
|
+
|
|
11
|
+
> *"Thank you for the impressive work on this GUI! The effort and thought that went into it is clear - the architecture is clean, the documentation is thorough, and it demonstrates a solid understanding of Gas Town's workflow. [...] If you're interested in continuing this work, I'd encourage publishing it as a standalone companion project."*
|
|
12
|
+
>
|
|
13
|
+
> — **Steve Yegge**, creator of Gas Town ([PR #212 comment](https://github.com/steveyegge/gastown/pull/212))
|
|
14
|
+
|
|
15
|
+
**Status:** 🚧 **Candidate for Testing** - Provides a solid starting point for a Gas Town GUI interface.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### 1. Install Prerequisites
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Gas Town CLI (required)
|
|
25
|
+
npm install -g @gastown/gt
|
|
26
|
+
# Or: go install github.com/steveyegge/gastown/cmd/gt@latest
|
|
27
|
+
|
|
28
|
+
# GitHub CLI (optional, for PR tracking)
|
|
29
|
+
gh auth login
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Install Gas Town GUI
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Via npm (recommended)
|
|
36
|
+
npm install -g gastown-gui
|
|
37
|
+
|
|
38
|
+
# Or from source
|
|
39
|
+
git clone https://github.com/web3dev1337/gastown-gui.git
|
|
40
|
+
cd gastown-gui
|
|
41
|
+
npm install
|
|
42
|
+
npm link
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 3. Start the GUI
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
gastown-gui start --open
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Opens `http://localhost:7667` in your browser.
|
|
52
|
+
|
|
53
|
+
### 4. Verify Setup
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
gastown-gui doctor
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
- **Rig Management** - Add, view, and organize project repositories
|
|
64
|
+
- **Work Tracking** - Create and manage work items (beads)
|
|
65
|
+
- **Task Assignment** - Sling work to rigs and agents
|
|
66
|
+
- **Real-Time Updates** - Live WebSocket updates for all operations
|
|
67
|
+
- **PR Tracking** - View GitHub pull requests across projects
|
|
68
|
+
- **Mail Inbox** - Read messages from agents and polecats
|
|
69
|
+
- **Health Monitoring** - Run doctor checks and view system status
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## CLI Usage
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Start server (default port 7667)
|
|
77
|
+
gastown-gui
|
|
78
|
+
|
|
79
|
+
# Custom port
|
|
80
|
+
gastown-gui start --port 4000
|
|
81
|
+
|
|
82
|
+
# Open browser automatically
|
|
83
|
+
gastown-gui start --open
|
|
84
|
+
|
|
85
|
+
# Development mode
|
|
86
|
+
gastown-gui start --dev
|
|
87
|
+
|
|
88
|
+
# Check prerequisites
|
|
89
|
+
gastown-gui doctor
|
|
90
|
+
|
|
91
|
+
# Show version
|
|
92
|
+
gastown-gui version
|
|
93
|
+
|
|
94
|
+
# Show help
|
|
95
|
+
gastown-gui help
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Options
|
|
99
|
+
|
|
100
|
+
| Option | Description | Default |
|
|
101
|
+
|--------|-------------|---------|
|
|
102
|
+
| `--port, -p` | Server port | 7667 |
|
|
103
|
+
| `--host, -h` | Server host | 127.0.0.1 |
|
|
104
|
+
| `--open, -o` | Open browser | false |
|
|
105
|
+
| `--dev` | Development mode | false |
|
|
106
|
+
|
|
107
|
+
### Environment Variables
|
|
108
|
+
|
|
109
|
+
| Variable | Description | Default |
|
|
110
|
+
|----------|-------------|---------|
|
|
111
|
+
| `PORT` | Server port | 7667 |
|
|
112
|
+
| `HOST` | Server host | 127.0.0.1 |
|
|
113
|
+
| `GT_ROOT` | Gas Town root directory | ~/gt |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## How It Works
|
|
118
|
+
|
|
119
|
+
The GUI acts as a **bridge** between your browser and the Gas Town CLI:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
┌─────────────┐
|
|
123
|
+
│ Browser │
|
|
124
|
+
│ (Client) │
|
|
125
|
+
└──────┬──────┘
|
|
126
|
+
│ HTTP API / WebSocket
|
|
127
|
+
↓
|
|
128
|
+
┌─────────────┐
|
|
129
|
+
│ gastown- │
|
|
130
|
+
│ gui server │
|
|
131
|
+
└──────┬──────┘
|
|
132
|
+
│ subprocess (gt, bd, gh)
|
|
133
|
+
↓
|
|
134
|
+
┌─────────────┐
|
|
135
|
+
│ ~/gt/ │
|
|
136
|
+
│ workspace │
|
|
137
|
+
└─────────────┘
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
All operations execute through the official `gt` and `bd` commands - the GUI never directly modifies Gas Town's internal state.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Architecture
|
|
145
|
+
|
|
146
|
+
### Tech Stack
|
|
147
|
+
|
|
148
|
+
- **Backend:** Node.js + Express
|
|
149
|
+
- **Frontend:** Vanilla JavaScript (no framework)
|
|
150
|
+
- **Communication:** WebSocket for real-time updates
|
|
151
|
+
- **Testing:** Vitest + Puppeteer E2E tests
|
|
152
|
+
|
|
153
|
+
### Design Principles
|
|
154
|
+
|
|
155
|
+
1. **Server-Authoritative** - All operations execute via `gt` and `bd` CLI commands
|
|
156
|
+
2. **Non-Blocking UI** - Modals close immediately, operations run in background
|
|
157
|
+
3. **Real-Time Updates** - WebSocket broadcasts status changes to all clients
|
|
158
|
+
4. **Graceful Degradation** - UI handles missing data and command failures
|
|
159
|
+
5. **Cache & Refresh** - Background data preloading with stale-while-revalidate
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## API Endpoints
|
|
164
|
+
|
|
165
|
+
| Method | Endpoint | Description | CLI Command |
|
|
166
|
+
|--------|----------|-------------|-------------|
|
|
167
|
+
| GET | `/api/status` | System status | `gt status --json` |
|
|
168
|
+
| GET | `/api/rigs` | List rigs | `gt rig list` |
|
|
169
|
+
| POST | `/api/rigs` | Add rig | `gt rig add` |
|
|
170
|
+
| GET | `/api/work` | List work items | `bd list` |
|
|
171
|
+
| POST | `/api/work` | Create work | `bd new` |
|
|
172
|
+
| POST | `/api/sling` | Sling work | `gt sling` |
|
|
173
|
+
| GET | `/api/prs` | GitHub PRs | `gh pr list` |
|
|
174
|
+
| GET | `/api/mail` | Mail inbox | `gt mail inbox` |
|
|
175
|
+
| GET | `/api/doctor` | Health check | `gt doctor` |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Project Structure
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
gastown-gui/
|
|
183
|
+
├── bin/cli.js # CLI entry point
|
|
184
|
+
├── server.js # Express + WebSocket server
|
|
185
|
+
├── index.html # Main HTML (single page)
|
|
186
|
+
├── css/ # Stylesheets
|
|
187
|
+
│ ├── variables.css
|
|
188
|
+
│ ├── reset.css
|
|
189
|
+
│ ├── layout.css
|
|
190
|
+
│ ├── components.css
|
|
191
|
+
│ └── animations.css
|
|
192
|
+
├── js/
|
|
193
|
+
│ ├── app.js # Main app entry
|
|
194
|
+
│ ├── api.js # API client
|
|
195
|
+
│ ├── state.js # State management
|
|
196
|
+
│ └── components/ # UI components
|
|
197
|
+
│ ├── dashboard.js
|
|
198
|
+
│ ├── rig-list.js
|
|
199
|
+
│ ├── work-list.js
|
|
200
|
+
│ ├── pr-list.js
|
|
201
|
+
│ ├── mail-list.js
|
|
202
|
+
│ └── ...
|
|
203
|
+
├── test/
|
|
204
|
+
│ ├── unit/ # Unit tests
|
|
205
|
+
│ └── e2e.test.js # E2E tests
|
|
206
|
+
└── assets/ # Favicons, icons
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Testing
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# All tests
|
|
215
|
+
npm test
|
|
216
|
+
|
|
217
|
+
# Unit tests only
|
|
218
|
+
npm run test:unit
|
|
219
|
+
|
|
220
|
+
# E2E tests
|
|
221
|
+
npm run test:e2e
|
|
222
|
+
|
|
223
|
+
# Watch mode
|
|
224
|
+
npm run test:watch
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Known Limitations
|
|
230
|
+
|
|
231
|
+
### Remaining Features (Use CLI)
|
|
232
|
+
|
|
233
|
+
| Feature | Status |
|
|
234
|
+
|---------|--------|
|
|
235
|
+
| Polecat spawn/kill/logs | ❌ CLI only |
|
|
236
|
+
| Agent configuration UI | ❌ Not implemented |
|
|
237
|
+
| Rig deletion | ❌ Not implemented |
|
|
238
|
+
|
|
239
|
+
### Recently Implemented
|
|
240
|
+
|
|
241
|
+
| Feature | Status |
|
|
242
|
+
|---------|--------|
|
|
243
|
+
| Crew management | ✅ Create/list/view |
|
|
244
|
+
| Formula operations | ✅ Create/list/use |
|
|
245
|
+
| Test coverage | ✅ 206 tests passing |
|
|
246
|
+
|
|
247
|
+
**Known Issues:**
|
|
248
|
+
- GT CLI sling may fail with "mol bond requires direct database access" (upstream issue)
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Compatibility
|
|
253
|
+
|
|
254
|
+
- **Gas Town:** v0.2.x and later
|
|
255
|
+
- **Node.js:** 18, 20, 22
|
|
256
|
+
- **Browsers:** Chrome, Firefox, Safari (latest)
|
|
257
|
+
|
|
258
|
+
The GUI calls CLI commands via subprocess, so it should work with any Gas Town version that has compatible CLI output.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Contributing
|
|
263
|
+
|
|
264
|
+
Contributions welcome!
|
|
265
|
+
|
|
266
|
+
1. Fork the repository
|
|
267
|
+
2. Create a feature branch
|
|
268
|
+
3. Make your changes
|
|
269
|
+
4. Test locally (start server with `npm start`, verify in browser)
|
|
270
|
+
5. Run automated tests: `npm test` (206 tests must pass)
|
|
271
|
+
6. Submit a pull request
|
|
272
|
+
|
|
273
|
+
### Looking for Maintainers
|
|
274
|
+
|
|
275
|
+
We're looking for maintainers to help review and merge PRs. If you're interested in helping maintain this project, please open an issue or reach out!
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## License
|
|
280
|
+
|
|
281
|
+
MIT
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Credits
|
|
286
|
+
|
|
287
|
+
- **Gas Town:** [steveyegge/gastown](https://github.com/steveyegge/gastown) by Steve Yegge
|
|
288
|
+
- **GUI Implementation:** Built with Claude Code
|
|
289
|
+
- **Original PR:** [#212](https://github.com/steveyegge/gastown/pull/212)
|
|
290
|
+
|
|
291
|
+
### Contributors
|
|
292
|
+
|
|
293
|
+
Thanks to these community members who contributed to the original PR through testing, comments, and recommended fixes:
|
|
294
|
+
|
|
295
|
+
- [@gsxdsm](https://github.com/gsxdsm)
|
|
296
|
+
- [@michaellady](https://github.com/michaellady)
|
|
297
|
+
- [@olivierlefloch](https://github.com/olivierlefloch)
|
|
298
|
+
- [@zalo](https://github.com/zalo)
|
|
299
|
+
- [@irelandpaul](https://github.com/irelandpaul)
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
**Disclaimer:** This is an independent community project, not officially affiliated with Gas Town. Use at your own risk.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gas Town GUI CLI
|
|
5
|
+
*
|
|
6
|
+
* Command-line interface for starting the Gas Town GUI server.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* gastown-gui [command] [options]
|
|
10
|
+
*
|
|
11
|
+
* Commands:
|
|
12
|
+
* start Start the GUI server (default)
|
|
13
|
+
* version Show version
|
|
14
|
+
* help Show help
|
|
15
|
+
*
|
|
16
|
+
* Options:
|
|
17
|
+
* --port, -p Port to run on (default: 7667)
|
|
18
|
+
* --host, -h Host to bind to (default: 127.0.0.1)
|
|
19
|
+
* --open, -o Open browser after starting
|
|
20
|
+
* --dev Enable development mode (auto-reload)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { spawn, execSync } from 'child_process';
|
|
24
|
+
import path from 'path';
|
|
25
|
+
import { fileURLToPath } from 'url';
|
|
26
|
+
import fs from 'fs';
|
|
27
|
+
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
const __dirname = path.dirname(__filename);
|
|
30
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
31
|
+
|
|
32
|
+
// Parse arguments
|
|
33
|
+
const args = process.argv.slice(2);
|
|
34
|
+
|
|
35
|
+
// Check for help/version flags first (before command parsing)
|
|
36
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
37
|
+
showHelp();
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
41
|
+
showVersion();
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const command = args.find(a => !a.startsWith('-')) || 'start';
|
|
46
|
+
const options = {
|
|
47
|
+
port: getOption(['--port', '-p']) || process.env.PORT || '7667',
|
|
48
|
+
host: getOption(['--host', '-h']) || process.env.HOST || '127.0.0.1',
|
|
49
|
+
open: hasFlag(['--open', '-o']),
|
|
50
|
+
dev: hasFlag(['--dev']),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function getOption(flags) {
|
|
54
|
+
for (const flag of flags) {
|
|
55
|
+
const idx = args.indexOf(flag);
|
|
56
|
+
if (idx !== -1 && args[idx + 1]) {
|
|
57
|
+
return args[idx + 1];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function hasFlag(flags) {
|
|
64
|
+
return flags.some(f => args.includes(f));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function showHelp() {
|
|
68
|
+
console.log(`
|
|
69
|
+
Gas Town GUI - Web interface for Gas Town multi-agent orchestrator
|
|
70
|
+
|
|
71
|
+
Usage:
|
|
72
|
+
gastown-gui [command] [options]
|
|
73
|
+
|
|
74
|
+
Commands:
|
|
75
|
+
start Start the GUI server (default)
|
|
76
|
+
version Show version information
|
|
77
|
+
doctor Check Gas Town installation
|
|
78
|
+
help Show this help message
|
|
79
|
+
|
|
80
|
+
Options:
|
|
81
|
+
--port, -p <port> Port to run on (default: 7667, or PORT env var)
|
|
82
|
+
--host, -h <host> Host to bind to (default: 127.0.0.1, or HOST env var)
|
|
83
|
+
--open, -o Open browser after starting
|
|
84
|
+
--dev Enable development mode
|
|
85
|
+
|
|
86
|
+
Environment Variables:
|
|
87
|
+
PORT Server port (default: 7667)
|
|
88
|
+
HOST Server host (default: 127.0.0.1)
|
|
89
|
+
GT_ROOT Gas Town root directory (default: ~/gt)
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
gastown-gui # Start on default port
|
|
93
|
+
gastown-gui start --port 4000 # Start on port 4000
|
|
94
|
+
gastown-gui start --open # Start and open browser
|
|
95
|
+
gastown-gui doctor # Check gt installation
|
|
96
|
+
|
|
97
|
+
Prerequisites:
|
|
98
|
+
- Gas Town CLI (gt) must be installed and in PATH
|
|
99
|
+
- GitHub CLI (gh) for PR/issue tracking (optional)
|
|
100
|
+
|
|
101
|
+
More info: https://github.com/web3dev1337/gastown-gui
|
|
102
|
+
`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function showVersion() {
|
|
106
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
107
|
+
console.log(`gastown-gui v${packageJson.version}`);
|
|
108
|
+
|
|
109
|
+
// Check gt version
|
|
110
|
+
try {
|
|
111
|
+
const gtVersion = execSync('gt version 2>/dev/null || echo "not installed"', { encoding: 'utf8' }).trim();
|
|
112
|
+
console.log(`gt: ${gtVersion}`);
|
|
113
|
+
} catch {
|
|
114
|
+
console.log('gt: not found in PATH');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check gh version
|
|
118
|
+
try {
|
|
119
|
+
const ghVersion = execSync('gh --version 2>/dev/null | head -1 || echo "not installed"', { encoding: 'utf8' }).trim();
|
|
120
|
+
console.log(`gh: ${ghVersion}`);
|
|
121
|
+
} catch {
|
|
122
|
+
console.log('gh: not found in PATH');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function runDoctor() {
|
|
127
|
+
console.log('Gas Town GUI Doctor\n');
|
|
128
|
+
console.log('Checking prerequisites...\n');
|
|
129
|
+
|
|
130
|
+
let allGood = true;
|
|
131
|
+
|
|
132
|
+
// Check Node.js version
|
|
133
|
+
const nodeVersion = process.version;
|
|
134
|
+
const major = parseInt(nodeVersion.slice(1).split('.')[0], 10);
|
|
135
|
+
if (major >= 18) {
|
|
136
|
+
console.log(`✅ Node.js ${nodeVersion} (>= 18 required)`);
|
|
137
|
+
} else {
|
|
138
|
+
console.log(`❌ Node.js ${nodeVersion} (>= 18 required)`);
|
|
139
|
+
allGood = false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Check gt
|
|
143
|
+
try {
|
|
144
|
+
const gtPath = execSync('which gt 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
145
|
+
const gtVersion = execSync('gt version 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
146
|
+
console.log(`✅ gt installed at ${gtPath}`);
|
|
147
|
+
console.log(` Version: ${gtVersion}`);
|
|
148
|
+
} catch {
|
|
149
|
+
console.log('❌ gt not found in PATH');
|
|
150
|
+
console.log(' Install: npm install -g @gastown/gt');
|
|
151
|
+
console.log(' Or visit: https://github.com/steveyegge/gastown');
|
|
152
|
+
allGood = false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Check bd
|
|
156
|
+
try {
|
|
157
|
+
execSync('which bd 2>/dev/null', { encoding: 'utf8' });
|
|
158
|
+
console.log('✅ bd (beads) installed');
|
|
159
|
+
} catch {
|
|
160
|
+
console.log('⚠️ bd (beads) not found - some features may not work');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Check gh
|
|
164
|
+
try {
|
|
165
|
+
const ghVersion = execSync('gh --version 2>/dev/null | head -1', { encoding: 'utf8' }).trim();
|
|
166
|
+
console.log(`✅ GitHub CLI: ${ghVersion}`);
|
|
167
|
+
|
|
168
|
+
// Check auth
|
|
169
|
+
try {
|
|
170
|
+
execSync('gh auth status 2>&1', { encoding: 'utf8' });
|
|
171
|
+
console.log(' ✅ Authenticated');
|
|
172
|
+
} catch {
|
|
173
|
+
console.log(' ⚠️ Not authenticated - run: gh auth login');
|
|
174
|
+
}
|
|
175
|
+
} catch {
|
|
176
|
+
console.log('⚠️ GitHub CLI (gh) not found - PR/issue tracking disabled');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check GT_ROOT
|
|
180
|
+
const gtRoot = process.env.GT_ROOT || path.join(process.env.HOME || '', 'gt');
|
|
181
|
+
if (fs.existsSync(gtRoot)) {
|
|
182
|
+
console.log(`✅ GT_ROOT exists: ${gtRoot}`);
|
|
183
|
+
try {
|
|
184
|
+
const rigs = fs.readdirSync(gtRoot).filter(f => {
|
|
185
|
+
const fullPath = path.join(gtRoot, f);
|
|
186
|
+
return fs.statSync(fullPath).isDirectory() && fs.existsSync(path.join(fullPath, 'config.json'));
|
|
187
|
+
});
|
|
188
|
+
console.log(` Found ${rigs.length} rig(s): ${rigs.join(', ') || '(none)'}`);
|
|
189
|
+
} catch {
|
|
190
|
+
// Ignore
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
console.log(`⚠️ GT_ROOT not found: ${gtRoot}`);
|
|
194
|
+
console.log(' Run: gt install ~/gt');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
console.log('');
|
|
198
|
+
if (allGood) {
|
|
199
|
+
console.log('✅ All prerequisites met! Run: gastown-gui start');
|
|
200
|
+
} else {
|
|
201
|
+
console.log('❌ Some prerequisites missing. Fix issues above and try again.');
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function startServer() {
|
|
207
|
+
console.log(`Starting Gas Town GUI on http://${options.host}:${options.port}...`);
|
|
208
|
+
|
|
209
|
+
const env = {
|
|
210
|
+
...process.env,
|
|
211
|
+
PORT: options.port,
|
|
212
|
+
HOST: options.host,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const serverPath = path.join(packageRoot, 'server.js');
|
|
216
|
+
const serverArgs = options.dev ? ['--dev'] : [];
|
|
217
|
+
|
|
218
|
+
const child = spawn('node', [serverPath, ...serverArgs], {
|
|
219
|
+
env,
|
|
220
|
+
stdio: 'inherit',
|
|
221
|
+
cwd: packageRoot,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// Open browser if requested
|
|
225
|
+
if (options.open) {
|
|
226
|
+
setTimeout(() => {
|
|
227
|
+
const url = `http://${options.host}:${options.port}`;
|
|
228
|
+
const openCmd = process.platform === 'darwin' ? 'open' :
|
|
229
|
+
process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
230
|
+
try {
|
|
231
|
+
execSync(`${openCmd} ${url}`, { stdio: 'ignore' });
|
|
232
|
+
} catch {
|
|
233
|
+
console.log(`Open browser manually: ${url}`);
|
|
234
|
+
}
|
|
235
|
+
}, 1500);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
child.on('error', (err) => {
|
|
239
|
+
console.error('Failed to start server:', err.message);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
child.on('exit', (code) => {
|
|
244
|
+
process.exit(code || 0);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Handle signals
|
|
248
|
+
process.on('SIGINT', () => {
|
|
249
|
+
child.kill('SIGINT');
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
process.on('SIGTERM', () => {
|
|
253
|
+
child.kill('SIGTERM');
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Main
|
|
258
|
+
switch (command) {
|
|
259
|
+
case 'start':
|
|
260
|
+
startServer();
|
|
261
|
+
break;
|
|
262
|
+
case 'version':
|
|
263
|
+
case '-v':
|
|
264
|
+
case '--version':
|
|
265
|
+
showVersion();
|
|
266
|
+
break;
|
|
267
|
+
case 'doctor':
|
|
268
|
+
runDoctor();
|
|
269
|
+
break;
|
|
270
|
+
case 'help':
|
|
271
|
+
case '-h':
|
|
272
|
+
case '--help':
|
|
273
|
+
showHelp();
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
console.error(`Unknown command: ${command}`);
|
|
277
|
+
console.error('Run: gastown-gui help');
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|