titan-cli 0.1.4__tar.gz → 0.1.6__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 (163) hide show
  1. {titan_cli-0.1.4 → titan_cli-0.1.6}/PKG-INFO +3 -5
  2. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/clients/git_client.py +140 -5
  3. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/plugin.py +13 -0
  4. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/steps/ai_commit_message_step.py +39 -34
  5. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/steps/branch_steps.py +18 -37
  6. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/checkout_step.py +66 -0
  7. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/steps/commit_step.py +18 -22
  8. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/create_branch_step.py +131 -0
  9. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/diff_summary_step.py +180 -0
  10. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/pull_step.py +70 -0
  11. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/steps/push_step.py +27 -11
  12. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/restore_original_branch_step.py +97 -0
  13. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/save_current_branch_step.py +82 -0
  14. titan_cli-0.1.6/plugins/titan-plugin-git/titan_plugin_git/steps/status_step.py +66 -0
  15. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/workflows/commit-ai.yaml +9 -3
  16. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/agents/pr_agent.py +15 -2
  17. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/steps/ai_pr_step.py +99 -40
  18. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/steps/create_pr_step.py +18 -8
  19. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/steps/github_prompt_steps.py +53 -1
  20. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/steps/issue_steps.py +31 -18
  21. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/steps/preview_step.py +15 -4
  22. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/utils.py +5 -4
  23. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/workflows/create-pr-ai.yaml +6 -11
  24. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/messages.py +12 -0
  25. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/plugin.py +4 -0
  26. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/steps/ai_analyze_issue_step.py +12 -7
  27. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/steps/get_issue_step.py +17 -13
  28. titan_cli-0.1.6/plugins/titan-plugin-jira/titan_plugin_jira/steps/list_versions_step.py +133 -0
  29. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/steps/prompt_select_issue_step.py +20 -8
  30. titan_cli-0.1.6/plugins/titan-plugin-jira/titan_plugin_jira/steps/search_jql_step.py +191 -0
  31. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/steps/search_saved_query_step.py +26 -24
  32. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/utils/__init__.py +1 -1
  33. {titan_cli-0.1.4 → titan_cli-0.1.6}/pyproject.toml +9 -9
  34. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/config.py +3 -1
  35. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/workflows/__init__.py +2 -1
  36. titan_cli-0.1.6/titan_cli/core/workflows/project_step_source.py +149 -0
  37. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/workflows/workflow_filter_service.py +16 -8
  38. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/workflows/workflow_registry.py +12 -1
  39. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/workflows/workflow_sources.py +1 -1
  40. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/__init__.py +5 -1
  41. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/results.py +31 -1
  42. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/steps/ai_assistant_step.py +47 -12
  43. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/workflow_executor.py +13 -3
  44. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/plugin_config_wizard.py +16 -0
  45. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/workflow_execution.py +28 -50
  46. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/workflows.py +8 -4
  47. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/textual_components.py +342 -185
  48. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/textual_workflow_executor.py +39 -3
  49. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/theme.py +34 -5
  50. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/widgets/__init__.py +17 -0
  51. titan_cli-0.1.6/titan_cli/ui/tui/widgets/multiline_input.py +32 -0
  52. titan_cli-0.1.6/titan_cli/ui/tui/widgets/prompt_choice.py +138 -0
  53. titan_cli-0.1.6/titan_cli/ui/tui/widgets/prompt_input.py +74 -0
  54. titan_cli-0.1.6/titan_cli/ui/tui/widgets/prompt_selection_list.py +150 -0
  55. titan_cli-0.1.6/titan_cli/ui/tui/widgets/prompt_textarea.py +87 -0
  56. titan_cli-0.1.6/titan_cli/ui/tui/widgets/step_container.py +70 -0
  57. titan_cli-0.1.6/titan_cli/ui/tui/widgets/styled_option_list.py +107 -0
  58. titan_cli-0.1.6/titan_cli/ui/tui/widgets/text.py +98 -0
  59. titan_cli-0.1.4/plugins/titan-plugin-git/titan_plugin_git/steps/status_step.py +0 -59
  60. titan_cli-0.1.4/titan_cli/core/workflows/project_step_source.py +0 -86
  61. titan_cli-0.1.4/titan_cli/ui/tui/widgets/text.py +0 -177
  62. {titan_cli-0.1.4 → titan_cli-0.1.6}/LICENSE +0 -0
  63. {titan_cli-0.1.4 → titan_cli-0.1.6}/README.md +0 -0
  64. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/__init__.py +0 -0
  65. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/clients/__init__.py +0 -0
  66. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/exceptions.py +0 -0
  67. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/messages.py +0 -0
  68. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/models.py +0 -0
  69. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/steps/__init__.py +0 -0
  70. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/workflows/__previews__/__init__.py +0 -0
  71. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-git/titan_plugin_git/workflows/__previews__/commit_ai_preview.py +0 -0
  72. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/__init__.py +0 -0
  73. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/agents/__init__.py +0 -0
  74. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/agents/config_loader.py +0 -0
  75. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/agents/issue_generator.py +0 -0
  76. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/clients/__init__.py +0 -0
  77. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/clients/github_client.py +0 -0
  78. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/config/__init__.py +0 -0
  79. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/config/pr_agent.toml +0 -0
  80. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/exceptions.py +0 -0
  81. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/messages.py +0 -0
  82. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/models.py +0 -0
  83. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/plugin.py +0 -0
  84. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/steps/__init__.py +0 -0
  85. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/workflows/__previews__/__init__.py +0 -0
  86. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/workflows/__previews__/create_pr_ai_preview.py +0 -0
  87. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-github/titan_plugin_github/workflows/create-issue-ai.yaml +0 -0
  88. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/__init__.py +0 -0
  89. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/__init__.py +0 -0
  90. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/config_loader.py +0 -0
  91. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/jira_agent.py +0 -0
  92. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/prompts.py +0 -0
  93. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/response_parser.py +0 -0
  94. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/token_tracker.py +0 -0
  95. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/agents/validators.py +0 -0
  96. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/clients/jira_client.py +0 -0
  97. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/config/jira_agent.toml +0 -0
  98. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/config/templates/issue_analysis.md.j2 +0 -0
  99. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/exceptions.py +0 -0
  100. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/formatters/__init__.py +0 -0
  101. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/formatters/markdown_formatter.py +0 -0
  102. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/models.py +0 -0
  103. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/utils/issue_sorter.py +0 -0
  104. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/utils/saved_queries.py +0 -0
  105. {titan_cli-0.1.4 → titan_cli-0.1.6}/plugins/titan-plugin-jira/titan_plugin_jira/workflows/analyze-jira-issues.yaml +0 -0
  106. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/__init__.py +0 -0
  107. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/__main__.py +0 -0
  108. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/__init__.py +0 -0
  109. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/agents/__init__.py +0 -0
  110. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/agents/base.py +0 -0
  111. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/client.py +0 -0
  112. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/constants.py +0 -0
  113. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/exceptions.py +0 -0
  114. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/models.py +0 -0
  115. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/oauth_helper.py +0 -0
  116. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/providers/__init__.py +0 -0
  117. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/providers/anthropic.py +0 -0
  118. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/providers/base.py +0 -0
  119. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ai/providers/gemini.py +0 -0
  120. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/cli.py +0 -0
  121. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/clients/__init__.py +0 -0
  122. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/clients/gcloud_client.py +0 -0
  123. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/__init__.py +0 -0
  124. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/discovery.py +0 -0
  125. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/errors.py +0 -0
  126. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/models.py +0 -0
  127. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/plugins/available.py +0 -0
  128. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/plugins/models.py +0 -0
  129. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/plugins/plugin_base.py +0 -0
  130. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/plugins/plugin_registry.py +0 -0
  131. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/secrets.py +0 -0
  132. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/workflows/models.py +0 -0
  133. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/core/workflows/workflow_exceptions.py +0 -0
  134. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/builder.py +0 -0
  135. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/context.py +0 -0
  136. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/mock_context.py +0 -0
  137. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/steps/command_step.py +0 -0
  138. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/utils/__init__.py +0 -0
  139. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/engine/utils/venv.py +0 -0
  140. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/external_cli/__init__.py +0 -0
  141. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/external_cli/configs.py +0 -0
  142. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/external_cli/launcher.py +0 -0
  143. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/messages.py +0 -0
  144. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/__init__.py +0 -0
  145. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/__previews__/statusbar_preview.py +0 -0
  146. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/app.py +0 -0
  147. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/icons.py +0 -0
  148. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/__init__.py +0 -0
  149. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/ai_config.py +0 -0
  150. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/ai_config_wizard.py +0 -0
  151. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/base.py +0 -0
  152. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/cli_launcher.py +0 -0
  153. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/global_setup_wizard.py +0 -0
  154. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/main_menu.py +0 -0
  155. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/plugin_management.py +0 -0
  156. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/screens/project_setup_wizard.py +0 -0
  157. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/widgets/button.py +0 -0
  158. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/widgets/header.py +0 -0
  159. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/widgets/panel.py +0 -0
  160. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/widgets/status_bar.py +0 -0
  161. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/ui/tui/widgets/table.py +0 -0
  162. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/utils/__init__.py +0 -0
  163. {titan_cli-0.1.4 → titan_cli-0.1.6}/titan_cli/utils/autoupdate.py +0 -0
