titan-cli 0.1.16__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. {titan_cli-0.1.16 → titan_cli-0.2.0}/PKG-INFO +7 -4
  2. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/push_step.py +17 -2
  3. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/status_step.py +7 -6
  4. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/github_client.py +4 -0
  5. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/network/graphql_queries.py +23 -0
  6. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/services/review_service.py +63 -16
  7. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/view.py +30 -0
  8. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/operations/__init__.py +4 -0
  9. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/operations/comment_operations.py +50 -18
  10. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/operations/pr_operations.py +49 -7
  11. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/pr_review_steps.py +171 -87
  12. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/workflows/create-pr-ai.yaml +8 -0
  13. {titan_cli-0.1.16 → titan_cli-0.2.0}/pyproject.toml +9 -2
  14. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/config.py +16 -13
  15. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/logging/config.py +6 -1
  16. titan_cli-0.2.0/titan_cli/core/plugins/community.py +543 -0
  17. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/plugins/plugin_base.py +18 -2
  18. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/plugins/plugin_registry.py +11 -4
  19. titan_cli-0.2.0/titan_cli/core/utils.py +44 -0
  20. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/models.py +1 -0
  21. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/workflow_filter_service.py +3 -3
  22. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/workflow_registry.py +44 -0
  23. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/workflow_sources.py +28 -9
  24. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/steps/ai_assistant_step.py +0 -1
  25. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/steps/command_step.py +3 -6
  26. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/__init__.py +18 -16
  27. titan_cli-0.2.0/titan_cli/ui/tui/screens/install_plugin_screen.py +567 -0
  28. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/main_menu.py +25 -0
  29. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/plugin_config_wizard.py +33 -30
  30. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/plugin_management.py +224 -16
  31. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/workflow_execution.py +9 -8
  32. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/textual_components.py +117 -3
  33. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/__init__.py +4 -0
  34. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/panel.py +45 -12
  35. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/prompt_input.py +3 -1
  36. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/table.py +30 -3
  37. titan_cli-0.2.0/titan_cli/ui/tui/widgets/wizard.py +49 -0
  38. {titan_cli-0.1.16 → titan_cli-0.2.0}/LICENSE +0 -0
  39. {titan_cli-0.1.16 → titan_cli-0.2.0}/README.md +0 -0
  40. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/__init__.py +0 -0
  41. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/__init__.py +0 -0
  42. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/git_client.py +0 -0
  43. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/network/__init__.py +0 -0
  44. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/network/git_network.py +0 -0
  45. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/__init__.py +0 -0
  46. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/branch_service.py +0 -0
  47. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/commit_service.py +0 -0
  48. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/diff_service.py +0 -0
  49. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/remote_service.py +0 -0
  50. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/stash_service.py +0 -0
  51. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/status_service.py +0 -0
  52. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/tag_service.py +0 -0
  53. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/clients/services/worktree_service.py +0 -0
  54. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/exceptions.py +0 -0
  55. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/messages.py +0 -0
  56. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/__init__.py +0 -0
  57. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/mappers/__init__.py +0 -0
  58. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/mappers/branch_mapper.py +0 -0
  59. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/mappers/commit_mapper.py +0 -0
  60. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/mappers/status_mapper.py +0 -0
  61. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/mappers/tag_mapper.py +0 -0
  62. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/mappers/worktree_mapper.py +0 -0
  63. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/network/__init__.py +0 -0
  64. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/network/branch.py +0 -0
  65. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/network/commit.py +0 -0
  66. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/network/status.py +0 -0
  67. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/network/tag.py +0 -0
  68. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/network/worktree.py +0 -0
  69. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/view/__init__.py +0 -0
  70. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/view/branch.py +0 -0
  71. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/view/commit.py +0 -0
  72. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/view/status.py +0 -0
  73. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/view/tag.py +0 -0
  74. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/models/view/worktree.py +0 -0
  75. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/operations/__init__.py +0 -0
  76. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/operations/branch_operations.py +0 -0
  77. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/operations/commit_operations.py +0 -0
  78. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/operations/diff_operations.py +0 -0
  79. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/plugin.py +0 -0
  80. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/__init__.py +0 -0
  81. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/ai_commit_message_step.py +0 -0
  82. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/branch_steps.py +0 -0
  83. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/checkout_step.py +0 -0
  84. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/commit_step.py +0 -0
  85. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/create_branch_step.py +0 -0
  86. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/create_worktree_step.py +0 -0
  87. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/diff_summary_step.py +0 -0
  88. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/pull_step.py +0 -0
  89. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/remove_worktree_step.py +0 -0
  90. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/restore_original_branch_step.py +0 -0
  91. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/save_current_branch_step.py +0 -0
  92. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/steps/worktree_command_step.py +0 -0
  93. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/workflows/__previews__/__init__.py +0 -0
  94. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/workflows/__previews__/commit_ai_preview.py +0 -0
  95. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-git/titan_plugin_git/workflows/commit-ai.yaml +0 -0
  96. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/__init__.py +0 -0
  97. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/agents/__init__.py +0 -0
  98. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/agents/config_loader.py +0 -0
  99. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/agents/issue_generator.py +0 -0
  100. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/agents/pr_agent.py +0 -0
  101. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/__init__.py +0 -0
  102. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/network/__init__.py +0 -0
  103. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/network/gh_network.py +0 -0
  104. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/network/graphql_network.py +0 -0
  105. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/protocols.py +0 -0
  106. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/services/__init__.py +0 -0
  107. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/services/issue_service.py +0 -0
  108. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/services/pr_service.py +0 -0
  109. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/clients/services/team_service.py +0 -0
  110. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/config/__init__.py +0 -0
  111. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/config/pr_agent.toml +0 -0
  112. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/exceptions.py +0 -0
  113. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/messages.py +0 -0
  114. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/__init__.py +0 -0
  115. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/formatting.py +0 -0
  116. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/mappers/__init__.py +0 -0
  117. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/mappers/comment_mapper.py +0 -0
  118. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/mappers/issue_mapper.py +0 -0
  119. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/mappers/pr_mapper.py +0 -0
  120. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/mappers/review_mapper.py +0 -0
  121. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/mappers/thread_mapper.py +0 -0
  122. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/__init__.py +0 -0
  123. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/graphql/__init__.py +0 -0
  124. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/graphql/issue_comment.py +0 -0
  125. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/graphql/review_comment.py +0 -0
  126. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/graphql/review_thread.py +0 -0
  127. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/graphql/user.py +0 -0
  128. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/rest/__init__.py +0 -0
  129. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/rest/issue.py +0 -0
  130. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/rest/pull_request.py +0 -0
  131. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/rest/review.py +0 -0
  132. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/models/network/rest/user.py +0 -0
  133. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/operations/issue_operations.py +0 -0
  134. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/operations/pr_creation_operations.py +0 -0
  135. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/operations/worktree_operations.py +0 -0
  136. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/plugin.py +0 -0
  137. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/__init__.py +0 -0
  138. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/ai_pr_step.py +0 -0
  139. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/create_pr_step.py +0 -0
  140. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/github_prompt_steps.py +0 -0
  141. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/issue_steps.py +0 -0
  142. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/preview_step.py +0 -0
  143. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/steps/worktree_steps.py +0 -0
  144. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/utils.py +0 -0
  145. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/widgets/__init__.py +0 -0
  146. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/widgets/code_block.py +0 -0
  147. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/widgets/comment.py +0 -0
  148. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/widgets/comment_thread.py +0 -0
  149. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/widgets/comment_utils.py +0 -0
  150. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/widgets/reply_comment.py +0 -0
  151. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/workflows/__previews__/__init__.py +0 -0
  152. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/workflows/__previews__/create_pr_ai_preview.py +0 -0
  153. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/workflows/create-issue-ai.yaml +0 -0
  154. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-github/titan_plugin_github/workflows/review-pr-comments.yaml +0 -0
  155. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/__init__.py +0 -0
  156. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/__init__.py +0 -0
  157. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/config_loader.py +0 -0
  158. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/jira_agent.py +0 -0
  159. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/prompts.py +0 -0
  160. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/response_parser.py +0 -0
  161. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/token_tracker.py +0 -0
  162. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/agents/validators.py +0 -0
  163. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/__init__.py +0 -0
  164. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/jira_client.py +0 -0
  165. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/network/__init__.py +0 -0
  166. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/network/jira_network.py +0 -0
  167. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/__init__.py +0 -0
  168. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/comment_service.py +0 -0
  169. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/issue_service.py +0 -0
  170. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/link_service.py +0 -0
  171. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/metadata_service.py +0 -0
  172. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/project_service.py +0 -0
  173. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/clients/services/transition_service.py +0 -0
  174. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/config/jira_agent.toml +0 -0
  175. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/config/templates/issue_analysis.md.j2 +0 -0
  176. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/exceptions.py +0 -0
  177. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/formatters/__init__.py +0 -0
  178. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/formatters/markdown_formatter.py +0 -0
  179. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/messages.py +0 -0
  180. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/__init__.py +0 -0
  181. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/formatting.py +0 -0
  182. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/mappers/__init__.py +0 -0
  183. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/mappers/comment_mapper.py +0 -0
  184. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/mappers/issue_mapper.py +0 -0
  185. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/mappers/project_mapper.py +0 -0
  186. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/mappers/transition_mapper.py +0 -0
  187. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/__init__.py +0 -0
  188. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/comment.py +0 -0
  189. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/issue.py +0 -0
  190. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/issue_type.py +0 -0
  191. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/priority.py +0 -0
  192. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/project.py +0 -0
  193. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/status.py +0 -0
  194. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/transition.py +0 -0
  195. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/network/rest/user.py +0 -0
  196. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/models/view.py +0 -0
  197. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/operations/__init__.py +0 -0
  198. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/operations/issue_formatting_operations.py +0 -0
  199. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/operations/jql_operations.py +0 -0
  200. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/plugin.py +0 -0
  201. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/steps/ai_analyze_issue_step.py +0 -0
  202. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/steps/get_issue_step.py +0 -0
  203. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/steps/list_versions_step.py +0 -0
  204. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/steps/prompt_select_issue_step.py +0 -0
  205. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/steps/search_jql_step.py +0 -0
  206. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/steps/search_saved_query_step.py +0 -0
  207. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/utils/__init__.py +0 -0
  208. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/utils/issue_sorter.py +0 -0
  209. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/utils/saved_queries.py +0 -0
  210. {titan_cli-0.1.16 → titan_cli-0.2.0}/plugins/titan-plugin-jira/titan_plugin_jira/workflows/analyze-jira-issues.yaml +0 -0
  211. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/__init__.py +0 -0
  212. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/__main__.py +0 -0
  213. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/__init__.py +0 -0
  214. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/agents/__init__.py +0 -0
  215. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/agents/base.py +0 -0
  216. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/client.py +0 -0
  217. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/constants.py +0 -0
  218. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/exceptions.py +0 -0
  219. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/llm_tools.py +0 -0
  220. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/models.py +0 -0
  221. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/oauth_helper.py +0 -0
  222. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/providers/__init__.py +0 -0
  223. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/providers/anthropic.py +0 -0
  224. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/providers/base.py +0 -0
  225. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ai/providers/gemini.py +0 -0
  226. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/cli.py +0 -0
  227. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/clients/__init__.py +0 -0
  228. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/clients/gcloud_client.py +0 -0
  229. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/__init__.py +0 -0
  230. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/discovery.py +0 -0
  231. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/errors.py +0 -0
  232. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/logging/__init__.py +0 -0
  233. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/logging/decorators.py +0 -0
  234. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/models.py +0 -0
  235. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/plugins/available.py +0 -0
  236. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/plugins/models.py +0 -0
  237. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/result.py +0 -0
  238. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/secrets.py +0 -0
  239. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/__init__.py +0 -0
  240. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/project_step_source.py +0 -0
  241. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/core/workflows/workflow_exceptions.py +0 -0
  242. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/__init__.py +0 -0
  243. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/builder.py +0 -0
  244. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/context.py +0 -0
  245. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/mock_context.py +0 -0
  246. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/results.py +0 -0
  247. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/utils/__init__.py +0 -0
  248. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/utils/venv.py +0 -0
  249. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/engine/workflow_executor.py +0 -0
  250. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/external_cli/__init__.py +0 -0
  251. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/external_cli/configs.py +0 -0
  252. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/external_cli/launcher.py +0 -0
  253. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/messages.py +0 -0
  254. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/__previews__/statusbar_preview.py +0 -0
  255. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/app.py +0 -0
  256. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/colors.py +0 -0
  257. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/icons.py +0 -0
  258. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/__init__.py +0 -0
  259. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/ai_config.py +0 -0
  260. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/ai_config_wizard.py +0 -0
  261. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/base.py +0 -0
  262. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/cli_launcher.py +0 -0
  263. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/global_setup_wizard.py +0 -0
  264. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/project_setup_wizard.py +0 -0
  265. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/screens/workflows.py +0 -0
  266. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/textual_workflow_executor.py +0 -0
  267. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/theme.py +0 -0
  268. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/button.py +0 -0
  269. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/decision_badge.py +0 -0
  270. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/header.py +0 -0
  271. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/multiline_input.py +0 -0
  272. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/panel_container.py +0 -0
  273. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/prompt_choice.py +0 -0
  274. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/prompt_option_list.py +0 -0
  275. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/prompt_selection_list.py +0 -0
  276. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/prompt_textarea.py +0 -0
  277. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/status_bar.py +0 -0
  278. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/step_container.py +0 -0
  279. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/styled_option_list.py +0 -0
  280. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/ui/tui/widgets/text.py +0 -0
  281. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/utils/__init__.py +0 -0
  282. {titan_cli-0.1.16 → titan_cli-0.2.0}/titan_cli/utils/autoupdate.py +0 -0
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: titan-cli
3
- Version: 0.1.16
3
+ Version: 0.2.0
4
4
  Summary: Modular development tools orchestrator - Streamline your workflows with AI integration and intuitive terminal UI
