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.
- titan_cli/core/config.py +3 -1
- titan_cli/core/plugins/models.py +35 -7
- titan_cli/core/plugins/plugin_registry.py +11 -2
- 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/plugin_config_wizard.py +40 -9
- 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.3.dist-info → titan_cli-0.1.5.dist-info}/METADATA +6 -3
- {titan_cli-0.1.3.dist-info → titan_cli-0.1.5.dist-info}/RECORD +42 -40
- {titan_cli-0.1.3.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.3.dist-info → titan_cli-0.1.5.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
|
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
|
-
|
|
248
|
-
|
|
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
|
-
|
|
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
|
|
280
|
-
self.output_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
|
+
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,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=
|
|
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=
|
|
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=
|
|
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
|
|
@@ -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=
|
|
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
|