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.
Files changed (2) hide show
  1. package/dist/index.js +283 -157
  2. 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 URL(req.url ?? "/", `http://localhost`);
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
- const loginSpin = spinner("Opening browser for X login...");
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.fail("Login timed out (5 minutes)");
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 inquirer from "inquirer";
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 inquirer.prompt([
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 inquirer.prompt([
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 inquirer2 from "inquirer";
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 inquirer2.prompt([
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(`calling ${names}`);
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 inquirer3 from "inquirer";
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 inquirer3.prompt([
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 inquirer3.prompt([
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 inquirer4 from "inquirer";
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 with X\n"));
1669
+ console.log(bold(" Step 1: Login\n"));
1562
1670
  await loginCommand();
1563
1671
  console.log();
1564
1672
  } else {
1565
- const { accountAction } = await inquirer4.prompt([
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 with X\n"));
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 inquirer4.prompt([
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 inquirer4.prompt([
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 inquirer4.prompt([
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.0").addHelpCommand("help", "Show help for a command");
1701
- program.command("login").description("Login with your X (Twitter) account").action(async () => {
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starkbot-cli",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "CLI for Starkbot — login, provision, and chat with your bot from the terminal",
5
5
  "type": "module",
6
6
  "bin": {