starkbot-cli 0.2.0 → 0.2.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 +166 -88
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1019,7 +1019,7 @@ __export(chat_exports, {
1019
1019
  chatOneShotCommand: () => chatOneShotCommand,
1020
1020
  chatReplCommand: () => chatReplCommand
1021
1021
  });
1022
- import { createInterface as createInterface2 } from "readline";
1022
+ import { createInterface as createInterface2 } from "readline/promises";
1023
1023
  function requireGateway() {
1024
1024
  const creds = requireCredentials();
1025
1025
  if (!creds.gateway_token || !creds.instance_domain) {
@@ -1032,8 +1032,28 @@ function requireGateway() {
1032
1032
  creds.gateway_token
1033
1033
  );
1034
1034
  }
1035
+ function isAuthError(err) {
1036
+ return err?.message?.includes("HTTP 401") || err?.message?.includes("Invalid gateway token");
1037
+ }
1038
+ async function tryRefreshToken() {
1039
+ const creds = loadCredentials();
1040
+ if (!creds?.jwt) return null;
1041
+ try {
1042
+ const client = new FlashClient(creds.jwt);
1043
+ const { token, domain } = await client.getGatewayToken();
1044
+ updateCredentials({ gateway_token: token, instance_domain: domain });
1045
+ const gw = new GatewayClient(`https://${domain}`, token);
1046
+ const ok = await gw.ping();
1047
+ if (ok) {
1048
+ printSuccess("Gateway token refreshed automatically.");
1049
+ return gw;
1050
+ }
1051
+ } catch {
1052
+ }
1053
+ return null;
1054
+ }
1035
1055
  async function chatOneShotCommand(message) {
1036
- const gw = requireGateway();
1056
+ let gw = requireGateway();
1037
1057
  const status = new StatusTracker();
1038
1058
  process.stdout.write(`${prefix.agent} `);
1039
1059
  try {
@@ -1042,15 +1062,36 @@ async function chatOneShotCommand(message) {
1042
1062
  } catch (err) {
1043
1063
  status.finish();
1044
1064
  console.log();
1045
- printError(err.message);
1065
+ if (isAuthError(err)) {
1066
+ printWarning("Gateway token is invalid or expired. Attempting to refresh...");
1067
+ const refreshed = await tryRefreshToken();
1068
+ if (refreshed) {
1069
+ gw = refreshed;
1070
+ process.stdout.write(`${prefix.agent} `);
1071
+ const status2 = new StatusTracker();
1072
+ try {
1073
+ await gw.chatStream(message, (event) => status2.handleEvent(event));
1074
+ console.log();
1075
+ return;
1076
+ } catch (retryErr) {
1077
+ status2.finish();
1078
+ console.log();
1079
+ printError(retryErr.message);
1080
+ }
1081
+ } else {
1082
+ printError("Could not refresh token. Run `starkbot connect` to set a new gateway token.");
1083
+ }
1084
+ } else {
1085
+ printError(err.message);
1086
+ }
1046
1087
  process.exit(1);
1047
1088
  }
1048
1089
  }
1049
1090
  async function chatReplCommand() {
1050
- const gw = requireGateway();
1091
+ let gw = requireGateway();
1051
1092
  console.log(
1052
1093
  dim(
1053
- "Starkbot CLI \u2014 type a message, /new to reset, /sessions to list, /quit to exit"
1094
+ "Starkbot CLI \u2014 type a message, /new to reset, /sessions to list, /connect to refresh token, /quit to exit"
1054
1095
  )
1055
1096
  );
1056
1097
  const rl = createInterface2({
@@ -1058,109 +1099,146 @@ async function chatReplCommand() {
1058
1099
  output: process.stdout,
1059
1100
  terminal: true
1060
1101
  });
1061
- const prompt = () => {
1062
- rl.question(`${prefix.you} `, async (input) => {
1063
- const trimmed = input.trim();
1064
- if (!trimmed) {
1065
- prompt();
1066
- return;
1102
+ let running = true;
1103
+ while (running) {
1104
+ let input;
1105
+ try {
1106
+ input = await rl.question(`${prefix.you} `);
1107
+ } catch {
1108
+ break;
1109
+ }
1110
+ const trimmed = input.trim();
1111
+ if (!trimmed) continue;
1112
+ switch (trimmed) {
1113
+ case "/quit":
1114
+ case "/exit":
1115
+ case "/q":
1116
+ running = false;
1117
+ console.log(dim("Goodbye!"));
1118
+ break;
1119
+ case "/new": {
1120
+ try {
1121
+ const resp = await gw.newSession();
1122
+ console.log(
1123
+ `${prefix.system} New session created (id: ${resp.session_id})`
1124
+ );
1125
+ } catch (err) {
1126
+ console.log(`${prefix.error} ${err.message}`);
1127
+ }
1128
+ break;
1067
1129
  }
1068
- switch (trimmed) {
1069
- case "/quit":
1070
- case "/exit":
1071
- case "/q":
1072
- rl.close();
1073
- console.log(dim("Goodbye!"));
1074
- return;
1075
- case "/new": {
1076
- try {
1077
- const resp = await gw.newSession();
1078
- console.log(
1079
- `${prefix.system} New session created (id: ${resp.session_id})`
1080
- );
1081
- } catch (err) {
1082
- console.log(`${prefix.error} ${err.message}`);
1130
+ case "/sessions": {
1131
+ try {
1132
+ const resp = await gw.listSessions();
1133
+ if (resp.sessions.length === 0) {
1134
+ console.log(`${prefix.system} No sessions found`);
1135
+ } else {
1136
+ console.log(`${prefix.system} Sessions:`);
1137
+ for (const s of resp.sessions) {
1138
+ console.log(
1139
+ ` ${info(s.session_key)} | ${s.message_count} msgs | last active: ${dim(s.last_activity_at)}`
1140
+ );
1141
+ }
1083
1142
  }
1084
- prompt();
1085
- return;
1143
+ } catch (err) {
1144
+ console.log(`${prefix.error} ${err.message}`);
1086
1145
  }
1087
- case "/sessions": {
1146
+ break;
1147
+ }
1148
+ case "/connect": {
1149
+ console.log(`${prefix.system} Refreshing gateway token...`);
1150
+ const refreshed = await tryRefreshToken();
1151
+ if (refreshed) {
1152
+ gw = refreshed;
1153
+ } else {
1154
+ console.log(`${prefix.system} Auto-refresh failed. Enter a new gateway token manually.`);
1088
1155
  try {
1089
- const resp = await gw.listSessions();
1090
- if (resp.sessions.length === 0) {
1091
- console.log(`${prefix.system} No sessions found`);
1092
- } else {
1093
- console.log(`${prefix.system} Sessions:`);
1094
- for (const s of resp.sessions) {
1095
- console.log(
1096
- ` ${info(s.session_key)} | ${s.message_count} msgs | last active: ${dim(s.last_activity_at)}`
1097
- );
1156
+ const newToken = (await rl.question(`${prefix.system} Gateway token: `)).trim();
1157
+ if (newToken) {
1158
+ const creds = requireCredentials();
1159
+ const domain = creds.instance_domain;
1160
+ updateCredentials({ gateway_token: newToken });
1161
+ gw = new GatewayClient(`https://${domain}`, newToken);
1162
+ const ok = await gw.ping();
1163
+ if (ok) {
1164
+ printSuccess(`Reconnected to ${domain}`);
1165
+ } else {
1166
+ printWarning("Token saved but instance is not responding.");
1098
1167
  }
1168
+ } else {
1169
+ console.log(`${prefix.system} Cancelled.`);
1099
1170
  }
1100
- } catch (err) {
1101
- console.log(`${prefix.error} ${err.message}`);
1171
+ } catch {
1102
1172
  }
1103
- prompt();
1104
- return;
1105
1173
  }
1106
- case "/help":
1107
- console.log(`${prefix.system} Commands:`);
1108
- console.log(` ${info("/new")} \u2014 Start a new session`);
1109
- console.log(` ${info("/sessions")} \u2014 List sessions`);
1110
- console.log(
1111
- ` ${info("/history <id>")} \u2014 Show message history`
1112
- );
1113
- console.log(` ${info("/quit")} \u2014 Exit`);
1114
- prompt();
1115
- return;
1116
- default:
1117
- if (trimmed.startsWith("/history")) {
1118
- const parts = trimmed.split(/\s+/);
1119
- if (parts.length < 2) {
1120
- console.log(
1121
- `${prefix.system} Usage: /history <session_id>`
1122
- );
1174
+ break;
1175
+ }
1176
+ case "/help":
1177
+ console.log(`${prefix.system} Commands:`);
1178
+ console.log(` ${info("/new")} \u2014 Start a new session`);
1179
+ console.log(` ${info("/sessions")} \u2014 List sessions`);
1180
+ console.log(
1181
+ ` ${info("/history <id>")} \u2014 Show message history`
1182
+ );
1183
+ console.log(` ${info("/connect")} \u2014 Refresh gateway token`);
1184
+ console.log(` ${info("/quit")} \u2014 Exit`);
1185
+ break;
1186
+ default:
1187
+ if (trimmed.startsWith("/history")) {
1188
+ const parts = trimmed.split(/\s+/);
1189
+ if (parts.length < 2) {
1190
+ console.log(
1191
+ `${prefix.system} Usage: /history <session_id>`
1192
+ );
1193
+ } else {
1194
+ const sid = parseInt(parts[1], 10);
1195
+ if (isNaN(sid)) {
1196
+ console.log(`${prefix.error} Invalid session ID: ${parts[1]}`);
1123
1197
  } else {
1124
- const sid = parseInt(parts[1], 10);
1125
- if (isNaN(sid)) {
1126
- console.log(`${prefix.error} Invalid session ID: ${parts[1]}`);
1127
- } else {
1128
- try {
1129
- const resp = await gw.getHistory(sid);
1130
- for (const m of resp.messages) {
1131
- const p = m.role === "user" ? prefix.you : m.role === "assistant" ? prefix.agent : dim(`${m.role}>`);
1132
- console.log(`${p} ${m.content}`);
1133
- }
1134
- } catch (err) {
1135
- console.log(`${prefix.error} ${err.message}`);
1198
+ try {
1199
+ const resp = await gw.getHistory(sid);
1200
+ for (const m of resp.messages) {
1201
+ const p = m.role === "user" ? prefix.you : m.role === "assistant" ? prefix.agent : dim(`${m.role}>`);
1202
+ console.log(`${p} ${m.content}`);
1136
1203
  }
1204
+ } catch (err) {
1205
+ console.log(`${prefix.error} ${err.message}`);
1137
1206
  }
1138
1207
  }
1139
- prompt();
1140
- return;
1141
1208
  }
1142
- process.stdout.write(`${prefix.agent} `);
1143
- try {
1144
- const status = new StatusTracker();
1145
- await gw.chatStream(trimmed, (event) => status.handleEvent(event));
1146
- console.log();
1147
- } catch (err) {
1148
- console.log();
1209
+ break;
1210
+ }
1211
+ process.stdout.write(`${prefix.agent} `);
1212
+ try {
1213
+ const status = new StatusTracker();
1214
+ await gw.chatStream(trimmed, (event) => status.handleEvent(event));
1215
+ console.log();
1216
+ } catch (err) {
1217
+ console.log();
1218
+ if (isAuthError(err)) {
1219
+ console.log(`${prefix.error} ${err.message}`);
1220
+ console.log(warn(" Gateway token is invalid or expired. Attempting to refresh..."));
1221
+ const refreshed = await tryRefreshToken();
1222
+ if (refreshed) {
1223
+ gw = refreshed;
1224
+ console.log(dim(" Try your message again."));
1225
+ } else {
1226
+ console.log(warn(" Auto-refresh failed. Use /connect to enter a new token."));
1227
+ }
1228
+ } else {
1149
1229
  console.log(`${prefix.error} ${err.message}`);
1150
1230
  }
1151
- prompt();
1152
- }
1153
- });
1154
- };
1155
- prompt();
1156
- rl.on("close", () => {
1157
- process.exit(0);
1158
- });
1231
+ }
1232
+ }
1233
+ }
1234
+ rl.close();
1235
+ process.exit(0);
1159
1236
  }
1160
1237
  var init_chat = __esm({
1161
1238
  "src/commands/chat.ts"() {
1162
1239
  "use strict";
1163
1240
  init_credentials();
1241
+ init_flash_client();
1164
1242
  init_gateway_client();
1165
1243
  init_status2();
1166
1244
  init_ui();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starkbot-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI for Starkbot — login, provision, and chat with your bot from the terminal",
5
5
  "type": "module",
6
6
  "bin": {