5
- Home-page: https://github.com/masorange/titan-cli
6
5
  License: MIT
6
+ License-File: LICENSE
7
7
  Keywords: cli,workflow,orchestrator,automation,devtools,ai
8
8
  Author: MasOrange Apps Team
9
9
  Author-email: apps-management-stores@masorange.es
@@ -17,6 +17,8 @@ Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
20
22
  Requires-Dist: anthropic (>=0.75.0,<0.76.0)
21
23
  Requires-Dist: google-auth (>=2.43.0,<3.0.0)
22
24
  Requires-Dist: google-genai (>=1.58.0,<2.0.0)
@@ -32,7 +34,8 @@ Requires-Dist: textual (>=1.0.0,<2.0.0)
32
34
  Requires-Dist: tomli (>=2.0.0,<3.0.0)
33
35
  Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
34
36
  Requires-Dist: typer (>=0.20.0,<1.0.0)
35
- Project-URL: Documentation, https://github.com/masorange/titan-cli
37
+ Project-URL: Documentation, https://masorange.github.io/titan-cli/
38
+ Project-URL: Homepage, https://github.com/masorange/titan-cli
36
39
  Project-URL: Repository, https://github.com/masorange/titan-cli
37
40
  Description-Content-Type: text/markdown
38
41
 
@@ -1,5 +1,5 @@
1
1
  # plugins/titan-plugin-git/titan_plugin_git/steps/push_step.py
