codemaxxing 0.1.3 → 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.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * codemaxxing auth CLI
4
+ *
5
+ * Commands:
6
+ * codemaxxing login — Interactive auth setup
7
+ * codemaxxing auth list — List saved credentials
8
+ * codemaxxing auth remove <name> — Remove a credential
9
+ * codemaxxing auth openrouter — Start OpenRouter OAuth
10
+ * codemaxxing auth anthropic — Get Anthropic via Claude Code
11
+ * codemaxxing auth openai — Import Codex CLI credentials
12
+ * codemaxxing auth qwen — Import Qwen CLI credentials
13
+ * codemaxxing auth copilot — GitHub Copilot device flow
14
+ * codemaxxing auth api-key <name> <key> — Save API key directly
15
+ */
16
+ export declare function main(): Promise<void>;
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * codemaxxing auth CLI
4
+ *
5
+ * Commands:
6
+ * codemaxxing login — Interactive auth setup
7
+ * codemaxxing auth list — List saved credentials
8
+ * codemaxxing auth remove <name> — Remove a credential
9
+ * codemaxxing auth openrouter — Start OpenRouter OAuth
10
+ * codemaxxing auth anthropic — Get Anthropic via Claude Code
11
+ * codemaxxing auth openai — Import Codex CLI credentials
12
+ * codemaxxing auth qwen — Import Qwen CLI credentials
13
+ * codemaxxing auth copilot — GitHub Copilot device flow
14
+ * codemaxxing auth api-key <name> <key> — Save API key directly
15
+ */
16
+ import { PROVIDERS, getCredentials, removeCredential, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow, saveApiKey, detectAvailableAuth, } from "./utils/auth.js";
17
+ export async function main() {
18
+ const command = process.argv[2] ?? "login";
19
+ switch (command) {
20
+ case "login": {
21
+ console.log("\n💪 Codemaxxing Authentication\n");
22
+ console.log("Available providers:\n");
23
+ PROVIDERS.forEach((p, i) => {
24
+ const methods = p.methods.filter((m) => m !== "none").join(", ");
25
+ console.log(` ${i + 1}. ${p.name}`);
26
+ console.log(` ${p.description}`);
27
+ console.log(` Methods: ${methods}\n`);
28
+ });
29
+ console.log("Detected on this machine:");
30
+ const detected = detectAvailableAuth();
31
+ if (detected.length === 0) {
32
+ console.log(" — No existing CLI credentials found\n");
33
+ }
34
+ else {
35
+ detected.forEach((d) => {
36
+ console.log(` ⚡ ${d.provider} — ${d.description}`);
37
+ });
38
+ console.log("");
39
+ }
40
+ const readline = await import("readline");
41
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
42
+ const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
43
+ const choice = await ask("Select a provider (1-" + PROVIDERS.length + ") or name: ");
44
+ const providerId = PROVIDERS[parseInt(choice) - 1]?.id ?? choice.toLowerCase();
45
+ const provider = PROVIDERS.find((p) => p.id === providerId);
46
+ if (!provider) {
47
+ console.log(`Unknown provider: ${providerId}`);
48
+ process.exit(1);
49
+ }
50
+ console.log(`\nSetting up ${provider.name}...\n`);
51
+ try {
52
+ if (providerId === "openrouter") {
53
+ const cred = await openRouterOAuth((msg) => console.log(` ${msg}`));
54
+ console.log(`\n✅ OpenRouter authenticated! (${cred.label})`);
55
+ }
56
+ else if (providerId === "anthropic") {
57
+ if (provider.methods.includes("setup-token")) {
58
+ const cred = await anthropicSetupToken((msg) => console.log(` ${msg}`));
59
+ console.log(`\n✅ Anthropic authenticated! (${cred.label})`);
60
+ }
61
+ else {
62
+ const apiKey = await ask("Enter your Anthropic API key: ");
63
+ const cred = saveApiKey(providerId, apiKey);
64
+ console.log(`\n✅ Saved API key for ${provider.name}`);
65
+ }
66
+ }
67
+ else if (providerId === "openai") {
68
+ const imported = importCodexToken((msg) => console.log(` ${msg}`));
69
+ if (imported) {
70
+ console.log(`\n✅ Imported Codex credentials! (${imported.label})`);
71
+ }
72
+ else {
73
+ const apiKey = await ask("Enter your OpenAI API key: ");
74
+ const cred = saveApiKey(providerId, apiKey);
75
+ console.log(`\n✅ Saved API key for ${provider.name}`);
76
+ }
77
+ }
78
+ else if (providerId === "qwen") {
79
+ const imported = importQwenToken((msg) => console.log(` ${msg}`));
80
+ if (imported) {
81
+ console.log(`\n✅ Imported Qwen credentials! (${imported.label})`);
82
+ }
83
+ else {
84
+ const apiKey = await ask("Enter your Qwen/DashScope API key: ");
85
+ const cred = saveApiKey(providerId, apiKey);
86
+ console.log(`\n✅ Saved API key for ${provider.name}`);
87
+ }
88
+ }
89
+ else if (providerId === "copilot") {
90
+ const cred = await copilotDeviceFlow((msg) => console.log(` ${msg}`));
91
+ console.log(`\n✅ GitHub Copilot authenticated!`);
92
+ }
93
+ else if (providerId === "custom") {
94
+ const baseUrl = await ask("Enter the base URL: ");
95
+ const apiKey = await ask("Enter your API key: ");
96
+ const cred = saveApiKey(providerId, apiKey, baseUrl, "Custom provider");
97
+ console.log(`\n✅ Saved custom provider`);
98
+ }
99
+ else {
100
+ const apiKey = await ask(`Enter your ${provider.name} API key (${provider.consoleUrl}): `);
101
+ const cred = saveApiKey(providerId, apiKey);
102
+ console.log(`\n✅ Saved API key for ${provider.name}`);
103
+ }
104
+ console.log("\nRun 'codemaxxing' to start coding!");
105
+ }
106
+ catch (err) {
107
+ console.error(`\n❌ Error: ${err.message}`);
108
+ process.exit(1);
109
+ }
110
+ finally {
111
+ rl.close();
112
+ }
113
+ break;
114
+ }
115
+ case "list":
116
+ case "ls": {
117
+ const creds = getCredentials();
118
+ console.log("\n💪 Saved Credentials\n");
119
+ if (creds.length === 0) {
120
+ console.log(" No credentials saved.\n");
121
+ console.log(" Run 'codemaxxing login' to set up authentication.\n");
122
+ break;
123
+ }
124
+ creds.forEach((c) => {
125
+ console.log(` ${c.provider}`);
126
+ console.log(` Method: ${c.method}`);
127
+ console.log(` Label: ${c.label ?? "—"}`);
128
+ const maskedKey = c.apiKey.length > 12
129
+ ? c.apiKey.slice(0, 4) + "•".repeat(8) + c.apiKey.slice(-4)
130
+ : "••••••••";
131
+ console.log(` Key: ${maskedKey}`);
132
+ console.log(` Base: ${c.baseUrl}`);
133
+ console.log("");
134
+ });
135
+ break;
136
+ }
137
+ case "remove":
138
+ case "rm":
139
+ case "delete": {
140
+ const target = process.argv[3];
141
+ if (!target) {
142
+ console.log("Usage: codemaxxing auth remove <provider-name>");
143
+ console.log("\nSaved providers:");
144
+ getCredentials().forEach((c) => console.log(` ${c.provider}`));
145
+ process.exit(1);
146
+ }
147
+ const removed = removeCredential(target);
148
+ if (removed) {
149
+ console.log(`✅ Removed ${target}`);
150
+ }
151
+ else {
152
+ console.log(`❌ No credential found for: ${target}`);
153
+ console.log("\nSaved providers:");
154
+ getCredentials().forEach((c) => console.log(` ${c.provider}`));
155
+ process.exit(1);
156
+ }
157
+ break;
158
+ }
159
+ case "openrouter": {
160
+ console.log("Starting OpenRouter OAuth flow...\n");
161
+ try {
162
+ const cred = await openRouterOAuth((msg) => console.log(` ${msg}`));
163
+ console.log(`\n✅ OpenRouter authenticated!`);
164
+ }
165
+ catch (err) {
166
+ console.error(`\n❌ ${err.message}`);
167
+ process.exit(1);
168
+ }
169
+ break;
170
+ }
171
+ case "anthropic": {
172
+ console.log("Starting Anthropic setup-token flow...\n");
173
+ try {
174
+ const cred = await anthropicSetupToken((msg) => console.log(` ${msg}`));
175
+ console.log(`\n✅ Anthropic authenticated!`);
176
+ }
177
+ catch (err) {
178
+ console.error(`\n❌ ${err.message}`);
179
+ process.exit(1);
180
+ }
181
+ break;
182
+ }
183
+ case "openai": {
184
+ console.log("Checking for Codex CLI credentials...\n");
185
+ const imported = importCodexToken((msg) => console.log(` ${msg}`));
186
+ if (imported) {
187
+ console.log(`\n✅ Imported Codex credentials!`);
188
+ }
189
+ else {
190
+ console.log("\n❌ No Codex CLI credentials found.");
191
+ console.log("Make sure Codex CLI is installed and you've logged in.");
192
+ }
193
+ break;
194
+ }
195
+ case "qwen": {
196
+ console.log("Checking for Qwen CLI credentials...\n");
197
+ const imported = importQwenToken((msg) => console.log(` ${msg}`));
198
+ if (imported) {
199
+ console.log(`\n✅ Imported Qwen credentials!`);
200
+ }
201
+ else {
202
+ console.log("\n❌ No Qwen CLI credentials found.");
203
+ console.log("Make sure Qwen CLI is installed and you've logged in.");
204
+ }
205
+ break;
206
+ }
207
+ case "copilot": {
208
+ console.log("Starting GitHub Copilot device flow...\n");
209
+ try {
210
+ const cred = await copilotDeviceFlow((msg) => console.log(` ${msg}`));
211
+ console.log(`\n✅ GitHub Copilot authenticated!`);
212
+ }
213
+ catch (err) {
214
+ console.error(`\n❌ ${err.message}`);
215
+ process.exit(1);
216
+ }
217
+ break;
218
+ }
219
+ case "api-key": {
220
+ const providerId = process.argv[3];
221
+ const apiKey = process.argv[4];
222
+ if (!providerId || !apiKey) {
223
+ console.log("Usage: codemaxxing auth api-key <provider-id> <api-key>");
224
+ process.exit(1);
225
+ }
226
+ const cred = saveApiKey(providerId, apiKey);
227
+ console.log(`\n✅ Saved API key for ${cred.provider}`);
228
+ break;
229
+ }
230
+ case "help":
231
+ case "--help":
232
+ case "-h": {
233
+ console.log(`
234
+ 💪 Codemaxxing Auth
235
+
236
+ Commands:
237
+ codemaxxing login Interactive authentication setup
238
+ codemaxxing auth list List saved credentials
239
+ codemaxxing auth remove <name> Remove a credential
240
+ codemaxxing auth openrouter Start OpenRouter OAuth flow
241
+ codemaxxing auth anthropic Get Anthropic via Claude Code CLI
242
+ codemaxxing auth openai Import Codex CLI credentials
243
+ codemaxxing auth qwen Import Qwen CLI credentials
244
+ codemaxxing auth copilot GitHub Copilot device flow
245
+ codemaxxing auth api-key <id> <key> Save API key directly
246
+ codemaxxing auth help Show this help
247
+
248
+ Examples:
249
+ codemaxxing login # Interactive provider picker
250
+ codemaxxing auth openrouter # One browser login, access to 200+ models
251
+ codemaxxing auth anthropic # Use your Claude subscription via Claude Code
252
+ codemaxxing auth list # See what's saved
253
+ `);
254
+ break;
255
+ }
256
+ default:
257
+ console.log(`Unknown command: ${command}`);
258
+ console.log("Run 'codemaxxing auth help' for available commands.");
259
+ process.exit(1);
260
+ }
261
+ }
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
@@ -0,0 +1,6 @@
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
+ export {};
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/config.d.ts CHANGED
@@ -39,3 +39,12 @@ export declare function detectLocalProvider(): Promise<ProviderConfig | null>;
39
39
  * List available models from a provider endpoint