@@ -1,14 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: titan-cli
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Modular development tools orchestrator - Streamline your workflows with AI integration and intuitive terminal UI
5
5
  Home-page: https://github.com/masmovil/titan-cli
6
6
  License: MIT
7
7
  Keywords: cli,workflow,orchestrator,automation,devtools,ai
8
- Author: finxo
9
- Author-email: finxeto@gmail.com
10
- Maintainer: r-pedraza
11
- Maintainer-email: raulpedrazaleon@gmail.com
8
+ Author: MasOrange Apps Team
9
+ Author-email: apps-management-stores@masorange.es
12
10
  Requires-Python: >=3.10,<4.0.0
13
11
  Classifier: Development Status :: 5 - Production/Stable
14
12
  Classifier: Environment :: Console
@@ -109,6 +109,27 @@ class GitClient:
109
109
  """
110
110
  return self._run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"])
111
111
 
112
+ def get_current_commit(self) -> str:
113
+ """
114
+ Get current commit SHA (HEAD)
115
+
116
+ Returns:
117
+ Full SHA of current commit
118
+ """
119
+ return self._run_command(["git", "rev-parse", "HEAD"])
120
+
121
+ def get_commit_sha(self, ref: str) -> str:
122
+ """
123
+ Get commit SHA for any git ref (branch, tag, remote branch, etc.)
124
+
125
+ Args:
126
+ ref: Git reference (e.g., "HEAD", "develop", "origin/main", "v1.0.0")
127
+
128
+ Returns:
129
+ Full SHA of the commit
130
+ """
131
+ return self._run_command(["git", "rev-parse", ref])
132
+
112
133
  def get_status(self) -> GitStatus:
113
134
  """
