django-agent-studio 0.3.1__py3-none-any.whl → 0.3.2__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.
- django_agent_studio/api/serializers.py +139 -0
- django_agent_studio/api/urls.py +35 -0
- django_agent_studio/api/views.py +470 -8
- django_agent_studio/templates/django_agent_studio/agent_list.html +12 -5
- django_agent_studio/templates/django_agent_studio/collaborators.html +418 -0
- django_agent_studio/templates/django_agent_studio/home.html +21 -12
- django_agent_studio/templates/django_agent_studio/system_create.html +148 -0
- django_agent_studio/templates/django_agent_studio/system_list.html +15 -3
- django_agent_studio/templates/django_agent_studio/system_test.html +7 -2
- django_agent_studio/templates/django_agent_studio/test.html +7 -2
- django_agent_studio/urls.py +3 -0
- django_agent_studio/views.py +306 -15
- {django_agent_studio-0.3.1.dist-info → django_agent_studio-0.3.2.dist-info}/METADATA +2 -1
- {django_agent_studio-0.3.1.dist-info → django_agent_studio-0.3.2.dist-info}/RECORD +17 -15
- {django_agent_studio-0.3.1.dist-info → django_agent_studio-0.3.2.dist-info}/WHEEL +0 -0
- {django_agent_studio-0.3.1.dist-info → django_agent_studio-0.3.2.dist-info}/licenses/LICENSE +0 -0
- {django_agent_studio-0.3.1.dist-info → django_agent_studio-0.3.2.dist-info}/top_level.txt +0 -0
|
@@ -60,11 +60,16 @@
|
|
|
60
60
|
</div>
|
|
61
61
|
</div>
|
|
62
62
|
<div class="flex items-center space-x-3">
|
|
63
|
-
<a href="{% url 'agent_studio:
|
|
63
|
+
<a href="{% url 'agent_studio:system_collaborators' system.id %}"
|
|
64
|
+
class="text-gray-600 hover:text-gray-800 px-3 py-1.5 border border-gray-300 rounded-lg text-sm"
|
|
65
|
+
title="Manage collaborators">
|
|
66
|
+
<i class="pi pi-users"></i>
|
|
67
|
+
</a>
|
|
68
|
+
<a href="{% url 'agent_studio:system_list' %}"
|
|
64
69
|
class="text-gray-600 hover:text-gray-800 px-3 py-1.5 border border-gray-300 rounded-lg text-sm">
|
|
65
70
|
← Back to Systems
|
|
66
71
|
</a>
|
|
67
|
-
<button @click="clearChat"
|
|
72
|
+
<button @click="clearChat"
|
|
68
73
|
class="text-gray-600 hover:text-gray-800 px-3 py-1.5 border border-gray-300 rounded-lg text-sm">
|
|
69
74
|
Clear Chat
|
|
70
75
|
</button>
|
|
@@ -59,11 +59,16 @@
|
|
|
59
59
|
</div>
|
|
60
60
|
</div>
|
|
61
61
|
<div class="flex items-center space-x-3">
|
|
62
|
-
<a href="{% url 'agent_studio:
|
|
62
|
+
<a href="{% url 'agent_studio:agent_collaborators' agent.id %}"
|
|
63
|
+
class="text-gray-600 hover:text-gray-800 px-3 py-1.5 border border-gray-300 rounded-lg text-sm"
|
|
64
|
+
title="Manage collaborators">
|
|
65
|
+
<i class="pi pi-users"></i>
|
|
66
|
+
</a>
|
|
67
|
+
<a href="{% url 'agent_studio:agent_edit' agent.id %}"
|
|
63
68
|
class="text-gray-600 hover:text-gray-800 px-3 py-1.5 border border-gray-300 rounded-lg text-sm">
|
|
64
69
|
← Back to Editor
|
|
65
70
|
</a>
|
|
66
|
-
<button @click="clearChat"
|
|
71
|
+
<button @click="clearChat"
|
|
67
72
|
class="text-gray-600 hover:text-gray-800 px-3 py-1.5 border border-gray-300 rounded-lg text-sm">
|
|
68
73
|
Clear Chat
|
|
69
74
|
</button>
|
django_agent_studio/urls.py
CHANGED
|
@@ -15,13 +15,16 @@ urlpatterns = [
|
|
|
15
15
|
|
|
16
16
|
# Systems (multi-agent systems)
|
|
17
17
|
path("systems/", views.SystemListView.as_view(), name="system_list"),
|
|
18
|
+
path("systems/create/", views.SystemCreateView.as_view(), name="system_create"),
|
|
18
19
|
path("systems/<uuid:system_id>/test/", views.SystemTestView.as_view(), name="system_test"),
|
|
20
|
+
path("systems/<uuid:system_id>/collaborators/", views.SystemCollaboratorsView.as_view(), name="system_collaborators"),
|
|
19
21
|
|
|
20
22
|
# Agent builder/editor
|
|
21
23
|
path("agents/", views.AgentListView.as_view(), name="agent_list"),
|
|
22
24
|
path("agents/new/", views.AgentBuilderView.as_view(), name="agent_create"),
|
|
23
25
|
path("agents/<uuid:agent_id>/", views.AgentBuilderView.as_view(), name="agent_edit"),
|
|
24
26
|
path("agents/<uuid:agent_id>/test/", views.AgentTestView.as_view(), name="agent_test"),
|
|
27
|
+
path("agents/<uuid:agent_id>/collaborators/", views.AgentCollaboratorsView.as_view(), name="agent_collaborators"),
|
|
25
28
|
|
|
26
29
|
# API endpoints
|
|
27
30
|
path("api/", include(api_urls)),
|
django_agent_studio/views.py
CHANGED
|
@@ -6,7 +6,14 @@ from django.db.models import Q
|
|
|
6
6
|
from django.views.generic import TemplateView, ListView
|
|
7
7
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
8
8
|
|
|
9
|
-
from django_agent_runtime.models import
|
|
9
|
+
from django_agent_runtime.models import (
|
|
10
|
+
AgentDefinition,
|
|
11
|
+
AgentSystem,
|
|
12
|
+
AgentSystemMember,
|
|
13
|
+
AgentCollaborator,
|
|
14
|
+
SystemCollaborator,
|
|
15
|
+
CollaboratorRole,
|
|
16
|
+
)
|
|
10
17
|
|
|
11
18
|
|
|
12
19
|
class AgentAccessMixin:
|
|
@@ -14,25 +21,170 @@ class AgentAccessMixin:
|
|
|
14
21
|
Mixin that provides consistent agent access logic.
|
|
15
22
|
|
|
16
23
|
- Superusers can access all agents
|
|
17
|
-
-
|
|
24
|
+
- Owners can access their own agents
|
|
25
|
+
- Collaborators can access agents they've been granted access to
|
|
26
|
+
- Users with system access can access agents in that system
|
|
18
27
|
"""
|
|
19
28
|
|
|
20
29
|
def get_user_agents_queryset(self):
|
|
21
30
|
"""Get queryset of agents accessible to the current user."""
|
|
22
31
|
if self.request.user.is_superuser:
|
|
23
32
|
return AgentDefinition.objects.all()
|
|
24
|
-
return AgentDefinition.objects.filter(owner=self.request.user)
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
user = self.request.user
|
|
35
|
+
|
|
36
|
+
# Get system IDs the user has access to (owner or collaborator)
|
|
37
|
+
accessible_system_ids = AgentSystem.objects.filter(
|
|
38
|
+
Q(owner=user) | Q(collaborators__user=user)
|
|
39
|
+
).values_list('id', flat=True)
|
|
40
|
+
|
|
41
|
+
# Get agent IDs that are members of accessible systems
|
|
42
|
+
agents_via_systems = AgentSystemMember.objects.filter(
|
|
43
|
+
system_id__in=accessible_system_ids
|
|
44
|
+
).values_list('agent_id', flat=True)
|
|
45
|
+
|
|
46
|
+
return AgentDefinition.objects.filter(
|
|
47
|
+
Q(owner=user) |
|
|
48
|
+
Q(collaborators__user=user) |
|
|
49
|
+
Q(id__in=agents_via_systems)
|
|
50
|
+
).distinct()
|
|
51
|
+
|
|
52
|
+
def get_agent_for_user(self, agent_id, require_edit=False):
|
|
27
53
|
"""
|
|
28
54
|
Get a specific agent if the user has access.
|
|
29
55
|
|
|
30
|
-
|
|
31
|
-
|
|
56
|
+
Args:
|
|
57
|
+
agent_id: The agent's ID
|
|
58
|
+
require_edit: If True, requires edit permission (editor or admin role)
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
AgentDefinition if user has access
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
AgentDefinition.DoesNotExist if no access
|
|
32
65
|
"""
|
|
33
66
|
if self.request.user.is_superuser:
|
|
34
67
|
return AgentDefinition.objects.get(id=agent_id)
|
|
35
|
-
|
|
68
|
+
|
|
69
|
+
agent = AgentDefinition.objects.get(id=agent_id)
|
|
70
|
+
user = self.request.user
|
|
71
|
+
|
|
72
|
+
# Owner always has full access
|
|
73
|
+
if agent.owner == user:
|
|
74
|
+
return agent
|
|
75
|
+
|
|
76
|
+
# Check direct collaborator access
|
|
77
|
+
try:
|
|
78
|
+
collab = AgentCollaborator.objects.get(agent=agent, user=user)
|
|
79
|
+
if require_edit and not collab.can_edit:
|
|
80
|
+
raise AgentDefinition.DoesNotExist("Edit permission required")
|
|
81
|
+
return agent
|
|
82
|
+
except AgentCollaborator.DoesNotExist:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
# Check if user has access via a system that contains this agent
|
|
86
|
+
agent_system_ids = AgentSystemMember.objects.filter(
|
|
87
|
+
agent=agent
|
|
88
|
+
).values_list('system_id', flat=True)
|
|
89
|
+
|
|
90
|
+
if agent_system_ids:
|
|
91
|
+
# Check for system owner or collaborator access
|
|
92
|
+
system_collab = SystemCollaborator.objects.filter(
|
|
93
|
+
system_id__in=agent_system_ids, user=user
|
|
94
|
+
).first()
|
|
95
|
+
if system_collab:
|
|
96
|
+
if require_edit and not system_collab.can_edit:
|
|
97
|
+
raise AgentDefinition.DoesNotExist("Edit permission required")
|
|
98
|
+
return agent
|
|
99
|
+
|
|
100
|
+
# Check if user owns any of these systems
|
|
101
|
+
if AgentSystem.objects.filter(id__in=agent_system_ids, owner=user).exists():
|
|
102
|
+
return agent
|
|
103
|
+
|
|
104
|
+
raise AgentDefinition.DoesNotExist("No access to this agent")
|
|
105
|
+
|
|
106
|
+
def get_agent_role(self, agent):
|
|
107
|
+
"""
|
|
108
|
+
Get the user's role for an agent.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
'owner', 'admin', 'editor', 'viewer', or None
|
|
112
|
+
Also returns tuple (role, source) where source is 'direct' or 'system:<name>'
|
|
113
|
+
"""
|
|
114
|
+
user = self.request.user
|
|
115
|
+
if user.is_superuser or agent.owner == user:
|
|
116
|
+
return 'owner'
|
|
117
|
+
|
|
118
|
+
# Check direct collaborator
|
|
119
|
+
try:
|
|
120
|
+
collab = AgentCollaborator.objects.get(agent=agent, user=user)
|
|
121
|
+
return collab.role
|
|
122
|
+
except AgentCollaborator.DoesNotExist:
|
|
123
|
+
pass
|
|
124
|
+
|
|
125
|
+
# Check system-level access
|
|
126
|
+
agent_systems = AgentSystemMember.objects.filter(
|
|
127
|
+
agent=agent
|
|
128
|
+
).select_related('system')
|
|
129
|
+
|
|
130
|
+
for member in agent_systems:
|
|
131
|
+
system = member.system
|
|
132
|
+
if system.owner == user:
|
|
133
|
+
return 'owner'
|
|
134
|
+
try:
|
|
135
|
+
sys_collab = SystemCollaborator.objects.get(system=system, user=user)
|
|
136
|
+
return sys_collab.role
|
|
137
|
+
except SystemCollaborator.DoesNotExist:
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
def get_agent_access_info(self, agent):
|
|
143
|
+
"""
|
|
144
|
+
Get detailed access info for an agent.
|
|
145
|
+
|
|
146
|
+
Returns dict with:
|
|
147
|
+
- role: 'owner', 'admin', 'editor', 'viewer', or None
|
|
148
|
+
- source: 'direct', 'system', or None
|
|
149
|
+
- system_name: Name of system granting access (if source is 'system')
|
|
150
|
+
"""
|
|
151
|
+
user = self.request.user
|
|
152
|
+
if user.is_superuser or agent.owner == user:
|
|
153
|
+
return {'role': 'owner', 'source': 'direct', 'system_name': None}
|
|
154
|
+
|
|
155
|
+
# Check direct collaborator
|
|
156
|
+
try:
|
|
157
|
+
collab = AgentCollaborator.objects.get(agent=agent, user=user)
|
|
158
|
+
return {'role': collab.role, 'source': 'direct', 'system_name': None}
|
|
159
|
+
except AgentCollaborator.DoesNotExist:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
# Check system-level access
|
|
163
|
+
agent_systems = AgentSystemMember.objects.filter(
|
|
164
|
+
agent=agent
|
|
165
|
+
).select_related('system')
|
|
166
|
+
|
|
167
|
+
for member in agent_systems:
|
|
168
|
+
system = member.system
|
|
169
|
+
if system.owner == user:
|
|
170
|
+
return {'role': 'owner', 'source': 'system', 'system_name': system.name}
|
|
171
|
+
try:
|
|
172
|
+
sys_collab = SystemCollaborator.objects.get(system=system, user=user)
|
|
173
|
+
return {'role': sys_collab.role, 'source': 'system', 'system_name': system.name}
|
|
174
|
+
except SystemCollaborator.DoesNotExist:
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
return {'role': None, 'source': None, 'system_name': None}
|
|
178
|
+
|
|
179
|
+
def can_edit_agent(self, agent):
|
|
180
|
+
"""Check if user can edit the agent."""
|
|
181
|
+
role = self.get_agent_role(agent)
|
|
182
|
+
return role in ['owner', 'admin', 'editor']
|
|
183
|
+
|
|
184
|
+
def can_admin_agent(self, agent):
|
|
185
|
+
"""Check if user can manage collaborators on the agent."""
|
|
186
|
+
role = self.get_agent_role(agent)
|
|
187
|
+
return role in ['owner', 'admin']
|
|
36
188
|
|
|
37
189
|
|
|
38
190
|
class SystemAccessMixin:
|
|
@@ -40,27 +192,76 @@ class SystemAccessMixin:
|
|
|
40
192
|
Mixin that provides consistent system access logic.
|
|
41
193
|
|
|
42
194
|
- Superusers can access all systems
|
|
43
|
-
-
|
|
195
|
+
- Owners can access their own systems
|
|
196
|
+
- Collaborators can access systems they've been granted access to
|
|
44
197
|
"""
|
|
45
198
|
|
|
46
199
|
def get_user_systems_queryset(self):
|
|
47
200
|
"""Get queryset of systems accessible to the current user."""
|
|
48
201
|
if self.request.user.is_superuser:
|
|
49
202
|
return AgentSystem.objects.all()
|
|
50
|
-
|
|
203
|
+
# Include owned systems and systems where user is a collaborator
|
|
204
|
+
return AgentSystem.objects.filter(
|
|
205
|
+
Q(owner=self.request.user) |
|
|
206
|
+
Q(collaborators__user=self.request.user)
|
|
207
|
+
).distinct()
|
|
51
208
|
|
|
52
|
-
def get_system_for_user(self, system_id):
|
|
209
|
+
def get_system_for_user(self, system_id, require_edit=False):
|
|
53
210
|
"""
|
|
54
211
|
Get a specific system if the user has access.
|
|
55
212
|
|
|
56
|
-
|
|
57
|
-
|
|
213
|
+
Args:
|
|
214
|
+
system_id: The system's ID
|
|
215
|
+
require_edit: If True, requires edit permission (editor or admin role)
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
AgentSystem if user has access
|
|
219
|
+
|
|
220
|
+
Raises:
|
|
221
|
+
AgentSystem.DoesNotExist if no access
|
|
58
222
|
"""
|
|
59
223
|
if self.request.user.is_superuser:
|
|
60
224
|
return AgentSystem.objects.select_related('entry_agent').get(id=system_id)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
225
|
+
|
|
226
|
+
system = AgentSystem.objects.select_related('entry_agent').get(id=system_id)
|
|
227
|
+
|
|
228
|
+
# Owner always has full access
|
|
229
|
+
if system.owner == self.request.user:
|
|
230
|
+
return system
|
|
231
|
+
|
|
232
|
+
# Check collaborator access
|
|
233
|
+
try:
|
|
234
|
+
collab = SystemCollaborator.objects.get(system=system, user=self.request.user)
|
|
235
|
+
if require_edit and not collab.can_edit:
|
|
236
|
+
raise AgentSystem.DoesNotExist("Edit permission required")
|
|
237
|
+
return system
|
|
238
|
+
except SystemCollaborator.DoesNotExist:
|
|
239
|
+
raise AgentSystem.DoesNotExist("No access to this system")
|
|
240
|
+
|
|
241
|
+
def get_system_role(self, system):
|
|
242
|
+
"""
|
|
243
|
+
Get the user's role for a system.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
'owner', 'admin', 'editor', 'viewer', or None
|
|
247
|
+
"""
|
|
248
|
+
if self.request.user.is_superuser or system.owner == self.request.user:
|
|
249
|
+
return 'owner'
|
|
250
|
+
try:
|
|
251
|
+
collab = SystemCollaborator.objects.get(system=system, user=self.request.user)
|
|
252
|
+
return collab.role
|
|
253
|
+
except SystemCollaborator.DoesNotExist:
|
|
254
|
+
return None
|
|
255
|
+
|
|
256
|
+
def can_edit_system(self, system):
|
|
257
|
+
"""Check if user can edit the system."""
|
|
258
|
+
role = self.get_system_role(system)
|
|
259
|
+
return role in ['owner', 'admin', 'editor']
|
|
260
|
+
|
|
261
|
+
def can_admin_system(self, system):
|
|
262
|
+
"""Check if user can manage collaborators on the system."""
|
|
263
|
+
role = self.get_system_role(system)
|
|
264
|
+
return role in ['owner', 'admin']
|
|
64
265
|
|
|
65
266
|
|
|
66
267
|
class StudioHomeView(LoginRequiredMixin, AgentAccessMixin, SystemAccessMixin, TemplateView):
|
|
@@ -144,6 +345,18 @@ class SystemListView(LoginRequiredMixin, SystemAccessMixin, ListView):
|
|
|
144
345
|
).prefetch_related('members__agent').order_by("-updated_at")
|
|
145
346
|
|
|
146
347
|
|
|
348
|
+
class SystemCreateView(LoginRequiredMixin, AgentAccessMixin, TemplateView):
|
|
349
|
+
"""Create a new multi-agent system."""
|
|
350
|
+
|
|
351
|
+
template_name = "django_agent_studio/system_create.html"
|
|
352
|
+
|
|
353
|
+
def get_context_data(self, **kwargs):
|
|
354
|
+
context = super().get_context_data(**kwargs)
|
|
355
|
+
# Get user's agents for the entry agent dropdown
|
|
356
|
+
context["agents"] = self.get_user_agents_queryset().order_by("name")
|
|
357
|
+
return context
|
|
358
|
+
|
|
359
|
+
|
|
147
360
|
class SystemTestView(LoginRequiredMixin, SystemAccessMixin, TemplateView):
|
|
148
361
|
"""
|
|
149
362
|
Full-screen system testing interface.
|
|
@@ -161,3 +374,81 @@ class SystemTestView(LoginRequiredMixin, SystemAccessMixin, TemplateView):
|
|
|
161
374
|
context["agent"] = system.entry_agent # The entry point agent
|
|
162
375
|
return context
|
|
163
376
|
|
|
377
|
+
|
|
378
|
+
class AgentCollaboratorsView(LoginRequiredMixin, AgentAccessMixin, TemplateView):
|
|
379
|
+
"""Manage collaborators for an agent."""
|
|
380
|
+
|
|
381
|
+
template_name = "django_agent_studio/collaborators.html"
|
|
382
|
+
|
|
383
|
+
def get_context_data(self, **kwargs):
|
|
384
|
+
context = super().get_context_data(**kwargs)
|
|
385
|
+
agent_id = kwargs.get("agent_id")
|
|
386
|
+
agent = self.get_agent_for_user(agent_id)
|
|
387
|
+
|
|
388
|
+
context["object"] = agent
|
|
389
|
+
context["object_name"] = agent.name
|
|
390
|
+
context["object_type"] = "agent"
|
|
391
|
+
context["can_admin"] = self.can_admin_agent(agent)
|
|
392
|
+
|
|
393
|
+
# Owner info
|
|
394
|
+
if agent.owner:
|
|
395
|
+
context["owner_email"] = agent.owner.email
|
|
396
|
+
context["owner_initial"] = agent.owner.email[0].upper() if agent.owner.email else "?"
|
|
397
|
+
else:
|
|
398
|
+
context["owner_email"] = "No owner"
|
|
399
|
+
context["owner_initial"] = "?"
|
|
400
|
+
|
|
401
|
+
# Get systems this agent belongs to (for showing inherited access info)
|
|
402
|
+
agent_systems = AgentSystemMember.objects.filter(
|
|
403
|
+
agent=agent
|
|
404
|
+
).select_related('system', 'system__owner')
|
|
405
|
+
context["parent_systems"] = [
|
|
406
|
+
{
|
|
407
|
+
'id': str(member.system.id),
|
|
408
|
+
'name': member.system.name,
|
|
409
|
+
'role': member.role,
|
|
410
|
+
}
|
|
411
|
+
for member in agent_systems
|
|
412
|
+
]
|
|
413
|
+
|
|
414
|
+
return context
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
class SystemCollaboratorsView(LoginRequiredMixin, SystemAccessMixin, TemplateView):
|
|
418
|
+
"""Manage collaborators for a system."""
|
|
419
|
+
|
|
420
|
+
template_name = "django_agent_studio/collaborators.html"
|
|
421
|
+
|
|
422
|
+
def get_context_data(self, **kwargs):
|
|
423
|
+
context = super().get_context_data(**kwargs)
|
|
424
|
+
system_id = kwargs.get("system_id")
|
|
425
|
+
system = self.get_system_for_user(system_id)
|
|
426
|
+
|
|
427
|
+
context["object"] = system
|
|
428
|
+
context["object_name"] = system.name
|
|
429
|
+
context["object_type"] = "system"
|
|
430
|
+
context["can_admin"] = self.can_admin_system(system)
|
|
431
|
+
|
|
432
|
+
# Owner info
|
|
433
|
+
if system.owner:
|
|
434
|
+
context["owner_email"] = system.owner.email
|
|
435
|
+
context["owner_initial"] = system.owner.email[0].upper() if system.owner.email else "?"
|
|
436
|
+
else:
|
|
437
|
+
context["owner_email"] = "No owner"
|
|
438
|
+
context["owner_initial"] = "?"
|
|
439
|
+
|
|
440
|
+
# Get agents in this system (for showing what agents are included)
|
|
441
|
+
system_members = AgentSystemMember.objects.filter(
|
|
442
|
+
system=system
|
|
443
|
+
).select_related('agent')
|
|
444
|
+
context["member_agents"] = [
|
|
445
|
+
{
|
|
446
|
+
'id': str(member.agent.id),
|
|
447
|
+
'name': member.agent.name,
|
|
448
|
+
'role': member.role,
|
|
449
|
+
}
|
|
450
|
+
for member in system_members
|
|
451
|
+
]
|
|
452
|
+
|
|
453
|
+
return context
|
|
454
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-agent-studio
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
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.2** | 2026-01-30 | **Multi-User Access Control** - Collaborator management UI, user search autocomplete, supports both email and username-based User models, system creation from homepage, permission inheritance display |
|
|
129
130
|
| **0.3.1** | 2026-01-30 | **Bug Fixes** - Fixed duplicate message emit in dynamic agents, fixed escapejs encoding in templates, added 800px max-width constraint to system test view |
|
|
130
131
|
| **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 |
|
|
131
132
|
| **0.2.0** | 2026-01-28 | **Multi-Agent Systems** - System management UI, shared memory configuration, memory privacy controls, builder tools for managing agent systems |
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
django_agent_studio/__init__.py,sha256=E2vGoil7ZmwTebaB5ap9Lt0ptAzqYB5xJpyi4bFbqL8,378
|
|
2
2
|
django_agent_studio/apps.py,sha256=L89QWn4XOvPBs2z6qHAhaE4uZQpasJntYD75aSd2p_k,607
|
|
3
|
-
django_agent_studio/urls.py,sha256=
|
|
4
|
-
django_agent_studio/views.py,sha256=
|
|
3
|
+
django_agent_studio/urls.py,sha256=xlL1ZkVxbLXnorAgvL3onUpCtGmzsxp5aQputRzTui8,1269
|
|
4
|
+
django_agent_studio/views.py,sha256=IXYSWu-nDunVTQtWiq0fO89UsZQ9--25LtvLDye1wNg,15565
|
|
5
5
|
django_agent_studio/agents/__init__.py,sha256=VYL_ato0DtggIo4BGRkyiz9cm1ARPXhhTQFzoG__NVM,800
|
|
6
6
|
django_agent_studio/agents/builder.py,sha256=dRPQk5-AhUsTBOFxv8H4Uk2X2PfK631jjVJZ1w13GtM,146777
|
|
7
7
|
django_agent_studio/agents/dynamic.py,sha256=b2bwvwF9DOjEds4c0748mjKzCWbymcSlR4B9nP9Bk4Q,25367
|
|
8
8
|
django_agent_studio/api/__init__.py,sha256=vtBwuvBENyFFhFqCWyFsI6cYu4N9ZGqSMmHIRhr9a_U,45
|
|
9
9
|
django_agent_studio/api/permissions.py,sha256=MutmA8TxZb4ZwGfeEoolK-QI04Gbcxs7DPNzkXe_Bss,5302
|
|
10
|
-
django_agent_studio/api/serializers.py,sha256=
|
|
11
|
-
django_agent_studio/api/urls.py,sha256=
|
|
12
|
-
django_agent_studio/api/views.py,sha256=
|
|
10
|
+
django_agent_studio/api/serializers.py,sha256=qIQ74JzOdJRp_Sh2xtETuRwtRThcpn3EYS14rvAKdHA,23593
|
|
11
|
+
django_agent_studio/api/urls.py,sha256=xfL3AbTP0GKRYarDExvUoXuz0txhgNCumgjVehSfmTY,9893
|
|
12
|
+
django_agent_studio/api/views.py,sha256=fECFWpu08ibQpOR-sL7AVCoTh4Ox6cYUEm4lh5GAPsE,90869
|
|
13
13
|
django_agent_studio/management/__init__.py,sha256=6O9RHMN_xMDrEzKWytpai6QqgTXZVqwRg4h9mIQWtA8,52
|
|
14
14
|
django_agent_studio/management/commands/__init__.py,sha256=6O9RHMN_xMDrEzKWytpai6QqgTXZVqwRg4h9mIQWtA8,52
|
|
15
15
|
django_agent_studio/migrations/0001_initial.py,sha256=ThIhf1X6ZaACQd-5GjJG-MDjIm6ETl0Nc2hcYK0L2Wg,4292
|
|
@@ -24,15 +24,17 @@ django_agent_studio/static/agent-frontend/chat-widget.js,sha256=Yla8YlsmMtdXZRjN
|
|
|
24
24
|
django_agent_studio/static/django_agent_studio/js/builder.js,sha256=eEUw2z-pNdoU3xv3NhLQ-uDZV7tsf8Bawseg7B7dpCo,413948
|
|
25
25
|
django_agent_studio/static/django_agent_studio/js/builder.js.map,sha256=sVkeGyZsBWEr4MKhqAfd3B4JL5n7D6eKc_4ZYUsbKO8,1633363
|
|
26
26
|
django_agent_studio/static/django_agent_studio/js/style.css,sha256=rigQJy_oHIhgb1_7DwAQ_8G002gQnT0AXUtwxImWj1o,1626515
|
|
27
|
-
django_agent_studio/templates/django_agent_studio/agent_list.html,sha256=
|
|
27
|
+
django_agent_studio/templates/django_agent_studio/agent_list.html,sha256=pIW6cRQ-i_hKWB_qDUuSBbzZw2qL_qJumhrW8C4Rs14,4931
|
|
28
28
|
django_agent_studio/templates/django_agent_studio/base.html,sha256=wSgwaqK1DAIIyYeZWsVvPlpAZyZHBEx3_NGtdRo0J3A,6019
|
|
29
29
|
django_agent_studio/templates/django_agent_studio/builder.html,sha256=yPzb0Pdp0d7Sp7gVkJd7OouDq-toKCA8i7OJLU9x6Z8,1542
|
|
30
|
-
django_agent_studio/templates/django_agent_studio/
|
|
31
|
-
django_agent_studio/templates/django_agent_studio/
|
|
32
|
-
django_agent_studio/templates/django_agent_studio/
|
|
33
|
-
django_agent_studio/templates/django_agent_studio/
|
|
34
|
-
django_agent_studio
|
|
35
|
-
django_agent_studio
|
|
36
|
-
django_agent_studio-0.3.
|
|
37
|
-
django_agent_studio-0.3.
|
|
38
|
-
django_agent_studio-0.3.
|
|
30
|
+
django_agent_studio/templates/django_agent_studio/collaborators.html,sha256=qPV0YG8V8eFCdK3e--kgxh3iT4jPHAXCxkSzOBkx7bg,19482
|
|
31
|
+
django_agent_studio/templates/django_agent_studio/home.html,sha256=ebA-U1HseIzY5pPeXKluzI8vsKOh1owkKZxhys27Yns,6914
|
|
32
|
+
django_agent_studio/templates/django_agent_studio/system_create.html,sha256=MOhKMuiR2Iley0J7gvFk9yxLT51BqPrOhk0PbJ-QXjo,6392
|
|
33
|
+
django_agent_studio/templates/django_agent_studio/system_list.html,sha256=CN2o3nFpsZHwv6Wva1DkzYaAZnK204Q6FAqVH08L6_0,4666
|
|
34
|
+
django_agent_studio/templates/django_agent_studio/system_test.html,sha256=CANXocxO1dG2JZSSHrEIYWQovapBA2GVQ9U8MIBzRg4,4238
|
|
35
|
+
django_agent_studio/templates/django_agent_studio/test.html,sha256=y2BjAwq0zxjdoMEM8K_rH0zCjcj1DL-Jj2BIQTJorxA,4088
|
|
36
|
+
django_agent_studio-0.3.2.dist-info/licenses/LICENSE,sha256=WIh21lpD7d7xCUtLysKK-kbfW4SG7GNPf_k7_Xm_sZg,3851
|
|
37
|
+
django_agent_studio-0.3.2.dist-info/METADATA,sha256=NLLNO4VvoR9E0xXQdnEX5m_ffQac5pKQdvbSE4HGmjM,16899
|
|
38
|
+
django_agent_studio-0.3.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
39
|
+
django_agent_studio-0.3.2.dist-info/top_level.txt,sha256=O1kqZzXPOsJlqnPSAcB2fH5WpJNY8ZNfHEJzX9_SZ0A,20
|
|
40
|
+
django_agent_studio-0.3.2.dist-info/RECORD,,
|
|
File without changes
|
{django_agent_studio-0.3.1.dist-info → django_agent_studio-0.3.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|