agentcrew-ai 0.8.13__py3-none-any.whl → 0.9.0__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.
- AgentCrew/__init__.py +1 -1
- AgentCrew/app.py +34 -633
- AgentCrew/main_docker.py +1 -30
- AgentCrew/modules/agents/local_agent.py +2 -2
- AgentCrew/modules/chat/message/command_processor.py +33 -8
- AgentCrew/modules/chat/message/handler.py +5 -1
- AgentCrew/modules/console/completers.py +1 -1
- AgentCrew/modules/console/console_ui.py +6 -11
- AgentCrew/modules/console/conversation_browser/__init__.py +9 -0
- AgentCrew/modules/console/conversation_browser/browser.py +84 -0
- AgentCrew/modules/console/conversation_browser/browser_input_handler.py +279 -0
- AgentCrew/modules/console/{conversation_browser.py → conversation_browser/browser_ui.py} +249 -163
- AgentCrew/modules/console/conversation_handler.py +34 -1
- AgentCrew/modules/console/display_handlers.py +123 -7
- AgentCrew/modules/gui/components/command_handler.py +137 -29
- AgentCrew/modules/gui/themes/README.md +30 -14
- AgentCrew/modules/gui/themes/__init__.py +2 -1
- AgentCrew/modules/gui/themes/atom_light.yaml +1287 -0
- AgentCrew/modules/gui/themes/catppuccin.yaml +1276 -0
- AgentCrew/modules/gui/themes/dracula.yaml +1262 -0
- AgentCrew/modules/gui/themes/nord.yaml +1267 -0
- AgentCrew/modules/gui/themes/saigontech.yaml +1268 -0
- AgentCrew/modules/gui/themes/style_provider.py +76 -264
- AgentCrew/modules/gui/themes/theme_loader.py +379 -0
- AgentCrew/modules/gui/themes/unicorn.yaml +1276 -0
- AgentCrew/modules/gui/widgets/configs/global_settings.py +3 -4
- AgentCrew/modules/llm/constants.py +13 -4
- AgentCrew/setup.py +470 -0
- {agentcrew_ai-0.8.13.dist-info → agentcrew_ai-0.9.0.dist-info}/METADATA +1 -1
- {agentcrew_ai-0.8.13.dist-info → agentcrew_ai-0.9.0.dist-info}/RECORD +34 -29
- {agentcrew_ai-0.8.13.dist-info → agentcrew_ai-0.9.0.dist-info}/WHEEL +1 -1
- AgentCrew/modules/gui/themes/atom_light.py +0 -1365
- AgentCrew/modules/gui/themes/catppuccin.py +0 -1404
- AgentCrew/modules/gui/themes/dracula.py +0 -1372
- AgentCrew/modules/gui/themes/nord.py +0 -1365
- AgentCrew/modules/gui/themes/saigontech.py +0 -1359
- AgentCrew/modules/gui/themes/unicorn.py +0 -1372
- {agentcrew_ai-0.8.13.dist-info → agentcrew_ai-0.9.0.dist-info}/entry_points.txt +0 -0
- {agentcrew_ai-0.8.13.dist-info → agentcrew_ai-0.9.0.dist-info}/licenses/LICENSE +0 -0
- {agentcrew_ai-0.8.13.dist-info → agentcrew_ai-0.9.0.dist-info}/top_level.txt +0 -0
|
@@ -122,12 +122,125 @@ class DisplayHandlers:
|
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
def display_debug_info(self, debug_info):
|
|
125
|
-
"""Display debug information.
|
|
126
|
-
|
|
125
|
+
"""Display debug information with formatting and truncation.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
debug_info: Either a dict with 'type' and 'messages' keys (new format)
|
|
129
|
+
or a raw list of messages (legacy format)
|
|
130
|
+
"""
|
|
131
|
+
if (
|
|
132
|
+
isinstance(debug_info, dict)
|
|
133
|
+
and "type" in debug_info
|
|
134
|
+
and "messages" in debug_info
|
|
135
|
+
):
|
|
136
|
+
# New format with type and messages
|
|
137
|
+
msg_type = debug_info["type"]
|
|
138
|
+
messages = debug_info["messages"]
|
|
139
|
+
title = "Agent Messages" if msg_type == "agent" else "Chat Messages"
|
|
140
|
+
else:
|
|
141
|
+
# Legacy format - just raw messages
|
|
142
|
+
title = "Messages"
|
|
143
|
+
messages = debug_info
|
|
144
|
+
|
|
145
|
+
self.console.print(
|
|
146
|
+
Text(f"\n{title} ({len(messages)} messages):", style=RICH_STYLE_YELLOW)
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
formatted = self._format_messages_for_debug(messages)
|
|
127
150
|
try:
|
|
128
|
-
self.console.print(json.dumps(
|
|
151
|
+
self.console.print(json.dumps(formatted, indent=2))
|
|
129
152
|
except Exception:
|
|
130
|
-
self.console.print(
|
|
153
|
+
self.console.print(str(formatted))
|
|
154
|
+
|
|
155
|
+
def _format_messages_for_debug(
|
|
156
|
+
self, messages, max_content_length: int = 200
|
|
157
|
+
) -> list:
|
|
158
|
+
"""Format messages for debug display with truncated content.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
messages: List of message dictionaries
|
|
162
|
+
max_content_length: Maximum length for message content
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
List of formatted message dictionaries
|
|
166
|
+
"""
|
|
167
|
+
formatted = []
|
|
168
|
+
|
|
169
|
+
for i, msg in enumerate(messages):
|
|
170
|
+
formatted_msg = {"#": i, "content": ""}
|
|
171
|
+
|
|
172
|
+
# Copy basic fields
|
|
173
|
+
if "role" in msg:
|
|
174
|
+
formatted_msg["role"] = msg["role"]
|
|
175
|
+
if "agent" in msg:
|
|
176
|
+
formatted_msg["agent"] = msg["agent"]
|
|
177
|
+
|
|
178
|
+
# Truncate content
|
|
179
|
+
content = msg.get("content", "")
|
|
180
|
+
formatted_msg["content"] = self._truncate_content(
|
|
181
|
+
content, max_content_length
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Include tool_use/tool_result indicators if present
|
|
185
|
+
if isinstance(content, list):
|
|
186
|
+
content_types = []
|
|
187
|
+
for item in content:
|
|
188
|
+
if isinstance(item, dict):
|
|
189
|
+
item_type = item.get("type", "unknown")
|
|
190
|
+
if item_type == "tool_use":
|
|
191
|
+
tool_name = item.get("name", "unknown")
|
|
192
|
+
content_types.append(f"tool_use:{tool_name}")
|
|
193
|
+
elif item_type == "tool_result":
|
|
194
|
+
content_types.append("tool_result")
|
|
195
|
+
elif item_type not in ("text",):
|
|
196
|
+
content_types.append(item_type)
|
|
197
|
+
if content_types:
|
|
198
|
+
formatted_msg["content_types"] = content_types
|
|
199
|
+
|
|
200
|
+
formatted.append(formatted_msg)
|
|
201
|
+
|
|
202
|
+
return formatted
|
|
203
|
+
|
|
204
|
+
def _truncate_content(self, content, max_length: int = 200) -> str:
|
|
205
|
+
"""Truncate content to max_length with ellipsis.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
content: Message content (can be string, list, or dict)
|
|
209
|
+
max_length: Maximum length for the output
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Truncated string representation
|
|
213
|
+
"""
|
|
214
|
+
if isinstance(content, str):
|
|
215
|
+
text = content
|
|
216
|
+
elif isinstance(content, list):
|
|
217
|
+
# Extract text from content blocks
|
|
218
|
+
text_parts = []
|
|
219
|
+
for item in content:
|
|
220
|
+
if isinstance(item, dict):
|
|
221
|
+
if item.get("type") == "text":
|
|
222
|
+
text_parts.append(item.get("text", ""))
|
|
223
|
+
elif item.get("type") == "tool_use":
|
|
224
|
+
text_parts.append(f"[tool:{item.get('name', 'unknown')}]")
|
|
225
|
+
elif item.get("type") == "tool_result":
|
|
226
|
+
result = item.get("content", "")
|
|
227
|
+
if isinstance(result, str):
|
|
228
|
+
text_parts.append(f"[result:{result[:50]}...]")
|
|
229
|
+
else:
|
|
230
|
+
text_parts.append("[result:...]")
|
|
231
|
+
elif isinstance(item, str):
|
|
232
|
+
text_parts.append(item)
|
|
233
|
+
text = " | ".join(text_parts)
|
|
234
|
+
else:
|
|
235
|
+
text = str(content)
|
|
236
|
+
|
|
237
|
+
# Clean up whitespace
|
|
238
|
+
text = " ".join(text.split())
|
|
239
|
+
|
|
240
|
+
if len(text) <= max_length:
|
|
241
|
+
return text
|
|
242
|
+
|
|
243
|
+
return text[: max_length - 3] + "..."
|
|
131
244
|
|
|
132
245
|
def display_models(self, models_by_provider: Dict):
|
|
133
246
|
"""Display available models grouped by provider."""
|
|
@@ -161,13 +274,15 @@ class DisplayHandlers:
|
|
|
161
274
|
self,
|
|
162
275
|
conversations: List[Dict[str, Any]],
|
|
163
276
|
get_history_callback=None,
|
|
277
|
+
delete_callback=None,
|
|
164
278
|
):
|
|
165
279
|
"""Display available conversations using interactive browser.
|
|
166
|
-
|
|
280
|
+
|
|
167
281
|
Args:
|
|
168
282
|
conversations: List of conversation metadata
|
|
169
283
|
get_history_callback: Optional callback to fetch full conversation history
|
|
170
|
-
|
|
284
|
+
delete_callback: Optional callback to delete conversations by IDs
|
|
285
|
+
|
|
171
286
|
Returns:
|
|
172
287
|
Selected conversation ID or None if cancelled
|
|
173
288
|
"""
|
|
@@ -177,11 +292,12 @@ class DisplayHandlers:
|
|
|
177
292
|
)
|
|
178
293
|
return None
|
|
179
294
|
|
|
180
|
-
from .conversation_browser import ConversationBrowser
|
|
295
|
+
from .conversation_browser.browser import ConversationBrowser
|
|
181
296
|
|
|
182
297
|
browser = ConversationBrowser(
|
|
183
298
|
console=self.console,
|
|
184
299
|
get_conversation_history=get_history_callback,
|
|
300
|
+
on_delete=delete_callback,
|
|
185
301
|
)
|
|
186
302
|
browser.set_conversations(conversations)
|
|
187
303
|
return browser.show()
|
|
@@ -136,33 +136,132 @@ class CommandHandler:
|
|
|
136
136
|
|
|
137
137
|
def display_debug_info(self):
|
|
138
138
|
"""Display debug information about the current messages."""
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
self.chat_window.message_handler.agent.history, indent=2
|
|
143
|
-
)
|
|
144
|
-
except Exception as _:
|
|
145
|
-
debug_info = str(self.chat_window.message_handler.agent.history)
|
|
146
|
-
# Add as a system message
|
|
147
|
-
self.chat_window.chat_components.add_system_message(
|
|
148
|
-
f"DEBUG INFO:\n\n```json\n{debug_info}\n```"
|
|
139
|
+
# Display agent messages
|
|
140
|
+
self._display_debug_messages(
|
|
141
|
+
"Agent Messages", self.chat_window.message_handler.agent.history
|
|
149
142
|
)
|
|
150
143
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
self.chat_window.message_handler.streamline_messages, indent=2
|
|
155
|
-
)
|
|
156
|
-
except Exception as _:
|
|
157
|
-
debug_info = str(self.chat_window.message_handler.streamline_messages)
|
|
158
|
-
# Add as a system message
|
|
159
|
-
self.chat_window.chat_components.add_system_message(
|
|
160
|
-
f"DEBUG INFO:\n\n```json\n{debug_info}\n```"
|
|
144
|
+
# Display chat/streamline messages
|
|
145
|
+
self._display_debug_messages(
|
|
146
|
+
"Chat Messages", self.chat_window.message_handler.streamline_messages
|
|
161
147
|
)
|
|
162
148
|
|
|
163
149
|
# Update status bar
|
|
164
150
|
self.chat_window.display_status_message("Debug information displayed")
|
|
165
151
|
|
|
152
|
+
def _display_debug_messages(
|
|
153
|
+
self, title: str, messages: list, max_content_length: int = 200
|
|
154
|
+
):
|
|
155
|
+
"""Display formatted debug messages with content truncation.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
title: Section title for the debug output
|
|
159
|
+
messages: List of message dictionaries
|
|
160
|
+
max_content_length: Maximum length for message content (default: 200)
|
|
161
|
+
"""
|
|
162
|
+
formatted_messages = self._format_messages_for_debug(
|
|
163
|
+
messages, max_content_length
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
debug_info = json.dumps(formatted_messages, indent=2)
|
|
168
|
+
except Exception:
|
|
169
|
+
debug_info = str(formatted_messages)
|
|
170
|
+
|
|
171
|
+
self.chat_window.chat_components.add_system_message(
|
|
172
|
+
f"DEBUG - {title} ({len(messages)} messages):\n\n```json\n{debug_info}\n```"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def _format_messages_for_debug(
|
|
176
|
+
self, messages: list, max_content_length: int = 200
|
|
177
|
+
) -> list:
|
|
178
|
+
"""Format messages for debug display with truncated content.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
messages: List of message dictionaries
|
|
182
|
+
max_content_length: Maximum length for message content
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
List of formatted message dictionaries
|
|
186
|
+
"""
|
|
187
|
+
formatted = []
|
|
188
|
+
|
|
189
|
+
for i, msg in enumerate(messages):
|
|
190
|
+
formatted_msg = {"#": i}
|
|
191
|
+
|
|
192
|
+
# Copy basic fields
|
|
193
|
+
if "role" in msg:
|
|
194
|
+
formatted_msg["role"] = msg["role"]
|
|
195
|
+
if "agent" in msg:
|
|
196
|
+
formatted_msg["agent"] = msg["agent"]
|
|
197
|
+
|
|
198
|
+
# Truncate content
|
|
199
|
+
content = msg.get("content", "")
|
|
200
|
+
formatted_msg["content"] = self._truncate_content(
|
|
201
|
+
content, max_content_length
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Include tool_use/tool_result indicators if present
|
|
205
|
+
if isinstance(content, list):
|
|
206
|
+
content_types = []
|
|
207
|
+
for item in content:
|
|
208
|
+
if isinstance(item, dict):
|
|
209
|
+
item_type = item.get("type", "unknown")
|
|
210
|
+
if item_type == "tool_use":
|
|
211
|
+
tool_name = item.get("name", "unknown")
|
|
212
|
+
content_types.append(f"tool_use:{tool_name}")
|
|
213
|
+
elif item_type == "tool_result":
|
|
214
|
+
content_types.append("tool_result")
|
|
215
|
+
elif item_type not in ("text",):
|
|
216
|
+
content_types.append(item_type)
|
|
217
|
+
if content_types:
|
|
218
|
+
formatted_msg["content_types"] = content_types
|
|
219
|
+
|
|
220
|
+
formatted.append(formatted_msg)
|
|
221
|
+
|
|
222
|
+
return formatted
|
|
223
|
+
|
|
224
|
+
def _truncate_content(self, content: Any, max_length: int) -> str:
|
|
225
|
+
"""Truncate content to max_length with ellipsis.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
content: Message content (can be string, list, or dict)
|
|
229
|
+
max_length: Maximum length for the output
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
Truncated string representation
|
|
233
|
+
"""
|
|
234
|
+
if isinstance(content, str):
|
|
235
|
+
text = content
|
|
236
|
+
elif isinstance(content, list):
|
|
237
|
+
# Extract text from content blocks
|
|
238
|
+
text_parts = []
|
|
239
|
+
for item in content:
|
|
240
|
+
if isinstance(item, dict):
|
|
241
|
+
if item.get("type") == "text":
|
|
242
|
+
text_parts.append(item.get("text", ""))
|
|
243
|
+
elif item.get("type") == "tool_use":
|
|
244
|
+
text_parts.append(f"[tool:{item.get('name', 'unknown')}]")
|
|
245
|
+
elif item.get("type") == "tool_result":
|
|
246
|
+
result = item.get("content", "")
|
|
247
|
+
if isinstance(result, str):
|
|
248
|
+
text_parts.append(f"[result:{result[:50]}...]")
|
|
249
|
+
else:
|
|
250
|
+
text_parts.append("[result:...]")
|
|
251
|
+
elif isinstance(item, str):
|
|
252
|
+
text_parts.append(item)
|
|
253
|
+
text = " | ".join(text_parts)
|
|
254
|
+
else:
|
|
255
|
+
text = str(content)
|
|
256
|
+
|
|
257
|
+
# Clean up whitespace
|
|
258
|
+
text = " ".join(text.split())
|
|
259
|
+
|
|
260
|
+
if len(text) <= max_length:
|
|
261
|
+
return text
|
|
262
|
+
|
|
263
|
+
return text[: max_length - 3] + "..."
|
|
264
|
+
|
|
166
265
|
def handle_event(self, event: str, data: Any) -> bool:
|
|
167
266
|
"""
|
|
168
267
|
Handle command-related events. Returns True if event was processed, False otherwise.
|
|
@@ -193,15 +292,24 @@ class CommandHandler:
|
|
|
193
292
|
return True
|
|
194
293
|
|
|
195
294
|
elif event == "debug_requested":
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
295
|
+
if isinstance(data, dict) and "type" in data and "messages" in data:
|
|
296
|
+
# New format with type and messages
|
|
297
|
+
msg_type = data["type"]
|
|
298
|
+
messages = data["messages"]
|
|
299
|
+
title = "Agent Messages" if msg_type == "agent" else "Chat Messages"
|
|
300
|
+
self._display_debug_messages(title, messages)
|
|
301
|
+
else:
|
|
302
|
+
# Legacy format - just raw messages
|
|
303
|
+
try:
|
|
304
|
+
formatted = self._format_messages_for_debug(data)
|
|
305
|
+
debug_info = json.dumps(formatted, indent=2)
|
|
306
|
+
self.chat_window.chat_components.add_system_message(
|
|
307
|
+
f"DEBUG INFO ({len(data)} messages):\n\n```json\n{debug_info}\n```"
|
|
308
|
+
)
|
|
309
|
+
except Exception:
|
|
310
|
+
self.chat_window.chat_components.add_system_message(
|
|
311
|
+
f"DEBUG INFO:\n\n{str(data)}"
|
|
312
|
+
)
|
|
205
313
|
return True
|
|
206
314
|
|
|
207
315
|
elif event == "agent_changed":
|
|
@@ -5,26 +5,32 @@ This directory contains the theming system for the AgentCrew GUI application.
|
|
|
5
5
|
## Available Themes
|
|
6
6
|
|
|
7
7
|
### 1. Catppuccin Theme (`catppuccin.py`)
|
|
8
|
+
|
|
8
9
|
- **Type**: Dark theme
|
|
9
10
|
- **Style**: Modern, vibrant dark theme with purple and blue accents
|
|
10
11
|
- **Usage**: Default dark theme, activated when `theme = "dark"` in config
|
|
11
12
|
|
|
12
13
|
### 2. Atom Light Theme (`atom_light.py`)
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
- **Type**: Light theme
|
|
14
16
|
- **Style**: Clean, minimalist light theme with blue accents
|
|
15
17
|
- **Usage**: Activated when `theme = "light"` in config
|
|
16
18
|
|
|
17
19
|
### 3. Nord Theme (`nord.py`)
|
|
20
|
+
|
|
18
21
|
- **Type**: Dark theme
|
|
19
22
|
- **Style**: Arctic-inspired color palette with cool blue/teal accents
|
|
20
23
|
- **Usage**: Activated when `theme = "nord"` in config
|
|
21
|
-
- **Color Palette**: Based on the official
|
|
24
|
+
- **Color Palette**: Based on the official
|
|
25
|
+
[Nord Color Palette](https://www.nordtheme.com/)
|
|
22
26
|
|
|
23
27
|
### 4. Dracula Theme (`dracula.py`) ⭐ **NEW**
|
|
28
|
+
|
|
24
29
|
- **Type**: Dark theme
|
|
25
30
|
- **Style**: Bold, vibrant dark theme with purple and pink accents
|
|
26
31
|
- **Usage**: Activated when `theme = "dracula"` in config
|
|
27
|
-
- **Color Palette**: Based on the official
|
|
32
|
+
- **Color Palette**: Based on the official
|
|
33
|
+
[Dracula Theme](https://draculatheme.com/contribute)
|
|
28
34
|
|
|
29
35
|
## Dracula Theme Details
|
|
30
36
|
|
|
@@ -33,12 +39,14 @@ The Dracula theme implements the complete official color palette:
|
|
|
33
39
|
### Color Groups
|
|
34
40
|
|
|
35
41
|
#### Base Colors
|
|
42
|
+
|
|
36
43
|
- `#282A36` - Background (Main application background)
|
|
37
44
|
- `#44475A` - Current Line (Secondary elements, input fields)
|
|
38
45
|
- `#F8F8F2` - Foreground (Text color)
|
|
39
46
|
- `#6272A4` - Comment (Secondary text, borders)
|
|
40
47
|
|
|
41
48
|
#### Accent Colors
|
|
49
|
+
|
|
42
50
|
- `#8BE9FD` - Cyan (Focus states, operators)
|
|
43
51
|
- `#50FA7B` - Green (Success states, strings)
|
|
44
52
|
- `#FFB86C` - Orange (Warnings, special text)
|
|
@@ -61,23 +69,27 @@ The Nord theme implements the complete 16-color Nord palette:
|
|
|
61
69
|
### Color Groups
|
|
62
70
|
|
|
63
71
|
#### Polar Night (Dark Backgrounds)
|
|
72
|
+
|
|
64
73
|
- `#2e3440` - Polar Night 0 (Main backgrounds)
|
|
65
74
|
- `#3b4252` - Polar Night 1 (Secondary backgrounds)
|
|
66
|
-
- `#434c5e` - Polar Night 2 (Input backgrounds)
|
|
75
|
+
- `#434c5e` - Polar Night 2 (Input backgrounds)
|
|
67
76
|
- `#4c566a` - Polar Night 3 (Borders, disabled states)
|
|
68
77
|
|
|
69
78
|
#### Snow Storm (Light Text)
|
|
79
|
+
|
|
70
80
|
- `#d8dee9` - Snow Storm 0 (Secondary text)
|
|
71
81
|
- `#e5e9f0` - Snow Storm 1 (Primary text)
|
|
72
82
|
- `#eceff4` - Snow Storm 2 (Highlighted text)
|
|
73
83
|
|
|
74
84
|
#### Frost (Blue Accents)
|
|
85
|
+
|
|
75
86
|
- `#8fbcbb` - Frost 0 (Hover states)
|
|
76
87
|
- `#88c0d0` - Frost 1 (Focus states, links)
|
|
77
88
|
- `#81a1c1` - Frost 2 (Active states)
|
|
78
89
|
- `#5e81ac` - Frost 3 (Primary actions)
|
|
79
90
|
|
|
80
91
|
#### Aurora (Semantic Colors)
|
|
92
|
+
|
|
81
93
|
- `#bf616a` - Aurora Red (Errors, stop actions)
|
|
82
94
|
- `#d08770` - Aurora Orange (Warnings, hover effects)
|
|
83
95
|
- `#ebcb8b` - Aurora Yellow (Classes, namespaces)
|
|
@@ -96,14 +108,16 @@ The Nord theme implements the complete 16-color Nord palette:
|
|
|
96
108
|
To use a specific theme in AgentCrew:
|
|
97
109
|
|
|
98
110
|
1. Set the theme in your global configuration:
|
|
99
|
-
|
|
111
|
+
|
|
100
112
|
For Nord theme:
|
|
113
|
+
|
|
101
114
|
```toml
|
|
102
115
|
[global_settings]
|
|
103
116
|
theme = "nord"
|
|
104
117
|
```
|
|
105
|
-
|
|
118
|
+
|
|
106
119
|
For Dracula theme:
|
|
120
|
+
|
|
107
121
|
```toml
|
|
108
122
|
[global_settings]
|
|
109
123
|
theme = "dracula"
|
|
@@ -111,7 +125,8 @@ To use a specific theme in AgentCrew:
|
|
|
111
125
|
|
|
112
126
|
2. Restart the application or reload the configuration
|
|
113
127
|
|
|
114
|
-
3. The application will automatically apply the Nord color scheme to all UI
|
|
128
|
+
3. The application will automatically apply the Nord color scheme to all UI
|
|
129
|
+
components
|
|
115
130
|
|
|
116
131
|
## Architecture
|
|
117
132
|
|
|
@@ -119,9 +134,11 @@ The theming system uses:
|
|
|
119
134
|
|
|
120
135
|
- **StyleProvider**: Central theme management class
|
|
121
136
|
- **Theme Classes**: Static classes containing CSS style definitions
|
|
122
|
-
- **Configuration Integration**: Automatic theme switching based on user
|
|
137
|
+
- **Configuration Integration**: Automatic theme switching based on user
|
|
138
|
+
preferences
|
|
123
139
|
|
|
124
140
|
Each theme class provides comprehensive styling for:
|
|
141
|
+
|
|
125
142
|
- Main application windows and containers
|
|
126
143
|
- Buttons (primary, secondary, stop, success, error)
|
|
127
144
|
- Input fields and text areas
|
|
@@ -135,11 +152,9 @@ Each theme class provides comprehensive styling for:
|
|
|
135
152
|
|
|
136
153
|
To add a new theme:
|
|
137
154
|
|
|
138
|
-
1. Create a new theme file (e.g., `mytheme.
|
|
139
|
-
2. Implement a theme
|
|
140
|
-
3.
|
|
141
|
-
4. Update `__init__.py` to export the new theme class
|
|
142
|
-
5. Document the theme configuration value
|
|
155
|
+
1. Create a new theme file (e.g., `mytheme.yaml`)
|
|
156
|
+
2. Implement a theme file with all required style constants
|
|
157
|
+
3. Document the theme configuration value
|
|
143
158
|
|
|
144
159
|
## Development Notes
|
|
145
160
|
|
|
@@ -147,4 +162,5 @@ To add a new theme:
|
|
|
147
162
|
- Color values should be hex codes with comments for clarity
|
|
148
163
|
- Maintain consistency with existing theme patterns
|
|
149
164
|
- Test all UI components with the new theme
|
|
150
|
-
- Ensure accessibility standards are met
|
|
165
|
+
- Ensure accessibility standards are met
|
|
166
|
+
|