114
135
  Get repository status
@@ -282,13 +303,14 @@ class GitClient:
282
303
  """
283
304
  self._run_command(["git", "branch", branch_name, start_point])
284
305
 
285
- def commit(self, message: str, all: bool = False) -> str:
306
+ def commit(self, message: str, all: bool = False, no_verify: bool = True) -> str:
286
307
  """
287
308
  Create a commit
288
309
 
289
310
  Args:
290
311
  message: Commit message
291
312
  all: Stage all modified and new files (`git add --all`)
313
+ no_verify: Skip pre-commit and commit-msg hooks
292
314
 
293
315
  Returns:
294
316
  Commit hash
@@ -298,6 +320,8 @@ class GitClient:
298
320
  self._run_command(["git", "add", "--all"])
299
321
 
300
322
  args = ["git", "commit", "-m", message]
323
+ if no_verify:
324
+ args.append("--no-verify")
301
325
  self._run_command(args)
302
326
 
303
327
  return self._run_command(["git", "rev-parse", "HEAD"])
@@ -347,7 +371,7 @@ class GitClient:
347
371
  self._run_command(["git", "branch", delete_arg, branch])
348
372
  return True
349
373
 
350
- def push(self, remote: str = "origin", branch: Optional[str] = None, set_upstream: bool = False) -> None:
374
+ def push(self, remote: str = "origin", branch: Optional[str] = None, set_upstream: bool = False, tags: bool = False) -> None:
351
375
  """
352
376
  Push to remote
353
377
 
@@ -355,12 +379,16 @@ class GitClient:
355
379
  remote: Remote name
356
380
  branch: Branch to push (default: current)
357
381
  set_upstream: Set upstream tracking
382
+ tags: Push tags to remote (use --tags flag)
358
383
  """
359
384
  args = ["git", "push"]
360
385
 
361
386
  if set_upstream:
362
387
  args.append("-u")
363
-
388
+
389
+ if tags:
390
+ args.append("--tags")
391
+
364
392
  args.append(remote)
365
393
 
366
394
  if branch:
@@ -383,12 +411,13 @@ class GitClient:
383
411
 
384
412
  self._run_command(args)
385
413
 
386
- def fetch(self, remote: str = "origin", all: bool = False) -> None:
414
+ def fetch(self, remote: str = "origin", branch: Optional[str] = None, all: bool = False) -> None:
387
415
  """
388
416
  Fetch from remote
389
417
 
390
418
  Args:
391
419
  remote: Remote name
420
+ branch: Specific branch to fetch (optional)
392
421
  all: Fetch from all remotes
393
422
  """
394
423
  args = ["git", "fetch"]
@@ -397,6 +426,8 @@ class GitClient:
397
426
  args.append("--all")
398
427
  else:
399
428
  args.append(remote)
429
+ if branch:
430
+ args.append(branch)
400
431
 
401
432
  self._run_command(args)
402
433
 
@@ -729,6 +760,39 @@ class GitClient:
729
760
  except GitCommandError:
730
761
  return ""
731
762
 
