Compare commits

..

230 Commits

Author SHA1 Message Date
di-sukharev
bf931b0c3c chore: update package and action descriptions to better reflect the purpose of the project and remove unnecessary details
feat: add keywords to package and action descriptions to improve searchability and discoverability of the project
feat: update deploy script in package.json to include version bump and publish to npm registry with latest tag
2023-05-21 16:15:13 +08:00
di-sukharev
f687709abe build 2023-05-21 15:57:29 +08:00
di-sukharev
a969d9819e build 2023-05-21 15:53:32 +08:00
di-sukharev
d0d4b2d11d build 2023-05-21 15:35:01 +08:00
di-sukharev
d03f16c6ee build 2023-05-21 15:10:18 +08:00
di-sukharev
925f004f28 build 2023-05-21 15:10:18 +08:00
di-sukharev
f7f878b6dd build 2023-05-21 15:10:18 +08:00
di-sukharev
2f923f94ea build 2023-05-21 15:10:18 +08:00
di-sukharev
60410e6404 build 2023-05-21 15:10:18 +08:00
di-sukharev
f42e1ff9a3 build 2023-05-21 15:10:18 +08:00
di-sukharev
0c92feb3ae build 2023-05-21 15:10:18 +08:00
di-sukharev
8ae293e947 build 2023-05-21 15:10:18 +08:00
di-sukharev
68746fa17d build 2023-05-21 15:10:18 +08:00
di-sukharev
1aeed7c9ca build 2023-05-21 15:10:18 +08:00
di-sukharev
867a0158ed build 2023-05-21 15:10:18 +08:00
di-sukharev
942c2d8612 build 2023-05-21 15:10:18 +08:00
di-sukharev
2932a1fc28 build 2023-05-21 15:10:18 +08:00
di-sukharev
fef923a099 build 2023-05-21 15:10:18 +08:00
di-sukharev
851c8baff1 build 2023-05-21 15:10:18 +08:00
di-sukharev
f5517ed59f build 2023-05-21 15:10:18 +08:00
di-sukharev
3c9aabd239 build 2023-05-21 15:10:18 +08:00
di-sukharev
f506c1287c build 2023-05-21 15:10:18 +08:00
di-sukharev
1012e3948a build 2023-05-21 15:10:18 +08:00
di-sukharev
f6e2d439a4 build 2023-05-21 15:10:18 +08:00
di-sukharev
bcdc976c49 build 2023-05-21 15:10:18 +08:00
di-sukharev
ed9729e327 build 2023-05-21 15:10:18 +08:00
di-sukharev
1bdcc8adae build 2023-05-21 15:10:18 +08:00
di-sukharev
efdd98318e build 2023-05-21 15:10:18 +08:00
di-sukharev
af2e25dce0 build 2023-05-21 15:10:18 +08:00
di-sukharev
a0961f899e build 2023-05-21 15:10:18 +08:00
di-sukharev
5065c75730 build 2023-05-21 15:10:18 +08:00
di-sukharev
447a938a48 build 2023-05-21 15:10:18 +08:00
di-sukharev
b4ecce224b build 2023-05-21 15:10:18 +08:00
di-sukharev
07f07e5e18 build 2023-05-21 15:10:18 +08:00
di-sukharev
cd89054f0f build 2023-05-21 15:10:18 +08:00
di-sukharev
430f08a705 build 2023-05-21 15:10:17 +08:00
di-sukharev
65c9c729de build 2023-05-21 15:10:17 +08:00
di-sukharev
6c3bcdb6f9 build 2023-05-21 15:10:17 +08:00
di-sukharev
730bebe8f5 build 2023-05-21 15:10:17 +08:00
di-sukharev
2265e92e84 build 2023-05-21 15:10:17 +08:00
di-sukharev
939deca46f build 2023-05-21 15:10:17 +08:00
di-sukharev
d715685f0d build 2023-05-21 15:10:17 +08:00
di-sukharev
f2cf084bbf build 2023-05-21 15:10:17 +08:00
di-sukharev
eb4da47642 build 2023-05-21 15:10:17 +08:00
di-sukharev
b475d16c82 build 2023-05-21 15:10:17 +08:00
di-sukharev
fee4371bc6 build 2023-05-21 15:10:17 +08:00
di-sukharev
69e398ea2f build 2023-05-21 15:10:17 +08:00
di-sukharev
de4b2bd74a build 2023-05-21 15:10:17 +08:00
di-sukharev
b8c1e8c5ba build 2023-05-21 15:10:17 +08:00
di-sukharev
b0363fa638 build 2023-05-21 15:10:17 +08:00
di-sukharev
223a587765 build 2023-05-21 15:10:17 +08:00
di-sukharev
22f37e0da5 build 2023-05-21 15:10:17 +08:00
di-sukharev
2c5a37525c build 2023-05-21 15:10:17 +08:00
di-sukharev
9c87d8f7b8 build 2023-05-21 15:10:17 +08:00
di-sukharev
8f50c021c4 build 2023-05-21 15:10:17 +08:00
di-sukharev
9fb6946a6b build 2023-05-21 15:10:17 +08:00
di-sukharev
03210f16d0 build 2023-05-21 15:10:17 +08:00
di-sukharev
cec6890525 build 2023-05-21 15:10:17 +08:00
di-sukharev
3d199eb6d3 build 2023-05-21 15:10:17 +08:00
di-sukharev
a17462e9a2 build 2023-05-21 15:10:17 +08:00
di-sukharev
cfa5462cbd build 2023-05-21 15:10:17 +08:00
di-sukharev
c30d34e1b5 build 2023-05-21 15:10:17 +08:00
di-sukharev
b2ef14c586 build 2023-05-21 15:10:17 +08:00
di-sukharev
88f367d662 build 2023-05-21 15:10:17 +08:00
di-sukharev
32df5d5fe1 build 2023-05-21 15:10:17 +08:00
di-sukharev
13afc81858 build 2023-05-21 15:10:17 +08:00
di-sukharev
bf430b23db build 2023-05-21 15:10:17 +08:00
di-sukharev
820365dd06 build 2023-05-21 15:10:17 +08:00
di-sukharev
dd39ef2473 build 2023-05-21 15:10:17 +08:00
di-sukharev
5b0e3bf061 build 2023-05-21 15:10:17 +08:00
di-sukharev
a7da40f151 build 2023-05-21 15:10:17 +08:00
di-sukharev
23037a3988 build 2023-05-21 15:10:17 +08:00
di-sukharev
66eb8e1008 build 2023-05-21 15:10:17 +08:00
di-sukharev
90361b65ee build 2023-05-21 15:10:17 +08:00
di-sukharev
b7938e3488 build 2023-05-21 15:10:17 +08:00
di-sukharev
13db5f4498 build 2023-05-21 15:10:17 +08:00
di-sukharev
885b653e2e build 2023-05-21 15:10:17 +08:00
di-sukharev
f7ca45540a build 2023-05-21 15:10:17 +08:00
di-sukharev
10c89ded6e build 2023-05-21 15:10:17 +08:00
di-sukharev
542a53f3db build 2023-05-21 15:10:17 +08:00
di-sukharev
3b32ef3608 build 2023-05-21 15:10:17 +08:00
di-sukharev
6d23333305 build 2023-05-21 15:10:17 +08:00
di-sukharev
bd65b100a5 build 2023-05-21 15:10:16 +08:00
di-sukharev
b1e099f4bc build 2023-05-21 15:10:16 +08:00
di-sukharev
cfe891fec4 build 2023-05-21 15:10:16 +08:00
di-sukharev
fd5bccbcb1 build 2023-05-21 15:10:16 +08:00
di-sukharev
cbd2138552 build 2023-05-21 15:10:16 +08:00
di-sukharev
432fe88e82 build 2023-05-21 15:10:16 +08:00
di-sukharev
0f0c976b08 build 2023-05-21 15:10:16 +08:00
di-sukharev
06574056d7 build 2023-05-21 15:10:16 +08:00
di-sukharev
39e6568d73 build 2023-05-21 15:10:16 +08:00
di-sukharev
1867c96f22 build 2023-05-21 15:10:16 +08:00
di-sukharev
7f83ff9943 build 2023-05-21 15:10:16 +08:00
di-sukharev
f6749f38e9 build 2023-05-21 15:10:16 +08:00
di-sukharev
bb2dc327a7 build 2023-05-21 15:10:16 +08:00
di-sukharev
c45d5aa12b build 2023-05-21 15:10:16 +08:00
di-sukharev
17e80e0b4f build 2023-05-21 15:10:16 +08:00
di-sukharev
8acaf4c860 build 2023-05-21 15:10:16 +08:00
di-sukharev
20a2f68389 build 2023-05-21 15:10:16 +08:00
di-sukharev
25f791cfd5 build 2023-05-21 15:10:16 +08:00
di-sukharev
c9eb947148 build 2023-05-21 15:10:16 +08:00
di-sukharev
d6219478fc build 2023-05-21 15:10:16 +08:00
di-sukharev
be06729ad8 build 2023-05-21 15:10:16 +08:00
di-sukharev
f2680f2bf3 build 2023-05-21 15:10:16 +08:00
di-sukharev
f7afa94c9e build 2023-05-21 15:10:16 +08:00
di-sukharev
291cb2b5b6 build 2023-05-21 15:10:16 +08:00
di-sukharev
4552cc49a8 build 2023-05-21 15:10:16 +08:00
di-sukharev
8d09fe0b7c build 2023-05-21 15:10:16 +08:00
di-sukharev
490d209c64 build 2023-05-21 15:10:16 +08:00
di-sukharev
52a71728d4 build 2023-05-21 15:10:16 +08:00
di-sukharev
ffdf45dc17 build 2023-05-21 15:10:16 +08:00
di-sukharev
211ad20c34 build 2023-05-21 15:10:16 +08:00
di-sukharev
17802dcbd6 build 2023-05-21 15:10:16 +08:00
di-sukharev
053e1da0f1 removed logs 2023-05-21 15:10:16 +08:00
di-sukharev
666760d412 fixed 2023-05-21 15:10:16 +08:00
di-sukharev
c0e183797f build 2023-05-21 15:10:16 +08:00
di-sukharev
3dfa1e4a33 build 2023-05-21 15:10:16 +08:00
di-sukharev
2f5ea33f0f build 2023-05-21 15:10:16 +08:00
di-sukharev
476136a391 build 2023-05-21 15:10:16 +08:00
di-sukharev
fe555c66ed fix(api.ts): handle unknown errors in catch block and log error message if available
refactor(github-action.ts): remove console.log statements and improve readability of code
2023-05-21 15:10:16 +08:00
di-sukharev
431e10cb54 build 2023-05-21 15:10:16 +08:00
di-sukharev
e356b5dcf3 added log 2023-05-21 15:10:16 +08:00
di-sukharev
9fea9e244c build 2023-05-21 15:10:16 +08:00
di-sukharev
b16271a62f build 2023-05-21 15:10:16 +08:00
di-sukharev
87c978a58a build 2023-05-21 15:10:16 +08:00
di-sukharev
d6caa0c73c refactor(github-action.ts): remove unused spinner import and usage
refactor(github-action.ts): remove unused retries parameter from run function
refactor(github-action.ts): remove unused core.info call
refactor(github-action.ts): remove unused intro call
refactor(github-action.ts): remove unused spinner.stop call and replace with outro call
2023-05-21 15:10:16 +08:00
di-sukharev
efe0172f2d chore(action.yml): update node version to 16 to match the latest LTS version 2023-05-21 15:10:16 +08:00
di-sukharev
ba9503142c build 2023-05-21 15:10:16 +08:00
di-sukharev
b87faf0096 chore(README.md): update OpenCommit configuration variables to match new naming convention
fix(api.ts): change config variable names to match new naming convention
fix(api.ts): increase default max_tokens to 500
fix(commit.ts): stop spinner after commit message is generated