2
- from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error
2
+ from titan_cli.engine import WorkflowContext, WorkflowResult, Success, Error, Skip
3
3
  from titan_cli.core.result import ClientSuccess, ClientError
4
4
  from titan_plugin_git.messages import msg
5
5
 
@@ -57,9 +57,24 @@ def create_git_push_step(ctx: WorkflowContext) -> WorkflowResult:
57
57
  exists_result = ctx.git.branch_exists_on_remote(branch=branch_to_use, remote=remote_to_use)
58
58
  match exists_result:
59
59
  case ClientSuccess(data=exists):
60
- # The first push of a branch should set the upstream
61
60
  if not exists:
61
+ # The first push of a branch should set the upstream
62
62
  set_upstream = True
63
+ else:
64
+ # Branch exists on remote — check if there's anything to push
65
+ unpushed_result = ctx.git.count_unpushed_commits(branch=branch_to_use, remote=remote_to_use)
66
+ match unpushed_result:
67
+ case ClientSuccess(data=unpushed_count):
68
+ if unpushed_count == 0:
69
+ ctx.textual.success_text(f"Branch {branch_to_use} is already up to date with {remote_to_use}")
70
+ ctx.textual.end_step("success")
71
+ return Skip(
72
+ "Branch already pushed",
73
+ metadata={"pr_head_branch": branch_to_use}
74
+ )
75
+ case ClientError():
76
+ # If we can't count, proceed with push anyway
77
+ pass
63
78
  case ClientError(error_message=err):
