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.
- agents/__init__.py +2 -0
- agents/coder/__init__.py +0 -0
- agents/coder/agent.json +4 -0
- agents/coder/api-integration.md +2150 -0
- agents/coder/cli-pretty.md +765 -0
- agents/coder/code-review.md +1092 -0
- agents/coder/database-design.md +1525 -0
- agents/coder/debugging.md +1102 -0
- agents/coder/dependency-management.md +1397 -0
- agents/coder/git-workflow.md +1099 -0
- agents/coder/refactoring.md +1454 -0
- agents/coder/security-hardening.md +1732 -0
- agents/coder/system_prompt.md +1448 -0
- agents/coder/tdd.md +1367 -0
- agents/creative-writer/__init__.py +0 -0
- agents/creative-writer/agent.json +4 -0
- agents/creative-writer/character-development.md +1852 -0
- agents/creative-writer/dialogue-craft.md +1122 -0
- agents/creative-writer/plot-structure.md +1073 -0
- agents/creative-writer/revision-editing.md +1484 -0
- agents/creative-writer/system_prompt.md +690 -0
- agents/creative-writer/worldbuilding.md +2049 -0
- agents/data-analyst/__init__.py +30 -0
- agents/data-analyst/agent.json +4 -0
- agents/data-analyst/data-visualization.md +992 -0
- agents/data-analyst/exploratory-data-analysis.md +1110 -0
- agents/data-analyst/pandas-data-manipulation.md +1081 -0
- agents/data-analyst/sql-query-optimization.md +881 -0
- agents/data-analyst/statistical-analysis.md +1118 -0
- agents/data-analyst/system_prompt.md +928 -0
- agents/default/__init__.py +0 -0
- agents/default/agent.json +4 -0
- agents/default/dead-code.md +794 -0
- agents/default/explore-agent-system.md +585 -0
- agents/default/system_prompt.md +1448 -0
- agents/kollabor/__init__.py +0 -0
- agents/kollabor/analyze-plugin-lifecycle.md +175 -0
- agents/kollabor/analyze-terminal-rendering.md +388 -0
- agents/kollabor/code-review.md +1092 -0
- agents/kollabor/debug-mcp-integration.md +521 -0
- agents/kollabor/debug-plugin-hooks.md +547 -0
- agents/kollabor/debugging.md +1102 -0
- agents/kollabor/dependency-management.md +1397 -0
- agents/kollabor/git-workflow.md +1099 -0
- agents/kollabor/inspect-llm-conversation.md +148 -0
- agents/kollabor/monitor-event-bus.md +558 -0
- agents/kollabor/profile-performance.md +576 -0
- agents/kollabor/refactoring.md +1454 -0
- agents/kollabor/system_prompt copy.md +1448 -0
- agents/kollabor/system_prompt.md +757 -0
- agents/kollabor/trace-command-execution.md +178 -0
- agents/kollabor/validate-config.md +879 -0
- agents/research/__init__.py +0 -0
- agents/research/agent.json +4 -0
- agents/research/architecture-mapping.md +1099 -0
- agents/research/codebase-analysis.md +1077 -0
- agents/research/dependency-audit.md +1027 -0
- agents/research/performance-profiling.md +1047 -0
- agents/research/security-review.md +1359 -0
- agents/research/system_prompt.md +492 -0
- agents/technical-writer/__init__.py +0 -0
- agents/technical-writer/agent.json +4 -0
- agents/technical-writer/api-documentation.md +2328 -0
- agents/technical-writer/changelog-management.md +1181 -0
- agents/technical-writer/readme-writing.md +1360 -0
- agents/technical-writer/style-guide.md +1410 -0
- agents/technical-writer/system_prompt.md +653 -0
- agents/technical-writer/tutorial-creation.md +1448 -0
- core/__init__.py +0 -2
- core/application.py +343 -88
- core/cli.py +229 -10
- core/commands/menu_renderer.py +463 -59
- core/commands/registry.py +14 -9
- core/commands/system_commands.py +2461 -14
- core/config/loader.py +151 -37
- core/config/service.py +18 -6
- core/events/bus.py +29 -9
- core/events/executor.py +205 -75
- core/events/models.py +27 -8
- core/fullscreen/command_integration.py +20 -24
- core/fullscreen/components/__init__.py +10 -1
- core/fullscreen/components/matrix_components.py +1 -2
- core/fullscreen/components/space_shooter_components.py +654 -0
- core/fullscreen/plugin.py +5 -0
- core/fullscreen/renderer.py +52 -13
- core/fullscreen/session.py +52 -15
- core/io/__init__.py +29 -5
- core/io/buffer_manager.py +6 -1
- core/io/config_status_view.py +7 -29
- core/io/core_status_views.py +267 -347
- core/io/input/__init__.py +25 -0
- core/io/input/command_mode_handler.py +711 -0
- core/io/input/display_controller.py +128 -0
- core/io/input/hook_registrar.py +286 -0
- core/io/input/input_loop_manager.py +421 -0
- core/io/input/key_press_handler.py +502 -0
- core/io/input/modal_controller.py +1011 -0
- core/io/input/paste_processor.py +339 -0
- core/io/input/status_modal_renderer.py +184 -0
- core/io/input_errors.py +5 -1
- core/io/input_handler.py +211 -2452
- core/io/key_parser.py +7 -0
- core/io/layout.py +15 -3
- core/io/message_coordinator.py +111 -2
- core/io/message_renderer.py +129 -4
- core/io/status_renderer.py +147 -607
- core/io/terminal_renderer.py +97 -51
- core/io/terminal_state.py +21 -4
- core/io/visual_effects.py +816 -165
- core/llm/agent_manager.py +1063 -0
- core/llm/api_adapters/__init__.py +44 -0
- core/llm/api_adapters/anthropic_adapter.py +432 -0
- core/llm/api_adapters/base.py +241 -0
- core/llm/api_adapters/openai_adapter.py +326 -0
- core/llm/api_communication_service.py +167 -113
- core/llm/conversation_logger.py +322 -16
- core/llm/conversation_manager.py +556 -30
- core/llm/file_operations_executor.py +84 -32
- core/llm/llm_service.py +934 -103
- core/llm/mcp_integration.py +541 -57
- core/llm/message_display_service.py +135 -18
- core/llm/plugin_sdk.py +1 -2
- core/llm/profile_manager.py +1183 -0
- core/llm/response_parser.py +274 -56
- core/llm/response_processor.py +16 -3
- core/llm/tool_executor.py +6 -1
- core/logging/__init__.py +2 -0
- core/logging/setup.py +34 -6
- core/models/resume.py +54 -0
- core/plugins/__init__.py +4 -2
- core/plugins/base.py +127 -0
- core/plugins/collector.py +23 -161
- core/plugins/discovery.py +37 -3
- core/plugins/factory.py +6 -12
- core/plugins/registry.py +5 -17
- core/ui/config_widgets.py +128 -28
- core/ui/live_modal_renderer.py +2 -1
- core/ui/modal_actions.py +5 -0
- core/ui/modal_overlay_renderer.py +0 -60
- core/ui/modal_renderer.py +268 -7
- core/ui/modal_state_manager.py +29 -4
- core/ui/widgets/base_widget.py +7 -0
- core/updates/__init__.py +10 -0
- core/updates/version_check_service.py +348 -0
- core/updates/version_comparator.py +103 -0
- core/utils/config_utils.py +685 -526
- core/utils/plugin_utils.py +1 -1
- core/utils/session_naming.py +111 -0
- fonts/LICENSE +21 -0
- fonts/README.md +46 -0
- fonts/SymbolsNerdFont-Regular.ttf +0 -0
- fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
- fonts/__init__.py +44 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
- kollabor-0.4.15.dist-info/RECORD +228 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
- plugins/agent_orchestrator/__init__.py +39 -0
- plugins/agent_orchestrator/activity_monitor.py +181 -0
- plugins/agent_orchestrator/file_attacher.py +77 -0
- plugins/agent_orchestrator/message_injector.py +135 -0
- plugins/agent_orchestrator/models.py +48 -0
- plugins/agent_orchestrator/orchestrator.py +403 -0
- plugins/agent_orchestrator/plugin.py +976 -0
- plugins/agent_orchestrator/xml_parser.py +191 -0
- plugins/agent_orchestrator_plugin.py +9 -0
- plugins/enhanced_input/box_styles.py +1 -0
- plugins/enhanced_input/color_engine.py +19 -4
- plugins/enhanced_input/config.py +2 -2
- plugins/enhanced_input_plugin.py +61 -11
- plugins/fullscreen/__init__.py +6 -2
- plugins/fullscreen/example_plugin.py +1035 -222
- plugins/fullscreen/setup_wizard_plugin.py +592 -0
- plugins/fullscreen/space_shooter_plugin.py +131 -0
- plugins/hook_monitoring_plugin.py +436 -78
- plugins/query_enhancer_plugin.py +66 -30
- plugins/resume_conversation_plugin.py +1494 -0
- plugins/save_conversation_plugin.py +98 -32
- plugins/system_commands_plugin.py +70 -56
- plugins/tmux_plugin.py +154 -78
- plugins/workflow_enforcement_plugin.py +94 -92
- system_prompt/default.md +952 -886
- core/io/input_mode_manager.py +0 -402
- core/io/modal_interaction_handler.py +0 -315
- core/io/raw_input_processor.py +0 -946
- core/storage/__init__.py +0 -5
- core/storage/state_manager.py +0 -84
- core/ui/widget_integration.py +0 -222
- core/utils/key_reader.py +0 -171
- kollabor-0.4.9.dist-info/RECORD +0 -128
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""Parse XML agent commands from LLM response text."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
from .models import AgentTask, ParsedCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class XMLCommandParser:
|
|
10
|
+
"""Parse XML agent commands from LLM response text."""
|
|
11
|
+
|
|
12
|
+
def parse(self, text: str) -> List[ParsedCommand]:
|
|
13
|
+
"""Extract all agent commands from text."""
|
|
14
|
+
commands = []
|
|
15
|
+
|
|
16
|
+
# <agent>...</agent>
|
|
17
|
+
commands.extend(self._parse_agent_blocks(text))
|
|
18
|
+
|
|
19
|
+
# <message to="name">content</message>
|
|
20
|
+
commands.extend(self._parse_messages(text))
|
|
21
|
+
|
|
22
|
+
# <stop>name</stop>
|
|
23
|
+
commands.extend(self._parse_stops(text))
|
|
24
|
+
|
|
25
|
+
# <status />
|
|
26
|
+
commands.extend(self._parse_status(text))
|
|
27
|
+
|
|
28
|
+
# <capture>name lines</capture>
|
|
29
|
+
commands.extend(self._parse_captures(text))
|
|
30
|
+
|
|
31
|
+
# <clone>...</clone>
|
|
32
|
+
commands.extend(self._parse_clones(text))
|
|
33
|
+
|
|
34
|
+
# <team>...</team>
|
|
35
|
+
commands.extend(self._parse_teams(text))
|
|
36
|
+
|
|
37
|
+
# <broadcast to="pattern">content</broadcast>
|
|
38
|
+
commands.extend(self._parse_broadcasts(text))
|
|
39
|
+
|
|
40
|
+
return commands
|
|
41
|
+
|
|
42
|
+
def _parse_agent_blocks(self, text: str) -> List[ParsedCommand]:
|
|
43
|
+
"""Parse <agent>...</agent> blocks."""
|
|
44
|
+
commands = []
|
|
45
|
+
pattern = r"<agent>(.*?)</agent>"
|
|
46
|
+
|
|
47
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
48
|
+
block = match.group(1)
|
|
49
|
+
agents = self._parse_agent_definitions(block)
|
|
50
|
+
if agents:
|
|
51
|
+
commands.append(ParsedCommand(type="agent", agents=agents))
|
|
52
|
+
|
|
53
|
+
return commands
|
|
54
|
+
|
|
55
|
+
def _parse_agent_definitions(self, block: str) -> List[AgentTask]:
|
|
56
|
+
"""Parse individual agent definitions within <agent> block."""
|
|
57
|
+
agents = []
|
|
58
|
+
|
|
59
|
+
# Match <name>...</name> pattern (agent name is the tag name)
|
|
60
|
+
# Use negative lookahead to avoid matching <task>, <files>, <file>
|
|
61
|
+
pattern = r"<((?!task|files|file|todo|goal|n\d)\w[\w-]*)>(.*?)</\1>"
|
|
62
|
+
|
|
63
|
+
for match in re.finditer(pattern, block, re.DOTALL):
|
|
64
|
+
name = match.group(1)
|
|
65
|
+
content = match.group(2)
|
|
66
|
+
|
|
67
|
+
# Extract <task>...</task>
|
|
68
|
+
task_match = re.search(r"<task>(.*?)</task>", content, re.DOTALL)
|
|
69
|
+
task = task_match.group(1).strip() if task_match else ""
|
|
70
|
+
|
|
71
|
+
# Extract <files>...</files>
|
|
72
|
+
files = []
|
|
73
|
+
files_match = re.search(r"<files>(.*?)</files>", content, re.DOTALL)
|
|
74
|
+
if files_match:
|
|
75
|
+
file_pattern = r"<file>(.*?)</file>"
|
|
76
|
+
files = [f.strip() for f in re.findall(file_pattern, files_match.group(1))]
|
|
77
|
+
|
|
78
|
+
agents.append(AgentTask(name=name, task=task, files=files))
|
|
79
|
+
|
|
80
|
+
return agents
|
|
81
|
+
|
|
82
|
+
def _parse_messages(self, text: str) -> List[ParsedCommand]:
|
|
83
|
+
"""Parse <message to="name">content</message>."""
|
|
84
|
+
commands = []
|
|
85
|
+
pattern = r'<message\s+to=["\']([^"\']+)["\']>(.*?)</message>'
|
|
86
|
+
|
|
87
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
88
|
+
target = match.group(1)
|
|
89
|
+
content = match.group(2).strip()
|
|
90
|
+
commands.append(
|
|
91
|
+
ParsedCommand(type="message", target=target, content=content)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return commands
|
|
95
|
+
|
|
96
|
+
def _parse_stops(self, text: str) -> List[ParsedCommand]:
|
|
97
|
+
"""Parse <stop>name</stop> or <stop>name1, name2</stop>."""
|
|
98
|
+
commands = []
|
|
99
|
+
pattern = r"<stop>(.*?)</stop>"
|
|
100
|
+
|
|
101
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
102
|
+
content = match.group(1).strip()
|
|
103
|
+
# Split by comma or whitespace
|
|
104
|
+
targets = [t.strip() for t in re.split(r"[,\s]+", content) if t.strip()]
|
|
105
|
+
if targets:
|
|
106
|
+
commands.append(ParsedCommand(type="stop", targets=targets))
|
|
107
|
+
|
|
108
|
+
return commands
|
|
109
|
+
|
|
110
|
+
def _parse_status(self, text: str) -> List[ParsedCommand]:
|
|
111
|
+
"""Parse <status></status> - requires proper open AND close tag."""
|
|
112
|
+
# Must have both opening and closing tag - ignores mentions in prose
|
|
113
|
+
if re.search(r"<status>\s*</status>", text):
|
|
114
|
+
return [ParsedCommand(type="status")]
|
|
115
|
+
return []
|
|
116
|
+
|
|
117
|
+
def _parse_captures(self, text: str) -> List[ParsedCommand]:
|
|
118
|
+
"""Parse <capture>name [lines]</capture>."""
|
|
119
|
+
commands = []
|
|
120
|
+
pattern = r"<capture>(.*?)</capture>"
|
|
121
|
+
|
|
122
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
123
|
+
content = match.group(1).strip()
|
|
124
|
+
parts = content.split()
|
|
125
|
+
|
|
126
|
+
target = parts[0] if parts else ""
|
|
127
|
+
lines = 50 # default
|
|
128
|
+
|
|
129
|
+
if len(parts) > 1:
|
|
130
|
+
try:
|
|
131
|
+
lines = int(parts[-1])
|
|
132
|
+
# If last part is a number, target might be comma-separated names
|
|
133
|
+
target = " ".join(parts[:-1]).replace(",", "").strip()
|
|
134
|
+
except ValueError:
|
|
135
|
+
# Last part is not a number, everything is the target
|
|
136
|
+
target = content
|
|
137
|
+
|
|
138
|
+
if target:
|
|
139
|
+
commands.append(
|
|
140
|
+
ParsedCommand(type="capture", target=target, lines=lines)
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return commands
|
|
144
|
+
|
|
145
|
+
def _parse_clones(self, text: str) -> List[ParsedCommand]:
|
|
146
|
+
"""Parse <clone>...</clone> blocks."""
|
|
147
|
+
commands = []
|
|
148
|
+
pattern = r"<clone>(.*?)</clone>"
|
|
149
|
+
|
|
150
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
151
|
+
block = match.group(1)
|
|
152
|
+
agents = self._parse_agent_definitions(block)
|
|
153
|
+
for agent in agents:
|
|
154
|
+
commands.append(
|
|
155
|
+
ParsedCommand(type="clone", agents=[agent], conversation=True)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return commands
|
|
159
|
+
|
|
160
|
+
def _parse_teams(self, text: str) -> List[ParsedCommand]:
|
|
161
|
+
"""Parse <team lead="name" workers="N">...</team>."""
|
|
162
|
+
commands = []
|
|
163
|
+
pattern = r'<team\s+lead=["\']([^"\']+)["\']\s+workers=["\'](\d+)["\']>(.*?)</team>'
|
|
164
|
+
|
|
165
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
166
|
+
lead = match.group(1)
|
|
167
|
+
workers = int(match.group(2))
|
|
168
|
+
content = match.group(3)
|
|
169
|
+
|
|
170
|
+
# Parse task content as if it were an agent definition
|
|
171
|
+
agents = self._parse_agent_definitions(f"<{lead}>{content}</{lead}>")
|
|
172
|
+
|
|
173
|
+
commands.append(
|
|
174
|
+
ParsedCommand(type="team", lead=lead, workers=workers, agents=agents)
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return commands
|
|
178
|
+
|
|
179
|
+
def _parse_broadcasts(self, text: str) -> List[ParsedCommand]:
|
|
180
|
+
"""Parse <broadcast to="pattern">content</broadcast>."""
|
|
181
|
+
commands = []
|
|
182
|
+
pattern = r'<broadcast\s+to=["\']([^"\']+)["\']>(.*?)</broadcast>'
|
|
183
|
+
|
|
184
|
+
for match in re.finditer(pattern, text, re.DOTALL):
|
|
185
|
+
pat = match.group(1)
|
|
186
|
+
content = match.group(2).strip()
|
|
187
|
+
commands.append(
|
|
188
|
+
ParsedCommand(type="broadcast", pattern=pat, content=content)
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return commands
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Agent Orchestrator Plugin - wrapper for plugin discovery.
|
|
2
|
+
|
|
3
|
+
This file exists to enable plugin discovery which looks for *_plugin.py files.
|
|
4
|
+
The actual implementation is in the agent_orchestrator/ directory.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from plugins.agent_orchestrator.plugin import AgentOrchestratorPlugin
|
|
8
|
+
|
|
9
|
+
__all__ = ["AgentOrchestratorPlugin"]
|
|
@@ -99,6 +99,7 @@ class BoxStyleRegistry:
|
|
|
99
99
|
"thick": BoxStyle("┏", "┓", "┗", "┛", "━", "┃"),
|
|
100
100
|
"dotted": BoxStyle("┌", "┐", "└", "┘", "┄", "┆"),
|
|
101
101
|
"dashed": BoxStyle("┌", "┐", "└", "┘", "┅", "┇"),
|
|
102
|
+
"thin": BoxStyle("┌", "┐", "└", "┘", "─", ""),
|
|
102
103
|
|
|
103
104
|
# Minimal styles
|
|
104
105
|
"minimal": BoxStyle(" ", " ", " ", " ", "─", " "),
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import List, Tuple
|
|
4
4
|
|
|
5
|
+
from core.io.visual_effects import get_color_support, ColorSupport, rgb_to_256
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
class ColorEngine:
|
|
7
9
|
"""Handles all color and gradient operations for enhanced input rendering."""
|
|
@@ -132,7 +134,10 @@ class ColorEngine:
|
|
|
132
134
|
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
|
|
133
135
|
|
|
134
136
|
def _rgb_to_ansi(self, r: int, g: int, b: int, is_background: bool = False) -> str:
|
|
135
|
-
"""Convert RGB to ANSI escape code.
|
|
137
|
+
"""Convert RGB to ANSI escape code with automatic fallback.
|
|
138
|
+
|
|
139
|
+
Uses true color (24-bit) when supported, otherwise falls back
|
|
140
|
+
to 256-color palette.
|
|
136
141
|
|
|
137
142
|
Args:
|
|
138
143
|
r: Red component (0-255).
|
|
@@ -143,10 +148,20 @@ class ColorEngine:
|
|
|
143
148
|
Returns:
|
|
144
149
|
ANSI escape sequence.
|
|
145
150
|
"""
|
|
146
|
-
|
|
147
|
-
|
|
151
|
+
support = get_color_support()
|
|
152
|
+
|
|
153
|
+
if support == ColorSupport.TRUE_COLOR:
|
|
154
|
+
if is_background:
|
|
155
|
+
return f"\033[48;2;{r};{g};{b}m"
|
|
156
|
+
else:
|
|
157
|
+
return f"\033[38;2;{r};{g};{b}m"
|
|
148
158
|
else:
|
|
149
|
-
|
|
159
|
+
# Use 256-color fallback
|
|
160
|
+
idx = rgb_to_256(r, g, b)
|
|
161
|
+
if is_background:
|
|
162
|
+
return f"\033[48;5;{idx}m"
|
|
163
|
+
else:
|
|
164
|
+
return f"\033[38;5;{idx}m"
|
|
150
165
|
|
|
151
166
|
def _interpolate_color(self, color1: Tuple[int, int, int], color2: Tuple[int, int, int], factor: float) -> Tuple[int, int, int]:
|
|
152
167
|
"""Interpolate between two RGB colors.
|
plugins/enhanced_input/config.py
CHANGED
|
@@ -20,7 +20,7 @@ class InputConfig:
|
|
|
20
20
|
|
|
21
21
|
# Dimensions
|
|
22
22
|
min_width: int = 60
|
|
23
|
-
max_width: int =
|
|
23
|
+
max_width: int = 80
|
|
24
24
|
min_height: int = 3
|
|
25
25
|
max_height: int = 10
|
|
26
26
|
|
|
@@ -75,7 +75,7 @@ class InputConfig:
|
|
|
75
75
|
show_placeholder=config.get("plugins.enhanced_input.show_placeholder", True),
|
|
76
76
|
|
|
77
77
|
min_width=config.get("plugins.enhanced_input.min_width", 60),
|
|
78
|
-
max_width=config.get("plugins.enhanced_input.max_width",
|
|
78
|
+
max_width=config.get("plugins.enhanced_input.max_width", 100),
|
|
79
79
|
min_height=config.get("plugins.enhanced_input.min_height", 3),
|
|
80
80
|
max_height=config.get("plugins.enhanced_input.max_height", 10),
|
|
81
81
|
|
plugins/enhanced_input_plugin.py
CHANGED
|
@@ -9,6 +9,8 @@ import sys
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Any, Dict, List, TYPE_CHECKING
|
|
11
11
|
|
|
12
|
+
from core.io.visual_effects import AgnosterSegment
|
|
13
|
+
|
|
12
14
|
logger = logging.getLogger(__name__)
|
|
13
15
|
|
|
14
16
|
# Add parent directory to path so we can import from chat_app
|
|
@@ -29,7 +31,6 @@ from plugins.enhanced_input.box_renderer import BoxRenderer
|
|
|
29
31
|
# Type hints (only needed for type checking)
|
|
30
32
|
if TYPE_CHECKING:
|
|
31
33
|
from core.config import ConfigManager
|
|
32
|
-
from core.storage import StateManager
|
|
33
34
|
from core.events import EventBus
|
|
34
35
|
from core.io.terminal_renderer import TerminalRenderer
|
|
35
36
|
|
|
@@ -80,7 +81,11 @@ class EnhancedInputPlugin:
|
|
|
80
81
|
"type": "dropdown",
|
|
81
82
|
"label": "Box Style",
|
|
82
83
|
"config_path": "plugins.enhanced_input.style",
|
|
83
|
-
"options": [
|
|
84
|
+
"options": [
|
|
85
|
+
"rounded", "square", "double", "thick", "thin",
|
|
86
|
+
"dotted", "dashed", "minimal", "brackets", "underline",
|
|
87
|
+
"lines_only", "dots_only", "mixed_weight", "sophisticated"
|
|
88
|
+
],
|
|
84
89
|
"help": "Visual style of the input box border"
|
|
85
90
|
},
|
|
86
91
|
{
|
|
@@ -180,23 +185,61 @@ class EnhancedInputPlugin:
|
|
|
180
185
|
"label": "Show Status",
|
|
181
186
|
"config_path": "plugins.enhanced_input.show_status",
|
|
182
187
|
"help": "Display status information below input box"
|
|
188
|
+
},
|
|
189
|
+
# Color settings
|
|
190
|
+
{
|
|
191
|
+
"type": "dropdown",
|
|
192
|
+
"label": "Border Color",
|
|
193
|
+
"config_path": "plugins.enhanced_input.colors.border",
|
|
194
|
+
"options": ["dim", "white", "cyan", "green", "yellow", "magenta", "blue", "red"],
|
|
195
|
+
"help": "Color of the input box border"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"type": "dropdown",
|
|
199
|
+
"label": "Text Color",
|
|
200
|
+
"config_path": "plugins.enhanced_input.colors.text",
|
|
201
|
+
"options": ["dim", "white", "cyan", "green", "yellow", "magenta", "blue", "red"],
|
|
202
|
+
"help": "Color of the input text"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"type": "dropdown",
|
|
206
|
+
"label": "Placeholder Color",
|
|
207
|
+
"config_path": "plugins.enhanced_input.colors.placeholder",
|
|
208
|
+
"options": ["dim", "white", "cyan", "green", "yellow", "magenta", "blue"],
|
|
209
|
+
"help": "Color of the placeholder text"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"type": "checkbox",
|
|
213
|
+
"label": "Gradient Mode",
|
|
214
|
+
"config_path": "plugins.enhanced_input.colors.gradient_mode",
|
|
215
|
+
"help": "Enable gradient coloring effects"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"type": "checkbox",
|
|
219
|
+
"label": "Border Gradient",
|
|
220
|
+
"config_path": "plugins.enhanced_input.colors.border_gradient",
|
|
221
|
+
"help": "Apply gradient to border"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"type": "checkbox",
|
|
225
|
+
"label": "Text Gradient",
|
|
226
|
+
"config_path": "plugins.enhanced_input.colors.text_gradient",
|
|
227
|
+
"help": "Apply gradient to input text"
|
|
183
228
|
}
|
|
184
229
|
]
|
|
185
230
|
}
|
|
186
231
|
|
|
187
|
-
def __init__(self, name: str,
|
|
232
|
+
def __init__(self, name: str, event_bus: 'EventBus',
|
|
188
233
|
renderer: 'TerminalRenderer', config: 'ConfigManager') -> None:
|
|
189
234
|
"""Initialize the enhanced input plugin.
|
|
190
235
|
|
|
191
236
|
Args:
|
|
192
237
|
name: Plugin name.
|
|
193
|
-
state_manager: State management system.
|
|
194
238
|
event_bus: Event bus for hook registration.
|
|
195
239
|
renderer: Terminal renderer.
|
|
196
240
|
config: Configuration manager.
|
|
197
241
|
"""
|
|
198
242
|
self.name = name
|
|
199
|
-
self.state_manager = state_manager
|
|
200
243
|
self.event_bus = event_bus
|
|
201
244
|
self.renderer = renderer
|
|
202
245
|
|
|
@@ -364,20 +407,27 @@ class EnhancedInputPlugin:
|
|
|
364
407
|
logger.error(f"Failed to register enhanced input status view: {e}")
|
|
365
408
|
|
|
366
409
|
def _get_input_ui_content(self) -> List[str]:
|
|
367
|
-
"""Get input UI content
|
|
410
|
+
"""Get input UI content (agnoster style)."""
|
|
368
411
|
try:
|
|
412
|
+
seg = AgnosterSegment()
|
|
413
|
+
|
|
369
414
|
if not self.config.enabled:
|
|
370
|
-
|
|
415
|
+
seg.add_neutral("Input: Off", "dark")
|
|
416
|
+
return [seg.render()]
|
|
371
417
|
|
|
372
418
|
style_display = self.state.get_status_display()
|
|
373
419
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
420
|
+
seg.add_lime("Input", "dark")
|
|
421
|
+
seg.add_cyan(style_display, "dark")
|
|
422
|
+
seg.add_neutral(f"Width: {self.config.width_mode}", "mid")
|
|
423
|
+
|
|
424
|
+
return [seg.render()]
|
|
377
425
|
|
|
378
426
|
except Exception as e:
|
|
379
427
|
logger.error(f"Error getting input UI content: {e}")
|
|
380
|
-
|
|
428
|
+
seg = AgnosterSegment()
|
|
429
|
+
seg.add_neutral("Input: Error", "dark")
|
|
430
|
+
return [seg.render()]
|
|
381
431
|
|
|
382
432
|
|
|
383
433
|
async def shutdown(self) -> None:
|
plugins/fullscreen/__init__.py
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"""Full-screen plugins directory."""
|
|
2
2
|
|
|
3
3
|
from .matrix_plugin import MatrixRainPlugin
|
|
4
|
-
from .example_plugin import
|
|
4
|
+
from .example_plugin import EnhancedExamplePlugin
|
|
5
|
+
from .setup_wizard_plugin import SetupWizardPlugin
|
|
6
|
+
from .space_shooter_plugin import SpaceShooterPlugin
|
|
5
7
|
|
|
6
8
|
__all__ = [
|
|
7
9
|
"MatrixRainPlugin",
|
|
8
|
-
"
|
|
10
|
+
"EnhancedExamplePlugin",
|
|
11
|
+
"SetupWizardPlugin",
|
|
12
|
+
"SpaceShooterPlugin"
|
|
9
13
|
]
|