django-agent-studio 0.2.7__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/PKG-INFO +2 -1
  2. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/README.md +1 -0
  3. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/api/serializers.py +18 -1
  4. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/api/urls.py +10 -10
  5. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/api/views.py +22 -12
  6. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/django_agent_studio.egg-info/PKG-INFO +2 -1
  7. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/django_agent_studio.egg-info/SOURCES.txt +4 -0
  8. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/pyproject.toml +1 -1
  9. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/static/agent-frontend/chat-widget.css +286 -0
  10. django_agent_studio-0.3.0/static/agent-frontend/chat-widget.js +591 -0
  11. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/templates/django_agent_studio/home.html +44 -6
  12. django_agent_studio-0.3.0/templates/django_agent_studio/system_list.html +92 -0
  13. django_agent_studio-0.3.0/templates/django_agent_studio/system_test.html +131 -0
  14. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/urls.py +6 -2
  15. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/views.py +65 -2
  16. django_agent_studio-0.2.7/static/agent-frontend/chat-widget.js +0 -481
  17. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/LICENSE +0 -0
  18. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/__init__.py +0 -0
  19. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/agents/__init__.py +0 -0
  20. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/agents/builder.py +0 -0
  21. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/agents/dynamic.py +0 -0
  22. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/api/__init__.py +0 -0
  23. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/api/permissions.py +0 -0
  24. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/apps.py +0 -0
  25. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/django_agent_studio.egg-info/dependency_links.txt +0 -0
  26. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/django_agent_studio.egg-info/requires.txt +0 -0
  27. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/django_agent_studio.egg-info/top_level.txt +0 -0
  28. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/management/__init__.py +0 -0
  29. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/management/commands/__init__.py +0 -0
  30. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/migrations/0001_initial.py +0 -0
  31. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/migrations/__init__.py +0 -0
  32. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/models/__init__.py +0 -0
  33. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/models/permissions.py +0 -0
  34. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/services/__init__.py +0 -0
  35. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/services/permissions.py +0 -0
  36. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/setup.cfg +0 -0
  37. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/static/agent-frontend/chat-widget-markdown.js +0 -0
  38. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/static/django_agent_studio/js/builder.js +0 -0
  39. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/static/django_agent_studio/js/builder.js.map +0 -0
  40. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/static/django_agent_studio/js/style.css +0 -0
  41. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/templates/django_agent_studio/agent_list.html +0 -0
  42. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/templates/django_agent_studio/base.html +0 -0
  43. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/templates/django_agent_studio/builder.html +0 -0
  44. {django_agent_studio-0.2.7 → django_agent_studio-0.3.0}/templates/django_agent_studio/test.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-agent-studio
3
- Version: 0.2.7
3
+ Version: 0.3.0
4
4
  Summary: Visual agent builder and management studio for Django - build custom GPTs with a two-pane interface
5
5
  Author: Chris Barry
6
6
  License: Business Source License 1.1
@@ -126,6 +126,7 @@ A visual agent builder and management interface for Django applications. Create,
126
126
 
127
127
  | Version | Date | Changes |
128
128
  |---------|------|---------|
129
+ | **0.3.0** | 2026-01-29 | **System Listing & Navigation** - Browse and test multi-agent systems from homepage, fixed URL routing for My Systems/My Agents links, system creation now supports optional entry agent |
129
130
  | **0.2.0** | 2026-01-28 | **Multi-Agent Systems** - System management UI, shared memory configuration, memory privacy controls, builder tools for managing agent systems |
130
131
  | **0.1.9** | 2026-01-27 | Spec documents migration, improved builder agent |
131
132
  | **0.1.0** | 2026-01-25 | Initial release with builder interface, dynamic tools, knowledge management |
@@ -6,6 +6,7 @@ A visual agent builder and management interface for Django applications. Create,
6
6
 
7
7
  | Version | Date | Changes |
8
8
  |---------|------|---------|
9
+ | **0.3.0** | 2026-01-29 | **System Listing & Navigation** - Browse and test multi-agent systems from homepage, fixed URL routing for My Systems/My Agents links, system creation now supports optional entry agent |
9
10
  | **0.2.0** | 2026-01-28 | **Multi-Agent Systems** - System management UI, shared memory configuration, memory privacy controls, builder tools for managing agent systems |
10
11
  | **0.1.9** | 2026-01-27 | Spec documents migration, improved builder agent |
11
12
  | **0.1.0** | 2026-01-25 | Initial release with builder interface, dynamic tools, knowledge management |
