kollabor 0.4.9__py3-none-any.whl → 0.4.15__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 (192) hide show
  1. agents/__init__.py +2 -0
  2. agents/coder/__init__.py +0 -0
  3. agents/coder/agent.json +4 -0
  4. agents/coder/api-integration.md +2150 -0
  5. agents/coder/cli-pretty.md +765 -0
  6. agents/coder/code-review.md +1092 -0
  7. agents/coder/database-design.md +1525 -0
  8. agents/coder/debugging.md +1102 -0
  9. agents/coder/dependency-management.md +1397 -0
  10. agents/coder/git-workflow.md +1099 -0
  11. agents/coder/refactoring.md +1454 -0
  12. agents/coder/security-hardening.md +1732 -0
  13. agents/coder/system_prompt.md +1448 -0
  14. agents/coder/tdd.md +1367 -0
  15. agents/creative-writer/__init__.py +0 -0
  16. agents/creative-writer/agent.json +4 -0
  17. agents/creative-writer/character-development.md +1852 -0
  18. agents/creative-writer/dialogue-craft.md +1122 -0
  19. agents/creative-writer/plot-structure.md +1073 -0
  20. agents/creative-writer/revision-editing.md +1484 -0
  21. agents/creative-writer/system_prompt.md +690 -0
  22. agents/creative-writer/worldbuilding.md +2049 -0
  23. agents/data-analyst/__init__.py +30 -0
  24. agents/data-analyst/agent.json +4 -0
  25. agents/data-analyst/data-visualization.md +992 -0
  26. agents/data-analyst/exploratory-data-analysis.md +1110 -0
  27. agents/data-analyst/pandas-data-manipulation.md +1081 -0
  28. agents/data-analyst/sql-query-optimization.md +881 -0
  29. agents/data-analyst/statistical-analysis.md +1118 -0
  30. agents/data-analyst/system_prompt.md +928 -0
  31. agents/default/__init__.py +0 -0
  32. agents/default/agent.json +4 -0
  33. agents/default/dead-code.md +794 -0
  34. agents/default/explore-agent-system.md +585 -0
  35. agents/default/system_prompt.md +1448 -0
  36. agents/kollabor/__init__.py +0 -0
  37. agents/kollabor/analyze-plugin-lifecycle.md +175 -0
  38. agents/kollabor/analyze-terminal-rendering.md +388 -0
  39. agents/kollabor/code-review.md +1092 -0
  40. agents/kollabor/debug-mcp-integration.md +521 -0
  41. agents/kollabor/debug-plugin-hooks.md +547 -0
  42. agents/kollabor/debugging.md +1102 -0
  43. agents/kollabor/dependency-management.md +1397 -0
  44. agents/kollabor/git-workflow.md +1099 -0
  45. agents/kollabor/inspect-llm-conversation.md +148 -0
  46. agents/kollabor/monitor-event-bus.md +558 -0
  47. agents/kollabor/profile-performance.md +576 -0
  48. agents/kollabor/refactoring.md +1454 -0
  49. agents/kollabor/system_prompt copy.md +1448 -0
  50. agents/kollabor/system_prompt.md +757 -0
  51. agents/kollabor/trace-command-execution.md +178 -0
  52. agents/kollabor/validate-config.md +879 -0
  53. agents/research/__init__.py +0 -0
  54. agents/research/agent.json +4 -0
  55. agents/research/architecture-mapping.md +1099 -0
  56. agents/research/codebase-analysis.md +1077 -0
  57. agents/research/dependency-audit.md +1027 -0
  58. agents/research/performance-profiling.md +1047 -0
  59. agents/research/security-review.md +1359 -0
  60. agents/research/system_prompt.md +492 -0
  61. agents/technical-writer/__init__.py +0 -0
  62. agents/technical-writer/agent.json +4 -0
  63. agents/technical-writer/api-documentation.md +2328 -0
  64. agents/technical-writer/changelog-management.md +1181 -0
  65. agents/technical-writer/readme-writing.md +1360 -0
  66. agents/technical-writer/style-guide.md +1410 -0
  67. agents/technical-writer/system_prompt.md +653 -0
  68. agents/technical-writer/tutorial-creation.md +1448 -0
  69. core/__init__.py +0 -2
  70. core/application.py +343 -88
  71. core/cli.py +229 -10
  72. core/commands/menu_renderer.py +463 -59
  73. core/commands/registry.py +14 -9
  74. core/commands/system_commands.py +2461 -14
  75. core/config/loader.py +151 -37
  76. core/config/service.py +18 -6
  77. core/events/bus.py +29 -9
  78. core/events/executor.py +205 -75
  79. core/events/models.py +27 -8
  80. core/fullscreen/command_integration.py +20 -24
  81. core/fullscreen/components/__init__.py +10 -1
  82. core/fullscreen/components/matrix_components.py +1 -2
  83. core/fullscreen/components/space_shooter_components.py +654 -0
  84. core/fullscreen/plugin.py +5 -0
  85. core/fullscreen/renderer.py +52 -13
  86. core/fullscreen/session.py +52 -15
  87. core/io/__init__.py +29 -5
  88. core/io/buffer_manager.py +6 -1
  89. core/io/config_status_view.py +7 -29
  90. core/io/core_status_views.py +267 -347
  91. core/io/input/__init__.py +25 -0
  92. core/io/input/command_mode_handler.py +711 -0
  93. core/io/input/display_controller.py +128 -0
  94. core/io/input/hook_registrar.py +286 -0
  95. core/io/input/input_loop_manager.py +421 -0
  96. core/io/input/key_press_handler.py +502 -0
  97. core/io/input/modal_controller.py +1011 -0
  98. core/io/input/paste_processor.py +339 -0
  99. core/io/input/status_modal_renderer.py +184 -0
  100. core/io/input_errors.py +5 -1
  101. core/io/input_handler.py +211 -2452
  102. core/io/key_parser.py +7 -0
  103. core/io/layout.py +15 -3
  104. core/io/message_coordinator.py +111 -2
  105. core/io/message_renderer.py +129 -4
  106. core/io/status_renderer.py +147 -607
  107. core/io/terminal_renderer.py +97 -51
  108. core/io/terminal_state.py +21 -4
  109. core/io/visual_effects.py +816 -165
  110. core/llm/agent_manager.py +1063 -0
  111. core/llm/api_adapters/__init__.py +44 -0
  112. core/llm/api_adapters/anthropic_adapter.py +432 -0
  113. core/llm/api_adapters/base.py +241 -0
  114. core/llm/api_adapters/openai_adapter.py +326 -0
  115. core/llm/api_communication_service.py +167 -113
  116. core/llm/conversation_logger.py +322 -16
  117. core/llm/conversation_manager.py +556 -30
  118. core/llm/file_operations_executor.py +84 -32
  119. core/llm/llm_service.py +934 -103
  120. core/llm/mcp_integration.py +541 -57
  121. core/llm/message_display_service.py +135 -18
  122. core/llm/plugin_sdk.py +1 -2
  123. core/llm/profile_manager.py +1183 -0
  124. core/llm/response_parser.py +274 -56
  125. core/llm/response_processor.py +16 -3
  126. core/llm/tool_executor.py +6 -1
  127. core/logging/__init__.py +2 -0
  128. core/logging/setup.py +34 -6
  129. core/models/resume.py +54 -0
  130. core/plugins/__init__.py +4 -2
  131. core/plugins/base.py +127 -0
  132. core/plugins/collector.py +23 -161
  133. core/plugins/discovery.py +37 -3
  134. core/plugins/factory.py +6 -12
  135. core/plugins/registry.py +5 -17
  136. core/ui/config_widgets.py +128 -28
  137. core/ui/live_modal_renderer.py +2 -1
  138. core/ui/modal_actions.py +5 -0
  139. core/ui/modal_overlay_renderer.py +0 -60
  140. core/ui/modal_renderer.py +268 -7
  141. core/ui/modal_state_manager.py +29 -4
  142. core/ui/widgets/base_widget.py +7 -0
  143. core/updates/__init__.py +10 -0
  144. core/updates/version_check_service.py +348 -0
  145. core/updates/version_comparator.py +103 -0
  146. core/utils/config_utils.py +685 -526
  147. core/utils/plugin_utils.py +1 -1
  148. core/utils/session_naming.py +111 -0
  149. fonts/LICENSE +21 -0
  150. fonts/README.md +46 -0
  151. fonts/SymbolsNerdFont-Regular.ttf +0 -0
  152. fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
  153. fonts/__init__.py +44 -0
  154. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
  155. kollabor-0.4.15.dist-info/RECORD +228 -0
  156. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
  157. plugins/agent_orchestrator/__init__.py +39 -0
  158. plugins/agent_orchestrator/activity_monitor.py +181 -0
  159. plugins/agent_orchestrator/file_attacher.py +77 -0
  160. plugins/agent_orchestrator/message_injector.py +135 -0
  161. plugins/agent_orchestrator/models.py +48 -0
  162. plugins/agent_orchestrator/orchestrator.py +403 -0
  163. plugins/agent_orchestrator/plugin.py +976 -0
  164. plugins/agent_orchestrator/xml_parser.py +191 -0
  165. plugins/agent_orchestrator_plugin.py +9 -0
  166. plugins/enhanced_input/box_styles.py +1 -0
  167. plugins/enhanced_input/color_engine.py +19 -4
  168. plugins/enhanced_input/config.py +2 -2
  169. plugins/enhanced_input_plugin.py +61 -11
  170. plugins/fullscreen/__init__.py +6 -2
  171. plugins/fullscreen/example_plugin.py +1035 -222
  172. plugins/fullscreen/setup_wizard_plugin.py +592 -0
  173. plugins/fullscreen/space_shooter_plugin.py +131 -0
  174. plugins/hook_monitoring_plugin.py +436 -78
  175. plugins/query_enhancer_plugin.py +66 -30
  176. plugins/resume_conversation_plugin.py +1494 -0
  177. plugins/save_conversation_plugin.py +98 -32
  178. plugins/system_commands_plugin.py +70 -56
  179. plugins/tmux_plugin.py +154 -78
  180. plugins/workflow_enforcement_plugin.py +94 -92
  181. system_prompt/default.md +952 -886
  182. core/io/input_mode_manager.py +0 -402
  183. core/io/modal_interaction_handler.py +0 -315
  184. core/io/raw_input_processor.py +0 -946
  185. core/storage/__init__.py +0 -5
  186. core/storage/state_manager.py +0 -84
  187. core/ui/widget_integration.py +0 -222
  188. core/utils/key_reader.py +0 -171
  189. kollabor-0.4.9.dist-info/RECORD +0 -128
  190. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
  191. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
  192. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
