refactor(llm): 拆分提示词与提交解析逻辑到独立模块
将 21 个多语言提示词及选择函数迁入 prompts 模块,将 commit 响应 解析与 GeneratedCommit 迁入 parsing 模块,为 rig 迁移期间新旧 实现共享同一份提示词与解析逻辑做准备。无行为变化。
This commit is contained in:
908
src/llm/mod.rs
908
src/llm/mod.rs
@@ -9,6 +9,8 @@ pub mod kimi;
|
|||||||
pub mod ollama;
|
pub mod ollama;
|
||||||
pub mod openai;
|
pub mod openai;
|
||||||
pub mod openrouter;
|
pub mod openrouter;
|
||||||
|
pub mod parsing;
|
||||||
|
pub mod prompts;
|
||||||
pub mod thinking;
|
pub mod thinking;
|
||||||
|
|
||||||
pub use anthropic::AnthropicClient;
|
pub use anthropic::AnthropicClient;
|
||||||
@@ -17,6 +19,7 @@ pub use kimi::KimiClient;
|
|||||||
pub use ollama::OllamaClient;
|
pub use ollama::OllamaClient;
|
||||||
pub use openai::OpenAiClient;
|
pub use openai::OpenAiClient;
|
||||||
pub use openrouter::OpenRouterClient;
|
pub use openrouter::OpenRouterClient;
|
||||||
|
pub use parsing::GeneratedCommit;
|
||||||
|
|
||||||
/// LLM provider trait
|
/// LLM provider trait
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -203,7 +206,7 @@ impl LlmClient {
|
|||||||
language: Language,
|
language: Language,
|
||||||
template: Option<&str>,
|
template: Option<&str>,
|
||||||
) -> Result<GeneratedCommit> {
|
) -> Result<GeneratedCommit> {
|
||||||
let mut system_prompt = get_commit_system_prompt(format, language).to_string();
|
let mut system_prompt = prompts::get_commit_system_prompt(format, language).to_string();
|
||||||
|
|
||||||
if let Some(tmpl) = template {
|
if let Some(tmpl) = template {
|
||||||
system_prompt.push_str(&format!(
|
system_prompt.push_str(&format!(
|
||||||
@@ -229,7 +232,7 @@ impl LlmClient {
|
|||||||
.generate_with_system(&system_prompt, &prompt)
|
.generate_with_system(&system_prompt, &prompt)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
self.parse_commit_response(&response, format)
|
parsing::parse_commit_response(&response, format)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate tag message from commits
|
/// Generate tag message from commits
|
||||||
@@ -239,7 +242,7 @@ impl LlmClient {
|
|||||||
commits: &[String],
|
commits: &[String],
|
||||||
language: Language,
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let system_prompt = get_tag_system_prompt(language);
|
let system_prompt = prompts::get_tag_system_prompt(language);
|
||||||
let commits_text = commits.join("\n");
|
let commits_text = commits.join("\n");
|
||||||
|
|
||||||
// Add language instruction to the prompt
|
// Add language instruction to the prompt
|
||||||
@@ -270,7 +273,7 @@ impl LlmClient {
|
|||||||
commits: &[(String, String)], // (type, message)
|
commits: &[(String, String)], // (type, message)
|
||||||
language: Language,
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let system_prompt = get_changelog_system_prompt(language);
|
let system_prompt = prompts::get_changelog_system_prompt(language);
|
||||||
|
|
||||||
let commits_text = commits
|
let commits_text = commits
|
||||||
.iter()
|
.iter()
|
||||||
@@ -304,289 +307,8 @@ impl LlmClient {
|
|||||||
self.provider.is_available().await
|
self.provider.is_available().await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse commit response from LLM
|
|
||||||
fn parse_commit_response(
|
|
||||||
&self,
|
|
||||||
response: &str,
|
|
||||||
format: crate::config::CommitFormat,
|
|
||||||
) -> Result<GeneratedCommit> {
|
|
||||||
// Clean markdown code fences from the response
|
|
||||||
let cleaned = Self::strip_code_fences(response);
|
|
||||||
|
|
||||||
let lines: Vec<&str> = cleaned
|
|
||||||
.lines()
|
|
||||||
.map(|l| l.trim())
|
|
||||||
.filter(|l| !l.is_empty())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if lines.is_empty() {
|
|
||||||
let preview: String = response.chars().take(200).collect();
|
|
||||||
bail!(
|
|
||||||
"LLM returned empty or whitespace-only response. \
|
|
||||||
Raw response preview: '{}'. \
|
|
||||||
Hint: If using DeepSeek/Kimi with thinking enabled, \
|
|
||||||
the model may have returned reasoning_content only. \
|
|
||||||
Try disabling thinking mode or switching models.",
|
|
||||||
preview
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the line most likely to be the commit subject
|
|
||||||
let first_line = Self::find_commit_subject_line(&lines, format);
|
|
||||||
|
|
||||||
// Parse based on format
|
|
||||||
match format {
|
|
||||||
crate::config::CommitFormat::Conventional => {
|
|
||||||
self.parse_conventional_commit(first_line, &lines, response)
|
|
||||||
}
|
|
||||||
crate::config::CommitFormat::Commitlint => {
|
|
||||||
self.parse_commitlint_commit(first_line, &lines, response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove surrounding markdown code fences (```) from LLM output
|
|
||||||
fn strip_code_fences(response: &str) -> String {
|
|
||||||
let mut lines: Vec<&str> = response.lines().collect();
|
|
||||||
|
|
||||||
// Strip leading fence lines (``` or ```lang)
|
|
||||||
while lines.first().map_or(false, |l| l.trim().starts_with("```")) {
|
|
||||||
lines.remove(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip trailing fence lines
|
|
||||||
while lines.last().map_or(false, |l| l.trim() == "```") {
|
|
||||||
lines.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.join("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find the line that is most likely the commit subject among extracted lines
|
|
||||||
fn find_commit_subject_line<'a>(
|
|
||||||
lines: &[&'a str],
|
|
||||||
format: crate::config::CommitFormat,
|
|
||||||
) -> &'a str {
|
|
||||||
let valid_types = crate::utils::validators::get_commit_types(matches!(
|
|
||||||
format,
|
|
||||||
crate::config::CommitFormat::Commitlint
|
|
||||||
));
|
|
||||||
|
|
||||||
// First pass: line starting with a known type that also has proper syntax
|
|
||||||
// (e.g. "type:", "type(scope):", "type!:")
|
|
||||||
for &line in lines {
|
|
||||||
let trimmed = line.trim();
|
|
||||||
for &t in valid_types {
|
|
||||||
if let Some(rest) = trimmed.strip_prefix(t) {
|
|
||||||
if rest.starts_with(':') || rest.starts_with('(') || rest.starts_with("!:") {
|
|
||||||
return trimmed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second pass: any line containing a colon (generic "prefix: description")
|
|
||||||
for &line in lines {
|
|
||||||
if line.contains(':') {
|
|
||||||
return line.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: return the first line as-is
|
|
||||||
lines[0].trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_conventional_commit(
|
|
||||||
&self,
|
|
||||||
first_line: &str,
|
|
||||||
lines: &[&str],
|
|
||||||
raw_response: &str,
|
|
||||||
) -> Result<GeneratedCommit> {
|
|
||||||
// Parse: type(scope)!: description
|
|
||||||
let parts: Vec<&str> = first_line.splitn(2, ':').collect();
|
|
||||||
if parts.len() != 2 {
|
|
||||||
let preview: String = raw_response.chars().take(300).collect();
|
|
||||||
bail!(
|
|
||||||
"Invalid conventional commit format: missing colon.\n\
|
|
||||||
Parsed subject line: '{}'\n\
|
|
||||||
Raw response preview: '{}'\n\
|
|
||||||
Expected: <type>[optional scope]: <description>",
|
|
||||||
first_line,
|
|
||||||
preview
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let type_part = parts[0];
|
|
||||||
let description = parts[1].trim();
|
|
||||||
|
|
||||||
// Extract type, scope, and breaking indicator
|
|
||||||
let breaking = type_part.ends_with('!');
|
|
||||||
let type_part = type_part.trim_end_matches('!');
|
|
||||||
|
|
||||||
let (commit_type, scope) = if let Some(start) = type_part.find('(') {
|
|
||||||
if let Some(end) = type_part.find(')') {
|
|
||||||
let t = &type_part[..start];
|
|
||||||
let s = &type_part[start + 1..end];
|
|
||||||
(t.to_string(), Some(s.to_string()))
|
|
||||||
} else {
|
|
||||||
bail!("Invalid scope format: missing closing parenthesis");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(type_part.to_string(), None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extract body and footer
|
|
||||||
let (body, footer) = self.extract_body_footer(lines);
|
|
||||||
|
|
||||||
Ok(GeneratedCommit {
|
|
||||||
commit_type,
|
|
||||||
scope,
|
|
||||||
description: description.to_string(),
|
|
||||||
body,
|
|
||||||
footer,
|
|
||||||
breaking,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_commitlint_commit(
|
|
||||||
&self,
|
|
||||||
first_line: &str,
|
|
||||||
lines: &[&str],
|
|
||||||
raw_response: &str,
|
|
||||||
) -> Result<GeneratedCommit> {
|
|
||||||
// Similar parsing but with commitlint rules
|
|
||||||
let parts: Vec<&str> = first_line.splitn(2, ':').collect();
|
|
||||||
if parts.len() != 2 {
|
|
||||||
let preview: String = raw_response.chars().take(300).collect();
|
|
||||||
bail!(
|
|
||||||
"Invalid commit format: missing colon.\n\
|
|
||||||
Parsed subject line: '{}'\n\
|
|
||||||
Raw response preview: '{}'\n\
|
|
||||||
Expected: <type>[optional scope]: <subject>",
|
|
||||||
first_line,
|
|
||||||
preview
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let type_part = parts[0];
|
|
||||||
let subject = parts[1].trim();
|
|
||||||
|
|
||||||
let (commit_type, scope) = if let Some(start) = type_part.find('(') {
|
|
||||||
if let Some(end) = type_part.find(')') {
|
|
||||||
let t = &type_part[..start];
|
|
||||||
let s = &type_part[start + 1..end];
|
|
||||||
(t.to_string(), Some(s.to_string()))
|
|
||||||
} else {
|
|
||||||
(type_part.to_string(), None)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(type_part.to_string(), None)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (body, footer) = self.extract_body_footer(&lines);
|
|
||||||
|
|
||||||
Ok(GeneratedCommit {
|
|
||||||
commit_type,
|
|
||||||
scope,
|
|
||||||
description: subject.to_string(),
|
|
||||||
body,
|
|
||||||
footer,
|
|
||||||
breaking: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_body_footer(&self, lines: &[&str]) -> (Option<String>, Option<String>) {
|
|
||||||
if lines.len() <= 1 {
|
|
||||||
return (None, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
let rest: Vec<&str> = lines[1..]
|
|
||||||
.iter()
|
|
||||||
.skip_while(|l| l.trim().is_empty())
|
|
||||||
.copied()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if rest.is_empty() {
|
|
||||||
return (None, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for footer markers
|
|
||||||
let footer_markers = [
|
|
||||||
"BREAKING CHANGE:",
|
|
||||||
"Closes",
|
|
||||||
"Fixes",
|
|
||||||
"Refs",
|
|
||||||
"Co-authored-by:",
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut body_lines = vec![];
|
|
||||||
let mut footer_lines = vec![];
|
|
||||||
let mut in_footer = false;
|
|
||||||
|
|
||||||
for line in &rest {
|
|
||||||
if footer_markers.iter().any(|m| line.starts_with(m)) {
|
|
||||||
in_footer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if in_footer {
|
|
||||||
footer_lines.push(*line);
|
|
||||||
} else {
|
|
||||||
body_lines.push(*line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let body = if body_lines.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(body_lines.join("\n"))
|
|
||||||
};
|
|
||||||
|
|
||||||
let footer = if footer_lines.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(footer_lines.join("\n"))
|
|
||||||
};
|
|
||||||
|
|
||||||
(body, footer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generated commit structure
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct GeneratedCommit {
|
|
||||||
pub commit_type: String,
|
|
||||||
pub scope: Option<String>,
|
|
||||||
pub description: String,
|
|
||||||
pub body: Option<String>,
|
|
||||||
pub footer: Option<String>,
|
|
||||||
pub breaking: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GeneratedCommit {
|
|
||||||
/// Format as conventional commit
|
|
||||||
pub fn to_conventional(&self) -> String {
|
|
||||||
crate::utils::formatter::format_conventional_commit(
|
|
||||||
&self.commit_type,
|
|
||||||
self.scope.as_deref(),
|
|
||||||
&self.description,
|
|
||||||
self.body.as_deref(),
|
|
||||||
self.footer.as_deref(),
|
|
||||||
self.breaking,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Format as commitlint commit
|
|
||||||
pub fn to_commitlint(&self) -> String {
|
|
||||||
crate::utils::formatter::format_commitlint_commit(
|
|
||||||
&self.commit_type,
|
|
||||||
self.scope.as_deref(),
|
|
||||||
&self.description,
|
|
||||||
self.body.as_deref(),
|
|
||||||
self.footer.as_deref(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// HTTP client helper
|
/// HTTP client helper
|
||||||
pub(crate) fn create_http_client(timeout: Duration) -> Result<reqwest::Client> {
|
pub(crate) fn create_http_client(timeout: Duration) -> Result<reqwest::Client> {
|
||||||
@@ -596,622 +318,6 @@ pub(crate) fn create_http_client(timeout: Duration) -> Result<reqwest::Client> {
|
|||||||
.context("Failed to create HTTP client")
|
.context("Failed to create HTTP client")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get commit system prompt based on format and language
|
|
||||||
fn get_commit_system_prompt(
|
|
||||||
format: crate::config::CommitFormat,
|
|
||||||
language: Language,
|
|
||||||
) -> &'static str {
|
|
||||||
match (format, language) {
|
|
||||||
(crate::config::CommitFormat::Conventional, Language::Chinese) => {
|
|
||||||
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ZH
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Conventional, Language::Japanese) => {
|
|
||||||
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_JA
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Conventional, Language::Korean) => {
|
|
||||||
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_KO
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Conventional, Language::Spanish) => {
|
|
||||||
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ES
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Conventional, Language::French) => {
|
|
||||||
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_FR
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Conventional, Language::German) => {
|
|
||||||
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_DE
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Conventional, _) => CONVENTIONAL_COMMIT_SYSTEM_PROMPT,
|
|
||||||
(crate::config::CommitFormat::Commitlint, Language::Chinese) => COMMITLINT_SYSTEM_PROMPT_ZH,
|
|
||||||
(crate::config::CommitFormat::Commitlint, Language::Japanese) => {
|
|
||||||
COMMITLINT_SYSTEM_PROMPT_JA
|
|
||||||
}
|
|
||||||
(crate::config::CommitFormat::Commitlint, Language::Korean) => COMMITLINT_SYSTEM_PROMPT_KO,
|
|
||||||
(crate::config::CommitFormat::Commitlint, Language::Spanish) => COMMITLINT_SYSTEM_PROMPT_ES,
|
|
||||||
(crate::config::CommitFormat::Commitlint, Language::French) => COMMITLINT_SYSTEM_PROMPT_FR,
|
|
||||||
(crate::config::CommitFormat::Commitlint, Language::German) => COMMITLINT_SYSTEM_PROMPT_DE,
|
|
||||||
(crate::config::CommitFormat::Commitlint, _) => COMMITLINT_SYSTEM_PROMPT,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_tag_system_prompt(language: Language) -> &'static str {
|
|
||||||
match language {
|
|
||||||
Language::Chinese => TAG_MESSAGE_SYSTEM_PROMPT_ZH,
|
|
||||||
Language::Japanese => TAG_MESSAGE_SYSTEM_PROMPT_JA,
|
|
||||||
Language::Korean => TAG_MESSAGE_SYSTEM_PROMPT_KO,
|
|
||||||
Language::Spanish => TAG_MESSAGE_SYSTEM_PROMPT_ES,
|
|
||||||
Language::French => TAG_MESSAGE_SYSTEM_PROMPT_FR,
|
|
||||||
Language::German => TAG_MESSAGE_SYSTEM_PROMPT_DE,
|
|
||||||
_ => TAG_MESSAGE_SYSTEM_PROMPT,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_changelog_system_prompt(language: Language) -> &'static str {
|
|
||||||
match language {
|
|
||||||
Language::Chinese => CHANGELOG_SYSTEM_PROMPT_ZH,
|
|
||||||
Language::Japanese => CHANGELOG_SYSTEM_PROMPT_JA,
|
|
||||||
Language::Korean => CHANGELOG_SYSTEM_PROMPT_KO,
|
|
||||||
Language::Spanish => CHANGELOG_SYSTEM_PROMPT_ES,
|
|
||||||
Language::French => CHANGELOG_SYSTEM_PROMPT_FR,
|
|
||||||
Language::German => CHANGELOG_SYSTEM_PROMPT_DE,
|
|
||||||
_ => CHANGELOG_SYSTEM_PROMPT,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// System prompts for LLM
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates conventional commit messages.
|
|
||||||
|
|
||||||
Analyze the git diff provided and generate a commit message following the Conventional Commits specification.
|
|
||||||
|
|
||||||
Format: <type>[optional scope]: <description>
|
|
||||||
|
|
||||||
Types:
|
|
||||||
- feat: A new feature
|
|
||||||
- fix: A bug fix
|
|
||||||
- docs: Documentation only changes
|
|
||||||
- style: Changes that don't affect code meaning (formatting, semicolons, etc.)
|
|
||||||
- refactor: Code change that neither fixes a bug nor adds a feature
|
|
||||||
- perf: Code change that improves performance
|
|
||||||
- test: Adding or correcting tests
|
|
||||||
- build: Changes to build system or dependencies
|
|
||||||
- ci: Changes to CI configuration
|
|
||||||
- chore: Other changes that don't modify src or test files
|
|
||||||
- revert: Reverts a previous commit
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
1. Use lowercase for type and scope
|
|
||||||
2. Keep description under 100 characters
|
|
||||||
3. Use imperative mood ("add" not "added")
|
|
||||||
4. Don't capitalize first letter
|
|
||||||
5. No period at the end
|
|
||||||
6. Include scope if the change is specific to a module/component
|
|
||||||
|
|
||||||
Output ONLY the commit message, nothing else.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成符合 Conventional Commits 规范的提交消息的助手。
|
|
||||||
|
|
||||||
分析提供的 git diff,并生成符合 Conventional Commits 规范的提交消息。
|
|
||||||
|
|
||||||
格式: <type>[可选作用域]: <描述>
|
|
||||||
|
|
||||||
类型:
|
|
||||||
- feat: 新功能
|
|
||||||
- fix: 修复错误
|
|
||||||
- docs: 仅文档更改
|
|
||||||
- style: 不影响代码含义的更改(格式化、分号等)
|
|
||||||
- refactor: 既不修复错误也不添加功能的代码更改
|
|
||||||
- perf: 提高性能的代码更改
|
|
||||||
- test: 添加或更正测试
|
|
||||||
- build: 更改构建系统或依赖项
|
|
||||||
- ci: 更改 CI 配置
|
|
||||||
- chore: 其他不修改 src 或测试文件的更改
|
|
||||||
- revert: 撤销之前的提交
|
|
||||||
|
|
||||||
规则:
|
|
||||||
1. 类型和小写使用小写
|
|
||||||
2. 描述保持在 100 个字符以内
|
|
||||||
3. 使用祈使语气("添加"而不是"已添加")
|
|
||||||
4. 不要大写首字母
|
|
||||||
5. 结尾不要句号
|
|
||||||
6. 如果更改特定于模块/组件,请包含作用域
|
|
||||||
7. 仅输出提交消息,不要输出其他内容。
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_JA: &str = r#"あなたはConventional Commits仕様に従ったコミットメッセージを生成するアシスタントです。
|
|
||||||
|
|
||||||
提供されたgit diffを分析し、Conventional Commits仕様に従ったコミットメッセージを生成してください。
|
|
||||||
|
|
||||||
形式: <type>[オプションのスコープ]: <説明>
|
|
||||||
|
|
||||||
タイプ:
|
|
||||||
- feat: 新機能
|
|
||||||
- fix: バグ修正
|
|
||||||
- docs: ドキュメントのみの変更
|
|
||||||
- style: コードの意味に影響しない変更(フォーマット、セミコロンなど)
|
|
||||||
- refactor: バグ修正や機能追加を伴わないコード変更
|
|
||||||
- perf: パフォーマンスを向上させるコード変更
|
|
||||||
- test: テストの追加または修正
|
|
||||||
- build: ビルドシステムまたは依存関係の変更
|
|
||||||
- ci: CI設定の変更
|
|
||||||
- chore: srcやテストファイルを変更しないその他の変更
|
|
||||||
- revert: 以前のコミットを取り消す
|
|
||||||
|
|
||||||
ルール:
|
|
||||||
1. タイプとスコープは小文字を使用
|
|
||||||
2. 説明は100文字以内にする
|
|
||||||
3. 命令形を使用する("追加"ではなく"追加する")
|
|
||||||
4. 先頭を大文字にしない
|
|
||||||
5. 最後にピリオドを付けない
|
|
||||||
6. 変更がモジュール/コンポーネントに固有の場合はスコープを含める
|
|
||||||
7. コミットメッセージのみを出力し、それ以外は出力しないでください。
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_KO: &str = r#"당신은 Conventional Commits 사양에 따른 커밋 메시지를 생성하는 도우미입니다.
|
|
||||||
|
|
||||||
제공된 git diff를 분석하고 Conventional Commits 사양에 따른 커밋 메시지를 생성하세요.
|
|
||||||
|
|
||||||
형식: <type>[선택적 범위]: <설명>
|
|
||||||
|
|
||||||
유형:
|
|
||||||
- feat: 새 기능
|
|
||||||
- fix: 버그 수정
|
|
||||||
- docs: 문서 변경만
|
|
||||||
- style: 코드 의미에 영향을 주지 않는 변경(서식, 세미콜론 등)
|
|
||||||
- refactor: 버그를 수정하거나 기능을 추가하지 않는 코드 변경
|
|
||||||
- perf: 성능을 향상시키는 코드 변경
|
|
||||||
- test: 테스트 추가 또는 수정
|
|
||||||
- build: 빌드 시스템 또는 종속성 변경
|
|
||||||
- ci: CI 구성 변경
|
|
||||||
- chore: src 또는 테스트 파일을 수정하지 않는 기타 변경
|
|
||||||
- revert: 이전 커밋 되돌리기
|
|
||||||
|
|
||||||
규칙:
|
|
||||||
1. 유형과 범위는 소문자 사용
|
|
||||||
2. 설명은 100자 이내로 유지
|
|
||||||
3. 명령형 사용("추가"가 아닌 "추가하다")
|
|
||||||
4. 첫 글자 대문자화하지 않음
|
|
||||||
5. 끝에 마침표 사용하지 않음
|
|
||||||
6. 변경 사항이 모듈/구성 요소에 특정한 경우 범위 포함
|
|
||||||
7. 커밋 메시지만 출력하고 다른 내용은 출력하지 마세요.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera mensajes de commit siguiendo la especificación Conventional Commits.
|
|
||||||
|
|
||||||
Analiza el diff de git proporcionado y genera un mensaje de commit siguiendo la especificación Conventional Commits.
|
|
||||||
|
|
||||||
Formato: <tipo>[alcance opcional]: <descripción>
|
|
||||||
|
|
||||||
Tipos:
|
|
||||||
- feat: Una nueva característica
|
|
||||||
- fix: Una corrección de error
|
|
||||||
- docs: Solo cambios en documentación
|
|
||||||
- style: Cambios que no afectan el significado del código (formato, punto y coma, etc.)
|
|
||||||
- refactor: Cambio de código que no corrige un error ni agrega una característica
|
|
||||||
- perf: Cambio de código que mejora el rendimiento
|
|
||||||
- test: Agregar o corregir pruebas
|
|
||||||
- build: Cambios en el sistema de construcción o dependencias
|
|
||||||
- ci: Cambios en la configuración de CI
|
|
||||||
- chore: Otros cambios que no modifican archivos src o de prueba
|
|
||||||
- revert: Revierte un commit anterior
|
|
||||||
|
|
||||||
Reglas:
|
|
||||||
1. Usa minúsculas para tipo y alcance
|
|
||||||
2. Mantén la descripción bajo 100 caracteres
|
|
||||||
3. Usa modo imperativo ("agregar" no "agregado")
|
|
||||||
4. No capitalices la primera letra
|
|
||||||
5. Sin punto al final
|
|
||||||
6. Incluye alcance si el cambio es específico de un módulo/componente
|
|
||||||
7. Genera SOLO el mensaje de commit, nada más.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des messages de commit suivant la spécification Conventional Commits.
|
|
||||||
|
|
||||||
Analysez le diff git fourni et générez un message de commit suivant la spécification Conventional Commits.
|
|
||||||
|
|
||||||
Format: <type>[portée optionnelle]: <description>
|
|
||||||
|
|
||||||
Types:
|
|
||||||
- feat: Une nouvelle fonctionnalité
|
|
||||||
- fix: Une correction de bug
|
|
||||||
- docs: Changements de documentation uniquement
|
|
||||||
- style: Changements qui n'affectent pas la signification du code (formatage, points-virgules, etc.)
|
|
||||||
- refactor: Changement de code qui ne corrige pas un bug ni n'ajoute une fonctionnalité
|
|
||||||
- perf: Changement de code qui améliore les performances
|
|
||||||
- test: Ajout ou correction de tests
|
|
||||||
- build: Changements du système de build ou des dépendances
|
|
||||||
- ci: Changements de la configuration CI
|
|
||||||
- chore: Autres changements qui ne modifient pas les fichiers src ou de test
|
|
||||||
- revert: Révertit un commit précédent
|
|
||||||
|
|
||||||
Règles:
|
|
||||||
1. Utilisez des minuscules pour le type et la portée
|
|
||||||
2. Gardez la description sous 100 caractères
|
|
||||||
3. Utilisez le mode impératif ("ajouter" non "ajouté")
|
|
||||||
4. Ne capitalisez pas la première lettre
|
|
||||||
5. Pas de point à la fin
|
|
||||||
6. Incluez la portée si le changement est spécifique à un module/composant
|
|
||||||
7. Générez SEULEMENT le message de commit, rien d'autre.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der Commit-Nachrichten gemäß der Conventional Commits-Spezifikation generiert.
|
|
||||||
|
|
||||||
Analysieren Sie den bereitgestellten git diff und generieren Sie eine Commit-Nachricht gemäß der Conventional Commits-Spezifikation.
|
|
||||||
|
|
||||||
Format: <typ>[optionaler Bereich]: <beschreibung>
|
|
||||||
|
|
||||||
Typen:
|
|
||||||
- feat: Eine neue Funktion
|
|
||||||
- fix: Ein Bugfix
|
|
||||||
- docs: Nur Dokumentationsänderungen
|
|
||||||
- style: Änderungen, die die Code-Bedeutung nicht beeinflussen (Formatierung, Semikolons usw.)
|
|
||||||
- refactor: Code-Änderung, die weder einen Bug behebt noch eine Funktion hinzufügt
|
|
||||||
- perf: Code-Änderung, die die Leistung verbessert
|
|
||||||
- test: Hinzufügen oder Korrigieren von Tests
|
|
||||||
- build: Änderungen am Build-System oder Abhängigkeiten
|
|
||||||
- ci: Änderungen an der CI-Konfiguration
|
|
||||||
- chore: Andere Änderungen, die src- oder Testdateien nicht ändern
|
|
||||||
- revert: Setzt einen vorherigen Commit zurück
|
|
||||||
|
|
||||||
Regeln:
|
|
||||||
1. Verwenden Sie Kleinbuchstaben für Typ und Bereich
|
|
||||||
2. Halten Sie die Beschreibung unter 100 Zeichen
|
|
||||||
3. Verwenden Sie den Imperativ ("hinzufügen" nicht "hinzugefügt")
|
|
||||||
4. Großschreiben Sie den ersten Buchstaben nicht
|
|
||||||
5. Kein Punkt am Ende
|
|
||||||
6. Fügen Sie einen Bereich ein, wenn die Änderung spezifisch für ein Modul/Komponente ist
|
|
||||||
7. Geben Sie NUR die Commit-Nachricht aus, nichts anderes.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates commit messages following @commitlint/config-conventional.
|
|
||||||
|
|
||||||
Analyze the git diff and generate a commit message.
|
|
||||||
|
|
||||||
Format: <type>[optional scope]: <subject>
|
|
||||||
|
|
||||||
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
1. Subject should not start with uppercase
|
|
||||||
2. Subject should not end with period
|
|
||||||
3. Subject should be 4-100 characters
|
|
||||||
4. Use imperative mood
|
|
||||||
5. Be concise but descriptive
|
|
||||||
6. Output ONLY the commit message, nothing else.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成符合 @commitlint/config-conventional 规范的提交消息的助手。
|
|
||||||
|
|
||||||
分析 git diff 并生成提交消息。
|
|
||||||
|
|
||||||
格式: <type>[可选作用域]: <主题>
|
|
||||||
|
|
||||||
类型: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
规则:
|
|
||||||
1. 主题不应以大写字母开头
|
|
||||||
2. 主题不应以句号结尾
|
|
||||||
3. 主题应为 4-100 个字符
|
|
||||||
4. 使用祈使语气
|
|
||||||
5. 简洁但描述性强
|
|
||||||
6. 仅输出提交消息,不要输出其他额外内容。
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT_JA: &str = r#"あなたは@commitlint/config-conventionalに従ったコミットメッセージを生成するアシスタントです。
|
|
||||||
|
|
||||||
git diffを分析し、コミットメッセージを生成してください。
|
|
||||||
|
|
||||||
形式: <type>[オプションのスコープ]: <件名>
|
|
||||||
|
|
||||||
タイプ: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
ルール:
|
|
||||||
1. 件名は大文字で始めないでください
|
|
||||||
2. 件名はピリオドで終わらないでください
|
|
||||||
3. 件名は4-100文字である必要があります
|
|
||||||
4. 命令形を使用してください
|
|
||||||
5. 簡潔ですが説明的であること
|
|
||||||
6. コミットメッセージのみを出力し、それ以外は出力しないでください。
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT_KO: &str = r#"당신은 @commitlint/config-conventional에 따른 커밋 메시지를 생성하는 도우미입니다.
|
|
||||||
|
|
||||||
git diff를 분석하고 커밋 메시지를 생성하세요.
|
|
||||||
|
|
||||||
형식: <type>[선택적 범위]: <제목>
|
|
||||||
|
|
||||||
유형: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
규칙:
|
|
||||||
1. 제목은 대문자로 시작하지 않아야 합니다
|
|
||||||
2. 제목은 마침표로 끝나지 않아야 합니다
|
|
||||||
3. 제목은 4-100자여야 합니다
|
|
||||||
4. 명령형을 사용하세요
|
|
||||||
5. 간결하지만 설명적이어야 합니다
|
|
||||||
6. 커밋 메시지만 출력하고 다른 내용은 출력하지 마세요.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera mensajes de commit siguiendo @commitlint/config-conventional.
|
|
||||||
|
|
||||||
Analiza el diff de git y genera un mensaje de commit.
|
|
||||||
|
|
||||||
Formato: <tipo>[alcance opcional]: <asunto>
|
|
||||||
|
|
||||||
Tipos: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
Reglas:
|
|
||||||
1. El asunto no debe comenzar con mayúscula
|
|
||||||
2. El asunto no debe terminar con punto
|
|
||||||
3. El asunto debe tener 4-100 caracteres
|
|
||||||
4. Usa modo imperativo
|
|
||||||
5. Sé conciso pero descriptivo
|
|
||||||
6. Genera SOLO el mensaje de commit, nada más.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des messages de commit suivant @commitlint/config-conventional.
|
|
||||||
|
|
||||||
Analysez le diff git et générez un message de commit.
|
|
||||||
|
|
||||||
Format: <type>[portée optionnelle]: <sujet>
|
|
||||||
|
|
||||||
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
Règles:
|
|
||||||
1. Le sujet ne doit pas commencer par une majuscule
|
|
||||||
2. Le sujet ne doit pas se terminer par un point
|
|
||||||
3. Le sujet doit avoir 4-100 caractères
|
|
||||||
4. Utilisez le mode impératif
|
|
||||||
5. Soyez concis mais descriptif
|
|
||||||
6. Générez SEULEMENT le message de commit, rien d'autre.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const COMMITLINT_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der Commit-Nachrichten gemäß @commitlint/config-conventional generiert.
|
|
||||||
|
|
||||||
Analysieren Sie den git diff und generieren Sie eine Commit-Nachricht.
|
|
||||||
|
|
||||||
Format: <typ>[optionaler Bereich]: <betreff>
|
|
||||||
|
|
||||||
Typen: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
|
||||||
|
|
||||||
Regeln:
|
|
||||||
1. Der Betreff sollte nicht mit einem Großbuchstaben beginnen
|
|
||||||
2. Der Betreff sollte nicht mit einem Punkt enden
|
|
||||||
3. Der Betreff sollte 4-100 Zeichen haben
|
|
||||||
4. Verwenden Sie den Imperativ
|
|
||||||
5. Seien Sie prägnant aber beschreibend
|
|
||||||
6. Geben Sie NUR die Commit-Nachricht aus, nichts anderes.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates git tag annotation messages.
|
|
||||||
|
|
||||||
Given a version number and a list of commits, generate a concise but informative tag message.
|
|
||||||
|
|
||||||
The message should:
|
|
||||||
1. Start with a brief summary of the release
|
|
||||||
2. Group changes by type (features, fixes, etc.)
|
|
||||||
3. Be suitable for a git annotated tag
|
|
||||||
|
|
||||||
Format:
|
|
||||||
<version> Release
|
|
||||||
|
|
||||||
Summary of changes...
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Feature: description
|
|
||||||
- Fix: description
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成 git 标签注释消息的助手。
|
|
||||||
|
|
||||||
给定版本号和提交列表,生成简洁但信息丰富的标签消息。
|
|
||||||
|
|
||||||
消息应该:
|
|
||||||
1. 以发布的简要摘要开始
|
|
||||||
2. 按类型分组更改(功能、修复等)
|
|
||||||
3. 适合 git 标注标签
|
|
||||||
|
|
||||||
格式:
|
|
||||||
<version> 发布
|
|
||||||
|
|
||||||
更改摘要...
|
|
||||||
|
|
||||||
更改:
|
|
||||||
- 功能:描述
|
|
||||||
- 修复:描述
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT_JA: &str = r#"あなたはgitタグ注釈メッセージを生成するアシスタントです。
|
|
||||||
|
|
||||||
バージョン番号とコミットのリストを考慮して、簡潔ですが情報豊富なタグメッセージを生成してください。
|
|
||||||
|
|
||||||
メッセージは以下のようであるべきです:
|
|
||||||
1. リリースの簡単な要約から始める
|
|
||||||
2. タイプ別に変更をグループ化する(機能、修正など)
|
|
||||||
3. git注釈タグに適している
|
|
||||||
|
|
||||||
形式:
|
|
||||||
<version> リリース
|
|
||||||
|
|
||||||
変更の概要...
|
|
||||||
|
|
||||||
変更:
|
|
||||||
- 機能:説明
|
|
||||||
- 修正:説明
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT_KO: &str = r#"당신은 git 태그 주석 메시지를 생성하는 도우미입니다.
|
|
||||||
|
|
||||||
버전 번호와 커밋 목록을 고려하여 간결하지만 정보가 풍부한 태그 메시지를 생성하세요.
|
|
||||||
|
|
||||||
메시지는 다음과 같아야 합니다:
|
|
||||||
1. 릴리스의 간단한 요약으로 시작
|
|
||||||
2. 유형별로 변경 사항 그룹화(기능, 수정 등)
|
|
||||||
3. git 주석 태그에 적합
|
|
||||||
|
|
||||||
형식:
|
|
||||||
<version> 릴리스
|
|
||||||
|
|
||||||
변경 사항 요약...
|
|
||||||
|
|
||||||
변경 사항:
|
|
||||||
- 기능: 설명
|
|
||||||
- 수정: 설명
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera mensajes de anotación de etiquetas git.
|
|
||||||
|
|
||||||
Dado un número de versión y una lista de commits, genera un mensaje de etiqueta conciso pero informativo.
|
|
||||||
|
|
||||||
El mensaje debe:
|
|
||||||
1. Comenzar con un resumen breve de la versión
|
|
||||||
2. Agrupar cambios por tipo (características, correcciones, etc.)
|
|
||||||
3. Ser adecuado para una etiqueta git anotada
|
|
||||||
|
|
||||||
Formato:
|
|
||||||
<version> Versión
|
|
||||||
|
|
||||||
Resumen de cambios...
|
|
||||||
|
|
||||||
Cambios:
|
|
||||||
- Característica: descripción
|
|
||||||
- Corrección: descripción
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des messages d'annotation de balises git.
|
|
||||||
|
|
||||||
Étant donné un numéro de version et une liste de commits, générez un message de balise concis mais informatif.
|
|
||||||
|
|
||||||
Le message doit :
|
|
||||||
1. Commencer par un bref résumé de la version
|
|
||||||
2. Grouper les changements par type (fonctionnalités, corrections, etc.)
|
|
||||||
3. Être adapté à une balise git annotée
|
|
||||||
|
|
||||||
Format :
|
|
||||||
<version> Version
|
|
||||||
|
|
||||||
Résumé des changements...
|
|
||||||
|
|
||||||
Changements :
|
|
||||||
- Fonctionnalité : description
|
|
||||||
- Correction : description
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const TAG_MESSAGE_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der git-Tag-Anmerkungsnachrichten generiert.
|
|
||||||
|
|
||||||
Gegeben eine Versionsnummer und eine Liste von Commits, generieren Sie eine prägnante aber informative Tag-Nachricht.
|
|
||||||
|
|
||||||
Die Nachricht sollte:
|
|
||||||
1. Mit einer kurzen Zusammenfassung der Version beginnen
|
|
||||||
2. Änderungen nach Typ gruppieren (Funktionen, Fixes, etc.)
|
|
||||||
3. Für ein git-annotiertes Tag geeignet sein
|
|
||||||
|
|
||||||
Format:
|
|
||||||
<version> Version
|
|
||||||
|
|
||||||
Zusammenfassung der Änderungen...
|
|
||||||
|
|
||||||
Änderungen:
|
|
||||||
- Funktion: Beschreibung
|
|
||||||
- Fix: Beschreibung
|
|
||||||
...
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates changelog entries.
|
|
||||||
|
|
||||||
Given a version and a list of commits, generate a well-formatted changelog section.
|
|
||||||
|
|
||||||
Group commits by:
|
|
||||||
- Features (feat)
|
|
||||||
- Bug Fixes (fix)
|
|
||||||
- Documentation (docs)
|
|
||||||
- Other Changes
|
|
||||||
|
|
||||||
Format in markdown with proper headings and bullet points.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成变更日志条目的助手。
|
|
||||||
|
|
||||||
给定版本和提交列表,生成格式良好的变更日志部分。
|
|
||||||
|
|
||||||
按以下方式分组提交:
|
|
||||||
- 功能 (feat)
|
|
||||||
- 错误修复 (fix)
|
|
||||||
- 文档 (docs)
|
|
||||||
- 其他更改
|
|
||||||
|
|
||||||
使用适当的标题和项目符号以 markdown 格式输出。
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT_JA: &str = r#"あなたは変更ログエントリを生成するアシスタントです。
|
|
||||||
|
|
||||||
バージョンとコミットのリストを考慮して、適切にフォーマットされた変更ログセクションを生成してください。
|
|
||||||
|
|
||||||
コミットを以下でグループ化してください:
|
|
||||||
- 機能 (feat)
|
|
||||||
- バグ修正 (fix)
|
|
||||||
- ドキュメント (docs)
|
|
||||||
- その他の変更
|
|
||||||
|
|
||||||
適切な見出しと箇条書きを使用してmarkdown形式でフォーマットしてください。
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT_KO: &str = r#"당신은 변경 로그 항목을 생성하는 도우미입니다.
|
|
||||||
|
|
||||||
버전과 커밋 목록을 고려하여 잘 포맷된 변경 로그 섹션을 생성하세요.
|
|
||||||
|
|
||||||
다음으로 커밋을 그룹화하세요:
|
|
||||||
- 기능 (feat)
|
|
||||||
- 버그 수정 (fix)
|
|
||||||
- 문서 (docs)
|
|
||||||
- 기타 변경 사항
|
|
||||||
|
|
||||||
적절한 제목과 글머리 기호를 사용하여 markdown 형식으로 포맷하세요.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera entradas de registro de cambios.
|
|
||||||
|
|
||||||
Dada una versión y una lista de commits, genera una sección de registro de cambios bien formateada.
|
|
||||||
|
|
||||||
Agrupa los commits por:
|
|
||||||
- Características (feat)
|
|
||||||
- Correcciones de errores (fix)
|
|
||||||
- Documentación (docs)
|
|
||||||
- Otros cambios
|
|
||||||
|
|
||||||
Formatea en markdown con encabezados y viñetas apropiados.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des entrées de journal des modifications.
|
|
||||||
|
|
||||||
Étant donné une version et une liste de commits, générez une section de journal des modifications bien formatée.
|
|
||||||
|
|
||||||
Groupez les commits par :
|
|
||||||
- Fonctionnalités (feat)
|
|
||||||
- Corrections de bugs (fix)
|
|
||||||
- Documentation (docs)
|
|
||||||
- Autres modifications
|
|
||||||
|
|
||||||
Formatez en markdown avec des en-têtes et des puces appropriés.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
const CHANGELOG_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der Changelog-Einträge generiert.
|
|
||||||
|
|
||||||
Gegeben eine Version und eine Liste von Commits, generieren Sie einen gut formatierten Changelog-Abschnitt.
|
|
||||||
|
|
||||||
Gruppieren Sie Commits nach:
|
|
||||||
- Funktionen (feat)
|
|
||||||
- Bugfixes (fix)
|
|
||||||
- Dokumentation (docs)
|
|
||||||
- Andere Änderungen
|
|
||||||
|
|
||||||
Formatieren Sie in Markdown mit geeigneten Überschriften und Aufzählungspunkten.
|
|
||||||
"#;
|
|
||||||
|
|
||||||
/// Test LLM connection
|
/// Test LLM connection
|
||||||
pub async fn test_connection(manager: &crate::config::manager::ConfigManager) -> Result<String> {
|
pub async fn test_connection(manager: &crate::config::manager::ConfigManager) -> Result<String> {
|
||||||
|
|||||||
281
src/llm/parsing.rs
Normal file
281
src/llm/parsing.rs
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
|
/// Parse commit response from LLM
|
||||||
|
pub(crate) fn parse_commit_response(
|
||||||
|
response: &str,
|
||||||
|
format: crate::config::CommitFormat,
|
||||||
|
) -> Result<GeneratedCommit> {
|
||||||
|
// Clean markdown code fences from the response
|
||||||
|
let cleaned = strip_code_fences(response);
|
||||||
|
|
||||||
|
let lines: Vec<&str> = cleaned
|
||||||
|
.lines()
|
||||||
|
.map(|l| l.trim())
|
||||||
|
.filter(|l| !l.is_empty())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if lines.is_empty() {
|
||||||
|
let preview: String = response.chars().take(200).collect();
|
||||||
|
bail!(
|
||||||
|
"LLM returned empty or whitespace-only response. \
|
||||||
|
Raw response preview: '{}'. \
|
||||||
|
Hint: If using DeepSeek/Kimi with thinking enabled, \
|
||||||
|
the model may have returned reasoning_content only. \
|
||||||
|
Try disabling thinking mode or switching models.",
|
||||||
|
preview
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the line most likely to be the commit subject
|
||||||
|
let first_line = find_commit_subject_line(&lines, format);
|
||||||
|
|
||||||
|
// Parse based on format
|
||||||
|
match format {
|
||||||
|
crate::config::CommitFormat::Conventional => {
|
||||||
|
parse_conventional_commit(first_line, &lines, response)
|
||||||
|
}
|
||||||
|
crate::config::CommitFormat::Commitlint => {
|
||||||
|
parse_commitlint_commit(first_line, &lines, response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove surrounding markdown code fences (```) from LLM output
|
||||||
|
fn strip_code_fences(response: &str) -> String {
|
||||||
|
let mut lines: Vec<&str> = response.lines().collect();
|
||||||
|
|
||||||
|
// Strip leading fence lines (``` or ```lang)
|
||||||
|
while lines.first().map_or(false, |l| l.trim().starts_with("```")) {
|
||||||
|
lines.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip trailing fence lines
|
||||||
|
while lines.last().map_or(false, |l| l.trim() == "```") {
|
||||||
|
lines.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the line that is most likely the commit subject among extracted lines
|
||||||
|
fn find_commit_subject_line<'a>(
|
||||||
|
lines: &[&'a str],
|
||||||
|
format: crate::config::CommitFormat,
|
||||||
|
) -> &'a str {
|
||||||
|
let valid_types = crate::utils::validators::get_commit_types(matches!(
|
||||||
|
format,
|
||||||
|
crate::config::CommitFormat::Commitlint
|
||||||
|
));
|
||||||
|
|
||||||
|
// First pass: line starting with a known type that also has proper syntax
|
||||||
|
// (e.g. "type:", "type(scope):", "type!:")
|
||||||
|
for &line in lines {
|
||||||
|
let trimmed = line.trim();
|
||||||
|
for &t in valid_types {
|
||||||
|
if let Some(rest) = trimmed.strip_prefix(t) {
|
||||||
|
if rest.starts_with(':') || rest.starts_with('(') || rest.starts_with("!:") {
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass: any line containing a colon (generic "prefix: description")
|
||||||
|
for &line in lines {
|
||||||
|
if line.contains(':') {
|
||||||
|
return line.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: return the first line as-is
|
||||||
|
lines[0].trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_conventional_commit(
|
||||||
|
first_line: &str,
|
||||||
|
lines: &[&str],
|
||||||
|
raw_response: &str,
|
||||||
|
) -> Result<GeneratedCommit> {
|
||||||
|
// Parse: type(scope)!: description
|
||||||
|
let parts: Vec<&str> = first_line.splitn(2, ':').collect();
|
||||||
|
if parts.len() != 2 {
|
||||||
|
let preview: String = raw_response.chars().take(300).collect();
|
||||||
|
bail!(
|
||||||
|
"Invalid conventional commit format: missing colon.\n\
|
||||||
|
Parsed subject line: '{}'\n\
|
||||||
|
Raw response preview: '{}'\n\
|
||||||
|
Expected: <type>[optional scope]: <description>",
|
||||||
|
first_line,
|
||||||
|
preview
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let type_part = parts[0];
|
||||||
|
let description = parts[1].trim();
|
||||||
|
|
||||||
|
// Extract type, scope, and breaking indicator
|
||||||
|
let breaking = type_part.ends_with('!');
|
||||||
|
let type_part = type_part.trim_end_matches('!');
|
||||||
|
|
||||||
|
let (commit_type, scope) = if let Some(start) = type_part.find('(') {
|
||||||
|
if let Some(end) = type_part.find(')') {
|
||||||
|
let t = &type_part[..start];
|
||||||
|
let s = &type_part[start + 1..end];
|
||||||
|
(t.to_string(), Some(s.to_string()))
|
||||||
|
} else {
|
||||||
|
bail!("Invalid scope format: missing closing parenthesis");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(type_part.to_string(), None)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract body and footer
|
||||||
|
let (body, footer) = extract_body_footer(lines);
|
||||||
|
|
||||||
|
Ok(GeneratedCommit {
|
||||||
|
commit_type,
|
||||||
|
scope,
|
||||||
|
description: description.to_string(),
|
||||||
|
body,
|
||||||
|
footer,
|
||||||
|
breaking,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_commitlint_commit(
|
||||||
|
first_line: &str,
|
||||||
|
lines: &[&str],
|
||||||
|
raw_response: &str,
|
||||||
|
) -> Result<GeneratedCommit> {
|
||||||
|
// Similar parsing but with commitlint rules
|
||||||
|
let parts: Vec<&str> = first_line.splitn(2, ':').collect();
|
||||||
|
if parts.len() != 2 {
|
||||||
|
let preview: String = raw_response.chars().take(300).collect();
|
||||||
|
bail!(
|
||||||
|
"Invalid commit format: missing colon.\n\
|
||||||
|
Parsed subject line: '{}'\n\
|
||||||
|
Raw response preview: '{}'\n\
|
||||||
|
Expected: <type>[optional scope]: <subject>",
|
||||||
|
first_line,
|
||||||
|
preview
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let type_part = parts[0];
|
||||||
|
let subject = parts[1].trim();
|
||||||
|
|
||||||
|
let (commit_type, scope) = if let Some(start) = type_part.find('(') {
|
||||||
|
if let Some(end) = type_part.find(')') {
|
||||||
|
let t = &type_part[..start];
|
||||||
|
let s = &type_part[start + 1..end];
|
||||||
|
(t.to_string(), Some(s.to_string()))
|
||||||
|
} else {
|
||||||
|
(type_part.to_string(), None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(type_part.to_string(), None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (body, footer) = extract_body_footer(&lines);
|
||||||
|
|
||||||
|
Ok(GeneratedCommit {
|
||||||
|
commit_type,
|
||||||
|
scope,
|
||||||
|
description: subject.to_string(),
|
||||||
|
body,
|
||||||
|
footer,
|
||||||
|
breaking: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_body_footer(lines: &[&str]) -> (Option<String>, Option<String>) {
|
||||||
|
if lines.len() <= 1 {
|
||||||
|
return (None, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rest: Vec<&str> = lines[1..]
|
||||||
|
.iter()
|
||||||
|
.skip_while(|l| l.trim().is_empty())
|
||||||
|
.copied()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if rest.is_empty() {
|
||||||
|
return (None, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for footer markers
|
||||||
|
let footer_markers = [
|
||||||
|
"BREAKING CHANGE:",
|
||||||
|
"Closes",
|
||||||
|
"Fixes",
|
||||||
|
"Refs",
|
||||||
|
"Co-authored-by:",
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut body_lines = vec![];
|
||||||
|
let mut footer_lines = vec![];
|
||||||
|
let mut in_footer = false;
|
||||||
|
|
||||||
|
for line in &rest {
|
||||||
|
if footer_markers.iter().any(|m| line.starts_with(m)) {
|
||||||
|
in_footer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if in_footer {
|
||||||
|
footer_lines.push(*line);
|
||||||
|
} else {
|
||||||
|
body_lines.push(*line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = if body_lines.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(body_lines.join("\n"))
|
||||||
|
};
|
||||||
|
|
||||||
|
let footer = if footer_lines.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(footer_lines.join("\n"))
|
||||||
|
};
|
||||||
|
|
||||||
|
(body, footer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generated commit structure
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct GeneratedCommit {
|
||||||
|
pub commit_type: String,
|
||||||
|
pub scope: Option<String>,
|
||||||
|
pub description: String,
|
||||||
|
pub body: Option<String>,
|
||||||
|
pub footer: Option<String>,
|
||||||
|
pub breaking: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GeneratedCommit {
|
||||||
|
/// Format as conventional commit
|
||||||
|
pub fn to_conventional(&self) -> String {
|
||||||
|
crate::utils::formatter::format_conventional_commit(
|
||||||
|
&self.commit_type,
|
||||||
|
self.scope.as_deref(),
|
||||||
|
&self.description,
|
||||||
|
self.body.as_deref(),
|
||||||
|
self.footer.as_deref(),
|
||||||
|
self.breaking,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format as commitlint commit
|
||||||
|
pub fn to_commitlint(&self) -> String {
|
||||||
|
crate::utils::formatter::format_commitlint_commit(
|
||||||
|
&self.commit_type,
|
||||||
|
self.scope.as_deref(),
|
||||||
|
&self.description,
|
||||||
|
self.body.as_deref(),
|
||||||
|
self.footer.as_deref(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
618
src/llm/prompts.rs
Normal file
618
src/llm/prompts.rs
Normal file
@@ -0,0 +1,618 @@
|
|||||||
|
use crate::config::Language;
|
||||||
|
|
||||||
|
/// Get commit system prompt based on format and language
|
||||||
|
pub(crate) fn get_commit_system_prompt(
|
||||||
|
format: crate::config::CommitFormat,
|
||||||
|
language: Language,
|
||||||
|
) -> &'static str {
|
||||||
|
match (format, language) {
|
||||||
|
(crate::config::CommitFormat::Conventional, Language::Chinese) => {
|
||||||
|
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ZH
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Conventional, Language::Japanese) => {
|
||||||
|
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_JA
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Conventional, Language::Korean) => {
|
||||||
|
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_KO
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Conventional, Language::Spanish) => {
|
||||||
|
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ES
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Conventional, Language::French) => {
|
||||||
|
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_FR
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Conventional, Language::German) => {
|
||||||
|
CONVENTIONAL_COMMIT_SYSTEM_PROMPT_DE
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Conventional, _) => CONVENTIONAL_COMMIT_SYSTEM_PROMPT,
|
||||||
|
(crate::config::CommitFormat::Commitlint, Language::Chinese) => COMMITLINT_SYSTEM_PROMPT_ZH,
|
||||||
|
(crate::config::CommitFormat::Commitlint, Language::Japanese) => {
|
||||||
|
COMMITLINT_SYSTEM_PROMPT_JA
|
||||||
|
}
|
||||||
|
(crate::config::CommitFormat::Commitlint, Language::Korean) => COMMITLINT_SYSTEM_PROMPT_KO,
|
||||||
|
(crate::config::CommitFormat::Commitlint, Language::Spanish) => COMMITLINT_SYSTEM_PROMPT_ES,
|
||||||
|
(crate::config::CommitFormat::Commitlint, Language::French) => COMMITLINT_SYSTEM_PROMPT_FR,
|
||||||
|
(crate::config::CommitFormat::Commitlint, Language::German) => COMMITLINT_SYSTEM_PROMPT_DE,
|
||||||
|
(crate::config::CommitFormat::Commitlint, _) => COMMITLINT_SYSTEM_PROMPT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_tag_system_prompt(language: Language) -> &'static str {
|
||||||
|
match language {
|
||||||
|
Language::Chinese => TAG_MESSAGE_SYSTEM_PROMPT_ZH,
|
||||||
|
Language::Japanese => TAG_MESSAGE_SYSTEM_PROMPT_JA,
|
||||||
|
Language::Korean => TAG_MESSAGE_SYSTEM_PROMPT_KO,
|
||||||
|
Language::Spanish => TAG_MESSAGE_SYSTEM_PROMPT_ES,
|
||||||
|
Language::French => TAG_MESSAGE_SYSTEM_PROMPT_FR,
|
||||||
|
Language::German => TAG_MESSAGE_SYSTEM_PROMPT_DE,
|
||||||
|
_ => TAG_MESSAGE_SYSTEM_PROMPT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_changelog_system_prompt(language: Language) -> &'static str {
|
||||||
|
match language {
|
||||||
|
Language::Chinese => CHANGELOG_SYSTEM_PROMPT_ZH,
|
||||||
|
Language::Japanese => CHANGELOG_SYSTEM_PROMPT_JA,
|
||||||
|
Language::Korean => CHANGELOG_SYSTEM_PROMPT_KO,
|
||||||
|
Language::Spanish => CHANGELOG_SYSTEM_PROMPT_ES,
|
||||||
|
Language::French => CHANGELOG_SYSTEM_PROMPT_FR,
|
||||||
|
Language::German => CHANGELOG_SYSTEM_PROMPT_DE,
|
||||||
|
_ => CHANGELOG_SYSTEM_PROMPT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// System prompts for LLM
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates conventional commit messages.
|
||||||
|
|
||||||
|
Analyze the git diff provided and generate a commit message following the Conventional Commits specification.
|
||||||
|
|
||||||
|
Format: <type>[optional scope]: <description>
|
||||||
|
|
||||||
|
Types:
|
||||||
|
- feat: A new feature
|
||||||
|
- fix: A bug fix
|
||||||
|
- docs: Documentation only changes
|
||||||
|
- style: Changes that don't affect code meaning (formatting, semicolons, etc.)
|
||||||
|
- refactor: Code change that neither fixes a bug nor adds a feature
|
||||||
|
- perf: Code change that improves performance
|
||||||
|
- test: Adding or correcting tests
|
||||||
|
- build: Changes to build system or dependencies
|
||||||
|
- ci: Changes to CI configuration
|
||||||
|
- chore: Other changes that don't modify src or test files
|
||||||
|
- revert: Reverts a previous commit
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
1. Use lowercase for type and scope
|
||||||
|
2. Keep description under 100 characters
|
||||||
|
3. Use imperative mood ("add" not "added")
|
||||||
|
4. Don't capitalize first letter
|
||||||
|
5. No period at the end
|
||||||
|
6. Include scope if the change is specific to a module/component
|
||||||
|
|
||||||
|
Output ONLY the commit message, nothing else.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成符合 Conventional Commits 规范的提交消息的助手。
|
||||||
|
|
||||||
|
分析提供的 git diff,并生成符合 Conventional Commits 规范的提交消息。
|
||||||
|
|
||||||
|
格式: <type>[可选作用域]: <描述>
|
||||||
|
|
||||||
|
类型:
|
||||||
|
- feat: 新功能
|
||||||
|
- fix: 修复错误
|
||||||
|
- docs: 仅文档更改
|
||||||
|
- style: 不影响代码含义的更改(格式化、分号等)
|
||||||
|
- refactor: 既不修复错误也不添加功能的代码更改
|
||||||
|
- perf: 提高性能的代码更改
|
||||||
|
- test: 添加或更正测试
|
||||||
|
- build: 更改构建系统或依赖项
|
||||||
|
- ci: 更改 CI 配置
|
||||||
|
- chore: 其他不修改 src 或测试文件的更改
|
||||||
|
- revert: 撤销之前的提交
|
||||||
|
|
||||||
|
规则:
|
||||||
|
1. 类型和小写使用小写
|
||||||
|
2. 描述保持在 100 个字符以内
|
||||||
|
3. 使用祈使语气("添加"而不是"已添加")
|
||||||
|
4. 不要大写首字母
|
||||||
|
5. 结尾不要句号
|
||||||
|
6. 如果更改特定于模块/组件,请包含作用域
|
||||||
|
7. 仅输出提交消息,不要输出其他内容。
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_JA: &str = r#"あなたはConventional Commits仕様に従ったコミットメッセージを生成するアシスタントです。
|
||||||
|
|
||||||
|
提供されたgit diffを分析し、Conventional Commits仕様に従ったコミットメッセージを生成してください。
|
||||||
|
|
||||||
|
形式: <type>[オプションのスコープ]: <説明>
|
||||||
|
|
||||||
|
タイプ:
|
||||||
|
- feat: 新機能
|
||||||
|
- fix: バグ修正
|
||||||
|
- docs: ドキュメントのみの変更
|
||||||
|
- style: コードの意味に影響しない変更(フォーマット、セミコロンなど)
|
||||||
|
- refactor: バグ修正や機能追加を伴わないコード変更
|
||||||
|
- perf: パフォーマンスを向上させるコード変更
|
||||||
|
- test: テストの追加または修正
|
||||||
|
- build: ビルドシステムまたは依存関係の変更
|
||||||
|
- ci: CI設定の変更
|
||||||
|
- chore: srcやテストファイルを変更しないその他の変更
|
||||||
|
- revert: 以前のコミットを取り消す
|
||||||
|
|
||||||
|
ルール:
|
||||||
|
1. タイプとスコープは小文字を使用
|
||||||
|
2. 説明は100文字以内にする
|
||||||
|
3. 命令形を使用する("追加"ではなく"追加する")
|
||||||
|
4. 先頭を大文字にしない
|
||||||
|
5. 最後にピリオドを付けない
|
||||||
|
6. 変更がモジュール/コンポーネントに固有の場合はスコープを含める
|
||||||
|
7. コミットメッセージのみを出力し、それ以外は出力しないでください。
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_KO: &str = r#"당신은 Conventional Commits 사양에 따른 커밋 메시지를 생성하는 도우미입니다.
|
||||||
|
|
||||||
|
제공된 git diff를 분석하고 Conventional Commits 사양에 따른 커밋 메시지를 생성하세요.
|
||||||
|
|
||||||
|
형식: <type>[선택적 범위]: <설명>
|
||||||
|
|
||||||
|
유형:
|
||||||
|
- feat: 새 기능
|
||||||
|
- fix: 버그 수정
|
||||||
|
- docs: 문서 변경만
|
||||||
|
- style: 코드 의미에 영향을 주지 않는 변경(서식, 세미콜론 등)
|
||||||
|
- refactor: 버그를 수정하거나 기능을 추가하지 않는 코드 변경
|
||||||
|
- perf: 성능을 향상시키는 코드 변경
|
||||||
|
- test: 테스트 추가 또는 수정
|
||||||
|
- build: 빌드 시스템 또는 종속성 변경
|
||||||
|
- ci: CI 구성 변경
|
||||||
|
- chore: src 또는 테스트 파일을 수정하지 않는 기타 변경
|
||||||
|
- revert: 이전 커밋 되돌리기
|
||||||
|
|
||||||
|
규칙:
|
||||||
|
1. 유형과 범위는 소문자 사용
|
||||||
|
2. 설명은 100자 이내로 유지
|
||||||
|
3. 명령형 사용("추가"가 아닌 "추가하다")
|
||||||
|
4. 첫 글자 대문자화하지 않음
|
||||||
|
5. 끝에 마침표 사용하지 않음
|
||||||
|
6. 변경 사항이 모듈/구성 요소에 특정한 경우 범위 포함
|
||||||
|
7. 커밋 메시지만 출력하고 다른 내용은 출력하지 마세요.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera mensajes de commit siguiendo la especificación Conventional Commits.
|
||||||
|
|
||||||
|
Analiza el diff de git proporcionado y genera un mensaje de commit siguiendo la especificación Conventional Commits.
|
||||||
|
|
||||||
|
Formato: <tipo>[alcance opcional]: <descripción>
|
||||||
|
|
||||||
|
Tipos:
|
||||||
|
- feat: Una nueva característica
|
||||||
|
- fix: Una corrección de error
|
||||||
|
- docs: Solo cambios en documentación
|
||||||
|
- style: Cambios que no afectan el significado del código (formato, punto y coma, etc.)
|
||||||
|
- refactor: Cambio de código que no corrige un error ni agrega una característica
|
||||||
|
- perf: Cambio de código que mejora el rendimiento
|
||||||
|
- test: Agregar o corregir pruebas
|
||||||
|
- build: Cambios en el sistema de construcción o dependencias
|
||||||
|
- ci: Cambios en la configuración de CI
|
||||||
|
- chore: Otros cambios que no modifican archivos src o de prueba
|
||||||
|
- revert: Revierte un commit anterior
|
||||||
|
|
||||||
|
Reglas:
|
||||||
|
1. Usa minúsculas para tipo y alcance
|
||||||
|
2. Mantén la descripción bajo 100 caracteres
|
||||||
|
3. Usa modo imperativo ("agregar" no "agregado")
|
||||||
|
4. No capitalices la primera letra
|
||||||
|
5. Sin punto al final
|
||||||
|
6. Incluye alcance si el cambio es específico de un módulo/componente
|
||||||
|
7. Genera SOLO el mensaje de commit, nada más.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des messages de commit suivant la spécification Conventional Commits.
|
||||||
|
|
||||||
|
Analysez le diff git fourni et générez un message de commit suivant la spécification Conventional Commits.
|
||||||
|
|
||||||
|
Format: <type>[portée optionnelle]: <description>
|
||||||
|
|
||||||
|
Types:
|
||||||
|
- feat: Une nouvelle fonctionnalité
|
||||||
|
- fix: Une correction de bug
|
||||||
|
- docs: Changements de documentation uniquement
|
||||||
|
- style: Changements qui n'affectent pas la signification du code (formatage, points-virgules, etc.)
|
||||||
|
- refactor: Changement de code qui ne corrige pas un bug ni n'ajoute une fonctionnalité
|
||||||
|
- perf: Changement de code qui améliore les performances
|
||||||
|
- test: Ajout ou correction de tests
|
||||||
|
- build: Changements du système de build ou des dépendances
|
||||||
|
- ci: Changements de la configuration CI
|
||||||
|
- chore: Autres changements qui ne modifient pas les fichiers src ou de test
|
||||||
|
- revert: Révertit un commit précédent
|
||||||
|
|
||||||
|
Règles:
|
||||||
|
1. Utilisez des minuscules pour le type et la portée
|
||||||
|
2. Gardez la description sous 100 caractères
|
||||||
|
3. Utilisez le mode impératif ("ajouter" non "ajouté")
|
||||||
|
4. Ne capitalisez pas la première lettre
|
||||||
|
5. Pas de point à la fin
|
||||||
|
6. Incluez la portée si le changement est spécifique à un module/composant
|
||||||
|
7. Générez SEULEMENT le message de commit, rien d'autre.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der Commit-Nachrichten gemäß der Conventional Commits-Spezifikation generiert.
|
||||||
|
|
||||||
|
Analysieren Sie den bereitgestellten git diff und generieren Sie eine Commit-Nachricht gemäß der Conventional Commits-Spezifikation.
|
||||||
|
|
||||||
|
Format: <typ>[optionaler Bereich]: <beschreibung>
|
||||||
|
|
||||||
|
Typen:
|
||||||
|
- feat: Eine neue Funktion
|
||||||
|
- fix: Ein Bugfix
|
||||||
|
- docs: Nur Dokumentationsänderungen
|
||||||
|
- style: Änderungen, die die Code-Bedeutung nicht beeinflussen (Formatierung, Semikolons usw.)
|
||||||
|
- refactor: Code-Änderung, die weder einen Bug behebt noch eine Funktion hinzufügt
|
||||||
|
- perf: Code-Änderung, die die Leistung verbessert
|
||||||
|
- test: Hinzufügen oder Korrigieren von Tests
|
||||||
|
- build: Änderungen am Build-System oder Abhängigkeiten
|
||||||
|
- ci: Änderungen an der CI-Konfiguration
|
||||||
|
- chore: Andere Änderungen, die src- oder Testdateien nicht ändern
|
||||||
|
- revert: Setzt einen vorherigen Commit zurück
|
||||||
|
|
||||||
|
Regeln:
|
||||||
|
1. Verwenden Sie Kleinbuchstaben für Typ und Bereich
|
||||||
|
2. Halten Sie die Beschreibung unter 100 Zeichen
|
||||||
|
3. Verwenden Sie den Imperativ ("hinzufügen" nicht "hinzugefügt")
|
||||||
|
4. Großschreiben Sie den ersten Buchstaben nicht
|
||||||
|
5. Kein Punkt am Ende
|
||||||
|
6. Fügen Sie einen Bereich ein, wenn die Änderung spezifisch für ein Modul/Komponente ist
|
||||||
|
7. Geben Sie NUR die Commit-Nachricht aus, nichts anderes.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates commit messages following @commitlint/config-conventional.
|
||||||
|
|
||||||
|
Analyze the git diff and generate a commit message.
|
||||||
|
|
||||||
|
Format: <type>[optional scope]: <subject>
|
||||||
|
|
||||||
|
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
1. Subject should not start with uppercase
|
||||||
|
2. Subject should not end with period
|
||||||
|
3. Subject should be 4-100 characters
|
||||||
|
4. Use imperative mood
|
||||||
|
5. Be concise but descriptive
|
||||||
|
6. Output ONLY the commit message, nothing else.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成符合 @commitlint/config-conventional 规范的提交消息的助手。
|
||||||
|
|
||||||
|
分析 git diff 并生成提交消息。
|
||||||
|
|
||||||
|
格式: <type>[可选作用域]: <主题>
|
||||||
|
|
||||||
|
类型: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
规则:
|
||||||
|
1. 主题不应以大写字母开头
|
||||||
|
2. 主题不应以句号结尾
|
||||||
|
3. 主题应为 4-100 个字符
|
||||||
|
4. 使用祈使语气
|
||||||
|
5. 简洁但描述性强
|
||||||
|
6. 仅输出提交消息,不要输出其他额外内容。
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT_JA: &str = r#"あなたは@commitlint/config-conventionalに従ったコミットメッセージを生成するアシスタントです。
|
||||||
|
|
||||||
|
git diffを分析し、コミットメッセージを生成してください。
|
||||||
|
|
||||||
|
形式: <type>[オプションのスコープ]: <件名>
|
||||||
|
|
||||||
|
タイプ: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
ルール:
|
||||||
|
1. 件名は大文字で始めないでください
|
||||||
|
2. 件名はピリオドで終わらないでください
|
||||||
|
3. 件名は4-100文字である必要があります
|
||||||
|
4. 命令形を使用してください
|
||||||
|
5. 簡潔ですが説明的であること
|
||||||
|
6. コミットメッセージのみを出力し、それ以外は出力しないでください。
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT_KO: &str = r#"당신은 @commitlint/config-conventional에 따른 커밋 메시지를 생성하는 도우미입니다.
|
||||||
|
|
||||||
|
git diff를 분석하고 커밋 메시지를 생성하세요.
|
||||||
|
|
||||||
|
형식: <type>[선택적 범위]: <제목>
|
||||||
|
|
||||||
|
유형: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
규칙:
|
||||||
|
1. 제목은 대문자로 시작하지 않아야 합니다
|
||||||
|
2. 제목은 마침표로 끝나지 않아야 합니다
|
||||||
|
3. 제목은 4-100자여야 합니다
|
||||||
|
4. 명령형을 사용하세요
|
||||||
|
5. 간결하지만 설명적이어야 합니다
|
||||||
|
6. 커밋 메시지만 출력하고 다른 내용은 출력하지 마세요.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera mensajes de commit siguiendo @commitlint/config-conventional.
|
||||||
|
|
||||||
|
Analiza el diff de git y genera un mensaje de commit.
|
||||||
|
|
||||||
|
Formato: <tipo>[alcance opcional]: <asunto>
|
||||||
|
|
||||||
|
Tipos: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
Reglas:
|
||||||
|
1. El asunto no debe comenzar con mayúscula
|
||||||
|
2. El asunto no debe terminar con punto
|
||||||
|
3. El asunto debe tener 4-100 caracteres
|
||||||
|
4. Usa modo imperativo
|
||||||
|
5. Sé conciso pero descriptivo
|
||||||
|
6. Genera SOLO el mensaje de commit, nada más.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des messages de commit suivant @commitlint/config-conventional.
|
||||||
|
|
||||||
|
Analysez le diff git et générez un message de commit.
|
||||||
|
|
||||||
|
Format: <type>[portée optionnelle]: <sujet>
|
||||||
|
|
||||||
|
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
Règles:
|
||||||
|
1. Le sujet ne doit pas commencer par une majuscule
|
||||||
|
2. Le sujet ne doit pas se terminer par un point
|
||||||
|
3. Le sujet doit avoir 4-100 caractères
|
||||||
|
4. Utilisez le mode impératif
|
||||||
|
5. Soyez concis mais descriptif
|
||||||
|
6. Générez SEULEMENT le message de commit, rien d'autre.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const COMMITLINT_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der Commit-Nachrichten gemäß @commitlint/config-conventional generiert.
|
||||||
|
|
||||||
|
Analysieren Sie den git diff und generieren Sie eine Commit-Nachricht.
|
||||||
|
|
||||||
|
Format: <typ>[optionaler Bereich]: <betreff>
|
||||||
|
|
||||||
|
Typen: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
|
||||||
|
|
||||||
|
Regeln:
|
||||||
|
1. Der Betreff sollte nicht mit einem Großbuchstaben beginnen
|
||||||
|
2. Der Betreff sollte nicht mit einem Punkt enden
|
||||||
|
3. Der Betreff sollte 4-100 Zeichen haben
|
||||||
|
4. Verwenden Sie den Imperativ
|
||||||
|
5. Seien Sie prägnant aber beschreibend
|
||||||
|
6. Geben Sie NUR die Commit-Nachricht aus, nichts anderes.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates git tag annotation messages.
|
||||||
|
|
||||||
|
Given a version number and a list of commits, generate a concise but informative tag message.
|
||||||
|
|
||||||
|
The message should:
|
||||||
|
1. Start with a brief summary of the release
|
||||||
|
2. Group changes by type (features, fixes, etc.)
|
||||||
|
3. Be suitable for a git annotated tag
|
||||||
|
|
||||||
|
Format:
|
||||||
|
<version> Release
|
||||||
|
|
||||||
|
Summary of changes...
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Feature: description
|
||||||
|
- Fix: description
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成 git 标签注释消息的助手。
|
||||||
|
|
||||||
|
给定版本号和提交列表,生成简洁但信息丰富的标签消息。
|
||||||
|
|
||||||
|
消息应该:
|
||||||
|
1. 以发布的简要摘要开始
|
||||||
|
2. 按类型分组更改(功能、修复等)
|
||||||
|
3. 适合 git 标注标签
|
||||||
|
|
||||||
|
格式:
|
||||||
|
<version> 发布
|
||||||
|
|
||||||
|
更改摘要...
|
||||||
|
|
||||||
|
更改:
|
||||||
|
- 功能:描述
|
||||||
|
- 修复:描述
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT_JA: &str = r#"あなたはgitタグ注釈メッセージを生成するアシスタントです。
|
||||||
|
|
||||||
|
バージョン番号とコミットのリストを考慮して、簡潔ですが情報豊富なタグメッセージを生成してください。
|
||||||
|
|
||||||
|
メッセージは以下のようであるべきです:
|
||||||
|
1. リリースの簡単な要約から始める
|
||||||
|
2. タイプ別に変更をグループ化する(機能、修正など)
|
||||||
|
3. git注釈タグに適している
|
||||||
|
|
||||||
|
形式:
|
||||||
|
<version> リリース
|
||||||
|
|
||||||
|
変更の概要...
|
||||||
|
|
||||||
|
変更:
|
||||||
|
- 機能:説明
|
||||||
|
- 修正:説明
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT_KO: &str = r#"당신은 git 태그 주석 메시지를 생성하는 도우미입니다.
|
||||||
|
|
||||||
|
버전 번호와 커밋 목록을 고려하여 간결하지만 정보가 풍부한 태그 메시지를 생성하세요.
|
||||||
|
|
||||||
|
메시지는 다음과 같아야 합니다:
|
||||||
|
1. 릴리스의 간단한 요약으로 시작
|
||||||
|
2. 유형별로 변경 사항 그룹화(기능, 수정 등)
|
||||||
|
3. git 주석 태그에 적합
|
||||||
|
|
||||||
|
형식:
|
||||||
|
<version> 릴리스
|
||||||
|
|
||||||
|
변경 사항 요약...
|
||||||
|
|
||||||
|
변경 사항:
|
||||||
|
- 기능: 설명
|
||||||
|
- 수정: 설명
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera mensajes de anotación de etiquetas git.
|
||||||
|
|
||||||
|
Dado un número de versión y una lista de commits, genera un mensaje de etiqueta conciso pero informativo.
|
||||||
|
|
||||||
|
El mensaje debe:
|
||||||
|
1. Comenzar con un resumen breve de la versión
|
||||||
|
2. Agrupar cambios por tipo (características, correcciones, etc.)
|
||||||
|
3. Ser adecuado para una etiqueta git anotada
|
||||||
|
|
||||||
|
Formato:
|
||||||
|
<version> Versión
|
||||||
|
|
||||||
|
Resumen de cambios...
|
||||||
|
|
||||||
|
Cambios:
|
||||||
|
- Característica: descripción
|
||||||
|
- Corrección: descripción
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des messages d'annotation de balises git.
|
||||||
|
|
||||||
|
Étant donné un numéro de version et une liste de commits, générez un message de balise concis mais informatif.
|
||||||
|
|
||||||
|
Le message doit :
|
||||||
|
1. Commencer par un bref résumé de la version
|
||||||
|
2. Grouper les changements par type (fonctionnalités, corrections, etc.)
|
||||||
|
3. Être adapté à une balise git annotée
|
||||||
|
|
||||||
|
Format :
|
||||||
|
<version> Version
|
||||||
|
|
||||||
|
Résumé des changements...
|
||||||
|
|
||||||
|
Changements :
|
||||||
|
- Fonctionnalité : description
|
||||||
|
- Correction : description
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const TAG_MESSAGE_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der git-Tag-Anmerkungsnachrichten generiert.
|
||||||
|
|
||||||
|
Gegeben eine Versionsnummer und eine Liste von Commits, generieren Sie eine prägnante aber informative Tag-Nachricht.
|
||||||
|
|
||||||
|
Die Nachricht sollte:
|
||||||
|
1. Mit einer kurzen Zusammenfassung der Version beginnen
|
||||||
|
2. Änderungen nach Typ gruppieren (Funktionen, Fixes, etc.)
|
||||||
|
3. Für ein git-annotiertes Tag geeignet sein
|
||||||
|
|
||||||
|
Format:
|
||||||
|
<version> Version
|
||||||
|
|
||||||
|
Zusammenfassung der Änderungen...
|
||||||
|
|
||||||
|
Änderungen:
|
||||||
|
- Funktion: Beschreibung
|
||||||
|
- Fix: Beschreibung
|
||||||
|
...
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates changelog entries.
|
||||||
|
|
||||||
|
Given a version and a list of commits, generate a well-formatted changelog section.
|
||||||
|
|
||||||
|
Group commits by:
|
||||||
|
- Features (feat)
|
||||||
|
- Bug Fixes (fix)
|
||||||
|
- Documentation (docs)
|
||||||
|
- Other Changes
|
||||||
|
|
||||||
|
Format in markdown with proper headings and bullet points.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT_ZH: &str = r#"你是一个生成变更日志条目的助手。
|
||||||
|
|
||||||
|
给定版本和提交列表,生成格式良好的变更日志部分。
|
||||||
|
|
||||||
|
按以下方式分组提交:
|
||||||
|
- 功能 (feat)
|
||||||
|
- 错误修复 (fix)
|
||||||
|
- 文档 (docs)
|
||||||
|
- 其他更改
|
||||||
|
|
||||||
|
使用适当的标题和项目符号以 markdown 格式输出。
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT_JA: &str = r#"あなたは変更ログエントリを生成するアシスタントです。
|
||||||
|
|
||||||
|
バージョンとコミットのリストを考慮して、適切にフォーマットされた変更ログセクションを生成してください。
|
||||||
|
|
||||||
|
コミットを以下でグループ化してください:
|
||||||
|
- 機能 (feat)
|
||||||
|
- バグ修正 (fix)
|
||||||
|
- ドキュメント (docs)
|
||||||
|
- その他の変更
|
||||||
|
|
||||||
|
適切な見出しと箇条書きを使用してmarkdown形式でフォーマットしてください。
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT_KO: &str = r#"당신은 변경 로그 항목을 생성하는 도우미입니다.
|
||||||
|
|
||||||
|
버전과 커밋 목록을 고려하여 잘 포맷된 변경 로그 섹션을 생성하세요.
|
||||||
|
|
||||||
|
다음으로 커밋을 그룹화하세요:
|
||||||
|
- 기능 (feat)
|
||||||
|
- 버그 수정 (fix)
|
||||||
|
- 문서 (docs)
|
||||||
|
- 기타 변경 사항
|
||||||
|
|
||||||
|
적절한 제목과 글머리 기호를 사용하여 markdown 형식으로 포맷하세요.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT_ES: &str = r#"Eres un asistente que genera entradas de registro de cambios.
|
||||||
|
|
||||||
|
Dada una versión y una lista de commits, genera una sección de registro de cambios bien formateada.
|
||||||
|
|
||||||
|
Agrupa los commits por:
|
||||||
|
- Características (feat)
|
||||||
|
- Correcciones de errores (fix)
|
||||||
|
- Documentación (docs)
|
||||||
|
- Otros cambios
|
||||||
|
|
||||||
|
Formatea en markdown con encabezados y viñetas apropiados.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT_FR: &str = r#"Vous êtes un assistant qui génère des entrées de journal des modifications.
|
||||||
|
|
||||||
|
Étant donné une version et une liste de commits, générez une section de journal des modifications bien formatée.
|
||||||
|
|
||||||
|
Groupez les commits par :
|
||||||
|
- Fonctionnalités (feat)
|
||||||
|
- Corrections de bugs (fix)
|
||||||
|
- Documentation (docs)
|
||||||
|
- Autres modifications
|
||||||
|
|
||||||
|
Formatez en markdown avec des en-têtes et des puces appropriés.
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const CHANGELOG_SYSTEM_PROMPT_DE: &str = r#"Sie sind ein Assistent, der Changelog-Einträge generiert.
|
||||||
|
|
||||||
|
Gegeben eine Version und eine Liste von Commits, generieren Sie einen gut formatierten Changelog-Abschnitt.
|
||||||
|
|
||||||
|
Gruppieren Sie Commits nach:
|
||||||
|
- Funktionen (feat)
|
||||||
|
- Bugfixes (fix)
|
||||||
|
- Dokumentation (docs)
|
||||||
|
- Andere Änderungen
|
||||||
|
|
||||||
|
Formatieren Sie in Markdown mit geeigneten Überschriften und Aufzählungspunkten.
|
||||||
|
"#;
|
||||||
Reference in New Issue
Block a user