git-repo-comitter 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +3 -0
- package/.eslintrc.cjs +19 -0
- package/.github/workflows/publish.yml +29 -0
- package/.prettierrc +7 -0
- package/LICENSE +24 -0
- package/config.yaml +16 -0
- package/docs/feature/01./345/210/235/345/247/213/345/214/226/351/241/271/347/233/256.md +143 -0
- package/package.json +49 -0
- package/src/commit.ts +12 -0
- package/src/config.ts +73 -0
- package/src/git.ts +47 -0
- package/src/index.ts +33 -0
- package/src/llm.ts +45 -0
- package/tsconfig.json +18 -0
- package/vite.config.ts +18 -0
package/.env.example
ADDED
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
parser: "@typescript-eslint/parser",
|
|
4
|
+
plugins: ["@typescript-eslint"],
|
|
5
|
+
extends: [
|
|
6
|
+
"eslint:recommended",
|
|
7
|
+
"plugin:@typescript-eslint/recommended",
|
|
8
|
+
"prettier",
|
|
9
|
+
],
|
|
10
|
+
env: {
|
|
11
|
+
node: true,
|
|
12
|
+
es2020: true,
|
|
13
|
+
},
|
|
14
|
+
parserOptions: {
|
|
15
|
+
ecmaVersion: 2020,
|
|
16
|
+
sourceType: "module",
|
|
17
|
+
},
|
|
18
|
+
rules: {},
|
|
19
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: pnpm/action-setup@v4
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: "20"
|
|
23
|
+
registry-url: "https://registry.npmjs.org"
|
|
24
|
+
|
|
25
|
+
- run: pnpm install --frozen-lockfile
|
|
26
|
+
|
|
27
|
+
- run: pnpm build
|
|
28
|
+
|
|
29
|
+
- run: npm publish --provenance --access public
|
package/.prettierrc
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <https://unlicense.org>
|
package/config.yaml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Git Repo Committer 配置文件
|
|
2
|
+
|
|
3
|
+
# 大模型配置
|
|
4
|
+
llm:
|
|
5
|
+
model: "gpt-4"
|
|
6
|
+
temperature: 0.7
|
|
7
|
+
max_tokens: 256
|
|
8
|
+
|
|
9
|
+
# 生成风格模板
|
|
10
|
+
style:
|
|
11
|
+
language: "zh-CN"
|
|
12
|
+
template: "conventional" # conventional | conventional-commit | custom
|
|
13
|
+
|
|
14
|
+
# Git 目录路径(默认为当前目录)
|
|
15
|
+
git:
|
|
16
|
+
repoPath: "."
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# 项目初始化
|
|
2
|
+
|
|
3
|
+
## 项目概述
|
|
4
|
+
|
|
5
|
+
本项目是一个基于 TypeScript 的前端工具,用于调用大语言模型(采用 OpenAI 兼容格式),管理 Git 差异(diff),自动生成 Git 提交信息(commit message),并执行提交操作。
|
|
6
|
+
|
|
7
|
+
## 技术栈
|
|
8
|
+
|
|
9
|
+
- 编程语言:TypeScript
|
|
10
|
+
- 构建工具:Vite
|
|
11
|
+
- 包管理器:npm
|
|
12
|
+
- 代码格式化:Prettier + ESLint
|
|
13
|
+
- Git 钩子:husky + lint-staged
|
|
14
|
+
|
|
15
|
+
## 功能需求
|
|
16
|
+
|
|
17
|
+
### 核心功能
|
|
18
|
+
|
|
19
|
+
1. **Git 差异管理**
|
|
20
|
+
- 读取当前 Git 仓库的变更内容(diff)
|
|
21
|
+
- 支持暂存区和工作区的差异提取
|
|
22
|
+
|
|
23
|
+
2. **大模型调用**
|
|
24
|
+
- 调用外部大语言模型 API 生成提交信息(OpenAI 兼容格式)
|
|
25
|
+
- 支持从环境变量读取模型配置:
|
|
26
|
+
- `LLM_API_KEY`:API 密钥
|
|
27
|
+
- `LLM_ENDPOINT`:服务地址(例如 `https://api.openai.com/v1`)
|
|
28
|
+
- `LLM_MODEL`:模型名称(例如 `gpt-4`、`gpt-3.5-turbo`)
|
|
29
|
+
|
|
30
|
+
3. **配置系统**
|
|
31
|
+
- 支持 YAML 配置文件(如 `.git-repo-committer.yaml`)
|
|
32
|
+
- 可配置项包括:
|
|
33
|
+
- 模型选择与参数(model、temperature、max_tokens 等)
|
|
34
|
+
- 生成风格或模板
|
|
35
|
+
- Git 目录路径
|
|
36
|
+
|
|
37
|
+
4. **Git 提交**
|
|
38
|
+
- 自动执行 `git commit` 操作
|
|
39
|
+
- 使用生成的提交信息
|
|
40
|
+
|
|
41
|
+
### 环境变量
|
|
42
|
+
|
|
43
|
+
项目将依赖以下环境变量:
|
|
44
|
+
|
|
45
|
+
- `LLM_API_KEY`:大模型 API 密钥
|
|
46
|
+
- `LLM_ENDPOINT`:大模型服务地址(OpenAI 兼容端点)
|
|
47
|
+
- `LLM_MODEL`:模型名称
|
|
48
|
+
|
|
49
|
+
## 项目结构
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
git-repo-committer/
|
|
53
|
+
├── src/
|
|
54
|
+
│ ├── index.ts # 入口文件
|
|
55
|
+
│ ├── git.ts # Git 差异处理
|
|
56
|
+
│ ├── llm.ts # 大模型调用(OpenAI 兼容)
|
|
57
|
+
│ ├── config.ts # 配置读取
|
|
58
|
+
│ └── commit.ts # 提交管理
|
|
59
|
+
├── config.yaml # YAML 配置文件
|
|
60
|
+
├── .env # 环境变量文件(不提交)
|
|
61
|
+
├── .env.example # 环境变量示例
|
|
62
|
+
├── .eslintrc.cjs # ESLint 配置
|
|
63
|
+
├── .prettierrc # Prettier 配置
|
|
64
|
+
├── tsconfig.json # TypeScript 配置
|
|
65
|
+
├── vite.config.ts # Vite 配置
|
|
66
|
+
├── package.json # 包描述文件
|
|
67
|
+
├── README.md # 项目说明
|
|
68
|
+
└── .gitignore # Git 忽略规则
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 初始化步骤
|
|
72
|
+
|
|
73
|
+
1. **创建项目目录并初始化 npm**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
mkdir git-repo-committer
|
|
77
|
+
cd git-repo-committer
|
|
78
|
+
npm init -y
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
2. **初始化 TypeScript 配置**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install --save-dev typescript
|
|
85
|
+
npx tsc --init
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. **安装 Vite 及相关依赖**
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install --save-dev vite @types/node
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
4. **安装代码格式化工具**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm install --save-dev prettier eslint eslint-config-prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
5. **安装 Git 钩子工具**
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm install --save-dev husky lint-staged
|
|
104
|
+
npx husky init
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
6. **安装运行时依赖**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm install yaml dotenv openai
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
7. **创建配置文件**
|
|
114
|
+
|
|
115
|
+
- 创建 `.env.example` 和 `.env`(写入环境变量)
|
|
116
|
+
- 创建 `config.yaml`(定义模型参数和模板)
|
|
117
|
+
- 创建 `.eslintrc.cjs`、`.prettierrc` 配置规则
|
|
118
|
+
- 创建 `vite.config.ts` 定义构建目标
|
|
119
|
+
|
|
120
|
+
8. **实现核心模块**
|
|
121
|
+
|
|
122
|
+
- `src/config.ts`:读取 YAML 配置和 `.env` 环境变量
|
|
123
|
+
- `src/git.ts`:执行 `git diff` 命令并解析结果
|
|
124
|
+
- `src/llm.ts`:使用 OpenAI SDK 调用兼容 API
|
|
125
|
+
- `src/commit.ts`:组装并执行 `git commit -m "..."`
|
|
126
|
+
|
|
127
|
+
9. **完善 package.json 元数据**
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## 发布计划
|
|
131
|
+
|
|
132
|
+
项目完成后将发布到 npm registry,作为命令行工具(CLI)供开发者使用。发布步骤:
|
|
133
|
+
|
|
134
|
+
1. 确保 `package.json` 中已填入正确的 GitHub 仓库地址和元信息
|
|
135
|
+
2. 运行 `npm run build` 构建产物
|
|
136
|
+
3. 执行 `npm publish` 发布
|
|
137
|
+
|
|
138
|
+
## 注意事项
|
|
139
|
+
|
|
140
|
+
- 确保 `.gitignore` 包含 `node_modules`、`dist`、`.env` 等目录
|
|
141
|
+
- 环境变量文件 `.env` 不应提交到版本控制系统
|
|
142
|
+
- 使用 `openai` 包时需配置 `baseURL` 为 `LLM_ENDPOINT` 的值
|
|
143
|
+
- 代码提交前会通过 husky + lint-staged 自动执行 ESLint 和 Prettier 格式化
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-repo-comitter",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "A CLI tool that uses LLM to generate Git commit messages and execute commits",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"git-repo-comitter": "dist/index.cjs"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"git",
|
|
12
|
+
"commit",
|
|
13
|
+
"llm",
|
|
14
|
+
"ai",
|
|
15
|
+
"openai"
|
|
16
|
+
],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "unlicense",
|
|
19
|
+
"lint-staged": {
|
|
20
|
+
"*.ts": [
|
|
21
|
+
"prettier --write",
|
|
22
|
+
"eslint --fix"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^26.1.1",
|
|
27
|
+
"@typescript-eslint/eslint-plugin": "^8.63.0",
|
|
28
|
+
"@typescript-eslint/parser": "^8.63.0",
|
|
29
|
+
"eslint": "^10.7.0",
|
|
30
|
+
"eslint-config-prettier": "^10.1.8",
|
|
31
|
+
"husky": "^9.1.7",
|
|
32
|
+
"lint-staged": "^16.4.0",
|
|
33
|
+
"prettier": "^3.9.5",
|
|
34
|
+
"typescript": "^6.0.3",
|
|
35
|
+
"vite": "^8.1.4"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"dotenv": "^17.4.2",
|
|
39
|
+
"openai": "^6.46.0",
|
|
40
|
+
"yaml": "^2.9.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"dev": "vite",
|
|
44
|
+
"build": "tsc && vite build",
|
|
45
|
+
"preview": "vite preview",
|
|
46
|
+
"lint": "eslint src/",
|
|
47
|
+
"format": "prettier --write \"src/**/*.ts\""
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/commit.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
|
|
3
|
+
export function gitCommit(message: string, repoPath?: string): void {
|
|
4
|
+
const cwd = repoPath || process.cwd();
|
|
5
|
+
const escapedMessage = message.replace(/"/g, '\\"');
|
|
6
|
+
execSync(`git commit -m "${escapedMessage}"`, { cwd, encoding: "utf-8" });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function gitAddAll(repoPath?: string): void {
|
|
10
|
+
const cwd = repoPath || process.cwd();
|
|
11
|
+
execSync("git add -A", { cwd, encoding: "utf-8" });
|
|
12
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import YAML from "yaml";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
|
|
6
|
+
dotenv.config();
|
|
7
|
+
|
|
8
|
+
export interface LLMConfig {
|
|
9
|
+
model: string;
|
|
10
|
+
temperature: number;
|
|
11
|
+
max_tokens: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface StyleConfig {
|
|
15
|
+
language: string;
|
|
16
|
+
template: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface GitConfig {
|
|
20
|
+
repoPath: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AppConfig {
|
|
24
|
+
llm: LLMConfig;
|
|
25
|
+
style: StyleConfig;
|
|
26
|
+
git: GitConfig;
|
|
27
|
+
apiKey: string;
|
|
28
|
+
endpoint: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DEFAULT_CONFIG: AppConfig = {
|
|
32
|
+
llm: {
|
|
33
|
+
model: "gpt-4",
|
|
34
|
+
temperature: 0.7,
|
|
35
|
+
max_tokens: 256,
|
|
36
|
+
},
|
|
37
|
+
style: {
|
|
38
|
+
language: "zh-CN",
|
|
39
|
+
template: "conventional",
|
|
40
|
+
},
|
|
41
|
+
git: {
|
|
42
|
+
repoPath: ".",
|
|
43
|
+
},
|
|
44
|
+
apiKey: "",
|
|
45
|
+
endpoint: "https://api.openai.com/v1",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export function loadConfig(configPath?: string): AppConfig {
|
|
49
|
+
const configFile =
|
|
50
|
+
configPath ||
|
|
51
|
+
[
|
|
52
|
+
".git-repo-committer.yaml",
|
|
53
|
+
".git-repo-committer.yml",
|
|
54
|
+
"config.yaml",
|
|
55
|
+
].find((f) => existsSync(resolve(process.cwd(), f)));
|
|
56
|
+
|
|
57
|
+
let fileConfig: Partial<AppConfig> = {};
|
|
58
|
+
|
|
59
|
+
if (configFile) {
|
|
60
|
+
const content = readFileSync(resolve(process.cwd(), configFile), "utf-8");
|
|
61
|
+
fileConfig = YAML.parse(content);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
...DEFAULT_CONFIG,
|
|
66
|
+
...fileConfig,
|
|
67
|
+
llm: { ...DEFAULT_CONFIG.llm, ...(fileConfig.llm || {}) },
|
|
68
|
+
style: { ...DEFAULT_CONFIG.style, ...(fileConfig.style || {}) },
|
|
69
|
+
git: { ...DEFAULT_CONFIG.git, ...(fileConfig.git || {}) },
|
|
70
|
+
apiKey: process.env.LLM_API_KEY || fileConfig.apiKey || "",
|
|
71
|
+
endpoint: process.env.LLM_ENDPOINT || fileConfig.endpoint || DEFAULT_CONFIG.endpoint,
|
|
72
|
+
};
|
|
73
|
+
}
|
package/src/git.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
|
|
3
|
+
export function getStagedDiff(repoPath?: string): string {
|
|
4
|
+
const cwd = repoPath || process.cwd();
|
|
5
|
+
try {
|
|
6
|
+
return execSync("git diff --cached", { cwd, encoding: "utf-8" });
|
|
7
|
+
} catch {
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getUnstagedDiff(repoPath?: string): string {
|
|
13
|
+
const cwd = repoPath || process.cwd();
|
|
14
|
+
try {
|
|
15
|
+
return execSync("git diff", { cwd, encoding: "utf-8" });
|
|
16
|
+
} catch {
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getAllDiff(repoPath?: string): string {
|
|
22
|
+
const cwd = repoPath || process.cwd();
|
|
23
|
+
const staged = getStagedDiff(cwd);
|
|
24
|
+
const unstaged = getUnstagedDiff(cwd);
|
|
25
|
+
|
|
26
|
+
const parts: string[] = [];
|
|
27
|
+
if (staged.trim()) {
|
|
28
|
+
parts.push("=== Staged Changes ===\n" + staged);
|
|
29
|
+
}
|
|
30
|
+
if (unstaged.trim()) {
|
|
31
|
+
parts.push("=== Unstaged Changes ===\n" + unstaged);
|
|
32
|
+
}
|
|
33
|
+
return parts.join("\n\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function hasStagedChanges(repoPath?: string): boolean {
|
|
37
|
+
const cwd = repoPath || process.cwd();
|
|
38
|
+
try {
|
|
39
|
+
const result = execSync("git diff --cached --name-only", {
|
|
40
|
+
cwd,
|
|
41
|
+
encoding: "utf-8",
|
|
42
|
+
});
|
|
43
|
+
return result.trim().length > 0;
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { loadConfig } from "./config";
|
|
4
|
+
import { getAllDiff, hasStagedChanges } from "./git";
|
|
5
|
+
import { generateCommitMessage } from "./llm";
|
|
6
|
+
import { gitCommit, gitAddAll } from "./commit";
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
|
|
11
|
+
if (!hasStagedChanges(config.git.repoPath)) {
|
|
12
|
+
console.log("No staged changes found. Staging all changes...");
|
|
13
|
+
gitAddAll(config.git.repoPath);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const diff = getAllDiff(config.git.repoPath);
|
|
17
|
+
if (!diff.trim()) {
|
|
18
|
+
console.log("No changes to commit.");
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.log("Generating commit message...\n");
|
|
23
|
+
const message = await generateCommitMessage(diff, config);
|
|
24
|
+
console.log(`Commit message:\n ${message}\n`);
|
|
25
|
+
|
|
26
|
+
gitCommit(message, config.git.repoPath);
|
|
27
|
+
console.log("Commit successful!");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
main().catch((err) => {
|
|
31
|
+
console.error("Error:", err.message);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
package/src/llm.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
import type { AppConfig } from "./config";
|
|
3
|
+
|
|
4
|
+
const SYSTEM_PROMPT = `You are an expert at writing Git commit messages.
|
|
5
|
+
Based on the provided Git diff, generate a concise and descriptive commit message.
|
|
6
|
+
Follow the Conventional Commits format: <type>(<scope>): <description>
|
|
7
|
+
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
8
|
+
Keep the message under 72 characters for the subject line.
|
|
9
|
+
If there are significant changes, add a blank line followed by a more detailed body.
|
|
10
|
+
Respond with ONLY the commit message, no explanation.`;
|
|
11
|
+
|
|
12
|
+
export async function generateCommitMessage(
|
|
13
|
+
diff: string,
|
|
14
|
+
config: AppConfig,
|
|
15
|
+
): Promise<string> {
|
|
16
|
+
if (!config.apiKey) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"LLM_API_KEY is not set. Please set it in .env or environment variables.",
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const client = new OpenAI({
|
|
23
|
+
apiKey: config.apiKey,
|
|
24
|
+
baseURL: config.endpoint,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const response = await client.chat.completions.create({
|
|
28
|
+
model: config.llm.model,
|
|
29
|
+
temperature: config.llm.temperature,
|
|
30
|
+
max_tokens: config.llm.max_tokens,
|
|
31
|
+
messages: [
|
|
32
|
+
{ role: "system", content: SYSTEM_PROMPT },
|
|
33
|
+
{
|
|
34
|
+
role: "user",
|
|
35
|
+
content: `Here is the Git diff:\n\n${diff}`,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const message = response.choices[0]?.message?.content?.trim();
|
|
41
|
+
if (!message) {
|
|
42
|
+
throw new Error("LLM returned an empty commit message.");
|
|
43
|
+
}
|
|
44
|
+
return message;
|
|
45
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"outDir": "./dist",
|
|
13
|
+
"rootDir": "./src",
|
|
14
|
+
"sourceMap": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
build: {
|
|
6
|
+
lib: {
|
|
7
|
+
entry: resolve(__dirname, "src/index.ts"),
|
|
8
|
+
name: "git-repo-comitter",
|
|
9
|
+
fileName: "index",
|
|
10
|
+
formats: ["cjs"],
|
|
11
|
+
},
|
|
12
|
+
outDir: "dist",
|
|
13
|
+
sourcemap: true,
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
external: ["openai", "yaml", "dotenv"],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|