titan-cli 0.1.4__py3-none-any.whl → 0.1.5__py3-none-any.whl
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.
- titan_cli/core/config.py +3 -1
- titan_cli/core/workflows/__init__.py +2 -1
- titan_cli/core/workflows/project_step_source.py +48 -30
- titan_cli/core/workflows/workflow_filter_service.py +14 -8
- titan_cli/core/workflows/workflow_registry.py +12 -1
- titan_cli/core/workflows/workflow_sources.py +1 -1
- titan_cli/engine/steps/ai_assistant_step.py +42 -7
- titan_cli/engine/workflow_executor.py +6 -1
- titan_cli/ui/tui/screens/workflow_execution.py +8 -28
- titan_cli/ui/tui/textual_components.py +59 -6
- titan_cli/ui/tui/textual_workflow_executor.py +9 -1
- titan_cli/ui/tui/widgets/__init__.py +2 -0
- titan_cli/ui/tui/widgets/step_container.py +70 -0
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.5.dist-info}/METADATA +6 -3
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.5.dist-info}/RECORD +39 -37
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.5.dist-info}/WHEEL +1 -1
- titan_plugin_git/clients/git_client.py +82 -4
- titan_plugin_git/plugin.py +3 -0
- titan_plugin_git/steps/ai_commit_message_step.py +33 -28
- titan_plugin_git/steps/branch_steps.py +18 -37
- titan_plugin_git/steps/commit_step.py +18 -22
- titan_plugin_git/steps/diff_summary_step.py +182 -0
- titan_plugin_git/steps/push_step.py +27 -11
- titan_plugin_git/steps/status_step.py +15 -18
- titan_plugin_git/workflows/commit-ai.yaml +5 -0
- titan_plugin_github/agents/pr_agent.py +15 -2
- titan_plugin_github/steps/ai_pr_step.py +12 -21
- titan_plugin_github/steps/create_pr_step.py +17 -7
- titan_plugin_github/steps/github_prompt_steps.py +52 -0
- titan_plugin_github/steps/issue_steps.py +28 -14
- titan_plugin_github/steps/preview_step.py +11 -0
- titan_plugin_github/utils.py +5 -4
- titan_plugin_github/workflows/create-pr-ai.yaml +5 -0
- titan_plugin_jira/steps/ai_analyze_issue_step.py +8 -3
- titan_plugin_jira/steps/get_issue_step.py +16 -12
- titan_plugin_jira/steps/prompt_select_issue_step.py +22 -9
- titan_plugin_jira/steps/search_saved_query_step.py +21 -19
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.5.dist-info}/entry_points.txt +0 -0
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.5.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: titan-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: Modular development tools orchestrator - Streamline your workflows with AI integration and intuitive terminal UI
|
|
5
|
-
Home-page: https://github.com/masmovil/titan-cli
|
|
6
5
|
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
7
|
Keywords: cli,workflow,orchestrator,automation,devtools,ai
|
|
8
8
|
Author: finxo
|
|
9
9
|
Author-email: finxeto@gmail.com
|
|
@@ -19,6 +19,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
24
|
Requires-Dist: anthropic (>=0.75.0,<0.76.0)
|
|
23
25
|
Requires-Dist: google-auth (>=2.43.0,<3.0.0)
|
|
24
26
|
Requires-Dist: google-genai (>=1.58.0,<2.0.0)
|
|
@@ -34,6 +36,7 @@ Requires-Dist: tomli (>=2.0.0,<3.0.0)
|
|
|
34
36
|
Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
|
|
35
37
|
Requires-Dist: typer (>=0.20.0,<1.0.0)
|
|
36
38
|
Project-URL: Documentation, https://github.com/masmovil/titan-cli
|
|
39
|
+
Project-URL: Homepage, https://github.com/masmovil/titan-cli
|
|
37
40
|
Project-URL: Repository, https://github.com/masmovil/titan-cli
|
|
38
41
|
Description-Content-Type: text/markdown
|
|
39
42
|
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
titan_plugin_git/__init__.py,sha256=msIvkIXf4msXC3-q9NS2Ln556Zt9QQl-lQ688RYJnjA,50
|
|
2
2
|
titan_plugin_git/clients/__init__.py,sha256=WNAZ_kqzD_GC9NpxSjZQvkQEkcvB-tZTZPcETAK7UkE,184
|
|
3
|
-
titan_plugin_git/clients/git_client.py,sha256=
|
|
3
|
+
titan_plugin_git/clients/git_client.py,sha256=Gq9fRiYU16S9NTjzkngqOQpEimQEDjIjd__NMNgWVfw,25721
|
|
4
4
|
titan_plugin_git/exceptions.py,sha256=540oqBBvyoAcO0Kh_seuBVY-Au9jEam88rif11XA-GY,657
|
|
5
5
|
titan_plugin_git/messages.py,sha256=esQJEYOC8-IaA-TkhCwtQ0ur0RWjMF_VdfGT_CX3eqs,5940
|
|
6
6
|
titan_plugin_git/models.py,sha256=z1tUi8bh-EzAOsLRkuqWbYMJAIzZmYP_m7AhH53z254,665
|
|
7
|
-
titan_plugin_git/plugin.py,sha256=
|
|
7
|
+
titan_plugin_git/plugin.py,sha256=j1OIkDmjO9edZ69283rZ6cFNGgfJAza1bqqkKvTrSlw,4113
|
|
8
8
|
titan_plugin_git/steps/__init__.py,sha256=msIvkIXf4msXC3-q9NS2Ln556Zt9QQl-lQ688RYJnjA,50
|
|
9
|
-
titan_plugin_git/steps/ai_commit_message_step.py,sha256=
|
|
10
|
-
titan_plugin_git/steps/branch_steps.py,sha256=
|
|
11
|
-
titan_plugin_git/steps/commit_step.py,sha256=
|
|
12
|
-
titan_plugin_git/steps/
|
|
13
|
-
titan_plugin_git/steps/
|
|
9
|
+
titan_plugin_git/steps/ai_commit_message_step.py,sha256=CR1b26p5FuOCjn4UUl06BUdcfx-1oQvjy1ytq_VF-mk,7066
|
|
10
|
+
titan_plugin_git/steps/branch_steps.py,sha256=WAvs9YfoRm5SErDJN3lXrdGamql8jw_PozL2XNNydKM,3135
|
|
11
|
+
titan_plugin_git/steps/commit_step.py,sha256=QyJzMTxprDV41LjoUHsaXHrVGvBDTdq3ioB7k7d005Y,3154
|
|
12
|
+
titan_plugin_git/steps/diff_summary_step.py,sha256=O6vk9VGoOaQP9dkHLV0UB9za5J7Ut26pj0ePi1XsHfs,6463
|
|
13
|
+
titan_plugin_git/steps/push_step.py,sha256=4t_fAMxAePQJrg8_UmFNXUbbpA5A79QhvDbOFC0vzug,2963
|
|
14
|
+
titan_plugin_git/steps/status_step.py,sha256=5a7Ov2E70xNK85aNutvG34uthboRZkov2330JkVCEwA,1931
|
|
14
15
|
titan_plugin_git/workflows/__previews__/__init__.py,sha256=MXi4U95Tyi2Ku1ODkMtzMyvfQhkmrBiFxEi9IzoDVdg,40
|
|
15
16
|
titan_plugin_git/workflows/__previews__/commit_ai_preview.py,sha256=lMQt9dzVQMAZe1mFSSxAUBaSxYSLB4XMThGCO92mHVM,3744
|
|
16
|
-
titan_plugin_git/workflows/commit-ai.yaml,sha256=
|
|
17
|
+
titan_plugin_git/workflows/commit-ai.yaml,sha256=x0CAq_w2XOvnZoeWhxY5s22Qexaxx1hynQOp8pbdq_g,684
|
|
17
18
|
titan_plugin_github/__init__.py,sha256=Isw61E7k0RKHHx3eyC7m5x8JBFSY0iR6tS24Pil6oEI,240
|
|
18
19
|
titan_plugin_github/agents/__init__.py,sha256=jTGWPeICit5UBN_UhIhwPPq_Z6TLOyl1hRXiQTq0I8s,184
|
|
19
20
|
titan_plugin_github/agents/config_loader.py,sha256=3zHseeCMabK7QfWmHQuviCL7gsVUEfM8WkuXrNhBtu8,5241
|
|
20
21
|
titan_plugin_github/agents/issue_generator.py,sha256=JC6ZjR-huBb4QBfbY4eGA-7G9NLYNuGNhPmQXsqAP2I,14360
|
|
21
|
-
titan_plugin_github/agents/pr_agent.py,sha256=
|
|
22
|
+
titan_plugin_github/agents/pr_agent.py,sha256=c4q_n-oAlJzM6kaj3qLd8hsA3qMdXiw7Ip8mhsceLss,18405
|
|
22
23
|
titan_plugin_github/clients/__init__.py,sha256=n5ovE3nzbHhSiB39Jrf0_E8rfRdcGYs8tpYw7qfglnI,166
|
|
23
24
|
titan_plugin_github/clients/github_client.py,sha256=UTSncdhkNINhE01gEYYZLssouk9Dc20qEhuraphrPXo,33981
|
|
24
25
|
titan_plugin_github/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -28,16 +29,16 @@ titan_plugin_github/messages.py,sha256=OFLgetbcsvlrI8x2zvoU3yGl1Cv7FO-WyOQFYdSrq
|
|
|
28
29
|
titan_plugin_github/models.py,sha256=Oauvp-jxMl35UJio1P0zEp4liZD-EDtCNxqSRc03UcU,9400
|
|
29
30
|
titan_plugin_github/plugin.py,sha256=kJPMvRiL5l_Ax4bbHZSzVKHvTAv3uuEvxQY50APNb70,5190
|
|
30
31
|
titan_plugin_github/steps/__init__.py,sha256=3HQgbDBbWluKTm7LN6gxkE4gMYpBcaSMDkZpIFHek2c,287
|
|
31
|
-
titan_plugin_github/steps/ai_pr_step.py,sha256=
|
|
32
|
-
titan_plugin_github/steps/create_pr_step.py,sha256=
|
|
33
|
-
titan_plugin_github/steps/github_prompt_steps.py,sha256=
|
|
34
|
-
titan_plugin_github/steps/issue_steps.py,sha256=
|
|
35
|
-
titan_plugin_github/steps/preview_step.py,sha256=
|
|
36
|
-
titan_plugin_github/utils.py,sha256=
|
|
32
|
+
titan_plugin_github/steps/ai_pr_step.py,sha256=P4PugA0KAuRySmyseyE9q0lEfoBEvW6z4lF8V-Jy4fw,5663
|
|
33
|
+
titan_plugin_github/steps/create_pr_step.py,sha256=Y8bbfFlJBlhTB3d7phJykxyzufGmklkfdedGaXbQQV4,4146
|
|
34
|
+
titan_plugin_github/steps/github_prompt_steps.py,sha256=M0Ual6I-XralTkz4kCwa7z286AH_EJ2eLWaEx9SV76Y,8461
|
|
35
|
+
titan_plugin_github/steps/issue_steps.py,sha256=iIV95-RrOGvmAY8b24vxtHBiGtJkjKm8kn7RHqH6ZM8,5731
|
|
36
|
+
titan_plugin_github/steps/preview_step.py,sha256=ZJIhHtnZ8wEbYMoKlRi3xIRBRSDEk1L_NNNt_LTD0vo,1953
|
|
37
|
+
titan_plugin_github/utils.py,sha256=P22O_OoJOLKA1BowwpdsDV_ZlE_8hhRLa6SxCgfiekE,2394
|
|
37
38
|
titan_plugin_github/workflows/__previews__/__init__.py,sha256=t3X_YXZCc4XvlfCW37gdE5z_z0b8y_XCl15UjXA3dl8,38
|
|
38
39
|
titan_plugin_github/workflows/__previews__/create_pr_ai_preview.py,sha256=Q6e6KJqj9UvtNK-D5xfESlUDoFMaaMhCOuFpWCQVNkw,4515
|
|
39
40
|
titan_plugin_github/workflows/create-issue-ai.yaml,sha256=GDrZhLDNc8_DaPI3BKG4O5A4qJMP20Kkb5VeowIjSpM,818
|
|
40
|
-
titan_plugin_github/workflows/create-pr-ai.yaml,sha256=
|
|
41
|
+
titan_plugin_github/workflows/create-pr-ai.yaml,sha256=6UUv_Z_xMAjEioHr-23nC7JKxFDmXm30ZLjhE00ZEiE,1186
|
|
41
42
|
titan_plugin_jira/__init__.py,sha256=b2-ut3LZmbu9lOjOL-9X8P27AC454XbxbrpoVSR6jgk,159
|
|
42
43
|
titan_plugin_jira/agents/__init__.py,sha256=pbooB15t2HT38JUQX0zuNu4EeXhTd0G8gTdL9bNZpRQ,194
|
|
43
44
|
titan_plugin_jira/agents/config_loader.py,sha256=SfRCW5xEW7ztFziJERcjsexp6Qup_8cuNiaXgC7As_k,7024
|
|
@@ -55,10 +56,10 @@ titan_plugin_jira/formatters/markdown_formatter.py,sha256=JG-u4rslaA1PH9UQ8LEs7w
|
|
|
55
56
|
titan_plugin_jira/messages.py,sha256=WRy6zwBoXzhsZXF1sLnRWGSrjnOhKxvk6BStBRh94DU,5760
|
|
56
57
|
titan_plugin_jira/models.py,sha256=jjW-Rw7BOYzlmfwjAuVSk2Gzyozw2gyZX4LFFPtUqD4,1664
|
|
57
58
|
titan_plugin_jira/plugin.py,sha256=q1yeK5iaqwo-jdCIVq3f6cwgYGDOsMkX0hoanaJChb0,9559
|
|
58
|
-
titan_plugin_jira/steps/ai_analyze_issue_step.py,sha256=
|
|
59
|
-
titan_plugin_jira/steps/get_issue_step.py,sha256=
|
|
60
|
-
titan_plugin_jira/steps/prompt_select_issue_step.py,sha256=
|
|
61
|
-
titan_plugin_jira/steps/search_saved_query_step.py,sha256=
|
|
59
|
+
titan_plugin_jira/steps/ai_analyze_issue_step.py,sha256=QZhaTjoGZ9N7OiSmicHZPmfGVaVtuGQYWtpOWInvfKI,4032
|
|
60
|
+
titan_plugin_jira/steps/get_issue_step.py,sha256=mfPD1UUKgxBJ7m_Pw5cDlGEwmxQujwBGAl-XfrPCerA,2945
|
|
61
|
+
titan_plugin_jira/steps/prompt_select_issue_step.py,sha256=b4VeQ9ibOiNtfBucopUe5L4JgKRedJgh-5rSZWlKRds,3374
|
|
62
|
+
titan_plugin_jira/steps/search_saved_query_step.py,sha256=yV0k78SCBhk01nTxOqq6iErrYf8wCrT-wZx3eDKRO5Y,8772
|
|
62
63
|
titan_plugin_jira/utils/__init__.py,sha256=CW540Bjbw33xaoiPlawEtNE7ncr4K3Pg_sFgZO_aIwM,238
|
|
63
64
|
titan_plugin_jira/utils/issue_sorter.py,sha256=5l5K20ppb1zfhuEOyXXkmfV_zh1wTio1IUWMU2IBaRE,4012
|
|
64
65
|
titan_plugin_jira/utils/saved_queries.py,sha256=bWFI1LSs8ydCRprcJTHk6DMrq1wXN27pb5zoYYVJpRw,5111
|
|
@@ -81,7 +82,7 @@ titan_cli/cli.py,sha256=K4ZeF_PysMtfJM7K6IReQTjwFJlrDuheR05YIIhxf_4,3156
|
|
|
81
82
|
titan_cli/clients/__init__.py,sha256=gI2mQ8JeuqFa8u7XAbYlyjOph1Z5VR42NnLOjq65iD4,22
|
|
82
83
|
titan_cli/clients/gcloud_client.py,sha256=BXc7PWqcWIjF4-l2GV3w__r11MmfPtl8OW5TFw4hgr4,1902
|
|
83
84
|
titan_cli/core/__init__.py,sha256=Z5dxtLlHbAQu79NUqjlA7Ovh9toDM2B9PiVv0J-kWGQ,71
|
|
84
|
-
titan_cli/core/config.py,sha256=
|
|
85
|
+
titan_cli/core/config.py,sha256=zMgmioJKYNIUOtB0iGXMORgsT_C_NeTOmRSb4D6UI1M,11603
|
|
85
86
|
titan_cli/core/discovery.py,sha256=SPU5OcCg7mJTiA8cIR_6gHw8AdZmDVGi-nK80138HRU,1816
|
|
86
87
|
titan_cli/core/errors.py,sha256=I-xX6CCIFhno0ZUK8IRPX6RhXfj3Q7mckiCj-xintdY,2419
|
|
87
88
|
titan_cli/core/models.py,sha256=468qjAXv6KBK3ZSEg4oV3wVOfNKDFzXIkqugBfMiisI,2373
|
|
@@ -90,23 +91,23 @@ titan_cli/core/plugins/models.py,sha256=CdaktVAEcq4t41X4IfXrBgjFxly6FxdJikqqkyJt
|
|
|
90
91
|
titan_cli/core/plugins/plugin_base.py,sha256=TtHjO-g1PBS0W0vfAM-5z-0xwL0IT2Ohi3BJ0TIfTEU,2597
|
|
91
92
|
titan_cli/core/plugins/plugin_registry.py,sha256=cuoarcNnsvLv30-01uGnjWwrqy2Jaf_eJGJelzcv_k0,7753
|
|
92
93
|
titan_cli/core/secrets.py,sha256=4A4rszaie1wJh7xccetOO9rM_0jwYiIQIZVgCM0tCT4,4642
|
|
93
|
-
titan_cli/core/workflows/__init__.py,sha256=
|
|
94
|
+
titan_cli/core/workflows/__init__.py,sha256=b2jT3_wIwZtSNn0Qfc2nDXdPJyUb0Ovno5wqONuu-bU,691
|
|
94
95
|
titan_cli/core/workflows/models.py,sha256=xMXmZKMTYRawUeuAO0hG5dF6QMRCM-TWFNfoveBxJpQ,4746
|
|
95
|
-
titan_cli/core/workflows/project_step_source.py,sha256=
|
|
96
|
+
titan_cli/core/workflows/project_step_source.py,sha256=TjPMi7Q5ZCWvW-F673fO55oJZWEwBSJ37FSB1gzbR6o,3510
|
|
96
97
|
titan_cli/core/workflows/workflow_exceptions.py,sha256=vgbMHtLMbksyALLEtUL8r9Vp9G-AqLja6ZARs8JyRAo,493
|
|
97
|
-
titan_cli/core/workflows/workflow_filter_service.py,sha256=
|
|
98
|
-
titan_cli/core/workflows/workflow_registry.py,sha256=
|
|
99
|
-
titan_cli/core/workflows/workflow_sources.py,sha256=
|
|
98
|
+
titan_cli/core/workflows/workflow_filter_service.py,sha256=xqelzHQvBWo_Mm-IXvEd2VcBo-Fa55m3rdljwhxNm5Y,4588
|
|
99
|
+
titan_cli/core/workflows/workflow_registry.py,sha256=tmNeyDpy-qADz6JbvZtWHMjjlp5hi397wMMb-Ej6Z8g,17829
|
|
100
|
+
titan_cli/core/workflows/workflow_sources.py,sha256=bPrTLMN4BPcPIHdklLmKB0_5fA2pq_u7oYnhdGcH5-c,11465
|
|
100
101
|
titan_cli/engine/__init__.py,sha256=mtTPvwswXRgV-BtBc8zJUy0qNUocagstbsXKCT_DRPk,816
|
|
101
102
|
titan_cli/engine/builder.py,sha256=yjJnqanJJtr4hq0qLPRYYr_Hc28i9svnHPoyq2QUSiU,5265
|
|
102
103
|
titan_cli/engine/context.py,sha256=6oY0RTnhBwnoDDC7dX1daE2E5__AG8WM8LvX-Ca55OM,2356
|
|
103
104
|
titan_cli/engine/mock_context.py,sha256=ZcWnPJFffyLK2ghrVRcZz8hRFYE0Hpr5noh49yIqLes,4987
|
|
104
105
|
titan_cli/engine/results.py,sha256=UKYYHPngRrzPoMPeGuTZLT689_WLNDrlopcrRxiM72s,2403
|
|
105
|
-
titan_cli/engine/steps/ai_assistant_step.py,sha256=
|
|
106
|
+
titan_cli/engine/steps/ai_assistant_step.py,sha256=uyZw4Q1EzmDWmER9jJIdl9MgcidIbwl0KBTNZTEv92s,9281
|
|
106
107
|
titan_cli/engine/steps/command_step.py,sha256=FH3mTzSqS9VuZPanmnmabBUJuYB6J1frIfkqwXlcrPE,3199
|
|
107
108
|
titan_cli/engine/utils/__init__.py,sha256=fkj1-rKdKRQRktUhmYKw6VMDAmnMsILjxZGTRMMcWPY,73
|
|
108
109
|
titan_cli/engine/utils/venv.py,sha256=drsu00VuQjiaS19Bq-WT3_IcrS3utj5T16840oSHE54,1063
|
|
109
|
-
titan_cli/engine/workflow_executor.py,sha256=
|
|
110
|
+
titan_cli/engine/workflow_executor.py,sha256=lZCgKeLwYU-nu3hZKz1ijBQwCAr3NA80QA6_0DsIA34,9298
|
|
110
111
|
titan_cli/external_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
111
112
|
titan_cli/external_cli/configs.py,sha256=thW7_8sRYC3t76Wsjvw20vovNOSz1MhVukzabfdFCOo,417
|
|
112
113
|
titan_cli/external_cli/launcher.py,sha256=2t8UJmGwjGsrPk4PRSba_ZnYgEpZNrCvKUENvHxwaSw,2450
|
|
@@ -125,22 +126,23 @@ titan_cli/ui/tui/screens/main_menu.py,sha256=5Z27Ny69PPJF0q6_H5zcNPOh8vrRDr_xgYF
|
|
|
125
126
|
titan_cli/ui/tui/screens/plugin_config_wizard.py,sha256=a8QIsVLGNNCLebJ7bWlRpftZU7yPhTRcf06XOLzFB4w,20416
|
|
126
127
|
titan_cli/ui/tui/screens/plugin_management.py,sha256=2UvdxISzaiQBpm1OW1cpDrQS4ghTSC_87nlpx5Nrjhw,12356
|
|
127
128
|
titan_cli/ui/tui/screens/project_setup_wizard.py,sha256=Q2cCHlzWpiLdtGUTHnkHnXapkxZahRAVTx5MI78sszU,24210
|
|
128
|
-
titan_cli/ui/tui/screens/workflow_execution.py,sha256=
|
|
129
|
+
titan_cli/ui/tui/screens/workflow_execution.py,sha256=YgxITarGnbTYx5ghVLrKDUO1mEcoQgkv-MZ652o5Oow,22610
|
|
129
130
|
titan_cli/ui/tui/screens/workflows.py,sha256=lhpUzktq_60jEtT30OOEUnWR-NYuTIJIzi8fysP_IQc,8828
|
|
130
|
-
titan_cli/ui/tui/textual_components.py,sha256=
|
|
131
|
-
titan_cli/ui/tui/textual_workflow_executor.py,sha256=
|
|
131
|
+
titan_cli/ui/tui/textual_components.py,sha256=DQb4At1OXqooy6KrCKYgsAynvTLQGvaqSS4C-RpDlnY,19194
|
|
132
|
+
titan_cli/ui/tui/textual_workflow_executor.py,sha256=FJ4poEnsoAWBETm6VmHMCpmqXX7cCxuB_2bOm-XXjMo,17458
|
|
132
133
|
titan_cli/ui/tui/theme.py,sha256=FixTClXu7uEsqQWd_6Lc7pi7Rw7GccdK9j3YpUNY8K4,2068
|
|
133
|
-
titan_cli/ui/tui/widgets/__init__.py,sha256=
|
|
134
|
+
titan_cli/ui/tui/widgets/__init__.py,sha256=35V-c3XhxFbk5E83iwf-tQdhE49ni9VqCqKyoaV0n0E,742
|
|
134
135
|
titan_cli/ui/tui/widgets/button.py,sha256=Z7aRve1PSKpcQOsPo1db2GlKfwKddAVsU2KfhSRarKw,2143
|
|
135
136
|
titan_cli/ui/tui/widgets/header.py,sha256=ZGZuhY4B15q56DcZItXjarOrDX0ASCPdDczIOrYXwJI,3043
|
|
136
137
|
titan_cli/ui/tui/widgets/panel.py,sha256=jcLKZQXVqMGsvi7mVoTyKWijjrmXOgtC2ZuAkk2Ulgc,1818
|
|
137
138
|
titan_cli/ui/tui/widgets/status_bar.py,sha256=XiRFpoOb9DPHStaMddNIAaYmHIzg8ZkmyBzvWy4CrZg,3361
|
|
139
|
+
titan_cli/ui/tui/widgets/step_container.py,sha256=yY9bMgc2Yyr3BFnpZrSbCixAAzt4gdTQYdAKnsDnQ3s,1612
|
|
138
140
|
titan_cli/ui/tui/widgets/table.py,sha256=uWXyUda6mvflBybrrUSZh5Nvf794ege8SUe_0D24y3c,1668
|
|
139
141
|
titan_cli/ui/tui/widgets/text.py,sha256=p5h2V9w-JmPigwUFn-ky_D7gyYiix_93FJNqNmCYNHY,4057
|
|
140
142
|
titan_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
141
143
|
titan_cli/utils/autoupdate.py,sha256=Tq3SJp3iOMNONQZOw-48G6AmpKrPOyWV9RxuCA03q4M,4151
|
|
142
|
-
titan_cli-0.1.
|
|
143
|
-
titan_cli-0.1.
|
|
144
|
-
titan_cli-0.1.
|
|
145
|
-
titan_cli-0.1.
|
|
146
|
-
titan_cli-0.1.
|
|
144
|
+
titan_cli-0.1.5.dist-info/METADATA,sha256=z5RajTVvGyMVvUS5AyZznDINWmzqqqyABxNaHEY086E,4662
|
|
145
|
+
titan_cli-0.1.5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
146
|
+
titan_cli-0.1.5.dist-info/entry_points.txt,sha256=i_Zucivhsx6FcrkKDQS00MJ_Nwse-nAEkuksCcs_Ym8,186
|
|
147
|
+
titan_cli-0.1.5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
148
|
+
titan_cli-0.1.5.dist-info/RECORD,,
|
|
@@ -282,13 +282,14 @@ class GitClient:
|
|
|
282
282
|
"""
|
|
283
283
|
self._run_command(["git", "branch", branch_name, start_point])
|
|
284
284
|
|
|
285
|
-
def commit(self, message: str, all: bool = False) -> str:
|
|
285
|
+
def commit(self, message: str, all: bool = False, no_verify: bool = False) -> str:
|
|
286
286
|
"""
|
|
287
287
|
Create a commit
|
|
288
288
|
|
|
289
289
|
Args:
|
|
290
290
|
message: Commit message
|
|
291
291
|
all: Stage all modified and new files (`git add --all`)
|
|
292
|
+
no_verify: Skip pre-commit and commit-msg hooks
|
|
292
293
|
|
|
293
294
|
Returns:
|
|
294
295
|
Commit hash
|
|
@@ -298,6 +299,8 @@ class GitClient:
|
|
|
298
299
|
self._run_command(["git", "add", "--all"])
|
|
299
300
|
|
|
300
301
|
args = ["git", "commit", "-m", message]
|
|
302
|
+
if no_verify:
|
|
303
|
+
args.append("--no-verify")
|
|
301
304
|
self._run_command(args)
|
|
302
305
|
|
|
303
306
|
return self._run_command(["git", "rev-parse", "HEAD"])
|
|
@@ -347,7 +350,7 @@ class GitClient:
|
|
|
347
350
|
self._run_command(["git", "branch", delete_arg, branch])
|
|
348
351
|
return True
|
|
349
352
|
|
|
350
|
-
def push(self, remote: str = "origin", branch: Optional[str] = None, set_upstream: bool = False) -> None:
|
|
353
|
+
def push(self, remote: str = "origin", branch: Optional[str] = None, set_upstream: bool = False, tags: bool = False) -> None:
|
|
351
354
|
"""
|
|
352
355
|
Push to remote
|
|
353
356
|
|
|
@@ -355,12 +358,16 @@ class GitClient:
|
|
|
355
358
|
remote: Remote name
|
|
356
359
|
branch: Branch to push (default: current)
|
|
357
360
|
set_upstream: Set upstream tracking
|
|
361
|
+
tags: Push tags to remote (use --tags flag)
|
|
358
362
|
"""
|
|
359
363
|
args = ["git", "push"]
|
|
360
364
|
|
|
361
365
|
if set_upstream:
|
|
362
366
|
args.append("-u")
|
|
363
|
-
|
|
367
|
+
|
|
368
|
+
if tags:
|
|
369
|
+
args.append("--tags")
|
|
370
|
+
|
|
364
371
|
args.append(remote)
|
|
365
372
|
|
|
366
373
|
if branch:
|
|
@@ -769,4 +776,75 @@ class GitClient:
|
|
|
769
776
|
except GitCommandError:
|
|
770
777
|
# Command failed, likely no remote 'origin' or not a git repo
|
|
771
778
|
pass
|
|
772
|
-
return None, None
|
|
779
|
+
return None, None
|
|
780
|
+
|
|
781
|
+
def create_tag(self, tag_name: str, message: str, ref: str = "HEAD") -> None:
|
|
782
|
+
"""
|
|
783
|
+
Create an annotated tag
|
|
784
|
+
|
|
785
|
+
Args:
|
|
786
|
+
tag_name: Name of the tag
|
|
787
|
+
message: Tag annotation message
|
|
788
|
+
ref: Reference to tag (default: HEAD)
|
|
789
|
+
|
|
790
|
+
Raises:
|
|
791
|
+
GitCommandError: If tag creation fails
|
|
792
|
+
"""
|
|
793
|
+
self._run_command(["git", "tag", "-a", tag_name, "-m", message, ref])
|
|
794
|
+
|
|
795
|
+
def delete_tag(self, tag_name: str) -> None:
|
|
796
|
+
"""
|
|
797
|
+
Delete a local tag
|
|
798
|
+
|
|
799
|
+
Args:
|
|
800
|
+
tag_name: Name of the tag to delete
|
|
801
|
+
|
|
802
|
+
Raises:
|
|
803
|
+
GitCommandError: If tag deletion fails
|
|
804
|
+
"""
|
|
805
|
+
self._run_command(["git", "tag", "-d", tag_name])
|
|
806
|
+
|
|
807
|
+
def tag_exists(self, tag_name: str) -> bool:
|
|
808
|
+
"""
|
|
809
|
+
Check if a tag exists locally
|
|
810
|
+
|
|
811
|
+
Args:
|
|
812
|
+
tag_name: Name of the tag to check
|
|
813
|
+
|
|
814
|
+
Returns:
|
|
815
|
+
True if tag exists, False otherwise
|
|
816
|
+
"""
|
|
817
|
+
try:
|
|
818
|
+
self._run_command(["git", "tag", "-l", tag_name], check=False)
|
|
819
|
+
tags = self._run_command(["git", "tag", "-l", tag_name]).strip()
|
|
820
|
+
return tags == tag_name
|
|
821
|
+
except GitCommandError:
|
|
822
|
+
return False
|
|
823
|
+
|
|
824
|
+
def list_tags(self) -> List[str]:
|
|
825
|
+
"""
|
|
826
|
+
List all tags in the repository
|
|
827
|
+
|
|
828
|
+
Returns:
|
|
829
|
+
List of tag names
|
|
830
|
+
"""
|
|
831
|
+
try:
|
|
832
|
+
output = self._run_command(["git", "tag", "-l"])
|
|
833
|
+
if output.strip():
|
|
834
|
+
return [tag.strip() for tag in output.split('\n') if tag.strip()]
|
|
835
|
+
return []
|
|
836
|
+
except GitCommandError:
|
|
837
|
+
return []
|
|
838
|
+
|
|
839
|
+
def is_protected_branch(self, branch: str) -> bool:
|
|
840
|
+
"""
|
|
841
|
+
Check if a branch is protected (main, master, develop, etc.)
|
|
842
|
+
|
|
843
|
+
Args:
|
|
844
|
+
branch: Branch name to check
|
|
845
|
+
|
|
846
|
+
Returns:
|
|
847
|
+
True if branch is protected
|
|
848
|
+
"""
|
|
849
|
+
protected_branches = ["main", "master", "develop", "production", "staging"]
|
|
850
|
+
return branch.lower() in protected_branches
|
titan_plugin_git/plugin.py
CHANGED
|
@@ -100,6 +100,7 @@ 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
|
|
103
104
|
|
|
104
105
|
return {
|
|
105
106
|
"get_status": get_git_status_step,
|
|
@@ -108,6 +109,8 @@ class GitPlugin(TitanPlugin):
|
|
|
108
109
|
"get_current_branch": get_current_branch_step,
|
|
109
110
|
"get_base_branch": get_base_branch_step,
|
|
110
111
|
"ai_generate_commit_message": ai_generate_commit_message,
|
|
112
|
+
"show_uncommitted_diff_summary": show_uncommitted_diff_summary,
|
|
113
|
+
"show_branch_diff_summary": show_branch_diff_summary,
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
@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,29 +28,25 @@ 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.
|
|
35
|
-
|
|
36
|
-
text=msg.Steps.AICommitMessage.AI_NOT_CONFIGURED,
|
|
37
|
-
panel_type="info"
|
|
38
|
-
)
|
|
39
|
-
)
|
|
36
|
+
ctx.textual.text(msg.Steps.AICommitMessage.AI_NOT_CONFIGURED, markup="dim")
|
|
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.
|
|
50
|
-
|
|
51
|
-
text=msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT,
|
|
52
|
-
panel_type="info"
|
|
53
|
-
)
|
|
54
|
-
)
|
|
48
|
+
ctx.textual.text(msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT, markup="dim")
|
|
49
|
+
ctx.textual.end_step("skip")
|
|
55
50
|
return Skip(msg.Steps.AICommitMessage.NO_CHANGES_TO_COMMIT)
|
|
56
51
|
|
|
57
52
|
try:
|
|
@@ -62,6 +57,7 @@ def ai_generate_commit_message(ctx: WorkflowContext) -> WorkflowResult:
|
|
|
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):
|
|
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):
|
|
97
|
-
- fix(api):
|
|
98
|
-
- refactor(ui):
|
|
99
|
-
- refactor(workflows):
|
|
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,6 +111,18 @@ 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
128
|
ctx.textual.text(msg.Steps.AICommitMessage.GENERATED_MESSAGE_TITLE, markup="bold")
|
|
@@ -136,25 +144,21 @@ 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}
|
|
@@ -164,6 +168,7 @@ Return ONLY the single-line commit message, absolutely nothing else."""
|
|
|
164
168
|
ctx.textual.text(msg.Steps.AICommitMessage.GENERATION_FAILED.format(e=e), markup="yellow")
|
|
165
169
|
ctx.textual.text(msg.Steps.AICommitMessage.FALLBACK_TO_MANUAL, markup="dim")
|
|
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.
|
|
26
|
-
|
|
27
|
-
text=error_msg,
|
|
28
|
-
panel_type="error"
|
|
29
|
-
)
|
|
30
|
-
)
|
|
27
|
+
ctx.textual.text(error_msg, markup="red")
|
|
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.
|
|
37
|
-
|
|
38
|
-
text=success_msg,
|
|
39
|
-
panel_type="success"
|
|
40
|
-
)
|
|
41
|
-
)
|
|
34
|
+
ctx.textual.text(success_msg, markup="green")
|
|
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.
|
|
49
|
-
|
|
50
|
-
text=error_msg,
|
|
51
|
-
panel_type="error"
|
|
52
|
-
)
|
|
53
|
-
)
|
|
42
|
+
ctx.textual.text(error_msg, markup="red")
|
|
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.
|
|
76
|
-
|
|
77
|
-
text=error_msg,
|
|
78
|
-
panel_type="error"
|
|
79
|
-
)
|
|
80
|
-
)
|
|
68
|
+
ctx.textual.text(error_msg, markup="red")
|
|
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.
|
|
87
|
-
|
|
88
|
-
text=success_msg,
|
|
89
|
-
panel_type="success"
|
|
90
|
-
)
|
|
91
|
-
)
|
|
75
|
+
ctx.textual.text(success_msg, markup="green")
|
|
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.
|
|
99
|
-
|
|
100
|
-
text=error_msg,
|
|
101
|
-
panel_type="error"
|
|
102
|
-
)
|
|
103
|
-
)
|
|
83
|
+
ctx.textual.text(error_msg, markup="red")
|
|
84
|
+
ctx.textual.end_step("error")
|
|
104
85
|
return Error(error_msg, exception=e)
|
|
@@ -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.
|
|
38
|
-
|
|
39
|
-
text=msg.Steps.Commit.WORKING_DIRECTORY_CLEAN,
|
|
40
|
-
panel_type="info"
|
|
41
|
-
)
|
|
42
|
-
)
|
|
40
|
+
ctx.textual.text(msg.Steps.Commit.WORKING_DIRECTORY_CLEAN, markup="dim")
|
|
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.
|
|
51
|
-
|
|
52
|
-
text=msg.Steps.Commit.NO_COMMIT_MESSAGE,
|
|
53
|
-
panel_type="info"
|
|
54
|
-
)
|
|
55
|
-
)
|
|
50
|
+
ctx.textual.text(msg.Steps.Commit.NO_COMMIT_MESSAGE, markup="dim")
|
|
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
|
|
64
|
-
ctx.textual.
|
|
65
|
-
Panel(
|
|
66
|
-
text=f"Commit created: {commit_hash[:7]}",
|
|
67
|
-
panel_type="success"
|
|
68
|
-
)
|
|
69
|
-
)
|
|
60
|
+
# Show success message
|
|
61
|
+
ctx.textual.text(f"Commit created: {commit_hash[:7]}", markup="green")
|
|
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))
|