titan-cli 0.1.4__py3-none-any.whl → 0.1.6__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 +95 -32
- titan_cli/core/workflows/workflow_filter_service.py +16 -8
- titan_cli/core/workflows/workflow_registry.py +12 -1
- titan_cli/core/workflows/workflow_sources.py +1 -1
- titan_cli/engine/__init__.py +5 -1
- titan_cli/engine/results.py +31 -1
- titan_cli/engine/steps/ai_assistant_step.py +47 -12
- titan_cli/engine/workflow_executor.py +13 -3
- titan_cli/ui/tui/screens/plugin_config_wizard.py +16 -0
- titan_cli/ui/tui/screens/workflow_execution.py +28 -50
- titan_cli/ui/tui/screens/workflows.py +8 -4
- titan_cli/ui/tui/textual_components.py +342 -185
- titan_cli/ui/tui/textual_workflow_executor.py +39 -3
- titan_cli/ui/tui/theme.py +34 -5
- titan_cli/ui/tui/widgets/__init__.py +17 -0
- titan_cli/ui/tui/widgets/multiline_input.py +32 -0
- titan_cli/ui/tui/widgets/prompt_choice.py +138 -0
- titan_cli/ui/tui/widgets/prompt_input.py +74 -0
- titan_cli/ui/tui/widgets/prompt_selection_list.py +150 -0
- titan_cli/ui/tui/widgets/prompt_textarea.py +87 -0
- titan_cli/ui/tui/widgets/step_container.py +70 -0
- titan_cli/ui/tui/widgets/styled_option_list.py +107 -0
- titan_cli/ui/tui/widgets/text.py +51 -130
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.6.dist-info}/METADATA +3 -5
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.6.dist-info}/RECORD +61 -46
- titan_plugin_git/clients/git_client.py +140 -5
- titan_plugin_git/plugin.py +13 -0
- titan_plugin_git/steps/ai_commit_message_step.py +39 -34
- titan_plugin_git/steps/branch_steps.py +18 -37
- titan_plugin_git/steps/checkout_step.py +66 -0
- titan_plugin_git/steps/commit_step.py +18 -22
- titan_plugin_git/steps/create_branch_step.py +131 -0
- titan_plugin_git/steps/diff_summary_step.py +180 -0
- titan_plugin_git/steps/pull_step.py +70 -0
- titan_plugin_git/steps/push_step.py +27 -11
- titan_plugin_git/steps/restore_original_branch_step.py +97 -0
- titan_plugin_git/steps/save_current_branch_step.py +82 -0
- titan_plugin_git/steps/status_step.py +32 -25
- titan_plugin_git/workflows/commit-ai.yaml +9 -3
- titan_plugin_github/agents/pr_agent.py +15 -2
- titan_plugin_github/steps/ai_pr_step.py +99 -40
- titan_plugin_github/steps/create_pr_step.py +18 -8
- titan_plugin_github/steps/github_prompt_steps.py +53 -1
- titan_plugin_github/steps/issue_steps.py +31 -18
- titan_plugin_github/steps/preview_step.py +15 -4
- titan_plugin_github/utils.py +5 -4
- titan_plugin_github/workflows/create-pr-ai.yaml +6 -11
- titan_plugin_jira/messages.py +12 -0
- titan_plugin_jira/plugin.py +4 -0
- titan_plugin_jira/steps/ai_analyze_issue_step.py +12 -7
- titan_plugin_jira/steps/get_issue_step.py +17 -13
- titan_plugin_jira/steps/list_versions_step.py +133 -0
- titan_plugin_jira/steps/prompt_select_issue_step.py +20 -8
- titan_plugin_jira/steps/search_jql_step.py +191 -0
- titan_plugin_jira/steps/search_saved_query_step.py +26 -24
- titan_plugin_jira/utils/__init__.py +1 -1
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.6.dist-info}/LICENSE +0 -0
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.6.dist-info}/WHEEL +0 -0
- {titan_cli-0.1.4.dist-info → titan_cli-0.1.6.dist-info}/entry_points.txt +0 -0
|
@@ -146,16 +146,16 @@ class WorkflowExecutionScreen(BaseScreen):
|
|
|
146
146
|
thread=True
|
|
147
147
|
)
|
|
148
148
|
|
|
149
|
-
except (WorkflowNotFoundError, WorkflowExecutionError):
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
149
|
+
except (WorkflowNotFoundError, WorkflowExecutionError) as e:
|
|
150
|
+
self._output(f"[red]{Icons.ERROR} Error loading workflow: {e}[/red]")
|
|
151
|
+
self._output("[dim]Press ESC or Q to return[/dim]")
|
|
152
|
+
except Exception as e:
|
|
153
|
+
import traceback
|
|
154
|
+
error_details = traceback.format_exc()
|
|
155
|
+
self._output(f"[red]{Icons.ERROR} Unexpected error loading workflow:[/red]")
|
|
156
|
+
self._output(f"[red]{type(e).__name__}: {e}[/red]")
|
|
157
|
+
self._output(f"[dim]{error_details}[/dim]")
|
|
158
|
+
self._output("[dim]Press ESC or Q to return[/dim]")
|
|
159
159
|
|
|
160
160
|
def _execute_workflow(self) -> None:
|
|
161
161
|
"""Execute the workflow in a background thread."""
|
|
@@ -493,18 +493,19 @@ class WorkflowExecutionContent(Widget):
|
|
|
493
493
|
|
|
494
494
|
def on_descendant_mount(self, event) -> None:
|
|
495
495
|
"""Auto-scroll when any widget is mounted as a descendant."""
|
|
496
|
-
|
|
497
|
-
from titan_cli.ui.tui.textual_components import PromptInput
|
|
496
|
+
from titan_cli.ui.tui.widgets import PromptInput, StepContainer
|
|
498
497
|
|
|
499
|
-
#
|
|
500
|
-
#
|
|
501
|
-
if
|
|
498
|
+
# Auto-scroll for StepContainers (new steps being added)
|
|
499
|
+
# StepContainer itself triggers scroll via begin_step(), but this is a safety net
|
|
500
|
+
if isinstance(event.widget, StepContainer):
|
|
501
|
+
self._scroll_to_end()
|
|
502
|
+
# Also scroll for other widgets, but skip PromptInput (it handles its own scroll)
|
|
503
|
+
elif not isinstance(event.widget, PromptInput):
|
|
502
504
|
self._scroll_to_end()
|
|
503
505
|
|
|
504
506
|
def handle_event(self, message) -> None:
|
|
505
507
|
"""Handle workflow events generically."""
|
|
506
508
|
from titan_cli.ui.tui.textual_workflow_executor import TextualWorkflowExecutor
|
|
507
|
-
from titan_cli.ui.tui.widgets import Panel
|
|
508
509
|
|
|
509
510
|
if isinstance(message, TextualWorkflowExecutor.WorkflowStarted):
|
|
510
511
|
# Track nested workflow depth
|
|
@@ -513,44 +514,21 @@ class WorkflowExecutionContent(Widget):
|
|
|
513
514
|
self.append_output(f"\n[bold cyan]🚀 Starting workflow: {message.workflow_name}[/bold cyan]")
|
|
514
515
|
|
|
515
516
|
elif isinstance(message, TextualWorkflowExecutor.StepStarted):
|
|
516
|
-
#
|
|
517
|
-
|
|
518
|
-
# Nested workflow: show with indentation, no step number
|
|
519
|
-
indent = " " * self._workflow_depth
|
|
520
|
-
self.append_output(f"[cyan]{indent}→ Step {message.step_index}: {message.step_name}[/cyan]")
|
|
521
|
-
else:
|
|
522
|
-
# Top-level workflow: show with step number
|
|
523
|
-
self.append_output(f"[cyan]→ Step {message.step_index}: {message.step_name}[/cyan]")
|
|
517
|
+
# StepContainer now handles step titles, so we don't display anything here
|
|
518
|
+
pass
|
|
524
519
|
|
|
525
520
|
elif isinstance(message, TextualWorkflowExecutor.StepCompleted):
|
|
526
|
-
#
|
|
527
|
-
|
|
528
|
-
indent = " " * self._workflow_depth
|
|
529
|
-
self.append_output(f"[green]{indent}{Icons.SUCCESS} Completed: {message.step_name}[/green]\n")
|
|
530
|
-
else:
|
|
531
|
-
self.append_output(f"[green]{Icons.SUCCESS} Completed: {message.step_name}[/green]\n")
|
|
521
|
+
# StepContainer now handles step completion (green border), so we don't display anything here
|
|
522
|
+
pass
|
|
532
523
|
|
|
533
524
|
elif isinstance(message, TextualWorkflowExecutor.StepFailed):
|
|
534
|
-
#
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
self._scroll_to_end()
|
|
538
|
-
except Exception:
|
|
539
|
-
pass
|
|
540
|
-
|
|
541
|
-
if message.on_error == "continue":
|
|
542
|
-
indent = " " * self._workflow_depth if self._workflow_depth > 0 else ""
|
|
543
|
-
self.append_output(f"[yellow]{indent} {Icons.WARNING} Continuing despite error[/yellow]\n")
|
|
544
|
-
else:
|
|
545
|
-
self.append_output("")
|
|
525
|
+
# Steps handle their own error display via ctx.textual
|
|
526
|
+
# Executor only coordinates execution, no visual output needed
|
|
527
|
+
pass
|
|
546
528
|
|
|
547
529
|
elif isinstance(message, TextualWorkflowExecutor.StepSkipped):
|
|
548
|
-
#
|
|
549
|
-
|
|
550
|
-
self.mount(Panel(f"Skipped: {message.step_name}", panel_type="warning"))
|
|
551
|
-
self._scroll_to_end()
|
|
552
|
-
except Exception:
|
|
553
|
-
pass
|
|
530
|
+
# StepContainer now handles step skips (yellow border), so we don't display the panel
|
|
531
|
+
pass
|
|
554
532
|
|
|
555
533
|
elif isinstance(message, TextualWorkflowExecutor.WorkflowCompleted):
|
|
556
534
|
# Track nested workflow depth
|
|
@@ -586,7 +564,7 @@ class WorkflowExecutionContent(Widget):
|
|
|
586
564
|
pass
|
|
587
565
|
|
|
588
566
|
elif isinstance(message, TextualWorkflowExecutor.WorkflowFailed):
|
|
589
|
-
#
|
|
567
|
+
# Steps handle their own error display via ctx.textual
|
|
568
|
+
# Just show a simple notification without duplicating the error message
|
|
590
569
|
self.app.notify(f"❌ Workflow failed at step: {message.step_name}", severity="error", timeout=10)
|
|
591
|
-
self.append_output(f"[red]{message.error_message}[/red]")
|
|
592
570
|
|
|
@@ -16,6 +16,7 @@ from titan_cli.core.workflows.workflow_filter_service import WorkflowFilterServi
|
|
|
16
16
|
from titan_cli.core.workflows.workflow_sources import WorkflowInfo
|
|
17
17
|
from titan_cli.ui.tui.screens.workflow_execution import WorkflowExecutionScreen
|
|
18
18
|
from titan_cli.ui.tui.icons import Icons
|
|
19
|
+
from titan_cli.ui.tui.widgets import StyledOption
|
|
19
20
|
from .base import BaseScreen
|
|
20
21
|
|
|
21
22
|
class WorkflowsScreen(BaseScreen):
|
|
@@ -170,11 +171,14 @@ class WorkflowsScreen(BaseScreen):
|
|
|
170
171
|
workflows_to_show = workflows
|
|
171
172
|
|
|
172
173
|
for wf_info in workflows_to_show:
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
styled_opt = StyledOption(
|
|
175
|
+
id=wf_info.name,
|
|
176
|
+
title=wf_info.name.capitalize(),
|
|
177
|
+
description=wf_info.description
|
|
177
178
|
)
|
|
179
|
+
# Convert StyledOption to Option with markup
|
|
180
|
+
prompt = f"[bold]{styled_opt.title}[/bold]\n[dim]{styled_opt.description}[/dim]"
|
|
181
|
+
options.append(Option(prompt, id=styled_opt.id))
|
|
178
182
|
|
|
179
183
|
return options if options else [Option("No workflows found", id="none", disabled=True)]
|
|
180
184
|
|