fix(config.ts): change config keys to use OCO prefix to avoid conflicts with other libraries
feat(config.ts): add support for OCO_EXCLUDE environment variable to exclude files from being committed
fix(prepare-commit-msg-hook.ts): change OPENAI_API_KEY to OCO_OPENAI_API_KEY to match new config keys
fix(generateCommitMessageFromGitDiff.ts): change config keys to use OCO prefix to match new config keys
2023-05-21 15:10:16 +08:00
di-sukharev
2681db1635 fix(action.yml): update path to main file to reflect new build output directory 2023-05-21 15:10:16 +08:00
di-sukharev
462798d7d2 remove /out from .gitignore to ba able to run opencommit via github action from other repos 2023-05-21 15:10:16 +08:00
di-sukharev
1abe655e00 chore(README.md): add instructions to setup OpenCommit as a Github Action
chore(action.yml): update description of the Github Action
feat(github-action.ts): add support for pattern input to only improve messages that match the regexp, e.g. ^fix$
2023-05-21 15:10:16 +08:00
di-sukharev
177a219ccb feat(commit.ts): add try-catch block to handle errors and show proper error messages
fix(commit.ts): fix indentation and formatting
feat(commit.ts): add support for selecting remote to push to when there are multiple remotes
fix(prepare-commit-msg-hook.ts): remove unnecessary if-else block and improve formatting
2023-05-21 15:10:16 +08:00
di-sukharev
373c90c760 refactor(commit.ts, prepare-commit-msg-hook.ts, generateCommitMessageFromGitDiff.ts, github-action.ts): rename generateCommitMessageWithChatCompletion to generateCommitMessageByDiff to improve semantics and consistency with other function names
feat(github-action.ts): add support for retrying the action in case of failure to improve robustness
2023-05-21 15:10:15 +08:00
di-sukharev
7652116e77 feat(github-action.ts): add support for pull_request events and improve event handling
refactor(github-action.ts): extract types for ListCommitsResponse, CommitsData, and CommitsArray
fix(github-action.ts): update improveCommitMessagesWithRebase function to accept CommitsArray type
2023-05-21 15:10:15 +08:00
di-sukharev
707d90de1c feat(package.json): add @octokit/webhooks-schemas and @octokit/webhooks-types for better webhook handling
refactor(github-action.ts): replace child_process with execa for better command execution
refactor(github-action.ts): use octokit/webhooks-types for improved typing and handling of GitHub events
feat(github-action.ts): add support for improving commit messages on push and pull_request events
2023-05-21 15:10:15 +08:00
di-sukharev
7615b95261 feat(action.yml): add OpenCommit GitHub Action configuration
feat(package.json): add @actions/core and @actions/github dependencies
feat(src/github-action.ts): create GitHub Action to check and replace 'oc' in commit messages with AI-generated messages
2023-05-21 15:10:15 +08:00
di-sukharev
54006826f8 2.0.15 2023-05-19 13:47:51 +08:00
di-sukharev
f674e2d99a 2.0.14 2023-05-19 13:47:45 +08:00
di-sukharev
8140322c32 refactor(prepare-commit-msg-hook.ts): remove console.log statement for commitSource variable to reduce noise in logs 2023-05-19 13:47:26 +08:00
di-sukharev
1cb8d580bb refactor(api.ts): reorder variable declarations to improve readability and semantics
refactor(prepare-commit-msg-hook.ts): remove console.log statement used for debugging purposes
2023-05-19 13:46:33 +08:00
di-sukharev
8daa3ca130 Merge remote-tracking branch 'origin/dev' 2023-05-19 13:42:43 +08:00
Takuya Ono
13015a9033 🐛 fix(config.ts): convert string value to number in OPENAI_MAX_TOKENS validator (#162)
The OPENAI_MAX_TOKENS validator now converts a string value to a number before validating it. This ensures that the validator works correctly when a string value is passed in.
2023-05-07 17:16:32 +08:00
Takuya Ono
7b90b6a287 🐛 fix(config.ts): error message for OPENAI_BASE_PATH validation (#164)
The error message for the OPENAI_BASE_PATH validation has been updated
to be more descriptive and helpful. The message now reads "Must be
string" instead of "${value} is not supported yet". This change improves
the clarity of the error message and makes it easier for developers to
understand what went wrong when the validation fails.
2023-05-07 17:15:55 +08:00
di-sukharev
598881a41c 2.0.13 2023-05-04 16:38:35 +08:00
di-sukharev
1080544631 2.0.12 2023-05-04 16:38:28 +08:00
di-sukharev
de68e6cc7a docs(README.md): add instructions for configuring openAI maxTokens and BASE_PATH parameters to customize API usage 2023-05-04 16:38:02 +08:00
di-sukharev
5addb7df25 2.0.11 2023-05-04 14:29:11 +08:00
di-sukharev
e447575980 2.0.10 2023-05-04 14:29:05 +08:00
di-sukharev
ffebbc6e1b docs: update opencommit-example.png to reflect recent changes in UI 2023-05-04 14:28:55 +08:00
di-sukharev
dab0f58d14 2.0.9 2023-05-04 12:52:22 +08:00
di-sukharev
226e21c28f 2.0.8 2023-05-04 12:52:14 +08:00
di-sukharev
0bb89abccc Merge remote-tracking branch 'origin/dev' 2023-05-04 12:51:35 +08:00
Tanoshii
ad70a90b1f Update commit.ts (#154)
* fixed type
2023-05-04 12:50:09 +08:00
di-sukharev
4deaf56e5a 2.0.7 2023-05-04 12:42:30 +08:00
di-sukharev
7c1fc10248 2.0.6 2023-05-04 12:42:24 +08:00
di-sukharev
0c25a9e32c Merge branch 'dev' 2023-05-04 12:41:35 +08:00
Juan José López Lira
3f5df6ef7c Bugfix/increase tokens (#132)
* feat(api.ts): add support for OPENAI_MAX_TOKENS environment variable
feat(config.ts): add OPENAI_MAX_TOKENS to CONFIG_KEYS and configValidators

* 2.0.2

* 2.0.3

* docs(README.md): add GPT-4 usage instructions and mention the cost difference compared to GPT-3.5-turbo

---------

Co-authored-by: di-sukharev <dim.sukharev@gmail.com>
2023-05-04 12:33:06 +08:00
di-sukharev
6cb85e40e9 2.0.5 2023-04-28 15:36:53 +08:00
di-sukharev
ba82d4d476 2.0.4 2023-04-28 15:36:45 +08:00
di-sukharev
9bf2ed34a5 docs(README.md): add GPT-4 usage instructions and mention the cost difference compared to GPT-3.5-turbo 2023-04-28 15:35:40 +08:00
di-sukharev
f6ab25ed1b 2.0.3 2023-04-28 15:31:54 +08:00
di-sukharev
83abd5ffd6 2.0.2 2023-04-28 15:31:46 +08:00
di-sukharev
42c26cbaaa fix(generateCommitMessageFromGitDiff.ts): update content to include WHAT and WHY in commit message instructions
fix(i18n/en.json): update commitFix and commitFeat messages to include reasons for changes
2023-04-28 15:31:10 +08:00
di-sukharev
51613c2aea feat(api.ts, config.ts): add support for custom model selection in OpenAi class
feat(config.ts): add model validation in configValidators
2023-04-28 15:29:32 +08:00
Sukharev
f04757f8af Revert "Suggest adding 'Edit' option to the Yes/No confirmation #53 (#70)" (#146)
This reverts commit 70f048672c.
2023-04-28 14:25:29 +08:00
Joshua Hamlet
70f048672c Suggest adding 'Edit' option to the Yes/No confirmation #53 (#70) 2023-04-28 14:22:45 +08:00
di-sukharev
a8a548ba5a 2.0.1 2023-04-28 14:15:39 +08:00
di-sukharev
eb09d5f4f6 Merge remote-tracking branch 'origin/dev' 2023-04-28 14:13:49 +08:00
Devrim Mazlum
801f6a9e7a feat(i18n): add support for Turkish (Türkçe) language (tr) (#110)
* feat(index.ts): Turkish language support

* feat(tr.json): Turkish language support
2023-04-17 01:14:34 +08:00
zenobit
b4f1bbdfe0 🌐 chore(i18n): add Czech language (#127)
* 🌐 chore(i18n): add Czech language

* 📦 chore(package-lock.json): aktualizace balíčku @dqbd/tiktoken na verzi 1.0.6
Byl aktualizován balíček @dqbd/tiktoken na verzi 1.0.6, což zahrnuje opravy chyb a zlepšení výkonu.
2023-04-17 01:09:51 +08:00
di-sukharev
1ecad09e44 chore(package.json): update package version from 1.1.51 to 2.0.0 2023-04-06 12:42:46 +08:00
di-sukharev
c57b5e394d 1.1.51 2023-04-06 12:30:14 +08:00
di-sukharev
8100d9beb8 1.1.50 2023-04-06 12:30:06 +08:00
di-sukharev
84997faea2 feat(package.json): add 'oco' alias for the 'opencommit' command line tool 2023-04-06 12:29:56 +08:00
di-sukharev
8f60345008 docs: update README.md
- Update information about the OpenAI model used by OpenCommit and its cost
2023-04-05 13:13:45 +08:00
Sukharev
c148048452 Create dependency-review.yml 2023-04-05 13:05:36 +08:00
Sukharev
add8855bf9 Create codeql.yml 2023-04-05 13:05:09 +08:00
di-sukharev
0cc5be10f2 1.1.49 2023-04-05 13:01:36 +08:00
di-sukharev
30d2d9d284 1.1.48 2023-04-05 13:01:28 +08:00
di-sukharev
d69fa6c2d7 Merge branch 'master' of github.com:di-sukharev/opencommit 2023-04-05 13:01:17 +08:00
di-sukharev
bf3b8c6ded chore(.yml): remove Close Stale Issues action from workflow. 2023-04-05 13:00:57 +08:00
Sukharev
f851ea1fff Create stale.yml 2023-04-05 13:00:29 +08:00
di-sukharev
d6cbaf5f5f refactor(tokenCount.ts): remove commented out code and unused import statement 2023-04-05 12:55:45 +08:00
di-sukharev
220d0b292f 1.1.47 2023-04-05 12:55:22 +08:00
di-sukharev
e5d3c8d4ff 1.1.46 2023-04-05 12:55:16 +08:00
di-sukharev
cbc8d61f99 feat(.yml): add GitHub Action to close stale issues using actions/stale@v4.1.1 2023-04-05 12:54:38 +08:00
di-sukharev
7fd357e78e 1.1.45 2023-04-05 12:45:01 +08:00
di-sukharev
5837d1fa2e 1.1.44 2023-04-05 12:44:54 +08:00
di-sukharev
36f282d8a5 Merge branch 'dev' 2023-04-05 12:44:30 +08:00
Raymond
9f65c450e3 build(esbuild.config.js): add esbuild configuration file and move build command to it (#82)
feat(package.json): add @dqbd/tiktoken dependency
fix(tokenCount.ts): uncomment Tiktoken import and encoding, and return token length instead of an approximation
2023-04-05 12:42:07 +08:00
di-sukharev
d5f53fec5a 1.1.43 2023-04-05 12:36:17 +08:00
di-sukharev
b6651a4c47 1.1.42 2023-04-05 12:36:13 +08:00
di-sukharev
2b10dc089c refactor(githook.ts): remove unused platform variable and switch statement
fix(githook.ts): change DEFAULT_SYMLINK_URL to use relative path instead of absolute path
2023-04-05 12:35:23 +08:00
di-sukharev
a5e60ac23c 1.1.41 2023-04-05 12:32:13 +08:00
di-sukharev
e519752938 1.1.40 2023-04-05 12:32:09 +08:00
di-sukharev
1ba5e20228 chore(TODO.md): add task to set max commit message length to improve commit message quality 2023-04-05 12:31:42 +08:00
di-sukharev
4103bafc4f chore(TODO.md): add task to try setting max commit message length 2023-04-05 12:30:01 +08:00
kimlym
5a9b460033 feat(api.ts): add support for OPENAI_BASE_PATH configuration variable (#80)
feat(config.ts): add OPENAI_BASE_PATH configuration key and validator function

Co-authored-by: yiminglu <yiming.lu@mioying.com>
2023-04-05 12:26:02 +08:00
l2D
3364289034 feat(i18n): add support for Thai (ไทย) language (th) (#117)
* feat(i18n): add Thai language support and translations for commit messages
2023-04-05 12:24:44 +08:00
Matt
5185f3365c Feature work with husky (#47) (#79)
* refactor(cli.ts): call isHookCalled function asynchronously

feat(githook.ts): add support for git core hooks path and fallback to default symlink url if not found

feat(utils/git.ts): add getCoreHooksPath function to retrieve the path of the core hooks directory.

* refactor(githook.ts): remove console.log statement from hookCommand function

* feat(prepare-commit-msg-hook.ts): add isStageAllFlag parameter to prepareCommitMessageHook function to stage all changes if flag is true

* refactor(githook.ts): use path.join to join path segments instead of string concatenation
style(githook.ts): format code with prettier
2023-04-01 13:29:22 +08:00
di-sukharev
17ed061f73 Merge branch 'dev' of github.com:di-sukharev/opencommit into dev 2023-04-01 13:25:57 +08:00
di-sukharev
06fa6daa72 1.1.39 2023-04-01 13:24:57 +08:00
di-sukharev
af457473be 1.1.38 2023-04-01 13:24:33 +08:00
di-sukharev
33b418e399 1.1.37 2023-04-01 13:24:28 +08:00
di-sukharev
7e5ed6de0b refactor(commit.ts): add push command when no remotes are found
refactor(githook.ts): simplify switch statement by removing comments and adding inline comments
2023-04-01 13:24:15 +08:00
Erick Amorim
6ba0f97163 Add support for the Android platform (#105) 2023-04-01 13:18:52 +08:00
Matt
0d559d4499 Issue templates (#78)
* Create bug.yaml

* adding issue templates

* Create featureRequest.yaml
2023-03-31 18:12:43 +08:00
zankyr
686f876cb0 [STYLE] Update commit messages using proper Italian language (#96)
* style(it.json): update commit message language to use proper Italian grammar and spelling
2023-03-31 18:11:39 +08:00
Manato
acf3e450ae chore(i18n): update Japanese translation for commit messages (#98)
Updated the Japanese translation for commit messages to reflect the changes made in the previous commit. The commitFix message now correctly states that the port variable was changed from lowercase 'port' to uppercase 'PORT'. The commitFeat message now correctly states that support for the 'process.env.PORT' environment variable was added. The commitDescription message explains that the use of the constant 'PORT' for the port variable provides consistency in naming conventions, and that the support for the 'process.env.PORT' environment variable allows the application to be more flexible and run on any available port specified by the environment variable.
2023-03-31 18:11:06 +08:00
Karol Lassak
8be30a734d feat(i18n): add support for Polish language (#102)
* feat(i18n): add support for Polish language
2023-03-31 18:09:17 +08:00
di-sukharev
e2f68b7256 refactor(githook.ts): replace comments with line breaks for switch cases in platform switch statement 2023-03-30 19:53:14 +08:00
di-sukharev
eacc750952 1.1.36 2023-03-30 15:15:03 +08:00
di-sukharev
3fe57537ad 1.1.35 2023-03-30 15:15:00 +08:00
di-sukharev
db9cff1ae1 refactor(githook.ts): add switch statement to determine path separator based on platform
fix(githook.ts): change path separator to use the determined separator variable
2023-03-30 15:14:43 +08:00
di-sukharev
1c29b91408 1.1.34 2023-03-30 15:01:20 +08:00
di-sukharev
425eeef732 1.1.33 2023-03-30 15:01:15 +08:00
di-sukharev
52c396eb16 feat(commit.ts): add support for aborting git push command if user chooses to do so 2023-03-30 15:00:46 +08:00
di-sukharev
f5bcf58f7b refactor(commit.ts): replace filter callback with Boolean function call
docs(commit.ts): remove unnecessary empty line
2023-03-30 14:57:22 +08:00
di-sukharev
4b53a08653 refactor(git.ts): change double quotes to single quotes in git commands and remove unnecessary whitespace 2023-03-30 14:53:18 +08:00
di-sukharev
95d3d8b6c9 chore(commit.ts, es_ES.json, id_ID.json, index.ts): remove unnecessary comments and fix typos in commit messages and translations 2023-03-30 14:52:01 +08:00
kakandavorever
2c79bf22df Add support for indonesia language (id_ID) (#94)
* Add support for indonesia language (id_ID)
2023-03-30 14:47:57 +08:00
Jeroen Smink
e8c1a75a46 Feat(i18n): Add Dutch translations (#85)
* feat(i18n): add support for Dutch language (nl) and translations for commit messages in Dutch

* chore(i18n): update Dutch translation of commit messages in nl.json file

---------

Co-authored-by: Jeroen Smink [TRES] <jeroensmink@TRES.local>
Co-authored-by: Sukharev <57486732+di-sukharev@users.noreply.github.com>
2023-03-30 14:43:12 +08:00
Maik Stegemann
5d064ac873 fix(githook.ts): fix SYMLINK_URL for Windows (#88)
* fix(githook.ts): fix SYMLINK_URL for Windows

* refactor(githook.ts): use path.join to create SYMLINK_URL
The SYMLINK_URL variable is now created using the path.join method, which is more platform-independent and ensures that the correct path separator is used. This improves the reliability of the code and makes it easier to maintain.

---------

Co-authored-by: Maik Stegemann <ms@lis-gmbh.com>
2023-03-30 14:42:02 +08:00
Alex Cáceres Gómez
8d01829a9b 🔥 refactor(githook.ts): remove unused import (#93)
The import statement for the fileURLToPath function from the url module is not used in the file. Therefore, it has been removed to improve code readability and maintainability.
2023-03-30 14:41:08 +08:00
di-sukharev
e9c66ae168 1.1.32 2023-03-29 18:24:18 +08:00
di-sukharev
18b0004b81 1.1.31 2023-03-29 18:24:14 +08:00
di-sukharev
4d4157087e Merge branch 'dev' of github.com:di-sukharev/opencommit into dev 2023-03-29 18:23:46 +08:00
di-sukharev
3edb6e2fc1 chore(generateCommitMessageFromGitDiff.ts): fix typo in GitMoji convention 2023-03-29 18:23:25 +08:00
Andrew
d428102a67 [FEAT](i18n): Add support for Russian language (ru) (#75) 2023-03-29 14:11:18 +08:00
42 changed files with 50906 additions and 232 deletions

91
.github/ISSUE_TEMPLATE/bug.yaml vendored Normal file
View File

@@ -0,0 +1,91 @@
name: 🐞 Bug Report
description: File a bug report
title: "[Bug]: "
labels: ["bug", "triage"]
assignees:
- octocat
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: opencommit-version
attributes:
label: Opencommit Version
description: What version of our software are you running?
placeholder: ex. 1.1.22
validations:
required: true
- type: input
id: node-version
attributes:
label: Node Version
description: What version of node are you running?
placeholder: ex. 19.8.1
validations:
required: true
- type: input
id: npm-version
attributes:
label: NPM Version
description: What version of npm are you running?
placeholder: ex. 9.6.2
validations:
required: true
- type: dropdown
id: OS
attributes:
label: What OS are you seeing the problem on?
multiple: true
options:
- Mac
- Windows
- Other Linux Distro
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
value: "A bug happened!"
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected Behavior
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you expected to happen!
validations:
required: true
- type: textarea
id: current-behavior
attributes:
label: Current Behavior
description: Also tell us, what is currently happening?
placeholder: Tell us what is happening now.
validations:
required: true
- type: textarea
id: possible-solution
attributes:
label: Possible Solution
description: Do you have a solution for the issue?
placeholder: Tell us what the solution could look like.
validations:
required: false
- type: textarea
id: steps-to-reproduce
attributes:
label: Steps to Reproduce
description: Tell us how to reproduce the issue?
placeholder: Tell us how to reproduce the issue?
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell

View File

@@ -0,0 +1,48 @@
---
name: 🛠️ Feature Request
description: Suggest an idea to help us improve Opencommit
title: "[Feature]: "
labels:
- "feature_request"
body:
- type: markdown
attributes:
value: |
**Thanks :heart: for taking the time to fill out this feature request report!**
We kindly ask that you search to see if an issue [already exists](https://github.com/di-sukharev/opencommit/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature.
We are also happy to accept contributions from our users. For more details see [here](https://github.com/di-sukharev/opencommit/blob/master/.github/CONTRIBUTING.md).
- type: textarea
attributes:
label: Description
description: |
A clear and concise description of the feature you're interested in.
validations:
required: true
- type: textarea
attributes:
label: Suggested Solution
description: |
Describe the solution you'd like. A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Alternatives
description: |
Describe alternatives you've considered.
A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
attributes:
label: Additional Context
description: |
Add any other context about the problem here.
validations:
required: false

1
.github/TODO.md vendored
View File

@@ -8,3 +8,4 @@
- [x] batch small files in one request
- [] add tests
- [] optimize prompt, maybe no prompt would be cleaner
- [] try setting max commit msg length, maybe it will make commits short and more concise

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

After

Width:  |  Height:  |  Size: 304 KiB

76
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '21 16 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

20
.github/workflows/dependency-review.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v2

28
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
on:
schedule:
- cron: '27 21 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 40
stale-issue-message: 'Stale issue message'
stale-pr-message: 'Stale pull request message'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'

2
.gitignore vendored
View File

@@ -1,9 +1,7 @@
node_modules/
coverage/
out/
temp/
build/
dist/
application.log
.DS_Store
/*.env

137
README.md
View File

@@ -18,7 +18,70 @@
All the commits in this repo are done with OpenCommit — look into [the commits](https://github.com/di-sukharev/opencommit/commit/eae7618d575ee8d2e9fff5de56da79d40c4bc5fc) to see how OpenCommit works. Emoji and long commit description text is configurable.
## Setup
## Setup OpenCommit as a Github Action
OpenCommit is now available as a GitHub Action which automatically improves all new commits messages when you push to remote!
This is great if you want to make sure all of the commits in all of repository branches are meaningful and not lame like `fix1` or `done2`.
### Automatic 1 click setup
You can simply [setup the action automatically via the GitHub Marketplace](TODO).
### Manual 3 clicks setup
Create a file `.github/workflows/opencommit.yml` with contents below:
```yml
name: 'OpenCommit'
on:
push:
# this list of branches is often enough,
# but you may still ignore other public branches
branches-ignore: [main master dev development release]
jobs:
opencommit:
name: OpenCommit
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Setup Node.js Environment
uses: actions/setup-node@v2
with:
node-version: '16'
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: di-sukharev/opencommit@github-action
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
env:
# set openAI api key in repo actions secrets,
# for openAI keys go to: https://platform.openai.com/account/api-keys
# for repo secret go to: <your_repo_url>/settings/secrets/actions
OCO_OPENAI_API_KEY: ${{ secrets.OCO_OPENAI_API_KEY }}
# customization
OCO_OPENAI_MAX_TOKENS: 500
OCO_OPENAI_BASE_PATH: ''
OCO_DESCRIPTION: false
OCO_EMOJI: false
OCO_MODEL: gpt-3.5-turbo
OCO_LANGUAGE: en
```
That is it. Now when you push to any branch in your repo — all NEW commits are being improved by never-tired-AI.
Make sure you exclude public collaboration branches (`main`, `dev`, `etc`) in `branches-ignore`, so OpenCommit does not rebase commits there when improving the messages.
Interactive rebase (`rebase -i`) changes commit SHA, so commit history in remote becomes different with your local branch history. It's ok when you work on the branch alone, but may be inconvenient for other collaborators.
## Setup OpenCommit as a CLI
You can use OpenCommit by simply running it via CLI like this `oc`. 2 seconds and your staged changes are committed with a meaningful message.
1. Install OpenCommit globally to use in any repository:
@@ -31,7 +94,7 @@ All the commits in this repo are done with OpenCommit — look into [the commits
3. Set the key to OpenCommit config:
```sh
opencommit config set OPENAI_API_KEY=<your_api_key>
opencommit config set OCO_OPENAI_API_KEY=<your_api_key>
```
Your api key is stored locally in `~/.opencommit` config file.
@@ -52,53 +115,72 @@ git add <files...>
oc
```
## Features
## Configuration
### Preface commits with emoji 🤠
### Local per repo configuration
[GitMoji](https://gitmoji.dev/) convention is used.
Create an `.env` file and add OpenCommit config variables there like this:
To add emoji:
```sh
oc config set emoji=true
```env
OCO_OPENAI_API_KEY=<your openAI API token>
OCO_OPENAI_MAX_TOKENS=<max response tokens from openAI API>
OCO_OPENAI_BASE_PATH=<may be used to set proxy path to openAI api>
OCO_DESCRIPTION=<postface a message with ~3 sentences description>
OCO_EMOJI=<add GitMoji>
OCO_MODEL=<either gpt-3.5-turbo or gpt-4>
OCO_LANGUAGE=<locale, scroll to the bottom to see options>
```
To remove emoji:
### Global config for all repos
Local config still has more priority as Global config, but you may set `OCO_MODEL` and `OCO_LOCALE` globally and set local configs for `OCO_EMOJI` and `OCO_DESCRIPTION` per repo which is more convenient.
Simply run any of the variable above like this:
```sh
oc config set emoji=false
oc config set OCO_OPENAI_API_KEY=gpt-4
```
### Postface commits with descriptions of changes
To add descriptions:
Configure [GitMoji](https://gitmoji.dev/) to preface a message.
```sh
oc config set description=true
oc config set OCO_EMOJI=true
```
To remove description:
To remove preface emoji:
```sh
oc config set description=false
oc config set OCO_EMOJI=false
```
### Internationalization support
### Switch to GPT-4
To specify the language used to generate commit messages:
By default OpenCommit uses GPT-3.5-turbo (ChatGPT).
You may switch to GPT-4 which performs better, but costs ~x15 times more 🤠
```sh
oc config set OCO_MODEL=gpt-4
```
Make sure you do lowercase `gpt-4` and you have API access to the 4th model. Even if you have ChatGPT+ it doesn't necessarily mean that you have API access to GPT-4.
## Locale configuration
To globally specify the language used to generate commit messages:
```sh
# de, German ,Deutsch
oc config set language=de
oc config set language=German
oc config set language=Deutsch
oc config set OCO_LANGUAGE=de
oc config set OCO_LANGUAGE=German
oc config set OCO_LANGUAGE=Deutsch
# fr, French, française
oc config set language=fr
oc config set language=French
oc config set language=française
oc config set OCO_LANGUAGE=fr
oc config set OCO_LANGUAGE=French
oc config set OCO_LANGUAGE=française
```
The default language set is **English**
All available languages are currently listed in the [i18n](https://github.com/di-sukharev/opencommit/tree/master/src/i18n) folder
@@ -117,6 +199,7 @@ git commit -m "${generatedMessage}" --no-verify
```
### Ignore files
You can ignore files from submission to OpenAI by creating a `.opencommitignore` file. For example:
```ignorelang
@@ -128,7 +211,7 @@ This is useful for preventing opencommit from uploading artifacts and large file
By default, opencommit ignores files matching: `*-lock.*` and `*.lock`
## Git hook
## Git hook (KILLER FEATURE)
You can set OpenCommit as Git [`prepare-commit-msg`](https://git-scm.com/docs/githooks#_prepare_commit_msg) hook. Hook integrates with you IDE Source Control and allows you edit the message before commit.
@@ -155,4 +238,4 @@ Or follow the process of your IDE Source Control feature, when it calls `git com
## Payments
You pay for your own requests to OpenAI API. OpenCommit uses ChatGPT official model, that is ~10x times cheaper than GPT-3 and ~6x times cheaper than GPT-4.
You pay for your own requests to OpenAI API. OpenCommit uses ChatGPT (3.5-turbo) official model, that is ~15x times cheaper than GPT-4.

26
action.yml Normal file
View File

@@ -0,0 +1,26 @@
name: 'OpenCommit'
description: 'Replaces lame commit messages with meaningful AI-generated messages when you push to remote 🤯🔫'
author: 'https://github.com/di-sukharev'
repo: 'https://github.com/di-sukharev/opencommit/tree/github-action'
keywords:
[
'git',
'chatgpt',
'gpt',
'ai',
'openai',
'opencommit',
'aicommit',
'aicommits',
'gptcommit',
'commit'
]
inputs:
GITHUB_TOKEN:
description: 'GitHub token'
required: true
runs:
using: 'node16'
main: 'out/github-action.cjs'

24
esbuild.config.js Normal file
View File

@@ -0,0 +1,24 @@
import { build } from 'esbuild';
import fs from 'fs';
await build({
entryPoints: ['./src/cli.ts'],
bundle: true,
platform: 'node',
format: 'cjs',
outfile: './out/cli.cjs'
});
await build({
entryPoints: ['./src/github-action.ts'],
bundle: true,
platform: 'node',
format: 'cjs',
outfile: './out/github-action.cjs'
});
const wasmFile = fs.readFileSync(
'./node_modules/@dqbd/tiktoken/lite/tiktoken_bg.wasm'
);
fs.writeFileSync('./out/tiktoken_bg.wasm', wasmFile);

22124
out/cli.cjs Executable file

File diff suppressed because one or more lines are too long

27337
out/github-action.cjs Normal file

File diff suppressed because one or more lines are too long

BIN
out/tiktoken_bg.wasm Normal file

Binary file not shown.

428
package-lock.json generated
View File

@@ -1,16 +1,21 @@
{
"name": "opencommit",
"version": "1.1.30",
"version": "2.0.15",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "opencommit",
"version": "1.1.30",
"version": "2.0.15",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@clack/prompts": "^0.6.1",
"@dqbd/tiktoken": "^1.0.2",
"@octokit/webhooks-schemas": "^6.11.0",
"@octokit/webhooks-types": "^6.11.0",
"axios": "^1.3.4",
"chalk": "^5.2.0",
"cleye": "^1.3.2",
@@ -22,6 +27,7 @@
},
"bin": {
"oc": "out/cli.cjs",
"oco": "out/cli.cjs",
"opencommit": "out/cli.cjs"
},
"devDependencies": {
@@ -38,6 +44,112 @@
"typescript": "^4.9.3"
}
},
"node_modules/@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/github": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"@octokit/core": "^3.6.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/auth-token": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
"dependencies": {
"@octokit/types": "^6.0.3"
}
},
"node_modules/@actions/github/node_modules/@octokit/core": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz",
"integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==",
"dependencies": {
"@octokit/auth-token": "^2.4.4",
"@octokit/graphql": "^4.5.8",
"@octokit/request": "^5.6.3",
"@octokit/request-error": "^2.0.5",
"@octokit/types": "^6.0.3",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/endpoint": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
"dependencies": {
"@octokit/types": "^6.0.3",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/graphql": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
"dependencies": {
"@octokit/request": "^5.6.0",
"@octokit/types": "^6.0.3",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/request": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz",
"integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==",
"dependencies": {
"@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.1.0",
"@octokit/types": "^6.16.1",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/request-error": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
"dependencies": {
"@octokit/types": "^6.0.3",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}
},
"node_modules/@actions/http-client": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
"integrity": "sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==",
"dependencies": {
"tunnel": "^0.0.6"
}
},
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@clack/core": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.2.tgz",
@@ -85,9 +197,9 @@
}
},
"node_modules/@dqbd/tiktoken": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@dqbd/tiktoken/-/tiktoken-1.0.2.tgz",
"integrity": "sha512-AjGTBRWsMoVmVeN55NLyupyM8TNamOUBl6tj5t/leLDVup3CFGO9tVagNL1jf3GyZLkWZSTmYVbPQ/M2LEcNzw=="
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@dqbd/tiktoken/-/tiktoken-1.0.6.tgz",
"integrity": "sha512-umSdeZTy/SbPPKVuZKV/XKyFPmXSN145CcM3iHjBbmhlohBJg7vaDp4cPCW+xNlWL6L2U1sp7T2BD+di2sUKdA=="
},
"node_modules/@esbuild/android-arm": {
"version": "0.15.18",
@@ -246,6 +358,231 @@
"node": ">= 8"
}
},
"node_modules/@octokit/auth-token": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz",
"integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==",
"peer": true,
"dependencies": {
"@octokit/types": "^9.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": {
"version": "17.1.2",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.2.tgz",
"integrity": "sha512-OaS7Ol4Y+U50PbejfzQflGWRMxO04nYWO5ZBv6JerqMKE2WS/tI9VoVDDPXHBlRMGG2fOdKwtVGlFfc7AVIstw==",
"peer": true
},
"node_modules/@octokit/auth-token/node_modules/@octokit/types": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.2.tgz",
"integrity": "sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^17.1.2"
}
},
"node_modules/@octokit/core": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz",
"integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==",
"peer": true,
"dependencies": {
"@octokit/auth-token": "^3.0.0",
"@octokit/graphql": "^5.0.0",
"@octokit/request": "^6.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^9.0.0",
"before-after-hook": "^2.2.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
"version": "17.1.2",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.2.tgz",
"integrity": "sha512-OaS7Ol4Y+U50PbejfzQflGWRMxO04nYWO5ZBv6JerqMKE2WS/tI9VoVDDPXHBlRMGG2fOdKwtVGlFfc7AVIstw==",
"peer": true
},
"node_modules/@octokit/core/node_modules/@octokit/types": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.2.tgz",
"integrity": "sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^17.1.2"
}
},
"node_modules/@octokit/endpoint": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz",
"integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==",
"peer": true,
"dependencies": {
"@octokit/types": "^9.0.0",
"is-plain-object": "^5.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
"version": "17.1.2",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.2.tgz",
"integrity": "sha512-OaS7Ol4Y+U50PbejfzQflGWRMxO04nYWO5ZBv6JerqMKE2WS/tI9VoVDDPXHBlRMGG2fOdKwtVGlFfc7AVIstw==",
"peer": true
},
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.2.tgz",
"integrity": "sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^17.1.2"
}
},
"node_modules/@octokit/graphql": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz",
"integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==",
"peer": true,
"dependencies": {
"@octokit/request": "^6.0.0",
"@octokit/types": "^9.0.0",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
"version": "17.1.2",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.2.tgz",
"integrity": "sha512-OaS7Ol4Y+U50PbejfzQflGWRMxO04nYWO5ZBv6JerqMKE2WS/tI9VoVDDPXHBlRMGG2fOdKwtVGlFfc7AVIstw==",
"peer": true
},
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.2.tgz",
"integrity": "sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^17.1.2"
}
},
"node_modules/@octokit/openapi-types": {
"version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "2.21.3",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz",
"integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==",
"dependencies": {
"@octokit/types": "^6.40.0"
},
"peerDependencies": {
"@octokit/core": ">=2"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "5.16.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz",
"integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==",
"dependencies": {
"@octokit/types": "^6.39.0",
"deprecation": "^2.3.1"
},
"peerDependencies": {
"@octokit/core": ">=3"
}
},
"node_modules/@octokit/request": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz",
"integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==",
"peer": true,
"dependencies": {
"@octokit/endpoint": "^7.0.0",
"@octokit/request-error": "^3.0.0",
"@octokit/types": "^9.0.0",
"is-plain-object": "^5.0.0",
"node-fetch": "^2.6.7",
"universal-user-agent": "^6.0.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/request-error": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz",
"integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==",
"peer": true,
"dependencies": {
"@octokit/types": "^9.0.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
"version": "17.1.2",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.2.tgz",
"integrity": "sha512-OaS7Ol4Y+U50PbejfzQflGWRMxO04nYWO5ZBv6JerqMKE2WS/tI9VoVDDPXHBlRMGG2fOdKwtVGlFfc7AVIstw==",
"peer": true
},
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.2.tgz",
"integrity": "sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^17.1.2"
}
},
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
"version": "17.1.2",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.1.2.tgz",
"integrity": "sha512-OaS7Ol4Y+U50PbejfzQflGWRMxO04nYWO5ZBv6JerqMKE2WS/tI9VoVDDPXHBlRMGG2fOdKwtVGlFfc7AVIstw==",
"peer": true
},
"node_modules/@octokit/request/node_modules/@octokit/types": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.2.tgz",
"integrity": "sha512-9BjDxjgQIvCjNWZsbqyH5QC2Yni16oaE6xL+8SUBMzcYPF4TGQBXGA97Cl3KceK9mwiNMb1mOYCz6FbCCLEL+g==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^17.1.2"
}
},
"node_modules/@octokit/types": {
"version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"dependencies": {
"@octokit/openapi-types": "^12.11.0"
}
},
"node_modules/@octokit/webhooks-schemas": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@octokit/webhooks-schemas/-/webhooks-schemas-6.11.0.tgz",
"integrity": "sha512-ekca2jZhb2vfQy43rjvJoV77IwEKvA42BmJ2m8H3WaNfG9BF05RodnFjh3MSOksNseoNO8w8IPLZ3d5546NH2w=="
},
"node_modules/@octokit/webhooks-types": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.11.0.tgz",
"integrity": "sha512-AanzbulOHljrku1NGfafxdpTCfw2ENaWzH01N2vqQM+cUFbk868Cgh0xylz0JIM9BoKbfI++bdD6EYX0Q/UTEw=="
},
"node_modules/@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
@@ -653,6 +990,11 @@
}
]
},
"node_modules/before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
"node_modules/bl": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
@@ -882,6 +1224,11 @@
"node": ">=0.4.0"
}
},
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@@ -2039,6 +2386,14 @@
"node": ">=8"
}
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
@@ -2264,6 +2619,25 @@
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"node_modules/node-fetch": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
@@ -2293,7 +2667,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
}
@@ -2903,6 +3276,11 @@
"node": ">=8.0"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/ts-node": {
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
@@ -2972,6 +3350,14 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -3017,6 +3403,11 @@
"node": ">=4.2.0"
}
},
"node_modules/universal-user-agent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -3031,6 +3422,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@@ -3045,6 +3444,20 @@
"defaults": "^1.0.3"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -3112,8 +3525,7 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/yallist": {
"version": "4.0.0",

View File

@@ -1,7 +1,7 @@
{
"name": "opencommit",
"version": "1.1.30",
"description": "GPT CLI to auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
"version": "2.0.15",
"description": "Auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
"keywords": [
"git",
"chatgpt",
@@ -17,7 +17,8 @@
"main": "cli.js",
"bin": {
"opencommit": "./out/cli.cjs",
"oc": "./out/cli.cjs"
"oc": "./out/cli.cjs",
"oco": "./out/cli.cjs"
},
"repository": {
"url": "https://github.com/di-sukharev/opencommit"
@@ -40,7 +41,7 @@
"watch": "npm run -S build -- --sourcemap --watch",
"start": "node ./out/cli.cjs",
"dev": "ts-node ./src/cli.ts",
"build": "rimraf out && esbuild ./src/cli.ts --bundle --outfile=out/cli.cjs --format=cjs --platform=node",
"build": "rimraf out && node esbuild.config.js",
"deploy": "npm run build && npm version patch && npm publish --tag latest",
"lint": "eslint src --ext ts && tsc --noEmit",
"format": "prettier --write src"
@@ -59,7 +60,13 @@
"typescript": "^4.9.3"
},
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@clack/prompts": "^0.6.1",
"@dqbd/tiktoken": "^1.0.2",
"@octokit/webhooks-schemas": "^6.11.0",
"@octokit/webhooks-types": "^6.11.0",
"axios": "^1.3.4",
"chalk": "^5.2.0",
"cleye": "^1.3.2",

View File

@@ -11,7 +11,9 @@ import { CONFIG_MODES, getConfig } from './commands/config';
const config = getConfig();
let apiKey = config?.OPENAI_API_KEY;
let maxTokens = config?.OCO_OPENAI_MAX_TOKENS;
let basePath = config?.OCO_OPENAI_BASE_PATH;
let apiKey = config?.OCO_OPENAI_API_KEY;
const [command, mode] = process.argv.slice(2);
@@ -19,7 +21,7 @@ if (!apiKey && command !== 'config' && mode !== CONFIG_MODES.set) {
intro('opencommit');
outro(
'OPENAI_API_KEY is not set, please run `oc config set OPENAI_API_KEY=<your token>. Make sure you add payment details, so API works.`'
'OCO_OPENAI_API_KEY is not set, please run `oc config set OCO_OPENAI_API_KEY=<your token>. Make sure you add payment details, so API works.`'
);
outro(
'For help look into README https://github.com/di-sukharev/opencommit#setup'
@@ -28,30 +30,42 @@ if (!apiKey && command !== 'config' && mode !== CONFIG_MODES.set) {
process.exit(1);
}
const MODEL = config?.OCO_MODEL || 'gpt-3.5-turbo';
class OpenAi {
private openAiApiConfiguration = new OpenAiApiConfiguration({
apiKey: apiKey
});
private openAI!: OpenAIApi;
private openAI = new OpenAIApi(this.openAiApiConfiguration);
constructor() {
if (basePath) {
this.openAiApiConfiguration.basePath = basePath;
}
this.openAI = new OpenAIApi(this.openAiApiConfiguration);
}
public generateCommitMessage = async (
messages: Array<ChatCompletionRequestMessage>
): Promise<string | undefined> => {
const params = {
model: MODEL,
messages,
temperature: 0,
top_p: 0.1,
max_tokens: maxTokens || 500
};
try {
const { data } = await this.openAI.createChatCompletion({
model: 'gpt-3.5-turbo',
messages,
temperature: 0,
top_p: 0.1,
max_tokens: 196
});
const { data } = await this.openAI.createChatCompletion(params);
const message = data.choices[0].message;
return message?.content;
} catch (error: unknown) {
outro(`${chalk.red('✖')} ${error}`);
} catch (error) {
outro(`${chalk.red('✖')} ${JSON.stringify(params)}`);
const err = error as Error;
outro(`${chalk.red('✖')} ${err?.message || err}`);
if (
axios.isAxiosError<{ error?: { message: string } }>(error) &&
@@ -65,7 +79,7 @@ class OpenAi {
);
}
process.exit(1);
throw err;
}
};
}

View File

@@ -22,7 +22,8 @@ cli(
},
async () => {
// await checkIsLatestVersion();
if (isHookCalled) {
if (await isHookCalled()) {
prepareCommitMessageHook();
} else {
commit(extraArgs);

View File

@@ -1,7 +1,7 @@
import { execa } from 'execa';
import {
GenerateCommitMessageErrorEnum,
generateCommitMessageWithChatCompletion
generateCommitMessageByDiff
} from '../generateCommitMessageFromGitDiff';
import {
assertGitRepo,
@@ -22,10 +22,9 @@ import {
import chalk from 'chalk';
import { trytm } from '../utils/trytm';
// Adding a function to get the list of remotes
const getGitRemotes = async () => {
const { stdout } = await execa('git', ['remote']);
return stdout.split('\n').filter((remote) => remote.trim() !== '');
return stdout.split('\n').filter((remote) => Boolean(remote.trim()));
};
const generateCommitMessageFromGitDiff = async (
@@ -36,93 +35,98 @@ const generateCommitMessageFromGitDiff = async (
const commitSpinner = spinner();
commitSpinner.start('Generating the commit message');
const commitMessage = await generateCommitMessageWithChatCompletion(diff);
try {
const commitMessage = await generateCommitMessageByDiff(diff);
// TODO: show proper error messages
if (typeof commitMessage !== 'string') {
const errorMessages = {
[GenerateCommitMessageErrorEnum.emptyMessage]:
'empty openAI response, weird, try again',
[GenerateCommitMessageErrorEnum.internalError]:
'internal error, try again',
[GenerateCommitMessageErrorEnum.tooMuchTokens]:
'too much tokens in git diff, stage and commit files in parts'
};
commitSpinner.stop('📝 Commit message generated');
outro(`${chalk.red('✖')} ${errorMessages[commitMessage.error]}`);
process.exit(1);
}
commitSpinner.stop('📝 Commit message generated');
outro(
`Commit message:
outro(
`Commit message:
${chalk.grey('——————————————————')}
${commitMessage}
${chalk.grey('——————————————————')}`
);
);
const isCommitConfirmedByUser = await confirm({
message: 'Confirm the commit message?'
});
const isCommitConfirmedByUser = await confirm({
message: 'Confirm the commit message?'
});
if (isCommitConfirmedByUser && !isCancel(isCommitConfirmedByUser)) {
const { stdout } = await execa('git', [
'commit',
'-m',
commitMessage,
...extraArgs
]);
if (isCommitConfirmedByUser && !isCancel(isCommitConfirmedByUser)) {
const { stdout } = await execa('git', [
'commit',
'-m',
commitMessage,
...extraArgs
]);
outro(`${chalk.green('✔')} successfully committed`);
outro(`${chalk.green('✔')} Successfully committed`);
outro(stdout);
const remotes = await getGitRemotes();
outro(stdout);
if (remotes.length === 1) {
const isPushConfirmedByUser = await confirm({
message: 'Do you want to run `git push`?'
});
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
const pushSpinner = spinner();
pushSpinner.start(`Running \`git push ${remotes[0]}\``);
const { stdout } = await execa('git', [
'push',
'--verbose',
remotes[0]
]);
pushSpinner.stop(
`${chalk.green('✔')} successfully pushed all commits to ${remotes[0]}`
);
const remotes = await getGitRemotes();
if (!remotes.length) {
const { stdout } = await execa('git', ['push']);
if (stdout) outro(stdout);
process.exit(0);
}
} else {
const selectedRemote = (await select({
message: 'Choose a remote to push to',
options: remotes.map((remote) => ({ value: remote, label: remote }))
})) as string;
if (!isCancel(selectedRemote)) {
const pushSpinner = spinner();
if (remotes.length === 1) {
const isPushConfirmedByUser = await confirm({
message: 'Do you want to run `git push`?'
});
pushSpinner.start(`Running \`git push ${selectedRemote}\``);
if (isPushConfirmedByUser && !isCancel(isPushConfirmedByUser)) {
const pushSpinner = spinner();
const { stdout } = await execa('git', ['push', selectedRemote]);
pushSpinner.start(`Running \`git push ${remotes[0]}\``);
pushSpinner.stop(
`${chalk.green(
'✔'
)} successfully pushed all commits to ${selectedRemote}`
);
const { stdout } = await execa('git', [
'push',
'--verbose',
remotes[0]
]);
if (stdout) outro(stdout);
} else outro(`${chalk.gray('')} process cancelled`);
pushSpinner.stop(
`${chalk.green('')} Successfully pushed all commits to ${
remotes[0]
}`
);
if (stdout) outro(stdout);
} else {
outro('`git push` aborted');
process.exit(0);
}
} else {
const selectedRemote = (await select({
message: 'Choose a remote to push to',
options: remotes.map((remote) => ({ value: remote, label: remote }))
})) as string;
if (!isCancel(selectedRemote)) {
const pushSpinner = spinner();
pushSpinner.start(`Running \`git push ${selectedRemote}\``);
const { stdout } = await execa('git', ['push', selectedRemote]);
pushSpinner.stop(
`${chalk.green(
'✔'
)} Successfully pushed all commits to ${selectedRemote}`
);
if (stdout) outro(stdout);
} else outro(`${chalk.gray('✖')} process cancelled`);
}
}
} catch (error) {
commitSpinner.stop('📝 Commit message generated');
const err = error as Error;
outro(`${chalk.red('✖')} ${err?.message || err}`);
process.exit(1);
}
};
@@ -207,5 +211,6 @@ export async function commit(
outro(`${chalk.red('✖')} ${generateCommitError}`);
process.exit(1);
}
process.exit(0);
}

View File

@@ -8,11 +8,18 @@ import chalk from 'chalk';
import { COMMANDS } from '../CommandsEnum';
import { getI18nLocal } from '../i18n';
import * as dotenv from 'dotenv';
dotenv.config();
export enum CONFIG_KEYS {
OPENAI_API_KEY = 'OPENAI_API_KEY',
description = 'description',
emoji = 'emoji',
language = 'language'
OCO_OPENAI_API_KEY = 'OCO_OPENAI_API_KEY',
OCO_OPENAI_MAX_TOKENS = 'OCO_OPENAI_MAX_TOKENS',
OCO_OPENAI_BASE_PATH = 'OCO_OPENAI_BASE_PATH',
OCO_DESCRIPTION = 'OCO_DESCRIPTION',
OCO_EMOJI = 'OCO_EMOJI',
OCO_MODEL = 'OCO_MODEL',
OCO_LANGUAGE = 'OCO_LANGUAGE'
}
export enum CONFIG_MODES {
@@ -35,15 +42,15 @@ const validateConfig = (
};
export const configValidators = {
[CONFIG_KEYS.OPENAI_API_KEY](value: any) {
validateConfig(CONFIG_KEYS.OPENAI_API_KEY, value, 'Cannot be empty');
[CONFIG_KEYS.OCO_OPENAI_API_KEY](value: any) {
validateConfig(CONFIG_KEYS.OCO_OPENAI_API_KEY, value, 'Cannot be empty');
validateConfig(
CONFIG_KEYS.OPENAI_API_KEY,
CONFIG_KEYS.OCO_OPENAI_API_KEY,
value.startsWith('sk-'),
'Must start with "sk-"'
);
validateConfig(
CONFIG_KEYS.OPENAI_API_KEY,
CONFIG_KEYS.OCO_OPENAI_API_KEY,
value.length === 51,
'Must be 51 characters long'
);
@@ -51,9 +58,9 @@ export const configValidators = {
return value;
},
[CONFIG_KEYS.description](value: any) {
[CONFIG_KEYS.OCO_DESCRIPTION](value: any) {
validateConfig(
CONFIG_KEYS.description,
CONFIG_KEYS.OCO_DESCRIPTION,
typeof value === 'boolean',
'Must be true or false'
);
@@ -61,9 +68,28 @@ export const configValidators = {
return value;
},
[CONFIG_KEYS.emoji](value: any) {
[CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS](value: any) {
// If the value is a string, convert it to a number.
if (typeof value === 'string') {
value = parseInt(value);
validateConfig(
CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS,
!isNaN(value),
'Must be a number'
);
}
validateConfig(
CONFIG_KEYS.emoji,
CONFIG_KEYS.OCO_OPENAI_MAX_TOKENS,
typeof value === 'number',
'Must be a number'
);
return value;
},
[CONFIG_KEYS.OCO_EMOJI](value: any) {
validateConfig(
CONFIG_KEYS.OCO_EMOJI,
typeof value === 'boolean',
'Must be true or false'
);
@@ -71,13 +97,31 @@ export const configValidators = {
return value;
},
[CONFIG_KEYS.language](value: any) {
[CONFIG_KEYS.OCO_LANGUAGE](value: any) {
validateConfig(
CONFIG_KEYS.language,
CONFIG_KEYS.OCO_LANGUAGE,
getI18nLocal(value),
`${value} is not supported yet`
);
return getI18nLocal(value);
},
[CONFIG_KEYS.OCO_OPENAI_BASE_PATH](value: any) {
validateConfig(
CONFIG_KEYS.OCO_OPENAI_BASE_PATH,
typeof value === 'string',
'Must be string'
);
return value;
},
[CONFIG_KEYS.OCO_MODEL](value: any) {
validateConfig(
CONFIG_KEYS.OCO_OPENAI_BASE_PATH,
value === 'gpt-3.5-turbo' || value === 'gpt-4',
`${value} is not supported yet, use 'gpt-4' or 'gpt-3.5-turbo' (default)`
);
return value;
}
};
@@ -88,18 +132,39 @@ export type ConfigType = {
const configPath = pathJoin(homedir(), '.opencommit');
export const getConfig = (): ConfigType | null => {
const configFromEnv = {
OCO_OPENAI_API_KEY: process.env.OCO_OPENAI_API_KEY,
OCO_OPENAI_MAX_TOKENS: Number(process.env.OCO_OPENAI_MAX_TOKENS),
OCO_OPENAI_BASE_PATH: process.env.OCO_OPENAI_BASE_PATH,
OCO_DESCRIPTION: process.env.OCO_DESCRIPTION === 'true' ? true : false,
OCO_EMOJI: process.env.OCO_EMOJI === 'true' ? true : false,
OCO_MODEL: process.env.OCO_MODEL,
OCO_LANGUAGE: process.env.OCO_LANGUAGE
};
const configExists = existsSync(configPath);
if (!configExists) return null;
if (!configExists) return configFromEnv;
const configFile = readFileSync(configPath, 'utf8');
const config = iniParse(configFile);
for (const configKey of Object.keys(config)) {
const validValue = configValidators[configKey as CONFIG_KEYS](
config[configKey]
);
try {
const validator = configValidators[configKey as CONFIG_KEYS];
const validValue = validator(
config[configKey] ?? configFromEnv[configKey as CONFIG_KEYS]
);
config[configKey] = validValue;
config[configKey] = validValue;
} catch (error) {
outro(
`'${configKey}' name is invalid, it should be either 'OCO_${configKey.toUpperCase()}' or it doesn't exist.`
);
outro(
`Manually fix the '.env' file or global '~/.opencommit' config file.`
);
process.exit(1);
}
}
return config;
@@ -128,7 +193,7 @@ export const setConfig = (keyValues: [key: string, value: string][]) => {
writeFileSync(configPath, iniStringify(config), 'utf8');
outro(`${chalk.green('✔')} config successfully set`);
outro(`${chalk.green('✔')} Config successfully set`);
};
export const configCommand = command(

View File

@@ -1,19 +1,33 @@
import fs from 'fs/promises';
import path from 'path';
import { command } from 'cleye';
import { assertGitRepo } from '../utils/git.js';
import { assertGitRepo, getCoreHooksPath } from '../utils/git.js';
import { existsSync } from 'fs';
import chalk from 'chalk';
import { intro, outro } from '@clack/prompts';
import { COMMANDS } from '../CommandsEnum.js';
import { fileURLToPath } from 'url';
const HOOK_NAME = 'prepare-commit-msg';
const SYMLINK_URL = `.git/hooks/${HOOK_NAME}`;
const DEFAULT_SYMLINK_URL = path.join('.git', 'hooks', HOOK_NAME);
export const isHookCalled = process.argv[1].endsWith(`/${SYMLINK_URL}`);
const getHooksPath = async (): Promise<string> => {
try {
const hooksPath = await getCoreHooksPath();
return path.join(hooksPath, HOOK_NAME);
} catch (error) {
return DEFAULT_SYMLINK_URL;
}
};
const isHookExists = existsSync(SYMLINK_URL);
export const isHookCalled = async (): Promise<boolean> => {
const hooksPath = await getHooksPath();
return process.argv[1].endsWith(hooksPath);
};
const isHookExists = async (): Promise<boolean> => {
const hooksPath = await getHooksPath();
return existsSync(hooksPath);
};
export const hookCommand = command(
{
@@ -22,16 +36,16 @@ export const hookCommand = command(
},
async (argv) => {
const HOOK_URL = __filename;
const SYMLINK_URL = await getHooksPath();
try {
await assertGitRepo();
const { setUnset: mode } = argv._;
if (mode === 'set') {
intro(`setting OpenCommit as '${HOOK_NAME}' hook`);
intro(`setting opencommit as '${HOOK_NAME}' hook at ${SYMLINK_URL}`);
if (isHookExists) {
if (await isHookExists()) {
let realPath;
try {
realPath = await fs.realpath(SYMLINK_URL);
@@ -56,9 +70,11 @@ export const hookCommand = command(
}
if (mode === 'unset') {
intro(`unsetting OpenCommit as '${HOOK_NAME}' hook`);
intro(
`unsetting opencommit as '${HOOK_NAME}' hook from ${SYMLINK_URL}`
);
if (!isHookExists) {
if (!(await isHookExists())) {
return outro(
`OpenCommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove`
);
@@ -76,7 +92,7 @@ export const hookCommand = command(
}
throw new Error(
`unsupported mode: ${mode}. Supported modes are: 'set' or 'unset'`
`Unsupported mode: ${mode}. Supported modes are: 'set' or 'unset'`
);
} catch (error) {
outro(`${chalk.red('✖')} ${error}`);

View File

@@ -3,11 +3,13 @@ import chalk from 'chalk';
import { intro, outro, spinner } from '@clack/prompts';
import { getChangedFiles, getDiff, getStagedFiles, gitAdd } from '../utils/git';
import { getConfig } from './config';
import { generateCommitMessageWithChatCompletion } from '../generateCommitMessageFromGitDiff';
import { generateCommitMessageByDiff } from '../generateCommitMessageFromGitDiff';
const [messageFilePath, commitSource] = process.argv.slice(2);
export const prepareCommitMessageHook = async () => {
export const prepareCommitMessageHook = async (
isStageAllFlag: Boolean = false
) => {
try {
if (!messageFilePath) {
throw new Error(
@@ -17,16 +19,16 @@ export const prepareCommitMessageHook = async () => {
if (commitSource) return;
const stagedFiles = await getStagedFiles();
const changedFiles = await getChangedFiles();
if (isStageAllFlag) {
const changedFiles = await getChangedFiles();
if (!stagedFiles && !changedFiles) {
outro('No changes detected, write some code and run `oc` again');
process.exit(1);
if (changedFiles) await gitAdd({ files: changedFiles });
else {
outro('No changes detected, write some code and run `oc` again');
process.exit(1);
}
}
if (!stagedFiles && changedFiles) await gitAdd({ files: changedFiles });
const staged = await getStagedFiles();
if (!staged) return;
@@ -35,7 +37,7 @@ export const prepareCommitMessageHook = async () => {
const config = getConfig();
if (!config?.OPENAI_API_KEY) {
if (!config?.OCO_OPENAI_API_KEY) {
throw new Error(
'No OPEN_AI_API exists. Set your OPEN_AI_API=<key> in ~/.opencommit'
);
@@ -43,13 +45,11 @@ export const prepareCommitMessageHook = async () => {
const spin = spinner();
spin.start('Generating commit message');
const commitMessage = await generateCommitMessageWithChatCompletion(
const commitMessage = await generateCommitMessageByDiff(
await getDiff({ files: staged })
);
if (typeof commitMessage !== 'string') {
spin.stop('Error');
throw new Error(commitMessage.error);
} else spin.stop('Done');
spin.stop('Done');
const fileContent = await fs.readFile(messageFilePath);

View File

@@ -9,15 +9,15 @@ import { i18n, I18nLocals } from './i18n';
import { tokenCount } from './utils/tokenCount';
const config = getConfig();
const translation = i18n[(config?.language as I18nLocals) || 'en'];
const translation = i18n[(config?.OCO_LANGUAGE as I18nLocals) || 'en'];
const INIT_MESSAGES_PROMPT: Array<ChatCompletionRequestMessage> = [
{
role: ChatCompletionRequestMessageRoleEnum.System,
// prettier-ignore
content: `You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain why a change was done. I'll send you an output of 'git diff --staged' command, and you convert it into a commit message.
${config?.emoji? 'Use Gitmoji convention to preface the commit.': 'Do not preface the commit with anything.'}
${config?.description ? 'Add a short description of why the commit is done after the commit message. Don\'t start it with "This commit", just describe the changes.': "Don't add any descriptions to the commit, only commit message."}
content: `You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain WHAT were the changes and WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you convert it into a commit message.
${config?.OCO_EMOJI ? 'Use GitMoji convention to preface the commit.': 'Do not preface the commit with anything.'}
${config?.OCO_DESCRIPTION ? 'Add a short description of WHY the changes are done after the commit message. Don\'t start it with "This commit", just describe the changes.': "Don't add any descriptions to the commit, only commit message."}
Use the present tense. Lines must not be longer than 74 characters. Use ${translation.localLanguage} to answer.`
},
{
@@ -49,9 +49,9 @@ app.use((_, res, next) => {
},
{
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: `${config?.emoji ? '🐛 ' : ''}${translation.commitFix}
${config?.emoji ? '✨ ' : ''}${translation.commitFeat}
${config?.description ? translation.commitDescription : ''}`
content: `${config?.OCO_EMOJI ? '🐛 ' : ''}${translation.commitFix}
${config?.OCO_EMOJI ? '✨ ' : ''}${translation.commitFeat}
${config?.OCO_DESCRIPTION ? translation.commitDescription : ''}`
}
];
@@ -82,11 +82,11 @@ const INIT_MESSAGES_PROMPT_LENGTH = INIT_MESSAGES_PROMPT.map(
(msg) => tokenCount(msg.content) + 4
).reduce((a, b) => a + b, 0);
const MAX_REQ_TOKENS = 3900 - INIT_MESSAGES_PROMPT_LENGTH;
const MAX_REQ_TOKENS = 3000 - INIT_MESSAGES_PROMPT_LENGTH;
export const generateCommitMessageWithChatCompletion = async (
export const generateCommitMessageByDiff = async (
diff: string
): Promise<string | GenerateCommitMessageError> => {
): Promise<string> => {
try {
if (tokenCount(diff) >= MAX_REQ_TOKENS) {
const commitMessagePromises = getCommitMsgsPromisesFromFileDiffs(
@@ -103,12 +103,12 @@ export const generateCommitMessageWithChatCompletion = async (
const commitMessage = await api.generateCommitMessage(messages);
if (!commitMessage)
return { error: GenerateCommitMessageErrorEnum.emptyMessage };
throw new Error(GenerateCommitMessageErrorEnum.emptyMessage);
return commitMessage;
}
} catch (error) {
return { error: GenerateCommitMessageErrorEnum.internalError };
throw error;
}
};

216
src/github-action.ts Normal file
View File

@@ -0,0 +1,216 @@
import core from '@actions/core';
import github from '@actions/github';
import exec from '@actions/exec';
import { intro, outro } from '@clack/prompts';
import { PushEvent } from '@octokit/webhooks-types';
import { generateCommitMessageByDiff } from './generateCommitMessageFromGitDiff';
import { sleep } from './utils/sleep';
import { randomIntFromInterval } from './utils/randomIntFromInterval';
import { unlinkSync, writeFileSync } from 'fs';
// This should be a token with access to your repository scoped in as a secret.
// The YML workflow will need to set GITHUB_TOKEN with the GitHub Secret Token
// GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
// https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#about-the-github_token-secret
const GITHUB_TOKEN = core.getInput('GITHUB_TOKEN');
const octokit = github.getOctokit(GITHUB_TOKEN);
const context = github.context;
const owner = context.repo.owner;
const repo = context.repo.repo;
type SHA = string;
type Diff = string;
async function getCommitDiff(commitSha: string) {
const diffResponse = await octokit.request<string>(
'GET /repos/{owner}/{repo}/commits/{ref}',
{
owner,
repo,
ref: commitSha,
headers: {
Accept: 'application/vnd.github.v3.diff'
}
}
);
return { sha: commitSha, diff: diffResponse.data };
}
interface DiffAndSHA {
sha: SHA;
diff: Diff;
}
interface MsgAndSHA {
sha: SHA;
msg: string;
}
// send only 3-4 size chunks of diffs in steps,
// because openAI restricts "too many requests" at once with 429 error
async function improveMessagesInChunks(diffsAndSHAs: DiffAndSHA[]) {
const chunkSize = diffsAndSHAs!.length % 2 === 0 ? 4 : 3;
outro(`Improving commit messages in chunks of ${chunkSize}.`);
const improvePromises = diffsAndSHAs!.map((commit) =>
generateCommitMessageByDiff(commit.diff)
);
let improvedMessagesAndSHAs: MsgAndSHA[] = [];
for (let step = 0; step < improvePromises.length; step += chunkSize) {
const chunkOfPromises = improvePromises.slice(step, step + chunkSize);
try {
const chunkOfImprovedMessages = await Promise.all(chunkOfPromises);
const chunkOfImprovedMessagesBySha = chunkOfImprovedMessages.map(
(improvedMsg, i) => {
const index = improvedMessagesAndSHAs.length;
const sha = diffsAndSHAs![index + i].sha;
return { sha, msg: improvedMsg };
}
);
improvedMessagesAndSHAs.push(...chunkOfImprovedMessagesBySha);
// sometimes openAI errors with 429 code (too many requests),
// so lets sleep a bit
const sleepFor =
1000 * randomIntFromInterval(1, 5) + 100 * randomIntFromInterval(1, 5);
outro(
`Improved ${chunkOfPromises.length} messages. Sleeping for ${sleepFor}`
);
await sleep(sleepFor);
} catch (error) {
outro(error as string);
// if sleeping in try block still fails with 429,
// openAI wants at least 1 minute before next request
const sleepFor = 60000 + 1000 * randomIntFromInterval(1, 5);
outro(`Retrying after sleeping for ${sleepFor}`);
await sleep(sleepFor);
// go to previous step
step -= chunkSize;
}
}
return improvedMessagesAndSHAs;
}
const getDiffsBySHAs = async (SHAs: string[]) => {
const diffPromises = SHAs.map((sha) => getCommitDiff(sha));
const diffs = await Promise.all(diffPromises).catch((error) => {
outro(`Error in Promise.all(getCommitDiffs(SHAs)): ${error}.`);
throw error;
});
return diffs;
};
async function improveCommitMessages(
commitsToImprove: { id: string; message: string }[]
): Promise<void> {
if (commitsToImprove.length) {
outro(`Found ${commitsToImprove.length} commits to improve.`);
} else {
outro('No new commits found.');
return;
}
outro('Fetching commit diffs by SHAs.');
const commitSHAsToImprove = commitsToImprove.map((commit) => commit.id);
const diffsWithSHAs = await getDiffsBySHAs(commitSHAsToImprove);
outro('Done.');
const improvedMessagesWithSHAs = await improveMessagesInChunks(diffsWithSHAs);
console.log(
`Improved ${improvedMessagesWithSHAs.length} commits: `,
improvedMessagesWithSHAs
);
const createCommitMessageFile = (message: string, index: number) =>
writeFileSync(`./commit-${index}.txt`, message);
improvedMessagesWithSHAs.forEach(({ msg }, i) =>
createCommitMessageFile(msg, i)
);
writeFileSync(`./count.txt`, '0');
writeFileSync(
'./rebase-exec.sh',
`#!/bin/bash
count=$(cat count.txt)
git commit --amend -F commit-$count.txt
echo $(( count + 1 )) > count.txt`
);
await exec.exec(`chmod +x ./rebase-exec.sh`);
await exec.exec(
'git',
['rebase', `${commitsToImprove[0].id}^`, '--exec', './rebase-exec.sh'],
{
env: {
GIT_SEQUENCE_EDITOR: 'sed -i -e "s/^pick/reword/g"',
GIT_COMMITTER_NAME: process.env.GITHUB_ACTOR!,
GIT_COMMITTER_EMAIL: `${process.env.GITHUB_ACTOR}@users.noreply.github.com`
}
}
);
const deleteCommitMessageFile = (index: number) =>
unlinkSync(`./commit-${index}.txt`);
commitsToImprove.forEach((_commit, i) => deleteCommitMessageFile(i));
unlinkSync('./count.txt');
unlinkSync('./rebase-exec.sh');
outro('Force pushing non-interactively rebased commits into remote.');
await exec.exec('git', ['status']);
// Force push the rebased commits
await exec.exec('git', ['push', `--force`]);
outro('Done 🧙');
}
async function run() {
intro('OpenCommit — improving lame commit messages');
try {
if (github.context.eventName === 'push') {
outro(`Processing commits in a Push event`);
const payload = github.context.payload as PushEvent;
const commits = payload.commits;
// Set local Git user identity for future git history manipulations
if (payload.pusher.email)
await exec.exec('git', ['config', 'user.email', payload.pusher.email]);
await exec.exec('git', ['config', 'user.name', payload.pusher.name]);
await exec.exec('git', ['status']);
await exec.exec('git', ['log', '--oneline']);
await improveCommitMessages(commits);
} else {
outro('Wrong action.');
core.error(
`OpenCommit was called on ${github.context.payload.action}. OpenCommit is supposed to be used on "push" action.`
);
}
} catch (error: any) {
const err = error?.message || error;
core.setFailed(err);
}
}
run();

6
src/i18n/cs.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "česky",
"commitFix": "fix(server.ts): zlepšení velikosti proměnné port na velká písmena PORT",
"commitFeat": "feat(server.ts): přidání podpory pro proměnnou prostředí process.env.PORT",
"commitDescription": "Proměnná port se nyní jmenuje PORT, což odpovídá konvenci pojmenování, protože PORT je konstanta. Podpora proměnné prostředí process.env.PORT umožňuje snadnější správu nastavení při spuštění."
}

View File

@@ -1,6 +1,6 @@
{
"localLanguage": "english",
"commitFix": "fix(server.ts): change port variable case from lowercase port to uppercase PORT",
"commitFeat": "feat(server.ts): add support for process.env.PORT environment variable",
"commitFix": "fix(server.ts): change port variable case from lowercase port to uppercase PORT to improve semantics",
"commitFeat": "feat(server.ts): add support for process.env.PORT environment variable to be able to run app on a configurable port",
"commitDescription": "The port variable is now named PORT, which improves consistency with the naming conventions as PORT is a constant. Support for an environment variable allows the application to be more flexible as it can now run on any available port specified via the process.env.PORT environment variable."
}

View File

@@ -1,7 +1,6 @@
{
"localLanguage": "spanish",
"commitFix": "fix(server.ts): cambiar la variable port de minúsculas a mayúsculas PORT",
"commitFeat": "feat(server.ts): añadir soporte para la variable de entorno process.env.PORT",
"commitDescription": "La variable port ahora se llama PORT, lo que mejora la coherencia con las convenciones de nomenclatura, ya que PORT es una constante. El soporte para una variable de entorno permite que la aplicación sea más flexible, ya que ahora puede ejecutarse en cualquier puerto disponible especificado a través de la variable de entorno process.env.PORT."
}
{
"localLanguage": "spanish",
"commitFix": "fix(server.ts): cambiar la variable port de minúsculas a mayúsculas PORT",
"commitFeat": "feat(server.ts): añadir soporte para la variable de entorno process.env.PORT",
"commitDescription": "La variable port ahora se llama PORT, lo que mejora la coherencia con las convenciones de nomenclatura, ya que PORT es una constante. El soporte para una variable de entorno permite que la aplicación sea más flexible, ya que ahora puede ejecutarse en cualquier puerto disponible especificado a través de la variable de entorno process.env.PORT."
}

6
src/i18n/id_ID.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "bahasa",
"commitFix": "fix(server.ts): mengubah huruf port variable dari huruf kecil ke huruf besar PORT",
"commitFeat": "feat(server.ts): menambahkan support di process.env.PORT environment variabel",
"commitDescription": "Port variabel bernama PORT, yang membantu konsistensi dengan memberi nama yaitu PORT yang konstan. Bantuan environment variabel membantu aplikasi lebih fleksibel, dan dapat di jalankan di port manapun yang tertulis pada process.env.PORT"
}

View File

@@ -1,4 +1,5 @@
import en from '../i18n/en.json' assert { type: 'json' };
import cs from '../i18n/cs.json' assert { type: 'json' };
import de from '../i18n/de.json' assert { type: 'json' };
import fr from '../i18n/fr.json' assert { type: 'json' };
import it from '../i18n/it.json' assert { type: 'json' };
@@ -10,26 +11,40 @@ import pt_br from '../i18n/pt_br.json' assert { type: 'json' };
import vi_VN from '../i18n/vi_VN.json' assert { type: 'json' };
import es_ES from '../i18n/es_ES.json' assert { type: 'json' };
import sv from '../i18n/sv.json' assert { type: 'json' };
import nl from '../i18n/nl.json' assert { type: 'json' };
import ru from '../i18n/ru.json' assert { type: 'json' };
import id_ID from '../i18n/id_ID.json' assert { type: 'json' };
import pl from '../i18n/pl.json' assert { type: 'json' };
import tr from '../i18n/tr.json' assert { type: 'json' };
import th from '../i18n/th.json' assert { type: 'json' };
export enum I18nLocals {
'en' = 'en',
'zh_CN' = 'zh_CN',
'zh_TW' = 'zh_TW',
'ja' = 'ja',
'cs' = 'cs',
'de' = 'de',
'fr' = 'fr',
'nl' = 'nl',
'it' = 'it',
'ko' = 'ko',
'pt_br' = 'pt_br',
'es_ES' = 'es_ES',
'sv' = 'sv',
};
'ru' = 'ru',
'id_ID' = 'id_ID',
'pl' = 'pl',
'tr' = 'tr',
'th' = 'th',
}
export const i18n = {
en,
zh_CN,
zh_TW,
ja,
cs,
de,
fr,
it,
@@ -37,7 +52,13 @@ export const i18n = {
pt_br,
vi_VN,
es_ES,
sv
sv,
id_ID,
nl,
ru,
pl,
tr,
th
};
export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
@@ -45,14 +66,21 @@ export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
zh_TW: ['zh_TW', '繁體中文', '繁體'],
ja: ['ja', 'Japanese', 'にほんご'],
ko: ['ko', 'Korean', '한국어'],
de: ['de', 'German' ,'Deutsch'],
cs: ['cs', 'Czech', 'česky'],
de: ['de', 'German', 'Deutsch'],
fr: ['fr', 'French', 'française'],
it: ['it', 'Italian', 'italiano'],
nl: ['nl', 'Dutch', 'Nederlands'],
pt_br: ['pt_br', 'Portuguese', 'português'],
vi_VN: ['vi_VN', 'Vietnamese', 'tiếng Việt'],
en: ['en', 'English', 'english'],
es_ES: ['es_ES', 'Spanish', 'español'],
sv: ['sv', 'Swedish', 'Svenska'],
ru: ['ru', 'Russian', 'русский'],
id_ID: ['id_ID', 'Bahasa', 'bahasa'],
pl: ['pl', 'Polish', 'Polski'],
tr: ['tr', 'Turkish', 'Turkish'],
th: ['th', 'Thai', 'ไทย']
};
export function getI18nLocal(value: string): string | boolean {

View File

@@ -1,6 +1,6 @@
{
"localLanguage": "italiano",
"commitFix": "fix(server.ts): cambia il caso della variabile di porta da minuscolo port a maiuscolo PORT",
"commitFeat": "funzionalità(server.ts): aggiungi supporto per la variabile di ambiente process.env.PORT",
"commitDescription": "La variabile di porta è ora chiamata PORT, il che migliora la coerenza con le convenzioni di denominazione in quanto PORT è una costante. Il supporto per una variabile di ambiente consente all'applicazione di essere più flessibile poiché ora può essere eseguita su qualsiasi porta disponibile specificata tramite la variabile di ambiente process.env.PORT."
"commitFix": "fix(server.ts): cambia la grafia della variabile della porta dal minuscolo port al maiuscolo PORT",
"commitFeat": "feat(server.ts): aggiunge il supporto per la variabile di ambiente process.env.PORT",
"commitDescription": "La variabile port è ora chiamata PORT, migliorando la coerenza con le convenzioni di denominazione in quanto PORT è una costante. Il supporto per una variabile di ambiente consente all'applicazione di essere più flessibile poiché ora può essere eseguita su qualsiasi porta disponibile specificata tramite la variabile di ambiente process.env.PORT."
}

View File

@@ -1,6 +1,6 @@
{
"localLanguage": "にほんご",
"commitFix": "修正(server.ts): ポート変数のケースを小文字のポートから大文字のPORTに変更",
"commitFeat": "新機能(server.ts): process.env.PORT環境変数のサポートを追加する",
"commitDescription": "ポート変数は現在PORTという名前になっており、PORTは定数であるため命名規則に一貫性があります。環境変数サポートにより、アプリケーションはより柔軟になり、process.env.PORT環境変数で指定された任意の利用可能なポートで実行できるようになりまし"
"localLanguage": "日本語",
"commitFix": "修正(server.ts): ポート変数を小文字のportから大文字のPORTに変更",
"commitFeat": "新機能(server.ts): 環境変数process.env.PORTのサポートを追加",
"commitDescription": "ポート変数は現在PORTという名前になり、定数であるPORTを使うことで命名規則に一貫性が生まれました。環境変数サポートすることで、環境変数process.env.PORTで指定された任意の利用可能なポートで実行できるようになり、アプリケーションはより柔軟になりました。"
}

6
src/i18n/nl.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "Nederlands",
"commitFix": "fix(server.ts): verander poortvariabele van kleine letters poort naar hoofdletters PORT",
"commitFeat": "feat(server.ts): voeg ondersteuning toe voor process.env.PORT omgevingsvariabele",
"commitDescription": "De poortvariabele heet nu PORT, wat de consistentie met de naamgevingsconventies verbetert omdat PORT een constante is. Ondersteuning voor een omgevingsvariabele maakt de applicatie flexibeler, omdat deze nu kan draaien op elke beschikbare poort die is gespecificeerd via de process.env.PORT omgevingsvariabele."
}

6
src/i18n/pl.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "polski",
"commitFix": "fix(server.ts): poprawa wielkości zmiennej port na pisane z dużymi literami PORT",
"commitFeat": "feat(server.ts): dodanie obsługi zmiennej środowiskowej process.env.PORT",
"commitDescription": "Zmienna port jest teraz nazwana PORT, co jest zgodne z konwencją nazewniczą ponieważ PORT jest stałą. Obsługa zmiennej środowiskowej process.env.PORT pozwala łatwiej zarządzać ustawieniami przy starcie."
}

View File

@@ -1,7 +1,6 @@
{
"localLanguage": "português",
"commitFix": "fix(server.ts): altera o caso da variável de porta de port minúscula para PORT maiúscula",
"commitFeat": "feat(server.ts): adiciona suporte para a variável de ambiente process.env.PORT",
"commitDescription": "A variável de porta agora é denominada PORT, o que melhora a consistência com as convenções de nomenclatura, pois PORT é uma constante. O suporte para uma variável de ambiente permite que o aplicativo seja mais flexível, pois agora pode ser executado em qualquer porta disponível especificada por meio da variável de ambiente process.env.PORT."
"localLanguage": "português",
"commitFix": "fix(server.ts): altera o caso da variável de porta de port minúscula para PORT maiúscula",
"commitFeat": "feat(server.ts): adiciona suporte para a variável de ambiente process.env.PORT",
"commitDescription": "A variável de porta agora é denominada PORT, o que melhora a consistência com as convenções de nomenclatura, pois PORT é uma constante. O suporte para uma variável de ambiente permite que o aplicativo seja mais flexível, pois agora pode ser executado em qualquer porta disponível especificada por meio da variável de ambiente process.env.PORT."
}

6
src/i18n/ru.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "русский",
"commitFix": "fix(server.ts): изменение регистра переменной порта с нижнего регистра port на верхний регистр PORT",
"commitFeat": "feat(server.ts): добавлена поддержка переменной окружения process.env.PORT",
"commitDescription": "Переменная port теперь называется PORT, что улучшает согласованность с соглашениями об именовании констант. Поддержка переменной окружения позволяет приложению быть более гибким, запускаясь на любом доступном порту, указанном с помощью переменной окружения process.env.PORT."
}

View File

@@ -1,6 +1,6 @@
{
"localLanguage": "svenska",
"commitFix": "fixa(server.ts): ändra variabelnamnet för port från små bokstäver till stora bokstäver PORT",
"commitFeat": "nyhet(server.ts): lägg till stöd för process.env.PORT miljövariabel",
"commitDescription": "Variabeln som innehåller portnumret heter nu PORT vilket förbättrar konsekvensen med namngivningskonventionerna eftersom PORT är en konstant. Stöd för en miljövariabel gör att applikationen kan vara mer flexibel då den nu kan köras på vilken port som helst som specificeras via miljövariabeln process.env.PORT."
}
"localLanguage": "svenska",
"commitFix": "fixa(server.ts): ändra variabelnamnet för port från små bokstäver till stora bokstäver PORT",
"commitFeat": "nyhet(server.ts): lägg till stöd för process.env.PORT miljövariabel",
"commitDescription": "Variabeln som innehåller portnumret heter nu PORT vilket förbättrar konsekvensen med namngivningskonventionerna eftersom PORT är en konstant. Stöd för en miljövariabel gör att applikationen kan vara mer flexibel då den nu kan köras på vilken port som helst som specificeras via miljövariabeln process.env.PORT."
}

6
src/i18n/th.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "ไทย",
"commitFix": "fix(server.ts): เปลี่ยนตัวพิมพ์ของตัวแปร จากตัวพิมพ์เล็ก port เป็นตัวพิมพ์ใหญ่ PORT",
"commitFeat": "feat(server.ts): เพิ่มการรองรับสำหรับตัวแปรสภาพแวดล้อม process.env.PORT",
"commitDescription": "ตอนนี้ตัวแปรพอร์ตมีชื่อว่า PORT, ซึ่งปรับปรุงความสอดคล้องกับหลักการตั้งชื่อเนื่องจาก PORT เป็นค่าคงที่. การสนับสนุนสำหรับตัวแปรสภาพแวดล้อม ช่วยให้แอปพลิเคชันมีความยืดหยุ่นมากขึ้นเนื่องจาก สามารถทำงานบนพอร์ตใด ๆ ตามที่กำหนด ซึ่งระบุผ่านตัวแปรสภาพแวดล้อม process.env.PORT"
}

6
src/i18n/tr.json Normal file
View File

@@ -0,0 +1,6 @@
{
"localLanguage": "Turkish",
"commitFix": "fix(server.ts): port değişkeni küçük harfli porttan büyük harfli PORT'a değiştirildi",
"commitFeat": "feat(server.ts): process.env.PORT ortam değişkeni için destek eklendi.",
"commitDescription": "Bağlantı noktası değişkeni artık PORT olarak adlandırıldı ve PORT bir sabit değişken olduğu için bu adlandırma tutarlılığı artırır. Ortam değişkeni desteği, artık process.env.PORT ortam değişkeni aracılığıyla belirtilen herhangi bir kullanılabilir bağlantı noktasında çalışabileceğinden uygulamanın daha esnek olmasını sağlar."
}

View File

@@ -25,17 +25,25 @@ export const getOpenCommitIgnore = (): Ignore => {
return ig;
};
export const getCoreHooksPath = async(): Promise<string> => {
const { stdout } = await execa('git', [
'config',
'core.hooksPath']);
return stdout;
}
export const getStagedFiles = async (): Promise<string[]> => {
const { stdout: gitDir } = await execa("git", [
"rev-parse",
"--show-toplevel"
const { stdout: gitDir } = await execa('git', [
'rev-parse',
'--show-toplevel'
]);
const { stdout: files } = await execa("git", [
"diff",
"--name-only",
"--cached",
"--relative",
const { stdout: files } = await execa('git', [
'diff',
'--name-only',
'--cached',
'--relative',
gitDir
]);

View File

@@ -0,0 +1,4 @@
export function randomIntFromInterval(min: number, max: number) {
// min and max included
return Math.floor(Math.random() * (max - min + 1) + min);
}

3
src/utils/sleep.ts Normal file
View File

@@ -0,0 +1,3 @@
export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

View File

@@ -1,14 +1,13 @@
// import { Tiktoken } from '@dqbd/tiktoken/lite';
// import cl100k_base from '@dqbd/tiktoken/encoders/cl100k_base.json' assert { type: 'json' };
import { Tiktoken } from '@dqbd/tiktoken/lite';
import cl100k_base from '@dqbd/tiktoken/encoders/cl100k_base.json' assert { type: 'json' };
export function tokenCount(content: string): number {
// const encoding = new Tiktoken(
// cl100k_base.bpe_ranks,
// cl100k_base.special_tokens,
// cl100k_base.pat_str
// );
// const tokens = encoding.encode(content);
// encoding.free();
return content.length / 2.7;
const encoding = new Tiktoken(
cl100k_base.bpe_ranks,
cl100k_base.special_tokens,
cl100k_base.pat_str
);
const tokens = encoding.encode(content);
encoding.free();
return tokens.length;
}