64
79
  ctx.textual.end_step("error")
65
80
  return Error(f"Failed to check remote branch: {err}")
@@ -16,7 +16,9 @@ def get_git_status_step(ctx: WorkflowContext) -> WorkflowResult:
16
16
 
17
17
  Behavior:
18
18
  - If there are uncommitted changes: Returns Success and continues workflow
19
- - If working directory is clean: Returns Exit (stops workflow - nothing to commit)
19
+ - If working directory is clean: Returns Exit — nothing to commit.
20
+ In nested workflows (e.g. commit-ai called from create-pr-ai), the engine
21
+ converts Exit to Success so the parent workflow continues normally.
20
22
 
21
23
  Requires:
22
24
  ctx.git: An initialized GitClient.
@@ -26,7 +28,7 @@ def get_git_status_step(ctx: WorkflowContext) -> WorkflowResult:
26
28
 
27
29
  Returns:
28
30
  Success: If there are changes to commit (workflow continues)
29
- Exit: If working directory is clean (workflow stops - nothing to commit)
31
+ Exit: If working directory is clean (stops commit workflow; parent continues)
30
32
  Error: If the GitClient is not available or the git command fails.
31
33
  """
32
34
  if not ctx.textual:
@@ -54,13 +56,12 @@ def get_git_status_step(ctx: WorkflowContext) -> WorkflowResult:
54
56
  metadata={"git_status": status}
55
57
  )
56
58
  else:
57
- # Working directory is clean - exit workflow (nothing to commit)
59
+ # Working directory is clean — nothing to commit, exit early.
60
+ # If commit-ai is nested inside another workflow (e.g. create-pr-ai),
61
+ # the engine converts this Exit to Success so the parent continues.
58
62
  ctx.textual.success_text(msg.Steps.Status.WORKING_DIRECTORY_IS_CLEAN)
59
- ctx.textual.text("")
60
- ctx.textual.dim_text("Nothing to commit. Skipping workflow.")
61
63
  ctx.textual.end_step("success")
62
64
 
63
- # Exit workflow early (not an error)
64
65
  return Exit("No changes to commit", metadata={"git_status": status})
65
66
 
66
67
  case ClientError(error_message=err):
@@ -215,6 +215,10 @@ class GitHubClient:
215
215
  """Reply to a PR comment."""
216
216
  return self._review_service.reply_to_comment(pr_number, comment_id, body)
217
217
 
218
+ def get_pr_general_comments(self, pr_number: int) -> ClientResult[List[UICommentThread]]:
219
+ """Get general PR comments (not attached to code lines)."""
220
+ return self._review_service.get_pr_general_comments(pr_number)
221
+
218
222
  def add_issue_comment(self, pr_number: int, body: str) -> ClientResult[None]:
219
223
  """Add a general comment to PR (issue comment)."""
220
224
  return self._review_service.add_issue_comment(pr_number, body)
@@ -44,6 +44,29 @@ query($owner: String!, $repo: String!, $prNumber: Int!) {
44
44
  }
45
45
  '''
46
46
 
47
+ GET_PR_ISSUE_COMMENTS = '''
48
+ query($owner: String!, $repo: String!, $prNumber: Int!) {
49
+ repository(owner: $owner, name: $repo) {
50
+ pullRequest(number: $prNumber) {
51
+ comments(first: 100) {
52
+ nodes {
53
+ databaseId
54
+ body
55
+ author {
56
+ login
57
+ ... on User {
58
+ name
59
+ }
60
+ }
61
+ createdAt
62
+ updatedAt
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ '''
69
+
47
70
  GET_PR_NODE_ID = '''
48
71
  query($owner: String!, $repo: String!, $prNumber: Int!) {
49
72
  repository(owner: $owner, name: $repo) {
@@ -6,14 +6,13 @@ Business logic for PR review operations.
6
6
  Uses GraphQL for complex operations (threads, comments, resolve).
7
7
  """