40
40
  */
41
41
  export declare function listModels(baseUrl: string, apiKey: string): Promise<string[]>;
42
+ /**
43
+ * Resolve provider configuration from auth store or config file
44
+ * Priority: CLI args > auth store > config file > auto-detect
45
+ */
46
+ export declare function resolveProvider(providerId: string, cliArgs: CLIArgs): {
47
+ baseUrl: string;
48
+ apiKey: string;
49
+ model: string;
50
+ } | null;
package/dist/config.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { readFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
2
2
  import { homedir } from "os";
3
3
  import { join } from "path";
4
+ import { getCredential } from "./utils/auth.js";
4
5
  const CONFIG_DIR = join(homedir(), ".codemaxxing");
5
6
  const CONFIG_FILE = join(CONFIG_DIR, "settings.json");
6
7
  const DEFAULT_CONFIG = {
@@ -172,3 +173,29 @@ export async function listModels(baseUrl, apiKey) {
172
173
  catch { /* ignore */ }
173
174
  return [];
174
175
  }
176
+ /**
177
+ * Resolve provider configuration from auth store or config file
178
+ * Priority: CLI args > auth store > config file > auto-detect
179
+ */
180
+ export function resolveProvider(providerId, cliArgs) {
181
+ // Check auth store first
182
+ const authCred = getCredential(providerId);
183
+ if (authCred) {
184
+ return {
185
+ baseUrl: authCred.baseUrl,
186
+ apiKey: authCred.apiKey,
187
+ model: cliArgs.model || "auto",
188
+ };
189
+ }
190
+ // Fall back to config file
191
+ const config = loadConfig();
192
+ const provider = config.providers?.[providerId];
193
+ if (provider) {
194
+ return {
195
+ baseUrl: provider.baseUrl,
196
+ apiKey: cliArgs.apiKey || provider.apiKey,
197
+ model: cliArgs.model || provider.model,
198
+ };
199
+ }
200
+ return null;
201
+ }
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
- const VERSION = "0.1.0";
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);
@@ -28,6 +29,8 @@ function formatTimeAgo(date) {
28
29
  // ── Slash Commands ──
29
30
  const SLASH_COMMANDS = [
30
31
  { cmd: "/help", desc: "show commands" },
32
+ { cmd: "/login", desc: "set up authentication" },
33
+ { cmd: "/login", desc: "set up authentication" },
31
34
  { cmd: "/map", desc: "show repository map" },
32
35
  { cmd: "/reset", desc: "clear conversation" },
33
36
  { cmd: "/context", desc: "show message count" },
@@ -104,6 +107,8 @@ function App() {
104
107
  const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
105
108
  const [themePicker, setThemePicker] = useState(false);
106
109
  const [themePickerIndex, setThemePickerIndex] = useState(0);
110
+ const [loginPicker, setLoginPicker] = useState(false);
111
+ const [loginPickerIndex, setLoginPickerIndex] = useState(0);
107
112
  const [approval, setApproval] = useState(null);
108
113
  // Listen for paste events from stdin interceptor
109
114
  useEffect(() => {
@@ -275,10 +280,16 @@ function App() {
275
280
  exit();
276
281
  return;
277
282
  }
283
+ if (trimmed === "/login" || trimmed === "/auth") {
284
+ setLoginPicker(true);
285
+ setLoginPickerIndex(0);
286
+ return;
287
+ }
278
288
  if (trimmed === "/help") {
279
289
  addMsg("info", [
280
290
  "Commands:",
281
291
  " /help — show this",
292
+ " /login — authentication setup (run codemaxxing login in terminal)",
282
293
  " /model — switch model mid-session",
283
294
  " /models — list available models",
284
295
  " /map — show repository map",
@@ -487,6 +498,92 @@ function App() {
487
498
  return;
488
499
  }
489
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
+ }
490
587
  // Theme picker navigation
491
588
  if (themePicker) {
492
589
  const themeKeys = listThemes();
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Auth management for Codemaxxing
3
+ *
4
+ * Supports:
5
+ * - OpenRouter OAuth PKCE (browser login, no API key needed)
6
+ * - Anthropic setup-token (via Claude Code CLI)
7
+ * - OpenAI/ChatGPT (via Codex CLI cached token)
8
+ * - Qwen (via Qwen CLI cached credentials)
9
+ * - GitHub Copilot (device flow)
10
+ * - Manual API key entry (any provider)
11
+ *
12
+ * Credentials stored in ~/.codemaxxing/auth.json with 0o600 permissions.
13
+ */
14
+ export interface AuthCredential {
15
+ provider: string;
16
+ method: "api-key" | "oauth" | "setup-token" | "cached-token";
17
+ apiKey: string;
18
+ baseUrl: string;
19
+ label?: string;
20
+ expiresAt?: string;
21
+ createdAt: string;
22
+ }
23
+ export interface ProviderDef {
24
+ id: string;
25
+ name: string;
26
+ methods: string[];
27
+ baseUrl: string;
28
+ consoleUrl?: string;
29
+ description: string;
30
+ }
31
+ export declare const PROVIDERS: ProviderDef[];
32
+ export declare function getCredentials(): AuthCredential[];
33
+ export declare function getCredential(providerId: string): AuthCredential | undefined;
34
+ export declare function saveCredential(cred: AuthCredential): void;
35
+ export declare function removeCredential(providerId: string): boolean;
36
+ export declare function openRouterOAuth(onStatus?: (msg: string) => void): Promise<AuthCredential>;
37
+ export declare function detectClaudeCLI(): boolean;
38
+ export declare function anthropicSetupToken(onStatus?: (msg: string) => void): Promise<AuthCredential>;
39
+ export declare function detectCodexToken(): string | null;
40
+ export declare function importCodexToken(onStatus?: (msg: string) => void): AuthCredential | null;
41
+ export declare function detectQwenToken(): string | null;
42
+ export declare function importQwenToken(onStatus?: (msg: string) => void): AuthCredential | null;
43
+ export declare function copilotDeviceFlow(onStatus?: (msg: string) => void): Promise<AuthCredential>;
44
+ export declare function saveApiKey(providerId: string, apiKey: string, baseUrl?: string, label?: string): AuthCredential;
45
+ /**
46
+ * Check which provider CLIs / cached tokens are available on this machine
47
+ */
48
+ export declare function detectAvailableAuth(): Array<{
49
+ provider: string;
50
+ method: string;
51
+ description: string;
52
+ }>;
53
+ /**
54
+ * Resolve provider config: check auth store first, then fall back to config
55
+ */
56
+ export declare function resolveProviderAuth(providerId: string): {
57
+ apiKey: string;
58
+ baseUrl: string;
59
+ } | null;