Skip to content

Commit 8d34019

Browse files
authored
Merge pull request #13 from ebenjs/feature-error-handling
added erreor handling
2 parents a31d0d7 + 5dc913f commit 8d34019

File tree

8 files changed

+182
-13
lines changed

8 files changed

+182
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
<!-- generated by git-cliff -->

cliff.toml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# git-cliff ~ default configuration file
2+
# https://git-cliff.org/docs/configuration
3+
#
4+
# Lines starting with "#" are comments.
5+
# Configuration options are organized into tables and keys.
6+
# See documentation for more information on available options.
7+
8+
[changelog]
9+
# changelog header
10+
header = """
11+
# Changelog\n
12+
All notable changes to this project will be documented in this file.\n
13+
"""
14+
# template for the changelog body
15+
# https://keats.github.io/tera/docs/#introduction
16+
body = """
17+
{% if version %}\
18+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
19+
{% else %}\
20+
## [unreleased]
21+
{% endif %}\
22+
{% for group, commits in commits | group_by(attribute="group") %}
23+
### {{ group | upper_first }}
24+
{% for commit in commits %}
25+
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\
26+
{% endfor %}
27+
{% endfor %}\n
28+
"""
29+
# remove the leading and trailing whitespace from the template
30+
trim = true
31+
# changelog footer
32+
footer = """
33+
<!-- generated by git-cliff -->
34+
"""
35+
# postprocessors
36+
postprocessors = [
37+
# { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
38+
]
39+
[git]
40+
# parse the commits based on https://www.conventionalcommits.org
41+
conventional_commits = true
42+
# filter out the commits that are not conventional
43+
filter_unconventional = true
44+
# process each line of a commit as an individual commit
45+
split_commits = false
46+
# regex for preprocessing the commit messages
47+
commit_preprocessors = [
48+
# { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"}, # replace issue numbers
49+
]
50+
# regex for parsing and grouping commits
51+
commit_parsers = [
52+
{ message = "^feat", group = "Features" },
53+
{ message = "^fix", group = "Bug Fixes" },
54+
{ message = "^doc", group = "Documentation" },
55+
{ message = "^perf", group = "Performance" },
56+
{ message = "^refactor", group = "Refactor" },
57+
{ message = "^style", group = "Styling" },
58+
{ message = "^test", group = "Testing" },
59+
{ message = "^chore\\(release\\): prepare for", skip = true },
60+
{ message = "^chore\\(deps\\)", skip = true },
61+
{ message = "^chore\\(pr\\)", skip = true },
62+
{ message = "^chore\\(pull\\)", skip = true },
63+
{ message = "^chore|ci", group = "Miscellaneous Tasks" },
64+
{ body = ".*security", group = "Security" },
65+
{ message = "^revert", group = "Revert" },
66+
]
67+
# protect breaking changes from being skipped due to matching a skipping commit_parser
68+
protect_breaking_commits = false
69+
# filter out the commits that are not matched by commit parsers
70+
filter_commits = false
71+
# regex for matching git tags
72+
tag_pattern = "v[0-9].*"
73+
74+
# regex for skipping tags
75+
skip_tags = "v0.1.0-beta.1"
76+
# regex for ignoring tags
77+
ignore_tags = ""
78+
# sort the tags topologically
79+
topo_order = false
80+
# sort the commits inside sections by oldest/newest order
81+
sort_commits = "oldest"
82+
# limit the number of commits included in the changelog.
83+
# limit_commits = 42

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ebenjs/gpt-shell",
3-
"version": "1.0.0",
3+
"version": "1.1.1",
44
"description": "Chat-GPT in the console",
55
"main": "index.js",
66
"type": "module",

src/main.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,26 @@ import { sendOpenApiRequest } from "./request-helper.js";
44
import { logger } from "./utilities/logger.js";
55

66
export const ask = (prompt) => {
7-
sendOpenApiRequest(prompt).then((data) => {
8-
logger.logResponse(data.choices[0].message.content);
9-
});
7+
sendOpenApiRequest(prompt)
8+
.then((data) => {
9+
logger.logResponse(data.choices[0].message.content);
10+
})
11+
.catch((error) => {
12+
logger.logError(JSON.parse(error.message));
13+
});
1014
};
1115

