titan-cli 0.1.3__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.
Files changed (42) hide show
  1. titan_cli/core/config.py +3 -1
  2. titan_cli/core/plugins/models.py +35 -7
  3. titan_cli/core/plugins/plugin_registry.py +11 -2
  4. titan_cli/core/workflows/__init__.py +2 -1
  5. titan_cli/core/workflows/project_step_source.py +48 -30
  6. titan_cli/core/workflows/workflow_filter_service.py +14 -8
  7. titan_cli/core/workflows/workflow_registry.py +12 -1
  8. titan_cli/core/workflows/workflow_sources.py +1 -1
  9. titan_cli/engine/steps/ai_assistant_step.py +42 -7
  10. titan_cli/engine/workflow_executor.py +6 -1
  11. titan_cli/ui/tui/screens/plugin_config_wizard.py +40 -9
  12. titan_cli/ui/tui/screens/workflow_execution.py +8 -28
  13. titan_cli/ui/tui/textual_components.py +59 -6
  14. titan_cli/ui/tui/textual_workflow_executor.py +9 -1
  15. titan_cli/ui/tui/widgets/__init__.py +2 -0
  16. titan_cli/ui/tui/widgets/step_container.py +70 -0
  17. {titan_cli-0.1.3.dist-info → titan_cli-0.1.5.dist-info}/METADATA +6 -3
  18. {titan_cli-0.1.3.dist-info → titan_cli-0.1.5.dist-info}/RECORD +42 -40
  19. {titan_cli-0.1.3.dist-info → titan_cli-0.1.5.dist-info}/WHEEL +1 -1
  20. titan_plugin_git/clients/git_client.py +82 -4
  21. titan_plugin_git/plugin.py +3 -0
  22. titan_plugin_git/steps/ai_commit_message_step.py +33 -28
  23. titan_plugin_git/steps/branch_steps.py +18 -37
  24. titan_plugin_git/steps/commit_step.py +18 -22
  25. titan_plugin_git/steps/diff_summary_step.py +182 -0
  26. titan_plugin_git/steps/push_step.py +27 -11
  27. titan_plugin_git/steps/status_step.py +15 -18
  28. titan_plugin_git/workflows/commit-ai.yaml +5 -0
  29. titan_plugin_github/agents/pr_agent.py +15 -2
  30. titan_plugin_github/steps/ai_pr_step.py +12 -21
  31. titan_plugin_github/steps/create_pr_step.py +17 -7
  32. titan_plugin_github/steps/github_prompt_steps.py +52 -0
  33. titan_plugin_github/steps/issue_steps.py +28 -14
  34. titan_plugin_github/steps/preview_step.py +11 -0
  35. titan_plugin_github/utils.py +5 -4
  36. titan_plugin_github/workflows/create-pr-ai.yaml +5 -0
  37. titan_plugin_jira/steps/ai_analyze_issue_step.py +8 -3
  38. titan_plugin_jira/steps/get_issue_step.py +16 -12
  39. titan_plugin_jira/steps/prompt_select_issue_step.py +22 -9
  40. titan_plugin_jira/steps/search_saved_query_step.py +21 -19
  41. {titan_cli-0.1.3.dist-info → titan_cli-0.1.5.dist-info}/entry_points.txt +0 -0
  42. {titan_cli-0.1.3.dist-info → titan_cli-0.1.5.dist-info/licenses}/LICENSE +0 -0
@@ -209,6 +209,46 @@ class TextualComponents:
209
209
  """
210
210
  self.app = app
211
211
  self.output_widget = output_widget
212
+ self._active_step_container = None
213
+
214
+ def begin_step(self, step_name: str) -> None:
215
+ """
216
+ Begin a new step by creating a StepContainer.
217
+
218
+ Args:
219
+ step_name: Name of the step
220
+ """
221
+ from titan_cli.ui.tui.widgets import StepContainer
222
+
223
+ def _create_container():
224
+ container = StepContainer(step_name=step_name)
225
+ self.output_widget.mount(container)
226
+ self._active_step_container = container
227
+
228
+ try:
229
+ self.app.call_from_thread(_create_container)
230
+ except Exception:
231
+ pass
232
+
233
+ def end_step(self, result_type: str) -> None:
234
+ """
235
+ End the current step by updating its container color.
236
+
237
+ Args:
238
+ result_type: One of 'success', 'skip', 'error'
239
+ """
240
+ if not self._active_step_container:
241
+ return
242
+
243
+ def _update_container():
244
+ if self._active_step_container:
245
+ self._active_step_container.set_result(result_type)
246
+ self._active_step_container = None
247
+
248
+ try:
249
+ self.app.call_from_thread(_update_container)
250
+ except Exception:
251
+ pass
212
252
 
213
253
  def mount(self, widget: Widget) -> None:
214
254
  """
