agentcrew-ai 0.8.6__py3-none-any.whl → 0.8.7__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 +1 -1
- AgentCrew/modules/a2a/registry.py +1 -1
- AgentCrew/modules/a2a/task_manager.py +6 -4
- AgentCrew/modules/agents/local_agent.py +1 -1
- AgentCrew/modules/code_analysis/service.py +1 -3
- AgentCrew/modules/console/diff_display.py +5 -1
- AgentCrew/modules/custom_llm/service.py +0 -1
- AgentCrew/modules/gui/components/tool_handlers.py +167 -4
- AgentCrew/modules/gui/themes/atom_light.py +20 -0
- AgentCrew/modules/gui/themes/catppuccin.py +20 -0
- AgentCrew/modules/gui/themes/dracula.py +20 -0
- AgentCrew/modules/gui/themes/nord.py +20 -0
- AgentCrew/modules/gui/themes/saigontech.py +20 -0
- AgentCrew/modules/gui/themes/style_provider.py +25 -0
- AgentCrew/modules/gui/themes/unicorn.py +20 -0
- AgentCrew/modules/gui/widgets/__init__.py +3 -0
- AgentCrew/modules/gui/widgets/diff_widget.py +532 -0
- AgentCrew/modules/gui/widgets/tool_widget.py +42 -7
- AgentCrew/modules/llm/constants.py +0 -1
- {agentcrew_ai-0.8.6.dist-info → agentcrew_ai-0.8.7.dist-info}/METADATA +1 -1
- {agentcrew_ai-0.8.6.dist-info → agentcrew_ai-0.8.7.dist-info}/RECORD +26 -25
- {agentcrew_ai-0.8.6.dist-info → agentcrew_ai-0.8.7.dist-info}/WHEEL +0 -0
- {agentcrew_ai-0.8.6.dist-info → agentcrew_ai-0.8.7.dist-info}/entry_points.txt +0 -0
- {agentcrew_ai-0.8.6.dist-info → agentcrew_ai-0.8.7.dist-info}/licenses/LICENSE +0 -0
- {agentcrew_ai-0.8.6.dist-info → agentcrew_ai-0.8.7.dist-info}/top_level.txt +0 -0
AgentCrew/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.8.
|
|
1
|
+
__version__ = "0.8.7"
|
AgentCrew/app.py
CHANGED
|
@@ -584,7 +584,7 @@ tools = ["memory", "browser", "web_search", "code_analysis"]
|
|
|
584
584
|
"No LLM API key found. Please set either ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENAI_API_KEY, GROQ_API_KEY, or DEEPINFRA_API_KEY"
|
|
585
585
|
)
|
|
586
586
|
|
|
587
|
-
services = self.setup_services(provider, memory_llm)
|
|
587
|
+
services = self.setup_services(provider, memory_llm, need_memory=False)
|
|
588
588
|
|
|
589
589
|
if mcp_config:
|
|
590
590
|
os.environ["MCP_CONFIG_PATH"] = mcp_config
|
|
@@ -4,10 +4,10 @@ from typing import TYPE_CHECKING
|
|
|
4
4
|
from pydantic import BaseModel
|
|
5
5
|
from .agent_cards import create_agent_card
|
|
6
6
|
from AgentCrew.modules.agents import LocalAgent
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
if TYPE_CHECKING:
|
|
10
|
-
from typing import Any, Dict, List, Optional
|
|
11
11
|
from AgentCrew.modules.agents import AgentManager
|
|
12
12
|
from a2a.types import AgentCard
|
|
13
13
|
|
|
@@ -85,7 +85,7 @@ class AgentTaskManager(TaskManager):
|
|
|
85
85
|
if self.agent is None or not isinstance(self.agent, LocalAgent):
|
|
86
86
|
raise ValueError(f"Agent {agent_name} not found or is not a LocalAgent")
|
|
87
87
|
|
|
88
|
-
self.memory_service = self.agent.services
|
|
88
|
+
self.memory_service = self.agent.services.get("memory", None)
|
|
89
89
|
|
|
90
90
|
def _is_terminal_state(self, state: TaskState) -> bool:
|
|
91
91
|
"""Check if a state is terminal."""
|
|
@@ -272,6 +272,7 @@ class AgentTaskManager(TaskManager):
|
|
|
272
272
|
|
|
273
273
|
finally:
|
|
274
274
|
# Clean up
|
|
275
|
+
self.tasks.pop(task_id, None)
|
|
275
276
|
self.streaming_tasks.pop(task_id, None)
|
|
276
277
|
|
|
277
278
|
def _create_ask_tool_message(
|
|
@@ -572,9 +573,10 @@ class AgentTaskManager(TaskManager):
|
|
|
572
573
|
.get("content", [{}])[0]
|
|
573
574
|
.get("text", "")
|
|
574
575
|
)
|
|
575
|
-
self.memory_service
|
|
576
|
-
|
|
577
|
-
|
|
576
|
+
if self.memory_service:
|
|
577
|
+
self.memory_service.store_conversation(
|
|
578
|
+
user_message, current_response, self.agent_name
|
|
579
|
+
)
|
|
578
580
|
|
|
579
581
|
# Create artifact from final response
|
|
580
582
|
artifact = convert_agent_response_to_a2a_artifact(
|
|
@@ -634,7 +634,7 @@ Check if `when` condition in <Global_Behavior> or <Project_Behavior> matches, up
|
|
|
634
634
|
- Skip agent evaluation if user request is when...,[action]... related to adaptive behaviors call `adapt` tool instead.""",
|
|
635
635
|
},
|
|
636
636
|
)
|
|
637
|
-
if self.services.get("memory"):
|
|
637
|
+
if not self.is_remoting_mode and self.services.get("memory"):
|
|
638
638
|
memory_headers = self.services["memory"].list_memory_headers(
|
|
639
639
|
agent_name=self.name
|
|
640
640
|
)
|
|
@@ -1290,9 +1290,7 @@ class CodeAnalysisService:
|
|
|
1290
1290
|
f"start_line {start_line} exceeds file length ({total_lines} lines)"
|
|
1291
1291
|
)
|
|
1292
1292
|
if end_line > total_lines:
|
|
1293
|
-
|
|
1294
|
-
f"end_line {end_line} exceeds file length ({total_lines} lines)"
|
|
1295
|
-
)
|
|
1293
|
+
end_line = total_lines
|
|
1296
1294
|
|
|
1297
1295
|
# Extract the line range (convert to 0-indexed)
|
|
1298
1296
|
selected_lines = lines[start_line - 1 : end_line]
|
|
@@ -179,7 +179,11 @@ class DiffDisplay:
|
|
|
179
179
|
Returns:
|
|
180
180
|
Rich Text with character-level highlighting
|
|
181
181
|
"""
|
|
182
|
-
result = Text(
|
|
182
|
+
result = Text()
|
|
183
|
+
if is_original:
|
|
184
|
+
result.append("- ", style="red")
|
|
185
|
+
else:
|
|
186
|
+
result.append("+ ", style="green")
|
|
183
187
|
matcher = difflib.SequenceMatcher(None, orig_line, mod_line)
|
|
184
188
|
|
|
185
189
|
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
|
|
@@ -7,10 +7,12 @@ from PySide6.QtWidgets import (
|
|
|
7
7
|
QVBoxLayout,
|
|
8
8
|
QPushButton,
|
|
9
9
|
QLabel,
|
|
10
|
+
QScrollArea,
|
|
10
11
|
)
|
|
11
12
|
from PySide6.QtGui import QKeySequence, QShortcut
|
|
12
13
|
from PySide6.QtCore import Qt
|
|
13
14
|
from AgentCrew.modules.gui.widgets.tool_widget import ToolWidget
|
|
15
|
+
from AgentCrew.modules.gui.widgets.diff_widget import DiffWidget
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class ToolEventHandler:
|
|
@@ -158,17 +160,18 @@ class ToolEventHandler:
|
|
|
158
160
|
tool_use = tool_info.copy()
|
|
159
161
|
confirmation_id = tool_use.pop("confirmation_id")
|
|
160
162
|
|
|
161
|
-
# Special handling for 'ask' tool
|
|
162
163
|
if tool_use["name"] == "ask":
|
|
163
164
|
self._handle_ask_tool_confirmation(tool_use, confirmation_id)
|
|
164
165
|
return
|
|
165
166
|
|
|
166
|
-
|
|
167
|
+
if tool_use["name"] == "write_or_edit_file":
|
|
168
|
+
self._handle_write_or_edit_file_confirmation(tool_use, confirmation_id)
|
|
169
|
+
return
|
|
170
|
+
|
|
167
171
|
dialog = QMessageBox(self.chat_window)
|
|
168
172
|
dialog.setWindowTitle("Tool Execution Confirmation")
|
|
169
173
|
dialog.setIcon(QMessageBox.Icon.Question)
|
|
170
174
|
|
|
171
|
-
# Format tool information for display
|
|
172
175
|
tool_description = f"The assistant wants to use the '{tool_use['name']}' tool."
|
|
173
176
|
params_text = ""
|
|
174
177
|
|
|
@@ -189,7 +192,6 @@ class ToolEventHandler:
|
|
|
189
192
|
text_edit.setReadOnly(True)
|
|
190
193
|
text_edit.setText(params_text)
|
|
191
194
|
|
|
192
|
-
# Style the text edit to match the main theme
|
|
193
195
|
text_edit.setStyleSheet(
|
|
194
196
|
self.chat_window.style_provider.get_tool_dialog_text_edit_style()
|
|
195
197
|
)
|
|
@@ -293,6 +295,167 @@ class ToolEventHandler:
|
|
|
293
295
|
self.chat_window.current_response_bubble = None
|
|
294
296
|
self.chat_window.current_response_container = None
|
|
295
297
|
|
|
298
|
+
def _handle_write_or_edit_file_confirmation(self, tool_use, confirmation_id):
|
|
299
|
+
"""Handle write_or_edit_file tool confirmation with diff view."""
|
|
300
|
+
from PySide6.QtWidgets import QWidget, QHBoxLayout
|
|
301
|
+
|
|
302
|
+
tool_input = tool_use.get("input", {})
|
|
303
|
+
file_path = tool_input.get("file_path", "")
|
|
304
|
+
text_or_blocks = tool_input.get("text_or_search_replace_blocks", "")
|
|
305
|
+
percentage = tool_input.get("percentage_to_change", 0)
|
|
306
|
+
|
|
307
|
+
has_diff = DiffWidget.has_search_replace_blocks(text_or_blocks)
|
|
308
|
+
|
|
309
|
+
dialog = QDialog(self.chat_window)
|
|
310
|
+
dialog.setWindowTitle("File Edit Confirmation")
|
|
311
|
+
dialog.setMinimumWidth(800 if has_diff else 600)
|
|
312
|
+
dialog.setMinimumHeight(600 if has_diff else 400)
|
|
313
|
+
|
|
314
|
+
layout = QVBoxLayout()
|
|
315
|
+
|
|
316
|
+
diff_colors = self.chat_window.style_provider.get_diff_colors()
|
|
317
|
+
header_label = QLabel(f"📝 <b>Edit File:</b> {file_path}")
|
|
318
|
+
header_label.setStyleSheet(
|
|
319
|
+
f"font-size: 14px; padding: 10px; color: {diff_colors.get('header_text', '#89b4fa')};"
|
|
320
|
+
)
|
|
321
|
+
layout.addWidget(header_label)
|
|
322
|
+
|
|
323
|
+
info_label = QLabel(
|
|
324
|
+
f"Change percentage: {percentage}% | "
|
|
325
|
+
f"Mode: {'Search/Replace Blocks' if has_diff else 'Full Content'}"
|
|
326
|
+
)
|
|
327
|
+
info_label.setStyleSheet(
|
|
328
|
+
f"font-size: 11px; color: {diff_colors.get('line_number_text', '#6c7086')}; padding: 0 10px;"
|
|
329
|
+
)
|
|
330
|
+
layout.addWidget(info_label)
|
|
331
|
+
|
|
332
|
+
scroll_area = QScrollArea()
|
|
333
|
+
scroll_area.setWidgetResizable(True)
|
|
334
|
+
scroll_area.setMinimumHeight(350)
|
|
335
|
+
|
|
336
|
+
if has_diff:
|
|
337
|
+
diff_widget = DiffWidget(style_provider=self.chat_window.style_provider)
|
|
338
|
+
diff_widget.set_diff_content(text_or_blocks, file_path)
|
|
339
|
+
scroll_area.setWidget(diff_widget)
|
|
340
|
+
else:
|
|
341
|
+
content_widget = QTextEdit()
|
|
342
|
+
content_widget.setReadOnly(True)
|
|
343
|
+
content_widget.setText(text_or_blocks)
|
|
344
|
+
content_widget.setStyleSheet(
|
|
345
|
+
self.chat_window.style_provider.get_tool_dialog_text_edit_style()
|
|
346
|
+
)
|
|
347
|
+
scroll_area.setWidget(content_widget)
|
|
348
|
+
|
|
349
|
+
layout.addWidget(scroll_area)
|
|
350
|
+
|
|
351
|
+
buttons_container = QWidget()
|
|
352
|
+
buttons_layout = QHBoxLayout(buttons_container)
|
|
353
|
+
buttons_layout.setContentsMargins(0, 10, 0, 0)
|
|
354
|
+
|
|
355
|
+
yes_button = QPushButton("✓ Approve")
|
|
356
|
+
yes_button.setStyleSheet(
|
|
357
|
+
self.chat_window.style_provider.get_tool_dialog_yes_button_style()
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
all_button = QPushButton("✓✓ Yes to All")
|
|
361
|
+
all_button.setStyleSheet(
|
|
362
|
+
self.chat_window.style_provider.get_tool_dialog_all_button_style()
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
forever_button = QPushButton("∞ Forever")
|
|
366
|
+
forever_button.setStyleSheet(
|
|
367
|
+
self.chat_window.style_provider.get_tool_dialog_all_button_style()
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
no_button = QPushButton("✗ Deny")
|
|
371
|
+
no_button.setStyleSheet(
|
|
372
|
+
self.chat_window.style_provider.get_tool_dialog_no_button_style()
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
buttons_layout.addWidget(yes_button)
|
|
376
|
+
buttons_layout.addWidget(all_button)
|
|
377
|
+
buttons_layout.addWidget(forever_button)
|
|
378
|
+
buttons_layout.addStretch()
|
|
379
|
+
buttons_layout.addWidget(no_button)
|
|
380
|
+
|
|
381
|
+
layout.addWidget(buttons_container)
|
|
382
|
+
|
|
383
|
+
dialog.setLayout(layout)
|
|
384
|
+
dialog.setStyleSheet(self.chat_window.style_provider.get_config_window_style())
|
|
385
|
+
|
|
386
|
+
result = {"action": ""}
|
|
387
|
+
|
|
388
|
+
def on_yes():
|
|
389
|
+
result["action"] = "approve"
|
|
390
|
+
dialog.accept()
|
|
391
|
+
|
|
392
|
+
def on_all():
|
|
393
|
+
result["action"] = "approve_all"
|
|
394
|
+
dialog.accept()
|
|
395
|
+
|
|
396
|
+
def on_forever():
|
|
397
|
+
result["action"] = "approve_forever"
|
|
398
|
+
dialog.accept()
|
|
399
|
+
|
|
400
|
+
def on_no():
|
|
401
|
+
result["action"] = "deny"
|
|
402
|
+
dialog.reject()
|
|
403
|
+
|
|
404
|
+
yes_button.clicked.connect(on_yes)
|
|
405
|
+
all_button.clicked.connect(on_all)
|
|
406
|
+
forever_button.clicked.connect(on_forever)
|
|
407
|
+
no_button.clicked.connect(on_no)
|
|
408
|
+
|
|
409
|
+
approve_shortcut = QShortcut(QKeySequence("Ctrl+Return"), dialog)
|
|
410
|
+
approve_shortcut.activated.connect(on_yes)
|
|
411
|
+
|
|
412
|
+
dialog.exec()
|
|
413
|
+
|
|
414
|
+
if result["action"] == "approve":
|
|
415
|
+
self.chat_window.message_handler.resolve_tool_confirmation(
|
|
416
|
+
confirmation_id, {"action": "approve"}
|
|
417
|
+
)
|
|
418
|
+
self.chat_window.display_status_message(f"Approved file edit: {file_path}")
|
|
419
|
+
|
|
420
|
+
elif result["action"] == "approve_all":
|
|
421
|
+
self.chat_window.message_handler.resolve_tool_confirmation(
|
|
422
|
+
confirmation_id, {"action": "approve_all"}
|
|
423
|
+
)
|
|
424
|
+
self.chat_window.display_status_message(
|
|
425
|
+
"Approved all future write_or_edit_file calls"
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
elif result["action"] == "approve_forever":
|
|
429
|
+
from AgentCrew.modules.config import ConfigManagement
|
|
430
|
+
|
|
431
|
+
config_manager = ConfigManagement()
|
|
432
|
+
config_manager.write_auto_approval_tools("write_or_edit_file", add=True)
|
|
433
|
+
|
|
434
|
+
self.chat_window.message_handler.resolve_tool_confirmation(
|
|
435
|
+
confirmation_id, {"action": "approve_all"}
|
|
436
|
+
)
|
|
437
|
+
self.chat_window.display_status_message(
|
|
438
|
+
"write_or_edit_file will be auto-approved forever"
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
else:
|
|
442
|
+
denial_reason = self.show_denial_reason_dialog("write_or_edit_file")
|
|
443
|
+
|
|
444
|
+
if denial_reason:
|
|
445
|
+
self.chat_window.message_handler.resolve_tool_confirmation(
|
|
446
|
+
confirmation_id, {"action": "deny", "reason": denial_reason}
|
|
447
|
+
)
|
|
448
|
+
self.chat_window.display_status_message(
|
|
449
|
+
f"Denied file edit - Reason: {denial_reason[:50]}..."
|
|
450
|
+
if len(denial_reason) > 50
|
|
451
|
+
else f"Denied file edit - Reason: {denial_reason}"
|
|
452
|
+
)
|
|
453
|
+
else:
|
|
454
|
+
self.chat_window.message_handler.resolve_tool_confirmation(
|
|
455
|
+
confirmation_id, {"action": "deny"}
|
|
456
|
+
)
|
|
457
|
+
self.chat_window.display_status_message("Denied file edit")
|
|
458
|
+
|
|
296
459
|
def _handle_ask_tool_confirmation(self, tool_use, confirmation_id):
|
|
297
460
|
"""Handle the ask tool - display question and guided answers in GUI."""
|
|
298
461
|
question = tool_use["input"].get("question", "")
|
|
@@ -1279,6 +1279,26 @@ QFrame {
|
|
|
1279
1279
|
"default": "🔧", # Default icon for unspecified tools
|
|
1280
1280
|
}
|
|
1281
1281
|
|
|
1282
|
+
# Diff Widget colors
|
|
1283
|
+
DIFF_COLORS = {
|
|
1284
|
+
"background": "#fafafa", # Light background
|
|
1285
|
+
"panel_bg": "#ffffff", # White
|
|
1286
|
+
"header_bg": "#e5e5e6", # Light gray
|
|
1287
|
+
"header_text": "#383a42", # Dark text
|
|
1288
|
+
"line_number_bg": "#f0f0f0", # Very light gray
|
|
1289
|
+
"line_number_text": "#9d9d9f", # Medium gray
|
|
1290
|
+
"removed_bg": "#ffeef0", # Light red background
|
|
1291
|
+
"removed_text": "#d73a49", # Red text
|
|
1292
|
+
"removed_highlight": "#d73a49", # Red for character highlight
|
|
1293
|
+
"added_bg": "#e6ffec", # Light green background
|
|
1294
|
+
"added_text": "#22863a", # Green text
|
|
1295
|
+
"added_highlight": "#22863a", # Green for character highlight
|
|
1296
|
+
"unchanged_text": "#9d9d9f", # Gray
|
|
1297
|
+
"border": "#e5e5e6", # Light border
|
|
1298
|
+
"block_header_bg": "#ddf4ff", # Light blue
|
|
1299
|
+
"block_header_text": "#0969da", # Blue text
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1282
1302
|
# JSON Editor styles
|
|
1283
1303
|
JSON_EDITOR_COLORS = {
|
|
1284
1304
|
"background": "#fafafa",
|
|
@@ -1318,6 +1318,26 @@ QFrame {
|
|
|
1318
1318
|
"default": "🔧", # Default icon for unspecified tools
|
|
1319
1319
|
}
|
|
1320
1320
|
|
|
1321
|
+
# Diff Widget colors
|
|
1322
|
+
DIFF_COLORS = {
|
|
1323
|
+
"background": "#1e1e2e", # Base
|
|
1324
|
+
"panel_bg": "#313244", # Surface0
|
|
1325
|
+
"header_bg": "#45475a", # Surface1
|
|
1326
|
+
"header_text": "#cdd6f4", # Text
|
|
1327
|
+
"line_number_bg": "#181825", # Mantle
|
|
1328
|
+
"line_number_text": "#6c7086", # Overlay0
|
|
1329
|
+
"removed_bg": "#3b2d33", # Subtle red background
|
|
1330
|
+
"removed_text": "#f38ba8", # Red
|
|
1331
|
+
"removed_highlight": "#f38ba8", # Red for character highlight
|
|
1332
|
+
"added_bg": "#2d3b33", # Subtle green background
|
|
1333
|
+
"added_text": "#a6e3a1", # Green
|
|
1334
|
+
"added_highlight": "#a6e3a1", # Green for character highlight
|
|
1335
|
+
"unchanged_text": "#6c7086", # Overlay0
|
|
1336
|
+
"border": "#45475a", # Surface1
|
|
1337
|
+
"block_header_bg": "#585b70", # Surface2
|
|
1338
|
+
"block_header_text": "#b4befe", # Lavender
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1321
1341
|
# JSON Editor styles
|
|
1322
1342
|
JSON_EDITOR_COLORS = {
|
|
1323
1343
|
"background": "#313244", # Surface0
|
|
@@ -1286,6 +1286,26 @@ QFrame {
|
|
|
1286
1286
|
"default": "🔧", # Default icon for unspecified tools
|
|
1287
1287
|
}
|
|
1288
1288
|
|
|
1289
|
+
# Diff Widget colors
|
|
1290
|
+
DIFF_COLORS = {
|
|
1291
|
+
"background": "#282a36", # Dracula Background
|
|
1292
|
+
"panel_bg": "#21222c", # Darker
|
|
1293
|
+
"header_bg": "#44475a", # Comment
|
|
1294
|
+
"header_text": "#f8f8f2", # Foreground
|
|
1295
|
+
"line_number_bg": "#1e1f29", # Very dark
|
|
1296
|
+
"line_number_text": "#6272a4", # Comment
|
|
1297
|
+
"removed_bg": "#3d2a36", # Subtle red background
|
|
1298
|
+
"removed_text": "#ff5555", # Red
|
|
1299
|
+
"removed_highlight": "#ff5555", # Red
|
|
1300
|
+
"added_bg": "#2a3d36", # Subtle green background
|
|
1301
|
+
"added_text": "#50fa7b", # Green
|
|
1302
|
+
"added_highlight": "#50fa7b", # Green
|
|
1303
|
+
"unchanged_text": "#6272a4", # Comment
|
|
1304
|
+
"border": "#44475a", # Border
|
|
1305
|
+
"block_header_bg": "#bd93f9", # Purple
|
|
1306
|
+
"block_header_text": "#282a36", # Background
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1289
1309
|
# JSON Editor styles
|
|
1290
1310
|
JSON_EDITOR_COLORS = {
|
|
1291
1311
|
"background": "#282a36",
|
|
@@ -1279,6 +1279,26 @@ QFrame {
|
|
|
1279
1279
|
"default": "🔧", # Default icon for unspecified tools
|
|
1280
1280
|
}
|
|
1281
1281
|
|
|
1282
|
+
# Diff Widget colors
|
|
1283
|
+
DIFF_COLORS = {
|
|
1284
|
+
"background": "#2e3440", # Polar Night
|
|
1285
|
+
"panel_bg": "#3b4252", # Polar Night lighter
|
|
1286
|
+
"header_bg": "#434c5e", # Polar Night
|
|
1287
|
+
"header_text": "#d8dee9", # Snow Storm
|
|
1288
|
+
"line_number_bg": "#2e3440", # Polar Night
|
|
1289
|
+
"line_number_text": "#4c566a", # Polar Night
|
|
1290
|
+
"removed_bg": "#3d2f3a", # Subtle red background
|
|
1291
|
+
"removed_text": "#bf616a", # Aurora Red
|
|
1292
|
+
"removed_highlight": "#bf616a", # Aurora Red
|
|
1293
|
+
"added_bg": "#2f3d38", # Subtle green background
|
|
1294
|
+
"added_text": "#a3be8c", # Aurora Green
|
|
1295
|
+
"added_highlight": "#a3be8c", # Aurora Green
|
|
1296
|
+
"unchanged_text": "#4c566a", # Polar Night
|
|
1297
|
+
"border": "#4c566a", # Border
|
|
1298
|
+
"block_header_bg": "#5e81ac", # Frost
|
|
1299
|
+
"block_header_text": "#eceff4", # Snow Storm
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1282
1302
|
# JSON Editor styles
|
|
1283
1303
|
JSON_EDITOR_COLORS = {
|
|
1284
1304
|
"background": "#2e3440",
|
|
@@ -1273,6 +1273,26 @@ QFrame {
|
|
|
1273
1273
|
"default": "🔧", # Default icon for unspecified tools
|
|
1274
1274
|
}
|
|
1275
1275
|
|
|
1276
|
+
# Diff Widget colors
|
|
1277
|
+
DIFF_COLORS = {
|
|
1278
|
+
"background": "#334155", # Slate 700
|
|
1279
|
+
"panel_bg": "#475569", # Slate 600
|
|
1280
|
+
"header_bg": "#1e293b", # Slate 800
|
|
1281
|
+
"header_text": "#f8fafc", # Slate 50
|
|
1282
|
+
"line_number_bg": "#1e293b", # Slate 800
|
|
1283
|
+
"line_number_text": "#64748b", # Slate 500
|
|
1284
|
+
"removed_bg": "#4c2c3a", # Subtle red
|
|
1285
|
+
"removed_text": "#fca5a5", # Red 300
|
|
1286
|
+
"removed_highlight": "#fca5a5", # Red 300
|
|
1287
|
+
"added_bg": "#2c4c3a", # Subtle green
|
|
1288
|
+
"added_text": "#7fb239", # Primary Green
|
|
1289
|
+
"added_highlight": "#7fb239", # Primary Green
|
|
1290
|
+
"unchanged_text": "#64748b", # Slate 500
|
|
1291
|
+
"border": "#475569", # Border
|
|
1292
|
+
"block_header_bg": "#638b2c", # Secondary Green
|
|
1293
|
+
"block_header_text": "#f8fafc", # Slate 50
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1276
1296
|
# JSON Editor styles
|
|
1277
1297
|
JSON_EDITOR_COLORS = {
|
|
1278
1298
|
"background": "#475569", # Input Fields - Slate 600
|
|
@@ -395,3 +395,28 @@ QPlainTextEdit:focus {
|
|
|
395
395
|
}
|
|
396
396
|
""",
|
|
397
397
|
)
|
|
398
|
+
|
|
399
|
+
def get_diff_colors(self):
|
|
400
|
+
"""Get color scheme for diff widget from current theme."""
|
|
401
|
+
return getattr(
|
|
402
|
+
self.theme_class,
|
|
403
|
+
"DIFF_COLORS",
|
|
404
|
+
{
|
|
405
|
+
"background": "#1e1e2e",
|
|
406
|
+
"panel_bg": "#313244",
|
|
407
|
+
"header_bg": "#45475a",
|
|
408
|
+
"header_text": "#cdd6f4",
|
|
409
|
+
"line_number_bg": "#181825",
|
|
410
|
+
"line_number_text": "#6c7086",
|
|
411
|
+
"removed_bg": "#3b2d33",
|
|
412
|
+
"removed_text": "#f38ba8",
|
|
413
|
+
"removed_highlight": "#f38ba8",
|
|
414
|
+
"added_bg": "#2d3b33",
|
|
415
|
+
"added_text": "#a6e3a1",
|
|
416
|
+
"added_highlight": "#a6e3a1",
|
|
417
|
+
"unchanged_text": "#6c7086",
|
|
418
|
+
"border": "#45475a",
|
|
419
|
+
"block_header_bg": "#585b70",
|
|
420
|
+
"block_header_text": "#b4befe",
|
|
421
|
+
},
|
|
422
|
+
)
|
|
@@ -1286,6 +1286,26 @@ QFrame {
|
|
|
1286
1286
|
"default": "🔧", # Default icon for unspecified tools
|
|
1287
1287
|
}
|
|
1288
1288
|
|
|
1289
|
+
# Diff Widget colors
|
|
1290
|
+
DIFF_COLORS = {
|
|
1291
|
+
"background": "#f8fafc", # Very light background
|
|
1292
|
+
"panel_bg": "#ffffff", # White
|
|
1293
|
+
"header_bg": "#f1f5f9", # Light slate
|
|
1294
|
+
"header_text": "#374151", # Dark text
|
|
1295
|
+
"line_number_bg": "#f8fafc", # Very light
|
|
1296
|
+
"line_number_text": "#9ca3af", # Gray
|
|
1297
|
+
"removed_bg": "#fef2f2", # Light red
|
|
1298
|
+
"removed_text": "#ef4444", # Red
|
|
1299
|
+
"removed_highlight": "#ef4444", # Red
|
|
1300
|
+
"added_bg": "#ecfdf5", # Light green
|
|
1301
|
+
"added_text": "#10b981", # Green
|
|
1302
|
+
"added_highlight": "#10b981", # Green
|
|
1303
|
+
"unchanged_text": "#9ca3af", # Gray
|
|
1304
|
+
"border": "#d1d5db", # Border
|
|
1305
|
+
"block_header_bg": "#e0e7ff", # Light purple
|
|
1306
|
+
"block_header_text": "#6b46c1", # Purple
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1289
1309
|
# JSON Editor styles
|
|
1290
1310
|
JSON_EDITOR_COLORS = {
|
|
1291
1311
|
"background": "#ffffff",
|
|
@@ -3,6 +3,7 @@ from .system_message import SystemMessageWidget
|
|
|
3
3
|
from .message_bubble import MessageBubble
|
|
4
4
|
from .history_sidebar import ConversationSidebar, ConversationLoader
|
|
5
5
|
from .tool_widget import ToolWidget
|
|
6
|
+
from .diff_widget import DiffWidget, CompactDiffWidget
|
|
6
7
|
|
|
7
8
|
__all__ = [
|
|
8
9
|
"TokenUsageWidget",
|
|
@@ -11,4 +12,6 @@ __all__ = [
|
|
|
11
12
|
"ConversationSidebar",
|
|
12
13
|
"ConversationLoader",
|
|
13
14
|
"ToolWidget",
|
|
15
|
+
"DiffWidget",
|
|
16
|
+
"CompactDiffWidget",
|
|
14
17
|
]
|
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Diff display widget for GUI showing file changes with split view.
|
|
3
|
+
Provides visual diff comparison for search/replace blocks.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import difflib
|
|
7
|
+
from typing import List, Dict
|
|
8
|
+
from PySide6.QtWidgets import (
|
|
9
|
+
QWidget,
|
|
10
|
+
QVBoxLayout,
|
|
11
|
+
QLabel,
|
|
12
|
+
QFrame,
|
|
13
|
+
)
|
|
14
|
+
from PySide6.QtCore import Qt
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DiffWidget(QWidget):
|
|
18
|
+
"""Widget to display split diff view for file changes."""
|
|
19
|
+
|
|
20
|
+
SEARCH_DELIMITER = "<<<<<<< SEARCH"
|
|
21
|
+
MIDDLE_DELIMITER = "======="
|
|
22
|
+
REPLACE_DELIMITER = ">>>>>>> REPLACE"
|
|
23
|
+
|
|
24
|
+
def __init__(self, parent=None, style_provider=None):
|
|
25
|
+
super().__init__(parent)
|
|
26
|
+
self._style_provider = style_provider
|
|
27
|
+
self._colors = self._get_colors()
|
|
28
|
+
self.setup_ui()
|
|
29
|
+
|
|
30
|
+
def _get_colors(self):
|
|
31
|
+
"""Get colors from style provider or use defaults."""
|
|
32
|
+
if self._style_provider:
|
|
33
|
+
return self._style_provider.get_diff_colors()
|
|
34
|
+
return {
|
|
35
|
+
"background": "#1e1e2e",
|
|
36
|
+
"panel_bg": "#313244",
|
|
37
|
+
"header_bg": "#45475a",
|
|
38
|
+
"header_text": "#cdd6f4",
|
|
39
|
+
"line_number_bg": "#181825",
|
|
40
|
+
"line_number_text": "#6c7086",
|
|
41
|
+
"removed_bg": "#3b2d33",
|
|
42
|
+
"removed_text": "#f38ba8",
|
|
43
|
+
"removed_highlight": "#f38ba8",
|
|
44
|
+
"added_bg": "#2d3b33",
|
|
45
|
+
"added_text": "#a6e3a1",
|
|
46
|
+
"added_highlight": "#a6e3a1",
|
|
47
|
+
"unchanged_text": "#6c7086",
|
|
48
|
+
"border": "#45475a",
|
|
49
|
+
"block_header_bg": "#585b70",
|
|
50
|
+
"block_header_text": "#b4befe",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
def set_style_provider(self, style_provider):
|
|
54
|
+
"""Update style provider and refresh colors."""
|
|
55
|
+
self._style_provider = style_provider
|
|
56
|
+
self._colors = self._get_colors()
|
|
57
|
+
|
|
58
|
+
def setup_ui(self):
|
|
59
|
+
"""Setup the main layout."""
|
|
60
|
+
self.main_layout = QVBoxLayout(self)
|
|
61
|
+
self.main_layout.setContentsMargins(0, 0, 0, 0)
|
|
62
|
+
self.main_layout.setSpacing(8)
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def has_search_replace_blocks(text: str) -> bool:
|
|
66
|
+
"""Check if text contains search/replace blocks."""
|
|
67
|
+
return (
|
|
68
|
+
"<<<<<<< SEARCH" in text and "=======" in text and ">>>>>>> REPLACE" in text
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def parse_search_replace_blocks(blocks_text: str) -> List[Dict]:
|
|
73
|
+
"""
|
|
74
|
+
Parse search/replace blocks from text.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
List of dicts with 'index', 'search', and 'replace' keys
|
|
78
|
+
"""
|
|
79
|
+
blocks = []
|
|
80
|
+
lines = blocks_text.split("\n")
|
|
81
|
+
i = 0
|
|
82
|
+
block_index = 0
|
|
83
|
+
|
|
84
|
+
while i < len(lines):
|
|
85
|
+
if lines[i].strip() == "<<<<<<< SEARCH":
|
|
86
|
+
search_lines = []
|
|
87
|
+
i += 1
|
|
88
|
+
|
|
89
|
+
while i < len(lines) and lines[i].strip() != "=======":
|
|
90
|
+
search_lines.append(lines[i])
|
|
91
|
+
i += 1
|
|
92
|
+
|
|
93
|
+
if i >= len(lines):
|
|
94
|
+
break
|
|
95
|
+
|
|
96
|
+
i += 1
|
|
97
|
+
replace_lines = []
|
|
98
|
+
|
|
99
|
+
while (
|
|
100
|
+
i < len(lines)
|
|
101
|
+
and lines[i].strip() != ">>>>>>> REPLACE"
|
|
102
|
+
and lines[i].strip() != "======="
|
|
103
|
+
):
|
|
104
|
+
replace_lines.append(lines[i])
|
|
105
|
+
i += 1
|
|
106
|
+
|
|
107
|
+
if i >= len(lines):
|
|
108
|
+
break
|
|
109
|
+
|
|
110
|
+
blocks.append(
|
|
111
|
+
{
|
|
112
|
+
"index": block_index,
|
|
113
|
+
"search": "\n".join(search_lines),
|
|
114
|
+
"replace": "\n".join(replace_lines),
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
block_index += 1
|
|
118
|
+
i += 1
|
|
119
|
+
else:
|
|
120
|
+
i += 1
|
|
121
|
+
|
|
122
|
+
return blocks
|
|
123
|
+
|
|
124
|
+
def set_diff_content(self, blocks_text: str, file_path: str = ""):
|
|
125
|
+
"""
|
|
126
|
+
Set the diff content to display.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
blocks_text: Text containing search/replace blocks
|
|
130
|
+
file_path: Optional file path to display in header
|
|
131
|
+
"""
|
|
132
|
+
self._clear_layout()
|
|
133
|
+
colors = self._colors
|
|
134
|
+
|
|
135
|
+
if file_path:
|
|
136
|
+
header = QLabel(f"📝 File: {file_path}")
|
|
137
|
+
header.setStyleSheet(
|
|
138
|
+
f"font-weight: bold; font-size: 13px; padding: 4px; color: {colors['block_header_text']};"
|
|
139
|
+
)
|
|
140
|
+
self.main_layout.addWidget(header)
|
|
141
|
+
|
|
142
|
+
blocks = self.parse_search_replace_blocks(blocks_text)
|
|
143
|
+
|
|
144
|
+
if not blocks:
|
|
145
|
+
no_blocks_label = QLabel("No valid search/replace blocks found")
|
|
146
|
+
no_blocks_label.setStyleSheet(
|
|
147
|
+
f"color: {colors['removed_text']}; padding: 8px;"
|
|
148
|
+
)
|
|
149
|
+
self.main_layout.addWidget(no_blocks_label)
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
for idx, block in enumerate(blocks):
|
|
153
|
+
if idx > 0:
|
|
154
|
+
separator = QFrame()
|
|
155
|
+
separator.setFrameShape(QFrame.Shape.HLine)
|
|
156
|
+
separator.setStyleSheet(
|
|
157
|
+
f"background-color: {colors['border']}; margin: 4px 0;"
|
|
158
|
+
)
|
|
159
|
+
self.main_layout.addWidget(separator)
|
|
160
|
+
|
|
161
|
+
block_widget = self._create_diff_block(
|
|
162
|
+
block["search"], block["replace"], idx + 1
|
|
163
|
+
)
|
|
164
|
+
self.main_layout.addWidget(block_widget)
|
|
165
|
+
|
|
166
|
+
def _clear_layout(self):
|
|
167
|
+
"""Clear all widgets from the layout."""
|
|
168
|
+
while self.main_layout.count():
|
|
169
|
+
item = self.main_layout.takeAt(0)
|
|
170
|
+
if item.widget():
|
|
171
|
+
item.widget().deleteLater()
|
|
172
|
+
|
|
173
|
+
def _create_diff_block(
|
|
174
|
+
self, original: str, modified: str, block_num: int
|
|
175
|
+
) -> QWidget:
|
|
176
|
+
"""Create a single diff block widget."""
|
|
177
|
+
colors = self._colors
|
|
178
|
+
container = QWidget()
|
|
179
|
+
container_layout = QVBoxLayout(container)
|
|
180
|
+
container_layout.setContentsMargins(0, 0, 0, 0)
|
|
181
|
+
container_layout.setSpacing(4)
|
|
182
|
+
|
|
183
|
+
block_header = QLabel(f"Block {block_num}")
|
|
184
|
+
block_header.setStyleSheet(
|
|
185
|
+
f"font-weight: bold; font-size: 11px; color: {colors['header_text']}; padding: 2px;"
|
|
186
|
+
)
|
|
187
|
+
container_layout.addWidget(block_header)
|
|
188
|
+
|
|
189
|
+
# diff_container = QWidget()
|
|
190
|
+
# diff_layout = QHBoxLayout(diff_container)
|
|
191
|
+
# diff_layout.setContentsMargins(0, 0, 0, 0)
|
|
192
|
+
# diff_layout.setSpacing(8)
|
|
193
|
+
#
|
|
194
|
+
# original_panel = self._create_side_panel("Original", original, is_original=True)
|
|
195
|
+
# modified_panel = self._create_side_panel(
|
|
196
|
+
# "Modified", modified, is_original=False
|
|
197
|
+
# )
|
|
198
|
+
#
|
|
199
|
+
# diff_layout.addWidget(original_panel, 1)
|
|
200
|
+
# diff_layout.addWidget(modified_panel, 1)
|
|
201
|
+
|
|
202
|
+
# container_layout.addWidget(diff_container)
|
|
203
|
+
|
|
204
|
+
diff_view = self._create_inline_diff(original, modified)
|
|
205
|
+
container_layout.addWidget(diff_view)
|
|
206
|
+
|
|
207
|
+
return container
|
|
208
|
+
|
|
209
|
+
def _create_side_panel(
|
|
210
|
+
self, title: str, content: str, is_original: bool
|
|
211
|
+
) -> QWidget:
|
|
212
|
+
"""Create a side panel for original or modified content."""
|
|
213
|
+
colors = self._colors
|
|
214
|
+
panel = QFrame()
|
|
215
|
+
panel.setFrameShape(QFrame.Shape.StyledPanel)
|
|
216
|
+
|
|
217
|
+
bg_color = colors["removed_bg"] if is_original else colors["added_bg"]
|
|
218
|
+
border_color = colors["removed_text"] if is_original else colors["added_text"]
|
|
219
|
+
text_color = colors["removed_text"] if is_original else colors["added_text"]
|
|
220
|
+
|
|
221
|
+
panel.setStyleSheet(
|
|
222
|
+
f"""
|
|
223
|
+
QFrame {{
|
|
224
|
+
background-color: {bg_color};
|
|
225
|
+
border: 1px solid {border_color};
|
|
226
|
+
border-radius: 4px;
|
|
227
|
+
}}
|
|
228
|
+
"""
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
layout = QVBoxLayout(panel)
|
|
232
|
+
layout.setContentsMargins(8, 4, 8, 8)
|
|
233
|
+
layout.setSpacing(4)
|
|
234
|
+
|
|
235
|
+
header = QLabel(title)
|
|
236
|
+
header.setStyleSheet(
|
|
237
|
+
f"font-weight: bold; font-size: 11px; color: {text_color}; padding: 2px;"
|
|
238
|
+
)
|
|
239
|
+
layout.addWidget(header)
|
|
240
|
+
|
|
241
|
+
content_label = QLabel(content if content else "(empty)")
|
|
242
|
+
content_label.setWordWrap(True)
|
|
243
|
+
content_label.setTextInteractionFlags(
|
|
244
|
+
Qt.TextInteractionFlag.TextSelectableByMouse
|
|
245
|
+
)
|
|
246
|
+
content_label.setStyleSheet(
|
|
247
|
+
f"""
|
|
248
|
+
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
|
249
|
+
font-size: 12px;
|
|
250
|
+
color: {text_color};
|
|
251
|
+
padding: 4px;
|
|
252
|
+
"""
|
|
253
|
+
)
|
|
254
|
+
layout.addWidget(content_label)
|
|
255
|
+
|
|
256
|
+
return panel
|
|
257
|
+
|
|
258
|
+
def _create_inline_diff(self, original: str, modified: str) -> QWidget:
|
|
259
|
+
"""Create inline diff view with character-level highlighting."""
|
|
260
|
+
colors = self._colors
|
|
261
|
+
container = QFrame()
|
|
262
|
+
container.setStyleSheet(
|
|
263
|
+
f"""
|
|
264
|
+
QFrame {{
|
|
265
|
+
background-color: {colors["background"]};
|
|
266
|
+
border: 1px solid {colors["border"]};
|
|
267
|
+
border-radius: 4px;
|
|
268
|
+
}}
|
|
269
|
+
"""
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
layout = QVBoxLayout(container)
|
|
273
|
+
layout.setContentsMargins(8, 8, 8, 8)
|
|
274
|
+
layout.setSpacing(2)
|
|
275
|
+
|
|
276
|
+
original_lines = original.split("\n")
|
|
277
|
+
modified_lines = modified.split("\n")
|
|
278
|
+
|
|
279
|
+
matcher = difflib.SequenceMatcher(None, original_lines, modified_lines)
|
|
280
|
+
|
|
281
|
+
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
|
|
282
|
+
if tag == "equal":
|
|
283
|
+
for i in range(i1, i2):
|
|
284
|
+
line_label = self._create_diff_line(
|
|
285
|
+
f" {original_lines[i]}", "equal"
|
|
286
|
+
)
|
|
287
|
+
layout.addWidget(line_label)
|
|
288
|
+
|
|
289
|
+
elif tag == "delete":
|
|
290
|
+
for i in range(i1, i2):
|
|
291
|
+
line_label = self._create_diff_line(
|
|
292
|
+
f"- {original_lines[i]}", "delete"
|
|
293
|
+
)
|
|
294
|
+
layout.addWidget(line_label)
|
|
295
|
+
|
|
296
|
+
elif tag == "insert":
|
|
297
|
+
for j in range(j1, j2):
|
|
298
|
+
line_label = self._create_diff_line(
|
|
299
|
+
f"+ {modified_lines[j]}", "insert"
|
|
300
|
+
)
|
|
301
|
+
layout.addWidget(line_label)
|
|
302
|
+
|
|
303
|
+
elif tag == "replace":
|
|
304
|
+
max_lines = max(i2 - i1, j2 - j1)
|
|
305
|
+
|
|
306
|
+
for offset in range(max_lines):
|
|
307
|
+
orig_idx = i1 + offset
|
|
308
|
+
mod_idx = j1 + offset
|
|
309
|
+
|
|
310
|
+
if orig_idx < i2:
|
|
311
|
+
line_label = self._create_diff_line(
|
|
312
|
+
f"- {original_lines[orig_idx]}", "delete"
|
|
313
|
+
)
|
|
314
|
+
layout.addWidget(line_label)
|
|
315
|
+
|
|
316
|
+
if mod_idx < j2:
|
|
317
|
+
line_label = self._create_diff_line(
|
|
318
|
+
f"+ {modified_lines[mod_idx]}", "insert"
|
|
319
|
+
)
|
|
320
|
+
layout.addWidget(line_label)
|
|
321
|
+
|
|
322
|
+
return container
|
|
323
|
+
|
|
324
|
+
def _create_diff_line(self, text: str, line_type: str) -> QLabel:
|
|
325
|
+
"""Create a single diff line label with appropriate styling."""
|
|
326
|
+
colors = self._colors
|
|
327
|
+
label = QLabel(text)
|
|
328
|
+
label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
|
|
329
|
+
|
|
330
|
+
base_font = "font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 11px;"
|
|
331
|
+
|
|
332
|
+
if line_type == "equal":
|
|
333
|
+
style = f"{base_font} color: {colors['unchanged_text']}; padding: 1px 4px;"
|
|
334
|
+
elif line_type == "delete":
|
|
335
|
+
style = f"{base_font} color: {colors['removed_text']}; background-color: {colors['removed_bg']}; padding: 1px 4px; border-radius: 2px;"
|
|
336
|
+
elif line_type == "insert":
|
|
337
|
+
style = f"{base_font} color: {colors['added_text']}; background-color: {colors['added_bg']}; padding: 1px 4px; border-radius: 2px;"
|
|
338
|
+
else:
|
|
339
|
+
style = f"{base_font} color: {colors['header_text']}; padding: 1px 4px;"
|
|
340
|
+
|
|
341
|
+
label.setStyleSheet(style)
|
|
342
|
+
return label
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class CompactDiffWidget(QWidget):
|
|
346
|
+
"""Compact diff widget for use inside ToolWidget."""
|
|
347
|
+
|
|
348
|
+
def __init__(self, parent=None, style_provider=None):
|
|
349
|
+
super().__init__(parent)
|
|
350
|
+
self._style_provider = style_provider
|
|
351
|
+
self._colors = self._get_colors()
|
|
352
|
+
self.setup_ui()
|
|
353
|
+
|
|
354
|
+
def _get_colors(self):
|
|
355
|
+
"""Get colors from style provider or use defaults."""
|
|
356
|
+
if self._style_provider:
|
|
357
|
+
return self._style_provider.get_diff_colors()
|
|
358
|
+
return {
|
|
359
|
+
"background": "#1e1e2e",
|
|
360
|
+
"panel_bg": "#313244",
|
|
361
|
+
"border": "#45475a",
|
|
362
|
+
"removed_bg": "#2d0a0a",
|
|
363
|
+
"removed_text": "#f38ba8",
|
|
364
|
+
"added_bg": "#0a2d0a",
|
|
365
|
+
"added_text": "#a6e3a1",
|
|
366
|
+
"unchanged_text": "#585b70",
|
|
367
|
+
"line_number_text": "#6c7086",
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
def set_style_provider(self, style_provider):
|
|
371
|
+
"""Update style provider and refresh colors."""
|
|
372
|
+
self._style_provider = style_provider
|
|
373
|
+
self._colors = self._get_colors()
|
|
374
|
+
|
|
375
|
+
def setup_ui(self):
|
|
376
|
+
"""Setup the compact layout."""
|
|
377
|
+
self.main_layout = QVBoxLayout(self)
|
|
378
|
+
self.main_layout.setContentsMargins(4, 4, 4, 4)
|
|
379
|
+
self.main_layout.setSpacing(4)
|
|
380
|
+
|
|
381
|
+
def set_diff_content(self, blocks_text: str, file_path: str = ""):
|
|
382
|
+
"""Set the diff content to display in compact form."""
|
|
383
|
+
self._clear_layout()
|
|
384
|
+
colors = self._colors
|
|
385
|
+
|
|
386
|
+
blocks = DiffWidget.parse_search_replace_blocks(blocks_text)
|
|
387
|
+
|
|
388
|
+
if not blocks:
|
|
389
|
+
return
|
|
390
|
+
|
|
391
|
+
for idx, block in enumerate(blocks):
|
|
392
|
+
if idx > 0:
|
|
393
|
+
separator = QFrame()
|
|
394
|
+
separator.setFrameShape(QFrame.Shape.HLine)
|
|
395
|
+
separator.setFixedHeight(1)
|
|
396
|
+
separator.setStyleSheet(f"background-color: {colors['border']};")
|
|
397
|
+
self.main_layout.addWidget(separator)
|
|
398
|
+
|
|
399
|
+
diff_view = self._create_compact_diff(
|
|
400
|
+
block["search"], block["replace"], idx + 1
|
|
401
|
+
)
|
|
402
|
+
self.main_layout.addWidget(diff_view)
|
|
403
|
+
|
|
404
|
+
def _clear_layout(self):
|
|
405
|
+
"""Clear all widgets from the layout."""
|
|
406
|
+
while self.main_layout.count():
|
|
407
|
+
item = self.main_layout.takeAt(0)
|
|
408
|
+
if item.widget():
|
|
409
|
+
item.widget().deleteLater()
|
|
410
|
+
|
|
411
|
+
def _create_compact_diff(
|
|
412
|
+
self, original: str, modified: str, block_num: int
|
|
413
|
+
) -> QWidget:
|
|
414
|
+
"""Create a compact inline diff view."""
|
|
415
|
+
colors = self._colors
|
|
416
|
+
container = QFrame()
|
|
417
|
+
container.setStyleSheet(
|
|
418
|
+
f"""
|
|
419
|
+
QFrame {{
|
|
420
|
+
background-color: {colors["background"]};
|
|
421
|
+
border: 1px solid {colors["panel_bg"]};
|
|
422
|
+
border-radius: 4px;
|
|
423
|
+
}}
|
|
424
|
+
"""
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
layout = QVBoxLayout(container)
|
|
428
|
+
layout.setContentsMargins(6, 6, 6, 6)
|
|
429
|
+
layout.setSpacing(1)
|
|
430
|
+
|
|
431
|
+
if len(DiffWidget.parse_search_replace_blocks(original + modified)) > 1:
|
|
432
|
+
block_header = QLabel(f"Block {block_num}")
|
|
433
|
+
block_header.setStyleSheet(
|
|
434
|
+
f"font-size: 10px; color: {colors['line_number_text']}; padding: 0 0 2px 0;"
|
|
435
|
+
)
|
|
436
|
+
layout.addWidget(block_header)
|
|
437
|
+
|
|
438
|
+
original_lines = original.split("\n")
|
|
439
|
+
modified_lines = modified.split("\n")
|
|
440
|
+
|
|
441
|
+
matcher = difflib.SequenceMatcher(None, original_lines, modified_lines)
|
|
442
|
+
|
|
443
|
+
max_display_lines = 20
|
|
444
|
+
line_count = 0
|
|
445
|
+
|
|
446
|
+
for tag, i1, i2, j1, j2 in matcher.get_opcodes():
|
|
447
|
+
if line_count >= max_display_lines:
|
|
448
|
+
truncate_label = QLabel("... (diff truncated)")
|
|
449
|
+
truncate_label.setStyleSheet(
|
|
450
|
+
f"font-size: 10px; color: {colors['line_number_text']}; font-style: italic;"
|
|
451
|
+
)
|
|
452
|
+
layout.addWidget(truncate_label)
|
|
453
|
+
break
|
|
454
|
+
|
|
455
|
+
if tag == "equal":
|
|
456
|
+
lines_to_show = min(2, i2 - i1)
|
|
457
|
+
if i2 - i1 > 2:
|
|
458
|
+
context_label = QLabel(f" ... ({i2 - i1 - 2} unchanged lines)")
|
|
459
|
+
context_label.setStyleSheet(
|
|
460
|
+
f"font-size: 10px; color: {colors['unchanged_text']}; font-style: italic;"
|
|
461
|
+
)
|
|
462
|
+
layout.addWidget(context_label)
|
|
463
|
+
line_count += 1
|
|
464
|
+
|
|
465
|
+
for i in range(i1, min(i1 + lines_to_show, i2)):
|
|
466
|
+
line_label = self._create_compact_line(
|
|
467
|
+
f" {original_lines[i]}", "equal"
|
|
468
|
+
)
|
|
469
|
+
layout.addWidget(line_label)
|
|
470
|
+
line_count += 1
|
|
471
|
+
|
|
472
|
+
elif tag == "delete":
|
|
473
|
+
for i in range(i1, i2):
|
|
474
|
+
if line_count >= max_display_lines:
|
|
475
|
+
break
|
|
476
|
+
line_label = self._create_compact_line(
|
|
477
|
+
f"- {original_lines[i]}", "delete"
|
|
478
|
+
)
|
|
479
|
+
layout.addWidget(line_label)
|
|
480
|
+
line_count += 1
|
|
481
|
+
|
|
482
|
+
elif tag == "insert":
|
|
483
|
+
for j in range(j1, j2):
|
|
484
|
+
if line_count >= max_display_lines:
|
|
485
|
+
break
|
|
486
|
+
line_label = self._create_compact_line(
|
|
487
|
+
f"+ {modified_lines[j]}", "insert"
|
|
488
|
+
)
|
|
489
|
+
layout.addWidget(line_label)
|
|
490
|
+
line_count += 1
|
|
491
|
+
|
|
492
|
+
elif tag == "replace":
|
|
493
|
+
for i in range(i1, i2):
|
|
494
|
+
if line_count >= max_display_lines:
|
|
495
|
+
break
|
|
496
|
+
line_label = self._create_compact_line(
|
|
497
|
+
f"- {original_lines[i]}", "delete"
|
|
498
|
+
)
|
|
499
|
+
layout.addWidget(line_label)
|
|
500
|
+
line_count += 1
|
|
501
|
+
|
|
502
|
+
for j in range(j1, j2):
|
|
503
|
+
if line_count >= max_display_lines:
|
|
504
|
+
break
|
|
505
|
+
line_label = self._create_compact_line(
|
|
506
|
+
f"+ {modified_lines[j]}", "insert"
|
|
507
|
+
)
|
|
508
|
+
layout.addWidget(line_label)
|
|
509
|
+
line_count += 1
|
|
510
|
+
|
|
511
|
+
return container
|
|
512
|
+
|
|
513
|
+
def _create_compact_line(self, text: str, line_type: str) -> QLabel:
|
|
514
|
+
"""Create a compact diff line label."""
|
|
515
|
+
colors = self._colors
|
|
516
|
+
label = QLabel(text)
|
|
517
|
+
label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
|
|
518
|
+
|
|
519
|
+
base_style = "font-family: monospace; font-size: 11px; padding: 0 2px;"
|
|
520
|
+
|
|
521
|
+
if line_type == "equal":
|
|
522
|
+
label.setStyleSheet(f"{base_style} color: {colors['unchanged_text']};")
|
|
523
|
+
elif line_type == "delete":
|
|
524
|
+
label.setStyleSheet(
|
|
525
|
+
f"{base_style} color: {colors['removed_text']}; background-color: {colors['removed_bg']};"
|
|
526
|
+
)
|
|
527
|
+
elif line_type == "insert":
|
|
528
|
+
label.setStyleSheet(
|
|
529
|
+
f"{base_style} color: {colors['added_text']}; background-color: {colors['added_bg']};"
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
return label
|
|
@@ -12,6 +12,7 @@ from PySide6.QtWidgets import (
|
|
|
12
12
|
)
|
|
13
13
|
from PySide6.QtCore import Qt
|
|
14
14
|
from AgentCrew.modules.gui.themes import StyleProvider
|
|
15
|
+
from AgentCrew.modules.gui.widgets.diff_widget import DiffWidget, CompactDiffWidget
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class ToolWidget(QWidget):
|
|
@@ -46,6 +47,7 @@ class ToolWidget(QWidget):
|
|
|
46
47
|
self.is_error = is_error
|
|
47
48
|
self.is_expanded = False
|
|
48
49
|
self.style_provider = StyleProvider()
|
|
50
|
+
self.is_diff_view = False
|
|
49
51
|
|
|
50
52
|
# Setup main layout - reduced margins and spacing for compactness
|
|
51
53
|
self.main_layout = QVBoxLayout(self)
|
|
@@ -138,22 +140,55 @@ class ToolWidget(QWidget):
|
|
|
138
140
|
|
|
139
141
|
def _create_content_section(self):
|
|
140
142
|
"""Create the single collapsible content section containing input and result"""
|
|
141
|
-
# Container for all content (input + result) - more compact
|
|
142
143
|
self.content_container = QWidget()
|
|
143
144
|
self.content_layout = QVBoxLayout(self.content_container)
|
|
144
|
-
self.content_layout.setContentsMargins(0, 2, 0, 0)
|
|
145
|
-
self.content_layout.setSpacing(4)
|
|
145
|
+
self.content_layout.setContentsMargins(0, 2, 0, 0)
|
|
146
|
+
self.content_layout.setSpacing(4)
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
if self._should_show_diff_view():
|
|
149
|
+
self._add_diff_content()
|
|
150
|
+
else:
|
|
151
|
+
self._add_input_content()
|
|
149
152
|
|
|
150
|
-
# Add result section if we have result data
|
|
151
153
|
if self.result_data is not None:
|
|
152
154
|
self._add_result_content()
|
|
153
155
|
|
|
154
|
-
# Add to card layout
|
|
155
156
|
self.card_layout.addWidget(self.content_container)
|
|
156
157
|
|
|
158
|
+
def _should_show_diff_view(self) -> bool:
|
|
159
|
+
"""Check if this tool should display a diff view."""
|
|
160
|
+
if self.tool_name != "write_or_edit_file":
|
|
161
|
+
return False
|
|
162
|
+
|
|
163
|
+
arg_key = "input" if "input" in self.tool_data else "arguments"
|
|
164
|
+
tool_params = self.tool_data.get(arg_key, {})
|
|
165
|
+
|
|
166
|
+
if not isinstance(tool_params, dict):
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
text_or_blocks = tool_params.get("text_or_search_replace_blocks", "")
|
|
170
|
+
return DiffWidget.has_search_replace_blocks(text_or_blocks)
|
|
171
|
+
|
|
172
|
+
def _add_diff_content(self):
|
|
173
|
+
"""Add diff view content for write_or_edit_file tool."""
|
|
174
|
+
self.is_diff_view = True
|
|
175
|
+
|
|
176
|
+
arg_key = "input" if "input" in self.tool_data else "arguments"
|
|
177
|
+
tool_params = self.tool_data.get(arg_key, {})
|
|
178
|
+
file_path = tool_params.get("file_path", "")
|
|
179
|
+
text_or_blocks = tool_params.get("text_or_search_replace_blocks", "")
|
|
180
|
+
|
|
181
|
+
diff_colors = self.style_provider.get_diff_colors()
|
|
182
|
+
file_label = QLabel(f"📝 <b>File:</b> {file_path}")
|
|
183
|
+
file_label.setStyleSheet(
|
|
184
|
+
f"font-size: 12px; color: {diff_colors.get('header_text', '#89b4fa')}; padding: 2px;"
|
|
185
|
+
)
|
|
186
|
+
self.content_layout.addWidget(file_label)
|
|
187
|
+
|
|
188
|
+
diff_widget = CompactDiffWidget(style_provider=self.style_provider)
|
|
189
|
+
diff_widget.set_diff_content(text_or_blocks, file_path)
|
|
190
|
+
self.content_layout.addWidget(diff_widget)
|
|
191
|
+
|
|
157
192
|
def _add_input_content(self):
|
|
158
193
|
"""Add input parameters to the content section"""
|
|
159
194
|
# Input title
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
AgentCrew/__init__.py,sha256=
|
|
2
|
-
AgentCrew/app.py,sha256=
|
|
1
|
+
AgentCrew/__init__.py,sha256=vTwvdJOZi8jZb9U-Em7-d50qNDNPS2z51IXqRoojeNM,22
|
|
2
|
+
AgentCrew/app.py,sha256=s3pPfZfaZYxCNUC3HYWVQScK1iQZil6_Xguht3XX6mc,36603
|
|
3
3
|
AgentCrew/main.py,sha256=tjyw4Z29YKKyzVKqDgF5icI1IM59DUiJrXZw6Sv_xN8,11187
|
|
4
4
|
AgentCrew/main_docker.py,sha256=1jpB-XOm-t3GWTKYidGHHkCSzJ-p39ua0E6-_Nj8_9Y,5472
|
|
5
5
|
AgentCrew/assets/agentcrew_logo.png,sha256=bA4WQ9QrZXxBd_GfbR2s5GWBRrRodzeDynQj7XHIPNw,944381
|
|
@@ -8,9 +8,9 @@ AgentCrew/modules/a2a/__init__.py,sha256=gFX0PAA6sxCRyAo_Gbs81cK2FckW11GnTxMhQpc
|
|
|
8
8
|
AgentCrew/modules/a2a/adapters.py,sha256=GOTZVstQOhMus1QWcqVQZXEmPovfhxRrJ9loUtypGSY,7989
|
|
9
9
|
AgentCrew/modules/a2a/agent_cards.py,sha256=SWmo3jVNSrPUqpL8Tv6T3h1a-0oXrOgqJrbPy7tz5XQ,4098
|
|
10
10
|
AgentCrew/modules/a2a/errors.py,sha256=Yaw7Ew5LYDvrYgKZ34heBnEqlIXFF3_5GqqpNhNlveI,2353
|
|
11
|
-
AgentCrew/modules/a2a/registry.py,sha256=
|
|
11
|
+
AgentCrew/modules/a2a/registry.py,sha256=Qrf8jSZSNc-VWnSsbci0PLRqD00ViE3hCT4VAZDIhZA,2667
|
|
12
12
|
AgentCrew/modules/a2a/server.py,sha256=CT_0Te4BBWJEwgbX0wLvHcu6gJAMFsGswwS4IOC5L_k,12345
|
|
13
|
-
AgentCrew/modules/a2a/task_manager.py,sha256=
|
|
13
|
+
AgentCrew/modules/a2a/task_manager.py,sha256=vXYOa1_6cJ6_MyT7JuWIPKehX7sP_z0Na8a3IAwKrUg,31014
|
|
14
14
|
AgentCrew/modules/a2a/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
AgentCrew/modules/a2a/common/client/__init__.py,sha256=PoBTKucH8G2onta-vHT4qUJcBYa3TIabGqCO5GVVyT0,118
|
|
16
16
|
AgentCrew/modules/a2a/common/client/card_resolver.py,sha256=imtwwMNb1yLxTPcrct1ToH9fA18mzgAFYKR5vYTHHRw,637
|
|
@@ -22,7 +22,7 @@ AgentCrew/modules/a2a/common/server/utils.py,sha256=pmIBG5cyzaVNXbyESLux2AcogwPa
|
|
|
22
22
|
AgentCrew/modules/agents/__init__.py,sha256=rMwchcGZzapLLZdUQUaJtCLowHoG-dOn8_VljKz8NrI,165
|
|
23
23
|
AgentCrew/modules/agents/base.py,sha256=i7w0X7mcTRWwgyQwqN-iOIniLce9cSM2wGG3njlZpHk,2641
|
|
24
24
|
AgentCrew/modules/agents/example.py,sha256=_-Nd7EKHprKXZLN9_ava0b9vR7wGyUzsXSEV7_js7Ho,6894
|
|
25
|
-
AgentCrew/modules/agents/local_agent.py,sha256=
|
|
25
|
+
AgentCrew/modules/agents/local_agent.py,sha256=dVm4DBceUqxICgAM0_5gni2F94vEt2cdqxrakpDEX5s,31828
|
|
26
26
|
AgentCrew/modules/agents/manager.py,sha256=JHwEp-GwlYMRTv2RItfJOnVJlePZOLK31xYi3taEuF0,24863
|
|
27
27
|
AgentCrew/modules/agents/remote_agent.py,sha256=bBgO8E3dXZuu9ofklXLfL5-8mxF_XZOLyqj6rrwTXR8,6432
|
|
28
28
|
AgentCrew/modules/agents/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -63,7 +63,7 @@ AgentCrew/modules/clipboard/__init__.py,sha256=Xb0wwQ-9dwwLT3R3TYB87pwtDTNX5HAzh
|
|
|
63
63
|
AgentCrew/modules/clipboard/service.py,sha256=FCo3zSJH0zDdvW73u4D_ty9fTMsXmOeVsAIOfyJ54Ws,6246
|
|
64
64
|
AgentCrew/modules/clipboard/tool.py,sha256=RMu6Cr5wP79SvfOqojAbu6g1WxBw6EUS4Mdfdr9VEuY,5474
|
|
65
65
|
AgentCrew/modules/code_analysis/__init__.py,sha256=veGcJQiv2eR2YNRWM1xNhA0WkmEkkL3OLst1uSM-OyM,83
|
|
66
|
-
AgentCrew/modules/code_analysis/service.py,sha256=
|
|
66
|
+
AgentCrew/modules/code_analysis/service.py,sha256=YMnUZjMtDqMAFoUz-oOIp66yacquqL6Kxkx2jShbDE4,63899
|
|
67
67
|
AgentCrew/modules/code_analysis/tool.py,sha256=BRkouK2radiW0_IAz8ptPdTLodDMsGzjEORnlDmgKGI,6552
|
|
68
68
|
AgentCrew/modules/command_execution/__init__.py,sha256=BIy7TSuz6yFaUQ0GEvXZO-ZSlkSwcRxforfIIhHCMTM,380
|
|
69
69
|
AgentCrew/modules/command_execution/constants.py,sha256=zG2pwmA3MqBhnJgPrcBgzxzH2sWCbXQ4NyidX8lKQ6I,4693
|
|
@@ -79,7 +79,7 @@ AgentCrew/modules/console/confirmation_handler.py,sha256=sOhJVmrMgiqTlUI6G9xjzse
|
|
|
79
79
|
AgentCrew/modules/console/console_ui.py,sha256=09XkGsIivVQK4z1-gOyuHtdXfiMMAyc4DvnWHlvIqho,29836
|
|
80
80
|
AgentCrew/modules/console/constants.py,sha256=fwLj52O96_t6m1qb0SOiaotM2dMLwXH83KAERm9ltLA,704
|
|
81
81
|
AgentCrew/modules/console/conversation_handler.py,sha256=vVtGxQJ4sEZJ77svBFJMIGiWiEfE47yDxvt7gZ9bRCA,3632
|
|
82
|
-
AgentCrew/modules/console/diff_display.py,sha256=
|
|
82
|
+
AgentCrew/modules/console/diff_display.py,sha256=HTFy5H0sx6OHN_yjMPUeF8aum7esdgIg9Xd4_gCvPaw,7193
|
|
83
83
|
AgentCrew/modules/console/display_handlers.py,sha256=ZSpBZxvX5X9VB2dvAB679KQwPTVhRPHRrmsgCMhANyA,17651
|
|
84
84
|
AgentCrew/modules/console/input_handler.py,sha256=SNoDDhdpIwrQ7mPhF427NnS8tT0pnCIbvbI1bCWwG-Q,18140
|
|
85
85
|
AgentCrew/modules/console/tool_display.py,sha256=aTjNWcfzmJXwpXU64PqMfNFRCiVrtMD-JFn_Wd2cNYY,7306
|
|
@@ -89,7 +89,7 @@ AgentCrew/modules/custom_llm/__init__.py,sha256=NvgE3c6rYd52SmRITqGeHqaGOnHrK9vU
|
|
|
89
89
|
AgentCrew/modules/custom_llm/copilot_response_service.py,sha256=tySzxnLMzMt3WjwhvBegtDP7Qk43D2Wc5bxZAi0Z3sA,4605
|
|
90
90
|
AgentCrew/modules/custom_llm/deepinfra_service.py,sha256=uY7f-lg-hnR7A1ZYwKSE10c4WlJ9C693eBiZxLV6jlw,7553
|
|
91
91
|
AgentCrew/modules/custom_llm/github_copilot_service.py,sha256=yCWpD5Sn6LiWMeMtR6sKMTq-xeEXxge5WFpHP84SvjU,14391
|
|
92
|
-
AgentCrew/modules/custom_llm/service.py,sha256=
|
|
92
|
+
AgentCrew/modules/custom_llm/service.py,sha256=XLq_n2TTh4CuGb9vmHZvO7l2a45SPSVfAHxZRFquB1Q,19395
|
|
93
93
|
AgentCrew/modules/file_editing/__init__.py,sha256=Q6oDyP3bHslFpmxHdrCCLVx1M_awaHD2WqFTSEU3VIY,241
|
|
94
94
|
AgentCrew/modules/file_editing/safety_validator.py,sha256=lLNb_GpIIX2QtN86U2NKbM-b3VYW3b6jNkXL5hKPlok,5575
|
|
95
95
|
AgentCrew/modules/file_editing/search_replace_engine.py,sha256=i8e18VIvxOwCazjnfrmLp637laDCsJSpZs5YsW9Ic-Y,10751
|
|
@@ -113,23 +113,24 @@ AgentCrew/modules/gui/components/input_components.py,sha256=IYKigulYCNJ6Et5rLCEX
|
|
|
113
113
|
AgentCrew/modules/gui/components/keyboard_handler.py,sha256=uNBvaOOIcBHaqstA4JbTrkDEmlh0r6Y6_gRG9gD1WCw,5770
|
|
114
114
|
AgentCrew/modules/gui/components/menu_components.py,sha256=Dy6yo61R4sEANZEfRdl3pOTUb5Io6nmUEqMfYc0nW9I,5327
|
|
115
115
|
AgentCrew/modules/gui/components/message_handlers.py,sha256=CluNFGNXjWbJFf6RhAlqgmA9o_gcJRXLEG7FIQW07W0,5391
|
|
116
|
-
AgentCrew/modules/gui/components/tool_handlers.py,sha256=
|
|
116
|
+
AgentCrew/modules/gui/components/tool_handlers.py,sha256=mHJRFwjGuGC8B7Ydy7qmMfZlNH0jfFdwHZaMJMjLNdk,22065
|
|
117
117
|
AgentCrew/modules/gui/components/ui_state_manager.py,sha256=w_gmdykpFbZE84lgA1I_ordqky_QpPUOf39ni26KEfw,5131
|
|
118
118
|
AgentCrew/modules/gui/themes/README.md,sha256=mYiu9SV1OjhDgjCpnnvhvME-5ROnAcvEu5AkW3rJEjo,4844
|
|
119
119
|
AgentCrew/modules/gui/themes/__init__.py,sha256=kOJruvfsx48F9V6ArwsnqfT2QxcJ_THdhJIZ81B3R3k,71
|
|
120
|
-
AgentCrew/modules/gui/themes/atom_light.py,sha256=
|
|
121
|
-
AgentCrew/modules/gui/themes/catppuccin.py,sha256=
|
|
122
|
-
AgentCrew/modules/gui/themes/dracula.py,sha256=
|
|
123
|
-
AgentCrew/modules/gui/themes/nord.py,sha256=
|
|
124
|
-
AgentCrew/modules/gui/themes/saigontech.py,sha256
|
|
125
|
-
AgentCrew/modules/gui/themes/style_provider.py,sha256=
|
|
126
|
-
AgentCrew/modules/gui/themes/unicorn.py,sha256=
|
|
120
|
+
AgentCrew/modules/gui/themes/atom_light.py,sha256=crx6Yw_5i_Sim5ZxJW_T3HzSpIsskyUdATlHuugpwds,36892
|
|
121
|
+
AgentCrew/modules/gui/themes/catppuccin.py,sha256=hbC4LtGQbRNvfRfSBhmvew2f9Zo8ORL-HfxlN90IkHQ,41116
|
|
122
|
+
AgentCrew/modules/gui/themes/dracula.py,sha256=hLpqmBl8bEV6zlxqmeEFI4BFBOvfH_4bv87cGRDR69o,39340
|
|
123
|
+
AgentCrew/modules/gui/themes/nord.py,sha256=FpwcB2yPN1ybDbiiDF1TD6Tw0MPtpzrFpKeQzMRAP40,39151
|
|
124
|
+
AgentCrew/modules/gui/themes/saigontech.py,sha256=-b-Sc44eM4cVpfcsIyFPrT1FTdjfUZnK06UorzIAl6I,41291
|
|
125
|
+
AgentCrew/modules/gui/themes/style_provider.py,sha256=2BUwvS4iZOGfgtryi8oPL4JaJjJS8VSoqakxW35VPAI,14470
|
|
126
|
+
AgentCrew/modules/gui/themes/unicorn.py,sha256=kGrQB9CNopoy9GS8KFZA07i-xTrN70p_qMrVH2vM2uk,38476
|
|
127
127
|
AgentCrew/modules/gui/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
128
|
AgentCrew/modules/gui/utils/macos_clipboard.py,sha256=VV0QP2_lWyaL8CB_9dGZuajpON5i12wiDeh6Nbci1pA,510
|
|
129
129
|
AgentCrew/modules/gui/utils/strings.py,sha256=zSnec-CHz8JF3H6BgPGjfDr10NilRumorlwh-tuvUBs,540
|
|
130
130
|
AgentCrew/modules/gui/utils/wins_clipboard.py,sha256=8LXKje-WzR3Iubu8c_37s-j8DP_5KDywrQEEpfxMcZU,2440
|
|
131
|
-
AgentCrew/modules/gui/widgets/__init__.py,sha256=
|
|
131
|
+
AgentCrew/modules/gui/widgets/__init__.py,sha256=Rc6P_K8d9Dw6H3AGAwnmkuhIxEu5ulht3w7VYJK-cds,493
|
|
132
132
|
AgentCrew/modules/gui/widgets/config_window.py,sha256=QxwnT7N6C0Jm8OOJ4WJE71j7tqDH0kTJVCCGnzR4SZw,3099
|
|
133
|
+
AgentCrew/modules/gui/widgets/diff_widget.py,sha256=p0z3iOwV4-OZfvxIdksp8xjECSrbZ7Jzw16v_L7YyPo,18692
|
|
133
134
|
AgentCrew/modules/gui/widgets/history_sidebar.py,sha256=n-WMPf5cm5jNB_cT3IoK_nzAAczRCA1GeWsY4O0bg5k,10596
|
|
134
135
|
AgentCrew/modules/gui/widgets/json_editor.py,sha256=lV-Me8TUJzIkF-tbiRiFSdRGDbxv9bBKDdSSLwof7oU,6211
|
|
135
136
|
AgentCrew/modules/gui/widgets/loading_overlay.py,sha256=jCfHDDJ5YudfwU15s61l3zQVeWoRhI38WvaTylysR9g,3630
|
|
@@ -138,7 +139,7 @@ AgentCrew/modules/gui/widgets/message_bubble.py,sha256=am3qhfilT-5vMSHatuAj44wvP
|
|
|
138
139
|
AgentCrew/modules/gui/widgets/paste_aware_textedit.py,sha256=_bbM3S0dWD-Kt5s_xxnwuS0OA7lLpvCmGAfsGrRvfNs,1891
|
|
139
140
|
AgentCrew/modules/gui/widgets/system_message.py,sha256=3uUwFMIL3vsm3Oa4EiNf9fw2zQzuqWWnb8XmrRCMxaY,5796
|
|
140
141
|
AgentCrew/modules/gui/widgets/token_usage.py,sha256=xfiY_IiCzMwDIYZi8bjRxgOWhqyAAWMNs22weJUABo0,1917
|
|
141
|
-
AgentCrew/modules/gui/widgets/tool_widget.py,sha256=
|
|
142
|
+
AgentCrew/modules/gui/widgets/tool_widget.py,sha256=h9-Pbn_dQ3Oebog-IJ8JcY7MqSduzGyPL9FTqCRZZu8,13849
|
|
142
143
|
AgentCrew/modules/gui/widgets/configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
143
144
|
AgentCrew/modules/gui/widgets/configs/agent_config.py,sha256=IRU-s6YsLJiPoi0buDiSL4CRFz1-k0VAmL9DLJh7jT0,52234
|
|
144
145
|
AgentCrew/modules/gui/widgets/configs/custom_llm_provider.py,sha256=TY3AJUl46vlpy9s4OzxdpFr_zsWCJTyM6roz9GBaUCs,35068
|
|
@@ -150,7 +151,7 @@ AgentCrew/modules/image_generation/service.py,sha256=OEuVaVd4ecKSdZn-WGMmqyZtqDw
|
|
|
150
151
|
AgentCrew/modules/image_generation/tool.py,sha256=TCe6tOvvCXj5LvjMtmxH1AQ5s2FWHDA79ix43hdzGZs,6087
|
|
151
152
|
AgentCrew/modules/llm/__init__.py,sha256=dMlHRa09bbPEVZnGXm62TcHmbvQzdBqmRIxstlrls8k,63
|
|
152
153
|
AgentCrew/modules/llm/base.py,sha256=S2Tzg4LXQv69MVjNScWbpid3cM20QCgW0KHQqvghjeI,11511
|
|
153
|
-
AgentCrew/modules/llm/constants.py,sha256=
|
|
154
|
+
AgentCrew/modules/llm/constants.py,sha256=yur9HHdmRtyvMUj8m5InM0EsOfcL1Q4TuvogAjHxXjA,19807
|
|
154
155
|
AgentCrew/modules/llm/model_registry.py,sha256=7gJqn-YoentH2Xx0AlF5goyxQDlEBMFWak2poafjhyI,5510
|
|
155
156
|
AgentCrew/modules/llm/service_manager.py,sha256=oXSjcAbrfcGLdBcm_ylnSWIp87Ecl96yZ8efkWFb4Gw,10669
|
|
156
157
|
AgentCrew/modules/llm/types.py,sha256=Bkr1OIRJJ5neUiSCMUJco8SwerrycPh5Xg1kVDpO0os,949
|
|
@@ -185,9 +186,9 @@ AgentCrew/modules/voice/text_cleaner.py,sha256=NgAVBPkP2hFI330nJOyMK_oqP3R2AGZ22
|
|
|
185
186
|
AgentCrew/modules/web_search/__init__.py,sha256=sVf_z6nH2JghK46pG92PUtDghPIkceiX1F0Ul30euXU,111
|
|
186
187
|
AgentCrew/modules/web_search/service.py,sha256=DKcOdRSHB5AEvbK8pvTXdffSnk6rFRTzaM1FXf2B70E,4006
|
|
187
188
|
AgentCrew/modules/web_search/tool.py,sha256=GV4xleVFs0UwiPS9toSzPzZei3ehsDZWxTQCJCRaEs8,6655
|
|
188
|
-
agentcrew_ai-0.8.
|
|
189
|
-
agentcrew_ai-0.8.
|
|
190
|
-
agentcrew_ai-0.8.
|
|
191
|
-
agentcrew_ai-0.8.
|
|
192
|
-
agentcrew_ai-0.8.
|
|
193
|
-
agentcrew_ai-0.8.
|
|
189
|
+
agentcrew_ai-0.8.7.dist-info/licenses/LICENSE,sha256=O51CIaOUcxVLNf0_PE_a8ap5bf3iXe4SrWN_5NO1PSU,11348
|
|
190
|
+
agentcrew_ai-0.8.7.dist-info/METADATA,sha256=pAPP0PKBi1ZUFW77GcCitWRS63n7cRw3N5puToKl2ms,18056
|
|
191
|
+
agentcrew_ai-0.8.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
192
|
+
agentcrew_ai-0.8.7.dist-info/entry_points.txt,sha256=N9R5jslrBYA8dTaNMRJ_JdSosJ6jkpGEtnJFzlcZD6k,54
|
|
193
|
+
agentcrew_ai-0.8.7.dist-info/top_level.txt,sha256=bSsmhCOn6g-JytoVMpxB_QAnCgb7lV56fcnxUhbfrvg,10
|
|
194
|
+
agentcrew_ai-0.8.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|