blun-king-cli 6.4.1 → 7.0.0

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/lib/auth.js CHANGED
@@ -1,217 +1,419 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const os = require('os');
4
- const https = require('https');
5
- const readline = require('readline');
6
- const chalk = require('chalk');
7
- const inquirer = require('inquirer');
8
-
9
- const CREDS_DIR = path.join(os.homedir(), '.blun');
10
- const CREDS_FILE = path.join(CREDS_DIR, 'credentials.json');
11
- const SETTINGS_FILE = path.join(CREDS_DIR, 'settings.json');
12
- const BASE_URL = 'blun.ai';
1
+ /**
2
+ * BLUN King CLI v7.0.0 - Auth Module
3
+ * CommonJS - inquirer@8
4
+ */
5
+
6
+ var fs = require("fs");
7
+ var path = require("path");
8
+ var os = require("os");
9
+ var https = require("https");
10
+ var readline = require("readline");
11
+ var chalk = require("chalk");
12
+ var inquirer = require("inquirer");
13
+
14
+ var CREDS_DIR = path.join(os.homedir(), ".blun");
15
+ var CREDS_FILE = path.join(CREDS_DIR, "credentials.json");
16
+ var SETTINGS_FILE = path.join(CREDS_DIR, "settings.json");
17
+ var BASE_URL = "blun.ai";
13
18
 
14
19
  function ensureDir() {
15
- if (!fs.existsSync(CREDS_DIR)) fs.mkdirSync(CREDS_DIR, { mode: 0o700, recursive: true });
20
+ if (!fs.existsSync(CREDS_DIR))
21
+ fs.mkdirSync(CREDS_DIR, { mode: 0o700, recursive: true });
16
22
  }
17
- function saveCredentials(creds) { ensureDir(); fs.writeFileSync(CREDS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 }); }
23
+
24
+ function saveCredentials(creds) {
25
+ ensureDir();
26
+ fs.writeFileSync(CREDS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
27
+ }
28
+
18
29
  function getStoredCredentials() {
19
30
  try {
20
31
  if (!fs.existsSync(CREDS_FILE)) return null;
21
- const data = JSON.parse(fs.readFileSync(CREDS_FILE, 'utf8'));
32
+ var data = JSON.parse(fs.readFileSync(CREDS_FILE, "utf8"));
22
33
  if (data.expires_at && new Date(data.expires_at) < new Date()) return null;
23
34
  return data;
24
- } catch { return null; }
35
+ } catch (e) {
36
+ return null;
37
+ }
25
38
  }
39
+
26
40
  function getSettings() {
27
41
  try {
28
- if (!fs.existsSync(SETTINGS_FILE)) return { model: 'auto', language: 'de', voice: false };
29
- return JSON.parse(fs.readFileSync(SETTINGS_FILE, 'utf8'));
30
- } catch { return { model: 'auto', language: 'de', voice: false }; }
42
+ if (!fs.existsSync(SETTINGS_FILE))
43
+ return { model: "auto", language: "de", voice: false, permissionMode: "normal" };
44
+ return JSON.parse(fs.readFileSync(SETTINGS_FILE, "utf8"));
45
+ } catch (e) {
46
+ return { model: "auto", language: "de", voice: false, permissionMode: "normal" };
47
+ }
48
+ }
49
+
50
+ function saveSettings(s) {
51
+ ensureDir();
52
+ fs.writeFileSync(SETTINGS_FILE, JSON.stringify(s, null, 2));
31
53
  }
32
- function saveSettings(s) { ensureDir(); fs.writeFileSync(SETTINGS_FILE, JSON.stringify(s, null, 2)); }
33
- function isAuthenticated() { return getStoredCredentials() !== null; }
54
+
55
+ function isAuthenticated() {
56
+ return getStoredCredentials() !== null;
57
+ }
58
+
34
59
  function getAuthHeader() {
35
- const c = getStoredCredentials(); if (!c) return null;
36
- if (c.apiKey) return { 'x-blun-key': c.apiKey };
37
- return { Authorization: 'Bearer ' + c.token };
60
+ var c = getStoredCredentials();
61
+ if (!c) return null;
62
+ if (c.apiKey) return { "x-blun-key": c.apiKey };
63
+ return { Authorization: "Bearer " + c.token };
38
64
  }