8
8
  import json
9
- import subprocess
10
9
  from typing import List, Optional, Dict, Any
11
10
 
12
11
  from titan_cli.core.result import ClientResult, ClientSuccess, ClientError
13
12
  from titan_cli.core.logging import log_client_operation
14
13
  from ..network import GHNetwork, GraphQLNetwork, graphql_queries
15
14
  from ...models.network.rest import NetworkReview
16
- from ...models.network.graphql import GraphQLPullRequestReviewThread
15
+ from ...models.network.graphql import GraphQLPullRequestReviewThread, GraphQLIssueComment
17
16
  from ...models.view import UICommentThread, UIReview
18
17
  from ...models.mappers import from_graphql_review_thread, from_network_review
19
18
  from ...exceptions import GitHubAPIError
@@ -106,6 +105,66 @@ class ReviewService:
106
105
  except GitHubAPIError as e:
107
106
  return ClientError(error_message=str(e), error_code="API_ERROR")
108
107
 
108
+ @log_client_operation()
109
+ def get_pr_general_comments(
110
+ self, pr_number: int
111
+ ) -> ClientResult[List[UICommentThread]]:
112
+ """
113
+ Get general PR comments (not attached to code lines).
114
+
115
+ Uses GraphQL to fetch top-level PR comments and wraps each one as
116
+ a pseudo-thread (thread_id = "general_{id}") for uniform rendering.
117
+
118
+ Args:
119
+ pr_number: PR number
120
+
121
+ Returns:
122
+ ClientResult[List[UICommentThread]]
123
+ """
124
+ try:
125
+ repo_string = self.gh.get_repo_string()
126
+ owner, repo = repo_string.split('/')
127
+
128
+ variables = {
129
+ "owner": owner,
130
+ "repo": repo,
131
+ "prNumber": pr_number
132
+ }
133
+
134
+ response = self.graphql.run_query(
135
+ graphql_queries.GET_PR_ISSUE_COMMENTS,
136
+ variables
137
+ )
138
+
139
+ comments_data = (
140
+ response.get("data", {})
141
+ .get("repository", {})
142
+ .get("pullRequest", {})
143
+ .get("comments", {})
144
+ .get("nodes", [])
145
+ )
146
+
147
+ network_comments = [
148
+ GraphQLIssueComment.from_graphql(c) for c in comments_data
149
+ ]
150
+
151
+ ui_threads = [
152
+ UICommentThread.from_issue_comment(c) for c in network_comments
153
+ ]
154
+
155
+ return ClientSuccess(
156
+ data=ui_threads,
157
+ message=f"Found {len(ui_threads)} general comments"
158
+ )
159
+
160
+ except (KeyError, ValueError) as e:
161
+ return ClientError(
162
+ error_message=f"Failed to parse general comments: {e}",
163
+ error_code="PARSE_ERROR"
164
+ )
165
+ except GitHubAPIError as e:
166
+ return ClientError(error_message=str(e), error_code="API_ERROR")
167
+
109
168
  @log_client_operation()