@@ -222,7 +262,9 @@ class TextualComponents:
222
262
  ctx.textual.mount(Panel("Success!", panel_type="success"))
223
263
  """
224
264
  def _mount():
225
- self.output_widget.mount(widget)
265
+ # Mount to active step container if it exists, otherwise to output widget
266
+ target = self._active_step_container if self._active_step_container else self.output_widget
267
+ target.mount(widget)
226
268
 
227
269
  # call_from_thread already blocks until the function completes
228
270
  try:
@@ -244,10 +286,20 @@ class TextualComponents:
244
286
  ctx.textual.text("Done!")
245
287
  """
246
288
  def _append():
247
- if markup:
248
- self.output_widget.append_output(f"[{markup}]{text}[/{markup}]")
289
+ # If there's an active step container, append to it; otherwise to output widget
290
+ if self._active_step_container:
291
+ from textual.widgets import Static
292
+ if markup:
293
+ widget = Static(f"[{markup}]{text}[/{markup}]")
294
+ else:
295
+ widget = Static(text)
296
+ widget.styles.height = "auto"
297
+ self._active_step_container.mount(widget)
249
298
  else:
250
- self.output_widget.append_output(text)
299
+ if markup:
300
+ self.output_widget.append_output(f"[{markup}]{text}[/{markup}]")
301
+ else:
302
+ self.output_widget.append_output(text)
251
303
 
252
304
  # call_from_thread already blocks until the function completes
253
305
  try:
@@ -276,8 +328,9 @@ class TextualComponents:
276
328
  md_widget.styles.margin = (0, 0, 1, 0)
277
329
 
278
330
  def _mount():
279
- # Mount markdown to output
280
- self.output_widget.mount(md_widget)
331
+ # Mount to active step container if it exists, otherwise to output widget
332
+ target = self._active_step_container if self._active_step_container else self.output_widget
333
+ target.mount(md_widget)
281
334
  # Trigger autoscroll after mounting
282
335
  self.output_widget._scroll_to_end()
283
336
 
@@ -341,6 +341,14 @@ class TextualWorkflowExecutor:
341
341
  f"Project step '{step_func_name}' not found in '.titan/steps/'.",
342
342
  WorkflowExecutionError(f"Project step '{step_func_name}' not found")
343
343
  )
344
+ elif plugin_name == "user":
345
+ # Handle virtual 'user' plugin for user-specific steps
346
+ step_func = self._workflow_registry.get_user_step(step_func_name)
347
+ if not step_func:
348
+ return Error(
349
+ f"User step '{step_func_name}' not found in '~/.titan/steps/'.",
350
+ WorkflowExecutionError(f"User step '{step_func_name}' not found")
351
+ )
344
352
  elif plugin_name == "core":
345
353
  # Handle virtual 'core' plugin for built-in core steps
346
354
  step_func = self.CORE_STEPS.get(step_func_name)
@@ -382,7 +390,7 @@ class TextualWorkflowExecutor:
382
390
  # Plugin and project steps receive only ctx (params are in ctx.data)
383
391
  return step_func(ctx)
384
392
  except Exception as e:
385
- error_source = f"plugin '{plugin_name}'" if plugin_name not in ("project", "core") else f"{plugin_name} step"
393
+ error_source = f"plugin '{plugin_name}'" if plugin_name not in ("project", "user", "core") else f"{plugin_name} step"
386
394
  return Error(f"Error executing step '{step_func_name}' from {error_source}: {e}", e)
387
395
 
388
396
  def _execute_command_step(self, step_config: WorkflowStepModel, ctx: WorkflowContext) -> WorkflowResult:
@@ -8,6 +8,7 @@ from .header import HeaderWidget
8
8
  from .panel import Panel
9
9
  from .table import Table
10
10
  from .button import Button
