opencode-account-manager 0.4.4 → 0.5.1
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/dist/cli.js +1 -1
- package/dist/tui/Dashboard.d.ts.map +1 -1
- package/dist/tui/Dashboard.js +199 -143
- package/dist/tui/Dashboard.js.map +1 -1
- package/dist/tui/components/ActionPalette.d.ts +16 -0
- package/dist/tui/components/ActionPalette.d.ts.map +1 -0
- package/dist/tui/components/ActionPalette.js +106 -0
- package/dist/tui/components/ActionPalette.js.map +1 -0
- package/dist/tui/components/DashboardView.d.ts +9 -0
- package/dist/tui/components/DashboardView.d.ts.map +1 -0
- package/dist/tui/components/DashboardView.js +112 -0
- package/dist/tui/components/DashboardView.js.map +1 -0
- package/dist/tui/components/index.d.ts +2 -0
- package/dist/tui/components/index.d.ts.map +1 -1
- package/dist/tui/components/index.js +5 -1
- package/dist/tui/components/index.js.map +1 -1
- package/docs/ROADMAP.md +25 -1
- package/package.json +1 -1
- package/src/cli.ts +1 -1
- package/src/tui/Dashboard.tsx +265 -183
- package/src/tui/components/ActionPalette.tsx +120 -0
- package/src/tui/components/DashboardView.tsx +170 -0
- package/src/tui/components/index.ts +2 -0
package/src/tui/Dashboard.tsx
CHANGED
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
Header,
|
|
5
5
|
StatsRow,
|
|
6
6
|
AccountList,
|
|
7
|
-
MenuBar,
|
|
8
|
-
MenuAction,
|
|
9
7
|
ProviderList,
|
|
10
8
|
McpServerList,
|
|
11
9
|
SectionBox,
|
|
12
10
|
ExportModal,
|
|
13
11
|
ImportModal,
|
|
12
|
+
ActionPalette,
|
|
13
|
+
PaletteAction,
|
|
14
|
+
DashboardView,
|
|
14
15
|
} from "./components";
|
|
15
16
|
import {
|
|
16
17
|
readPluginAccountsFile,
|
|
@@ -32,8 +33,8 @@ interface DashboardProps {
|
|
|
32
33
|
pluginPath?: string;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
type
|
|
36
|
-
type
|
|
36
|
+
type ModalType = "none" | "export" | "import" | "export-selected" | "palette";
|
|
37
|
+
type MainTab = "dashboard" | "settings";
|
|
37
38
|
|
|
38
39
|
function safeReadPluginFile(pluginPath: string): PluginAccountsFile {
|
|
39
40
|
try {
|
|
@@ -55,10 +56,15 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
55
56
|
const [summary, setSummary] = useState({ total: 0, available: 0, limited: 0 });
|
|
56
57
|
const [message, setMessage] = useState<string | null>(null);
|
|
57
58
|
|
|
58
|
-
//
|
|
59
|
-
const [
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
// Main tab state
|
|
60
|
+
const [activeTab, setActiveTab] = useState<MainTab>("dashboard");
|
|
61
|
+
|
|
62
|
+
// Dashboard tab state
|
|
63
|
+
const [dashboardIndex, setDashboardIndex] = useState(0);
|
|
64
|
+
|
|
65
|
+
// Settings tab state
|
|
66
|
+
const [expandedSection, setExpandedSection] = useState<"providers" | "accounts" | "mcp">("accounts");
|
|
67
|
+
const [settingsNavIndex, setSettingsNavIndex] = useState(0);
|
|
62
68
|
const [checkedEmails, setCheckedEmails] = useState<Set<string>>(new Set());
|
|
63
69
|
|
|
64
70
|
// Modal state
|
|
@@ -79,7 +85,6 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
79
85
|
setAccounts(file.accounts);
|
|
80
86
|
setSummary(summarizeAccounts(file.accounts));
|
|
81
87
|
setCheckedEmails(new Set());
|
|
82
|
-
setSelectedIndex(0);
|
|
83
88
|
};
|
|
84
89
|
|
|
85
90
|
const refresh = () => {
|
|
@@ -93,75 +98,128 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
93
98
|
loadAccounts();
|
|
94
99
|
}, []);
|
|
95
100
|
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
// Build settings navigation items
|
|
102
|
+
const buildSettingsNavItems = () => {
|
|
103
|
+
const items: Array<{ type: "section" | "account"; id?: string; index?: number; email?: string }> = [
|
|
104
|
+
{ type: "section", id: "providers" },
|
|
105
|
+
{ type: "section", id: "accounts" },
|
|
106
|
+
];
|
|
99
107
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (prev === "providers") return "accounts";
|
|
104
|
-
if (prev === "accounts") return "mcp";
|
|
105
|
-
return "providers";
|
|
108
|
+
if (expandedSection === "accounts") {
|
|
109
|
+
accounts.forEach((acc, index) => {
|
|
110
|
+
items.push({ type: "account", index, email: acc.email });
|
|
106
111
|
});
|
|
107
|
-
if (!key.rightArrow || activeSection !== "accounts") {
|
|
108
|
-
setSelectMode(false);
|
|
109
|
-
}
|
|
110
|
-
return;
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
items.push({ type: "section", id: "mcp" });
|
|
115
|
+
return items;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const settingsNavItems = buildSettingsNavItems();
|
|
119
|
+
|
|
120
|
+
// Palette actions
|
|
121
|
+
const paletteActions: PaletteAction[] = [
|
|
122
|
+
{ id: "refresh", label: "Refresh", shortcut: "R" },
|
|
123
|
+
{ id: "export", label: "Export All Accounts", shortcut: "E" },
|
|
124
|
+
{ id: "import", label: "Import from File", shortcut: "I" },
|
|
125
|
+
{ id: "import-am", label: "Import from Antigravity Manager", shortcut: "A" },
|
|
126
|
+
...(checkedEmails.size > 0 ? [
|
|
127
|
+
{ id: "export-selected", label: `Export Selected (${checkedEmails.size})`, shortcut: "X" },
|
|
128
|
+
{ id: "enable-selected", label: `Enable Selected (${checkedEmails.size})` },
|
|
129
|
+
{ id: "disable-selected", label: `Disable Selected (${checkedEmails.size})` },
|
|
130
|
+
{ id: "delete-selected", label: `Delete Selected (${checkedEmails.size})`, shortcut: "Del" },
|
|
131
|
+
{ id: "clear-selection", label: "Clear Selection", shortcut: "N" },
|
|
132
|
+
] : []),
|
|
133
|
+
{ id: "select-all", label: "Select All Accounts", shortcut: "Ctrl+A" },
|
|
134
|
+
{ id: "quit", label: "Quit", shortcut: "Q" },
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
// Keyboard navigation
|
|
138
|
+
useInput((input, key) => {
|
|
139
|
+
if (activeModal === "palette") return;
|
|
140
|
+
if (activeModal !== "none") return;
|
|
141
|
+
|
|
142
|
+
// Tab to switch between main tabs
|
|
143
|
+
if (key.tab) {
|
|
144
|
+
setActiveTab(prev => prev === "dashboard" ? "settings" : "dashboard");
|
|
122
145
|
return;
|
|
123
146
|
}
|
|
124
147
|
|
|
125
|
-
//
|
|
126
|
-
if (input === "
|
|
127
|
-
|
|
128
|
-
setSelectMode(false);
|
|
148
|
+
// Open palette with P
|
|
149
|
+
if (input === "p" || input === "P") {
|
|
150
|
+
setActiveModal("palette");
|
|
129
151
|
return;
|
|
130
152
|
}
|
|
131
|
-
|
|
132
|
-
|
|
153
|
+
|
|
154
|
+
// Quick shortcuts
|
|
155
|
+
if (input === "q" || input === "Q") {
|
|
156
|
+
exit();
|
|
133
157
|
return;
|
|
134
158
|
}
|
|
135
|
-
if (input === "
|
|
136
|
-
|
|
137
|
-
setSelectMode(false);
|
|
159
|
+
if (input === "r" || input === "R") {
|
|
160
|
+
refresh();
|
|
138
161
|
return;
|
|
139
162
|
}
|
|
140
163
|
|
|
141
|
-
//
|
|
142
|
-
if (
|
|
164
|
+
// Tab-specific navigation
|
|
165
|
+
if (activeTab === "dashboard") {
|
|
166
|
+
// Dashboard tab navigation
|
|
143
167
|
if (key.upArrow) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
168
|
+
setDashboardIndex(prev => Math.max(0, prev - 1));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (key.downArrow) {
|
|
172
|
+
setDashboardIndex(prev => Math.min(accounts.length - 1, prev + 1));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Space/Enter to toggle selection
|
|
176
|
+
if (input === " " || key.return) {
|
|
177
|
+
const email = accounts[dashboardIndex]?.email;
|
|
178
|
+
if (email) {
|
|
179
|
+
setCheckedEmails(prev => {
|
|
180
|
+
const next = new Set(prev);
|
|
181
|
+
if (next.has(email)) {
|
|
182
|
+
next.delete(email);
|
|
183
|
+
} else {
|
|
184
|
+
next.add(email);
|
|
185
|
+
}
|
|
186
|
+
return next;
|
|
187
|
+
});
|
|
149
188
|
}
|
|
150
189
|
return;
|
|
151
190
|
}
|
|
191
|
+
} else {
|
|
192
|
+
// Settings tab navigation
|
|
193
|
+
if (key.upArrow) {
|
|
194
|
+
setSettingsNavIndex(prev => Math.max(0, prev - 1));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
152
197
|
if (key.downArrow) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
198
|
+
setSettingsNavIndex(prev => Math.min(settingsNavItems.length - 1, prev + 1));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (key.return) {
|
|
202
|
+
const currentItem = settingsNavItems[settingsNavIndex];
|
|
203
|
+
if (currentItem?.type === "section" && currentItem.id) {
|
|
204
|
+
setExpandedSection(currentItem.id as "providers" | "accounts" | "mcp");
|
|
205
|
+
} else if (currentItem?.type === "account" && currentItem.email) {
|
|
206
|
+
const email = currentItem.email;
|
|
207
|
+
setCheckedEmails(prev => {
|
|
208
|
+
const next = new Set(prev);
|
|
209
|
+
if (next.has(email)) {
|
|
210
|
+
next.delete(email);
|
|
211
|
+
} else {
|
|
212
|
+
next.add(email);
|
|
213
|
+
}
|
|
214
|
+
return next;
|
|
215
|
+
});
|
|
158
216
|
}
|
|
159
217
|
return;
|
|
160
218
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
219
|
+
if (input === " ") {
|
|
220
|
+
const currentItem = settingsNavItems[settingsNavIndex];
|
|
221
|
+
if (currentItem?.type === "account" && currentItem.email) {
|
|
222
|
+
const email = currentItem.email;
|
|
165
223
|
setCheckedEmails(prev => {
|
|
166
224
|
const next = new Set(prev);
|
|
167
225
|
if (next.has(email)) {
|
|
@@ -172,10 +230,67 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
172
230
|
return next;
|
|
173
231
|
});
|
|
174
232
|
}
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Escape to clear selection
|
|
238
|
+
if (key.escape) {
|
|
239
|
+
if (checkedEmails.size > 0) {
|
|
240
|
+
setCheckedEmails(new Set());
|
|
241
|
+
showMessage("Selection cleared", 1500);
|
|
175
242
|
}
|
|
243
|
+
return;
|
|
176
244
|
}
|
|
177
245
|
});
|
|
178
246
|
|
|
247
|
+
// Handle palette action
|
|
248
|
+
const handlePaletteAction = (actionId: string) => {
|
|
249
|
+
setActiveModal("none");
|
|
250
|
+
|
|
251
|
+
switch (actionId) {
|
|
252
|
+
case "refresh":
|
|
253
|
+
refresh();
|
|
254
|
+
break;
|
|
255
|
+
case "export":
|
|
256
|
+
setActiveModal("export");
|
|
257
|
+
break;
|
|
258
|
+
case "import":
|
|
259
|
+
setActiveModal("import");
|
|
260
|
+
break;
|
|
261
|
+
case "import-am":
|
|
262
|
+
handleImportAM();
|
|
263
|
+
break;
|
|
264
|
+
case "export-selected":
|
|
265
|
+
if (checkedEmails.size > 0) {
|
|
266
|
+
setActiveModal("export-selected");
|
|
267
|
+
} else {
|
|
268
|
+
showMessage("No accounts selected", 2000);
|
|
269
|
+
}
|
|
270
|
+
break;
|
|
271
|
+
case "enable-selected":
|
|
272
|
+
handleEnableSelected();
|
|
273
|
+
break;
|
|
274
|
+
case "disable-selected":
|
|
275
|
+
handleDisableSelected();
|
|
276
|
+
break;
|
|
277
|
+
case "delete-selected":
|
|
278
|
+
handleDeleteSelected();
|
|
279
|
+
break;
|
|
280
|
+
case "select-all":
|
|
281
|
+
setCheckedEmails(new Set(accounts.map(a => a.email)));
|
|
282
|
+
showMessage(`Selected ${accounts.length} accounts`, 2000);
|
|
283
|
+
break;
|
|
284
|
+
case "clear-selection":
|
|
285
|
+
setCheckedEmails(new Set());
|
|
286
|
+
showMessage("Selection cleared", 1500);
|
|
287
|
+
break;
|
|
288
|
+
case "quit":
|
|
289
|
+
exit();
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
179
294
|
// Export completion handler
|
|
180
295
|
const handleExportComplete = (filePath: string) => {
|
|
181
296
|
setActiveModal("none");
|
|
@@ -184,7 +299,6 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
184
299
|
|
|
185
300
|
// Import completion handler
|
|
186
301
|
const handleImportComplete = (importedAccounts: Account[], newCount: number, overwrittenCount: number) => {
|
|
187
|
-
// Merge imported accounts with existing (overwrite mode)
|
|
188
302
|
const file = safeReadPluginFile(resolvedPath);
|
|
189
303
|
const merged = mergeAccounts(file, importedAccounts, "merge");
|
|
190
304
|
writePluginAccountsFile(pluginPath, merged);
|
|
@@ -214,7 +328,7 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
214
328
|
|
|
215
329
|
const added = merged.accounts.length - existingFile.accounts.length;
|
|
216
330
|
showMessage(
|
|
217
|
-
`Imported from AM: ${result.accounts.length} found, ${added} new
|
|
331
|
+
`Imported from AM: ${result.accounts.length} found, ${added} new`,
|
|
218
332
|
5000
|
|
219
333
|
);
|
|
220
334
|
|
|
@@ -241,7 +355,7 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
241
355
|
writePluginAccountsFile(pluginPath, file);
|
|
242
356
|
showMessage(`Enabled ${count} accounts`, 3000);
|
|
243
357
|
loadAccounts();
|
|
244
|
-
|
|
358
|
+
setCheckedEmails(new Set());
|
|
245
359
|
};
|
|
246
360
|
|
|
247
361
|
const handleDisableSelected = () => {
|
|
@@ -264,7 +378,7 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
264
378
|
writePluginAccountsFile(pluginPath, file);
|
|
265
379
|
showMessage(`Disabled ${count} accounts`, 3000);
|
|
266
380
|
loadAccounts();
|
|
267
|
-
|
|
381
|
+
setCheckedEmails(new Set());
|
|
268
382
|
};
|
|
269
383
|
|
|
270
384
|
const handleDeleteSelected = () => {
|
|
@@ -282,75 +396,13 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
282
396
|
writePluginAccountsFile(pluginPath, file);
|
|
283
397
|
showMessage(`Deleted ${deletedCount} accounts`, 3000);
|
|
284
398
|
loadAccounts();
|
|
285
|
-
setSelectMode(false);
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const handleSelectAll = () => {
|
|
289
|
-
setCheckedEmails(new Set(accounts.map(a => a.email)));
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
const handleSelectNone = () => {
|
|
293
399
|
setCheckedEmails(new Set());
|
|
294
400
|
};
|
|
295
401
|
|
|
296
|
-
const handleAction = (action: MenuAction) => {
|
|
297
|
-
// Don't handle actions when modal is open
|
|
298
|
-
if (activeModal !== "none") return;
|
|
299
|
-
|
|
300
|
-
switch (action) {
|
|
301
|
-
case "refresh":
|
|
302
|
-
refresh();
|
|
303
|
-
break;
|
|
304
|
-
case "export":
|
|
305
|
-
setActiveModal("export");
|
|
306
|
-
break;
|
|
307
|
-
case "import-file":
|
|
308
|
-
setActiveModal("import");
|
|
309
|
-
break;
|
|
310
|
-
case "import-am":
|
|
311
|
-
handleImportAM();
|
|
312
|
-
break;
|
|
313
|
-
case "toggle-select-mode":
|
|
314
|
-
if (activeSection === "accounts") {
|
|
315
|
-
setSelectMode(prev => !prev);
|
|
316
|
-
setCheckedEmails(new Set());
|
|
317
|
-
setSelectedIndex(0);
|
|
318
|
-
} else {
|
|
319
|
-
showMessage("Switch to Accounts section first (Tab)", 2000);
|
|
320
|
-
}
|
|
321
|
-
break;
|
|
322
|
-
case "select-all":
|
|
323
|
-
handleSelectAll();
|
|
324
|
-
break;
|
|
325
|
-
case "select-none":
|
|
326
|
-
handleSelectNone();
|
|
327
|
-
break;
|
|
328
|
-
case "enable-selected":
|
|
329
|
-
handleEnableSelected();
|
|
330
|
-
break;
|
|
331
|
-
case "disable-selected":
|
|
332
|
-
handleDisableSelected();
|
|
333
|
-
break;
|
|
334
|
-
case "delete-selected":
|
|
335
|
-
handleDeleteSelected();
|
|
336
|
-
break;
|
|
337
|
-
case "export-selected":
|
|
338
|
-
if (checkedEmails.size === 0) {
|
|
339
|
-
showMessage("No accounts selected", 2000);
|
|
340
|
-
} else {
|
|
341
|
-
setActiveModal("export-selected");
|
|
342
|
-
}
|
|
343
|
-
break;
|
|
344
|
-
case "quit":
|
|
345
|
-
exit();
|
|
346
|
-
break;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
|
|
350
402
|
// Calculate stats
|
|
351
403
|
const configSummary = opencodeInfo ? getConfigSummary(opencodeInfo) : null;
|
|
352
404
|
|
|
353
|
-
// Get accounts to export
|
|
405
|
+
// Get accounts to export
|
|
354
406
|
const getAccountsForExport = (): Account[] => {
|
|
355
407
|
if (activeModal === "export-selected") {
|
|
356
408
|
return accounts.filter(acc => checkedEmails.has(acc.email));
|
|
@@ -358,7 +410,11 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
358
410
|
return accounts;
|
|
359
411
|
};
|
|
360
412
|
|
|
361
|
-
//
|
|
413
|
+
// Settings nav helpers
|
|
414
|
+
const currentSettingsItem = settingsNavItems[settingsNavIndex];
|
|
415
|
+
const isOnSection = (id: string) => currentSettingsItem?.type === "section" && currentSettingsItem.id === id;
|
|
416
|
+
|
|
417
|
+
// Render modals
|
|
362
418
|
if (activeModal === "export" || activeModal === "export-selected") {
|
|
363
419
|
return (
|
|
364
420
|
<Box flexDirection="column" padding={1}>
|
|
@@ -385,90 +441,116 @@ export function Dashboard({ pluginPath }: DashboardProps) {
|
|
|
385
441
|
|
|
386
442
|
return (
|
|
387
443
|
<Box flexDirection="column" padding={1}>
|
|
388
|
-
<Header title="OpenCode Account Manager" subtitle="Dashboard" />
|
|
444
|
+
<Header title="OpenCode Account Manager" subtitle={activeTab === "dashboard" ? "Dashboard" : "Settings"} />
|
|
445
|
+
|
|
446
|
+
{/* Tab bar */}
|
|
447
|
+
<Box marginBottom={1}>
|
|
448
|
+
<Text
|
|
449
|
+
backgroundColor={activeTab === "dashboard" ? "cyan" : undefined}
|
|
450
|
+
color={activeTab === "dashboard" ? "black" : "gray"}
|
|
451
|
+
bold={activeTab === "dashboard"}
|
|
452
|
+
>
|
|
453
|
+
{" DASHBOARD "}
|
|
454
|
+
</Text>
|
|
455
|
+
<Text> </Text>
|
|
456
|
+
<Text
|
|
457
|
+
backgroundColor={activeTab === "settings" ? "cyan" : undefined}
|
|
458
|
+
color={activeTab === "settings" ? "black" : "gray"}
|
|
459
|
+
bold={activeTab === "settings"}
|
|
460
|
+
>
|
|
461
|
+
{" SETTINGS "}
|
|
462
|
+
</Text>
|
|
463
|
+
<Text dimColor> (Tab to switch)</Text>
|
|
464
|
+
</Box>
|
|
389
465
|
|
|
390
466
|
{/* Global Stats */}
|
|
391
467
|
<StatsRow
|
|
392
468
|
stats={[
|
|
393
|
-
{ label: "Providers", value: configSummary?.providers || 0, color: "cyan" },
|
|
394
|
-
{ label: "Models", value: configSummary?.models || 0, color: "yellow" },
|
|
395
|
-
{ label: "MCP On", value: configSummary?.mcpEnabled || 0, color: "green" },
|
|
396
|
-
{ label: "MCP Off", value: configSummary?.mcpDisabled || 0, color: "red" },
|
|
397
469
|
{ label: "Accounts", value: summary.total, color: "white" },
|
|
398
470
|
{ label: "Available", value: summary.available, color: "green" },
|
|
399
471
|
{ label: "Limited", value: summary.limited, color: "yellow" },
|
|
472
|
+
{ label: "Providers", value: configSummary?.providers || 0, color: "cyan" },
|
|
473
|
+
{ label: "MCP", value: configSummary?.mcpEnabled || 0, color: "magenta" },
|
|
400
474
|
]}
|
|
401
475
|
/>
|
|
402
476
|
|
|
403
|
-
{/*
|
|
477
|
+
{/* Help bar */}
|
|
404
478
|
<Box marginY={1}>
|
|
405
|
-
<Text dimColor
|
|
406
|
-
<Text color=
|
|
407
|
-
|
|
408
|
-
</Text>
|
|
409
|
-
<Text> </Text>
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
<Text> </Text>
|
|
414
|
-
<Text color={activeSection === "mcp" ? "cyan" : "gray"} bold={activeSection === "mcp"}>
|
|
415
|
-
[3] MCP
|
|
416
|
-
</Text>
|
|
417
|
-
<Text dimColor> (←→ or Tab to switch, ↑↓ in Accounts)</Text>
|
|
479
|
+
<Text dimColor>↑↓ navigate • Space select • </Text>
|
|
480
|
+
<Text color="cyan" bold>P</Text>
|
|
481
|
+
<Text dimColor> actions • </Text>
|
|
482
|
+
<Text color="cyan" bold>Tab</Text>
|
|
483
|
+
<Text dimColor> switch • Q quit</Text>
|
|
484
|
+
{checkedEmails.size > 0 && (
|
|
485
|
+
<Text color="yellow"> • {checkedEmails.size} selected</Text>
|
|
486
|
+
)}
|
|
418
487
|
</Box>
|
|
419
488
|
|
|
420
|
-
{/*
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
489
|
+
{/* Tab content */}
|
|
490
|
+
{activeTab === "dashboard" ? (
|
|
491
|
+
// Dashboard Tab - Rate limits view like Antigravity Manager
|
|
492
|
+
<Box flexDirection="column" borderStyle="round" borderColor="cyan" padding={1}>
|
|
493
|
+
<DashboardView
|
|
494
|
+
accounts={accounts}
|
|
495
|
+
selectedIndex={dashboardIndex}
|
|
496
|
+
/>
|
|
497
|
+
</Box>
|
|
498
|
+
) : (
|
|
499
|
+
// Settings Tab - Original sections view
|
|
500
|
+
<>
|
|
501
|
+
<SectionBox
|
|
502
|
+
title="PROVIDERS"
|
|
503
|
+
borderColor={isOnSection("providers") ? "cyan" : (expandedSection === "providers" ? "white" : "gray")}
|
|
504
|
+
collapsed={expandedSection !== "providers"}
|
|
505
|
+
>
|
|
506
|
+
{opencodeInfo && <ProviderList providers={opencodeInfo.providers} />}
|
|
507
|
+
</SectionBox>
|
|
508
|
+
|
|
509
|
+
<SectionBox
|
|
510
|
+
title={`ACCOUNTS (${opencodeInfo?.plugins[0]?.name || "antigravity-auth"})`}
|
|
511
|
+
borderColor={isOnSection("accounts") || (currentSettingsItem?.type === "account") ? "cyan" : (expandedSection === "accounts" ? "white" : "gray")}
|
|
512
|
+
collapsed={expandedSection !== "accounts"}
|
|
513
|
+
>
|
|
514
|
+
<AccountList
|
|
515
|
+
accounts={accounts}
|
|
516
|
+
selectedIndex={currentSettingsItem?.type === "account" ? (currentSettingsItem.index ?? -1) : -1}
|
|
517
|
+
checkedEmails={checkedEmails}
|
|
518
|
+
showCheckbox={true}
|
|
519
|
+
/>
|
|
520
|
+
</SectionBox>
|
|
521
|
+
|
|
522
|
+
<SectionBox
|
|
523
|
+
title="MCP SERVERS"
|
|
524
|
+
borderColor={isOnSection("mcp") ? "cyan" : (expandedSection === "mcp" ? "white" : "gray")}
|
|
525
|
+
collapsed={expandedSection !== "mcp"}
|
|
526
|
+
>
|
|
527
|
+
{opencodeInfo && <McpServerList servers={opencodeInfo.mcpServers} />}
|
|
528
|
+
</SectionBox>
|
|
529
|
+
</>
|
|
530
|
+
)}
|
|
451
531
|
|
|
452
532
|
{/* Config path */}
|
|
453
533
|
<Box marginTop={1}>
|
|
454
534
|
<Text dimColor>Config: {opencodeInfo?.configPath || "N/A"}</Text>
|
|
455
535
|
</Box>
|
|
456
536
|
|
|
457
|
-
{/* Menu */}
|
|
458
|
-
<Box marginTop={1}>
|
|
459
|
-
<MenuBar
|
|
460
|
-
onSelect={handleAction}
|
|
461
|
-
selectMode={selectMode}
|
|
462
|
-
selectedCount={checkedEmails.size}
|
|
463
|
-
/>
|
|
464
|
-
</Box>
|
|
465
|
-
|
|
466
537
|
{/* Message */}
|
|
467
538
|
{message && (
|
|
468
539
|
<Box marginTop={1}>
|
|
469
540
|
<Text color="green">→ {message}</Text>
|
|
470
541
|
</Box>
|
|
471
542
|
)}
|
|
543
|
+
|
|
544
|
+
{/* Action Palette overlay */}
|
|
545
|
+
{activeModal === "palette" && (
|
|
546
|
+
<Box position="absolute" marginTop={3} marginLeft={10}>
|
|
547
|
+
<ActionPalette
|
|
548
|
+
actions={paletteActions}
|
|
549
|
+
onSelect={handlePaletteAction}
|
|
550
|
+
onClose={() => setActiveModal("none")}
|
|
551
|
+
/>
|
|
552
|
+
</Box>
|
|
553
|
+
)}
|
|
472
554
|
</Box>
|
|
473
555
|
);
|
|
474
556
|
}
|