110
169
  def resolve_review_thread(self, thread_node_id: str) -> ClientResult[None]:
111
170
  """
@@ -191,16 +250,9 @@ class ReviewService:
191
250
  "--input", "-",
192
251
  ]
193
252
 
194
- # Run with JSON payload via stdin
195
- result = subprocess.run(
196
- ["gh"] + args,
197
- input=json.dumps(payload),
198
- capture_output=True,
199
- text=True,
200
- check=True,
201
- )
253
+ result = self.gh.run_command(args, stdin_input=json.dumps(payload))
202
254
 
203
- response = json.loads(result.stdout)
255
+ response = json.loads(result)
204
256
  review_id = response["id"]
205
257
 
206
258
  return ClientSuccess(
@@ -213,11 +265,6 @@ class ReviewService:
213
265
  error_message=f"Failed to parse review response: {e}",
214
266
  error_code="PARSE_ERROR"
215
267
  )
216
- except subprocess.CalledProcessError as e:
217
- return ClientError(
218
- error_message=f"Failed to create draft review: gh API returned exit code {e.returncode}",
219
- error_code="API_ERROR"
220
- )
221
268
  except GitHubAPIError as e:
222
269
  return ClientError(error_message=str(e), error_code="API_ERROR")
223
270
 
@@ -94,6 +94,36 @@ class UICommentThread:
94
94
  from .mappers import from_graphql_review_thread
95
95
  return from_graphql_review_thread(thread)
96
96
 
97
+ @classmethod
98
+ def from_issue_comment(cls, comment: 'Any') -> 'UICommentThread':
99
+ """
100
+ Wrap a GraphQLIssueComment as a pseudo-thread for uniform rendering.
101
+
102
+ General PR comments have no thread concept, so they are wrapped in a
103
+ UICommentThread with a synthetic thread_id ("general_{id}") that
104
+ downstream code uses to distinguish them from review threads.
105
+
106
+ Args:
107
+ comment: GraphQLIssueComment instance from GraphQL
108
+
109
+ Returns:
110
+ UICommentThread with thread_id="general_{id}", no replies, not resolved
111
+ """
112
+ from .mappers import from_graphql_issue_comment
113
+ ui_comment = from_graphql_issue_comment(comment)
114
+ return cls(
115
+ thread_id=f"general_{comment.databaseId}",
116
+ main_comment=ui_comment,
117
+ replies=[],
118
+ is_resolved=False,
119
+ is_outdated=False
120
+ )
121
+
122
+ @property
123
+ def is_general_comment(self) -> bool:
124
+ """True if this thread wraps a general PR comment (not an inline review thread)."""
125
+ return self.thread_id.startswith("general_")
126
+
97
127
 
98
128
  @dataclass
99
129
  class UIPullRequest:
@@ -14,6 +14,7 @@ Modules:
14
14
 
15
15
  from .comment_operations import (
16
16
  build_ai_review_context,
17
+ build_ai_review_prompt,
17
18
  find_ai_response_file,
18
19
  create_commit_message,
19
20
  reply_to_comment_batch,
@@ -22,6 +23,7 @@ from .comment_operations import (
22
23
 
23
24
  from .pr_operations import (
24
25
  fetch_pr_threads,
26
+ fetch_pr_general_comments,
25
27
  )
26
28
 
27
29
  from .worktree_operations import (
@@ -44,6 +46,7 @@ from .issue_operations import (
44
46
  __all__ = [
45
47
  # Comment operations
46
48
  "build_ai_review_context",
49
+ "build_ai_review_prompt",
47
50
  "find_ai_response_file",
48
51
  "create_commit_message",
49
52
  "reply_to_comment_batch",
@@ -51,6 +54,7 @@ __all__ = [
51
54
 
52
55
  # PR operations
53
56
  "fetch_pr_threads",
57
+ "fetch_pr_general_comments",
54
58
 
55
59
  # Worktree operations
56
60
  "setup_worktree",
@@ -35,13 +35,6 @@ def build_ai_review_context(
35
35
  "diff_hunk": str (acotado),
36
36
  "thread": [{"author": str, "date": str, "body": str}, ...]
37
37
  }
38
-
39
- Example:
40
- >>> context = build_ai_review_context(pr_thread, "feat: Add feature")
41
- >>> context['pr']
42
- 'feat: Add feature'
43
- >>> len(context['diff_hunk'].split('\\n'))
44
- 11 # ~11 lines instead of 200+
45
38
  """