@@ -570,12 +570,29 @@ class AgentSystemCreateSerializer(serializers.Serializer):
570
570
  slug = serializers.SlugField(max_length=100)
571
571
  name = serializers.CharField(max_length=255)
572
572
  description = serializers.CharField(required=False, default="")
573
- entry_agent_id = serializers.UUIDField(help_text="ID of the entry point agent")
573
+ # Accept both entry_agent_id and entry_agent for flexibility
574
+ entry_agent_id = serializers.UUIDField(
575
+ required=False,
576
+ help_text="ID of the entry point agent",
577
+ )
578
+ entry_agent = serializers.UUIDField(
579
+ required=False,
580
+ help_text="ID of the entry point agent (alias for entry_agent_id)",
581
+ )
574
582
  auto_discover = serializers.BooleanField(
575
583
  default=True,
576
584
  help_text="Automatically discover and add all reachable sub-agents",
577
585
  )
578
586
 
587
+ def validate(self, data):
588
+ """Normalize entry_agent to entry_agent_id."""
589
+ # Accept either entry_agent or entry_agent_id
590
+ if 'entry_agent' in data and data['entry_agent']:
591
+ data['entry_agent_id'] = data.pop('entry_agent')
592
+ elif 'entry_agent' in data:
593
+ data.pop('entry_agent')
594
+ return data
595
+
579
596
 
580
597
  class AddMemberSerializer(serializers.Serializer):
581
598
  """Serializer for adding a member to a system."""
@@ -8,8 +8,8 @@ from django_agent_studio.api import views
8
8
 
