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.
- core/__init__.py +18 -0
- core/application.py +578 -0
- core/cli.py +193 -0
- core/commands/__init__.py +43 -0
- core/commands/executor.py +277 -0
- core/commands/menu_renderer.py +319 -0
- core/commands/parser.py +186 -0
- core/commands/registry.py +331 -0
- core/commands/system_commands.py +479 -0
- core/config/__init__.py +7 -0
- core/config/llm_task_config.py +110 -0
- core/config/loader.py +501 -0
- core/config/manager.py +112 -0
- core/config/plugin_config_manager.py +346 -0
- core/config/plugin_schema.py +424 -0
- core/config/service.py +399 -0
- core/effects/__init__.py +1 -0
- core/events/__init__.py +12 -0
- core/events/bus.py +129 -0
- core/events/executor.py +154 -0
- core/events/models.py +258 -0
- core/events/processor.py +176 -0
- core/events/registry.py +289 -0
- core/fullscreen/__init__.py +19 -0
- core/fullscreen/command_integration.py +290 -0
- core/fullscreen/components/__init__.py +12 -0
- core/fullscreen/components/animation.py +258 -0
- core/fullscreen/components/drawing.py +160 -0
- core/fullscreen/components/matrix_components.py +177 -0
- core/fullscreen/manager.py +302 -0
- core/fullscreen/plugin.py +204 -0
- core/fullscreen/renderer.py +282 -0
- core/fullscreen/session.py +324 -0
- core/io/__init__.py +52 -0
- core/io/buffer_manager.py +362 -0
- core/io/config_status_view.py +272 -0
- core/io/core_status_views.py +410 -0
- core/io/input_errors.py +313 -0
- core/io/input_handler.py +2655 -0
- core/io/input_mode_manager.py +402 -0
- core/io/key_parser.py +344 -0
- core/io/layout.py +587 -0
- core/io/message_coordinator.py +204 -0
- core/io/message_renderer.py +601 -0
- core/io/modal_interaction_handler.py +315 -0
- core/io/raw_input_processor.py +946 -0
- core/io/status_renderer.py +845 -0
- core/io/terminal_renderer.py +586 -0
- core/io/terminal_state.py +551 -0
- core/io/visual_effects.py +734 -0
- core/llm/__init__.py +26 -0
- core/llm/api_communication_service.py +863 -0
- core/llm/conversation_logger.py +473 -0
- core/llm/conversation_manager.py +414 -0
- core/llm/file_operations_executor.py +1401 -0
- core/llm/hook_system.py +402 -0
- core/llm/llm_service.py +1629 -0
- core/llm/mcp_integration.py +386 -0
- core/llm/message_display_service.py +450 -0
- core/llm/model_router.py +214 -0
- core/llm/plugin_sdk.py +396 -0
- core/llm/response_parser.py +848 -0
- core/llm/response_processor.py +364 -0
- core/llm/tool_executor.py +520 -0
- core/logging/__init__.py +19 -0
- core/logging/setup.py +208 -0
- core/models/__init__.py +5 -0
- core/models/base.py +23 -0
- core/plugins/__init__.py +13 -0
- core/plugins/collector.py +212 -0
- core/plugins/discovery.py +386 -0
- core/plugins/factory.py +263 -0
- core/plugins/registry.py +152 -0
- core/storage/__init__.py +5 -0
- core/storage/state_manager.py +84 -0
- core/ui/__init__.py +6 -0
- core/ui/config_merger.py +176 -0
- core/ui/config_widgets.py +369 -0
- core/ui/live_modal_renderer.py +276 -0
- core/ui/modal_actions.py +162 -0
- core/ui/modal_overlay_renderer.py +373 -0
- core/ui/modal_renderer.py +591 -0
- core/ui/modal_state_manager.py +443 -0
- core/ui/widget_integration.py +222 -0
- core/ui/widgets/__init__.py +27 -0
- core/ui/widgets/base_widget.py +136 -0
- core/ui/widgets/checkbox.py +85 -0
- core/ui/widgets/dropdown.py +140 -0
- core/ui/widgets/label.py +78 -0
- core/ui/widgets/slider.py +185 -0
- core/ui/widgets/text_input.py +224 -0
- core/utils/__init__.py +11 -0
- core/utils/config_utils.py +656 -0
- core/utils/dict_utils.py +212 -0
- core/utils/error_utils.py +275 -0
- core/utils/key_reader.py +171 -0
- core/utils/plugin_utils.py +267 -0
- core/utils/prompt_renderer.py +151 -0
- kollabor-0.4.9.dist-info/METADATA +298 -0
- kollabor-0.4.9.dist-info/RECORD +128 -0
- kollabor-0.4.9.dist-info/WHEEL +5 -0
- kollabor-0.4.9.dist-info/entry_points.txt +2 -0
- kollabor-0.4.9.dist-info/licenses/LICENSE +21 -0
- kollabor-0.4.9.dist-info/top_level.txt +4 -0
- kollabor_cli_main.py +20 -0
- plugins/__init__.py +1 -0
- plugins/enhanced_input/__init__.py +18 -0
- plugins/enhanced_input/box_renderer.py +103 -0
- plugins/enhanced_input/box_styles.py +142 -0
- plugins/enhanced_input/color_engine.py +165 -0
- plugins/enhanced_input/config.py +150 -0
- plugins/enhanced_input/cursor_manager.py +72 -0
- plugins/enhanced_input/geometry.py +81 -0
- plugins/enhanced_input/state.py +130 -0
- plugins/enhanced_input/text_processor.py +115 -0
- plugins/enhanced_input_plugin.py +385 -0
- plugins/fullscreen/__init__.py +9 -0
- plugins/fullscreen/example_plugin.py +327 -0
- plugins/fullscreen/matrix_plugin.py +132 -0
- plugins/hook_monitoring_plugin.py +1299 -0
- plugins/query_enhancer_plugin.py +350 -0
- plugins/save_conversation_plugin.py +502 -0
- plugins/system_commands_plugin.py +93 -0
- plugins/tmux_plugin.py +795 -0
- plugins/workflow_enforcement_plugin.py +629 -0
- system_prompt/default.md +1286 -0
- system_prompt/default_win.md +265 -0
- 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
|
+
}
|