46
39
  main_comment = pr_thread.main_comment
47
40
 
@@ -93,11 +86,6 @@ def find_ai_response_file(comment_id: int, expected_path: str) -> Optional[str]:
93
86
 
94
87
  Returns:
95
88
  Path to the found file, or None if not found
96
-
97
- Example:
98
- >>> path = find_ai_response_file(123, "/tmp/titan-ai-response-comment-123.txt")
99
- >>> path
100
- '/home/user/.gemini/tmp/.../titan-ai-response-comment-123.txt'
101
89
  """
102
90
  # Try expected location first
103
91
  if os.path.exists(expected_path):
@@ -145,6 +133,56 @@ def create_commit_message(comment_body: str, comment_author: str, comment_path:
145
133
  return message
146
134
 
147
135
 
136
+ def build_ai_review_prompt(response_file: str) -> str:
137
+ """
138
+ Build the prompt template for AI review of a PR comment thread.
139
+
140
+ Args:
141
+ response_file: Path where the AI should write text responses
142
+
143
+ Returns:
144
+ Prompt string with {context} placeholder for the JSON context
145
+ """
146
+ return f"""Review this PR comment thread:
147
+
148
+ ```json
149
+ {{context}}
150
+ ```
151
+
152
+ ## Your Task
153
+
154
+ 1. **First, evaluate if the review comment makes sense:**
155
+ - Is the feedback valid and applicable to the current code?
156
+ - Is the requested change appropriate?
157
+ - Could previous attempts have already addressed this (check the thread conversation)?
158
+
159
+ 2. **Then, based on your evaluation:**
160
+ - **If the comment makes sense**: Make the necessary code changes to address it
161
+ - **If the comment doesn't make sense or is outdated**:
162
+ * DO NOT make code changes
163
+ * Write your explanation/response EXACTLY to this file path: {response_file}
164
+ * IMPORTANT: Use this exact command to write the response:
165
+ ```bash
166
+ cat > {response_file} << 'EOF'
167
+ Your response text here
168
+ EOF
169
+ ```
170
+
171
+ ## Response Style (CRITICAL)
172
+ - **Keep responses SHORT and CONCISE** (maximum 2-3 sentences)
173
+ - **Be direct and to the point** - no verbose explanations
174
+ - **Avoid multiple paragraphs** - use a single short paragraph
175
+ - **Don't over-explain** - state the key point clearly and move on
176
+ - Example GOOD: "This is intentional. The logic handles X at layer Y, ensuring Z."
177
+ - Example BAD: Long multi-paragraph explanations with bullet points and detailed justifications
178
+
179
+ Note: Review the entire conversation thread carefully - previous fix attempts may have failed or been incomplete.
180
+
181
+ ## When You're Done
182
+ Once you have completed your single action (code fix OR written the response file), tell the user:
183
+ "Done. Press Ctrl+C twice to exit and return to Titan." """
184
+
185
+
148
186
  def prepare_replies_for_sending(
149
187
  pending_responses: Dict[int, Dict],
150
188
  comment_commits: Dict[int, str],
@@ -202,12 +240,6 @@ def reply_to_comment_batch(
202
240
 
203
241
  Returns:
204
242
  Dictionary mapping comment_id -> success (bool)
205
-
206
- Example:
207
- >>> replies = {123: "Fixed", 456: "Done"}
208
- >>> results = reply_to_comment_batch(github, 789, replies)
209
- >>> results
210
- {123: True, 456: True}
211
243
  """
