kollabor 0.4.9__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 (128) hide show
  1. core/__init__.py +18 -0
  2. core/application.py +578 -0
  3. core/cli.py +193 -0
  4. core/commands/__init__.py +43 -0
  5. core/commands/executor.py +277 -0
  6. core/commands/menu_renderer.py +319 -0
  7. core/commands/parser.py +186 -0
  8. core/commands/registry.py +331 -0
  9. core/commands/system_commands.py +479 -0
  10. core/config/__init__.py +7 -0
  11. core/config/llm_task_config.py +110 -0
  12. core/config/loader.py +501 -0
  13. core/config/manager.py +112 -0
  14. core/config/plugin_config_manager.py +346 -0
  15. core/config/plugin_schema.py +424 -0
  16. core/config/service.py +399 -0
  17. core/effects/__init__.py +1 -0
  18. core/events/__init__.py +12 -0
  19. core/events/bus.py +129 -0
  20. core/events/executor.py +154 -0
  21. core/events/models.py +258 -0
  22. core/events/processor.py +176 -0
  23. core/events/registry.py +289 -0
  24. core/fullscreen/__init__.py +19 -0
  25. core/fullscreen/command_integration.py +290 -0
  26. core/fullscreen/components/__init__.py +12 -0
  27. core/fullscreen/components/animation.py +258 -0
  28. core/fullscreen/components/drawing.py +160 -0
  29. core/fullscreen/components/matrix_components.py +177 -0
  30. core/fullscreen/manager.py +302 -0
  31. core/fullscreen/plugin.py +204 -0
  32. core/fullscreen/renderer.py +282 -0
  33. core/fullscreen/session.py +324 -0
  34. core/io/__init__.py +52 -0
  35. core/io/buffer_manager.py +362 -0
  36. core/io/config_status_view.py +272 -0
  37. core/io/core_status_views.py +410 -0
  38. core/io/input_errors.py +313 -0
  39. core/io/input_handler.py +2655 -0
  40. core/io/input_mode_manager.py +402 -0
  41. core/io/key_parser.py +344 -0
  42. core/io/layout.py +587 -0
  43. core/io/message_coordinator.py +204 -0
  44. core/io/message_renderer.py +601 -0
  45. core/io/modal_interaction_handler.py +315 -0
  46. core/io/raw_input_processor.py +946 -0
  47. core/io/status_renderer.py +845 -0
  48. core/io/terminal_renderer.py +586 -0
  49. core/io/terminal_state.py +551 -0
  50. core/io/visual_effects.py +734 -0
  51. core/llm/__init__.py +26 -0
  52. core/llm/api_communication_service.py +863 -0
  53. core/llm/conversation_logger.py +473 -0
  54. core/llm/conversation_manager.py +414 -0
  55. core/llm/file_operations_executor.py +1401 -0
  56. core/llm/hook_system.py +402 -0
  57. core/llm/llm_service.py +1629 -0
  58. core/llm/mcp_integration.py +386 -0
  59. core/llm/message_display_service.py +450 -0
  60. core/llm/model_router.py +214 -0
  61. core/llm/plugin_sdk.py +396 -0
  62. core/llm/response_parser.py +848 -0
  63. core/llm/response_processor.py +364 -0
  64. core/llm/tool_executor.py +520 -0
  65. core/logging/__init__.py +19 -0
  66. core/logging/setup.py +208 -0
  67. core/models/__init__.py +5 -0
  68. core/models/base.py +23 -0
  69. core/plugins/__init__.py +13 -0
  70. core/plugins/collector.py +212 -0
  71. core/plugins/discovery.py +386 -0
  72. core/plugins/factory.py +263 -0
  73. core/plugins/registry.py +152 -0
  74. core/storage/__init__.py +5 -0
  75. core/storage/state_manager.py +84 -0
  76. core/ui/__init__.py +6 -0
  77. core/ui/config_merger.py +176 -0
  78. core/ui/config_widgets.py +369 -0
  79. core/ui/live_modal_renderer.py +276 -0
  80. core/ui/modal_actions.py +162 -0
  81. core/ui/modal_overlay_renderer.py +373 -0
  82. core/ui/modal_renderer.py +591 -0
  83. core/ui/modal_state_manager.py +443 -0
  84. core/ui/widget_integration.py +222 -0
  85. core/ui/widgets/__init__.py +27 -0
  86. core/ui/widgets/base_widget.py +136 -0
  87. core/ui/widgets/checkbox.py +85 -0
  88. core/ui/widgets/dropdown.py +140 -0
  89. core/ui/widgets/label.py +78 -0
  90. core/ui/widgets/slider.py +185 -0
  91. core/ui/widgets/text_input.py +224 -0
  92. core/utils/__init__.py +11 -0
  93. core/utils/config_utils.py +656 -0
  94. core/utils/dict_utils.py +212 -0
  95. core/utils/error_utils.py +275 -0
  96. core/utils/key_reader.py +171 -0
  97. core/utils/plugin_utils.py +267 -0
  98. core/utils/prompt_renderer.py +151 -0
  99. kollabor-0.4.9.dist-info/METADATA +298 -0
  100. kollabor-0.4.9.dist-info/RECORD +128 -0
  101. kollabor-0.4.9.dist-info/WHEEL +5 -0
  102. kollabor-0.4.9.dist-info/entry_points.txt +2 -0
  103. kollabor-0.4.9.dist-info/licenses/LICENSE +21 -0
  104. kollabor-0.4.9.dist-info/top_level.txt +4 -0
  105. kollabor_cli_main.py +20 -0
  106. plugins/__init__.py +1 -0
  107. plugins/enhanced_input/__init__.py +18 -0
  108. plugins/enhanced_input/box_renderer.py +103 -0
  109. plugins/enhanced_input/box_styles.py +142 -0
  110. plugins/enhanced_input/color_engine.py +165 -0
  111. plugins/enhanced_input/config.py +150 -0
  112. plugins/enhanced_input/cursor_manager.py +72 -0
  113. plugins/enhanced_input/geometry.py +81 -0
  114. plugins/enhanced_input/state.py +130 -0
  115. plugins/enhanced_input/text_processor.py +115 -0
  116. plugins/enhanced_input_plugin.py +385 -0
  117. plugins/fullscreen/__init__.py +9 -0
  118. plugins/fullscreen/example_plugin.py +327 -0
  119. plugins/fullscreen/matrix_plugin.py +132 -0
  120. plugins/hook_monitoring_plugin.py +1299 -0
  121. plugins/query_enhancer_plugin.py +350 -0
  122. plugins/save_conversation_plugin.py +502 -0
  123. plugins/system_commands_plugin.py +93 -0
  124. plugins/tmux_plugin.py +795 -0
  125. plugins/workflow_enforcement_plugin.py +629 -0
  126. system_prompt/default.md +1286 -0
  127. system_prompt/default_win.md +265 -0
  128. system_prompt/example_with_trender.md +47 -0
