tgit 0.24.0__tar.gz → 0.26.0__tar.gz

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.
Files changed (48) hide show
  1. {tgit-0.24.0 → tgit-0.26.0}/CHANGELOG.md +29 -0
  2. {tgit-0.24.0 → tgit-0.26.0}/PKG-INFO +3 -7
  3. {tgit-0.24.0 → tgit-0.26.0}/README.md +2 -6
  4. {tgit-0.24.0 → tgit-0.26.0}/pyproject.toml +1 -1
  5. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_commit.py +96 -4
  6. {tgit-0.24.0 → tgit-0.26.0}/tgit/commit.py +42 -9
  7. tgit-0.26.0/tgit/constants.py +4 -0
  8. {tgit-0.24.0 → tgit-0.26.0}/tgit/interactive_settings.py +2 -1
  9. {tgit-0.24.0 → tgit-0.26.0}/tgit/prompts/commit.txt +18 -5
  10. {tgit-0.24.0 → tgit-0.26.0}/tgit/types.py +3 -1
  11. {tgit-0.24.0 → tgit-0.26.0}/tgit/utils/__init__.py +2 -1
  12. tgit-0.26.0/uv.lock +902 -0
  13. tgit-0.24.0/uv.lock +0 -781
  14. {tgit-0.24.0 → tgit-0.26.0}/.claude/settings.local.json +0 -0
  15. {tgit-0.24.0 → tgit-0.26.0}/.github/workflows/build.yml +0 -0
  16. {tgit-0.24.0 → tgit-0.26.0}/.github/workflows/ci.yml +0 -0
  17. {tgit-0.24.0 → tgit-0.26.0}/.github/workflows/claude-code-review.yml +0 -0
  18. {tgit-0.24.0 → tgit-0.26.0}/.github/workflows/claude.yml +0 -0
  19. {tgit-0.24.0 → tgit-0.26.0}/.gitignore +0 -0
  20. {tgit-0.24.0 → tgit-0.26.0}/.python-version +0 -0
  21. {tgit-0.24.0 → tgit-0.26.0}/.tgit/settings.json +0 -0
  22. {tgit-0.24.0 → tgit-0.26.0}/.vscode/extensions.json +0 -0
  23. {tgit-0.24.0 → tgit-0.26.0}/.vscode/launch.json +0 -0
  24. {tgit-0.24.0 → tgit-0.26.0}/CLAUDE.md +0 -0
  25. {tgit-0.24.0 → tgit-0.26.0}/pyrightconfig.json +0 -0
  26. {tgit-0.24.0 → tgit-0.26.0}/scripts/publish.sh +0 -0
  27. {tgit-0.24.0 → tgit-0.26.0}/scripts/test.sh +0 -0
  28. {tgit-0.24.0 → tgit-0.26.0}/tests/README.md +0 -0
  29. {tgit-0.24.0 → tgit-0.26.0}/tests/__init__.py +0 -0
  30. {tgit-0.24.0 → tgit-0.26.0}/tests/conftest.py +0 -0
  31. {tgit-0.24.0 → tgit-0.26.0}/tests/integration/__init__.py +0 -0
  32. {tgit-0.24.0 → tgit-0.26.0}/tests/integration/test_version_integration.py +0 -0
  33. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/__init__.py +0 -0
  34. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_add.py +0 -0
  35. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_changelog.py +0 -0
  36. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_cli.py +0 -0
  37. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_interactive_settings.py +0 -0
  38. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_settings.py +0 -0
  39. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_types.py +0 -0
  40. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_utils.py +0 -0
  41. {tgit-0.24.0 → tgit-0.26.0}/tests/unit/test_version.py +0 -0
  42. {tgit-0.24.0 → tgit-0.26.0}/tgit/__init__.py +0 -0
  43. {tgit-0.24.0 → tgit-0.26.0}/tgit/add.py +0 -0
  44. {tgit-0.24.0 → tgit-0.26.0}/tgit/changelog.py +0 -0
  45. {tgit-0.24.0 → tgit-0.26.0}/tgit/cli.py +0 -0
  46. {tgit-0.24.0 → tgit-0.26.0}/tgit/settings.py +0 -0
  47. {tgit-0.24.0 → tgit-0.26.0}/tgit/shared.py +0 -0
  48. {tgit-0.24.0 → tgit-0.26.0}/tgit/version.py +0 -0