763
+ def get_uncommitted_diff_stat(self) -> str:
764
+ """
765
+ Get diff stat summary of uncommitted changes (git diff --stat HEAD).
766
+
767
+ Returns a summary showing files changed, insertions, and deletions.
768
+
769
+ Returns:
770
+ Diff stat output as string
771
+ """
772
+ try:
773
+ return self._run_command(["git", "diff", "--stat", "HEAD"], check=False)
774
+ except GitCommandError:
775
+ return ""
776
+
777
+ def get_branch_diff_stat(self, base_branch: str, head_branch: str) -> str:
778
+ """
779
+ Get diff stat summary between two branches.
780
+
781
+ Args:
782
+ base_branch: Base branch name
783
+ head_branch: Head branch name
784
+
785
+ Returns:
786
+ Diff stat output as string
787
+ """
788
+ try:
789
+ return self._run_command(
790
+ ["git", "diff", "--stat", f"{base_branch}...{head_branch}"],
791
+ check=False
792
+ )
793
+ except GitCommandError:
794
+ return ""
795
+
732
796
  def get_branch_commits(self, base_branch: str, head_branch: str) -> list[str]:
733
797
  """
734
798
  Get list of commits in head_branch that are not in base_branch.
@@ -769,4 +833,75 @@ class GitClient:
769
833
  except GitCommandError:
770
834
  # Command failed, likely no remote 'origin' or not a git repo
771
835
  pass
772
- return None, None
836
+ return None, None
837
+
838
+ def create_tag(self, tag_name: str, message: str, ref: str = "HEAD") -> None:
839
+ """
840
+ Create an annotated tag
841
+
842
+ Args:
843
+ tag_name: Name of the tag
844
+ message: Tag annotation message
845
+ ref: Reference to tag (default: HEAD)
846
+
847
+ Raises:
848
+ GitCommandError: If tag creation fails
849
+ """
850
+ self._run_command(["git", "tag", "-a", tag_name, "-m", message, ref])
851
+
852
+ def delete_tag(self, tag_name: str) -> None:
853
+ """
854
+ Delete a local tag
855
+
856
+ Args:
857
+ tag_name: Name of the tag to delete
858
+
859
+ Raises:
860
+ GitCommandError: If tag deletion fails
861
+ """
862
+ self._run_command(["git", "tag", "-d", tag_name])
863
+
864
+ def tag_exists(self, tag_name: str) -> bool:
865
+ """
866
+ Check if a tag exists locally
867
+
868
+ Args:
869
+ tag_name: Name of the tag to check
870
+
871
+ Returns:
872
+ True if tag exists, False otherwise
873
+ """
874
+ try:
875
+ self._run_command(["git", "tag", "-l", tag_name], check=False)
876
+ tags = self._run_command(["git", "tag", "-l", tag_name]).strip()
877
+ return tags == tag_name
878
+ except GitCommandError:
879
+ return False
880
+
881
+ def list_tags(self) -> List[str]:
882
+ """
883
+ List all tags in the repository
884
+
885
+ Returns:
886
+ List of tag names
887
+ """
888
+ try:
889
+ output = self._run_command(["git", "tag", "-l"])
890
+ if output.strip():
891
+ return [tag.strip() for tag in output.split('\n') if tag.strip()]
892
+ return []
893
+ except GitCommandError:
894
+ return []
895
+
896
+ def is_protected_branch(self, branch: str) -> bool:
897
+ """
898
+ Check if a branch is protected (main, master, develop, etc.)
899
+
900
+ Args:
901
+ branch: Branch name to check
902
+
903
+ Returns:
904
+ True if branch is protected
905
+ """
906
+ protected_branches = ["main", "master", "develop", "production", "staging"]
907
+ return branch.lower() in protected_branches
@@ -100,6 +100,12 @@ class GitPlugin(TitanPlugin):
100
100
  """
101
101
  from .steps.branch_steps import get_current_branch_step, get_base_branch_step
102
102
  from .steps.ai_commit_message_step import ai_generate_commit_message
103
+ from .steps.diff_summary_step import show_uncommitted_diff_summary, show_branch_diff_summary
104
+ from .steps.save_current_branch_step import save_current_branch_step
105
+ from .steps.restore_original_branch_step import restore_original_branch_step
106
+ from .steps.checkout_step import checkout_branch_step
107
+ from .steps.pull_step import pull_step
108
+ from .steps.create_branch_step import create_branch_step
103
109
 
104
110
  return {
105
111
  "get_status": get_git_status_step,
@@ -108,6 +114,13 @@ class GitPlugin(TitanPlugin):
108
114
  "get_current_branch": get_current_branch_step,
109
115
  "get_base_branch": get_base_branch_step,
110
116
  "ai_generate_commit_message": ai_generate_commit_message,
117
+ "show_uncommitted_diff_summary": show_uncommitted_diff_summary,
118
+ "show_branch_diff_summary": show_branch_diff_summary,
119
+ "save_current_branch": save_current_branch_step,
120
+ "restore_original_branch": restore_original_branch_step,
121
+ "checkout": checkout_branch_step,
122
+ "pull": pull_step,
123
+ "create_branch": create_branch_step,
111
124
  }
