starkbot-cli 0.2.2 → 0.3.1
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/index.js +283 -157
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -182,15 +182,16 @@ var init_flash_client = __esm({
|
|
|
182
182
|
import { createServer } from "http";
|
|
183
183
|
import { createInterface } from "readline";
|
|
184
184
|
import { randomBytes } from "crypto";
|
|
185
|
-
import { URL } from "url";
|
|
185
|
+
import { URL as URL2 } from "url";
|
|
186
186
|
import open from "open";
|
|
187
187
|
async function runOAuthFlow() {
|
|
188
188
|
return new Promise((resolve, reject) => {
|
|
189
189
|
let server;
|
|
190
190
|
let timeout;
|
|
191
|
+
let loginSpin = null;
|
|
191
192
|
const csrfNonce = randomBytes(16).toString("hex");
|
|
192
193
|
server = createServer((req, res) => {
|
|
193
|
-
const url = new
|
|
194
|
+
const url = new URL2(req.url ?? "/", `http://localhost`);
|
|
194
195
|
if (url.pathname === "/callback") {
|
|
195
196
|
const returnedNonce = url.searchParams.get("nonce");
|
|
196
197
|
if (returnedNonce !== csrfNonce) {
|
|
@@ -215,6 +216,7 @@ async function runOAuthFlow() {
|
|
|
215
216
|
</body>
|
|
216
217
|
</html>
|
|
217
218
|
`);
|
|
219
|
+
loginSpin?.stop();
|
|
218
220
|
clearTimeout(timeout);
|
|
219
221
|
server.close();
|
|
220
222
|
resolve({
|
|
@@ -225,6 +227,7 @@ async function runOAuthFlow() {
|
|
|
225
227
|
} else {
|
|
226
228
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
227
229
|
res.end("<h1>Login failed</h1><p>Missing JWT or username in callback.</p>");
|
|
230
|
+
loginSpin?.stop();
|
|
228
231
|
clearTimeout(timeout);
|
|
229
232
|
server.close();
|
|
230
233
|
reject(new Error("OAuth callback missing jwt or username"));
|
|
@@ -256,16 +259,17 @@ async function runOAuthFlow() {
|
|
|
256
259
|
res();
|
|
257
260
|
});
|
|
258
261
|
});
|
|
259
|
-
|
|
262
|
+
loginSpin = spinner("Opening browser for X login...");
|
|
260
263
|
loginSpin.start();
|
|
261
264
|
await open(url);
|
|
262
265
|
loginSpin.text = "Waiting for login in browser...";
|
|
263
266
|
timeout = setTimeout(() => {
|
|
264
|
-
loginSpin
|
|
267
|
+
loginSpin?.fail("Login timed out (5 minutes)");
|
|
265
268
|
server.close();
|
|
266
269
|
reject(new Error("Login timed out"));
|
|
267
270
|
}, 5 * 60 * 1e3);
|
|
268
271
|
} catch (err) {
|
|
272
|
+
loginSpin?.stop();
|
|
269
273
|
printError("Failed to start login");
|
|
270
274
|
server.close();
|
|
271
275
|
reject(err);
|
|
@@ -318,6 +322,7 @@ function clearCredentials() {
|
|
|
318
322
|
}
|
|
319
323
|
}
|
|
320
324
|
function isJwtExpired(creds) {
|
|
325
|
+
if (creds.mode === "external") return false;
|
|
321
326
|
if (!creds.jwt) return true;
|
|
322
327
|
try {
|
|
323
328
|
const parts = creds.jwt.split(".");
|
|
@@ -337,6 +342,12 @@ function requireCredentials() {
|
|
|
337
342
|
if (!creds) {
|
|
338
343
|
throw new Error("Not logged in. Run `starkbot login` first.");
|
|
339
344
|
}
|
|
345
|
+
if (creds.mode === "external") {
|
|
346
|
+
if (!creds.gateway_token || !creds.instance_domain) {
|
|
347
|
+
throw new Error("External credentials incomplete. Run `starkbot login` to reconfigure.");
|
|
348
|
+
}
|
|
349
|
+
return creds;
|
|
350
|
+
}
|
|
340
351
|
if (isJwtExpired(creds)) {
|
|
341
352
|
throw new Error("Session expired. Run `starkbot login` to re-authenticate.");
|
|
342
353
|
}
|
|
@@ -351,17 +362,168 @@ var init_credentials = __esm({
|
|
|
351
362
|
}
|
|
352
363
|
});
|
|
353
364
|
|
|
365
|
+
// src/lib/gateway-client.ts
|
|
366
|
+
var GatewayClient;
|
|
367
|
+
var init_gateway_client = __esm({
|
|
368
|
+
"src/lib/gateway-client.ts"() {
|
|
369
|
+
"use strict";
|
|
370
|
+
GatewayClient = class {
|
|
371
|
+
baseUrl;
|
|
372
|
+
token;
|
|
373
|
+
sessionId;
|
|
374
|
+
constructor(baseUrl, token, sessionId) {
|
|
375
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
376
|
+
this.token = token;
|
|
377
|
+
this.sessionId = sessionId;
|
|
378
|
+
}
|
|
379
|
+
headers() {
|
|
380
|
+
return {
|
|
381
|
+
Authorization: `Bearer ${this.token}`,
|
|
382
|
+
"Content-Type": "application/json"
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
chatBody(message) {
|
|
386
|
+
return {
|
|
387
|
+
message,
|
|
388
|
+
...this.sessionId ? { session_id: this.sessionId } : {}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
/** Send a message and get the full response */
|
|
392
|
+
async chat(message) {
|
|
393
|
+
const url = `${this.baseUrl}/api/gateway/chat`;
|
|
394
|
+
const resp = await fetch(url, {
|
|
395
|
+
method: "POST",
|
|
396
|
+
headers: this.headers(),
|
|
397
|
+
body: JSON.stringify(this.chatBody(message))
|
|
398
|
+
});
|
|
399
|
+
if (!resp.ok) {
|
|
400
|
+
const text = await resp.text().catch(() => "");
|
|
401
|
+
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
402
|
+
}
|
|
403
|
+
return resp.json();
|
|
404
|
+
}
|
|
405
|
+
/** Send a message and stream SSE events */
|
|
406
|
+
async chatStream(message, onEvent) {
|
|
407
|
+
const url = `${this.baseUrl}/api/gateway/chat/stream`;
|
|
408
|
+
const resp = await fetch(url, {
|
|
409
|
+
method: "POST",
|
|
410
|
+
headers: this.headers(),
|
|
411
|
+
body: JSON.stringify(this.chatBody(message))
|
|
412
|
+
});
|
|
413
|
+
if (!resp.ok) {
|
|
414
|
+
const text = await resp.text().catch(() => "");
|
|
415
|
+
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
416
|
+
}
|
|
417
|
+
if (!resp.body) throw new Error("No response body");
|
|
418
|
+
const reader = resp.body.getReader();
|
|
419
|
+
const decoder = new TextDecoder();
|
|
420
|
+
let buffer = "";
|
|
421
|
+
while (true) {
|
|
422
|
+
const { done, value } = await reader.read();
|
|
423
|
+
if (done) break;
|
|
424
|
+
buffer += decoder.decode(value, { stream: true });
|
|
425
|
+
let pos;
|
|
426
|
+
while ((pos = buffer.indexOf("\n\n")) !== -1) {
|
|
427
|
+
const frame = buffer.slice(0, pos);
|
|
428
|
+
buffer = buffer.slice(pos + 2);
|
|
429
|
+
for (const line of frame.split("\n")) {
|
|
430
|
+
if (line.startsWith("data: ")) {
|
|
431
|
+
try {
|
|
432
|
+
const event = JSON.parse(line.slice(6));
|
|
433
|
+
const isDone = event.type === "done";
|
|
434
|
+
onEvent(event);
|
|
435
|
+
if (isDone) return;
|
|
436
|
+
} catch {
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/** Create a new session */
|
|
444
|
+
async newSession() {
|
|
445
|
+
const url = `${this.baseUrl}/api/gateway/sessions/new`;
|
|
446
|
+
const resp = await fetch(url, {
|
|
447
|
+
method: "POST",
|
|
448
|
+
headers: this.headers()
|
|
449
|
+
});
|
|
450
|
+
if (!resp.ok) {
|
|
451
|
+
const text = await resp.text().catch(() => "");
|
|
452
|
+
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
453
|
+
}
|
|
454
|
+
return resp.json();
|
|
455
|
+
}
|
|
456
|
+
/** List sessions */
|
|
457
|
+
async listSessions() {
|
|
458
|
+
const url = `${this.baseUrl}/api/gateway/sessions`;
|
|
459
|
+
const resp = await fetch(url, {
|
|
460
|
+
method: "GET",
|
|
461
|
+
headers: this.headers()
|
|
462
|
+
});
|
|
463
|
+
if (!resp.ok) {
|
|
464
|
+
const text = await resp.text().catch(() => "");
|
|
465
|
+
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
466
|
+
}
|
|
467
|
+
return resp.json();
|
|
468
|
+
}
|
|
469
|
+
/** Get message history for a session */
|
|
470
|
+
async getHistory(sessionId) {
|
|
471
|
+
const url = `${this.baseUrl}/api/gateway/sessions/${sessionId}/messages`;
|
|
472
|
+
const resp = await fetch(url, {
|
|
473
|
+
method: "GET",
|
|
474
|
+
headers: this.headers()
|
|
475
|
+
});
|
|
476
|
+
if (!resp.ok) {
|
|
477
|
+
const text = await resp.text().catch(() => "");
|
|
478
|
+
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
479
|
+
}
|
|
480
|
+
return resp.json();
|
|
481
|
+
}
|
|
482
|
+
/** Simple health check */
|
|
483
|
+
async ping() {
|
|
484
|
+
try {
|
|
485
|
+
const resp = await fetch(`${this.baseUrl}/api/health`, {
|
|
486
|
+
headers: this.headers()
|
|
487
|
+
});
|
|
488
|
+
return resp.ok;
|
|
489
|
+
} catch {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
|
|
354
497
|
// src/commands/login.ts
|
|
355
498
|
var login_exports = {};
|
|
356
499
|
__export(login_exports, {
|
|
357
500
|
loginCommand: () => loginCommand
|
|
358
501
|
});
|
|
502
|
+
import inquirer from "inquirer";
|
|
359
503
|
async function loginCommand() {
|
|
360
504
|
const existing = loadCredentials();
|
|
361
505
|
if (existing && !isJwtExpired(existing)) {
|
|
362
506
|
printWarning(`Already logged in as @${existing.username}. Use \`starkbot logout\` first to switch accounts.`);
|
|
363
507
|
return;
|
|
364
508
|
}
|
|
509
|
+
const { loginMethod } = await inquirer.prompt([
|
|
510
|
+
{
|
|
511
|
+
type: "list",
|
|
512
|
+
name: "loginMethod",
|
|
513
|
+
message: "How would you like to connect?",
|
|
514
|
+
choices: [
|
|
515
|
+
{ name: "Login with X", value: "x" },
|
|
516
|
+
{ name: "Custom external channel", value: "external" }
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
]);
|
|
520
|
+
if (loginMethod === "external") {
|
|
521
|
+
await externalLogin();
|
|
522
|
+
} else {
|
|
523
|
+
await xLogin();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
async function xLogin() {
|
|
365
527
|
const result = await runOAuthFlow();
|
|
366
528
|
const spin = spinner("Fetching account info...");
|
|
367
529
|
spin.start();
|
|
@@ -373,7 +535,8 @@ async function loginCommand() {
|
|
|
373
535
|
username: me.user.username,
|
|
374
536
|
tenant_id: me.tenant.id,
|
|
375
537
|
instance_domain: me.tenant.domain ?? void 0,
|
|
376
|
-
jwt_expires_at: new Date(Date.now() + 24 * 60 * 60 * 1e3).toISOString()
|
|
538
|
+
jwt_expires_at: new Date(Date.now() + 24 * 60 * 60 * 1e3).toISOString(),
|
|
539
|
+
mode: "x"
|
|
377
540
|
});
|
|
378
541
|
spin.stop();
|
|
379
542
|
printSuccess(`Logged in as @${me.user.username}`);
|
|
@@ -388,17 +551,71 @@ async function loginCommand() {
|
|
|
388
551
|
saveCredentials({
|
|
389
552
|
jwt: result.jwt,
|
|
390
553
|
username: result.username,
|
|
391
|
-
tenant_id: result.tenant_id ?? ""
|
|
554
|
+
tenant_id: result.tenant_id ?? "",
|
|
555
|
+
mode: "x"
|
|
392
556
|
});
|
|
393
557
|
printSuccess(`Logged in as @${result.username}`);
|
|
394
558
|
}
|
|
395
559
|
}
|
|
560
|
+
async function externalLogin() {
|
|
561
|
+
const { instanceUrl, apiToken } = await inquirer.prompt([
|
|
562
|
+
{
|
|
563
|
+
type: "input",
|
|
564
|
+
name: "instanceUrl",
|
|
565
|
+
message: "Instance URL (e.g. https://mybot.example.com):",
|
|
566
|
+
validate: (val) => {
|
|
567
|
+
if (!val.trim()) return "Instance URL is required";
|
|
568
|
+
try {
|
|
569
|
+
new URL(val.trim());
|
|
570
|
+
return true;
|
|
571
|
+
} catch {
|
|
572
|
+
return "Please enter a valid URL";
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
type: "password",
|
|
578
|
+
name: "apiToken",
|
|
579
|
+
message: "API token:",
|
|
580
|
+
mask: "*",
|
|
581
|
+
validate: (val) => val.trim() ? true : "API token is required"
|
|
582
|
+
}
|
|
583
|
+
]);
|
|
584
|
+
const url = new URL(instanceUrl.trim());
|
|
585
|
+
const domain = url.host;
|
|
586
|
+
const baseUrl = url.origin;
|
|
587
|
+
const token = apiToken.trim();
|
|
588
|
+
const spin = spinner("Testing connection...");
|
|
589
|
+
spin.start();
|
|
590
|
+
try {
|
|
591
|
+
const gw = new GatewayClient(baseUrl, token);
|
|
592
|
+
const ok = await gw.ping();
|
|
593
|
+
spin.stop();
|
|
594
|
+
if (!ok) {
|
|
595
|
+
printError("Instance is not responding. Check the URL and try again.");
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
saveCredentials({
|
|
599
|
+
jwt: "",
|
|
600
|
+
username: "external",
|
|
601
|
+
tenant_id: "",
|
|
602
|
+
gateway_token: token,
|
|
603
|
+
instance_domain: domain,
|
|
604
|
+
mode: "external"
|
|
605
|
+
});
|
|
606
|
+
printSuccess(`Connected to ${domain}`);
|
|
607
|
+
} catch (err) {
|
|
608
|
+
spin.stop();
|
|
609
|
+
printError(`Connection failed: ${err.message}`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
396
612
|
var init_login = __esm({
|
|
397
613
|
"src/commands/login.ts"() {
|
|
398
614
|
"use strict";
|
|
399
615
|
init_auth();
|
|
400
616
|
init_credentials();
|
|
401
617
|
init_flash_client();
|
|
618
|
+
init_gateway_client();
|
|
402
619
|
init_ui();
|
|
403
620
|
}
|
|
404
621
|
});
|
|
@@ -508,7 +725,7 @@ var subscribe_exports = {};
|
|
|
508
725
|
__export(subscribe_exports, {
|
|
509
726
|
subscribeCommand: () => subscribeCommand
|
|
510
727
|
});
|
|
511
|
-
import
|
|
728
|
+
import inquirer2 from "inquirer";
|
|
512
729
|
async function subscribeCommand() {
|
|
513
730
|
const creds = requireCredentials();
|
|
514
731
|
const client = new FlashClient(creds.jwt);
|
|
@@ -520,7 +737,7 @@ async function subscribeCommand() {
|
|
|
520
737
|
printSuccess(`You already have an active subscription (${me.subscription.days_remaining} days remaining).`);
|
|
521
738
|
return;
|
|
522
739
|
}
|
|
523
|
-
const { action } = await
|
|
740
|
+
const { action } = await inquirer2.prompt([
|
|
524
741
|
{
|
|
525
742
|
type: "list",
|
|
526
743
|
name: "action",
|
|
@@ -548,7 +765,7 @@ async function subscribeCommand() {
|
|
|
548
765
|
printError(err.message);
|
|
549
766
|
}
|
|
550
767
|
} else if (action === "voucher") {
|
|
551
|
-
const { code } = await
|
|
768
|
+
const { code } = await inquirer2.prompt([
|
|
552
769
|
{
|
|
553
770
|
type: "input",
|
|
554
771
|
name: "code",
|
|
@@ -645,144 +862,12 @@ var init_provision = __esm({
|
|
|
645
862
|
}
|
|
646
863
|
});
|
|
647
864
|
|
|
648
|
-
// src/lib/gateway-client.ts
|
|
649
|
-
var GatewayClient;
|
|
650
|
-
var init_gateway_client = __esm({
|
|
651
|
-
"src/lib/gateway-client.ts"() {
|
|
652
|
-
"use strict";
|
|
653
|
-
GatewayClient = class {
|
|
654
|
-
baseUrl;
|
|
655
|
-
token;
|
|
656
|
-
sessionId;
|
|
657
|
-
constructor(baseUrl, token, sessionId) {
|
|
658
|
-
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
659
|
-
this.token = token;
|
|
660
|
-
this.sessionId = sessionId;
|
|
661
|
-
}
|
|
662
|
-
headers() {
|
|
663
|
-
return {
|
|
664
|
-
Authorization: `Bearer ${this.token}`,
|
|
665
|
-
"Content-Type": "application/json"
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
chatBody(message) {
|
|
669
|
-
return {
|
|
670
|
-
message,
|
|
671
|
-
...this.sessionId ? { session_id: this.sessionId } : {}
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
/** Send a message and get the full response */
|
|
675
|
-
async chat(message) {
|
|
676
|
-
const url = `${this.baseUrl}/api/gateway/chat`;
|
|
677
|
-
const resp = await fetch(url, {
|
|
678
|
-
method: "POST",
|
|
679
|
-
headers: this.headers(),
|
|
680
|
-
body: JSON.stringify(this.chatBody(message))
|
|
681
|
-
});
|
|
682
|
-
if (!resp.ok) {
|
|
683
|
-
const text = await resp.text().catch(() => "");
|
|
684
|
-
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
685
|
-
}
|
|
686
|
-
return resp.json();
|
|
687
|
-
}
|
|
688
|
-
/** Send a message and stream SSE events */
|
|
689
|
-
async chatStream(message, onEvent) {
|
|
690
|
-
const url = `${this.baseUrl}/api/gateway/chat/stream`;
|
|
691
|
-
const resp = await fetch(url, {
|
|
692
|
-
method: "POST",
|
|
693
|
-
headers: this.headers(),
|
|
694
|
-
body: JSON.stringify(this.chatBody(message))
|
|
695
|
-
});
|
|
696
|
-
if (!resp.ok) {
|
|
697
|
-
const text = await resp.text().catch(() => "");
|
|
698
|
-
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
699
|
-
}
|
|
700
|
-
if (!resp.body) throw new Error("No response body");
|
|
701
|
-
const reader = resp.body.getReader();
|
|
702
|
-
const decoder = new TextDecoder();
|
|
703
|
-
let buffer = "";
|
|
704
|
-
while (true) {
|
|
705
|
-
const { done, value } = await reader.read();
|
|
706
|
-
if (done) break;
|
|
707
|
-
buffer += decoder.decode(value, { stream: true });
|
|
708
|
-
let pos;
|
|
709
|
-
while ((pos = buffer.indexOf("\n\n")) !== -1) {
|
|
710
|
-
const frame = buffer.slice(0, pos);
|
|
711
|
-
buffer = buffer.slice(pos + 2);
|
|
712
|
-
for (const line of frame.split("\n")) {
|
|
713
|
-
if (line.startsWith("data: ")) {
|
|
714
|
-
try {
|
|
715
|
-
const event = JSON.parse(line.slice(6));
|
|
716
|
-
const isDone = event.type === "done";
|
|
717
|
-
onEvent(event);
|
|
718
|
-
if (isDone) return;
|
|
719
|
-
} catch {
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
/** Create a new session */
|
|
727
|
-
async newSession() {
|
|
728
|
-
const url = `${this.baseUrl}/api/gateway/sessions/new`;
|
|
729
|
-
const resp = await fetch(url, {
|
|
730
|
-
method: "POST",
|
|
731
|
-
headers: this.headers()
|
|
732
|
-
});
|
|
733
|
-
if (!resp.ok) {
|
|
734
|
-
const text = await resp.text().catch(() => "");
|
|
735
|
-
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
736
|
-
}
|
|
737
|
-
return resp.json();
|
|
738
|
-
}
|
|
739
|
-
/** List sessions */
|
|
740
|
-
async listSessions() {
|
|
741
|
-
const url = `${this.baseUrl}/api/gateway/sessions`;
|
|
742
|
-
const resp = await fetch(url, {
|
|
743
|
-
method: "GET",
|
|
744
|
-
headers: this.headers()
|
|
745
|
-
});
|
|
746
|
-
if (!resp.ok) {
|
|
747
|
-
const text = await resp.text().catch(() => "");
|
|
748
|
-
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
749
|
-
}
|
|
750
|
-
return resp.json();
|
|
751
|
-
}
|
|
752
|
-
/** Get message history for a session */
|
|
753
|
-
async getHistory(sessionId) {
|
|
754
|
-
const url = `${this.baseUrl}/api/gateway/sessions/${sessionId}/messages`;
|
|
755
|
-
const resp = await fetch(url, {
|
|
756
|
-
method: "GET",
|
|
757
|
-
headers: this.headers()
|
|
758
|
-
});
|
|
759
|
-
if (!resp.ok) {
|
|
760
|
-
const text = await resp.text().catch(() => "");
|
|
761
|
-
throw new Error(`HTTP ${resp.status}: ${text}`);
|
|
762
|
-
}
|
|
763
|
-
return resp.json();
|
|
764
|
-
}
|
|
765
|
-
/** Simple health check */
|
|
766
|
-
async ping() {
|
|
767
|
-
try {
|
|
768
|
-
const resp = await fetch(`${this.baseUrl}/api/health`, {
|
|
769
|
-
headers: this.headers()
|
|
770
|
-
});
|
|
771
|
-
return resp.ok;
|
|
772
|
-
} catch {
|
|
773
|
-
return false;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
});
|
|
779
|
-
|
|
780
865
|
// src/commands/connect.ts
|
|
781
866
|
var connect_exports = {};
|
|
782
867
|
__export(connect_exports, {
|
|
783
868
|
connectCommand: () => connectCommand
|
|
784
869
|
});
|
|
785
|
-
import
|
|
870
|
+
import inquirer3 from "inquirer";
|
|
786
871
|
async function connectCommand(opts = {}) {
|
|
787
872
|
const creds = requireCredentials();
|
|
788
873
|
if (opts.token) {
|
|
@@ -839,7 +924,7 @@ async function connectCommand(opts = {}) {
|
|
|
839
924
|
printWarning("Could not auto-fetch gateway credentials \u2014 you can enter them manually.");
|
|
840
925
|
console.log(dim(` (${err.message})
|
|
841
926
|
`));
|
|
842
|
-
const answers = await
|
|
927
|
+
const answers = await inquirer3.prompt([
|
|
843
928
|
{
|
|
844
929
|
type: "input",
|
|
845
930
|
name: "token",
|
|
@@ -870,7 +955,7 @@ var init_connect = __esm({
|
|
|
870
955
|
// src/lib/status.ts
|
|
871
956
|
import ora2 from "ora";
|
|
872
957
|
import chalk2 from "chalk";
|
|
873
|
-
var subtypeColor, toolColor, subagentColor, dimText, StatusTracker;
|
|
958
|
+
var subtypeColor, toolColor, subagentColor, dimText, successMark, failMark, StatusTracker;
|
|
874
959
|
var init_status2 = __esm({
|
|
875
960
|
"src/lib/status.ts"() {
|
|
876
961
|
"use strict";
|
|
@@ -878,6 +963,8 @@ var init_status2 = __esm({
|
|
|
878
963
|
toolColor = chalk2.yellow;
|
|
879
964
|
subagentColor = chalk2.cyan;
|
|
880
965
|
dimText = chalk2.dim;
|
|
966
|
+
successMark = chalk2.green("\u2705");
|
|
967
|
+
failMark = chalk2.red("\u274C");
|
|
881
968
|
StatusTracker = class {
|
|
882
969
|
spinner;
|
|
883
970
|
activeSubtype = "";
|
|
@@ -891,10 +978,12 @@ var init_status2 = __esm({
|
|
|
891
978
|
handleEvent(event) {
|
|
892
979
|
switch (event.type) {
|
|
893
980
|
case "tool_call":
|
|
981
|
+
this.printToolCall(event);
|
|
894
982
|
this.addTool(event.tool_name ?? "unknown");
|
|
895
983
|
break;
|
|
896
984
|
case "tool_result":
|
|
897
985
|
this.removeTool(event.tool_name ?? "unknown");
|
|
986
|
+
this.printToolResult(event);
|
|
898
987
|
break;
|
|
899
988
|
case "subagent_spawned":
|
|
900
989
|
this.addSubagent(event.label ?? "?", event.agent_subtype);
|
|
@@ -925,6 +1014,25 @@ var init_status2 = __esm({
|
|
|
925
1014
|
break;
|
|
926
1015
|
}
|
|
927
1016
|
}
|
|
1017
|
+
printToolCall(event) {
|
|
1018
|
+
const name = event.tool_name ?? "unknown";
|
|
1019
|
+
this.pauseForText();
|
|
1020
|
+
console.log(dimText(` \u{1F527} ${toolColor("Calling:")} ${chalk2.bold(name)}`));
|
|
1021
|
+
this.resumeAfterText();
|
|
1022
|
+
}
|
|
1023
|
+
printToolResult(event) {
|
|
1024
|
+
const name = event.tool_name ?? "unknown";
|
|
1025
|
+
const ok = event.success !== false;
|
|
1026
|
+
const mark = ok ? successMark : failMark;
|
|
1027
|
+
const durationStr = event.duration_ms != null ? ` ${dimText(`(${event.duration_ms}ms)`)}` : "";
|
|
1028
|
+
this.pauseForText();
|
|
1029
|
+
console.log(dimText(` ${mark} ${chalk2.bold(name)}${durationStr}`));
|
|
1030
|
+
if (!ok && event.content) {
|
|
1031
|
+
const snippet = event.content.length > 200 ? event.content.slice(0, 200) + "..." : event.content;
|
|
1032
|
+
console.log(dimText(` ${chalk2.red(snippet)}`));
|
|
1033
|
+
}
|
|
1034
|
+
this.resumeAfterText();
|
|
1035
|
+
}
|
|
928
1036
|
prefix() {
|
|
929
1037
|
if (this.activeSubtype) {
|
|
930
1038
|
return `${subtypeColor(`[${this.activeSubtype}]`)} `;
|
|
@@ -969,7 +1077,7 @@ var init_status2 = __esm({
|
|
|
969
1077
|
}
|
|
970
1078
|
if (this.activeTools.length > 0) {
|
|
971
1079
|
const names = this.activeTools.map((t) => toolColor(t)).join(", ");
|
|
972
|
-
parts.push(`
|
|
1080
|
+
parts.push(`running ${names}`);
|
|
973
1081
|
}
|
|
974
1082
|
if (parts.length === 0) {
|
|
975
1083
|
if (this.spinner.isSpinning && !this.paused) {
|
|
@@ -1253,7 +1361,7 @@ __export(instances_exports, {
|
|
|
1253
1361
|
instancesNewCommand: () => instancesNewCommand,
|
|
1254
1362
|
instancesSelectCommand: () => instancesSelectCommand
|
|
1255
1363
|
});
|
|
1256
|
-
import
|
|
1364
|
+
import inquirer4 from "inquirer";
|
|
1257
1365
|
async function instancesListCommand() {
|
|
1258
1366
|
const creds = requireCredentials();
|
|
1259
1367
|
const client = new FlashClient(creds.jwt);
|
|
@@ -1335,7 +1443,7 @@ async function instancesSelectCommand(tenantId) {
|
|
|
1335
1443
|
name: `${inst.display_name ?? inst.id} ${dim(`(${inst.status}${inst.domain ? ` - ${inst.domain}` : ""})`)}${inst.id === creds.tenant_id ? success(" *active*") : ""}`,
|
|
1336
1444
|
value: inst.id
|
|
1337
1445
|
}));
|
|
1338
|
-
const answer = await
|
|
1446
|
+
const answer = await inquirer4.prompt([
|
|
1339
1447
|
{
|
|
1340
1448
|
type: "list",
|
|
1341
1449
|
name: "tenantId",
|
|
@@ -1409,7 +1517,7 @@ async function instancesDeleteCommand(tenantId) {
|
|
|
1409
1517
|
await doDelete(client, creds.tenant_id, creds);
|
|
1410
1518
|
}
|
|
1411
1519
|
async function doDelete(client, tenantId, creds) {
|
|
1412
|
-
const answer = await
|
|
1520
|
+
const answer = await inquirer4.prompt([
|
|
1413
1521
|
{
|
|
1414
1522
|
type: "confirm",
|
|
1415
1523
|
name: "confirm",
|
|
@@ -1553,16 +1661,16 @@ var wizard_exports = {};
|
|
|
1553
1661
|
__export(wizard_exports, {
|
|
1554
1662
|
wizardCommand: () => wizardCommand
|
|
1555
1663
|
});
|
|
1556
|
-
import
|
|
1664
|
+
import inquirer5 from "inquirer";
|
|
1557
1665
|
async function wizardCommand() {
|
|
1558
1666
|
banner();
|
|
1559
1667
|
let creds = loadCredentials();
|
|
1560
1668
|
if (!creds || isJwtExpired(creds)) {
|
|
1561
|
-
console.log(bold(" Step 1: Login
|
|
1669
|
+
console.log(bold(" Step 1: Login\n"));
|
|
1562
1670
|
await loginCommand();
|
|
1563
1671
|
console.log();
|
|
1564
1672
|
} else {
|
|
1565
|
-
const { accountAction } = await
|
|
1673
|
+
const { accountAction } = await inquirer5.prompt([
|
|
1566
1674
|
{
|
|
1567
1675
|
type: "list",
|
|
1568
1676
|
name: "accountAction",
|
|
@@ -1575,12 +1683,30 @@ async function wizardCommand() {
|
|
|
1575
1683
|
]);
|
|
1576
1684
|
if (accountAction === "signout") {
|
|
1577
1685
|
await logoutCommand();
|
|
1578
|
-
console.log(bold("\n Login
|
|
1686
|
+
console.log(bold("\n Login\n"));
|
|
1579
1687
|
await loginCommand();
|
|
1580
1688
|
console.log();
|
|
1581
1689
|
creds = loadCredentials();
|
|
1582
1690
|
}
|
|
1583
1691
|
}
|
|
1692
|
+
creds = loadCredentials();
|
|
1693
|
+
if (creds?.mode === "external") {
|
|
1694
|
+
if (creds.gateway_token && creds.instance_domain) {
|
|
1695
|
+
const { startChat } = await inquirer5.prompt([
|
|
1696
|
+
{
|
|
1697
|
+
type: "confirm",
|
|
1698
|
+
name: "startChat",
|
|
1699
|
+
message: "Start chatting with your bot?",
|
|
1700
|
+
default: true
|
|
1701
|
+
}
|
|
1702
|
+
]);
|
|
1703
|
+
if (startChat) {
|
|
1704
|
+
console.log();
|
|
1705
|
+
await chatReplCommand();
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1584
1710
|
const currentCreds = requireCredentials();
|
|
1585
1711
|
const client = new FlashClient(currentCreds.jwt);
|
|
1586
1712
|
const spin = spinner("Checking account...");
|
|
@@ -1607,7 +1733,7 @@ async function wizardCommand() {
|
|
|
1607
1733
|
});
|
|
1608
1734
|
choices.push({ name: "Create new instance", value: "__new__" });
|
|
1609
1735
|
console.log(bold("\n Select an instance\n"));
|
|
1610
|
-
const { instanceChoice } = await
|
|
1736
|
+
const { instanceChoice } = await inquirer5.prompt([
|
|
1611
1737
|
{
|
|
1612
1738
|
type: "list",
|
|
1613
1739
|
name: "instanceChoice",
|
|
@@ -1617,7 +1743,7 @@ async function wizardCommand() {
|
|
|
1617
1743
|
}
|
|
1618
1744
|
]);
|
|
1619
1745
|
if (instanceChoice === "__new__") {
|
|
1620
|
-
const { displayName } = await
|
|
1746
|
+
const { displayName } = await inquirer5.prompt([
|
|
1621
1747
|
{
|
|
1622
1748
|
type: "input",
|
|
1623
1749
|
name: "displayName",
|
|
@@ -1665,7 +1791,7 @@ async function wizardCommand() {
|
|
|
1665
1791
|
}
|
|
1666
1792
|
const finalCreds = loadCredentials();
|
|
1667
1793
|
if (finalCreds?.gateway_token && finalCreds?.instance_domain) {
|
|
1668
|
-
const { startChat } = await
|
|
1794
|
+
const { startChat } = await inquirer5.prompt([
|
|
1669
1795
|
{
|
|
1670
1796
|
type: "confirm",
|
|
1671
1797
|
name: "startChat",
|
|
@@ -1697,8 +1823,8 @@ var init_wizard = __esm({
|
|
|
1697
1823
|
init_ui();
|
|
1698
1824
|
import { Command } from "commander";
|
|
1699
1825
|
var program = new Command();
|
|
1700
|
-
program.name("starkbot").description("CLI for Starkbot \u2014 login, provision, and chat with your bot").version("0.1
|
|
1701
|
-
program.command("login").description("Login with
|
|
1826
|
+
program.name("starkbot").description("CLI for Starkbot \u2014 login, provision, and chat with your bot").version("0.3.1").addHelpCommand("help", "Show help for a command");
|
|
1827
|
+
program.command("login").description("Login with X or connect to an external instance").action(async () => {
|
|
1702
1828
|
const { loginCommand: loginCommand2 } = await Promise.resolve().then(() => (init_login(), login_exports));
|
|
1703
1829
|
await loginCommand2();
|
|
1704
1830
|
});
|