@@ -1,3 +1,32 @@
1
+ ## v0.26.0
2
+
3
+ [v0.25.0...v0.26.0](https://github.com/Jannchie/tgit/compare/v0.25.0...v0.26.0)
4
+
5
+ ### :sparkles: Features
6
+
7
+ - **commit**: add secret detection support - By [Jannchie](mailto:jannchie@gmail.com) in [e1f5207](https://github.com/Jannchie/tgit/commit/e1f5207)
8
+
9
+ ### :wrench: Chores
10
+
11
+ - **commit**: add default token limit and defaults to commit model - By [Jannchie](mailto:jannchie@gmail.com) in [66d4d45](https://github.com/Jannchie/tgit/commit/66d4d45)
12
+
13
+ ## v0.25.0
14
+
15
+ [v0.24.1...v0.25.0](https://github.com/Jannchie/tgit/compare/v0.24.1...v0.25.0)
16
+
17
+ ### :sparkles: Features
18
+
19
+ - **ai**: add reasoning support for compatible models - By [Jannchie](mailto:jannchie@gmail.com) in [66d0b41](https://github.com/Jannchie/tgit/commit/66d0b41)
20
+ - **config**: centralize default model and use it - By [Jannchie](mailto:jannchie@gmail.com) in [a4e3ec1](https://github.com/Jannchie/tgit/commit/a4e3ec1)
21
+
22
+ ### :wrench: Chores
23
+
24
+ - **constants**: add gpt-5 to reasoning model hints - By [Jannchie](mailto:jannchie@gmail.com) in [bad2722](https://github.com/Jannchie/tgit/commit/bad2722)
25
+
26
+ ## v0.24.1
27
+
28
+ [v0.24.0...v0.24.1](https://github.com/Jannchie/tgit/compare/v0.24.0...v0.24.1)
29
+
1
30
  ## v0.24.0
2
31
 
3
32
  [v0.23.1...v0.24.0](https://github.com/Jannchie/tgit/compare/v0.23.1...v0.24.0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tgit
3
- Version: 0.24.0
3
+ Version: 0.26.0
4
4
  Summary: Tool for Git Interaction Temptation (tgit): An elegant CLI tool that simplifies and streamlines your Git workflow, making version control a breeze.
5
5
  Author-email: Jannchie <jannchie@gmail.com>
6
6
  License-Expression: MIT
@@ -83,10 +83,6 @@ tgit changelog
83
83
  # Bump version and generate changelog
84
84
  tgit version
85
85
 
86
- # Interactive settings configuration
87
- tgit settings
88
- ```
89
-
90
86
  ### Configuration
91
87
 
92
88
  The easiest way to configure TGIT is through the interactive settings command:
@@ -99,7 +95,7 @@ tgit settings
99
95
  This will guide you through setting up:
100
96
 
101
97
  - OpenAI API key for AI-powered commits
102
- - Preferred AI model (gpt-4, gpt-3.5-turbo, etc.)
98
+ - Preferred AI model (gpt-5-mini, gpt-4.1, etc.)
103
99
  - Commit emoji preferences
104
100
  - Custom commit types
105
101
 
@@ -107,7 +103,7 @@ Alternatively, you can manually create a `.tgit.yaml` file in your project root
107
103
 
108
104
  ```yaml
109
105
  apiKey: "your-openai-api-key"
110
- model: "gpt-4"
106
+ model: "gpt-5-mini"
111
107
  commit:
112
108
  emoji: true
113
109
  types:
@@ -58,10 +58,6 @@ tgit changelog
58
58
  # Bump version and generate changelog
59
59
  tgit version
60
60
 
61
- # Interactive settings configuration
62
- tgit settings
63
- ```
64
-
65
61
  ### Configuration
66
62
 
67
63
  The easiest way to configure TGIT is through the interactive settings command:
@@ -74,7 +70,7 @@ tgit settings
74
70
  This will guide you through setting up:
75
71
 
76
72
  - OpenAI API key for AI-powered commits
77
- - Preferred AI model (gpt-4, gpt-3.5-turbo, etc.)
73
+ - Preferred AI model (gpt-5-mini, gpt-4.1, etc.)
78
74
  - Commit emoji preferences
79
75
  - Custom commit types
80
76
 
@@ -82,7 +78,7 @@ Alternatively, you can manually create a `.tgit.yaml` file in your project root
82
78
 
83
79
  ```yaml
84
80
  apiKey: "your-openai-api-key"
85
- model: "gpt-4"
81
+ model: "gpt-5-mini"
86
82
  commit:
87
83
  emoji: true
88
84
  types:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tgit"
3
- version = "0.24.0"
3
+ version = "0.26.0"
4
4
  description = "Tool for Git Interaction Temptation (tgit): An elegant CLI tool that simplifies and streamlines your Git workflow, making version control a breeze."
5
5
  authors = [{ name = "Jannchie", email = "jannchie@gmail.com" }]
6
6
  dependencies = [
@@ -10,6 +10,7 @@ from click.testing import CliRunner
10
10
  from tgit.commit import (
11
11
  CommitArgs,
12
12
  CommitData,
13
+ PotentialSecret,
13
14
  TemplateParams,
14
15
  get_changed_files_from_status,
15
16
  get_file_change_sizes,
@@ -61,7 +62,7 @@ class TestCommitData:
61
62
 
62
63
  def test_commit_data_creation(self):
63
64
  """Test creating CommitData instance."""
64
- data = CommitData(type="feat", scope="auth", msg="add login functionality", is_breaking=False)
65
+ data = CommitData(type="feat", scope="auth", msg="add login functionality", is_breaking=False, secrets=[])
65
66
  assert data.type == "feat"
66
67
  assert data.scope == "auth"
67
68
  assert data.msg == "add login functionality"
@@ -69,9 +70,16 @@ class TestCommitData:
69
70
 
70
71
  def test_commit_data_with_none_scope(self):
71
72
  """Test CommitData with None scope."""
72
- data = CommitData(type="fix", scope=None, msg="fix bug", is_breaking=False)
73
+ data = CommitData(type="fix", scope=None, msg="fix bug", is_breaking=False, secrets=[])
73
74
  assert data.scope is None
74
75
 
76
+ def test_commit_data_with_secrets(self):
77
+ """Test CommitData with suspected secrets."""
78
+ secret = PotentialSecret(file="config.env", description="looks like api key")
79
+ data = CommitData(type="chore", scope=None, msg="update config", is_breaking=False, secrets=[secret])
80
+ assert len(data.secrets) == 1
81
+ assert data.secrets[0].file == "config.env"
82
+
75
83
 
76
84
  class TestGetChangedFilesFromStatus:
77
85
  """Test get_changed_files_from_status function."""
@@ -296,7 +304,7 @@ class TestGenerateCommitWithAI:
296
304
 
297
305
  # Mock the response
298
306
  mock_response = Mock()
299
- mock_commit_data = CommitData(type="feat", scope="auth", msg="add login", is_breaking=False)
307
+ mock_commit_data = CommitData(type="feat", scope="auth", msg="add login", is_breaking=False, secrets=[])
300
308
  mock_response.output_parsed = mock_commit_data
301
309
  mock_client.responses.parse.return_value = mock_response
302
310
 
@@ -306,6 +314,8 @@ class TestGenerateCommitWithAI:
306
314
  mock_check.assert_called_once()
307
315
  mock_create_client.assert_called_once()
308
316
  mock_client.responses.parse.assert_called_once()
317
+ _, kwargs = mock_client.responses.parse.call_args
318
+ assert "reasoning" not in kwargs
309
319
 
310
320
  @patch("tgit.commit._check_openai_availability")
311
321
  @patch("tgit.commit._create_openai_client")
@@ -319,6 +329,31 @@ class TestGenerateCommitWithAI:
319
329
  with pytest.raises(Exception):
320
330
  _generate_commit_with_ai("diff content", None, "main")
321
331
 
332
+ @patch("tgit.commit._check_openai_availability")
333
+ @patch("tgit.commit._create_openai_client")
334
+ @patch("tgit.commit.console")
335
+ @patch("tgit.commit.commit_prompt_template")
336
+ @patch("tgit.commit.settings")
337
+ def test_generate_commit_with_ai_reasoning_model(self, mock_settings, mock_template, mock_console, mock_create_client, mock_check):
338
+ """Test reasoning effort is added for reasoning-capable models."""
339
+ mock_client = Mock()
340
+ mock_create_client.return_value = mock_client
341
+ mock_template.render.return_value = "system prompt"
342
+ mock_settings.model = "o1-mini"
343
+
344
+ mock_response = Mock()
345
+ mock_commit_data = CommitData(type="fix", scope=None, msg="correct bug", is_breaking=False, secrets=[])
346
+ mock_response.output_parsed = mock_commit_data
347
+ mock_client.responses.parse.return_value = mock_response
348
+
349
+ result = _generate_commit_with_ai("diff content", None, "main")
350
+
351
+ assert result == mock_commit_data
352
+ mock_check.assert_called_once()
353
+ mock_create_client.assert_called_once()
354
+ _, kwargs = mock_client.responses.parse.call_args
355
+ assert kwargs["reasoning"] == {"effort": "minimal"}
356
+
322
357
 
323
358
  class TestGetAICommand:
324
359
  """Test get_ai_command function."""
@@ -369,7 +404,7 @@ class TestGetAICommand:
369
404
  mock_repo_instance.active_branch.name = "main"
370
405
  mock_settings.commit.emoji = True
371
406
 
372
- mock_commit_data = CommitData(type="feat", scope="auth", msg="add login", is_breaking=False)
407
+ mock_commit_data = CommitData(type="feat", scope="auth", msg="add login", is_breaking=False, secrets=[])
373
408
  mock_generate.return_value = mock_commit_data
374
409
  mock_get_commit_command.return_value = "git commit -m 'feat(auth): add login'"
375
410
 
@@ -379,6 +414,63 @@ class TestGetAICommand:
379
414
  mock_generate.assert_called_once()
380
415
  mock_get_commit_command.assert_called_once_with("feat", "auth", "add login", use_emoji=True, is_breaking=False)
381
416
 
417
+ @patch("tgit.commit.click.confirm")
418
+ @patch("tgit.commit.Path.cwd")
419
+ @patch("tgit.commit.git.Repo")
420
+ @patch("tgit.commit.get_filtered_diff_files")
421
+ @patch("tgit.commit._generate_commit_with_ai")
422
+ @patch("tgit.commit.get_commit_command")
423
+ @patch("tgit.commit.settings")
424
+ def test_get_ai_command_detected_secrets_abort(self, mock_settings, mock_get_commit_command, mock_generate, mock_get_files, mock_repo, mock_cwd, mock_confirm):
425
+ """Test get_ai_command aborts when secrets are detected and user declines."""
426
+ mock_cwd.return_value = Path(tempfile.gettempdir())
427
+ mock_repo_instance = Mock()
428
+ mock_repo.return_value = mock_repo_instance
429
+ mock_get_files.return_value = (["src/file.py"], [])
430
+ mock_repo_instance.git.diff.return_value = "diff content"
431
+ mock_repo_instance.active_branch.name = "main"
432
+ mock_settings.commit.emoji = True
433
+
434
+ secret = PotentialSecret(file="src/file.py", description="possible api key")
435
+ mock_commit_data = CommitData(type="feat", scope="auth", msg="add login", is_breaking=False, secrets=[secret])
436
+ mock_generate.return_value = mock_commit_data
437
+ mock_confirm.return_value = False
438
+
439
+ result = get_ai_command()
440
+
441
+ assert result is None
442
+ mock_confirm.assert_called_once_with("Detected potential secrets. Continue with commit?", default=False)
443
+ mock_get_commit_command.assert_not_called()
444
+
445
+ @patch("tgit.commit.click.confirm")
446
+ @patch("tgit.commit.Path.cwd")
447
+ @patch("tgit.commit.git.Repo")
448
+ @patch("tgit.commit.get_filtered_diff_files")
449
+ @patch("tgit.commit._generate_commit_with_ai")
450
+ @patch("tgit.commit.get_commit_command")
451
+ @patch("tgit.commit.settings")
452
+ def test_get_ai_command_detected_secrets_continue(self, mock_settings, mock_get_commit_command, mock_generate, mock_get_files, mock_repo, mock_cwd, mock_confirm):
453
+ """Test get_ai_command continues when secrets are detected and user agrees."""
454
+ mock_cwd.return_value = Path(tempfile.gettempdir())
455
+ mock_repo_instance = Mock()
456
+ mock_repo.return_value = mock_repo_instance
457
+ mock_get_files.return_value = (["src/file.py"], [])
458
+ mock_repo_instance.git.diff.return_value = "diff content"
459
+ mock_repo_instance.active_branch.name = "main"
460
+ mock_settings.commit.emoji = True
461
+
462
+ secret = PotentialSecret(file="src/file.py", description="possible api key")
463
+ mock_commit_data = CommitData(type="feat", scope="auth", msg="add login", is_breaking=False, secrets=[secret])
464
+ mock_generate.return_value = mock_commit_data
465
+ mock_get_commit_command.return_value = "git commit -m 'feat(auth): add login'"
466
+ mock_confirm.return_value = True
467
+
468
+ result = get_ai_command()
469
+
470
+ assert result == "git commit -m 'feat(auth): add login'"
471
+ mock_confirm.assert_called_once_with("Detected potential secrets. Continue with commit?", default=False)
472
+ mock_get_commit_command.assert_called_once_with("feat", "auth", "add login", use_emoji=True, is_breaking=False)
473
+
382
474
  @patch("tgit.commit.Path.cwd")
383
475
  @patch("tgit.commit.git.Repo")
384
476
  @patch("tgit.commit.get_filtered_diff_files")
@@ -3,14 +3,15 @@ import importlib.resources
3
3
  import itertools
4
4
  from dataclasses import dataclass
5
5
  from pathlib import Path
6
- from typing import TYPE_CHECKING
6
+ from typing import TYPE_CHECKING, Any
7
7
 
8
8
  import click
9
9
  import git
10
10
  from jinja2 import Environment, FileSystemLoader
11
- from pydantic import BaseModel
11
+ from pydantic import BaseModel, Field
12
12
  from rich import get_console, print
13
13
 
14
+ from tgit.constants import DEFAULT_MODEL, REASONING_MODEL_HINTS
14
15
  from tgit.shared import settings
15
16
  from tgit.utils import get_commit_command, run_command, type_emojis
16
17
 
@@ -24,6 +25,7 @@ with importlib.resources.path("tgit", "prompts") as prompt_path:
24
25
  commit_types = ["feat", "fix", "chore", "docs", "style", "refactor", "perf", "wip"]
25
26
  commit_file = "commit.txt"
26
27
  commit_prompt_template = env.get_template("commit.txt")
28
+ DEFAULT_MAX_OUTPUT_TOKENS = 256
27
29
 
28
30
  # Define click arguments/options at module level to avoid B008
29
31
  MESSAGE_ARG = click.argument(
@@ -64,11 +66,25 @@ class TemplateParams:
64
66
  specified_type: str | None = None
65
67
 
66
68
 
69
+ class PotentialSecret(BaseModel):
70
+ file: str
71
+ description: str
72
+
73
+
67
74
  class CommitData(BaseModel):
68
75
  type: str
69
- scope: str | None
76
+ scope: str | None = None
70
77
  msg: str
71
- is_breaking: bool
78
+ is_breaking: bool = False
79
+ secrets: list[PotentialSecret] = Field(default_factory=list)
80
+
81
+
82
+ def _supports_reasoning(model: str) -> bool:
83
+ """Return True when the selected model supports reasoning parameters."""
84
+ if not model:
85
+ return False
86
+ model_lower = model.lower()
87
+ return any(hint in model_lower for hint in REASONING_MODEL_HINTS)
72
88
 
73
89
 
74
90
  def get_changed_files_from_status(repo: git.Repo) -> set[str]:
@@ -177,17 +193,24 @@ def _generate_commit_with_ai(diff: str, specified_type: str | None, current_bran
177
193
  )
178
194
 
179
195
  with console.status("[bold green]Generating commit message...[/bold green]"):
180
- chat_completion = client.responses.parse(
181
- input=[
196
+ model_name = settings.model or DEFAULT_MODEL
197
+ request_kwargs: dict[str, Any] = {
198
+ "input": [
182
199
  {
183
200
  "role": "system",
184
201
  "content": commit_prompt_template.render(**template_params.__dict__),
185
202
  },
186
203
  {"role": "user", "content": diff},
187
204
  ],
188
- model=settings.model or "gpt-4.1",
189
- max_output_tokens=50,
190
- text_format=CommitData,
205
+ "model": model_name,
206
+ "max_output_tokens": DEFAULT_MAX_OUTPUT_TOKENS,
207
+ "text_format": CommitData,
208
+ }
209
+ if _supports_reasoning(model_name):
210
+ request_kwargs["reasoning"] = {"effort": "minimal"}
211
+
212
+ chat_completion = client.responses.parse(
213
+ **request_kwargs,
191
214
  )
192
215
 
193
216
  return chat_completion.output_parsed
@@ -227,6 +250,16 @@ def get_ai_command(specified_type: str | None = None) -> str | None:
227
250
  print(e)
228
251
  return None
229
252
 
253
+ detected_secrets: list[PotentialSecret] = resp.secrets if resp.secrets else []
254
+ if detected_secrets:
255
+ print("[red]Detected potential secrets in these files:[/red]")
256
+ for secret in detected_secrets:
257
+ print(f"[red]- {secret.file}: {secret.description}[/red]")
258
+ proceed = click.confirm("Detected potential secrets. Continue with commit?", default=False)
259
+ if not proceed:
260
+ print("[yellow]Commit aborted. Please review sensitive content.[/yellow]")
261
+ return None
262
+
230
263
  # 如果用户指定了类型,则使用用户指定的类型,否则使用 AI 生成的类型
231
264
  commit_type = specified_type if specified_type is not None else resp.type
232
265
 
@@ -0,0 +1,4 @@
1
+ """Global constants used across the TGIT project."""
2
+
3
+ DEFAULT_MODEL = "gpt-5-mini"
4
+ REASONING_MODEL_HINTS = ("-reasoning", "o1", "o3", "gpt-5")
@@ -8,6 +8,7 @@ import questionary
8
8
  from questionary import Choice
9
9
  from rich import print
10
10
 
11
+ from tgit.constants import DEFAULT_MODEL
11
12
  from tgit.utils import load_global_settings, load_workspace_settings
12
13
 
13
14
 
@@ -84,7 +85,7 @@ def _configure_global_settings() -> None:
84
85
 
85
86
  model = questionary.text(
86
87
  "Model name",
87
- default=current_settings.get("model", "gpt-4o-mini"),
88
+ default=current_settings.get("model", DEFAULT_MODEL),
88
89
  ).ask()
89
90
  if model is None:
90
91
  return
@@ -34,12 +34,18 @@ Mark `is_breaking: true` only if changes:
34
34
  - Require user action for compatibility
35
35
  - Remove or significantly change existing functionality
36
36
 
37
+ ### Secret Detection
38
+ - Review the diff for potential secrets (API keys, tokens, passwords, private keys, credentials, etc.).
39
+ - For every suspected secret, add an entry to the `secrets` array with the file path and a brief description of why it is sensitive.
40
+ - If no secrets are found, return an empty array.
41
+
37
42
  ## Analysis Process
38
43
  1. Review the diff comprehensively
39
44
  2. Identify the primary type of change
40
45
  3. Determine appropriate scope from modified files/areas
41
46
  4. Craft a concise message covering main changes
42
47
  5. Assess backward compatibility impact
48
+ 6. Flag any suspected secrets
43
49
 
44
50
  ## Output Format
45
51
  Return valid JSON matching this structure:
@@ -48,15 +54,22 @@ Return valid JSON matching this structure:
48
54
  "type": "string",
49
55
  "scope": "string|null",
50
56
  "msg": "string",
51
- "is_breaking": "boolean"
57
+ "is_breaking": "boolean",
58
+ "secrets": [
59
+ {
60
+ "file": "string",
61
+ "description": "string"
62
+ }
63
+ ]
52
64
  }
53
65
  ```
54
66
 
55
67
  ## Examples
56
68
  ```json
57
- {"type": "feat", "scope": "auth", "msg": "add oauth2 login", "is_breaking": false}
58
- {"type": "fix", "scope": "api", "msg": "handle null user responses", "is_breaking": false}
59
- {"type": "refactor", "scope": null, "msg": "restructure project layout", "is_breaking": true}
69
+ {"type": "feat", "scope": "auth", "msg": "add oauth2 login", "is_breaking": false, "secrets": []}
70
+ {"type": "fix", "scope": "api", "msg": "handle null user responses", "is_breaking": false, "secrets": []}
71
+ {"type": "refactor", "scope": null, "msg": "restructure project layout", "is_breaking": true, "secrets": []}
72
+ {"type": "chore", "scope": "config", "msg": "update secrets storage", "is_breaking": false, "secrets": [{"file": "config/.env", "description": "detected value resembling api key"}]}
60
73
  ```
61
74
 
62
- Now analyze the provided diff and generate the commit message.
75
+ Now analyze the provided diff and generate the commit message.
@@ -3,6 +3,8 @@
3
3
  from dataclasses import dataclass, field
4
4
  from typing import TYPE_CHECKING, Any
5
5
 
6
+ from tgit.constants import DEFAULT_MODEL
7
+
6
8
  if TYPE_CHECKING:
7
9
  import argparse
8
10
 
@@ -31,6 +33,6 @@ class TGitSettings:
31
33
  commit: CommitSettings = field(default_factory=CommitSettings)
32
34
  api_key: str = ""
33
35
  api_url: str = ""
34
- model: str = ""
36
+ model: str = DEFAULT_MODEL
35
37
  show_command: bool = True
36
38
  skip_confirm: bool = False
@@ -8,6 +8,7 @@ import questionary
8
8
  import rich
9
9
  from rich.syntax import Syntax
10
10
 
11
+ from tgit.constants import DEFAULT_MODEL
11
12
  from tgit.types import CommitSettings, CommitType, TGitSettings
12
13
 
13
14
  console = rich.get_console()
@@ -147,7 +148,7 @@ def _dict_to_settings(data: dict[str, Any]) -> TGitSettings:
147
148
  commit=commit_settings,
148
149
  api_key=data.get("apiKey", ""),
149
150
  api_url=data.get("apiUrl", ""),
150
- model=data.get("model", ""),
151
+ model=data.get("model") or DEFAULT_MODEL,
151
152
  show_command=data.get("show_command", True),
152
153
  skip_confirm=data.get("skip_confirm", False),
153
154
  )