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 +378 -176
- package/lib/chat.js +347 -143
- package/lib/client.js +101 -39
- package/lib/ui.js +150 -34
- package/lib/workspace.js +79 -55
- package/package.json +1 -1
package/lib/auth.js
CHANGED
|
@@ -1,217 +1,419 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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))
|
|
20
|
+
if (!fs.existsSync(CREDS_DIR))
|
|
21
|
+
fs.mkdirSync(CREDS_DIR, { mode: 0o700, recursive: true });
|
|
16
22
|
}
|
|
17
|
-
|
|
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
|
-
|
|
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 {
|
|
35
|
+
} catch (e) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
25
38
|
}
|
|
39
|
+
|
|
26
40
|
function getSettings() {
|
|
27
41
|
try {
|
|
28
|
-
if (!fs.existsSync(SETTINGS_FILE))
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
33
|
-
function isAuthenticated() {
|
|
54
|
+
|
|
55
|
+
function isAuthenticated() {
|
|
56
|
+
return getStoredCredentials() !== null;
|
|
57
|
+
}
|
|
58
|
+
|
|
34
59
|
function getAuthHeader() {
|
|
35
|
-
|
|
36
|
-
if (c
|
|
37
|
-
return {
|
|
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())
|
|
67
|
+
if (!isAuthenticated())
|
|
68
|
+
throw new Error('Not authenticated. Run "blun login" first.');
|
|
41
69
|
return getStoredCredentials();
|
|
42
70
|
}
|
|
43
71
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
133
|
-
console.log(chalk.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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 {
|
|
208
|
-
|
|
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
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
+
};
|