@@ -0,0 +1,204 @@
1
+ """Message coordination system for preventing race conditions.
2
+
3
+ This coordinator solves the fundamental race condition where multiple
4
+ message writing systems interfere with each other, causing messages
5
+ to be overwritten or cleared unexpectedly.
6
+ """
7
+
8
+ import logging
9
+ from typing import List, Tuple, Dict, Any
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class MessageDisplayCoordinator:
15
+ """Coordinates message display to prevent interference between systems.
16
+
17
+ Key Features:
18
+ - Atomic message sequences (all messages display together)
19
+ - Unified state management (prevents clearing conflicts)
20
+ - Proper ordering (system messages before responses)
21
+ - Protection from interference (no race conditions)
22
+ """
23
+
24
+ def __init__(self, terminal_renderer):
25
+ """Initialize message display coordinator.
26
+
27
+ Args:
28
+ terminal_renderer: TerminalRenderer instance for display
29
+ """
30
+ self.terminal_renderer = terminal_renderer
31
+ self.message_queue: List[Tuple[str, str, Dict[str, Any]]] = []
32
+ self.is_displaying = False
33
+
34
+ logger.debug("MessageDisplayCoordinator initialized")
35
+
36
+ def queue_message(self, message_type: str, content: str, **kwargs) -> None:
37
+ """Queue a message for coordinated display.
38
+
39
+ Args:
40
+ message_type: Type of message ("system", "assistant", "user", "error")
41
+ content: Message content to display
42
+ **kwargs: Additional arguments for message formatting
43
+ """
44
+ self.message_queue.append((message_type, content, kwargs))
45
+ logger.debug(f"Queued {message_type} message: {content[:50]}...")
46
+
47
+ def display_single_message(
48
+ self, message_type: str, content: str, **kwargs
49
+ ) -> None:
50
+ """Display a single message immediately through coordination.
51
+
52
+ This method provides a coordinated way for plugins and other systems
53
+ to display individual messages without bypassing the coordination system.
54
+
55
+ Args:
56
+ message_type: Type of message ("system", "assistant", "user", "error")
57
+ content: Message content to display
58
+ **kwargs: Additional arguments for message formatting
59
+ """
60
+ self.display_message_sequence([(message_type, content, kwargs)])
61
+
62
+ def display_queued_messages(self) -> None:
63
+ """Display all queued messages in proper atomic sequence.
64
+
65
+ This method ensures all queued messages display together
66
+ without interference from other systems.
67
+ """
68
+ if self.is_displaying or not self.message_queue:
69
+ return
70
+
71
+ logger.debug(f"Displaying {len(self.message_queue)} queued messages")
72
+
73
+ # Enter atomic display mode
74
+ self.is_displaying = True
75
+ self.terminal_renderer.writing_messages = True
76
+
77
+ # Clear active area once before all messages
78
+ self.terminal_renderer.clear_active_area()
79
+
80
+ try:
81
+ # Display all messages in sequence
82
+ for message_type, content, kwargs in self.message_queue:
83
+ self._display_single_message(message_type, content, kwargs)
84
+
85
+ # Add blank line for visual separation
86
+ self.terminal_renderer.message_renderer.write_message(
87
+ "", apply_gradient=False
88
+ )
89
+
90
+ finally:
91
+ # Exit atomic display mode
92
+ self.terminal_renderer.writing_messages = False
93
+ self.message_queue.clear()
94
+ self.is_displaying = False
95
+ logger.debug("Completed atomic message display")
96
+
97
+ def display_message_sequence(
98
+ self, messages: List[Tuple[str, str, Dict[str, Any]]]
99
+ ) -> None:
100
+ """Display a sequence of messages atomically.
101
+
102
+ This is the primary method for coordinated message display.
103
+ All messages in the sequence will display together without
104
+ interference from other systems.
105
+
106
+ Args:
107
+ messages: List of (message_type, content, kwargs) tuples
108
+
109
+ Example:
110
+ coordinator.display_message_sequence([
111
+ ("system", "Thought for 2.1 seconds", {}),
112
+ ("assistant", "Hello! How can I help you?", {})
113
+ ])
114
+ """
115
+ # Queue all messages
116
+ for message_type, content, kwargs in messages:
117
+ self.queue_message(message_type, content, **kwargs)
118
+
119
+ # Display them atomically
120
+ self.display_queued_messages()
121
+
122
+ def _display_single_message(
123
+ self, message_type: str, content: str, kwargs: Dict[str, Any]
124
+ ) -> None:
125
+ """Display a single message using the appropriate method.
126
+
127
+ Args:
128
+ message_type: Type of message to display
129
+ content: Message content
130
+ kwargs: Additional formatting arguments
131
+ """
132
+ try:
133
+ if message_type == "system":
134
+ # System messages use DIMMED format as per CLAUDE.md spec
135
+ from .message_renderer import MessageType, MessageFormat
136
+
137
+ self.terminal_renderer.message_renderer.conversation_renderer.write_message(
138
+ content,
139
+ message_type=MessageType.SYSTEM, # No ∴ prefix for system messages
140
+ format_style=MessageFormat.DIMMED, # Professional dimmed formatting
141
+ **kwargs,
142
+ )
143
+ elif message_type == "assistant":
144
+ # Use MessageFormat.GRADIENT for assistant messages
145
+ from .message_renderer import MessageType, MessageFormat
146
+
147
+ format_style = (
148
+ MessageFormat.GRADIENT
149
+ if kwargs.get("apply_gradient", True)
150
+ else MessageFormat.PLAIN
151
+ )
152
+ self.terminal_renderer.message_renderer.conversation_renderer.write_message(
153
+ content,
154
+ message_type=MessageType.ASSISTANT,
155
+ format_style=format_style,
156
+ **kwargs,
157
+ )
158
+ elif message_type == "user":
159
+ self.terminal_renderer.message_renderer.write_user_message(
160
+ content, **kwargs
161
+ )
162
+ elif message_type == "error":
163
+ # For error messages, use MessageType.ERROR for proper red color, no ∴ prefix
164
+ from .message_renderer import MessageType, MessageFormat
165
+
166
+ self.terminal_renderer.message_renderer.conversation_renderer.write_message(
167
+ content,
168
+ message_type=MessageType.ERROR,
169
+ format_style=MessageFormat.HIGHLIGHTED, # Uses red color from _format_highlighted
170
+ **kwargs,
171
+ )
172
+ else:
173
+ logger.warning(f"Unknown message type: {message_type}")
174
+ # Fallback to regular message
175
+ self.terminal_renderer.message_renderer.write_message(
176
+ content, apply_gradient=False
177
+ )
178
+
179
+ except Exception as e:
180
+ logger.error(f"Error displaying {message_type} message: {e}")
181
+ # Fallback display to prevent total failure
182
+ try:
183
+ print(f"[{message_type.upper()}] {content}")
184
+ except Exception:
185
+ logger.error(
186
+ "Critical: Failed to display message even with fallback"
187
+ )
188
+
189
+ def clear_queue(self) -> None:
190
+ """Clear all queued messages without displaying them."""
191
+ self.message_queue.clear()
192
+ logger.debug("Cleared message queue")
193
+
194
+ def get_queue_status(self) -> Dict[str, Any]:
195
+ """Get current queue status for debugging.
196
+
197
+ Returns:
198
+ Dictionary with queue information
199
+ """
200
+ return {
201
+ "queue_length": len(self.message_queue),
202
+ "is_displaying": self.is_displaying,
203
+ "queued_types": [msg[0] for msg in self.message_queue],
204
+ }