@@ -8,6 +8,8 @@ single responsibility for message display orchestration.
8
8
  import logging
9
9
  from typing import Any, Dict, List, Optional, Tuple
10
10
 
11
+ from core.io.visual_effects import ColorPalette
12
+
11
13
  logger = logging.getLogger(__name__)
12
14
 
13
15
 
@@ -68,8 +70,8 @@ class MessageDisplayService:
68
70
 
69
71
  # Format tool execution display with consistent styling
70
72
  tool_display = self._format_tool_header(result, tool_data)
71
- result_display = self._format_tool_result(result)
72
-
73
+ result_display = self._format_tool_result(result, tool_data)
74
+
73
75
  # Build combined tool display message
74
76
  combined_output = [tool_display, result_display]
75
77
 
@@ -154,21 +156,64 @@ class MessageDisplayService:
154
156
  Returns:
155
157
  Formatted tool header string
156
158
  """
159
+ # Tool indicator with dynamic color support
160
+ indicator = f"{ColorPalette.BRIGHT_LIME}⏺{ColorPalette.RESET}"
161
+
157
162
  if result.tool_type == "terminal":
158
163
  # Extract actual command from original tool data
159
164
  command = tool_data.get("command", "unknown") if tool_data else result.tool_id
160
- return f"\033[1;33m⟣\033[0m terminal({command})"
165
+ return f"{indicator} terminal({command})"
161
166
  elif result.tool_type == "mcp_tool":
162
167
  # Extract tool name and arguments from original tool data
163
168
  tool_name = tool_data.get("name", "unknown") if tool_data else result.tool_id
164
169
  arguments = tool_data.get("arguments", {}) if tool_data else {}
165
- return f"\033[1;33m⟣\033[0m {tool_name}({arguments})"
170
+
171
+ # Clean up malformed tool names (may contain XML from confused LLM)
172
+ if '<' in tool_name or '>' in tool_name:
173
+ import re
174
+ # Try to extract clean tool name
175
+ match = re.search(r'<tool_call>([^<]+)', tool_name)
176
+ if match:
177
+ tool_name = match.group(1).strip()
178
+ else:
179
+ # Find last word that looks like a tool name
180
+ words = re.findall(r'\b([a-z_]+)\b', tool_name.lower())
181
+ tool_name = words[-1] if words else "mcp_tool"
182
+
183
+ # For Read-like tools, show file path with line info
184
+ if tool_name.lower() in ("read", "file_read", "readfile"):
185
+ file_path = arguments.get("file_path") or arguments.get("path") or arguments.get("file", "")
186
+ offset = arguments.get("offset")
187
+ limit = arguments.get("limit")
188
+ if offset is not None or limit is not None:
189
+ offset_val = offset if offset is not None else 0
190
+ if limit:
191
+ return f"{indicator} {tool_name}({file_path}, lines {offset_val + 1}-{offset_val + limit})"
192
+ else:
193
+ return f"{indicator} {tool_name}({file_path}, from line {offset_val + 1})"
194
+ return f"{indicator} {tool_name}({file_path})"
195
+
196
+ # Format arguments cleanly
197
+ if arguments:
198
+ # Show key arguments inline, truncate long values
199
+ arg_parts = []
200
+ for k, v in list(arguments.items())[:3]: # Max 3 args
201
+ v_str = str(v)
202
+ if len(v_str) > 30:
203
+ v_str = v_str[:27] + "..."
204
+ arg_parts.append(f'{k}="{v_str}"')
205
+ args_display = ", ".join(arg_parts)
206
+ if len(arguments) > 3:
207
+ args_display += f", +{len(arguments) - 3} more"
208
+ return f"{indicator} {tool_name}({args_display})"
209
+ else:
210
+ return f"{indicator} {tool_name}()"
166
211
  elif result.tool_type.startswith("file_"):
167
212
  # Extract filename/path from file operation data
168
213
  display_info = self._extract_file_display_info(tool_data, result.tool_type)
169
- return f"\033[1;33m⟣\033[0m {result.tool_type}({display_info})"
214
+ return f"{indicator} {result.tool_type}({display_info})"
170
215
  else:
171
- return f"\033[1;33m⟣\033[0m {result.tool_type}({result.tool_id})"
216
+ return f"{indicator} {result.tool_type}({result.tool_id})"
172
217
 
173
218
  def _extract_file_display_info(self, tool_data: Dict, tool_type: str) -> str:
174
219
  """Extract display information from file operation data.