1216
export const configure = (args) => {
17+
let existingConfig = null;
18+
if (fs.existsSync("./.gpt-shell-config.json")) {
19+
existingConfig = JSON.parse(fs.readFileSync("./.gpt-shell-config.json"));
20+
}
21+
1322
const { apikey, model, url } = args;
1423
const config = {
15-
apikey: apikey || process.env.OPENAI_API_KEY,
16-
model: model || process.env.OPENAI_DEFAULT_MODEL,
17-
url: url || process.env.OPENAI_API_URL,
24+
apikey: apikey || existingConfig?.apikey || process.env.OPENAI_API_KEY,
25+
model: model || existingConfig?.model || process.env.OPENAI_DEFAULT_MODEL,
26+
url: url || existingConfig?.url || process.env.OPENAI_API_URL,
1827
};
1928

2029
fs.writeFileSync("./.gpt-shell-config.json", JSON.stringify(config, null, 2));

src/request-helper.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,26 @@ export const sendOpenApiRequest = async (requestPrompt) => {
66
logger.logPrompt(requestPrompt + "\n");
77
const animation = loadingAnimation();
88

9-
console.log(getConfig());
9+
const config = getConfig();
10+
11+
if (config.status === "error") {
12+
clearInterval(animation);
13+
process.stdout.write("\r");
14+
throw new Error(JSON.stringify(config.errors));
15+
}
1016

1117
const requestOptions = {
1218
method: "POST",
1319
headers: {
1420
"Content-Type": "application/json",
15-
Authorization: "Bearer " + getConfig().apikey,
21+
Authorization: "Bearer " + getConfig().config.apikey,
1622
},
1723
body: JSON.stringify({
18-
model: getConfig().model,
24+
model: getConfig().config.model,
1925
messages: [{ role: "user", content: requestPrompt }],
2026
}),
2127
};
22-
const response = await fetch(getConfig().url, requestOptions);
28+
const response = await fetch(getConfig().config.url, requestOptions);
2329
const data = await response.json();
2430

2531
clearInterval(animation);

src/utilities/error-handling.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { logger } from "./logger.js";
2+
3+
let aggregatedErrors = [];
4+
5+
export const addError = (error) => {
6+
aggregatedErrors.push(error);
7+
};
8+
9+
export const getErrors = () => aggregatedErrors;
10+
11+
export const clearErrors = () => (aggregatedErrors = []);
12+
13+
export const logErrors = () => {
14+
aggregatedErrors.forEach((error) => {
15+
logger.logError(error);
16+
});
17+
};
18+
19+
export const throwError = (message) => {
20+
throw new Error(message);
21+
};

src/utilities/get-config.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
11
import fs from "fs";
2+
import { getErrors, addError } from "./error-handling.js";
3+
4+
const checkForRequiredEnvironmentVariables = (config) => {
5+
if (!config.apikey) {
6+
addError("OPENAI_API_KEY is not defined");
7+
}
8+
9+
if (!config.model) {
10+
addError("OPENAI_MODEL is not defined");
11+
}
12+
13+
if (!config.url) {
14+
addError("OPENAI_API_URL is not defined");
15+
}
16+
17+
return !getErrors().length > 0;
18+
};
219

320
export const getConfig = () => {
421
if (fs.existsSync("./.gpt-shell-config.json")) {
522
const config = JSON.parse(fs.readFileSync("./.gpt-shell-config.json"));
6-
return config;
23+
if (!checkForRequiredEnvironmentVariables(config)) {
24+
return { status: "error", errors: getErrors() };
25+
}
26+
27+
return { status: "success", config: config };
728
}
829

930
const config = {
@@ -12,5 +33,9 @@ export const getConfig = () => {
1233
url: process.env.OPENAI_API_URL,
1334
};
1435

15-
return config;
36+
if (!checkForRequiredEnvironmentVariables(config)) {
37+
return { status: "error", errors: getErrors() };
38+
}
39+
40+
return { status: "success", config: config };
1641
};

src/utilities/logger.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ const customPromptLoggerFormat = winston.format.printf(({ message }) => {
99
return `${chalk.blueBright("[gpt-shell-prompt]")} : ${message}`;
1010
});
1111

12+
const customErrorLoggerFormat = winston.format.printf(({ message }) => {
13+
return chalk.redBright("[error] : " + message);
14+
});
15+
16+
const customPrefixedErrorLoggerFormat = (prefix) => {
17+
return winston.format.printf(({ message }) => {
18+
return chalk.redBright(prefix + message);
19+
});
20+
};
21+
1222
const _logger = winston.createLogger({
1323
level: "info",
1424
transports: [
@@ -35,8 +45,18 @@ const logResponse = (response) => {
3545
_logger.info(response);
3646
};
3747

48+
const logError = (errors) => {
49+
_logger.format = customErrorLoggerFormat;
50+
_logger.error("Some configuration errors were found");
51+
errors.forEach((error, index) => {
52+
_logger.format = customPrefixedErrorLoggerFormat(`[${index}] `);
53+
_logger.error(error);
54+
});
55+
};
56+
3857
export const logger = {
3958
default: _logger,
4059
logPrompt,
4160
logResponse,
61+
logError,
4262
};

0 commit comments

Comments
 (0)