212
244
  results = {}
213
245
 
@@ -10,6 +10,55 @@ from titan_cli.core.result import ClientSuccess, ClientError
10
10
  from ..models.view import UICommentThread
11
11
 
12
12
 
13
+ def fetch_pr_general_comments(
14
+ github_client,
15
+ pr_number: int,
16
+ ) -> List[UICommentThread]:
17
+ """
18
+ Fetch general PR comments (not attached to code lines).
19
+
20
+ Filters out:
21
+ - Bot comments
22
+ - Empty comments
23
+ - JSON-only comments (coverage reports, CI badges, etc.)
24
+
25
+ Args:
26
+ github_client: GitHub client instance
27
+ pr_number: PR number
28
+
29
+ Returns:
30
+ List of UICommentThread pseudo-threads (thread_id starts with "general_")
31
+
32
+ Raises:
33
+ Exception: If fetching comments fails
34
+ """
35
+ result = github_client.get_pr_general_comments(pr_number)
36
+
37
+ match result:
38
+ case ClientSuccess(data=threads):
39
+ all_threads = threads
40
+ case ClientError(error_message=err):
41
+ raise Exception(f"Failed to fetch general comments: {err}")
42
+ case _:
43
+ raise Exception("Unexpected result type")
44
+
45
+ filtered = []
46
+ for thread in all_threads:
47
+ comment = thread.main_comment
48
+ if not comment:
49
+ continue
50
+ if comment.author_login and 'bot' in comment.author_login.lower():
51
+ continue
52
+ if not comment.body or not comment.body.strip():
53
+ continue
54
+ body_stripped = comment.body.strip()
55
+ if body_stripped.startswith('{') and body_stripped.endswith('}'):
56
+ continue
57
+ filtered.append(thread)
58
+
59
+ return filtered
60
+
61
+
13
62
  def fetch_pr_threads(
14
63
  github_client,
15
64
  pr_number: int,
@@ -34,13 +83,6 @@ def fetch_pr_threads(
34
83
 
35
84
  Raises:
36
85
  Exception: If fetching threads fails
37
-
38
- Example:
39
- >>> threads = fetch_pr_threads(github, 123, include_resolved=False)
40
- >>> len(threads)
41
- 5
42
- >>> all(not t.is_resolved for t in threads)
43
- True
44
86
  """
45
87
  # Fetch all threads using GraphQL
46
88
  result = github_client.get_pr_review_threads(