bashio 0.5.1 → 0.7.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/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/cli/index.ts
4
4
  import { Builtins, Cli } from "clipanion";
5
+ import pc17 from "picocolors";
5
6
  import updateNotifier from "update-notifier";
6
7
 
7
8
  // src/core/config.ts
@@ -579,8 +580,11 @@ var AddShortcutCommand = class extends Command {
579
580
  };
580
581
 
581
582
  // src/cli/commands/AuthCommand.ts
582
- import { input as input3, password, select } from "@inquirer/prompts";
583
583
  import { Command as Command2 } from "clipanion";
584
+ import pc4 from "picocolors";
585
+
586
+ // src/core/auth.ts
587
+ import { input as input3, password, select } from "@inquirer/prompts";
584
588
  import pc3 from "picocolors";
585
589
 
586
590
  // src/providers/base.ts
@@ -932,6 +936,205 @@ function createSpinner(text) {
932
936
  });
933
937
  }
934
938
 
939
+ // src/core/auth.ts
940
+ function showWelcomeBanner() {
941
+ const cyan = pc3.cyan;
942
+ const dim = pc3.dim;
943
+ const width = 58;
944
+ const ansiRegex = new RegExp(
945
+ `${String.fromCharCode(27)}\\[[0-9;]*[a-zA-Z]`,
946
+ "g"
947
+ );
948
+ const stripAnsi2 = (str) => str.replace(ansiRegex, "");
949
+ const visibleLength = (str) => stripAnsi2(str).length;
950
+ const pad = (text, len) => {
951
+ const padding = len - visibleLength(text);
952
+ return text + " ".repeat(Math.max(0, padding));
953
+ };
954
+ const line = (content) => cyan(" \u2502") + pad(content, width) + cyan("\u2502");
955
+ console.log();
956
+ console.log(cyan(` \u250C${"\u2500".repeat(width)}\u2510`));
957
+ console.log(line(""));
958
+ console.log(
959
+ line(
960
+ ` ${pc3.bold(pc3.white("\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557"))}`
961
+ )
962
+ );
963
+ console.log(
964
+ line(
965
+ ` ${pc3.bold(pc3.white("\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557"))}`
966
+ )
967
+ );
968
+ console.log(
969
+ line(
970
+ ` ${pc3.bold(pc3.white("\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551"))}`
971
+ )
972
+ );
973
+ console.log(
974
+ line(
975
+ ` ${pc3.bold(pc3.white("\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551"))}`
976
+ )
977
+ );
978
+ console.log(
979
+ line(
980
+ ` ${pc3.bold(pc3.white("\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D"))}`
981
+ )
982
+ );
983
+ console.log(
984
+ line(
985
+ ` ${pc3.bold(pc3.white("\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D"))}`
986
+ )
987
+ );
988
+ console.log(line(""));
989
+ console.log(line(dim(" Natural language to shell commands.")));
990
+ console.log(line(dim(" Stop Googling, start doing.")));
991
+ console.log(line(""));
992
+ console.log(cyan(` \u2514${"\u2500".repeat(width)}\u2518`));
993
+ console.log();
994
+ }
995
+ async function runAuthSetup(showBanner = true) {
996
+ if (showBanner) {
997
+ showWelcomeBanner();
998
+ }
999
+ console.log(pc3.bold(" Bashio Setup\n"));
1000
+ const provider = await select({
1001
+ message: "Select your AI provider:",
1002
+ choices: [
1003
+ {
1004
+ value: "claude",
1005
+ name: "Claude (Anthropic)",
1006
+ description: "Use Anthropic API key"
1007
+ },
1008
+ {
1009
+ value: "openai",
1010
+ name: "ChatGPT (OpenAI)",
1011
+ description: "Use OpenAI API key"
1012
+ },
1013
+ {
1014
+ value: "ollama",
1015
+ name: "Ollama (Local)",
1016
+ description: "Free, runs on your machine"
1017
+ },
1018
+ {
1019
+ value: "openrouter",
1020
+ name: "OpenRouter",
1021
+ description: "Pay per use, multiple models"
1022
+ }
1023
+ ]
1024
+ });
1025
+ let credentials;
1026
+ let model;
1027
+ switch (provider) {
1028
+ case "claude": {
1029
+ const apiKey = await password({
1030
+ message: "Enter your Anthropic API key:",
1031
+ mask: "*"
1032
+ });
1033
+ credentials = { type: "api_key", apiKey };
1034
+ model = await select({
1035
+ message: "Select model:",
1036
+ choices: CLAUDE_MODELS.map((m) => ({
1037
+ value: m.value,
1038
+ name: m.label
1039
+ }))
1040
+ });
1041
+ break;
1042
+ }
1043
+ case "openai": {
1044
+ const apiKey = await password({
1045
+ message: "Enter your OpenAI API key:",
1046
+ mask: "*"
1047
+ });
1048
+ credentials = { type: "api_key", apiKey };
1049
+ model = await select({
1050
+ message: "Select model:",
1051
+ choices: OPENAI_MODELS.map((m) => ({
1052
+ value: m.value,
1053
+ name: m.label
1054
+ }))
1055
+ });
1056
+ break;
1057
+ }
1058
+ case "ollama": {
1059
+ const host = await input3({
1060
+ message: "Ollama host:",
1061
+ default: "http://localhost:11434"
1062
+ });
1063
+ credentials = { type: "local", host };
1064
+ const spinner2 = createSpinner("Checking Ollama connection...").start();
1065
+ const availableModels = await OllamaProvider.getAvailableModels(host);
1066
+ if (availableModels.length === 0) {
1067
+ spinner2.fail("Could not connect to Ollama or no models installed");
1068
+ console.log(pc3.yellow("\nMake sure Ollama is running: ollama serve"));
1069
+ console.log(pc3.yellow("Install a model: ollama pull llama3.2\n"));
1070
+ return false;
1071
+ }
1072
+ spinner2.succeed(`Found ${availableModels.length} models`);
1073
+ const modelChoices = availableModels.map((m) => ({
1074
+ value: m,
1075
+ name: m
1076
+ }));
1077
+ model = await select({
1078
+ message: "Select model:",
1079
+ choices: modelChoices
1080
+ });
1081
+ break;
1082
+ }
1083
+ case "openrouter": {
1084
+ const apiKey = await password({
1085
+ message: "Enter your OpenRouter API key:",
1086
+ mask: "*"
1087
+ });
1088
+ credentials = { type: "api_key", apiKey };
1089
+ model = await select({
1090
+ message: "Select model:",
1091
+ choices: OPENROUTER_MODELS.map((m) => ({
1092
+ value: m.value,
1093
+ name: m.label
1094
+ }))
1095
+ });
1096
+ break;
1097
+ }
1098
+ default:
1099
+ throw new Error(`Unknown provider: ${provider}`);
1100
+ }
1101
+ const config = {
1102
+ version: 1,
1103
+ provider,
1104
+ model,
1105
+ credentials,
1106
+ settings: {
1107
+ confirmBeforeExecute: true,
1108
+ historyEnabled: true,
1109
+ historyRetentionDays: 30,
1110
+ historyMaxEntries: 2e3,
1111
+ autoConfirmShortcuts: false
1112
+ }
1113
+ };
1114
+ const spinner = createSpinner("Validating credentials...").start();
1115
+ try {
1116
+ const providerInstance = createProvider(config);
1117
+ const valid = await providerInstance.validateCredentials();
1118
+ if (!valid) {
1119
+ spinner.fail("Invalid credentials");
1120
+ return false;
1121
+ }
1122
+ spinner.succeed("Credentials valid");
1123
+ } catch (err) {
1124
+ spinner.fail(
1125
+ `Validation failed: ${err instanceof Error ? err.message : "Unknown error"}`
1126
+ );
1127
+ return false;
1128
+ }
1129
+ saveConfig(config);
1130
+ console.log();
1131
+ logger.success("Configuration saved!");
1132
+ console.log(pc3.gray(` Provider: ${provider}`));
1133
+ console.log(pc3.gray(` Model: ${model}`));
1134
+ console.log();
1135
+ return true;
1136
+ }
1137
+
935
1138
  // src/cli/commands/AuthCommand.ts