65
+
39
66
  function ensureAuth() {
40
- if (!isAuthenticated()) throw new Error('Not authenticated. Run "blun login" first.');
67
+ if (!isAuthenticated())
68
+ throw new Error('Not authenticated. Run "blun login" first.');
41
69
  return getStoredCredentials();
42
70
  }
43
71
 
44
- async function httpsRequest(options, body) {
45
- const url = 'https://' + (options.hostname || BASE_URL) + options.path;
46
- const fetchOpts = { method: options.method || 'GET', headers: options.headers || {} };
47
- if (body) { fetchOpts.body = JSON.stringify(body); }
48
- const res = await fetch(url, fetchOpts);
49
- let data;
50
- const text = await res.text();
51
- try { data = JSON.parse(text); } catch { data = text; }
52
- return { status: res.status, data };
72
+ function httpsRequest(options, body) {
73
+ var url =
74
+ "https://" + (options.hostname || BASE_URL) + options.path;
75
+ var fetchOpts = {
76
+ method: options.method || "GET",
77
+ headers: options.headers || {},
78
+ };
79
+ if (body) {
80
+ fetchOpts.body = JSON.stringify(body);
81
+ }
82
+ return fetch(url, fetchOpts).then(function (res) {
83
+ return res.text().then(function (text) {
84
+ var data;
85
+ try {
86
+ data = JSON.parse(text);
87
+ } catch (e) {
88
+ data = text;
89
+ }
90
+ return { status: res.status, data: data };
91
+ });
92
+ });
53
93
  }
54
94
 
55
95
  function prompt(question) {
56
- return new Promise(resolve => {
57
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
58
- rl.question(question, a => { rl.close(); resolve(a.trim()); });
96
+ return new Promise(function (resolve) {
97
+ var rl = readline.createInterface({
98
+ input: process.stdin,
99
+ output: process.stdout,
100
+ });
101
+ rl.question(question, function (a) {
102
+ rl.close();
103
+ resolve(a.trim());
104
+ });
59
105
  });
60
106
  }
61
107
 
62
- function promptPassword(question) {
63
- return new Promise(resolve => {
64
- process.stdout.write(question); let pw = '';
65
- const stdin = process.stdin; const wasRaw = stdin.isRaw;
66
- if (stdin.setRawMode) stdin.setRawMode(true); stdin.resume();
67
- const onData = (ch) => {
68
- const c = ch.toString('utf8');
69
- if (c === '\n' || c === '\r' || c === '\u0004') {
70
- if (stdin.setRawMode) stdin.setRawMode(wasRaw || false);
71
- stdin.removeListener('data', onData); stdin.pause(); process.stdout.write('\n'); resolve(pw);
72
- } else if (c === '\u007f' || c === '\b') {
73
- if (pw.length > 0) { pw = pw.slice(0, -1); process.stdout.write('\b \b'); }
74
- } else if (c === '\u0003') { process.exit(0); }
75
- else { pw += c; process.stdout.write('*'); }
76
- };
77
- stdin.on('data', onData);
78
- });
108
+ function promptMenu(title, choices) {
109
+ return inquirer
110
+ .prompt([
111
+ {
112
+ type: "list",
113
+ name: "answer",
114
+ message: title,
115
+ choices: choices.map(function (c) {
116
+ return { name: c.label, value: c.value };
117
+ }),
118
+ },
119
+ ])
120
+ .then(function (res) {
121
+ return res.answer;
122
+ });
79
123
  }
80
124
 
81
- async function promptMenu(title, choices) {
82
- const { answer } = await inquirer.prompt([{
83
- type: 'list',
84
- name: 'answer',
85
- message: title,
86
- choices: choices.map(c => ({ name: c.label, value: c.value }))
87
- }]);
88
- return answer;
89
- }
90
- async function login() {
91
- console.log(chalk.bold.cyan('\n BLUN Login\n'));
92
- const { email } = await inquirer.prompt([{ type: 'input', name: 'email', message: 'Email:' }]);
93
- const { password } = await inquirer.prompt([{ type: 'password', name: 'password', message: 'Password:', mask: '*' }]);
94
- if (!email || !password) throw new Error('Email and password required.');
95
- const res = await httpsRequest({
96
- hostname: BASE_URL, path: '/api/king/auth/login',
97
- method: 'POST', headers: { 'Content-Type': 'application/json' }
98
- }, { email, password });
99
- if (res.status !== 200 || !res.data.token) {
100
- throw new Error('Login failed: ' + (res.data.message || res.data.error || JSON.stringify(res.data)));
101
- }
102
- const creds = {
103
- token: res.data.token, email: res.data.email || email,
104
- name: res.data.name || (res.data.user ? res.data.user.name : '') || '',
105
- plan: res.data.plan || (res.data.user ? res.data.user.plan : '') || 'free'
106
- };
107
- saveCredentials(creds);
108
- console.log(chalk.green('\n Login successful! Welcome, ' + (creds.name || creds.email)));
109
- return creds;
110
- }
111
-
112
- async function register() {
113
- console.log(chalk.bold.cyan('\n BLUN Registration\n'));
114
- const { name } = await inquirer.prompt([{ type: 'input', name: 'name', message: 'Name:' }]);
115
- const { email } = await inquirer.prompt([{ type: 'input', name: 'email', message: 'Email:' }]);
116
- const { password } = await inquirer.prompt([{ type: 'password', name: 'password', message: 'Password:', mask: '*' }]);
117
- if (!email || !password || !name) throw new Error('Name, email and password required.');
118
- const res = await httpsRequest({
119
- hostname: BASE_URL, path: '/api/king/auth/register',
120
- method: 'POST', headers: { 'Content-Type': 'application/json' }
121
- }, { name, email, password });
122
- if (res.status !== 200 && res.status !== 201) {
123
- throw new Error('Registration failed: ' + (res.data.message || res.data.error || JSON.stringify(res.data)));
124
- }
125
- if (res.data.token) {
126
- const creds = { token: res.data.token, email: res.data.email || email, name: res.data.name || name, plan: res.data.plan || 'free' };
127
- saveCredentials(creds); console.log(chalk.green('\n Account created! Welcome, ' + name)); return creds;
128
- }
129
- console.log(chalk.green('\n Account created! Please login with: blun login')); return null;
125
+ function login() {
126
+ console.log(chalk.bold.cyan("\n BLUN Login\n"));
127
+ return inquirer
128
+ .prompt([
129
+ { type: "input", name: "email", message: "Email:" },
130
+ { type: "password", name: "password", message: "Password:", mask: "*" },
131
+ ])
132
+ .then(function (answers) {
133
+ if (!answers.email || !answers.password)
134
+ throw new Error("Email and password required.");
135
+ return httpsRequest(
136
+ {
137
+ hostname: BASE_URL,
138
+ path: "/api/king/auth/login",
139
+ method: "POST",
140
+ headers: { "Content-Type": "application/json" },
141
+ },
142
+ { email: answers.email, password: answers.password }
143
+ ).then(function (res) {
144
+ if (res.status !== 200 || !res.data.token) {
145
+ throw new Error(
146
+ "Login failed: " +
147
+ (res.data.message || res.data.error || JSON.stringify(res.data))
148
+ );
149
+ }
150
+ var creds = {
151
+ token: res.data.token,
152
+ email: res.data.email || answers.email,
153
+ name:
154
+ res.data.name ||
155
+ (res.data.user ? res.data.user.name : "") ||
156
+ "",
157
+ plan:
158
+ res.data.plan ||
159
+ (res.data.user ? res.data.user.plan : "") ||
160
+ "free",
161
+ };
162
+ saveCredentials(creds);
163
+ console.log(
164
+ chalk.green(
165
+ "\n Login successful! Welcome, " + (creds.name || creds.email)
166
+ )
167
+ );
168
+ return creds;
169
+ });
170
+ });
130
171
  }
131
172
 
132
- async function loginWithApiKey(apiKey) {
133
- console.log(chalk.dim(' Validating API key...'));
134
- const res = await httpsRequest({ hostname: BASE_URL, path: '/api/king/auth/me', method: 'GET', headers: { 'x-blun-key': apiKey } });
135
- if (res.status !== 200) throw new Error('Invalid API key: ' + (res.data.message || 'validation failed'));
136
- const creds = { apiKey, token: apiKey, email: res.data.email || '', name: res.data.name || '', plan: res.data.plan || 'free' };
137
- saveCredentials(creds); console.log(chalk.green(' API key validated and saved.')); return creds;
173
+ function register() {
174
+ console.log(chalk.bold.cyan("\n BLUN Registration\n"));
175
+ return inquirer
176
+ .prompt([
177
+ { type: "input", name: "name", message: "Name:" },
178
+ { type: "input", name: "email", message: "Email:" },
179
+ { type: "password", name: "password", message: "Password:", mask: "*" },
180
+ ])
181
+ .then(function (answers) {
182
+ if (!answers.email || !answers.password || !answers.name)
183
+ throw new Error("Name, email and password required.");
184
+ return httpsRequest(
185
+ {
186
+ hostname: BASE_URL,
187
+ path: "/api/king/auth/register",
188
+ method: "POST",
189
+ headers: { "Content-Type": "application/json" },
190
+ },
191
+ { name: answers.name, email: answers.email, password: answers.password }
192
+ ).then(function (res) {
193
+ if (res.status !== 200 && res.status !== 201) {
194
+ throw new Error(
195
+ "Registration failed: " +
196
+ (res.data.message || res.data.error || JSON.stringify(res.data))
197
+ );
198
+ }
199
+ if (res.data.token) {
200
+ var creds = {
201
+ token: res.data.token,
202
+ email: res.data.email || answers.email,
203
+ name: res.data.name || answers.name,
204
+ plan: res.data.plan || "free",
205
+ };
206
+ saveCredentials(creds);
207
+ console.log(chalk.green("\n Account created! Welcome, " + answers.name));
208
+ return creds;
209
+ }
210
+ console.log(
211
+ chalk.green("\n Account created! Please login with: blun login")
212
+ );
213
+ return null;
214
+ });
215
+ });
138
216
  }
139
217
 
140
- async function createApiKey(name) {
218
+ function loginWithApiKey(apiKey) {
219
+ console.log(chalk.dim(" Validating API key..."));
220
+ return httpsRequest({
221
+ hostname: BASE_URL,
222
+ path: "/api/king/auth/me",
223
+ method: "GET",
224
+ headers: { "x-blun-key": apiKey },
225
+ }).then(function (res) {
226
+ if (res.status !== 200)
227
+ throw new Error(
228
+ "Invalid API key: " + (res.data.message || "validation failed")
229
+ );
230
+ var creds = {
231
+ apiKey: apiKey,
232
+ token: apiKey,
233
+ email: res.data.email || "",
234
+ name: res.data.name || "",
235
+ plan: res.data.plan || "free",
236
+ };
237
+ saveCredentials(creds);
238
+ console.log(chalk.green(" API key validated and saved."));
239
+ return creds;
240
+ });
241
+ }
242
+
243
+ function createApiKey(name) {
141
244
  ensureAuth();
142
- const keyName = name || await prompt(chalk.green(' Key name: '));
143
- const headers = { 'Content-Type': 'application/json' };
144
- const ah = getAuthHeader(); if (ah) Object.assign(headers, ah);
145
- const res = await httpsRequest({ hostname: BASE_URL, path: '/api/king/auth/api-keys', method: 'POST', headers }, { name: keyName });
146
- if (res.status !== 200 && res.status !== 201) throw new Error('Failed to create key: ' + (res.data.message || JSON.stringify(res.data)));
147
- console.log(chalk.green('\n API Key created:'));
148
- console.log(chalk.yellow(' ' + (res.data.key || res.data.apiKey || JSON.stringify(res.data))));
149
- console.log(chalk.dim(' Save this key - it will not be shown again.\n'));
150
- return res.data;
151
- }
152
- async function listApiKeys() {
245
+ var p = name
246
+ ? Promise.resolve(name)
247
+ : prompt(chalk.green(" Key name: "));
248
+ return p.then(function (keyName) {
249
+ var headers = { "Content-Type": "application/json" };
250
+ var ah = getAuthHeader();
251
+ if (ah) Object.assign(headers, ah);
252
+ return httpsRequest(
253
+ {
254
+ hostname: BASE_URL,
255
+ path: "/api/king/auth/api-keys",
256
+ method: "POST",
257
+ headers: headers,
258
+ },
259
+ { name: keyName }
260
+ ).then(function (res) {
261
+ if (res.status !== 200 && res.status !== 201)
262
+ throw new Error(
263
+ "Failed to create key: " +
264
+ (res.data.message || JSON.stringify(res.data))
265
+ );
266
+ console.log(chalk.green("\n API Key created:"));
267
+ console.log(
268
+ chalk.yellow(
269
+ " " + (res.data.key || res.data.apiKey || JSON.stringify(res.data))
270
+ )
271
+ );
272
+ console.log(chalk.dim(" Save this key - it will not be shown again.\n"));
273
+ return res.data;
274
+ });
275
+ });
276
+ }
277
+
278
+ function listApiKeys() {
153
279
  ensureAuth();
154
- const headers = {}; const ah = getAuthHeader(); if (ah) Object.assign(headers, ah);
155
- const res = await httpsRequest({ hostname: BASE_URL, path: '/api/king/auth/api-keys', method: 'GET', headers });
156
- if (res.status !== 200) throw new Error('Failed to list keys: ' + (res.data.message || JSON.stringify(res.data)));
157
- const keys = res.data.keys || res.data || [];
158
- if (keys.length === 0) { console.log(chalk.dim('\n No API keys found. Create one with: blun keys create\n')); }
159
- else {
160
- console.log(chalk.bold.cyan('\n Your API Keys:\n'));
161
- keys.forEach((k, i) => console.log(chalk.yellow(' ' + (i+1) + ') ') + chalk.white(k.name || 'unnamed') + chalk.dim(' - ' + (k.prefix || k.id || '***'))));
162
- console.log('');
163
- }
164
- return keys;
165
- }
166
-
167
- async function whoami() {
168
- const creds = getStoredCredentials();
169
- if (!creds) { console.log(chalk.dim('\n Not logged in.\n')); return null; }
170
- const headers = {}; const ah = getAuthHeader(); if (ah) Object.assign(headers, ah);
171
- const res = await httpsRequest({ hostname: BASE_URL, path: '/api/king/auth/me', method: 'GET', headers });
172
- if (res.status === 200) {
173
- console.log(chalk.bold.cyan('\n Current User:'));
174
- console.log(chalk.white(' Name: ') + (res.data.name || creds.name || '-'));
175
- console.log(chalk.white(' Email: ') + (res.data.email || creds.email || '-'));
176
- console.log(chalk.white(' Plan: ') + (res.data.plan || creds.plan || 'free'));
177
- console.log(''); return res.data;
178
- } else {
179
- console.log(chalk.yellow('\n Stored: ') + (creds.name || creds.email || '-'));
180
- console.log(''); return creds;
280
+ var headers = {};
281
+ var ah = getAuthHeader();
282
+ if (ah) Object.assign(headers, ah);
283
+ return httpsRequest({
284
+ hostname: BASE_URL,
285
+ path: "/api/king/auth/api-keys",
286
+ method: "GET",
287
+ headers: headers,
288
+ }).then(function (res) {
289
+ if (res.status !== 200)
290
+ throw new Error(
291
+ "Failed to list keys: " +
292
+ (res.data.message || JSON.stringify(res.data))
293
+ );
294
+ var keys = res.data.keys || res.data || [];
295
+ if (keys.length === 0) {
296
+ console.log(
297
+ chalk.dim("\n No API keys found. Create one with: blun keys create\n")
298
+ );
299
+ } else {
300
+ console.log(chalk.bold.cyan("\n Your API Keys:\n"));
301
+ keys.forEach(function (k, i) {
302
+ console.log(
303
+ chalk.yellow(" " + (i + 1) + ") ") +
304
+ chalk.white(k.name || "unnamed") +
305
+ chalk.dim(" - " + (k.prefix || k.id || "***"))
306
+ );
307
+ });
308
+ console.log("");
309
+ }
310
+ return keys;
311
+ });
312
+ }
313
+
314
+ function whoami() {
315
+ var creds = getStoredCredentials();
316
+ if (!creds) {
317
+ console.log(chalk.dim("\n Not logged in.\n"));
318
+ return Promise.resolve(null);
181
319
  }
320
+ var headers = {};
321
+ var ah = getAuthHeader();
322
+ if (ah) Object.assign(headers, ah);
323
+ return httpsRequest({
324
+ hostname: BASE_URL,
325
+ path: "/api/king/auth/me",
326
+ method: "GET",
327
+ headers: headers,
328
+ }).then(function (res) {
329
+ if (res.status === 200) {
330
+ console.log(chalk.bold.cyan("\n Current User:"));
331
+ console.log(
332
+ chalk.white(" Name: ") + (res.data.name || creds.name || "-")
333
+ );
334
+ console.log(
335
+ chalk.white(" Email: ") + (res.data.email || creds.email || "-")
336
+ );
337
+ console.log(
338
+ chalk.white(" Plan: ") + (res.data.plan || creds.plan || "free")
339
+ );
340
+ console.log("");
341
+ return res.data;
342
+ } else {
343
+ console.log(
344
+ chalk.yellow("\n Stored: ") + (creds.name || creds.email || "-")
345
+ );
346
+ console.log("");
347
+ return creds;
348
+ }
349
+ });
182
350
  }
183
351
 
184
- async function showWelcomeMenu() {
185
- const chalk = require("chalk");
186
- const { action } = await inquirer.prompt([{
187
- type: "list",
188
- name: "action",
189
- message: chalk.cyan("Welcome to BLUN CLI"),
190
- choices: [
191
- { name: "Login (email + password)", value: "login" },
192
- { name: "Register new account", value: "register" },
193
- { name: "Enter API Key", value: "apikey" },
194
- { name: "Continue without auth (local mode)", value: "local" },
195
- new inquirer.Separator(),
196
- { name: "Exit", value: "exit" }
197
- ]
198
- }]);
199
- if (action === "login") { await login(); return true; }
200
- if (action === "register") { await register(); return true; }
201
- if (action === "apikey") { const { key } = await inquirer.prompt([{ type: "password", name: "key", message: "API Key:" }]); await loginWithApiKey(key); return true; }
202
- if (action === "local") { console.log(chalk.yellow(" Running in local mode.")); return true; }
203
- if (action === "exit") { process.exit(0); }
352
+ function showWelcomeMenu() {
353
+ return inquirer
354
+ .prompt([
355
+ {
356
+ type: "list",
357
+ name: "action",
358
+ message: chalk.cyan("Welcome to BLUN King CLI"),
359
+ choices: [
360
+ { name: "Login (email + password)", value: "login" },
361
+ { name: "Register new account", value: "register" },
362
+ { name: "Enter API Key", value: "apikey" },
363
+ {
364
+ name: "Continue without auth (local mode)",
365
+ value: "local",
366
+ },
367
+ new inquirer.Separator(),
368
+ { name: "Exit", value: "exit" },
369
+ ],
370
+ },
371
+ ])
372
+ .then(function (res) {
373
+ var action = res.action;
374
+ if (action === "login") return login().then(function () { return "login"; });
375
+ if (action === "register") return register().then(function () { return "register"; });
376
+ if (action === "apikey") {
377
+ return inquirer
378
+ .prompt([{ type: "password", name: "key", message: "API Key:" }])
379
+ .then(function (res) {
380
+ return loginWithApiKey(res.key).then(function () { return "apikey"; });
381
+ });
382
+ }
383
+ if (action === "local") {
384
+ console.log(chalk.yellow(" Running in local mode."));
385
+ return "local";
386
+ }
387
+ if (action === "exit") {
388
+ process.exit(0);
389
+ }
390
+ });
204
391
  }
205
392
 
206
393
  function logout() {
207
- try { if (fs.existsSync(CREDS_FILE)) fs.unlinkSync(CREDS_FILE); console.log(chalk.green(' Logged out.')); }
208
- catch (e) { throw new Error('Failed to logout: ' + e.message); }
394
+ try {
395
+ if (fs.existsSync(CREDS_FILE)) fs.unlinkSync(CREDS_FILE);
396
+ console.log(chalk.green(" Logged out."));
397
+ } catch (e) {
398
+ throw new Error("Failed to logout: " + e.message);
399
+ }
209
400
  }
210
401
 
211
402
  module.exports = {
212
- login, register, loginWithApiKey, logout,
213
- getStoredCredentials, isAuthenticated, getAuthHeader, ensureAuth,
214
- createApiKey, listApiKeys, whoami,
215
- showWelcomeMenu, promptMenu, prompt,
216
- getSettings, saveSettings
217
- };
403
+ login: login,
404
+ register: register,
405
+ loginWithApiKey: loginWithApiKey,
406
+ logout: logout,
407
+ getStoredCredentials: getStoredCredentials,
408
+ isAuthenticated: isAuthenticated,
409
+ getAuthHeader: getAuthHeader,
410
+ ensureAuth: ensureAuth,
411
+ createApiKey: createApiKey,
412
+ listApiKeys: listApiKeys,
413
+ whoami: whoami,
414
+ showWelcomeMenu: showWelcomeMenu,
415
+ promptMenu: promptMenu,
416
+ prompt: prompt,
417
+ getSettings: getSettings,
418
+ saveSettings: saveSettings,
419
+ };