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 +366 -277
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
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
|
-
|
|
1152
|
+
console.log();
|
|
1072
1153
|
}
|
|
1073
|
-
|
|
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
|
|
1161
|
+
import pc6 from "picocolors";
|
|
1092
1162
|
|
|
1093
1163
|
// src/utils/danger-ui.ts
|
|
1094
|
-
import
|
|
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 =
|
|
1102
|
-
const middle = ` ${
|
|
1103
|
-
const bottom =
|
|
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(
|
|
1126
|
-
console.log(
|
|
1127
|
-
console.log(
|
|
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
|
-
|
|
1199
|
+
pc6.gray(" --older-than N Clear entries older than N days")
|
|
1130
1200
|
);
|
|
1131
1201
|
console.log();
|
|
1132
|
-
console.log(
|
|
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
|
|
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(
|
|
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(
|
|
1214
|
-
console.log(` Provider: ${
|
|
1215
|
-
console.log(` Model: ${
|
|
1216
|
-
console.log(` Auth: ${
|
|
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(
|
|
1289
|
+
console.log(pc7.bold(" Settings"));
|
|
1220
1290
|
console.log(
|
|
1221
|
-
` History: ${settings?.historyEnabled !== false ?
|
|
1291
|
+
` History: ${settings?.historyEnabled !== false ? pc7.green("enabled") : pc7.gray("disabled")}`
|
|
1222
1292
|
);
|
|
1223
1293
|
console.log(
|
|
1224
|
-
` Auto-confirm shortcuts: ${settings?.autoConfirmShortcuts ?
|
|
1294
|
+
` Auto-confirm shortcuts: ${settings?.autoConfirmShortcuts ? pc7.green("enabled") : pc7.gray("disabled")}`
|
|
1225
1295
|
);
|
|
1226
1296
|
console.log();
|
|
1227
|
-
console.log(
|
|
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
|
|
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
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
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(
|
|
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(
|
|
1512
|
+
console.log(pc8.bold("\n Bashio - Natural language to shell commands\n"));
|
|
1440
1513
|
console.log(" Usage:");
|
|
1441
|
-
console.log(
|
|
1442
|
-
console.log(
|
|
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(
|
|
1446
|
-
console.log(
|
|
1447
|
-
console.log(
|
|
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(
|
|
1523
|
+
console.log(pc8.gray(" b --auth Configure AI provider"));
|
|
1451
1524
|
console.log(
|
|
1452
|
-
|
|
1525
|
+
pc8.gray(" b --config View current configuration")
|
|
1453
1526
|
);
|
|
1454
|
-
console.log(
|
|
1455
|
-
console.log(
|
|
1456
|
-
console.log(
|
|
1457
|
-
console.log(
|
|
1458
|
-
console.log(
|
|
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(
|
|
1462
|
-
console.log(
|
|
1463
|
-
console.log(
|
|
1464
|
-
console.log(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
1496
|
-
console.log(
|
|
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(
|
|
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(
|
|
1694
|
+
console.log(pc8.yellow(" Reasons:"));
|
|
1622
1695
|
for (const reason of reasons) {
|
|
1623
|
-
console.log(
|
|
1696
|
+
console.log(pc8.yellow(` - ${reason}`));
|
|
1624
1697
|
}
|
|
1625
1698
|
console.log();
|
|
1626
|
-
console.log(
|
|
1627
|
-
console.log(
|
|
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(`${
|
|
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
|
|
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(
|
|
1749
|
+
console.log(pc9.gray(`
|
|
1677
1750
|
Example: export EDITOR=vim`));
|
|
1678
|
-
console.log(
|
|
1679
|
-
console.log(
|
|
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(
|
|
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(
|
|
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
|
|
1800
|
+
import pc11 from "picocolors";
|
|
1728
1801
|
|
|
1729
1802
|
// src/utils/table.ts
|
|
1730
|
-
import
|
|
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(
|
|
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(
|
|
1869
|
+
console.log(pc10.dim(topBorder));
|
|
1797
1870
|
let headerRow = ` ${BOX.vertical}`;
|
|
1798
1871
|
for (const col of columns) {
|
|
1799
|
-
headerRow += ` ${
|
|
1872
|
+
headerRow += ` ${pc10.bold(padString(col.header, col.width, col.align))} ${BOX.vertical}`;
|
|
1800
1873
|
}
|
|
1801
1874
|
console.log(
|
|
1802
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
1943
|
+
console.log(pc11.bold(`
|
|
1871
1944
|
${title}
|
|
1872
1945
|
`));
|
|
1873
|
-
console.log(
|
|
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:
|
|
1889
|
-
{ header: "Query", key: "query", width: 25, color:
|
|
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" ?
|
|
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(
|
|
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 `${
|
|
1981
|
+
return `${pc11.gray("\u25CB")} skipped`;
|
|
1909
1982
|
}
|
|
1910
1983
|
if (entry.exitCode === 0) {
|
|
1911
|
-
return `${
|
|
1984
|
+
return `${pc11.green("\u2713")} success`;
|
|
1912
1985
|
}
|
|
1913
|
-
return `${
|
|
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
|
|
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
|
-
|
|
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(
|
|
1984
|
-
console.log(
|
|
1985
|
-
console.log(
|
|
1986
|
-
console.log(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
2158
|
+
console.log(pc13.gray(` Template: ${shortcut.template}`));
|
|
2086
2159
|
if (shortcut.description) {
|
|
2087
|
-
console.log(
|
|
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
|
|
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(
|
|
2125
|
-
console.log(
|
|
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:
|
|
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:
|
|
2217
|
+
color: pc14.white
|
|
2145
2218
|
},
|
|
2146
|
-
{ header: "Arguments", key: "args", width: 15, color:
|
|
2219
|
+
{ header: "Arguments", key: "args", width: 15, color: pc14.gray }
|
|
2147
2220
|
],
|
|
2148
2221
|
data
|
|
2149
2222
|
});
|
|
2150
2223
|
console.log(
|
|
2151
|
-
|
|
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
|
|
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(
|
|
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:
|
|
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" ?
|
|
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
|
|
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(
|
|
2390
|
+
console.log(pc16.bold("\n Shortcut Suggestions\n"));
|
|
2318
2391
|
if (suggestions.length === 0) {
|
|
2319
2392
|
console.log(
|
|
2320
|
-
|
|
2393
|
+
pc16.gray(
|
|
2321
2394
|
" No suggestions yet. Use Bashio more to get personalized suggestions."
|
|
2322
2395
|
)
|
|
2323
2396
|
);
|
|
2324
2397
|
console.log(
|
|
2325
|
-
|
|
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
|
-
|
|
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(
|
|
2338
|
-
console.log(` ${
|
|
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
|
-
` ${
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
2515
|
+
console.log(pc16.red(` \u250C${line}\u2510`));
|
|
2443
2516
|
console.log(
|
|
2444
|
-
|
|
2517
|
+
pc16.red(" \u2502") + pc16.bold(pc16.red(" \u274C Shortcut Already Exists")) + " ".repeat(boxWidth - 27) + pc16.red("\u2502")
|
|
2445
2518
|
);
|
|
2446
|
-
console.log(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
2540
|
+
console.log(pc16.red(` \u2514${line}\u2518`));
|
|
2468
2541
|
console.log();
|
|
2469
|
-
console.log(
|
|
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.
|
|
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.
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
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();
|