Compare commits

...

28 Commits

Author SHA1 Message Date
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
20 changed files with 272 additions and 60 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

2
.yml Normal file
View File

@@ -0,0 +1,2 @@
- name: Close Stale Issues
uses: actions/stale@v4.1.1

14
esbuild.config.js Normal file
View File

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

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "opencommit",
"version": "1.1.36",
"version": "1.1.47",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "opencommit",
"version": "1.1.36",
"version": "1.1.47",
"license": "MIT",
"dependencies": {
"@clack/prompts": "^0.6.1",

View File

@@ -1,6 +1,6 @@
{
"name": "opencommit",
"version": "1.1.36",
"version": "1.1.47",
"description": "GPT CLI to auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
"keywords": [
"git",
@@ -40,7 +40,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"
@@ -60,6 +60,7 @@
},
"dependencies": {
"@clack/prompts": "^0.6.1",
"@dqbd/tiktoken": "^1.0.2",
"axios": "^1.3.4",
"chalk": "^5.2.0",
"cleye": "^1.3.2",

View File

@@ -12,6 +12,7 @@ import { CONFIG_MODES, getConfig } from './commands/config';
const config = getConfig();
let apiKey = config?.OPENAI_API_KEY;
let basePath = config?.OPENAI_BASE_PATH;
const [command, mode] = process.argv.slice(2);
@@ -32,8 +33,14 @@ 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>

View File

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

View File

@@ -79,6 +79,12 @@ ${chalk.grey('——————————————————')}`
const remotes = await getGitRemotes();
if (!remotes.length) {
const { stdout } = await execa('git', ['push']);
if (stdout) outro(stdout);
process.exit(0);
}
if (remotes.length === 1) {
const isPushConfirmedByUser = await confirm({
message: 'Do you want to run `git push`?'

View File

@@ -10,6 +10,7 @@ import { getI18nLocal } from '../i18n';
export enum CONFIG_KEYS {
OPENAI_API_KEY = 'OPENAI_API_KEY',
OPENAI_BASE_PATH = 'OPENAI_BASE_PATH',
description = 'description',
emoji = 'emoji',
language = 'language'
@@ -78,6 +79,15 @@ export const configValidators = {
`${value} is not supported yet`
);
return getI18nLocal(value);
},
[CONFIG_KEYS.OPENAI_BASE_PATH](value: any) {
validateConfig(
CONFIG_KEYS.OPENAI_BASE_PATH,
typeof value == 'string',
`${value} is not supported yet`
);
return value;
}
};

View File

@@ -1,35 +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';
const platform = process.platform;
let separator = '';
switch (platform) {
case 'win32': // Windows
separator = path.sep;
break;
case 'darwin': // macOS
separator = '';
break;
case 'linux': // Linux
separator = '';
break;
default:
throw new Error(`Unsupported platform: ${platform}`);
}
const HOOK_NAME = 'prepare-commit-msg';
const SYMLINK_URL = path.join(separator, '.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(
{
@@ -38,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);
@@ -72,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`
);

View File

@@ -7,7 +7,9 @@ import { generateCommitMessageWithChatCompletion } from '../generateCommitMessag
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;

View File

@@ -13,6 +13,8 @@ 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 th from '../i18n/th.json' assert { type: 'json' };
export enum I18nLocals {
'en' = 'en',
@@ -28,7 +30,9 @@ export enum I18nLocals {
'es_ES' = 'es_ES',
'sv' = 'sv',
'ru' = 'ru',
'id_ID' = 'id_ID'
'id_ID' = 'id_ID',
'pl' = 'pl',
'th' = 'th',
}
export const i18n = {
@@ -46,7 +50,9 @@ export const i18n = {
sv,
id_ID,
nl,
ru
ru,
pl,
th
};
export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
@@ -64,7 +70,9 @@ export const I18N_CONFIG_ALIAS: { [key: string]: string[] } = {
es_ES: ['es_ES', 'Spanish', 'español'],
sv: ['sv', 'Swedish', 'Svenska'],
ru: ['ru', 'Russian', 'русский'],
id_ID: ['id_ID', 'Bahasa', 'bahasa']
id_ID: ['id_ID', 'Bahasa', 'bahasa'],
pl: ['pl', 'Polish', 'Polski'],
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/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."
}

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"
}

View File

@@ -25,6 +25,14 @@ 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',

View File

@@ -1,14 +1,15 @@
// 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();
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;
return content.length / 2.7;
//return content.length / 2.7;
}