codemaxxing 0.1.4 → 0.1.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/dist/auth-cli.d.ts +1 -1
- package/dist/auth-cli.js +9 -6
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +32 -0
- package/dist/index.js +93 -20
- package/package.json +2 -2
- package/src/auth-cli.ts +9 -6
- package/src/cli.ts +39 -0
- package/src/index.tsx +88 -20
package/dist/auth-cli.d.ts
CHANGED
package/dist/auth-cli.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* codemaxxing auth api-key <name> <key> — Save API key directly
|
|
15
15
|
*/
|
|
16
16
|
import { PROVIDERS, getCredentials, removeCredential, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow, saveApiKey, detectAvailableAuth, } from "./utils/auth.js";
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
export async function main() {
|
|
18
|
+
const command = process.argv[2] ?? "login";
|
|
19
19
|
switch (command) {
|
|
20
20
|
case "login": {
|
|
21
21
|
console.log("\n💪 Codemaxxing Authentication\n");
|
|
@@ -259,7 +259,10 @@ Examples:
|
|
|
259
259
|
process.exit(1);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
-
main
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
});
|
|
262
|
+
// Run main if this is the main module
|
|
263
|
+
if (typeof require !== "undefined" && require.main === module) {
|
|
264
|
+
main().catch((err) => {
|
|
265
|
+
console.error(`Error: ${err.message}`);
|
|
266
|
+
process.exit(1);
|
|
267
|
+
});
|
|
268
|
+
}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Codemaxxing CLI entry point
|
|
4
|
+
* Routes subcommands (login, auth) to auth-cli, everything else to the TUI
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
const subcmd = process.argv[2];
|
|
12
|
+
if (subcmd === "login" || subcmd === "auth") {
|
|
13
|
+
// Route to auth CLI
|
|
14
|
+
const authScript = join(__dirname, "auth-cli.js");
|
|
15
|
+
const args = subcmd === "login"
|
|
16
|
+
? [authScript, "login", ...process.argv.slice(3)]
|
|
17
|
+
: [authScript, ...process.argv.slice(3)];
|
|
18
|
+
const child = spawn(process.execPath, args, {
|
|
19
|
+
stdio: "inherit",
|
|
20
|
+
cwd: process.cwd(),
|
|
21
|
+
});
|
|
22
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Route to TUI
|
|
26
|
+
const tuiScript = join(__dirname, "index.js");
|
|
27
|
+
const child = spawn(process.execPath, [tuiScript, ...process.argv.slice(2)], {
|
|
28
|
+
stdio: "inherit",
|
|
29
|
+
cwd: process.cwd(),
|
|
30
|
+
});
|
|
31
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
32
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,8 @@ import { listSessions, getSession, loadMessages } from "./utils/sessions.js";
|
|
|
10
10
|
import { execSync } from "child_process";
|
|
11
11
|
import { isGitRepo, getBranch, getStatus, getDiff, undoLastCommit } from "./utils/git.js";
|
|
12
12
|
import { getTheme, listThemes, THEMES, DEFAULT_THEME } from "./themes.js";
|
|
13
|
-
|
|
13
|
+
import { PROVIDERS, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow } from "./utils/auth.js";
|
|
14
|
+
const VERSION = "0.1.5";
|
|
14
15
|
// ── Helpers ──
|
|
15
16
|
function formatTimeAgo(date) {
|
|
16
17
|
const secs = Math.floor((Date.now() - date.getTime()) / 1000);
|
|
@@ -29,6 +30,7 @@ function formatTimeAgo(date) {
|
|
|
29
30
|
const SLASH_COMMANDS = [
|
|
30
31
|
{ cmd: "/help", desc: "show commands" },
|
|
31
32
|
{ cmd: "/login", desc: "set up authentication" },
|
|
33
|
+
{ cmd: "/login", desc: "set up authentication" },
|
|
32
34
|
{ cmd: "/map", desc: "show repository map" },
|
|
33
35
|
{ cmd: "/reset", desc: "clear conversation" },
|
|
34
36
|
{ cmd: "/context", desc: "show message count" },
|
|
@@ -105,6 +107,8 @@ function App() {
|
|
|
105
107
|
const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
|
|
106
108
|
const [themePicker, setThemePicker] = useState(false);
|
|
107
109
|
const [themePickerIndex, setThemePickerIndex] = useState(0);
|
|
110
|
+
const [loginPicker, setLoginPicker] = useState(false);
|
|
111
|
+
const [loginPickerIndex, setLoginPickerIndex] = useState(0);
|
|
108
112
|
const [approval, setApproval] = useState(null);
|
|
109
113
|
// Listen for paste events from stdin interceptor
|
|
110
114
|
useEffect(() => {
|
|
@@ -277,25 +281,8 @@ function App() {
|
|
|
277
281
|
return;
|
|
278
282
|
}
|
|
279
283
|
if (trimmed === "/login" || trimmed === "/auth") {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
"",
|
|
283
|
-
"Run 'codemaxxing login' in a new terminal to set up:",
|
|
284
|
-
" • OpenRouter OAuth (browser login, 200+ models)",
|
|
285
|
-
" • Anthropic via Claude Code (your Pro/Max subscription)",
|
|
286
|
-
" • ChatGPT via Codex CLI (your Plus/Pro subscription)",
|
|
287
|
-
" • Qwen CLI (your Qwen access)",
|
|
288
|
-
" • GitHub Copilot (device flow)",
|
|
289
|
-
" • Manual API keys for any provider",
|
|
290
|
-
"",
|
|
291
|
-
"Commands:",
|
|
292
|
-
" codemaxxing login — interactive setup",
|
|
293
|
-
" codemaxxing auth list — see saved credentials",
|
|
294
|
-
" codemaxxing auth openrouter — OpenRouter OAuth",
|
|
295
|
-
" codemaxxing auth anthropic — Anthropic subscription",
|
|
296
|
-
" codemaxxing auth openai — ChatGPT subscription",
|
|
297
|
-
" codemaxxing auth copilot — GitHub Copilot",
|
|
298
|
-
].join("\n"));
|
|
284
|
+
setLoginPicker(true);
|
|
285
|
+
setLoginPickerIndex(0);
|
|
299
286
|
return;
|
|
300
287
|
}
|
|
301
288
|
if (trimmed === "/help") {
|
|
@@ -511,6 +498,92 @@ function App() {
|
|
|
511
498
|
return;
|
|
512
499
|
}
|
|
513
500
|
}
|
|
501
|
+
// Login picker navigation
|
|
502
|
+
if (loginPicker) {
|
|
503
|
+
const loginProviders = PROVIDERS.filter((p) => p.id !== "local");
|
|
504
|
+
if (key.upArrow) {
|
|
505
|
+
setLoginPickerIndex((prev) => (prev - 1 + loginProviders.length) % loginProviders.length);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (key.downArrow) {
|
|
509
|
+
setLoginPickerIndex((prev) => (prev + 1) % loginProviders.length);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (key.return) {
|
|
513
|
+
const selected = loginProviders[loginPickerIndex];
|
|
514
|
+
setLoginPicker(false);
|
|
515
|
+
if (selected.id === "openrouter") {
|
|
516
|
+
addMsg("info", "Starting OpenRouter OAuth — opening browser...");
|
|
517
|
+
setLoading(true);
|
|
518
|
+
setSpinnerMsg("Waiting for authorization...");
|
|
519
|
+
openRouterOAuth((msg) => addMsg("info", msg))
|
|
520
|
+
.then((cred) => {
|
|
521
|
+
addMsg("info", `✅ OpenRouter authenticated! You now have access to 200+ models.`);
|
|
522
|
+
addMsg("info", `Switch with: /model anthropic/claude-sonnet-4`);
|
|
523
|
+
setLoading(false);
|
|
524
|
+
})
|
|
525
|
+
.catch((err) => {
|
|
526
|
+
addMsg("error", `OAuth failed: ${err.message}`);
|
|
527
|
+
setLoading(false);
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
else if (selected.id === "anthropic") {
|
|
531
|
+
addMsg("info", "Starting Anthropic setup-token flow...");
|
|
532
|
+
setLoading(true);
|
|
533
|
+
setSpinnerMsg("Waiting for Claude Code auth...");
|
|
534
|
+
anthropicSetupToken((msg) => addMsg("info", msg))
|
|
535
|
+
.then((cred) => {
|
|
536
|
+
addMsg("info", `✅ Anthropic authenticated! (${cred.label})`);
|
|
537
|
+
setLoading(false);
|
|
538
|
+
})
|
|
539
|
+
.catch((err) => {
|
|
540
|
+
addMsg("error", `Anthropic auth failed: ${err.message}`);
|
|
541
|
+
setLoading(false);
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
else if (selected.id === "openai") {
|
|
545
|
+
const imported = importCodexToken((msg) => addMsg("info", msg));
|
|
546
|
+
if (imported) {
|
|
547
|
+
addMsg("info", `✅ Imported Codex credentials! (${imported.label})`);
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
addMsg("info", "No Codex CLI found. Run: codemaxxing auth api-key openai <your-key>");
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
else if (selected.id === "qwen") {
|
|
554
|
+
const imported = importQwenToken((msg) => addMsg("info", msg));
|
|
555
|
+
if (imported) {
|
|
556
|
+
addMsg("info", `✅ Imported Qwen credentials! (${imported.label})`);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
addMsg("info", "No Qwen CLI found. Run: codemaxxing auth api-key qwen <your-key>");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else if (selected.id === "copilot") {
|
|
563
|
+
addMsg("info", "Starting GitHub Copilot device flow...");
|
|
564
|
+
setLoading(true);
|
|
565
|
+
setSpinnerMsg("Waiting for GitHub authorization...");
|
|
566
|
+
copilotDeviceFlow((msg) => addMsg("info", msg))
|
|
567
|
+
.then(() => {
|
|
568
|
+
addMsg("info", `✅ GitHub Copilot authenticated!`);
|
|
569
|
+
setLoading(false);
|
|
570
|
+
})
|
|
571
|
+
.catch((err) => {
|
|
572
|
+
addMsg("error", `Copilot auth failed: ${err.message}`);
|
|
573
|
+
setLoading(false);
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
addMsg("info", `Run: codemaxxing auth api-key ${selected.id} <your-key>\n Get key at: ${selected.consoleUrl ?? selected.baseUrl}`);
|
|
578
|
+
}
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (key.escape) {
|
|
582
|
+
setLoginPicker(false);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
514
587
|
// Theme picker navigation
|
|
515
588
|
if (themePicker) {
|
|
516
589
|
const themeKeys = listThemes();
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemaxxing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Open-source terminal coding agent. Connect any LLM. Max your code.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"codemaxxing": "./dist/
|
|
7
|
+
"codemaxxing": "./dist/cli.js",
|
|
8
8
|
"codemaxxing-auth": "./dist/auth-cli.js"
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
package/src/auth-cli.ts
CHANGED
|
@@ -28,9 +28,9 @@ import {
|
|
|
28
28
|
detectAvailableAuth,
|
|
29
29
|
} from "./utils/auth.js";
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
export async function main() {
|
|
32
|
+
const command = process.argv[2] ?? "login";
|
|
32
33
|
|
|
33
|
-
async function main() {
|
|
34
34
|
switch (command) {
|
|
35
35
|
case "login": {
|
|
36
36
|
console.log("\n💪 Codemaxxing Authentication\n");
|
|
@@ -280,7 +280,10 @@ Examples:
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
main
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
});
|
|
283
|
+
// Run main if this is the main module
|
|
284
|
+
if (typeof require !== "undefined" && require.main === module) {
|
|
285
|
+
main().catch((err) => {
|
|
286
|
+
console.error(`Error: ${err.message}`);
|
|
287
|
+
process.exit(1);
|
|
288
|
+
});
|
|
289
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Codemaxxing CLI entry point
|
|
5
|
+
* Routes subcommands (login, auth) to auth-cli, everything else to the TUI
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { spawn } from "node:child_process";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
|
|
15
|
+
const subcmd = process.argv[2];
|
|
16
|
+
|
|
17
|
+
if (subcmd === "login" || subcmd === "auth") {
|
|
18
|
+
// Route to auth CLI
|
|
19
|
+
const authScript = join(__dirname, "auth-cli.js");
|
|
20
|
+
const args = subcmd === "login"
|
|
21
|
+
? [authScript, "login", ...process.argv.slice(3)]
|
|
22
|
+
: [authScript, ...process.argv.slice(3)];
|
|
23
|
+
|
|
24
|
+
const child = spawn(process.execPath, args, {
|
|
25
|
+
stdio: "inherit",
|
|
26
|
+
cwd: process.cwd(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
30
|
+
} else {
|
|
31
|
+
// Route to TUI
|
|
32
|
+
const tuiScript = join(__dirname, "index.js");
|
|
33
|
+
const child = spawn(process.execPath, [tuiScript, ...process.argv.slice(2)], {
|
|
34
|
+
stdio: "inherit",
|
|
35
|
+
cwd: process.cwd(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
39
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -10,8 +10,9 @@ import { listSessions, getSession, loadMessages } from "./utils/sessions.js";
|
|
|
10
10
|
import { execSync } from "child_process";
|
|
11
11
|
import { isGitRepo, getBranch, getStatus, getDiff, undoLastCommit } from "./utils/git.js";
|
|
12
12
|
import { getTheme, listThemes, THEMES, DEFAULT_THEME, type Theme } from "./themes.js";
|
|
13
|
+
import { PROVIDERS, getCredentials, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow, saveApiKey } from "./utils/auth.js";
|
|
13
14
|
|
|
14
|
-
const VERSION = "0.1.
|
|
15
|
+
const VERSION = "0.1.5";
|
|
15
16
|
|
|
16
17
|
// ── Helpers ──
|
|
17
18
|
function formatTimeAgo(date: Date): string {
|
|
@@ -29,6 +30,7 @@ function formatTimeAgo(date: Date): string {
|
|
|
29
30
|
const SLASH_COMMANDS = [
|
|
30
31
|
{ cmd: "/help", desc: "show commands" },
|
|
31
32
|
{ cmd: "/login", desc: "set up authentication" },
|
|
33
|
+
{ cmd: "/login", desc: "set up authentication" },
|
|
32
34
|
{ cmd: "/map", desc: "show repository map" },
|
|
33
35
|
{ cmd: "/reset", desc: "clear conversation" },
|
|
34
36
|
{ cmd: "/context", desc: "show message count" },
|
|
@@ -134,6 +136,8 @@ function App() {
|
|
|
134
136
|
const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
|
|
135
137
|
const [themePicker, setThemePicker] = useState(false);
|
|
136
138
|
const [themePickerIndex, setThemePickerIndex] = useState(0);
|
|
139
|
+
const [loginPicker, setLoginPicker] = useState(false);
|
|
140
|
+
const [loginPickerIndex, setLoginPickerIndex] = useState(0);
|
|
137
141
|
const [approval, setApproval] = useState<{
|
|
138
142
|
tool: string;
|
|
139
143
|
args: Record<string, unknown>;
|
|
@@ -325,25 +329,8 @@ function App() {
|
|
|
325
329
|
return;
|
|
326
330
|
}
|
|
327
331
|
if (trimmed === "/login" || trimmed === "/auth") {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
"",
|
|
331
|
-
"Run 'codemaxxing login' in a new terminal to set up:",
|
|
332
|
-
" • OpenRouter OAuth (browser login, 200+ models)",
|
|
333
|
-
" • Anthropic via Claude Code (your Pro/Max subscription)",
|
|
334
|
-
" • ChatGPT via Codex CLI (your Plus/Pro subscription)",
|
|
335
|
-
" • Qwen CLI (your Qwen access)",
|
|
336
|
-
" • GitHub Copilot (device flow)",
|
|
337
|
-
" • Manual API keys for any provider",
|
|
338
|
-
"",
|
|
339
|
-
"Commands:",
|
|
340
|
-
" codemaxxing login — interactive setup",
|
|
341
|
-
" codemaxxing auth list — see saved credentials",
|
|
342
|
-
" codemaxxing auth openrouter — OpenRouter OAuth",
|
|
343
|
-
" codemaxxing auth anthropic — Anthropic subscription",
|
|
344
|
-
" codemaxxing auth openai — ChatGPT subscription",
|
|
345
|
-
" codemaxxing auth copilot — GitHub Copilot",
|
|
346
|
-
].join("\n"));
|
|
332
|
+
setLoginPicker(true);
|
|
333
|
+
setLoginPickerIndex(0);
|
|
347
334
|
return;
|
|
348
335
|
}
|
|
349
336
|
if (trimmed === "/help") {
|
|
@@ -557,6 +544,87 @@ function App() {
|
|
|
557
544
|
}
|
|
558
545
|
}
|
|
559
546
|
|
|
547
|
+
// Login picker navigation
|
|
548
|
+
if (loginPicker) {
|
|
549
|
+
const loginProviders = PROVIDERS.filter((p) => p.id !== "local");
|
|
550
|
+
if (key.upArrow) {
|
|
551
|
+
setLoginPickerIndex((prev: number) => (prev - 1 + loginProviders.length) % loginProviders.length);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
if (key.downArrow) {
|
|
555
|
+
setLoginPickerIndex((prev: number) => (prev + 1) % loginProviders.length);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (key.return) {
|
|
559
|
+
const selected = loginProviders[loginPickerIndex];
|
|
560
|
+
setLoginPicker(false);
|
|
561
|
+
|
|
562
|
+
if (selected.id === "openrouter") {
|
|
563
|
+
addMsg("info", "Starting OpenRouter OAuth — opening browser...");
|
|
564
|
+
setLoading(true);
|
|
565
|
+
setSpinnerMsg("Waiting for authorization...");
|
|
566
|
+
openRouterOAuth((msg: string) => addMsg("info", msg))
|
|
567
|
+
.then((cred) => {
|
|
568
|
+
addMsg("info", `✅ OpenRouter authenticated! You now have access to 200+ models.`);
|
|
569
|
+
addMsg("info", `Switch with: /model anthropic/claude-sonnet-4`);
|
|
570
|
+
setLoading(false);
|
|
571
|
+
})
|
|
572
|
+
.catch((err: any) => {
|
|
573
|
+
addMsg("error", `OAuth failed: ${err.message}`);
|
|
574
|
+
setLoading(false);
|
|
575
|
+
});
|
|
576
|
+
} else if (selected.id === "anthropic") {
|
|
577
|
+
addMsg("info", "Starting Anthropic setup-token flow...");
|
|
578
|
+
setLoading(true);
|
|
579
|
+
setSpinnerMsg("Waiting for Claude Code auth...");
|
|
580
|
+
anthropicSetupToken((msg: string) => addMsg("info", msg))
|
|
581
|
+
.then((cred) => {
|
|
582
|
+
addMsg("info", `✅ Anthropic authenticated! (${cred.label})`);
|
|
583
|
+
setLoading(false);
|
|
584
|
+
})
|
|
585
|
+
.catch((err: any) => {
|
|
586
|
+
addMsg("error", `Anthropic auth failed: ${err.message}`);
|
|
587
|
+
setLoading(false);
|
|
588
|
+
});
|
|
589
|
+
} else if (selected.id === "openai") {
|
|
590
|
+
const imported = importCodexToken((msg: string) => addMsg("info", msg));
|
|
591
|
+
if (imported) {
|
|
592
|
+
addMsg("info", `✅ Imported Codex credentials! (${imported.label})`);
|
|
593
|
+
} else {
|
|
594
|
+
addMsg("info", "No Codex CLI found. Run: codemaxxing auth api-key openai <your-key>");
|
|
595
|
+
}
|
|
596
|
+
} else if (selected.id === "qwen") {
|
|
597
|
+
const imported = importQwenToken((msg: string) => addMsg("info", msg));
|
|
598
|
+
if (imported) {
|
|
599
|
+
addMsg("info", `✅ Imported Qwen credentials! (${imported.label})`);
|
|
600
|
+
} else {
|
|
601
|
+
addMsg("info", "No Qwen CLI found. Run: codemaxxing auth api-key qwen <your-key>");
|
|
602
|
+
}
|
|
603
|
+
} else if (selected.id === "copilot") {
|
|
604
|
+
addMsg("info", "Starting GitHub Copilot device flow...");
|
|
605
|
+
setLoading(true);
|
|
606
|
+
setSpinnerMsg("Waiting for GitHub authorization...");
|
|
607
|
+
copilotDeviceFlow((msg: string) => addMsg("info", msg))
|
|
608
|
+
.then(() => {
|
|
609
|
+
addMsg("info", `✅ GitHub Copilot authenticated!`);
|
|
610
|
+
setLoading(false);
|
|
611
|
+
})
|
|
612
|
+
.catch((err: any) => {
|
|
613
|
+
addMsg("error", `Copilot auth failed: ${err.message}`);
|
|
614
|
+
setLoading(false);
|
|
615
|
+
});
|
|
616
|
+
} else {
|
|
617
|
+
addMsg("info", `Run: codemaxxing auth api-key ${selected.id} <your-key>\n Get key at: ${selected.consoleUrl ?? selected.baseUrl}`);
|
|
618
|
+
}
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (key.escape) {
|
|
622
|
+
setLoginPicker(false);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
|
|
560
628
|
// Theme picker navigation
|
|
561
629
|
if (themePicker) {
|
|
562
630
|
const themeKeys = listThemes();
|