@@ -197,11 +242,12 @@ class MessageDisplayService:
197
242
 
198
243
  return "unknown"
199
244
 
200
- def _format_tool_result(self, result) -> str:
245
+ def _format_tool_result(self, result, tool_data: Dict = None) -> str:
201
246
  """Format tool execution result summary.
202
247
 
203
248
  Args:
204
249
  result: Tool execution result
250
+ tool_data: Original tool data for request info (optional)
205
251
 
206
252
  Returns:
207
253
  Formatted result summary string
@@ -214,15 +260,60 @@ class MessageDisplayService:
214
260
  if result.tool_type == "terminal" and result.output:
215
261
  return f"\033[32m ▮ Read {output_lines} lines ({output_chars} chars)\033[0m"
216
262
  elif result.tool_type == "file_read" and result.output:
217
- # Extract line count from output message "✓ Read X lines from..."
263
+ # Extract line count and optional range from output
264
+ # Format: "✓ Read X lines from path (lines N-M):" or "✓ Read X lines from path:"
218
265
  import re
219
- match = re.search(r'Read (\d+) lines', result.output)
266
+ match = re.search(r'Read (\d+) lines from .+?(?:\(lines ([^)]+)\))?:', result.output)
220
267
  if match:
221
268
  line_count = match.group(1)
269
+ lines_from_output = match.group(2) # May be None
270
+
271
+ # Build line range from various sources
272
+ lines_spec = None
273
+ if lines_from_output:
274
+ lines_spec = lines_from_output
275
+ elif tool_data:
276
+ if tool_data.get("lines"):
277
+ lines_spec = tool_data["lines"]
278
+ elif tool_data.get("offset") is not None or tool_data.get("limit") is not None:
279
+ # Calculate range from offset/limit
280
+ offset = tool_data.get("offset", 0)
281
+ limit = tool_data.get("limit")
282
+ start = offset + 1 # 1-indexed for display
283
+ if limit:
284
+ lines_spec = f"{start}-{start + int(line_count) - 1}"
285
+ else:
286
+ lines_spec = f"{start}+"
287
+
288
+ if lines_spec:
289
+ return f"\033[32m ▮ Read {line_count} lines (lines {lines_spec})\033[0m"
222
290
  return f"\033[32m ▮ Read {line_count} lines\033[0m"
223
291
  return f"\033[32m ▮ Success\033[0m"
224
292
  elif result.tool_type == "mcp_tool" and result.output:
225
- preview = result.output[:50] + "..." if len(result.output) > 50 else result.output
293
+ # Try to summarize JSON output
294
+ try:
295
+ import json
296
+ data = json.loads(result.output)
297
+ if isinstance(data, dict):
298
+ # Count items in response
299
+ if "content" in data:
300
+ content = data["content"]
301
+ if isinstance(content, list):
302
+ return f"\033[32m ▮ Returned {len(content)} items\033[0m"
303
+ elif isinstance(content, str):
304
+ preview = content[:40] + "..." if len(content) > 40 else content
305
+ return f"\033[32m ▮ {preview}\033[0m"
306
+ # Count top-level keys
307
+ keys = list(data.keys())[:3]
308
+ return f"\033[32m ▮ Returned {{{', '.join(keys)}{'...' if len(data) > 3 else ''}}}\033[0m"
309
+ elif isinstance(data, list):
310
+ return f"\033[32m ▮ Returned {len(data)} items\033[0m"
311
+ except (json.JSONDecodeError, TypeError):
312
+ pass
313
+ # Fallback to text preview
314
+ preview = result.output[:50].replace('\n', ' ')
315
+ if len(result.output) > 50:
316
+ preview += "..."
226
317
  return f"\033[32m ▮ {preview}\033[0m"
227
318
  else:
228
319
  return f"\033[32m ▮ Success\033[0m"
@@ -286,6 +377,7 @@ class MessageDisplayService:
286
377
  find_text = diff_info.get('find', '')
287
378
  replace_text = diff_info.get('replace', '')
288
379
  count = diff_info.get('count', 0)
380
+ line_numbers = diff_info.get('lines', []) # First few line numbers where edit occurred
289
381
 
290
382
  formatted_lines = []
291
383
 
@@ -296,10 +388,17 @@ class MessageDisplayService:
296
388
  # Add pretty diff visualization
297
389
  formatted_lines.append("")
298
390
 
299
- # Removed lines (red with -)
391
+ # Calculate starting line number for display
392
+ start_line = line_numbers[0] if line_numbers else None
393
+
394
+ # Removed lines (red with -) with line numbers
300
395
  removed_lines = find_text.split('\n')
301
- for line in removed_lines[:3]: # Show max 3 lines
302
- formatted_lines.append(f" \033[31m│- {line}\033[0m")
396
+ for i, line in enumerate(removed_lines[:3]): # Show max 3 lines
397
+ if start_line:
398
+ line_num = start_line + i
399
+ formatted_lines.append(f" \033[31m│- {line_num:4d} {line}\033[0m")
400
+ else:
401
+ formatted_lines.append(f" \033[31m│- {line}\033[0m")
303
402
 
304
403
  if len(removed_lines) > 3:
305
404
  formatted_lines.append(f" \033[31m│ ... ({len(removed_lines) - 3} more lines)\033[0m")
@@ -307,10 +406,14 @@ class MessageDisplayService:
307
406
  # Separator
308
407
  formatted_lines.append(" \033[90m│\033[0m")
309
408
 
310
- # Added lines (green with +)
409
+ # Added lines (green with +) with line numbers
311
410
  added_lines = replace_text.split('\n')
312
- for line in added_lines[:3]: # Show max 3 lines
313
- formatted_lines.append(f" \033[32m│+ {line}\033[0m")
411
+ for i, line in enumerate(added_lines[:3]): # Show max 3 lines
412
+ if start_line:
413
+ line_num = start_line + i
414
+ formatted_lines.append(f" \033[32m│+ {line_num:4d} {line}\033[0m")
415
+ else:
416
+ formatted_lines.append(f" \033[32m│+ {line}\033[0m")
314
417
 
315
418
  if len(added_lines) > 3:
316
419
  formatted_lines.append(f" \033[32m│ ... ({len(added_lines) - 3} more lines)\033[0m")
@@ -341,7 +444,21 @@ class MessageDisplayService:
341
444
  """Clear thinking/generating display."""
342
445
  self.renderer.update_thinking(False)
343
446
  logger.debug("Cleared thinking display")
344
-
447
+
448
+ def show_loading(self, message: str = "Loading...") -> None:
449
+ """Show loading indicator with custom message.
450
+
451
+ Args:
452
+ message: Loading message to display (default: "Loading...")
453
+ """
454
+ self.renderer.update_thinking(True, message)
455
+ logger.debug(f"Showing loading: {message}")
456
+
457
+ def hide_loading(self) -> None:
458
+ """Hide loading indicator."""
459
+ self.renderer.update_thinking(False)
460
+ logger.debug("Hiding loading indicator")
461
+
345
462
  def start_streaming_response(self) -> None:
346
463
  """Start a streaming response session.
347
464
 
@@ -409,7 +526,7 @@ class MessageDisplayService:
409
526
 
410
527
  # Format tool execution display with consistent styling
411
528
  tool_display = self._format_tool_header(result, tool_data)
412
- result_display = self._format_tool_result(result)
529
+ result_display = self._format_tool_result(result, tool_data)
413
530
 
414
531
  # Build combined tool display message
415
532
  combined_output = [tool_display, result_display]
core/llm/plugin_sdk.py CHANGED
@@ -45,10 +45,9 @@ class {class_name}:
45
45
  }}
46
46
  }}
47
47
 
48
- def __init__(self, name: str, state_manager, event_bus, renderer, config):
48
+ def __init__(self, name: str, event_bus, renderer, config):
49
49
  """Initialize the plugin."""
50
50
  self.name = name
51
- self.state_manager = state_manager
52
51
  self.event_bus = event_bus
53
52
  self.renderer = renderer
54
53
  self.config = config