936
1139
  var AuthCommand = class extends Command2 {
937
1140
  static paths = [["auth"], ["--auth"]];
@@ -940,167 +1143,34 @@ var AuthCommand = class extends Command2 {
940
1143
  examples: [["Configure AI provider", "$0 --auth"]]
941
1144
  });
942
1145
  async execute() {
943
- console.log(pc3.bold("\n Bashio Setup\n"));
944
- const provider = await select({
945
- message: "Select your AI provider:",
946
- choices: [
947
- {
948
- value: "claude",
949
- name: "Claude (Anthropic)",
950
- description: "Use Anthropic API key"
951
- },
952
- {
953
- value: "openai",
954
- name: "ChatGPT (OpenAI)",
955
- description: "Use OpenAI API key"
956
- },
957
- {
958
- value: "ollama",
959
- name: "Ollama (Local)",
960
- description: "Free, runs on your machine"
961
- },
962
- {
963
- value: "openrouter",
964
- name: "OpenRouter",
965
- description: "Pay per use, multiple models"
966
- }
967
- ]
968
- });
969
- let credentials;
970
- let model;
971
- switch (provider) {
972
- case "claude": {
973
- const apiKey = await password({
974
- message: "Enter your Anthropic API key:",
975
- mask: "*"
976
- });
977
- credentials = { type: "api_key", apiKey };
978
- model = await select({
979
- message: "Select model:",
980
- choices: CLAUDE_MODELS.map((m) => ({
981
- value: m.value,
982
- name: m.label
983
- }))
984
- });
985
- break;
986
- }
987
- case "openai": {
988
- const apiKey = await password({
989
- message: "Enter your OpenAI API key:",
990
- mask: "*"
991
- });
992
- credentials = { type: "api_key", apiKey };
993
- model = await select({
994
- message: "Select model:",
995
- choices: OPENAI_MODELS.map((m) => ({
996
- value: m.value,
997
- name: m.label
998
- }))
999
- });
1000
- break;
1001
- }
1002
- case "ollama": {
1003
- const host = await input3({
1004
- message: "Ollama host:",
1005
- default: "http://localhost:11434"
1006
- });
1007
- credentials = { type: "local", host };
1008
- const spinner2 = createSpinner("Checking Ollama connection...").start();
1009
- const availableModels = await OllamaProvider.getAvailableModels(host);
1010
- if (availableModels.length === 0) {
1011
- spinner2.fail("Could not connect to Ollama or no models installed");
1012
- console.log(pc3.yellow("\nMake sure Ollama is running: ollama serve"));
1013
- console.log(pc3.yellow("Install a model: ollama pull llama3.2\n"));
1014
- return 1;
1015
- }
1016
- spinner2.succeed(`Found ${availableModels.length} models`);
1017
- const modelChoices = availableModels.map((m) => ({
1018
- value: m,
1019
- name: m
1020
- }));
1021
- model = await select({
1022
- message: "Select model:",
1023
- choices: modelChoices
1024
- });
1025
- break;
1026
- }
1027
- case "openrouter": {
1028
- const apiKey = await password({
1029
- message: "Enter your OpenRouter API key:",
1030
- mask: "*"
1031
- });
1032
- credentials = { type: "api_key", apiKey };
1033
- model = await select({
1034
- message: "Select model:",
1035
- choices: OPENROUTER_MODELS.map((m) => ({
1036
- value: m.value,
1037
- name: m.label
1038
- }))
1039
- });
1040
- break;
1041
- }
1042
- default:
1043
- throw new Error(`Unknown provider: ${provider}`);
1044
- }
1045
- const config = {
1046
- version: 1,
1047
- provider,
1048
- model,
1049
- credentials,
1050
- settings: {
1051
- confirmBeforeExecute: true,
1052
- historyEnabled: true,
1053
- historyRetentionDays: 30,
1054
- historyMaxEntries: 2e3,
1055
- autoConfirmShortcuts: false
1056
- }
1057
- };
1058
- const spinner = createSpinner("Validating credentials...").start();
1059
- try {
1060
- const providerInstance = createProvider(config);
1061
- const valid = await providerInstance.validateCredentials();
1062
- if (!valid) {
1063
- spinner.fail("Invalid credentials");
1064
- return 1;
1065
- }
1066
- spinner.succeed("Credentials valid");
1067
- } catch (err) {
1068
- spinner.fail(
1069
- `Validation failed: ${err instanceof Error ? err.message : "Unknown error"}`
1146
+ const success = await runAuthSetup();
1147
+ if (success) {
1148
+ console.log(
1149
+ pc4.green("You're all set! Try:"),
1150
+ pc4.cyan("b find all png files")
1070
1151
  );
1071
- return 1;
1152
+ console.log();
1072
1153
  }
1073
- saveConfig(config);
1074
- console.log();
1075
- logger.success("Configuration saved!");
1076
- console.log(pc3.gray(` Provider: ${provider}`));
1077
- console.log(pc3.gray(` Model: ${model}`));
1078
- console.log();
1079
- console.log(
1080
- pc3.green("You're all set! Try:"),
1081
- pc3.cyan("b find all png files")
1082
- );
1083
- console.log();
1084
- return 0;
1154
+ return success ? 0 : 1;
1085
1155
  }
1086
1156
  };
1087
1157
 
1088
1158
  // src/cli/commands/ClearHistoryCommand.ts
1089
1159
  import { confirm } from "@inquirer/prompts";
1090
1160
  import { Command as Command3, Option as Option2 } from "clipanion";
1091
- import pc5 from "picocolors";
1161
+ import pc6 from "picocolors";
1092
1162
 
1093
1163
  // src/utils/danger-ui.ts
1094
- import pc4 from "picocolors";
1164
+ import pc5 from "picocolors";
1095
1165
  var renderDangerBanner = (message, label = "DANGER") => {
1096
1166
  const labelText = ` ${label} `;
1097
1167
  const spacer = " ";
1098
1168
  const contentLength = labelText.length + spacer.length + message.length;
1099
1169
  const innerWidth = contentLength + 2;
1100
1170
  const border = "\u2500".repeat(innerWidth);
1101
- const top = pc4.red(` \u250C${border}\u2510`);
1102
- const middle = ` ${pc4.red("\u2502 ")}` + pc4.bgRed(pc4.white(labelText)) + pc4.red(`${spacer}${message}`) + pc4.red(" \u2502");
1103
- const bottom = pc4.red(` \u2514${border}\u2518`);
1171
+ const top = pc5.red(` \u250C${border}\u2510`);
1172
+ const middle = ` ${pc5.red("\u2502 ")}` + pc5.bgRed(pc5.white(labelText)) + pc5.red(`${spacer}${message}`) + pc5.red(" \u2502");
1173
+ const bottom = pc5.red(` \u2514${border}\u2518`);
1104
1174
  return [top, middle, bottom];
1105
1175
  };
1106
1176
 
@@ -1122,14 +1192,14 @@ var ClearHistoryCommand = class extends Command3 {
1122
1192
  });