112
125
 
113
126
  @property
@@ -1,7 +1,6 @@
1
1
  # plugins/titan-plugin-git/titan_plugin_git/steps/ai_commit_message_step.py
2
2
  from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error, Skip
3
3
  from titan_plugin_git.messages import msg
4
- from titan_cli.ui.tui.widgets import Panel
5
4
 
6
5
 
7
6
  def ai_generate_commit_message(ctx: WorkflowContext) -> WorkflowResult:
@@ -29,39 +28,36 @@ def ai_generate_commit_message(ctx: WorkflowContext) -> WorkflowResult:
29
28
  if not ctx.textual:
30
29
  return Error("Textual UI context is not available for this step.")
31
30
 
31
+ # Begin step container
32
+ ctx.textual.begin_step("AI Commit Message")
33
+
32
34
  # Check if AI is configured
33
35
  if not ctx.ai or not ctx.ai.is_available():
34
- ctx.textual.mount(
35
- Panel(
36
- text=msg.Steps.AICommitMessage.AI_NOT_CONFIGURED,
37
- panel_type="info"
38
- )
39
- )
36
+ ctx.textual.dim_text(msg.Steps.AICommitMessage.AI_NOT_CONFIGURED)
37
+ ctx.textual.end_step("skip")
40
38
  return Skip(msg.Steps.AICommitMessage.AI_NOT_CONFIGURED)
41
39
 
42
40
  # Get git client
43
41
  if not ctx.git:
42
+ ctx.textual.end_step("error")
44
43
  return Error(msg.Steps.AICommitMessage.GIT_CLIENT_NOT_AVAILABLE)
45
44
 
46
45
  # Get git status
47
46
  git_status = ctx.get('git_status')
48
47
  if not git_status or git_status.is_clean:
49
- ctx.textual.mount(
50
- Panel(
51
- text=msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT,
52
- panel_type="info"
53
- )
54
- )
48
+ ctx.textual.dim_text(msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT)
49
+ ctx.textual.end_step("skip")
55
50
  return Skip(msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT)
56
51
 
57
52
  try:
58
53
  # Get diff of uncommitted changes
59
- ctx.textual.text(msg.Steps.AICommitMessage.ANALYZING_CHANGES, markup="dim")
54
+ ctx.textual.dim_text(msg.Steps.AICommitMessage.ANALYZING_CHANGES)
60
55
 
61
56
  # Get diff of all uncommitted changes
62
57
  diff_text = ctx.git.get_uncommitted_diff()
63
58
 
64
59
  if not diff_text or diff_text.strip() == "":
60
+ ctx.textual.end_step("skip")
65
61
  return Skip(msg.Steps.AICommitMessage.NO_UNCOMMITTED_CHANGES)
66
62
 
67
63
  # Build AI prompt
@@ -86,17 +82,17 @@ def ai_generate_commit_message(ctx: WorkflowContext) -> WorkflowResult:
86
82
 
87
83
  ## CRITICAL Instructions
88
84
  Generate ONE single-line conventional commit message following this EXACT format:
89
- - type(scope): description
85
+ - type(scope): Description
90
86
  - Types: feat, fix, refactor, docs, test, chore, style, perf
91
87
  - Scope: area affected (e.g., auth, api, ui)
92
- - Description: clear summary in imperative mood (be descriptive, concise, and at least 5 words long)
88
+ - Description: clear summary in imperative mood, starting with CAPITAL letter (be descriptive, concise, and at least 5 words long)
93
89
  - NO line breaks, NO body, NO additional explanation
94
90
 
95
- Examples (notice they are all one line):
96
- - feat(auth): add OAuth2 integration with Google provider
97
- - fix(api): resolve race condition in cache invalidation
98
- - refactor(ui): simplify menu component and remove unused props
99
- - refactor(workflows): add support for nested workflow execution
91
+ Examples (notice they start with capital letter and are all one line):
92
+ - feat(auth): Add OAuth2 integration with Google provider
93
+ - fix(api): Resolve race condition in cache invalidation
94
+ - refactor(ui): Simplify menu component and remove unused props
95
+ - refactor(workflows): Add support for nested workflow execution
100
96
 
101
97
  Return ONLY the single-line commit message, absolutely nothing else."""
102
98
 
@@ -115,14 +111,26 @@ Return ONLY the single-line commit message, absolutely nothing else."""
115
111
  # Take only the first line if AI returned multiple lines
116
112
  commit_message = commit_message.split('\n')[0].strip()
117
113
 
