opencode-account-manager 0.6.4 → 0.6.5
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 +235 -216
- package/README_VI.md +235 -216
- package/dist/cli.js +83 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/config-store.d.ts +12 -0
- package/dist/core/config-store.d.ts.map +1 -1
- package/dist/core/config-store.js +98 -0
- package/dist/core/config-store.js.map +1 -1
- package/dist/core/health-log.d.ts +9 -0
- package/dist/core/health-log.d.ts.map +1 -0
- package/dist/core/health-log.js +154 -0
- package/dist/core/health-log.js.map +1 -0
- package/dist/core/health-oauth.d.ts +5 -0
- package/dist/core/health-oauth.d.ts.map +1 -0
- package/dist/core/health-oauth.js +147 -0
- package/dist/core/health-oauth.js.map +1 -0
- package/dist/core/health-orchestrator.d.ts +32 -0
- package/dist/core/health-orchestrator.d.ts.map +1 -0
- package/dist/core/health-orchestrator.js +148 -0
- package/dist/core/health-orchestrator.js.map +1 -0
- package/dist/core/health-utils.d.ts +15 -0
- package/dist/core/health-utils.d.ts.map +1 -0
- package/dist/core/health-utils.js +60 -0
- package/dist/core/health-utils.js.map +1 -0
- package/dist/core/paths.d.ts +1 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +4 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/types.d.ts +26 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/tui/Dashboard.d.ts.map +1 -1
- package/dist/tui/Dashboard.js +69 -2
- package/dist/tui/Dashboard.js.map +1 -1
- package/dist/tui/components/AccountList.d.ts +5 -3
- package/dist/tui/components/AccountList.d.ts.map +1 -1
- package/dist/tui/components/AccountList.js +9 -3
- package/dist/tui/components/AccountList.js.map +1 -1
- package/dist/tui/components/DashboardView.d.ts +3 -2
- package/dist/tui/components/DashboardView.d.ts.map +1 -1
- package/dist/tui/components/DashboardView.js +50 -4
- package/dist/tui/components/DashboardView.js.map +1 -1
- package/dist/tui/components/HealthBadge.d.ts +9 -0
- package/dist/tui/components/HealthBadge.d.ts.map +1 -0
- package/dist/tui/components/HealthBadge.js +56 -0
- package/dist/tui/components/HealthBadge.js.map +1 -0
- package/dist/tui/components/StatusBadge.d.ts +2 -1
- package/dist/tui/components/StatusBadge.d.ts.map +1 -1
- package/dist/tui/components/StatusBadge.js +30 -2
- package/dist/tui/components/StatusBadge.js.map +1 -1
- package/dist/tui/components/index.d.ts +1 -0
- package/dist/tui/components/index.d.ts.map +1 -1
- package/dist/tui/components/index.js +3 -1
- package/dist/tui/components/index.js.map +1 -1
- package/docs/BLUEPRINT.md +476 -476
- package/docs/ROADMAP.md +125 -107
- package/package.json +36 -36
- package/src/cli.ts +139 -38
- package/src/core/config-store.ts +278 -171
- package/src/core/crypto.ts +162 -162
- package/src/core/health-log.ts +173 -0
- package/src/core/health-oauth.ts +190 -0
- package/src/core/health-orchestrator.ts +224 -0
- package/src/core/importers/amExport.ts +177 -177
- package/src/core/opencode-config.ts +217 -217
- package/src/core/paths.ts +10 -6
- package/src/core/types.ts +193 -147
- package/src/tui/Dashboard.tsx +557 -478
- package/src/tui/components/AccountList.tsx +122 -104
- package/src/tui/components/ActionPalette.tsx +117 -117
- package/src/tui/components/Box.tsx +7 -7
- package/src/tui/components/DashboardView.tsx +285 -230
- package/src/tui/components/ExportModal.tsx +255 -255
- package/src/tui/components/FileBrowser.tsx +393 -393
- package/src/tui/components/Header.tsx +26 -26
- package/src/tui/components/HealthBadge.tsx +64 -0
- package/src/tui/components/ImportModal.tsx +334 -334
- package/src/tui/components/McpServerList.tsx +67 -67
- package/src/tui/components/Menu.tsx +61 -61
- package/src/tui/components/PasswordInput.tsx +159 -159
- package/src/tui/components/ProviderList.tsx +59 -59
- package/src/tui/components/SectionBox.tsx +35 -35
- package/src/tui/components/StatsRow.tsx +33 -33
- package/src/tui/components/StatusBadge.tsx +36 -3
- package/src/tui/components/index.ts +15 -14
- package/test-minimal.js +26 -26
- package/test-with-accounts.js +58 -58
package/docs/ROADMAP.md
CHANGED
|
@@ -1,125 +1,143 @@
|
|
|
1
|
-
# OpenCode Account Manager - Roadmap
|
|
2
|
-
|
|
3
|
-
## Version History
|
|
4
|
-
|
|
5
|
-
### v0.1.0 - Initial Release
|
|
6
|
-
- [x] Basic TUI dashboard
|
|
7
|
-
- [x] View accounts from antigravity-auth plugin
|
|
8
|
-
- [x] Show rate limit status per account
|
|
9
|
-
- [x] Import from Antigravity Manager folder
|
|
10
|
-
|
|
11
|
-
### v0.2.0 - Account Management
|
|
12
|
-
- [x] Select mode with keyboard navigation
|
|
13
|
-
- [x] Enable/Disable selected accounts
|
|
14
|
-
- [x] Delete selected accounts
|
|
15
|
-
- [x] Export selected accounts to JSON
|
|
16
|
-
- [x] Per-model rate limit display (claude, gemini, etc.)
|
|
17
|
-
|
|
18
|
-
### v0.3.0 - OpenCode Dashboard
|
|
19
|
-
- [x] Rename to opencode-account-manager
|
|
20
|
-
- [x] Read opencode.json config
|
|
21
|
-
- [x] Display all AI providers with model counts
|
|
22
|
-
- [x] Display MCP servers with enabled/disabled status
|
|
23
|
-
- [x] Tab navigation between sections (Providers, Accounts, MCP)
|
|
24
|
-
- [x] Collapsible sections
|
|
25
|
-
|
|
26
|
-
### v0.4.0 - Encrypted Export/Import
|
|
27
|
-
- [x] **Encrypted Export** - AES-256-GCM with password protection
|
|
28
|
-
- [x] **Plain JSON Export** - Keep original format as option
|
|
29
|
-
- [x] **File Browser UI** - Browse folders, quick locations, paste path
|
|
30
|
-
- [x] **Import from File** - Select .ocam or .json files
|
|
31
|
-
- [x] **Password Input** - Masked input with confirmation
|
|
32
|
-
- [x] **Remember Preferences** - Last export/import folder saved
|
|
33
|
-
- [x] **Overwrite Mode** - Replace existing accounts on import
|
|
34
|
-
|
|
35
|
-
### v0.4.1 - npm Publish
|
|
36
|
-
- [x] Published to npm registry
|
|
37
|
-
- [x] Global install via `npm install -g opencode-account-manager`
|
|
38
|
-
- [x] Commands: `ocam`, `opencode-account-manager`
|
|
39
|
-
|
|
40
|
-
### v0.4.2 - Antigravity Manager Export Support
|
|
41
|
-
- [x] **AM Export Import** - Support `[{email, refresh_token}]` format
|
|
42
|
-
- [x] **Auto-detect Format** - Recognize encrypted, portable, AM export formats
|
|
43
|
-
- [x] **Format Preview** - Show detected format in import preview
|
|
44
|
-
- [x] **Professional README** - Updated documentation with LLM installation guide
|
|
45
|
-
|
|
46
|
-
### v0.4.3 - Keyboard Navigation Fix
|
|
47
|
-
- [x] **Number Keys** - Press 1/2/3 to switch sections (Providers/Accounts/MCP)
|
|
48
|
-
- [x] **Tab Navigation** - Fixed Tab key to cycle through sections
|
|
49
|
-
- [x] **UI Indicator** - Show `[1] Providers [2] Accounts [3] MCP` in header
|
|
50
|
-
|
|
51
|
-
### v0.4.4 - Arrow Key Navigation
|
|
52
|
-
- [x] **←→ Arrow Keys** - Switch between sections (Providers ↔ Accounts ↔ MCP)
|
|
53
|
-
- [x] **↑↓ Arrow Keys** - Navigate account list, auto-enters select mode
|
|
54
|
-
- [x] **Space Key** - Toggle selection in select mode
|
|
55
|
-
- [x] **Updated Help Text** - Show arrow key hints in UI
|
|
56
|
-
|
|
57
|
-
### v0.5.0 - OpenCode-style UX
|
|
58
|
-
- [x] **Action Palette** - Press P to open command palette (like OpenCode Ctrl+P)
|
|
59
|
-
- [x] **Unified Navigation** - ↑↓ to navigate everything, Enter to expand/select
|
|
60
|
-
- [x] **Simplified Controls** - No more complex keyboard shortcuts to remember
|
|
61
|
-
- [x] **Inline Selection** - Space to toggle, selection count shown in help bar
|
|
62
|
-
- [x] **Removed MenuBar** - Clean minimal interface
|
|
63
|
-
|
|
64
|
-
### v0.5.1 - Dashboard Tab
|
|
65
|
-
- [x] **Two Tabs** - Dashboard (rate limits) + Settings (providers, accounts, MCP)
|
|
66
|
-
- [x] **Tab Switching** - Press Tab to switch between Dashboard and Settings
|
|
67
|
-
- [x] **Rate Limit View** - Like Antigravity Manager, shows accounts with model limits
|
|
68
|
-
- [x] **Progress Bars** - Visual indicator of rate limit status per model
|
|
69
|
-
- [x] **Time Remaining** - Shows hours/minutes until limit resets
|
|
70
|
-
|
|
71
|
-
### v0.5.2 - Loading Indicator
|
|
1
|
+
# OpenCode Account Manager - Roadmap
|
|
2
|
+
|
|
3
|
+
## Version History
|
|
4
|
+
|
|
5
|
+
### v0.1.0 - Initial Release
|
|
6
|
+
- [x] Basic TUI dashboard
|
|
7
|
+
- [x] View accounts from antigravity-auth plugin
|
|
8
|
+
- [x] Show rate limit status per account
|
|
9
|
+
- [x] Import from Antigravity Manager folder
|
|
10
|
+
|
|
11
|
+
### v0.2.0 - Account Management
|
|
12
|
+
- [x] Select mode with keyboard navigation
|
|
13
|
+
- [x] Enable/Disable selected accounts
|
|
14
|
+
- [x] Delete selected accounts
|
|
15
|
+
- [x] Export selected accounts to JSON
|
|
16
|
+
- [x] Per-model rate limit display (claude, gemini, etc.)
|
|
17
|
+
|
|
18
|
+
### v0.3.0 - OpenCode Dashboard
|
|
19
|
+
- [x] Rename to opencode-account-manager
|
|
20
|
+
- [x] Read opencode.json config
|
|
21
|
+
- [x] Display all AI providers with model counts
|
|
22
|
+
- [x] Display MCP servers with enabled/disabled status
|
|
23
|
+
- [x] Tab navigation between sections (Providers, Accounts, MCP)
|
|
24
|
+
- [x] Collapsible sections
|
|
25
|
+
|
|
26
|
+
### v0.4.0 - Encrypted Export/Import
|
|
27
|
+
- [x] **Encrypted Export** - AES-256-GCM with password protection
|
|
28
|
+
- [x] **Plain JSON Export** - Keep original format as option
|
|
29
|
+
- [x] **File Browser UI** - Browse folders, quick locations, paste path
|
|
30
|
+
- [x] **Import from File** - Select .ocam or .json files
|
|
31
|
+
- [x] **Password Input** - Masked input with confirmation
|
|
32
|
+
- [x] **Remember Preferences** - Last export/import folder saved
|
|
33
|
+
- [x] **Overwrite Mode** - Replace existing accounts on import
|
|
34
|
+
|
|
35
|
+
### v0.4.1 - npm Publish
|
|
36
|
+
- [x] Published to npm registry
|
|
37
|
+
- [x] Global install via `npm install -g opencode-account-manager`
|
|
38
|
+
- [x] Commands: `ocam`, `opencode-account-manager`
|
|
39
|
+
|
|
40
|
+
### v0.4.2 - Antigravity Manager Export Support
|
|
41
|
+
- [x] **AM Export Import** - Support `[{email, refresh_token}]` format
|
|
42
|
+
- [x] **Auto-detect Format** - Recognize encrypted, portable, AM export formats
|
|
43
|
+
- [x] **Format Preview** - Show detected format in import preview
|
|
44
|
+
- [x] **Professional README** - Updated documentation with LLM installation guide
|
|
45
|
+
|
|
46
|
+
### v0.4.3 - Keyboard Navigation Fix
|
|
47
|
+
- [x] **Number Keys** - Press 1/2/3 to switch sections (Providers/Accounts/MCP)
|
|
48
|
+
- [x] **Tab Navigation** - Fixed Tab key to cycle through sections
|
|
49
|
+
- [x] **UI Indicator** - Show `[1] Providers [2] Accounts [3] MCP` in header
|
|
50
|
+
|
|
51
|
+
### v0.4.4 - Arrow Key Navigation
|
|
52
|
+
- [x] **←→ Arrow Keys** - Switch between sections (Providers ↔ Accounts ↔ MCP)
|
|
53
|
+
- [x] **↑↓ Arrow Keys** - Navigate account list, auto-enters select mode
|
|
54
|
+
- [x] **Space Key** - Toggle selection in select mode
|
|
55
|
+
- [x] **Updated Help Text** - Show arrow key hints in UI
|
|
56
|
+
|
|
57
|
+
### v0.5.0 - OpenCode-style UX
|
|
58
|
+
- [x] **Action Palette** - Press P to open command palette (like OpenCode Ctrl+P)
|
|
59
|
+
- [x] **Unified Navigation** - ↑↓ to navigate everything, Enter to expand/select
|
|
60
|
+
- [x] **Simplified Controls** - No more complex keyboard shortcuts to remember
|
|
61
|
+
- [x] **Inline Selection** - Space to toggle, selection count shown in help bar
|
|
62
|
+
- [x] **Removed MenuBar** - Clean minimal interface
|
|
63
|
+
|
|
64
|
+
### v0.5.1 - Dashboard Tab
|
|
65
|
+
- [x] **Two Tabs** - Dashboard (rate limits) + Settings (providers, accounts, MCP)
|
|
66
|
+
- [x] **Tab Switching** - Press Tab to switch between Dashboard and Settings
|
|
67
|
+
- [x] **Rate Limit View** - Like Antigravity Manager, shows accounts with model limits
|
|
68
|
+
- [x] **Progress Bars** - Visual indicator of rate limit status per model
|
|
69
|
+
- [x] **Time Remaining** - Shows hours/minutes until limit resets
|
|
70
|
+
|
|
71
|
+
### v0.5.2 - Loading Indicator
|
|
72
72
|
- [x] **Loading State** - Shows progress during refresh
|
|
73
73
|
- [x] **Step Messages** - "Loading OpenCode config...", "Loading accounts...", "Done!"
|
|
74
74
|
- [x] **R Key Shortcut** - Added R to help bar for quick refresh
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
### v0.6.4 - Account Health Check (Current)
|
|
77
|
+
- [x] **Health Check Cache** - TTL + cooldown stored in ocam-config.json
|
|
78
|
+
- [x] **OAuth Validation** - Refresh token check with status mapping
|
|
79
|
+
- [x] **Log Hints** - Parse antigravity-logs for verification errors
|
|
80
|
+
- [x] **Dashboard Badges** - Health indicator + summary counts
|
|
81
|
+
- [x] **CLI Command** - `ocam check` with progress and warnings
|
|
82
|
+
|
|
83
|
+
**Controls:**
|
|
84
|
+
| Key | Action |
|
|
85
|
+
|-----|--------|
|
|
79
86
|
| Tab | Switch between Dashboard and Settings |
|
|
80
87
|
| ↑↓ | Navigate accounts/sections |
|
|
81
88
|
| Space | Toggle account selection |
|
|
82
89
|
| R | Refresh with progress indicator |
|
|
90
|
+
| H | Check account health |
|
|
83
91
|
| P | Open Action Palette |
|
|
84
92
|
| Q | Quit |
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## Future Ideas (Backlog)
|
|
89
|
-
|
|
90
|
-
### v0.5.0 - Enhanced Security
|
|
91
|
-
- [ ] Password strength indicator
|
|
92
|
-
- [ ] Auto-lock after inactivity
|
|
93
|
-
- [ ] Encrypted storage for config
|
|
94
|
-
|
|
95
|
-
### v0.6.0 - Cloud Sync
|
|
96
|
-
- [ ] Sync accounts to cloud storage (Google Drive, Dropbox)
|
|
97
|
-
- [ ] Multi-device sync
|
|
98
|
-
- [ ] Conflict resolution
|
|
99
|
-
|
|
100
|
-
### v0.7.0 - Account Health
|
|
101
|
-
- [ ] Check if refresh tokens are still valid
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Future Ideas (Backlog)
|
|
97
|
+
|
|
98
|
+
### v0.5.0 - Enhanced Security
|
|
99
|
+
- [ ] Password strength indicator
|
|
100
|
+
- [ ] Auto-lock after inactivity
|
|
101
|
+
- [ ] Encrypted storage for config
|
|
102
|
+
|
|
103
|
+
### v0.6.0 - Cloud Sync
|
|
104
|
+
- [ ] Sync accounts to cloud storage (Google Drive, Dropbox)
|
|
105
|
+
- [ ] Multi-device sync
|
|
106
|
+
- [ ] Conflict resolution
|
|
107
|
+
|
|
108
|
+
### v0.7.0 - Account Health (Follow-ups)
|
|
102
109
|
- [ ] Auto-refresh expired tokens
|
|
110
|
+
- [ ] Background health monitoring
|
|
103
111
|
- [ ] Health check on startup
|
|
112
|
+
|
|
113
|
+
### v0.8.0 - MCP Management
|
|
114
|
+
- [ ] Enable/Disable MCP servers from TUI
|
|
115
|
+
- [ ] Add new MCP servers
|
|
116
|
+
- [ ] View MCP server logs
|
|
117
|
+
|
|
118
|
+
### v0.9.0 - Provider Management
|
|
119
|
+
- [ ] Add/Edit custom providers
|
|
120
|
+
- [ ] Test provider connection
|
|
121
|
+
- [ ] Model usage statistics
|
|
122
|
+
|
|
123
|
+
### v1.0.0 - Stable Release
|
|
124
|
+
- [x] npm publish
|
|
125
|
+
- [ ] Full documentation
|
|
126
|
+
- [ ] Windows/Mac/Linux installers
|
|
127
|
+
- [ ] Integration tests
|
|
128
|
+
|
|
129
|
+
---
|
|
104
130
|
|
|
105
|
-
|
|
106
|
-
- [ ] Enable/Disable MCP servers from TUI
|
|
107
|
-
- [ ] Add new MCP servers
|
|
108
|
-
- [ ] View MCP server logs
|
|
109
|
-
|
|
110
|
-
### v0.9.0 - Provider Management
|
|
111
|
-
- [ ] Add/Edit custom providers
|
|
112
|
-
- [ ] Test provider connection
|
|
113
|
-
- [ ] Model usage statistics
|
|
131
|
+
## Manual Test Checklist (Health Check)
|
|
114
132
|
|
|
115
|
-
|
|
116
|
-
- [
|
|
117
|
-
- [ ]
|
|
118
|
-
- [ ]
|
|
119
|
-
- [ ]
|
|
133
|
+
- [ ] **Happy path**: OAuth config set, refresh token valid → status `ok`
|
|
134
|
+
- [ ] **Invalid grant**: revoked/expired token → status `revoked` (or `password_changed` if error_description matches)
|
|
135
|
+
- [ ] **Verification required**: trigger `verification_required` mapping via `invalid_grant` with verify/challenge text
|
|
136
|
+
- [ ] **Network error**: disconnect network → status `network_error`
|
|
137
|
+
- [ ] **Missing OAuth config**: no client_id/client_secret → status `not_configured`
|
|
120
138
|
|
|
121
139
|
---
|
|
122
140
|
|
|
123
141
|
## Contributing
|
|
124
|
-
|
|
125
|
-
See [BLUEPRINT.md](./BLUEPRINT.md) for technical architecture and implementation details.
|
|
142
|
+
|
|
143
|
+
See [BLUEPRINT.md](./BLUEPRINT.md) for technical architecture and implementation details.
|
package/package.json
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "opencode-account-manager",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "TUI Dashboard for OpenCode - View providers, MCP servers, and plugin accounts",
|
|
5
|
-
"main": "dist/cli.js",
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-account-manager",
|
|
3
|
+
"version": "0.6.5",
|
|
4
|
+
"description": "TUI Dashboard for OpenCode - View providers, MCP servers, and plugin accounts",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"ocam": "
|
|
8
|
-
"opencode-account-manager": "
|
|
7
|
+
"ocam": "dist/cli.js",
|
|
8
|
+
"opencode-account-manager": "dist/cli.js"
|
|
9
9
|
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "npx tsc",
|
|
12
|
-
"dev": "npx tsc -w",
|
|
13
|
-
"start": "node dist/cli.js",
|
|
14
|
-
"dashboard": "node dist/cli.js dashboard"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"opencode",
|
|
18
|
-
"antigravity",
|
|
19
|
-
"account-manager",
|
|
20
|
-
"dashboard",
|
|
21
|
-
"tui",
|
|
22
|
-
"mcp",
|
|
23
|
-
"providers"
|
|
24
|
-
],
|
|
25
|
-
"author": "",
|
|
26
|
-
"license": "MIT",
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@types/node": "^20.10.0",
|
|
29
|
-
"@types/react": "^17.0.0",
|
|
30
|
-
"typescript": "^5.3.0"
|
|
31
|
-
},
|
|
32
|
-
"dependencies": {
|
|
33
|
-
"chalk": "^4.1.2",
|
|
34
|
-
"commander": "^11.1.0",
|
|
35
|
-
"ink": "^3.2.0",
|
|
36
|
-
"react": "^17.0.2"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "npx tsc",
|
|
12
|
+
"dev": "npx tsc -w",
|
|
13
|
+
"start": "node dist/cli.js",
|
|
14
|
+
"dashboard": "node dist/cli.js dashboard"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"opencode",
|
|
18
|
+
"antigravity",
|
|
19
|
+
"account-manager",
|
|
20
|
+
"dashboard",
|
|
21
|
+
"tui",
|
|
22
|
+
"mcp",
|
|
23
|
+
"providers"
|
|
24
|
+
],
|
|
25
|
+
"author": "",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.10.0",
|
|
29
|
+
"@types/react": "^17.0.0",
|
|
30
|
+
"typescript": "^5.3.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"chalk": "^4.1.2",
|
|
34
|
+
"commander": "^11.1.0",
|
|
35
|
+
"ink": "^3.2.0",
|
|
36
|
+
"react": "^17.0.2"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -3,24 +3,84 @@ import fs from "fs";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import chalk from "chalk";
|
|
6
|
-
import {
|
|
7
|
-
buildPortableExport,
|
|
8
|
-
createEmptyPluginAccountsFile,
|
|
9
|
-
extractAccountsFromImport,
|
|
10
|
-
mergeAccounts,
|
|
11
|
-
readPluginAccountsFile,
|
|
12
|
-
summarizeAccounts,
|
|
13
|
-
writePluginAccountsFile,
|
|
14
|
-
} from "./core/accounts";
|
|
15
|
-
import { getPluginAccountsPath, getAmFolderPath } from "./core/paths";
|
|
16
|
-
import { importFromAmFolder, isAmFolder } from "./core/importers/amJson";
|
|
17
|
-
import { writeJsonFile } from "./core/utils";
|
|
18
|
-
import { startTuiDashboard } from "./tui";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
import {
|
|
7
|
+
buildPortableExport,
|
|
8
|
+
createEmptyPluginAccountsFile,
|
|
9
|
+
extractAccountsFromImport,
|
|
10
|
+
mergeAccounts,
|
|
11
|
+
readPluginAccountsFile,
|
|
12
|
+
summarizeAccounts,
|
|
13
|
+
writePluginAccountsFile,
|
|
14
|
+
} from "./core/accounts";
|
|
15
|
+
import { getPluginAccountsPath, getAmFolderPath } from "./core/paths";
|
|
16
|
+
import { importFromAmFolder, isAmFolder } from "./core/importers/amJson";
|
|
17
|
+
import { writeJsonFile } from "./core/utils";
|
|
18
|
+
import { startTuiDashboard } from "./tui";
|
|
19
|
+
import { checkAccountsHealth, HealthCheckResult } from "./core/health-orchestrator";
|
|
20
|
+
import { AccountHealthStatus } from "./core/types";
|
|
21
|
+
|
|
22
|
+
function formatTimestamp(timestamp?: number): string {
|
|
23
|
+
if (!timestamp) return "-";
|
|
24
|
+
return new Date(timestamp).toLocaleString();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getStatusLabel(status: AccountHealthStatus): string {
|
|
28
|
+
switch (status) {
|
|
29
|
+
case "verification_required":
|
|
30
|
+
return chalk.bgYellow.black(" VERIFY ");
|
|
31
|
+
case "revoked":
|
|
32
|
+
return chalk.bgRed.white(" REVOKED ");
|
|
33
|
+
case "disabled":
|
|
34
|
+
return chalk.bgRed.white(" DISABLED ");
|
|
35
|
+
case "deleted":
|
|
36
|
+
return chalk.bgRed.white(" DELETED ");
|
|
37
|
+
case "password_changed":
|
|
38
|
+
return chalk.bgYellow.black(" PASSWD ");
|
|
39
|
+
case "network_error":
|
|
40
|
+
return chalk.bgBlue.white(" NETWORK ");
|
|
41
|
+
case "unknown_error":
|
|
42
|
+
return chalk.bgRed.white(" ERROR ");
|
|
43
|
+
case "not_configured":
|
|
44
|
+
return chalk.bgGray.white(" CONFIG ");
|
|
45
|
+
default:
|
|
46
|
+
return chalk.bgGray.white(` ${status.toUpperCase()} `);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function printHealthCheckResult(result: HealthCheckResult) {
|
|
51
|
+
const { counts, timing, items } = result;
|
|
52
|
+
const issues =
|
|
53
|
+
counts.total -
|
|
54
|
+
counts.byStatus.ok -
|
|
55
|
+
(counts.byStatus.not_checked || 0);
|
|
56
|
+
|
|
57
|
+
console.log(chalk.bold("\n=== Health Check Summary ==="));
|
|
58
|
+
console.log(
|
|
59
|
+
`Total: ${counts.total} | ` +
|
|
60
|
+
`${chalk.green("OK: " + counts.byStatus.ok)} | ` +
|
|
61
|
+
`${
|
|
62
|
+
issues > 0 ? chalk.red("Issues: " + issues) : chalk.gray("Issues: 0")
|
|
63
|
+
} | ` +
|
|
64
|
+
`Time: ${(timing.durationMs / 1000).toFixed(1)}s\n`
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const warnings = items.filter(
|
|
68
|
+
(item) => item.result.status !== "ok" && item.result.status !== "not_checked"
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (warnings.length > 0) {
|
|
72
|
+
console.log(chalk.bold("Warnings:"));
|
|
73
|
+
for (const item of warnings) {
|
|
74
|
+
const label = getStatusLabel(item.result.status);
|
|
75
|
+
const msg = item.result.message || item.result.status;
|
|
76
|
+
console.log(`${label} ${item.email} ${chalk.gray(`(${msg})`)}`);
|
|
77
|
+
}
|
|
78
|
+
console.log("");
|
|
79
|
+
} else if (counts.total > 0) {
|
|
80
|
+
console.log(chalk.green("All accounts are healthy.\n"));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
24
84
|
|
|
25
85
|
function isLimited(rateLimitResetTimes?: Record<string, number>): boolean {
|
|
26
86
|
if (!rateLimitResetTimes) return false;
|
|
@@ -28,20 +88,29 @@ function isLimited(rateLimitResetTimes?: Record<string, number>): boolean {
|
|
|
28
88
|
return Object.values(rateLimitResetTimes).some((value) => value > now);
|
|
29
89
|
}
|
|
30
90
|
|
|
31
|
-
function safeReadPluginFile(pluginPath: string) {
|
|
32
|
-
try {
|
|
33
|
-
return readPluginAccountsFile(pluginPath);
|
|
34
|
-
} catch {
|
|
35
|
-
return createEmptyPluginAccountsFile();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
91
|
+
function safeReadPluginFile(pluginPath: string) {
|
|
92
|
+
try {
|
|
93
|
+
return readPluginAccountsFile(pluginPath);
|
|
94
|
+
} catch {
|
|
95
|
+
return createEmptyPluginAccountsFile();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseEmailList(input?: string): string[] | undefined {
|
|
100
|
+
if (!input) return undefined;
|
|
101
|
+
const items = input
|
|
102
|
+
.split(",")
|
|
103
|
+
.map((value) => value.trim())
|
|
104
|
+
.filter((value) => value.length > 0);
|
|
105
|
+
return items.length > 0 ? items : undefined;
|
|
106
|
+
}
|
|
38
107
|
|
|
39
108
|
const program = new Command();
|
|
40
109
|
|
|
41
|
-
program
|
|
42
|
-
.name("ocam")
|
|
43
|
-
.description("OpenCode Account Manager - TUI dashboard and CLI for managing accounts")
|
|
44
|
-
.version("0.5.3");
|
|
110
|
+
program
|
|
111
|
+
.name("ocam")
|
|
112
|
+
.description("OpenCode Account Manager - TUI dashboard and CLI for managing accounts")
|
|
113
|
+
.version("0.5.3");
|
|
45
114
|
|
|
46
115
|
// Default command - show dashboard
|
|
47
116
|
program
|
|
@@ -54,11 +123,11 @@ program
|
|
|
54
123
|
});
|
|
55
124
|
});
|
|
56
125
|
|
|
57
|
-
program
|
|
58
|
-
.command("list")
|
|
59
|
-
.description("List plugin accounts")
|
|
60
|
-
.option("--plugin-path <path>", "Path to plugin accounts file")
|
|
61
|
-
.action((options) => {
|
|
126
|
+
program
|
|
127
|
+
.command("list")
|
|
128
|
+
.description("List plugin accounts")
|
|
129
|
+
.option("--plugin-path <path>", "Path to plugin accounts file")
|
|
130
|
+
.action((options) => {
|
|
62
131
|
const pluginPath = getPluginAccountsPath(options.pluginPath);
|
|
63
132
|
const file = safeReadPluginFile(pluginPath);
|
|
64
133
|
const summary = summarizeAccounts(file.accounts);
|
|
@@ -79,9 +148,41 @@ program
|
|
|
79
148
|
console.log(chalk.gray(` └─ ${model}: ${hours}h`));
|
|
80
149
|
}
|
|
81
150
|
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
program
|
|
156
|
+
.command("check")
|
|
157
|
+
.description("Check account health status")
|
|
158
|
+
.option("--plugin-path <path>", "Path to plugin accounts file")
|
|
159
|
+
.option("--emails <emails>", "Comma-separated list of emails to check")
|
|
160
|
+
.option("--force", "Bypass cache and cooldown checks", false)
|
|
161
|
+
.action(async (options) => {
|
|
162
|
+
const pluginPath = getPluginAccountsPath(options.pluginPath);
|
|
163
|
+
const file = safeReadPluginFile(pluginPath);
|
|
164
|
+
const emails = parseEmailList(options.emails);
|
|
165
|
+
|
|
166
|
+
if (file.accounts.length === 0) {
|
|
167
|
+
console.log(chalk.yellow("No accounts to check."));
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const result = await checkAccountsHealth(file.accounts, {
|
|
172
|
+
emails,
|
|
173
|
+
force: options.force === true,
|
|
174
|
+
includeLogs: true,
|
|
175
|
+
onProgress: (current, total, message) => {
|
|
176
|
+
if (total > 0) {
|
|
177
|
+
process.stdout.write(`\r${chalk.gray(`[${current}/${total}]`)} ${message} `);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
process.stdout.write("\n");
|
|
183
|
+
|
|
184
|
+
printHealthCheckResult(result);
|
|
185
|
+
});
|
|
85
186
|
|
|
86
187
|
program
|
|
87
188
|
.command("export")
|
|
@@ -204,4 +305,4 @@ program
|
|
|
204
305
|
console.log(`Total: ${merged.accounts.length} accounts`);
|
|
205
306
|
});
|
|
206
307
|
|
|
207
|
-
program.parse();
|
|
308
|
+
program.parse();
|