1123
1193
  async execute() {
1124
1194
  if (!this.all && !this.olderThan) {
1125
- console.log(pc5.bold("\n Clear History\n"));
1126
- console.log(pc5.gray(" Options:"));
1127
- console.log(pc5.gray(" --all Clear all history"));
1195
+ console.log(pc6.bold("\n Clear History\n"));
1196
+ console.log(pc6.gray(" Options:"));
1197
+ console.log(pc6.gray(" --all Clear all history"));
1128
1198
  console.log(
1129
- pc5.gray(" --older-than N Clear entries older than N days")
1199
+ pc6.gray(" --older-than N Clear entries older than N days")
1130
1200
  );
1131
1201
  console.log();
1132
- console.log(pc5.dim(" Example: b --clear-history --older-than 30\n"));
1202
+ console.log(pc6.dim(" Example: b --clear-history --older-than 30\n"));
1133
1203
  return 1;
1134
1204
  }
1135
1205
  const currentCount = getHistoryCount();
@@ -1192,7 +1262,7 @@ var ClearHistoryCommand = class extends Command3 {
1192
1262
 
1193
1263
  // src/cli/commands/ConfigCommand.ts
1194
1264
  import { Command as Command4 } from "clipanion";
1195
- import pc6 from "picocolors";
1265
+ import pc7 from "picocolors";
1196
1266
  var ConfigCommand = class extends Command4 {
1197
1267
  static paths = [["config"], ["--config"]];
1198
1268
  static usage = Command4.Usage({
@@ -1202,7 +1272,7 @@ var ConfigCommand = class extends Command4 {
1202
1272
  async execute() {
1203
1273
  if (!configExists()) {
1204
1274
  logger.warn("Bashio is not configured yet.");
1205
- console.log(pc6.gray("Run 'b --auth' to set up your AI provider.\n"));
1275
+ console.log(pc7.gray("Run 'b --auth' to set up your AI provider.\n"));
1206
1276
  return 1;
1207
1277
  }
1208
1278
  const config = loadConfig();
@@ -1210,21 +1280,21 @@ var ConfigCommand = class extends Command4 {
1210
1280
  logger.error("Failed to load configuration.");
1211
1281
  return 1;
1212
1282
  }
1213
- console.log(pc6.bold("\n Bashio Configuration\n"));
1214
- console.log(` Provider: ${pc6.cyan(config.provider)}`);
1215
- console.log(` Model: ${pc6.cyan(config.model)}`);
1216
- console.log(` Auth: ${pc6.green("Configured")}`);
1283
+ console.log(pc7.bold("\n Bashio Configuration\n"));
1284
+ console.log(` Provider: ${pc7.cyan(config.provider)}`);
1285
+ console.log(` Model: ${pc7.cyan(config.model)}`);
1286
+ console.log(` Auth: ${pc7.green("Configured")}`);
1217
1287
  const settings = config.settings;
1218
1288
  console.log();
1219
- console.log(pc6.bold(" Settings"));
1289
+ console.log(pc7.bold(" Settings"));
1220
1290
  console.log(
1221
- ` History: ${settings?.historyEnabled !== false ? pc6.green("enabled") : pc6.gray("disabled")}`
1291
+ ` History: ${settings?.historyEnabled !== false ? pc7.green("enabled") : pc7.gray("disabled")}`
1222
1292
  );
1223
1293
  console.log(
1224
- ` Auto-confirm shortcuts: ${settings?.autoConfirmShortcuts ? pc6.green("enabled") : pc6.gray("disabled")}`
1294
+ ` Auto-confirm shortcuts: ${settings?.autoConfirmShortcuts ? pc7.green("enabled") : pc7.gray("disabled")}`
1225
1295
  );
1226
1296
  console.log();
1227
- console.log(pc6.gray(` Config file: ${getConfigPath()}`));
1297
+ console.log(pc7.gray(` Config file: ${getConfigPath()}`));
1228
1298
  console.log();
1229
1299
  return 0;
1230
1300
  }
@@ -1234,7 +1304,7 @@ var ConfigCommand = class extends Command4 {
1234
1304
  import * as readline from "readline";
1235
1305
  import { confirm as confirm2, input as input4 } from "@inquirer/prompts";
1236
1306
  import { Command as Command5, Option as Option3 } from "clipanion";
1237
- import pc7 from "picocolors";
1307
+ import pc8 from "picocolors";
1238
1308
 
1239
1309
  // src/core/executor.ts
1240
1310
  import { spawn } from "child_process";
@@ -1398,18 +1468,21 @@ var DefaultCommand = class extends Command5 {
1398
1468
  context
1399
1469
  );
1400
1470
  }
1401
- if (!configExists()) {
1402
- logger.warn("Bashio is not configured yet.");
1403
- console.log(pc7.gray("Run 'b --auth' to set up your AI provider.\n"));
1404
- return 1;
1405
- }
1406
- if (!config) {
1407
- logger.error("Failed to load configuration.");
1408
- console.log(pc7.gray("Run 'b --auth' to reconfigure.\n"));
1409
- return 1;
1471
+ let currentConfig = config;
1472
+ if (!configExists() || !currentConfig) {
1473
+ const success = await runAuthSetup();
1474
+ if (!success) {
1475
+ return 1;
1476
+ }
1477
+ console.log(pc8.green("Setup complete! Running your command...\n"));
1478
+ currentConfig = loadConfig();
1479
+ if (!currentConfig) {
1480
+ logger.error("Failed to load configuration after setup.");
1481
+ return 1;
1482
+ }
1410
1483
  }
1411
1484
  const queryText = this.query.join(" ").trim();
1412
- const provider = createProvider(config);
1485
+ const provider = createProvider(currentConfig);
1413
1486
  const spinner = createSpinner("Generating command...").start();
1414
1487
  let generatedCommand;
1415
1488
  try {
@@ -1436,41 +1509,41 @@ var DefaultCommand = class extends Command5 {
1436
1509
  });
1437
1510
  }
1438
1511
  showHelp() {
1439
- console.log(pc7.bold("\n Bashio - Natural language to shell commands\n"));
1512
+ console.log(pc8.bold("\n Bashio - Natural language to shell commands\n"));
1440
1513
  console.log(" Usage:");
1441
- console.log(pc7.cyan(" b <natural language query>"));
1442
- console.log(pc7.cyan(" b <shortcut> [arguments]"));
1514
+ console.log(pc8.cyan(" b <natural language query>"));
1515
+ console.log(pc8.cyan(" b <shortcut> [arguments]"));
1443
1516
  console.log();
1444
1517
  console.log(" Examples:");
1445
- console.log(pc7.gray(" b find all files larger than 100mb"));
1446
- console.log(pc7.gray(" b kill whatever is running on port 3000"));
1447
- console.log(pc7.gray(" b killport 3000") + pc7.cyan(" (shortcut)"));
1518
+ console.log(pc8.gray(" b find all files larger than 100mb"));
1519
+ console.log(pc8.gray(" b kill whatever is running on port 3000"));
1520
+ console.log(pc8.gray(" b killport 3000") + pc8.cyan(" (shortcut)"));
1448
1521
  console.log();
1449
1522
  console.log(" Commands:");
1450
- console.log(pc7.gray(" b --auth Configure AI provider"));
1523
+ console.log(pc8.gray(" b --auth Configure AI provider"));
1451
1524
  console.log(
1452
- pc7.gray(" b --config View current configuration")
1525
+ pc8.gray(" b --config View current configuration")
1453
1526
  );
1454
- console.log(pc7.gray(" b --model Change AI model"));
1455
- console.log(pc7.gray(" b --shortcuts List all shortcuts"));
1456
- console.log(pc7.gray(" b --add-shortcut Add a new shortcut"));
1457
- console.log(pc7.gray(" b --remove-shortcut Remove a shortcut"));
1458
- console.log(pc7.gray(" b --edit-shortcuts Edit shortcuts in editor"));
1527
+ console.log(pc8.gray(" b --model Change AI model"));
1528
+ console.log(pc8.gray(" b --shortcuts List all shortcuts"));
1529
+ console.log(pc8.gray(" b --add-shortcut Add a new shortcut"));
1530
+ console.log(pc8.gray(" b --remove-shortcut Remove a shortcut"));
1531
+ console.log(pc8.gray(" b --edit-shortcuts Edit shortcuts in editor"));
1459
1532
  console.log();
1460
1533
  console.log(" History & Stats:");
1461
- console.log(pc7.gray(" b --history View command history"));
1462
- console.log(pc7.gray(" b --stats View usage statistics"));
1463
- console.log(pc7.gray(" b --clear-history Clear command history"));
1464
- console.log(pc7.gray(" b --suggest-shortcuts Suggest new shortcuts"));
1534
+ console.log(pc8.gray(" b --history View command history"));
1535
+ console.log(pc8.gray(" b --stats View usage statistics"));
1536
+ console.log(pc8.gray(" b --clear-history Clear command history"));
1537
+ console.log(pc8.gray(" b --suggest-shortcuts Suggest new shortcuts"));
1465
1538
  console.log();
1466
- console.log(pc7.gray(" b --help Show help"));
1539
+ console.log(pc8.gray(" b --help Show help"));
1467
1540
  console.log();
1468
1541
  }
1469
1542
  async executeWithConfirmation(command, source, context) {
1470
1543
  let currentCommand = command;
1471
1544
  console.log();
1472
1545
  if (source === "shortcut" && context.shortcutName) {
1473
- console.log(pc7.gray(` [shortcut: ${context.shortcutName}]`));
1546
+ console.log(pc8.gray(` [shortcut: ${context.shortcutName}]`));
1474
1547
  }
1475
1548
  logger.command(currentCommand);
1476
1549
  console.log();
@@ -1479,7 +1552,7 @@ var DefaultCommand = class extends Command5 {
1479
1552
  if (action === "explain") {
1480
1553
  if (source === "shortcut") {
1481
1554
  console.log(
1482
- pc7.gray("\n This command comes from a shortcut, not AI.\n")
1555
+ pc8.gray("\n This command comes from a shortcut, not AI.\n")
1483
1556
  );
1484
1557
  } else {
1485
1558
  const explainConfig = loadConfig();
@@ -1492,8 +1565,8 @@ var DefaultCommand = class extends Command5 {
1492
1565
  const explanation = await provider.explainCommand(currentCommand);
1493
1566
  explainSpinner.stop();
1494
1567
  console.log();
1495
- console.log(pc7.bold(" Explanation:"));
1496
- console.log(pc7.gray(` ${explanation.split("\n").join("\n ")}`));
1568
+ console.log(pc8.bold(" Explanation:"));
1569
+ console.log(pc8.gray(` ${explanation.split("\n").join("\n ")}`));
1497
1570
  console.log();
1498
1571
  } catch {
1499
1572
  explainSpinner.fail("Failed to get explanation");
@@ -1555,7 +1628,7 @@ var DefaultCommand = class extends Command5 {
1555
1628
  if (danger) {
1556
1629
  console.log();
1557
1630
  if (context.shortcutName) {
1558
- console.log(pc7.gray(` [shortcut: ${context.shortcutName}]`));
1631
+ console.log(pc8.gray(` [shortcut: ${context.shortcutName}]`));
1559
1632
  }
1560
1633
  logger.command(command);
1561
1634
  console.log();
@@ -1618,13 +1691,13 @@ var DefaultCommand = class extends Command5 {
1618
1691
  console.log(line);
1619
1692
  }
1620
1693
  console.log();
1621
- console.log(pc7.yellow(" Reasons:"));
1694
+ console.log(pc8.yellow(" Reasons:"));
1622
1695
  for (const reason of reasons) {
1623
- console.log(pc7.yellow(` - ${reason}`));
1696
+ console.log(pc8.yellow(` - ${reason}`));
1624
1697
  }
1625
1698
  console.log();
1626
- console.log(pc7.gray(" Command:"));
1627
- console.log(pc7.cyan(` ${command}`));
1699
+ console.log(pc8.gray(" Command:"));
1700
+ console.log(pc8.cyan(` ${command}`));
1628
1701
  console.log();
1629
1702
  return confirm2({
1630
1703
  message: "Proceed with this command?",
@@ -1637,7 +1710,7 @@ var DefaultCommand = class extends Command5 {
1637
1710
  input: process.stdin,
1638
1711
  output: process.stdout
1639
1712
  });
1640
- process.stdout.write(`${pc7.green("?")} ${pc7.bold("Edit command:")} `);
1713
+ process.stdout.write(`${pc8.green("?")} ${pc8.bold("Edit command:")} `);
1641
1714
  rl.write(currentCommand);
1642
1715
  rl.on("line", (answer) => {
1643
1716
  rl.close();
@@ -1657,7 +1730,7 @@ var DefaultCommand = class extends Command5 {
1657
1730
  // src/cli/commands/EditShortcutsCommand.ts
1658
1731
  import { spawn as spawn2 } from "child_process";
1659
1732
  import { Command as Command6 } from "clipanion";
1660
- import pc8 from "picocolors";
1733
+ import pc9 from "picocolors";
1661
1734
  var EditShortcutsCommand = class extends Command6 {
1662
1735
  static paths = [["edit-shortcuts"], ["--edit-shortcuts"]];
1663
1736
  static usage = Command6.Usage({
@@ -1673,15 +1746,15 @@ var EditShortcutsCommand = class extends Command6 {
1673
1746
  const editor = process.env.EDITOR || process.env.VISUAL || this.getDefaultEditor();
1674
1747
  if (!editor) {
1675
1748
  logger.error("No editor found. Set $EDITOR environment variable.");
1676
- console.log(pc8.gray(`
1749
+ console.log(pc9.gray(`
1677
1750
  Example: export EDITOR=vim`));
1678
- console.log(pc8.gray(` Or: export EDITOR="code --wait"`));
1679
- console.log(pc8.gray(`
1751
+ console.log(pc9.gray(` Or: export EDITOR="code --wait"`));
1752
+ console.log(pc9.gray(`
1680
1753
  File location: ${filePath}
1681
1754
  `));
1682
1755
  return 1;
1683
1756
  }
1684
- console.log(pc8.gray(`
1757
+ console.log(pc9.gray(`
1685
1758
  Opening ${filePath} in ${editor}...
1686
1759
  `));
1687
1760
  return new Promise((resolve) => {
@@ -1703,7 +1776,7 @@ var EditShortcutsCommand = class extends Command6 {
1703
1776
  });
1704
1777
  child.on("error", (err) => {
1705
1778
  logger.error(`Failed to open editor: ${err.message}`);
1706
- console.log(pc8.gray(`
1779
+ console.log(pc9.gray(`
1707
1780
  File location: ${filePath}
1708
1781
  `));
1709
1782
  resolve(1);
@@ -1724,10 +1797,10 @@ var EditShortcutsCommand = class extends Command6 {
1724
1797
 
1725
1798
  // src/cli/commands/HistoryCommand.ts
1726
1799
  import { Command as Command7, Option as Option4 } from "clipanion";
1727
- import pc10 from "picocolors";
1800
+ import pc11 from "picocolors";
1728
1801
 
1729
1802
  // src/utils/table.ts
1730
- import pc9 from "picocolors";
1803
+ import pc10 from "picocolors";
1731
1804
  var BOX = {
1732
1805
  topLeft: "\u250C",
1733
1806
  topRight: "\u2510",
@@ -1784,7 +1857,7 @@ function wrapText(text, maxWidth) {
1784
1857
  function renderTable(options) {
1785
1858
  const { columns, data, title } = options;
1786
1859
  if (title) {
1787
- console.log(pc9.bold(`
1860
+ console.log(pc10.bold(`
1788
1861
  ${title}
1789
1862
  `));
1790
1863
  }
@@ -1793,20 +1866,20 @@ function renderTable(options) {
1793
1866
  topBorder += BOX.horizontal.repeat(columns[i].width + 2);
1794
1867
  topBorder += i < columns.length - 1 ? BOX.topMid : BOX.topRight;
1795
1868
  }
1796
- console.log(pc9.dim(topBorder));
1869
+ console.log(pc10.dim(topBorder));
1797
1870
  let headerRow = ` ${BOX.vertical}`;
1798
1871
  for (const col of columns) {
1799
- headerRow += ` ${pc9.bold(padString(col.header, col.width, col.align))} ${BOX.vertical}`;
1872
+ headerRow += ` ${pc10.bold(padString(col.header, col.width, col.align))} ${BOX.vertical}`;
1800
1873
  }
1801
1874
  console.log(
1802
- pc9.dim(headerRow.slice(0, 2)) + headerRow.slice(2, -1) + pc9.dim(BOX.vertical)
1875
+ pc10.dim(headerRow.slice(0, 2)) + headerRow.slice(2, -1) + pc10.dim(BOX.vertical)
1803
1876
  );
1804
1877
  let headerSep = ` ${BOX.leftMid}`;
1805
1878
  for (let i = 0; i < columns.length; i++) {
1806
1879
  headerSep += BOX.horizontal.repeat(columns[i].width + 2);
1807
1880
  headerSep += i < columns.length - 1 ? BOX.midMid : BOX.rightMid;
1808
1881
  }
1809
- console.log(pc9.dim(headerSep));
1882
+ console.log(pc10.dim(headerSep));
1810
1883
  for (const row of data) {
1811
1884
  const wrappedColumns = columns.map((col) => {
1812
1885
  const value = row[col.key] || "";
@@ -1826,7 +1899,7 @@ function renderTable(options) {
1826
1899
  dataRow += ` ${cellValue} ${BOX.vertical}`;
1827
1900
  }
1828
1901
  console.log(
1829
- pc9.dim(dataRow.slice(0, 2)) + dataRow.slice(2, -1) + pc9.dim(BOX.vertical)
1902
+ pc10.dim(dataRow.slice(0, 2)) + dataRow.slice(2, -1) + pc10.dim(BOX.vertical)
1830
1903
  );
1831
1904
  }
1832
1905
  }
@@ -1835,7 +1908,7 @@ function renderTable(options) {
1835
1908
  bottomBorder += BOX.horizontal.repeat(columns[i].width + 2);
1836
1909
  bottomBorder += i < columns.length - 1 ? BOX.bottomMid : BOX.bottomRight;
1837
1910
  }
1838
- console.log(pc9.dim(bottomBorder));
1911
+ console.log(pc10.dim(bottomBorder));
1839
1912
  }
1840
1913
 
1841
1914
  // src/cli/commands/HistoryCommand.ts
@@ -1867,10 +1940,10 @@ var HistoryCommand = class extends Command7 {
1867
1940
  title = "Recent Command History";
1868
1941
  }
1869
1942
  if (entries.length === 0) {
1870
- console.log(pc10.bold(`
1943
+ console.log(pc11.bold(`
1871
1944
  ${title}
1872
1945
  `));
1873
- console.log(pc10.gray(" No history entries found.\n"));
1946
+ console.log(pc11.gray(" No history entries found.\n"));
1874
1947
  return 0;
1875
1948
  }
1876
1949
  const data = entries.map((entry, index) => ({
@@ -1885,32 +1958,32 @@ var HistoryCommand = class extends Command7 {
1885
1958
  title,
1886
1959
  columns: [
1887
1960
  { header: "#", key: "num", width: 3, align: "right" },
1888
- { header: "Command", key: "command", width: 35, color: pc10.yellow },
1889
- { header: "Query", key: "query", width: 25, color: pc10.gray },
1961
+ { header: "Command", key: "command", width: 35, color: pc11.yellow },
1962
+ { header: "Query", key: "query", width: 25, color: pc11.gray },
1890
1963
  {
1891
1964
  header: "Source",
1892
1965
  key: "source",
1893
1966
  width: 8,
1894
- color: (v) => v.trim() === "ai" ? pc10.blue(v) : pc10.cyan(v)
1967
+ color: (v) => v.trim() === "ai" ? pc11.blue(v) : pc11.cyan(v)
1895
1968
  },
1896
1969
  { header: "Status", key: "status", width: 10 },
1897
1970
  { header: "Time", key: "time", width: 10 }
1898
1971
  ],
1899
1972
  data
1900
1973
  });
1901
- console.log(pc10.dim(`
1974
+ console.log(pc11.dim(`
1902
1975
  Showing ${entries.length} entries
1903
1976
  `));
1904
1977
  return 0;
1905
1978
  }
1906
1979
  getStatusDisplay(entry) {
1907
1980
  if (entry.executed === 0) {
1908
- return `${pc10.gray("\u25CB")} skipped`;
1981
+ return `${pc11.gray("\u25CB")} skipped`;
1909
1982
  }
1910
1983
  if (entry.exitCode === 0) {
1911
- return `${pc10.green("\u2713")} success`;
1984
+ return `${pc11.green("\u2713")} success`;
1912
1985
  }
1913
- return `${pc10.red("\u2717")} exit:${entry.exitCode}`;
1986
+ return `${pc11.red("\u2717")} exit:${entry.exitCode}`;
1914
1987
  }
1915
1988
  getTimeAgo(isoString) {
1916
1989
  const date = new Date(isoString);
@@ -1931,7 +2004,7 @@ var HistoryCommand = class extends Command7 {
1931
2004
  import * as readline2 from "readline";
1932
2005
  import { select as select2 } from "@inquirer/prompts";
1933
2006
  import { Command as Command8 } from "clipanion";
1934
- import pc11 from "picocolors";
2007
+ import pc12 from "picocolors";
1935
2008
  var selectWithEsc = async (config) => {
1936
2009
  const controller = new AbortController();
1937
2010
  const input6 = process.stdin;
@@ -1971,7 +2044,7 @@ var ModelCommand = class extends Command8 {
1971
2044
  if (!configExists()) {
1972
2045
  logger.warn("Bashio is not configured yet.");
1973
2046
  console.log(
1974
- pc11.gray("Run 'b --auth' to set up your AI provider first.\n")
2047
+ pc12.gray("Run 'b --auth' to set up your AI provider first.\n")
1975
2048
  );
1976
2049
  return 1;
1977
2050
  }
@@ -1980,10 +2053,10 @@ var ModelCommand = class extends Command8 {
1980
2053
  logger.error("Failed to load configuration.");
1981
2054
  return 1;
1982
2055
  }
1983
- console.log(pc11.bold("\n Change AI Model\n"));
1984
- console.log(pc11.gray(` Current provider: ${config.provider}`));
1985
- console.log(pc11.gray(` Current model: ${config.model}`));
1986
- console.log(pc11.dim(" Press Esc to cancel\n"));
2056
+ console.log(pc12.bold("\n Change AI Model\n"));
2057
+ console.log(pc12.gray(` Current provider: ${config.provider}`));
2058
+ console.log(pc12.gray(` Current model: ${config.model}`));
2059
+ console.log(pc12.dim(" Press Esc to cancel\n"));
1987
2060
  let newModel;
1988
2061
  try {
1989
2062
  switch (config.provider) {
@@ -2016,7 +2089,7 @@ var ModelCommand = class extends Command8 {
2016
2089
  spinner.stop();
2017
2090
  if (availableModels.length === 0) {
2018
2091
  logger.warn("No models found. Make sure Ollama is running.");
2019
- console.log(pc11.gray("\n Install a model: ollama pull llama3.2\n"));
2092
+ console.log(pc12.gray("\n Install a model: ollama pull llama3.2\n"));
2020
2093
  return 1;
2021
2094
  }
2022
2095
  newModel = await selectWithEsc({
@@ -2046,7 +2119,7 @@ var ModelCommand = class extends Command8 {
2046
2119
  }
2047
2120
  } catch (error) {
2048
2121
  if (isPromptExit(error)) {
2049
- console.log(pc11.dim("\n Cancelled.\n"));
2122
+ console.log(pc12.dim("\n Cancelled.\n"));
2050
2123
  return 0;
2051
2124
  }
2052
2125
  throw error;
@@ -2067,7 +2140,7 @@ var ModelCommand = class extends Command8 {
2067
2140
  // src/cli/commands/RemoveShortcutCommand.ts
2068
2141
  import { confirm as confirm3 } from "@inquirer/prompts";
2069
2142
  import { Command as Command9, Option as Option5 } from "clipanion";
2070
- import pc12 from "picocolors";
2143
+ import pc13 from "picocolors";
2071
2144
  var RemoveShortcutCommand = class extends Command9 {
2072
2145
  static paths = [["remove-shortcut"], ["--remove-shortcut"]];
2073
2146
  static usage = Command9.Usage({
@@ -2082,9 +2155,9 @@ var RemoveShortcutCommand = class extends Command9 {
2082
2155
  return 1;
2083
2156
  }
2084
2157
  console.log();
2085
- console.log(pc12.gray(` Template: ${shortcut.template}`));
2158
+ console.log(pc13.gray(` Template: ${shortcut.template}`));
2086
2159
  if (shortcut.description) {
2087
- console.log(pc12.gray(` Description: ${shortcut.description}`));
2160
+ console.log(pc13.gray(` Description: ${shortcut.description}`));
2088
2161
  }
2089
2162
  console.log();
2090
2163
  for (const line of renderDangerBanner(
@@ -2110,7 +2183,7 @@ var RemoveShortcutCommand = class extends Command9 {
2110
2183
 
2111
2184
  // src/cli/commands/ShortcutsCommand.ts
2112
2185
  import { Command as Command10 } from "clipanion";
2113
- import pc13 from "picocolors";
2186
+ import pc14 from "picocolors";
2114
2187
  var ShortcutsCommand = class extends Command10 {
2115
2188
  static paths = [["shortcuts"], ["--shortcuts"]];
2116
2189
  static usage = Command10.Usage({
@@ -2121,8 +2194,8 @@ var ShortcutsCommand = class extends Command10 {
2121
2194
  const shortcuts = listShortcuts();
2122
2195
  const names = Object.keys(shortcuts);
2123
2196
  if (names.length === 0) {
2124
- console.log(pc13.yellow("\n No shortcuts configured yet.\n"));
2125
- console.log(pc13.gray(" Add one with: b --add-shortcut\n"));
2197
+ console.log(pc14.yellow("\n No shortcuts configured yet.\n"));
2198
+ console.log(pc14.gray(" Add one with: b --add-shortcut\n"));
2126
2199
  return 0;
2127
2200
  }
2128
2201
  const data = names.map((name) => {
@@ -2136,19 +2209,19 @@ var ShortcutsCommand = class extends Command10 {
2136
2209
  renderTable({
2137
2210
  title: "Your Shortcuts",
2138
2211
  columns: [
2139
- { header: "Name", key: "name", width: 15, color: pc13.cyan },
2212
+ { header: "Name", key: "name", width: 15, color: pc14.cyan },
2140
2213
  {
2141
2214
  header: "Command Template",
2142
2215
  key: "template",
2143
2216
  width: 45,
2144
- color: pc13.white
2217
+ color: pc14.white
2145
2218
  },
2146
- { header: "Arguments", key: "args", width: 15, color: pc13.gray }
2219
+ { header: "Arguments", key: "args", width: 15, color: pc14.gray }
2147
2220
  ],
2148
2221
  data
2149
2222
  });
2150
2223
  console.log(
2151
- pc13.dim(
2224
+ pc14.dim(
2152
2225
  `
2153
2226
  Total: ${names.length} shortcut${names.length === 1 ? "" : "s"}
2154
2227
  `
@@ -2160,7 +2233,7 @@ var ShortcutsCommand = class extends Command10 {
2160
2233
 
2161
2234
  // src/cli/commands/StatsCommand.ts
2162
2235
  import { Command as Command11 } from "clipanion";
2163
- import pc14 from "picocolors";
2236
+ import pc15 from "picocolors";
2164
2237
  var StatsCommand = class extends Command11 {
2165
2238
  static paths = [["--stats"]];
2166
2239
  static usage = Command11.Usage({
@@ -2169,7 +2242,7 @@ var StatsCommand = class extends Command11 {
2169
2242
  });
2170
2243
  async execute() {
2171
2244
  const stats = getStats();
2172
- console.log(pc14.bold("\n Bashio Usage Statistics\n"));
2245
+ console.log(pc15.bold("\n Bashio Usage Statistics\n"));
2173
2246
  renderTable({
2174
2247
  title: "Overview",
2175
2248
  columns: [
@@ -2216,13 +2289,13 @@ var StatsCommand = class extends Command11 {
2216
2289
  title: "Most Used Commands",
2217
2290
  columns: [
2218
2291
  { header: "#", key: "rank", width: 3, align: "right" },
2219
- { header: "Command", key: "command", width: 45, color: pc14.cyan },
2292
+ { header: "Command", key: "command", width: 45, color: pc15.cyan },
2220
2293
  { header: "Uses", key: "uses", width: 8, align: "right" },
2221
2294
  {
2222
2295
  header: "Source",
2223
2296
  key: "source",
2224
2297
  width: 10,
2225
- color: (v) => v.trim() === "ai" ? pc14.blue(v) : pc14.cyan(v)
2298
+ color: (v) => v.trim() === "ai" ? pc15.blue(v) : pc15.cyan(v)
2226
2299
  }
2227
2300
  ],
2228
2301
  data: stats.topQueries.map((q, i) => ({
@@ -2241,7 +2314,7 @@ var StatsCommand = class extends Command11 {
2241
2314
  // src/cli/commands/SuggestShortcutsCommand.ts
2242
2315
  import { confirm as confirm4, input as input5 } from "@inquirer/prompts";
2243
2316
  import { Command as Command12, Option as Option6 } from "clipanion";
2244
- import pc15 from "picocolors";
2317
+ import pc16 from "picocolors";
2245
2318
 
2246
2319
  // src/core/learning.ts
2247
2320
  function suggestShortcutNameFromCommand(command) {
@@ -2314,35 +2387,35 @@ var SuggestShortcutsCommand = class extends Command12 {
2314
2387
  async execute() {
2315
2388
  const thresholdNum = Number.parseInt(this.threshold, 10) || 3;
2316
2389
  const suggestions = getShortcutSuggestions(thresholdNum);
2317
- console.log(pc15.bold("\n Shortcut Suggestions\n"));
2390
+ console.log(pc16.bold("\n Shortcut Suggestions\n"));
2318
2391
  if (suggestions.length === 0) {
2319
2392
  console.log(
2320
- pc15.gray(
2393
+ pc16.gray(
2321
2394
  " No suggestions yet. Use Bashio more to get personalized suggestions."
2322
2395
  )
2323
2396
  );
2324
2397
  console.log(
2325
- pc15.dim(` (Commands need to be used ${thresholdNum}+ times)
2398
+ pc16.dim(` (Commands need to be used ${thresholdNum}+ times)
2326
2399
  `)
2327
2400
  );
2328
2401
  return 0;
2329
2402
  }
2330
2403
  console.log(
2331
- pc15.dim(
2404
+ pc16.dim(
2332
2405
  ` Found ${suggestions.length} frequently used commands that could be shortcuts:
2333
2406
  `
2334
2407
  )
2335
2408
  );
2336
2409
  for (const suggestion of suggestions) {
2337
- console.log(pc15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2338
- console.log(` ${pc15.yellow("Command:")} ${pc15.cyan(suggestion.command)}`);
2410
+ console.log(pc16.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2411
+ console.log(` ${pc16.yellow("Command:")} ${pc16.cyan(suggestion.command)}`);
2339
2412
  console.log(
2340
- ` ${pc15.yellow("Used:")} ${pc15.white(suggestion.useCount.toString())} times`
2413
+ ` ${pc16.yellow("Used:")} ${pc16.white(suggestion.useCount.toString())} times`
2341
2414
  );
2342
2415
  console.log();
2343
2416
  const action = await this.promptCreateShortcut();
2344
2417
  if (action === "exit") {
2345
- console.log(pc15.dim("\n Exiting suggestions.\n"));
2418
+ console.log(pc16.dim("\n Exiting suggestions.\n"));
2346
2419
  return 0;
2347
2420
  }
2348
2421
  if (action === "yes") {
@@ -2383,7 +2456,7 @@ var SuggestShortcutsCommand = class extends Command12 {
2383
2456
  markPatternAsSuggested(suggestion.command);
2384
2457
  logger.success(`\u2713 Created shortcut: ${finalName}`);
2385
2458
  console.log(
2386
- pc15.dim(
2459
+ pc16.dim(
2387
2460
  ` Usage: b ${finalName}${args2.length > 0 ? ` ${args2.map((a) => `<${a}>`).join(" ")}` : ""}`
2388
2461
  )
2389
2462
  );
@@ -2393,7 +2466,7 @@ var SuggestShortcutsCommand = class extends Command12 {
2393
2466
  console.log();
2394
2467
  }
2395
2468
  }
2396
- console.log(pc15.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
2469
+ console.log(pc16.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
2397
2470
  return 0;
2398
2471
  }
2399
2472
  async promptCreateShortcut() {
@@ -2439,58 +2512,74 @@ var SuggestShortcutsCommand = class extends Command12 {
2439
2512
  const boxWidth = 50;
2440
2513
  const line = "\u2500".repeat(boxWidth);
2441
2514
  console.log();
2442
- console.log(pc15.red(` \u250C${line}\u2510`));
2515
+ console.log(pc16.red(` \u250C${line}\u2510`));
2443
2516
  console.log(
2444
- pc15.red(" \u2502") + pc15.bold(pc15.red(" \u274C Shortcut Already Exists")) + " ".repeat(boxWidth - 27) + pc15.red("\u2502")
2517
+ pc16.red(" \u2502") + pc16.bold(pc16.red(" \u274C Shortcut Already Exists")) + " ".repeat(boxWidth - 27) + pc16.red("\u2502")
2445
2518
  );
2446
- console.log(pc15.red(` \u251C${line}\u2524`));
2519
+ console.log(pc16.red(` \u251C${line}\u2524`));
2447
2520
  const nameLabel = " Name: ";
2448
2521
  const nameValue = name;
2449
2522
  const namePadding = boxWidth - nameLabel.length - nameValue.length + 2;
2450
2523
  console.log(
2451
- pc15.red(" \u2502") + pc15.gray(nameLabel) + pc15.white(nameValue) + " ".repeat(Math.max(0, namePadding)) + pc15.red("\u2502")
2524
+ pc16.red(" \u2502") + pc16.gray(nameLabel) + pc16.white(nameValue) + " ".repeat(Math.max(0, namePadding)) + pc16.red("\u2502")
2452
2525
  );
2453
2526
  const cmdLabel = " Command: ";
2454
2527
  const cmdValue = shortcut.template.length > 35 ? `${shortcut.template.slice(0, 32)}...` : shortcut.template;
2455
2528
  const cmdPadding = boxWidth - cmdLabel.length - cmdValue.length + 2;
2456
2529
  console.log(
2457
- pc15.red(" \u2502") + pc15.gray(cmdLabel) + pc15.cyan(cmdValue) + " ".repeat(Math.max(0, cmdPadding)) + pc15.red("\u2502")
2530
+ pc16.red(" \u2502") + pc16.gray(cmdLabel) + pc16.cyan(cmdValue) + " ".repeat(Math.max(0, cmdPadding)) + pc16.red("\u2502")
2458
2531
  );
2459
2532
  if (shortcut.args && shortcut.args.length > 0) {
2460
2533
  const argsLabel = " Args: ";
2461
2534
  const argsValue = shortcut.args.join(", ");
2462
2535
  const argsPadding = boxWidth - argsLabel.length - argsValue.length + 2;
2463
2536
  console.log(
2464
- pc15.red(" \u2502") + pc15.gray(argsLabel) + pc15.yellow(argsValue) + " ".repeat(Math.max(0, argsPadding)) + pc15.red("\u2502")
2537
+ pc16.red(" \u2502") + pc16.gray(argsLabel) + pc16.yellow(argsValue) + " ".repeat(Math.max(0, argsPadding)) + pc16.red("\u2502")
2465
2538
  );
2466
2539
  }
2467
- console.log(pc15.red(` \u2514${line}\u2518`));
2540
+ console.log(pc16.red(` \u2514${line}\u2518`));
2468
2541
  console.log();
2469
- console.log(pc15.yellow(" Please enter a different name:\n"));
2542
+ console.log(pc16.yellow(" Please enter a different name:\n"));
2470
2543
  }
2471
2544
  };
2472
2545
 
2473
2546
  // src/cli/index.ts
2474
2547
  var pkg = {
2475
2548
  name: "bashio",
2476
- version: "0.5.1"
2549
+ version: "0.7.0"
2477
2550
  };
2478
2551
  var notifier = updateNotifier({
2479
2552
  pkg,
2480
2553
  updateCheckInterval: 1e3 * 60 * 60 * 24
2481
2554
  // 1 day
2482
2555
  });
2483
- notifier.notify({
2484
- message: "Bashio update available: {currentVersion} \u2192 {latestVersion}\nRun: {updateCommand}",
2485
- boxenOptions: {
2486
- padding: 1,
2487
- margin: 1,
2488
- borderStyle: "round",
2489
- borderColor: "cyan",
2490
- title: "\u2728 Update Available",
2491
- titleAlignment: "center"
2492
- }
2493
- });
2556
+ if (notifier.update) {
2557
+ const { current, latest } = notifier.update;
2558
+ const cyan = pc17.cyan;
2559
+ const width = 44;
2560
+ const ansiRegex = new RegExp(
2561
+ `${String.fromCharCode(27)}\\[[0-9;]*[a-zA-Z]`,
2562
+ "g"
2563
+ );
2564
+ const stripAnsi2 = (str) => str.replace(ansiRegex, "");
2565
+ const visibleLength = (str) => stripAnsi2(str).length;
2566
+ const pad = (text, len) => {
2567
+ const padding = len - visibleLength(text);
2568
+ return text + " ".repeat(Math.max(0, padding));
2569
+ };
2570
+ const line = (content) => cyan(" \u2502") + pad(content, width) + cyan("\u2502");
2571
+ console.log();
2572
+ console.log(cyan(` \u250C${"\u2500".repeat(width)}\u2510`));
2573
+ console.log(line(""));
2574
+ console.log(line(pc17.bold(" Bashio Update Available!")));
2575
+ console.log(line(""));
2576
+ console.log(line(` ${pc17.dim(current)} \u2192 ${pc17.green(pc17.bold(latest))}`));
2577
+ console.log(line(""));
2578
+ console.log(line(` Run: ${pc17.cyan("npm i -g bashio@latest")}`));
2579
+ console.log(line(""));
2580
+ console.log(cyan(` \u2514${"\u2500".repeat(width)}\u2518`));
2581
+ console.log();
2582
+ }
2494
2583
  initDatabase();
2495
2584
  if (shouldRunCleanup()) {
2496
2585
  const config = loadConfig();