11
+ from .step_container import StepContainer
11
12
  from .text import (
12
13
  Text,
13
14
  DimText,
@@ -27,6 +28,7 @@ __all__ = [
27
28
  "Panel",
28
29
  "Table",
29
30
  "Button",
31
+ "StepContainer",
30
32
  "Text",
31
33
  "DimText",
32
34
  "BoldText",
@@ -0,0 +1,70 @@
1
+ """
2
+ Step Container Widget
3
+
4
+ A container that groups all output from a workflow step, with a titled border
5
+ that changes color based on the step result (success, skip, error).
6
+ """
7
+ from textual.containers import VerticalScroll
8
+
9
+
10
+ class StepContainer(VerticalScroll):
11
+ """
12
+ Container for step output with colored border and title.
13
+
14
+ The border color changes based on step result:
15
+ - Running: cyan (default)
16
+ - Success: green
17
+ - Skip: yellow
18
+ - Error: red
19
+ """
20
+
21
+ DEFAULT_CSS = """
22
+ StepContainer {
23
+ width: 100%;
24
+ height: auto;
25
+ border: round $accent;
26
+ padding: 1 2;
27
+ margin: 1 0;
28
+ }
29
+
30
+ StepContainer.running {
31
+ border: round $accent;
32
+ }
33
+
34
+ StepContainer.success {
35
+ border: round $success;
36
+ }
37
+
38
+ StepContainer.skip {
39
+ border: round $warning;
40
+ }
41
+
42
+ StepContainer.error {
43
+ border: round $error;
44
+ }
45
+
46
+ StepContainer > Static {
47
+ color: initial;
48
+ }
49
+ """
50
+
51
+ def __init__(self, step_name: str, **kwargs):
52
+ super().__init__(**kwargs)
53
+ self.border_title = step_name
54
+ self.add_class("running")
55
+
56
+ def set_result(self, result_type: str):
57
+ """
58
+ Update the border color based on step result.
59
+
60
+ Args:
61
+ result_type: One of 'success', 'skip', 'error'
62
+ """
63
+ # Remove all result classes
64
+ self.remove_class("running", "success", "skip", "error")
65
+
66
+ # Add the new result class
67
+ if result_type in ["success", "skip", "error"]:
68
+ self.add_class(result_type)
69
+ else:
70
+ self.add_class("running")
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: titan-cli
3
- Version: 0.1.3
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=Z1vBcKEfvdah9FyMyUqkg3_4zCTI2VSpbKps50t_EjM,23425
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=cYQO9HkSXF4qEuOiD4YEmWgRXjxZsL12ocLHS8EO1hg,3870
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=gC7AYZNvFc1ZiMYOMSJ3UoT_jwFFhSWxTYF2db9sOFk,6395
10
- titan_plugin_git/steps/branch_steps.py,sha256=TwZ7OyrQhy4kfInjSnXWFK9NlHFCh9laxtHT070Bg_E,3320
11
- titan_plugin_git/steps/commit_step.py,sha256=nHHXdpfuWgYhJqFEKkGFRRszEQnv40dzMoHwKr3ceK0,2966
12
- titan_plugin_git/steps/push_step.py,sha256=3GRHF0Y8EjDva5EB6l9AA_VwRtOu8XXI0hZRDo7LwsM,2372
13
- titan_plugin_git/steps/status_step.py,sha256=z_M_MBpkYnc9-X2U_EbDZtrKGeoEM_tmrhyJzYIU8aY,1920
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=ZVhB9CHtzJEa13e8twNDB_b9tzDJDlflpYqoz2v6E7g,573
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=Zp13p29F9r-DYlqSFrEVp6W66jaG6pJ0JyDexPK7oY4,17787
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=v2-GM3u9xcWAREiMXWKVh3pRL1fDurIpAN_A0Vjmuiw,5752
32
- titan_plugin_github/steps/create_pr_step.py,sha256=W5HTYhdZ-HCcUyCINS2moUpgdIwJwBKrHObYoK8oMEo,3326
33
- titan_plugin_github/steps/github_prompt_steps.py,sha256=JOPR9f43oKI1r-8mLBvjT7mwcIEEb7rg60LwpqJM-Kg,6154
34
- titan_plugin_github/steps/issue_steps.py,sha256=HrXo_RGCalys4FBO5i90RGkgGPuN_jt7iMOtqmVimSE,4786
35
- titan_plugin_github/steps/preview_step.py,sha256=TT7giO6H1hMcWxvTqJVEJiXBiZ7vNxzeekt1CErg8Ik,1403
36
- titan_plugin_github/utils.py,sha256=ZMaYLABD6rvHRkoyDz72WGE-aIKRnyKaZgpw2FHxLK0,2325
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=VW08CxgmPZfvgfWE9-6RFcGDjnJwUUpOHVWv4wg4mVU,1066
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=VDYwHQno_bheKjBeXfF4p6C-o_d0ThOsLmCR1Lj9s5Q,3916
59
- titan_plugin_jira/steps/get_issue_step.py,sha256=Q5KUlU7b7QqPBRjdZha3szUNlnJcrHuwVqNEeyXY11g,2790
60
- titan_plugin_jira/steps/prompt_select_issue_step.py,sha256=fwCSAy8JChHHRHiKb8U-ilVtpL2phOsm3UftGtArZnI,2588
61
- titan_plugin_jira/steps/search_saved_query_step.py,sha256=o6uM1fqY9-o4vZdXxopmOFgz_RoW933E91VjtKPZU3M,8623
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,32 +82,32 @@ 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=gI_32djLbKSV2QJ4FbRx3yXEgoaACbT_FTE3SFOd7HI,11496
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
88
89
  titan_cli/core/plugins/available.py,sha256=__ejonPeOqw2Zy9gIRB-CHeFO9SvTFclG095afgnIz4,1163
89
- titan_cli/core/plugins/models.py,sha256=3TFFKLkoIu6wzeFbGh2vGAU-Hr6Bvt9lroY7ZghUugE,3525
90
+ titan_cli/core/plugins/models.py,sha256=CdaktVAEcq4t41X4IfXrBgjFxly6FxdJikqqkyJtTtM,4012
90
91
  titan_cli/core/plugins/plugin_base.py,sha256=TtHjO-g1PBS0W0vfAM-5z-0xwL0IT2Ohi3BJ0TIfTEU,2597
91
- titan_cli/core/plugins/plugin_registry.py,sha256=TcCZCVHW9sL6vlCgv2SnfRFNa0D-5M3urg74yvRNWjQ,7487
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=CvpDKR4Co5Vzbb5aFTt5r6vyoqjGexj6Mt1_x0Z4iwg,653
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=K03MSe-417e2gIL8ygdE3TCPMWBCBA-mL4W57RZG1-Y,3009
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=HucZSXka15_2Ns2fJdm85NRT-rJwISuyYcyJQq-Sf9s,4346
98
- titan_cli/core/workflows/workflow_registry.py,sha256=HZeP5tR5_r9smjC2e5xzEr_3Vr6nMq054ctUsgO0z8I,17324
99
- titan_cli/core/workflows/workflow_sources.py,sha256=aD0xuBKvACmyFSu7x6_ZJ2u_FbVZQ8mBFKGVihAHW1w,11457
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=513hG1zD6kzOJQg6AG_IXE0d_iURO9tBkIxZhoelOVI,7281
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=A-TSz60HO121J2JfYBE8J0JuJEdRpJCsuh1R2UowRQk,8918
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
@@ -122,25 +123,26 @@ titan_cli/ui/tui/screens/base.py,sha256=ufVYBkVzetQxsPQTobN0HgUGdSB0ARfRtvo-02DS
122
123
  titan_cli/ui/tui/screens/cli_launcher.py,sha256=C9XWe1jUr0-Q_PGwchL6bVu9N2g-QLa83jJZGl7ucHI,4385
123
124
  titan_cli/ui/tui/screens/global_setup_wizard.py,sha256=gbkGMGXWJdfrIWvRvT5DDFZKKRWmf7nlGUuUkTtDiKI,12115
124
125
  titan_cli/ui/tui/screens/main_menu.py,sha256=5Z27Ny69PPJF0q6_H5zcNPOh8vrRDr_xgYFSmUbn244,4493
125
- titan_cli/ui/tui/screens/plugin_config_wizard.py,sha256=yxwfBuZk3spn6fT3twoc9ZTokL0kDOvvMnOgKyMzJVQ,18882
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=JHZlKtqpYRosVP4TVSGzT1L8UxlCoCNorBFVXYPyzik,23526
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=5OplwbSuSdS5Q6Zwfs-wxp-rETvmpLt5IlVCYdoCYqg,17215
131
- titan_cli/ui/tui/textual_workflow_executor.py,sha256=bVQx2TLkVlXfNZZgb9mmH4EZx5WPj3Djr0bMWx1lW68,17020
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=NLJMQOyI0IPFLNZ62wrJBulKgOG8bK0J2utehgSQIxs,679
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.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
143
- titan_cli-0.1.3.dist-info/METADATA,sha256=vKcX5Pq9CGckQCutN1nHA8C9coxz-G3-TurBekhV1VU,4526
144
- titan_cli-0.1.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
145
- titan_cli-0.1.3.dist-info/entry_points.txt,sha256=i_Zucivhsx6FcrkKDQS00MJ_Nwse-nAEkuksCcs_Ym8,186
146
- titan_cli-0.1.3.dist-info/RECORD,,
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -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
@@ -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