114
+ # Ensure subject starts with capital letter (conventional commits requirement)
115
+ # Format: type(scope): Description
116
+ if ':' in commit_message:
117
+ parts = commit_message.split(':', 1)
118
+ if len(parts) == 2:
119
+ prefix = parts[0] # type(scope)
120
+ subject = parts[1].strip() # description
121
+ # Capitalize first letter of subject
122
+ if subject and subject[0].islower():
123
+ subject = subject[0].upper() + subject[1:]
124
+ commit_message = f"{prefix}: {subject}"
125
+
118
126
  # Show preview to user
119
127
  ctx.textual.text("") # spacing
120
- ctx.textual.text(msg.Steps.AICommitMessage.GENERATED_MESSAGE_TITLE, markup="bold")
121
- ctx.textual.text(f" {commit_message}", markup="bold cyan")
128
+ ctx.textual.bold_text(msg.Steps.AICommitMessage.GENERATED_MESSAGE_TITLE)
129
+ ctx.textual.bold_primary_text(f" {commit_message}")
122
130
 
123
131
  # Warn if message is too long
124
132
  if len(commit_message) > 72:
125
- ctx.textual.text(msg.Steps.AICommitMessage.MESSAGE_LENGTH_WARNING.format(length=len(commit_message)), markup="yellow")
133
+ ctx.textual.warning_text(msg.Steps.AICommitMessage.MESSAGE_LENGTH_WARNING.format(length=len(commit_message)))
126
134
 
127
135
  ctx.textual.text("") # spacing
128
136
 