9
9
  urlpatterns = [
10
10
  # Agent definition CRUD
11
- path("agents/", views.AgentDefinitionListCreateView.as_view(), name="agent_list"),
12
- path("agents/<uuid:pk>/", views.AgentDefinitionDetailView.as_view(), name="agent_detail"),
11
+ path("agents/", views.AgentDefinitionListCreateView.as_view(), name="api_agent_list"),
12
+ path("agents/<uuid:pk>/", views.AgentDefinitionDetailView.as_view(), name="api_agent_detail"),
13
13
 
14
14
  # Agent versions
15
15
  path(
@@ -194,46 +194,46 @@ urlpatterns = [
194
194
  path(
195
195
  "systems/",
196
196
  views.AgentSystemListCreateView.as_view(),
197
- name="system_list",
197
+ name="api_system_list",
198
198
  ),
199
199
  path(
200
200
  "systems/<uuid:pk>/",
201
201
  views.AgentSystemDetailView.as_view(),
202
- name="system_detail",
202
+ name="api_system_detail",
203
203
  ),
204
204
 
205
205
  # System members
206
206
  path(
207
207
  "systems/<uuid:system_id>/members/",
208
208
  views.AgentSystemMemberListCreateView.as_view(),
209
- name="system_member_list",
209
+ name="api_system_member_list",
210
210
  ),
211
211
  path(
212
212
  "systems/<uuid:system_id>/members/<uuid:pk>/",
213
213
  views.AgentSystemMemberDetailView.as_view(),
214
- name="system_member_detail",
214
+ name="api_system_member_detail",
215
215
  ),
216
216
 
217
217
  # System versions
218
218
  path(
219
219
  "systems/<uuid:system_id>/versions/",
220
220
  views.AgentSystemVersionListView.as_view(),
221
- name="system_version_list",
221
+ name="api_system_version_list",
222
222
  ),
223
223
  path(
224
224
  "systems/<uuid:system_id>/publish/",
225
225
  views.AgentSystemPublishView.as_view(),
226
- name="system_publish",
226
+ name="api_system_publish",
227
227
  ),
228
228
  path(
229
229
  "systems/<uuid:system_id>/versions/<uuid:version_id>/deploy/",
230
230
  views.AgentSystemDeployView.as_view(),
231
- name="system_deploy",
231
+ name="api_system_deploy",
232
232
  ),
233
233
  path(
234
234
  "systems/<uuid:system_id>/versions/<uuid:version_id>/export/",
235
235
  views.AgentSystemExportView.as_view(),
236
- name="system_export",
236
+ name="api_system_export",
237
237
  ),
238
238
 
239
239
  # Discover agents from entry point
@@ -1434,20 +1434,30 @@ class AgentSystemListCreateView(generics.ListCreateAPIView):
1434
1434
  serializer = self.get_serializer(data=request.data)
1435
1435
  serializer.is_valid(raise_exception=True)
1436
1436
 
1437
- # Get the entry agent
1438
- entry_agent = get_agent_for_user(request.user, serializer.validated_data['entry_agent_id'])
1437
+ entry_agent_id = serializer.validated_data.get('entry_agent_id')
1439
1438
 
1440
- # Use the service to create the system
1441
- from django_agent_runtime.services.multi_agent import create_system_from_entry_agent
1439
+ if entry_agent_id:
1440
+ # Get the entry agent and use the service to create with auto-discovery
1441
+ entry_agent = get_agent_for_user(request.user, entry_agent_id)
1442
1442
 
1443
- system = create_system_from_entry_agent(
1444
- slug=serializer.validated_data['slug'],
1445
- name=serializer.validated_data['name'],
1446
- entry_agent=entry_agent,
1447
- description=serializer.validated_data.get('description', ''),
1448
- owner=request.user,
1449
- auto_discover=serializer.validated_data.get('auto_discover', True),
1450
- )
1443
+ from django_agent_runtime.services.multi_agent import create_system_from_entry_agent
1444
+
1445
+ system = create_system_from_entry_agent(
1446
+ slug=serializer.validated_data['slug'],
1447
+ name=serializer.validated_data['name'],
1448
+ entry_agent=entry_agent,
1449
+ description=serializer.validated_data.get('description', ''),
1450
+ owner=request.user,
1451
+ auto_discover=serializer.validated_data.get('auto_discover', True),
1452
+ )
1453
+ else:
1454
+ # Create system without entry agent - can be set later
1455
+ system = AgentSystem.objects.create(
1456
+ slug=serializer.validated_data['slug'],
1457
+ name=serializer.validated_data['name'],
1458
+ description=serializer.validated_data.get('description', ''),
1459
+ owner=request.user,
1460
+ )
1451
1461
 
1452
1462
  return Response(
1453
1463
  AgentSystemDetailSerializer(system).data,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-agent-studio
3
- Version: 0.2.7
3
+ Version: 0.3.0
4
4
  Summary: Visual agent builder and management studio for Django - build custom GPTs with a two-pane interface
5
5
  Author: Chris Barry
6
6
  License: Business Source License 1.1
@@ -126,6 +126,7 @@ A visual agent builder and management interface for Django applications. Create,
126
126
 
127
127
  | Version | Date | Changes |
128
128
  |---------|------|---------|
129
+ | **0.3.0** | 2026-01-29 | **System Listing & Navigation** - Browse and test multi-agent systems from homepage, fixed URL routing for My Systems/My Agents links, system creation now supports optional entry agent |
129
130
  | **0.2.0** | 2026-01-28 | **Multi-Agent Systems** - System management UI, shared memory configuration, memory privacy controls, builder tools for managing agent systems |
130
131
  | **0.1.9** | 2026-01-27 | Spec documents migration, improved builder agent |
131
132
  | **0.1.0** | 2026-01-25 | Initial release with builder interface, dynamic tools, knowledge management |
@@ -35,6 +35,8 @@ views.py
35
35
  ./templates/django_agent_studio/base.html
36
36
  ./templates/django_agent_studio/builder.html
37
37
  ./templates/django_agent_studio/home.html
38
+ ./templates/django_agent_studio/system_list.html
39
+ ./templates/django_agent_studio/system_test.html
38
40
  ./templates/django_agent_studio/test.html
39
41
  agents/__init__.py
40
42
  agents/builder.py
@@ -67,4 +69,6 @@ templates/django_agent_studio/agent_list.html
67
69
  templates/django_agent_studio/base.html
68
70
  templates/django_agent_studio/builder.html
69
71
  templates/django_agent_studio/home.html
72
+ templates/django_agent_studio/system_list.html
73
+ templates/django_agent_studio/system_test.html
70
74
  templates/django_agent_studio/test.html
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "django-agent-studio"
7
- version = "0.2.7"
7
+ version = "0.3.0"
8
8
  description = "Visual agent builder and management studio for Django - build custom GPTs with a two-pane interface"
9
9
  readme = "README.md"
10
10
  license = {file = "LICENSE"}
@@ -1819,3 +1819,289 @@
1819
1819
  opacity: 0.5;
1820
1820
  cursor: not-allowed;
1821
1821
  }
1822
+
1823
+ /* =============================================================================
1824
+ TABS
1825
+ ============================================================================= */
1826
+
1827
+ .cw-tabs {
1828
+ display: flex;
1829
+ border-bottom: 1px solid var(--cw-border);
1830
+ background: var(--cw-bg);
1831
+ flex-shrink: 0;
1832
+ }
1833
+
1834
+ .cw-tab {
1835
+ flex: 1;
1836
+ padding: 10px 16px;
1837
+ border: none;
1838
+ background: transparent;
1839
+ color: var(--cw-text-muted);
1840
+ font-size: 13px;
1841
+ font-weight: 500;
1842
+ cursor: pointer;
1843
+ transition: all 0.2s ease;
1844
+ position: relative;
1845
+ display: flex;
1846
+ align-items: center;
1847
+ justify-content: center;
1848
+ gap: 6px;
1849
+ }
1850
+
1851
+ .cw-tab:hover {
1852
+ color: var(--cw-text);
1853
+ background: var(--cw-bg-muted);
1854
+ }
1855
+
1856
+ .cw-tab-active {
1857
+ color: var(--cw-primary);
1858
+ }
1859
+
1860
+ .cw-tab-active::after {
1861
+ content: '';
1862
+ position: absolute;
1863
+ bottom: -1px;
1864
+ left: 0;
1865
+ right: 0;
1866
+ height: 2px;
1867
+ background: var(--cw-primary);
1868
+ }
1869
+
1870
+ .cw-tab-badge {
1871
+ font-size: 11px;
1872
+ padding: 2px 6px;
1873
+ background: var(--cw-bg-muted);
1874
+ border-radius: 10px;
1875
+ color: var(--cw-text-muted);
1876
+ }
1877
+
1878
+ .cw-tab-active .cw-tab-badge {
1879
+ background: var(--cw-primary);
1880
+ color: white;
1881
+ }
1882
+
1883
+ /* =============================================================================
1884
+ TASK LIST
1885
+ ============================================================================= */
1886
+
1887
+ .cw-tasks-container {
1888
+ flex: 1;
1889
+ display: flex;
1890
+ flex-direction: column;
1891
+ overflow: hidden;
1892
+ background: var(--cw-bg);
1893
+ }
1894
+
1895
+ .cw-tasks-header {
1896
+ display: flex;
1897
+ align-items: center;
1898
+ justify-content: space-between;
1899
+ padding: 12px 16px;
1900
+ border-bottom: 1px solid var(--cw-border);
1901
+ background: var(--cw-bg-muted);
1902
+ }
1903
+
1904
+ .cw-tasks-progress {
1905
+ display: flex;
1906
+ align-items: center;
1907
+ gap: 10px;
1908
+ flex: 1;
1909
+ }
1910
+
1911
+ .cw-tasks-progress-text {
1912
+ font-size: 12px;
1913
+ color: var(--cw-text-muted);
1914
+ white-space: nowrap;
1915
+ }
1916
+
1917
+ .cw-tasks-progress-bar {
1918
+ flex: 1;
1919
+ height: 6px;
1920
+ background: var(--cw-border);
1921
+ border-radius: 3px;
1922
+ overflow: hidden;
1923
+ max-width: 120px;
1924
+ }
1925
+
1926
+ .cw-tasks-progress-fill {
1927
+ height: 100%;
1928
+ background: var(--cw-primary);
1929
+ border-radius: 3px;
1930
+ transition: width 0.3s ease;
1931
+ }
1932
+
1933
+ .cw-tasks-actions {
1934
+ display: flex;
1935
+ gap: 4px;
1936
+ }
1937
+
1938
+ .cw-tasks-action-btn {
1939
+ width: 28px;
1940
+ height: 28px;
1941
+ border: none;
1942
+ background: transparent;
1943
+ color: var(--cw-text-muted);
1944
+ cursor: pointer;
1945
+ border-radius: var(--cw-radius-sm);
1946
+ display: flex;
1947
+ align-items: center;
1948
+ justify-content: center;
1949
+ font-size: 14px;
1950
+ transition: all 0.2s ease;
1951
+ }
1952
+
1953
+ .cw-tasks-action-btn:hover {
1954
+ background: var(--cw-bg);
1955
+ color: var(--cw-text);
1956
+ }
1957
+
1958
+ .cw-tasks-error {
1959
+ padding: 8px 16px;
1960
+ background: #fee2e2;
1961
+ color: #dc2626;
1962
+ font-size: 12px;
1963
+ }
1964
+
1965
+ .cw-tasks-list {
1966
+ flex: 1;
1967
+ overflow-y: auto;
1968
+ padding: 8px 0;
1969
+ }
1970
+
1971
+ .cw-tasks-empty {
1972
+ display: flex;
1973
+ flex-direction: column;
1974
+ align-items: center;
1975
+ justify-content: center;
1976
+ padding: 40px 20px;
1977
+ text-align: center;
1978
+ color: var(--cw-text-muted);
1979
+ }
1980
+
1981
+ .cw-tasks-empty p {
1982
+ margin: 0;
1983
+ }
1984
+
1985
+ .cw-tasks-empty-hint {
1986
+ font-size: 12px;
1987
+ margin-top: 8px !important;
1988
+ opacity: 0.7;
1989
+ }
1990
+
1991
+ .cw-tasks-loading {
1992
+ display: flex;
1993
+ align-items: center;
1994
+ justify-content: center;
1995
+ padding: 40px 20px;
1996
+ color: var(--cw-text-muted);
1997
+ }
1998
+
1999
+ /* Task Item */
2000
+ .cw-task-item {
2001
+ display: flex;
2002
+ align-items: center;
2003
+ gap: 8px;
2004
+ padding: 8px 12px;
2005
+ transition: background 0.15s ease;
2006
+ }
2007
+
2008
+ .cw-task-item:hover {
2009
+ background: var(--cw-bg-muted);
2010
+ }
2011
+
2012
+ .cw-task-state-btn {
2013
+ width: 20px;
2014
+ height: 20px;
2015
+ border: none;
2016
+ background: transparent;
2017
+ cursor: pointer;
2018
+ font-size: 14px;
2019
+ padding: 0;
2020
+ display: flex;
2021
+ align-items: center;
2022
+ justify-content: center;
2023
+ color: var(--cw-text-muted);
2024
+ flex-shrink: 0;
2025
+ transition: transform 0.15s ease;
2026
+ }
2027
+
2028
+ .cw-task-state-btn:hover {
2029
+ transform: scale(1.2);
2030
+ }
2031
+
2032
+ .cw-task-state-not-started .cw-task-state-btn {
2033
+ color: var(--cw-text-muted);
2034
+ }
2035
+
2036
+ .cw-task-state-in-progress .cw-task-state-btn {
2037
+ color: #f59e0b;
2038
+ }
2039
+
2040
+ .cw-task-state-complete .cw-task-state-btn {
2041
+ color: #10b981;
2042
+ }
2043
+
2044
+ .cw-task-state-cancelled .cw-task-state-btn {
2045
+ color: #ef4444;
2046
+ }
2047
+
2048
+ .cw-task-name {
2049
+ flex: 1;
2050
+ font-size: 13px;
2051
+ color: var(--cw-text);
2052
+ cursor: text;
2053
+ padding: 2px 4px;
2054
+ border-radius: 4px;
2055
+ transition: background 0.15s ease;
2056
+ }
2057
+
2058
+ .cw-task-name:hover {
2059
+ background: var(--cw-bg);
2060
+ }
2061
+
2062
+ .cw-task-state-complete .cw-task-name {
2063
+ text-decoration: line-through;
2064
+ color: var(--cw-text-muted);
2065
+ }
2066
+
2067
+ .cw-task-state-cancelled .cw-task-name {
2068
+ text-decoration: line-through;
2069
+ color: var(--cw-text-muted);
2070
+ opacity: 0.6;
2071
+ }
2072
+
2073
+ .cw-task-edit-input {
2074
+ flex: 1;
2075
+ font-size: 13px;
2076
+ padding: 4px 8px;
2077
+ border: 1px solid var(--cw-primary);
2078
+ border-radius: 4px;
2079
+ outline: none;
2080
+ background: var(--cw-bg);
2081
+ color: var(--cw-text);
2082
+ }
2083
+
2084
+ .cw-task-remove-btn {
2085
+ width: 20px;
2086
+ height: 20px;
2087
+ border: none;
2088
+ background: transparent;
2089
+ cursor: pointer;
2090
+ font-size: 16px;
2091
+ padding: 0;
2092
+ display: flex;
2093
+ align-items: center;
2094
+ justify-content: center;
2095
+ color: var(--cw-text-muted);
2096
+ opacity: 0;
2097
+ transition: all 0.15s ease;
2098
+ flex-shrink: 0;
2099
+ }
2100
+
2101
+ .cw-task-item:hover .cw-task-remove-btn {
2102
+ opacity: 1;
2103
+ }
2104
+
2105
+ .cw-task-remove-btn:hover {
2106
+ color: #ef4444;
2107
+ }