codemaxxing 0.1.4 → 0.1.7
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 +3 -2
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +27 -0
- package/dist/index.js +92 -20
- package/package.json +3 -3
- package/src/auth-cli.ts +3 -2
- package/src/cli.ts +33 -0
- package/src/index.tsx +87 -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,6 +259,7 @@ Examples:
|
|
|
259
259
|
process.exit(1);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
+
// Always run main — this module is either imported and main() called, or run directly
|
|
262
263
|
main().catch((err) => {
|
|
263
264
|
console.error(`Error: ${err.message}`);
|
|
264
265
|
process.exit(1);
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
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 (spawn is fine here — no TUI/raw mode needed)
|
|
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
|
+
// TUI mode — import directly (not spawn) to preserve raw stdin
|
|
26
|
+
await import("./index.js");
|
|
27
|
+
}
|
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);
|
|
@@ -105,6 +106,8 @@ function App() {
|
|
|
105
106
|
const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
|
|
106
107
|
const [themePicker, setThemePicker] = useState(false);
|
|
107
108
|
const [themePickerIndex, setThemePickerIndex] = useState(0);
|
|
109
|
+
const [loginPicker, setLoginPicker] = useState(false);
|
|
110
|
+
const [loginPickerIndex, setLoginPickerIndex] = useState(0);
|
|
108
111
|
const [approval, setApproval] = useState(null);
|
|
109
112
|
// Listen for paste events from stdin interceptor
|
|
110
113
|
useEffect(() => {
|
|
@@ -277,25 +280,8 @@ function App() {
|
|
|
277
280
|
return;
|
|
278
281
|
}
|
|
279
282
|
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"));
|
|
283
|
+
setLoginPicker(true);
|
|
284
|
+
setLoginPickerIndex(0);
|
|
299
285
|
return;
|
|
300
286
|
}
|
|
301
287
|
if (trimmed === "/help") {
|
|
@@ -511,6 +497,92 @@ function App() {
|
|
|
511
497
|
return;
|
|
512
498
|
}
|
|
513
499
|
}
|
|
500
|
+
// Login picker navigation
|
|
501
|
+
if (loginPicker) {
|
|
502
|
+
const loginProviders = PROVIDERS.filter((p) => p.id !== "local");
|
|
503
|
+
if (key.upArrow) {
|
|
504
|
+
setLoginPickerIndex((prev) => (prev - 1 + loginProviders.length) % loginProviders.length);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (key.downArrow) {
|
|
508
|
+
setLoginPickerIndex((prev) => (prev + 1) % loginProviders.length);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
if (key.return) {
|
|
512
|
+
const selected = loginProviders[loginPickerIndex];
|
|
513
|
+
setLoginPicker(false);
|
|
514
|
+
if (selected.id === "openrouter") {
|
|
515
|
+
addMsg("info", "Starting OpenRouter OAuth — opening browser...");
|
|
516
|
+
setLoading(true);
|
|
517
|
+
setSpinnerMsg("Waiting for authorization...");
|
|
518
|
+
openRouterOAuth((msg) => addMsg("info", msg))
|
|
519
|
+
.then((cred) => {
|
|
520
|
+
addMsg("info", `✅ OpenRouter authenticated! You now have access to 200+ models.`);
|
|
521
|
+
addMsg("info", `Switch with: /model anthropic/claude-sonnet-4`);
|
|
522
|
+
setLoading(false);
|
|
523
|
+
})
|
|
524
|
+
.catch((err) => {
|
|
525
|
+
addMsg("error", `OAuth failed: ${err.message}`);
|
|
526
|
+
setLoading(false);
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
else if (selected.id === "anthropic") {
|
|
530
|
+
addMsg("info", "Starting Anthropic setup-token flow...");
|
|
531
|
+
setLoading(true);
|
|
532
|
+
setSpinnerMsg("Waiting for Claude Code auth...");
|
|
533
|
+
anthropicSetupToken((msg) => addMsg("info", msg))
|
|
534
|
+
.then((cred) => {
|
|
535
|
+
addMsg("info", `✅ Anthropic authenticated! (${cred.label})`);
|
|
536
|
+
setLoading(false);
|
|
537
|
+
})
|
|
538
|
+
.catch((err) => {
|
|
539
|
+
addMsg("error", `Anthropic auth failed: ${err.message}`);
|
|
540
|
+
setLoading(false);
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
else if (selected.id === "openai") {
|
|
544
|
+
const imported = importCodexToken((msg) => addMsg("info", msg));
|
|
545
|
+
if (imported) {
|
|
546
|
+
addMsg("info", `✅ Imported Codex credentials! (${imported.label})`);
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
addMsg("info", "No Codex CLI found. Run: codemaxxing auth api-key openai <your-key>");
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else if (selected.id === "qwen") {
|
|
553
|
+
const imported = importQwenToken((msg) => addMsg("info", msg));
|
|
554
|
+
if (imported) {
|
|
555
|
+
addMsg("info", `✅ Imported Qwen credentials! (${imported.label})`);
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
addMsg("info", "No Qwen CLI found. Run: codemaxxing auth api-key qwen <your-key>");
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
else if (selected.id === "copilot") {
|
|
562
|
+
addMsg("info", "Starting GitHub Copilot device flow...");
|
|
563
|
+
setLoading(true);
|
|
564
|
+
setSpinnerMsg("Waiting for GitHub authorization...");
|
|
565
|
+
copilotDeviceFlow((msg) => addMsg("info", msg))
|
|
566
|
+
.then(() => {
|
|
567
|
+
addMsg("info", `✅ GitHub Copilot authenticated!`);
|
|
568
|
+
setLoading(false);
|
|
569
|
+
})
|
|
570
|
+
.catch((err) => {
|
|
571
|
+
addMsg("error", `Copilot auth failed: ${err.message}`);
|
|
572
|
+
setLoading(false);
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
addMsg("info", `Run: codemaxxing auth api-key ${selected.id} <your-key>\n Get key at: ${selected.consoleUrl ?? selected.baseUrl}`);
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (key.escape) {
|
|
581
|
+
setLoginPicker(false);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
514
586
|
// Theme picker navigation
|
|
515
587
|
if (themePicker) {
|
|
516
588
|
const themeKeys = listThemes();
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemaxxing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
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": "
|
|
8
|
-
"codemaxxing-auth": "
|
|
7
|
+
"codemaxxing": "dist/cli.js",
|
|
8
|
+
"codemaxxing-auth": "dist/auth-cli.js"
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
|
11
11
|
"scripts": {
|
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,6 +280,7 @@ Examples:
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
// Always run main — this module is either imported and main() called, or run directly
|
|
283
284
|
main().catch((err) => {
|
|
284
285
|
console.error(`Error: ${err.message}`);
|
|
285
286
|
process.exit(1);
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
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 (spawn is fine here — no TUI/raw mode needed)
|
|
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
|
+
// TUI mode — import directly (not spawn) to preserve raw stdin
|
|
32
|
+
await import("./index.js");
|
|
33
|
+
}
|
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 {
|
|
@@ -134,6 +135,8 @@ function App() {
|
|
|
134
135
|
const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
|
|
135
136
|
const [themePicker, setThemePicker] = useState(false);
|
|
136
137
|
const [themePickerIndex, setThemePickerIndex] = useState(0);
|
|
138
|
+
const [loginPicker, setLoginPicker] = useState(false);
|
|
139
|
+
const [loginPickerIndex, setLoginPickerIndex] = useState(0);
|
|
137
140
|
const [approval, setApproval] = useState<{
|
|
138
141
|
tool: string;
|
|
139
142
|
args: Record<string, unknown>;
|
|
@@ -325,25 +328,8 @@ function App() {
|
|
|
325
328
|
return;
|
|
326
329
|
}
|
|
327
330
|
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"));
|
|
331
|
+
setLoginPicker(true);
|
|
332
|
+
setLoginPickerIndex(0);
|
|
347
333
|
return;
|
|
348
334
|
}
|
|
349
335
|
if (trimmed === "/help") {
|
|
@@ -557,6 +543,87 @@ function App() {
|
|
|
557
543
|
}
|
|
558
544
|
}
|
|
559
545
|
|
|
546
|
+
// Login picker navigation
|
|
547
|
+
if (loginPicker) {
|
|
548
|
+
const loginProviders = PROVIDERS.filter((p) => p.id !== "local");
|
|
549
|
+
if (key.upArrow) {
|
|
550
|
+
setLoginPickerIndex((prev: number) => (prev - 1 + loginProviders.length) % loginProviders.length);
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (key.downArrow) {
|
|
554
|
+
setLoginPickerIndex((prev: number) => (prev + 1) % loginProviders.length);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
if (key.return) {
|
|
558
|
+
const selected = loginProviders[loginPickerIndex];
|
|
559
|
+
setLoginPicker(false);
|
|
560
|
+
|
|
561
|
+
if (selected.id === "openrouter") {
|
|
562
|
+
addMsg("info", "Starting OpenRouter OAuth — opening browser...");
|
|
563
|
+
setLoading(true);
|
|
564
|
+
setSpinnerMsg("Waiting for authorization...");
|
|
565
|
+
openRouterOAuth((msg: string) => addMsg("info", msg))
|
|
566
|
+
.then((cred) => {
|
|
567
|
+
addMsg("info", `✅ OpenRouter authenticated! You now have access to 200+ models.`);
|
|
568
|
+
addMsg("info", `Switch with: /model anthropic/claude-sonnet-4`);
|
|
569
|
+
setLoading(false);
|
|
570
|
+
})
|
|
571
|
+
.catch((err: any) => {
|
|
572
|
+
addMsg("error", `OAuth failed: ${err.message}`);
|
|
573
|
+
setLoading(false);
|
|
574
|
+
});
|
|
575
|
+
} else if (selected.id === "anthropic") {
|
|
576
|
+
addMsg("info", "Starting Anthropic setup-token flow...");
|
|
577
|
+
setLoading(true);
|
|
578
|
+
setSpinnerMsg("Waiting for Claude Code auth...");
|
|
579
|
+
anthropicSetupToken((msg: string) => addMsg("info", msg))
|
|
580
|
+
.then((cred) => {
|
|
581
|
+
addMsg("info", `✅ Anthropic authenticated! (${cred.label})`);
|
|
582
|
+
setLoading(false);
|
|
583
|
+
})
|
|
584
|
+
.catch((err: any) => {
|
|
585
|
+
addMsg("error", `Anthropic auth failed: ${err.message}`);
|
|
586
|
+
setLoading(false);
|
|
587
|
+
});
|
|
588
|
+
} else if (selected.id === "openai") {
|
|
589
|
+
const imported = importCodexToken((msg: string) => addMsg("info", msg));
|
|
590
|
+
if (imported) {
|
|
591
|
+
addMsg("info", `✅ Imported Codex credentials! (${imported.label})`);
|
|
592
|
+
} else {
|
|
593
|
+
addMsg("info", "No Codex CLI found. Run: codemaxxing auth api-key openai <your-key>");
|
|
594
|
+
}
|
|
595
|
+
} else if (selected.id === "qwen") {
|
|
596
|
+
const imported = importQwenToken((msg: string) => addMsg("info", msg));
|
|
597
|
+
if (imported) {
|
|
598
|
+
addMsg("info", `✅ Imported Qwen credentials! (${imported.label})`);
|
|
599
|
+
} else {
|
|
600
|
+
addMsg("info", "No Qwen CLI found. Run: codemaxxing auth api-key qwen <your-key>");
|
|
601
|
+
}
|
|
602
|
+
} else if (selected.id === "copilot") {
|
|
603
|
+
addMsg("info", "Starting GitHub Copilot device flow...");
|
|
604
|
+
setLoading(true);
|
|
605
|
+
setSpinnerMsg("Waiting for GitHub authorization...");
|
|
606
|
+
copilotDeviceFlow((msg: string) => addMsg("info", msg))
|
|
607
|
+
.then(() => {
|
|
608
|
+
addMsg("info", `✅ GitHub Copilot authenticated!`);
|
|
609
|
+
setLoading(false);
|
|
610
|
+
})
|
|
611
|
+
.catch((err: any) => {
|
|
612
|
+
addMsg("error", `Copilot auth failed: ${err.message}`);
|
|
613
|
+
setLoading(false);
|
|
614
|
+
});
|
|
615
|
+
} else {
|
|
616
|
+
addMsg("info", `Run: codemaxxing auth api-key ${selected.id} <your-key>\n Get key at: ${selected.consoleUrl ?? selected.baseUrl}`);
|
|
617
|
+
}
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (key.escape) {
|
|
621
|
+
setLoginPicker(false);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
560
627
|
// Theme picker navigation
|
|
561
628
|
if (themePicker) {
|
|
562
629
|
const themeKeys = listThemes();
|