@@ -136,34 +144,31 @@ Return ONLY the single-line commit message, absolutely nothing else."""
136
144
  try:
137
145
  manual_message = ctx.textual.ask_text(msg.Prompts.ENTER_COMMIT_MESSAGE)
138
146
  if not manual_message:
147
+ ctx.textual.end_step("error")
139
148
  return Error(msg.Steps.Commit.COMMIT_MESSAGE_REQUIRED)
140
149
 
141
150
  # Overwrite the metadata to ensure the manual message is used
151
+ ctx.textual.end_step("success")
142
152
  return Success(
143
153
  message=msg.Steps.Prompt.COMMIT_MESSAGE_CAPTURED,
144
154
  metadata={"commit_message": manual_message}
145
155
  )
146
156
  except (KeyboardInterrupt, EOFError):
157
+ ctx.textual.end_step("error")
147
158
  return Error(msg.Steps.Prompt.USER_CANCELLED)
148
159
 
149
- # Show success panel
150
- ctx.textual.mount(
151
- Panel(
152
- text="AI commit message generated successfully",
153
- panel_type="success"
154
- )
155
- )
156
-
157
160
  # Success - save to context
161
+ ctx.textual.end_step("success")
158
162
  return Success(
159
163
  msg.Steps.AICommitMessage.SUCCESS_MESSAGE,
160
164
  metadata={"commit_message": commit_message}
161
165
  )
162
166
 
163
167
  except Exception as e:
164
- ctx.textual.text(msg.Steps.AICommitMessage.GENERATION_FAILED.format(e=e), markup="yellow")
165
- ctx.textual.text(msg.Steps.AICommitMessage.FALLBACK_TO_MANUAL, markup="dim")
168
+ ctx.textual.warning_text(msg.Steps.AICommitMessage.GENERATION_FAILED.format(e=e))
169
+ ctx.textual.dim_text(msg.Steps.AICommitMessage.FALLBACK_TO_MANUAL)
166
170
 
171
+ ctx.textual.end_step("skip")
167
172
  return Skip(msg.Steps.AICommitMessage.GENERATION_FAILED.format(e=e))
168
173
 
169
174
 
@@ -1,6 +1,5 @@
1
1
  # plugins/titan-plugin-git/titan_plugin_git/steps/branch_steps.py
2
2
  from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
3
- from titan_cli.ui.tui.widgets import Panel
4
3
  from titan_plugin_git.messages import msg
5
4
 
6
5
  def get_current_branch_step(ctx: WorkflowContext) -> WorkflowResult:
@@ -20,37 +19,28 @@ def get_current_branch_step(ctx: WorkflowContext) -> WorkflowResult:
20
19
  if not ctx.textual:
21
20
  return Error("Textual UI context is not available for this step.")
22
21
 
22
+ # Begin step container
23
+ ctx.textual.begin_step("Get Head Branch")
24
+
23
25
  if not ctx.git:
24
26
  error_msg = msg.Steps.Status.GIT_CLIENT_NOT_AVAILABLE
25
- ctx.textual.mount(
26
- Panel(
27
- text=error_msg,
28
- panel_type="error"
29
- )
30
- )
27
+ ctx.textual.error_text(error_msg)
28
+ ctx.textual.end_step("error")
31
29
  return Error(error_msg)
32
30
 
33
31
  try:
34
32
  current_branch = ctx.git.get_current_branch()
35
33
  success_msg = msg.Steps.Branch.GET_CURRENT_BRANCH_SUCCESS.format(branch=current_branch)
36
- ctx.textual.mount(
37
- Panel(
38
- text=success_msg,
39
- panel_type="success"
40
- )
41
- )
34
+ ctx.textual.success_text(success_msg)
35
+ ctx.textual.end_step("success")
42
36
  return Success(
43
37
  success_msg,
44
38
  metadata={"pr_head_branch": current_branch}
45
39
  )
46
40
  except Exception as e:
47
41
  error_msg = msg.Steps.Branch.GET_CURRENT_BRANCH_FAILED.format(e=e)
48
- ctx.textual.mount(
49
- Panel(
50
- text=error_msg,
51
- panel_type="error"
52
- )
53
- )
42
+ ctx.textual.error_text(error_msg)
43
+ ctx.textual.end_step("error")
54
44
  return Error(error_msg, exception=e)
55
45
 
56
46
  def get_base_branch_step(ctx: WorkflowContext) -> WorkflowResult:
@@ -70,35 +60,26 @@ def get_base_branch_step(ctx: WorkflowContext) -> WorkflowResult:
70
60
  if not ctx.textual:
71
61
  return Error("Textual UI context is not available for this step.")
72
62
 
63
+ # Begin step container
64
+ ctx.textual.begin_step("Get Base Branch")
65
+
73
66
  if not ctx.git:
74
67
  error_msg = msg.Steps.Status.GIT_CLIENT_NOT_AVAILABLE
75
- ctx.textual.mount(
76
- Panel(
77
- text=error_msg,
78
- panel_type="error"
79
- )
80
- )
68
+ ctx.textual.error_text(error_msg)
69
+ ctx.textual.end_step("error")
81
70
  return Error(error_msg)
82
71
 
83
72
  try:
84
73
  base_branch = ctx.git.main_branch
85
74
  success_msg = msg.Steps.Branch.GET_BASE_BRANCH_SUCCESS.format(branch=base_branch)
86
- ctx.textual.mount(
87
- Panel(
88
- text=success_msg,
89
- panel_type="success"
90
- )
91
- )
75
+ ctx.textual.success_text(success_msg)
76
+ ctx.textual.end_step("success")
92
77
  return Success(
93
78
  success_msg,
94
79
  metadata={"pr_base_branch": base_branch}
95
80
  )
96
81
  except Exception as e:
97
82
  error_msg = msg.Steps.Branch.GET_BASE_BRANCH_FAILED.format(e=e)
98
- ctx.textual.mount(
99
- Panel(
100
- text=error_msg,
101
- panel_type="error"
102
- )
103
- )
83
+ ctx.textual.error_text(error_msg)
84
+ ctx.textual.end_step("error")
104
85
  return Error(error_msg, exception=e)
@@ -0,0 +1,66 @@
1
+ """
2
+ Checkout a Git branch.
3
+ """
4
+
5
+ from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
6
+ from titan_plugin_git.exceptions import GitError
7
+
8
+
9
+ def checkout_branch_step(ctx: WorkflowContext) -> WorkflowResult:
10
+ """
11
+ Checkout a Git branch.
12
+
13
+ Inputs (from ctx.data):
14
+ branch (str): Branch name to checkout
15
+
16
+ Returns:
17
+ Success: Branch checked out successfully
18
+ Error: Git operation failed
19
+ """
20
+ if ctx.textual:
21
+ ctx.textual.begin_step("Checkout Branch")
22
+
23
+ if not ctx.textual:
24
+ return Error("Textual UI context is not available for this step.")
25
+
26
+ if not ctx.git:
27
+ ctx.textual.error_text("Git client not available in context")
28
+ ctx.textual.end_step("error")
29
+ return Error("Git client not available in context")
30
+
31
+ try:
32
+ # Get branch from params, or use main_branch from git config
33
+ branch = ctx.get("branch")
34
+ if not branch:
35
+ branch = ctx.git.main_branch
36
+ ctx.textual.dim_text(f"Using main branch from config: {branch}")
37
+
38
+ ctx.textual.text("")
39
+ ctx.textual.dim_text(f"Checking out: {branch}")
40
+
41
+ # Checkout branch
42
+ try:
43
+ ctx.git.checkout(branch)
44
+ ctx.textual.success_text(f"✓ Checked out {branch}")
45
+ except GitError as e:
46
+ ctx.textual.text("")
47
+ ctx.textual.error_text(f"Failed to checkout {branch}: {str(e)}")
48
+ ctx.textual.end_step("error")
49
+ return Error(f"Failed to checkout: {str(e)}")
50
+
51
+ ctx.textual.text("")
52
+ ctx.textual.end_step("success")
53
+ return Success(
54
+ f"Checked out {branch}",
55
+ metadata={"branch": branch}
56
+ )
57
+
58
+ except Exception as e:
59
+ ctx.textual.text("")
60
+ ctx.textual.error_text(f"Failed to checkout branch: {str(e)}")
61
+ ctx.textual.text("")
62
+ ctx.textual.end_step("error")
63
+ return Error(f"Failed to checkout: {str(e)}")
64
+
65
+
66
+ __all__ = ["checkout_branch_step"]
@@ -3,7 +3,6 @@ from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
3
3
  from titan_cli.engine.results import Skip
4
4
  from titan_plugin_git.exceptions import GitClientError, GitCommandError
5
5
  from titan_plugin_git.messages import msg
6
- from titan_cli.ui.tui.widgets import Panel
7
6
 
8
7
 
9
8
  def create_git_commit_step(ctx: WorkflowContext) -> WorkflowResult:
@@ -18,6 +17,7 @@ def create_git_commit_step(ctx: WorkflowContext) -> WorkflowResult:
18
17
  git_status (GitStatus): The git status object, used to check if the working directory is clean.
19
18
  commit_message (str): The message for the commit.
20
19
  all_files (bool, optional): Whether to commit all modified and new files. Defaults to True.
20
+ no_verify (bool, optional): Skip pre-commit and commit-msg hooks. Defaults to False.
21
21
  commit_hash (str, optional): If present, indicates a commit was already created.
22
22
 
23
23
  Outputs (saved to ctx.data):
@@ -31,50 +31,46 @@ def create_git_commit_step(ctx: WorkflowContext) -> WorkflowResult:
31
31
  if not ctx.textual:
32
32
  return Error("Textual UI context is not available for this step.")
33
33
 
34
+ # Begin step container
35
+ ctx.textual.begin_step("Create Commit")
36
+
34
37
  # Skip if there's nothing to commit
35
38
  git_status = ctx.data.get("git_status")
36
39
  if git_status and git_status.is_clean:
37
- ctx.textual.mount(
38
- Panel(
39
- text=msg.Steps.Commit.WORKING_DIRECTORY_CLEAN,
40
- panel_type="info"
41
- )
42
- )
40
+ ctx.textual.dim_text(msg.Steps.Commit.WORKING_DIRECTORY_CLEAN)
41
+ ctx.textual.end_step("skip")
43
42
  return Skip(msg.Steps.Commit.WORKING_DIRECTORY_CLEAN)
44
43
 
45
44
  if not ctx.git:
45
+ ctx.textual.end_step("error")
46
46
  return Error(msg.Steps.Commit.GIT_CLIENT_NOT_AVAILABLE)
47
47
 
48
48
  commit_message = ctx.get('commit_message')
49
49
  if not commit_message:
50
- ctx.textual.mount(
51
- Panel(
52
- text=msg.Steps.Commit.NO_COMMIT_MESSAGE,
53
- panel_type="info"
54
- )
55
- )
50
+ ctx.textual.dim_text(msg.Steps.Commit.NO_COMMIT_MESSAGE)
51
+ ctx.textual.end_step("skip")
56
52
  return Skip(msg.Steps.Commit.NO_COMMIT_MESSAGE)
57
-
53
+
58
54
  all_files = ctx.get('all_files', True)
55
+ no_verify = ctx.get('no_verify', False)
59
56
 
60
57
  try:
61
- commit_hash = ctx.git.commit(message=commit_message, all=all_files)
58
+ commit_hash = ctx.git.commit(message=commit_message, all=all_files, no_verify=no_verify)
62
59
 
63
- # Show success panel
64
- ctx.textual.mount(
65
- Panel(
66
- text=f"Commit created: {commit_hash[:7]}",
67
- panel_type="success"
68
- )
69
- )
60
+ # Show success message
61
+ ctx.textual.success_text(f"Commit created: {commit_hash[:7]}")
70
62
 
63
+ ctx.textual.end_step("success")
71
64
  return Success(
72
65
  message=msg.Steps.Commit.COMMIT_SUCCESS.format(commit_hash=commit_hash),
73
66
  metadata={"commit_hash": commit_hash}
74
67
  )
75
68
  except GitClientError as e:
69
+ ctx.textual.end_step("error")
76
70
  return Error(msg.Steps.Commit.CLIENT_ERROR_DURING_COMMIT.format(e=e))
77
71
  except GitCommandError as e:
72
+ ctx.textual.end_step("error")
78
73
  return Error(msg.Steps.Commit.COMMAND_FAILED_DURING_COMMIT.format(e=e))
79
74
  except Exception as e:
75
+ ctx.textual.end_step("error")
80
76
  return Error(msg.Steps.Commit.UNEXPECTED_ERROR_DURING_COMMIT.format(e=e))