django-agent-studio 0.3.3__py3-none-any.whl → 0.3.4__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/agents/dynamic.py +164 -4
- django_agent_studio/api/serializers.py +27 -8
- django_agent_studio/branding.py +103 -0
- django_agent_studio/static/agent-frontend/chat-widget.css +52 -0
- django_agent_studio/static/agent-frontend/chat-widget.js +222 -206
- django_agent_studio/static/django_agent_studio/js/builder.js +58 -58
- django_agent_studio/static/django_agent_studio/js/builder.js.map +1 -1
- django_agent_studio/static/django_agent_studio/js/style.css +1 -1
- django_agent_studio/templates/django_agent_studio/agent_list.html +31 -28
- django_agent_studio/templates/django_agent_studio/base.html +116 -28
- django_agent_studio/templates/django_agent_studio/builder.html +1 -1
- django_agent_studio/templates/django_agent_studio/collaborators.html +83 -95
- django_agent_studio/templates/django_agent_studio/home.html +66 -48
- django_agent_studio/templates/django_agent_studio/system_create.html +22 -24
- django_agent_studio/templates/django_agent_studio/system_list.html +38 -30
- django_agent_studio/templates/django_agent_studio/system_test.html +27 -21
- django_agent_studio/templates/django_agent_studio/test.html +22 -17
- {django_agent_studio-0.3.3.dist-info → django_agent_studio-0.3.4.dist-info}/METADATA +1 -1
- {django_agent_studio-0.3.3.dist-info → django_agent_studio-0.3.4.dist-info}/RECORD +22 -21
- {django_agent_studio-0.3.3.dist-info → django_agent_studio-0.3.4.dist-info}/WHEEL +0 -0
- {django_agent_studio-0.3.3.dist-info → django_agent_studio-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {django_agent_studio-0.3.3.dist-info → django_agent_studio-0.3.4.dist-info}/top_level.txt +0 -0
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
{% extends "django_agent_studio/base.html" %}
|
|
2
2
|
|
|
3
|
-
{% block title %}Collaborators - {{ object_name }} -
|
|
3
|
+
{% block title %}Collaborators - {{ object_name }} - {{ studio_app_name }}{% endblock %}
|
|
4
4
|
|
|
5
5
|
{% block breadcrumbs %}
|
|
6
6
|
<nav class="flex items-center space-x-2 ml-4 text-sm">
|
|
7
|
-
<span class="text-
|
|
7
|
+
<span class="text-white/40">/</span>
|
|
8
8
|
{% if object_type == 'agent' %}
|
|
9
|
-
<a href="{% url 'agent_studio:agent_list' %}" class="text-
|
|
10
|
-
<span class="text-
|
|
11
|
-
<a href="{% url 'agent_studio:agent_edit' object.id %}" class="text-
|
|
9
|
+
<a href="{% url 'agent_studio:agent_list' %}" class="text-white/60 hover:text-white/90 transition-colors">My Agents</a>
|
|
10
|
+
<span class="text-white/40">/</span>
|
|
11
|
+
<a href="{% url 'agent_studio:agent_edit' object.id %}" class="text-white/60 hover:text-white/90 transition-colors">{{ object_name }}</a>
|
|
12
12
|
{% else %}
|
|
13
|
-
<a href="{% url 'agent_studio:system_list' %}" class="text-
|
|
14
|
-
<span class="text-
|
|
15
|
-
<a href="{% url 'agent_studio:system_test' object.id %}" class="text-
|
|
13
|
+
<a href="{% url 'agent_studio:system_list' %}" class="text-white/60 hover:text-white/90 transition-colors">My Systems</a>
|
|
14
|
+
<span class="text-white/40">/</span>
|
|
15
|
+
<a href="{% url 'agent_studio:system_test' object.id %}" class="text-white/60 hover:text-white/90 transition-colors">{{ object_name }}</a>
|
|
16
16
|
{% endif %}
|
|
17
|
-
<span class="text-
|
|
18
|
-
<span class="text-
|
|
17
|
+
<span class="text-white/40">/</span>
|
|
18
|
+
<span class="text-white/70">Collaborators</span>
|
|
19
19
|
</nav>
|
|
20
20
|
{% endblock %}
|
|
21
21
|
|
|
22
22
|
{% block content %}
|
|
23
|
-
<div class="h-full p-6 overflow-auto">
|
|
23
|
+
<div class="h-full p-6 overflow-auto bg-gradient-to-br from-slate-50 to-slate-100">
|
|
24
24
|
<div class="max-w-4xl mx-auto">
|
|
25
25
|
<!-- Header -->
|
|
26
26
|
<div class="flex items-center justify-between mb-6">
|
|
27
27
|
<div>
|
|
28
|
-
<h1 class="text-2xl font-bold text-
|
|
29
|
-
<p class="text-
|
|
28
|
+
<h1 class="text-2xl font-bold text-navy">👥 Collaborators</h1>
|
|
29
|
+
<p class="text-slate-500 mt-1">Manage who can access {{ object_name }}</p>
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
33
|
{% if object_type == 'system' and member_agents %}
|
|
34
34
|
<!-- System: Show included agents -->
|
|
35
|
-
<div class="bg-
|
|
36
|
-
<h3 class="font-semibold text-
|
|
37
|
-
<i class="pi pi-info-circle mr-2"></i>Included Agents
|
|
35
|
+
<div class="bg-cyan/5 border border-cyan/30 rounded-xl p-4 mb-6">
|
|
36
|
+
<h3 class="font-semibold text-navy mb-2">
|
|
37
|
+
<i class="pi pi-info-circle mr-2 text-cyan"></i>Included Agents
|
|
38
38
|
</h3>
|
|
39
|
-
<p class="text-sm text-
|
|
39
|
+
<p class="text-sm text-slate-600 mb-3">
|
|
40
40
|
Collaborators on this system automatically get access to all agents below:
|
|
41
41
|
</p>
|
|
42
42
|
<div class="flex flex-wrap gap-2">
|
|
43
43
|
{% for agent in member_agents %}
|
|
44
44
|
<a href="{% url 'agent_studio:agent_collaborators' agent.id %}"
|
|
45
|
-
class="inline-flex items-center px-3 py-1.5 bg-white border border-
|
|
46
|
-
<i class="pi pi-android mr-1.5"></i>
|
|
45
|
+
class="inline-flex items-center px-3 py-1.5 bg-white border border-cyan/30 rounded-lg text-sm text-navy hover:bg-cyan/10 transition-colors">
|
|
46
|
+
<i class="pi pi-android mr-1.5 text-cyan"></i>
|
|
47
47
|
{{ agent.name }}
|
|
48
|
-
<span class="ml-1.5 text-xs text-
|
|
48
|
+
<span class="ml-1.5 text-xs text-slate-400">({{ agent.role }})</span>
|
|
49
49
|
</a>
|
|
50
50
|
{% endfor %}
|
|
51
51
|
</div>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
{% if object_type == 'agent' and parent_systems %}
|
|
56
56
|
<!-- Agent: Show parent systems -->
|
|
57
|
-
<div class="bg-amber-50 border border-amber-200 rounded-
|
|
57
|
+
<div class="bg-amber-50 border border-amber-200 rounded-xl p-4 mb-6">
|
|
58
58
|
<h3 class="font-semibold text-amber-800 mb-2">
|
|
59
59
|
<i class="pi pi-info-circle mr-2"></i>Inherited Access
|
|
60
60
|
</h3>
|
|
@@ -75,77 +75,77 @@
|
|
|
75
75
|
{% endif %}
|
|
76
76
|
|
|
77
77
|
<!-- Owner Info -->
|
|
78
|
-
<div class="bg-white border border-
|
|
78
|
+
<div class="bg-white border border-slate-200 rounded-xl p-4 mb-6 shadow-sm">
|
|
79
79
|
<div class="flex items-center justify-between">
|
|
80
80
|
<div class="flex items-center space-x-3">
|
|
81
|
-
<div class="w-10 h-10 bg-
|
|
82
|
-
<span class="text-
|
|
81
|
+
<div class="w-10 h-10 bg-navy/10 rounded-full flex items-center justify-center">
|
|
82
|
+
<span class="text-navy font-semibold">{{ owner_initial }}</span>
|
|
83
83
|
</div>
|
|
84
84
|
<div>
|
|
85
|
-
<p class="font-medium text-
|
|
86
|
-
<p class="text-sm text-
|
|
85
|
+
<p class="font-medium text-navy">{{ owner_email }}</p>
|
|
86
|
+
<p class="text-sm text-slate-500">Owner</p>
|
|
87
87
|
</div>
|
|
88
88
|
</div>
|
|
89
|
-
<span class="bg-
|
|
89
|
+
<span class="bg-navy/10 text-navy px-3 py-1 rounded-full text-sm font-medium">Owner</span>
|
|
90
90
|
</div>
|
|
91
91
|
</div>
|
|
92
92
|
|
|
93
93
|
<!-- Add Collaborator Form -->
|
|
94
94
|
{% if can_admin %}
|
|
95
|
-
<div class="bg-white border border-
|
|
96
|
-
<h3 class="font-semibold text-
|
|
95
|
+
<div class="bg-white border border-slate-200 rounded-xl p-5 mb-6 shadow-sm">
|
|
96
|
+
<h3 class="font-semibold text-navy mb-4">Add Collaborator</h3>
|
|
97
97
|
<form @submit.prevent="addCollaborator" class="flex items-end space-x-4">
|
|
98
98
|
<div class="flex-1 relative">
|
|
99
|
-
<label class="block text-sm font-medium text-
|
|
99
|
+
<label class="block text-sm font-medium text-navy mb-1">Search User</label>
|
|
100
100
|
<input type="text" v-model="searchQuery" @input="searchUsers" @focus="showResults = true"
|
|
101
|
-
class="w-full px-
|
|
101
|
+
class="w-full px-4 py-2.5 border border-slate-200 rounded-lg focus:ring-2 focus:ring-cyan/30 focus:border-cyan transition-all"
|
|
102
102
|
placeholder="Type to search by name or email..."
|
|
103
103
|
autocomplete="off">
|
|
104
104
|
<!-- Search Results Dropdown -->
|
|
105
105
|
<div v-if="showResults && (searchResults.length > 0 || searchQuery.length >= 2)"
|
|
106
|
-
class="absolute z-10 w-full mt-1 bg-white border border-
|
|
107
|
-
<div v-if="searching" class="p-3 text-center text-
|
|
106
|
+
class="absolute z-10 w-full mt-1 bg-white border border-slate-200 rounded-xl shadow-lg max-h-60 overflow-auto">
|
|
107
|
+
<div v-if="searching" class="p-3 text-center text-slate-500">
|
|
108
108
|
<i class="pi pi-spin pi-spinner mr-2"></i>Searching...
|
|
109
109
|
</div>
|
|
110
|
-
<div v-else-if="searchResults.length === 0 && searchQuery.length >= 2" class="p-3 text-center text-
|
|
110
|
+
<div v-else-if="searchResults.length === 0 && searchQuery.length >= 2" class="p-3 text-center text-slate-500">
|
|
111
111
|
No users found
|
|
112
112
|
</div>
|
|
113
113
|
<div v-else>
|
|
114
114
|
<button v-for="user in searchResults" :key="user.id" type="button"
|
|
115
115
|
@click="selectUser(user)"
|
|
116
|
-
class="w-full px-3 py-2 text-left hover:bg-
|
|
117
|
-
<div class="w-8 h-8 bg-
|
|
118
|
-
<span class="text-
|
|
116
|
+
class="w-full px-3 py-2 text-left hover:bg-cyan/5 flex items-center space-x-3 border-b border-slate-100 last:border-0 transition-colors">
|
|
117
|
+
<div class="w-8 h-8 bg-cyan/10 rounded-full flex items-center justify-center flex-shrink-0">
|
|
118
|
+
<span class="text-navy font-semibold text-sm">[[ user.name.charAt(0).toUpperCase() ]]</span>
|
|
119
119
|
</div>
|
|
120
120
|
<div class="min-w-0 flex-1">
|
|
121
|
-
<p class="font-medium text-
|
|
122
|
-
<p class="text-sm text-
|
|
121
|
+
<p class="font-medium text-navy truncate">[[ user.name ]]</p>
|
|
122
|
+
<p class="text-sm text-slate-500 truncate">[[ user.email ]]</p>
|
|
123
123
|
</div>
|
|
124
124
|
</button>
|
|
125
125
|
</div>
|
|
126
126
|
</div>
|
|
127
127
|
<!-- Selected User Display -->
|
|
128
|
-
<div v-if="selectedUser" class="mt-2 flex items-center space-x-2 bg-
|
|
129
|
-
<div class="w-6 h-6 bg-
|
|
130
|
-
<span class="text-
|
|
128
|
+
<div v-if="selectedUser" class="mt-2 flex items-center space-x-2 bg-cyan/10 border border-cyan/30 rounded-lg px-3 py-2">
|
|
129
|
+
<div class="w-6 h-6 bg-cyan/20 rounded-full flex items-center justify-center">
|
|
130
|
+
<span class="text-navy font-semibold text-xs">[[ selectedUser.name.charAt(0).toUpperCase() ]]</span>
|
|
131
131
|
</div>
|
|
132
|
-
<span class="text-sm text-
|
|
133
|
-
<button type="button" @click="clearSelection" class="text-
|
|
132
|
+
<span class="text-sm text-navy flex-1">[[ selectedUser.display ]]</span>
|
|
133
|
+
<button type="button" @click="clearSelection" class="text-navy/60 hover:text-navy">
|
|
134
134
|
<i class="pi pi-times text-sm"></i>
|
|
135
135
|
</button>
|
|
136
136
|
</div>
|
|
137
137
|
</div>
|
|
138
138
|
<div class="w-40">
|
|
139
|
-
<label class="block text-sm font-medium text-
|
|
139
|
+
<label class="block text-sm font-medium text-navy mb-1">Role</label>
|
|
140
140
|
<select v-model="newRole"
|
|
141
|
-
class="w-full px-
|
|
141
|
+
class="w-full px-4 py-2.5 border border-slate-200 rounded-lg focus:ring-2 focus:ring-cyan/30 focus:border-cyan transition-all">
|
|
142
142
|
<option value="viewer">Viewer</option>
|
|
143
143
|
<option value="editor">Editor</option>
|
|
144
144
|
<option value="admin">Admin</option>
|
|
145
145
|
</select>
|
|
146
146
|
</div>
|
|
147
147
|
<button type="submit" :disabled="adding || !selectedUser"
|
|
148
|
-
class="bg-
|
|
148
|
+
class="bg-cyan hover:bg-cyan-dark text-navy px-5 py-2.5 rounded-xl flex items-center space-x-2 transition-all disabled:opacity-50 font-medium hover:shadow-md">
|
|
149
149
|
<i class="pi pi-plus"></i>
|
|
150
150
|
<span>[[ adding ? 'Adding...' : 'Add' ]]</span>
|
|
151
151
|
</button>
|
|
@@ -155,49 +155,51 @@
|
|
|
155
155
|
{% endif %}
|
|
156
156
|
|
|
157
157
|
<!-- Collaborators List -->
|
|
158
|
-
<div class="bg-white border border-
|
|
159
|
-
<div class="px-
|
|
160
|
-
<h3 class="font-semibold text-
|
|
158
|
+
<div class="bg-white border border-slate-200 rounded-xl overflow-hidden shadow-sm">
|
|
159
|
+
<div class="px-5 py-3 border-b border-slate-100 bg-slate-50/50">
|
|
160
|
+
<h3 class="font-semibold text-navy">Collaborators ([[ collaborators.length ]])</h3>
|
|
161
161
|
</div>
|
|
162
162
|
|
|
163
|
-
<div v-if="loading" class="p-8 text-center text-
|
|
164
|
-
<i class="pi pi-spin pi-spinner text-2xl"></i>
|
|
163
|
+
<div v-if="loading" class="p-8 text-center text-slate-500">
|
|
164
|
+
<i class="pi pi-spin pi-spinner text-2xl text-cyan"></i>
|
|
165
165
|
<p class="mt-2">Loading collaborators...</p>
|
|
166
166
|
</div>
|
|
167
167
|
|
|
168
|
-
<div v-else-if="collaborators.length === 0" class="p-8 text-center
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
<div v-else-if="collaborators.length === 0" class="p-8 text-center">
|
|
169
|
+
<div class="w-12 h-12 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-3">
|
|
170
|
+
<i class="pi pi-users text-2xl text-slate-400"></i>
|
|
171
|
+
</div>
|
|
172
|
+
<p class="text-slate-500">No collaborators yet</p>
|
|
173
|
+
<p class="text-sm text-slate-400">Add collaborators to share access to this {{ object_type }}</p>
|
|
172
174
|
</div>
|
|
173
175
|
|
|
174
|
-
<div v-else class="divide-y divide-
|
|
176
|
+
<div v-else class="divide-y divide-slate-100">
|
|
175
177
|
<div v-for="collab in collaborators" :key="collab.id"
|
|
176
|
-
class="p-4 flex items-center justify-between hover:bg-
|
|
178
|
+
class="p-4 flex items-center justify-between hover:bg-slate-50/50 transition-colors">
|
|
177
179
|
<div class="flex items-center space-x-3">
|
|
178
|
-
<div class="w-10 h-10 bg-
|
|
179
|
-
<span class="text-
|
|
180
|
+
<div class="w-10 h-10 bg-slate-100 rounded-full flex items-center justify-center">
|
|
181
|
+
<span class="text-slate-600 font-semibold">[[ getInitial(collab.user_email) ]]</span>
|
|
180
182
|
</div>
|
|
181
183
|
<div>
|
|
182
|
-
<p class="font-medium text-
|
|
183
|
-
<p class="text-sm text-
|
|
184
|
+
<p class="font-medium text-navy">[[ collab.user_name || collab.user_email ]]</p>
|
|
185
|
+
<p class="text-sm text-slate-500">[[ collab.user_email ]]</p>
|
|
184
186
|
</div>
|
|
185
187
|
</div>
|
|
186
188
|
<div class="flex items-center space-x-3">
|
|
187
189
|
{% if can_admin %}
|
|
188
190
|
<select v-model="collab.role" @change="updateRole(collab)"
|
|
189
|
-
class="px-3 py-1.5 border border-
|
|
191
|
+
class="px-3 py-1.5 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-cyan/30 focus:border-cyan transition-all">
|
|
190
192
|
<option value="viewer">Viewer</option>
|
|
191
193
|
<option value="editor">Editor</option>
|
|
192
194
|
<option value="admin">Admin</option>
|
|
193
195
|
</select>
|
|
194
196
|
<button @click="removeCollaborator(collab)"
|
|
195
|
-
class="text-red-
|
|
197
|
+
class="text-red-500 hover:text-red-600 p-1.5 hover:bg-red-50 rounded-lg transition-colors"
|
|
196
198
|
title="Remove collaborator">
|
|
197
199
|
<i class="pi pi-trash"></i>
|
|
198
200
|
</button>
|
|
199
201
|
{% else %}
|
|
200
|
-
<span class="px-3 py-1.5 bg-
|
|
202
|
+
<span class="px-3 py-1.5 bg-slate-100 text-slate-700 rounded-lg text-sm">[[ collab.role_display ]]</span>
|
|
201
203
|
{% endif %}
|
|
202
204
|
</div>
|
|
203
205
|
</div>
|
|
@@ -205,26 +207,26 @@
|
|
|
205
207
|
</div>
|
|
206
208
|
|
|
207
209
|
<!-- Role Descriptions -->
|
|
208
|
-
<div class="mt-6 bg-
|
|
209
|
-
<h4 class="font-medium text-
|
|
210
|
+
<div class="mt-6 bg-white border border-slate-200 rounded-xl p-5 shadow-sm">
|
|
211
|
+
<h4 class="font-medium text-navy mb-3">Role Permissions</h4>
|
|
210
212
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
|
211
|
-
<div>
|
|
212
|
-
<p class="font-medium text-
|
|
213
|
-
<p class="text-
|
|
213
|
+
<div class="p-3 bg-slate-50 rounded-lg">
|
|
214
|
+
<p class="font-medium text-navy">Viewer</p>
|
|
215
|
+
<p class="text-slate-500">Can view and test the {{ object_type }}</p>
|
|
214
216
|
</div>
|
|
215
|
-
<div>
|
|
216
|
-
<p class="font-medium text-
|
|
217
|
-
<p class="text-
|
|
217
|
+
<div class="p-3 bg-slate-50 rounded-lg">
|
|
218
|
+
<p class="font-medium text-navy">Editor</p>
|
|
219
|
+
<p class="text-slate-500">Can view, test, and edit the {{ object_type }}</p>
|
|
218
220
|
</div>
|
|
219
|
-
<div>
|
|
220
|
-
<p class="font-medium text-
|
|
221
|
-
<p class="text-
|
|
221
|
+
<div class="p-3 bg-slate-50 rounded-lg">
|
|
222
|
+
<p class="font-medium text-navy">Admin</p>
|
|
223
|
+
<p class="text-slate-500">Can view, test, edit, and manage collaborators</p>
|
|
222
224
|
</div>
|
|
223
225
|
</div>
|
|
224
226
|
{% if object_type == 'system' %}
|
|
225
|
-
<div class="mt-4 pt-4 border-t border-
|
|
226
|
-
<p class="text-sm text-
|
|
227
|
-
<i class="pi pi-info-circle mr-1"></i>
|
|
227
|
+
<div class="mt-4 pt-4 border-t border-slate-100">
|
|
228
|
+
<p class="text-sm text-slate-600">
|
|
229
|
+
<i class="pi pi-info-circle mr-1 text-cyan"></i>
|
|
228
230
|
<strong>Note:</strong> System collaborators automatically get the same access level to all agents in this system.
|
|
229
231
|
</p>
|
|
230
232
|
</div>
|
|
@@ -250,14 +252,12 @@ createApp({
|
|
|
250
252
|
return {
|
|
251
253
|
collaborators: [],
|
|
252
254
|
loading: true,
|
|
253
|
-
// Search state
|
|
254
255
|
searchQuery: '',
|
|
255
256
|
searchResults: [],
|
|
256
257
|
selectedUser: null,
|
|
257
258
|
showResults: false,
|
|
258
259
|
searching: false,
|
|
259
260
|
searchTimeout: null,
|
|
260
|
-
// Form state
|
|
261
261
|
newRole: 'viewer',
|
|
262
262
|
adding: false,
|
|
263
263
|
addError: null,
|
|
@@ -268,14 +268,11 @@ createApp({
|
|
|
268
268
|
this.loading = true;
|
|
269
269
|
try {
|
|
270
270
|
const response = await fetch(apiUrl, {
|
|
271
|
-
headers: {
|
|
272
|
-
'Content-Type': 'application/json',
|
|
273
|
-
},
|
|
271
|
+
headers: { 'Content-Type': 'application/json' },
|
|
274
272
|
credentials: 'same-origin',
|
|
275
273
|
});
|
|
276
274
|
if (response.ok) {
|
|
277
275
|
const data = await response.json();
|
|
278
|
-
// Handle both paginated and non-paginated responses
|
|
279
276
|
this.collaborators = data.results !== undefined ? data.results : data;
|
|
280
277
|
}
|
|
281
278
|
} catch (error) {
|
|
@@ -285,15 +282,12 @@ createApp({
|
|
|
285
282
|
}
|
|
286
283
|
},
|
|
287
284
|
searchUsers() {
|
|
288
|
-
// Debounce search
|
|
289
285
|
clearTimeout(this.searchTimeout);
|
|
290
286
|
this.showResults = true;
|
|
291
|
-
|
|
292
287
|
if (this.searchQuery.length < 2) {
|
|
293
288
|
this.searchResults = [];
|
|
294
289
|
return;
|
|
295
290
|
}
|
|
296
|
-
|
|
297
291
|
this.searchTimeout = setTimeout(async () => {
|
|
298
292
|
this.searching = true;
|
|
299
293
|
try {
|
|
@@ -322,7 +316,6 @@ createApp({
|
|
|
322
316
|
},
|
|
323
317
|
async addCollaborator() {
|
|
324
318
|
if (!this.selectedUser) return;
|
|
325
|
-
|
|
326
319
|
this.adding = true;
|
|
327
320
|
this.addError = null;
|
|
328
321
|
try {
|
|
@@ -365,7 +358,6 @@ createApp({
|
|
|
365
358
|
body: JSON.stringify({ role: collab.role }),
|
|
366
359
|
});
|
|
367
360
|
if (!response.ok) {
|
|
368
|
-
// Revert on error
|
|
369
361
|
await this.loadCollaborators();
|
|
370
362
|
}
|
|
371
363
|
} catch (error) {
|
|
@@ -378,9 +370,7 @@ createApp({
|
|
|
378
370
|
try {
|
|
379
371
|
const response = await fetch(`${apiUrl}${collab.id}/`, {
|
|
380
372
|
method: 'DELETE',
|
|
381
|
-
headers: {
|
|
382
|
-
'X-CSRFToken': this.getCsrfToken(),
|
|
383
|
-
},
|
|
373
|
+
headers: { 'X-CSRFToken': this.getCsrfToken() },
|
|
384
374
|
credentials: 'same-origin',
|
|
385
375
|
});
|
|
386
376
|
if (response.ok) {
|
|
@@ -405,7 +395,6 @@ createApp({
|
|
|
405
395
|
},
|
|
406
396
|
mounted() {
|
|
407
397
|
this.loadCollaborators();
|
|
408
|
-
// Close search results when clicking outside
|
|
409
398
|
document.addEventListener('click', (e) => {
|
|
410
399
|
if (!e.target.closest('.relative')) {
|
|
411
400
|
this.showResults = false;
|
|
@@ -415,4 +404,3 @@ createApp({
|
|
|
415
404
|
}).use(primevue.config.default).mount('#app');
|
|
416
405
|
</script>
|
|
417
406
|
{% endblock %}
|
|
418
|
-
|
|
@@ -1,88 +1,100 @@
|
|
|
1
1
|
{% extends "django_agent_studio/base.html" %}
|
|
2
2
|
|
|
3
|
-
{% block title %}
|
|
3
|
+
{% block title %}{{ studio_app_name }} - Home{% endblock %}
|
|
4
4
|
|
|
5
5
|
{% block content %}
|
|
6
|
-
<div class="h-full p-6 overflow-auto">
|
|
6
|
+
<div class="h-full p-6 overflow-auto bg-gradient-to-br from-slate-50 to-slate-100">
|
|
7
7
|
<div class="max-w-6xl mx-auto">
|
|
8
8
|
<!-- Welcome Section -->
|
|
9
9
|
<div class="mb-8">
|
|
10
|
-
<h1 class="text-3xl font-bold text-
|
|
11
|
-
<p class="text-
|
|
10
|
+
<h1 class="text-3xl font-bold text-navy mb-2">Welcome to Agent Studio</h1>
|
|
11
|
+
<p class="text-slate-600">Build, customize, and manage your AI agents in one place.</p>
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
14
|
<!-- Quick Actions -->
|
|
15
15
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4 mb-8">
|
|
16
16
|
<a href="{% url 'agent_studio:system_create' %}"
|
|
17
|
-
class="bg-
|
|
17
|
+
class="bg-navy hover:bg-navy-light text-white rounded-xl p-5 transition-all hover:shadow-lg hover:-translate-y-0.5 group">
|
|
18
18
|
<div class="flex items-center space-x-3 mb-2">
|
|
19
|
-
<span class="text-2xl">🔗</span>
|
|
19
|
+
<span class="text-2xl group-hover:scale-110 transition-transform">🔗</span>
|
|
20
20
|
<span class="text-lg font-semibold">New System</span>
|
|
21
21
|
</div>
|
|
22
|
-
<p class="text-
|
|
22
|
+
<p class="text-white/70 text-sm">Create a multi-agent system</p>
|
|
23
23
|
</a>
|
|
24
24
|
|
|
25
25
|
<a href="{% url 'agent_studio:agent_create' %}"
|
|
26
|
-
class="bg-
|
|
26
|
+
class="bg-cyan text-navy rounded-xl p-5 transition-all hover:shadow-lg hover:-translate-y-0.5 group hover:bg-cyan-dark">
|
|
27
27
|
<div class="flex items-center space-x-3 mb-2">
|
|
28
|
-
<span class="text-2xl">✨</span>
|
|
28
|
+
<span class="text-2xl group-hover:scale-110 transition-transform">✨</span>
|
|
29
29
|
<span class="text-lg font-semibold">New Agent</span>
|
|
30
30
|
</div>
|
|
31
|
-
<p class="text-
|
|
31
|
+
<p class="text-navy/70 text-sm">Build a custom AI agent</p>
|
|
32
32
|
</a>
|
|
33
33
|
|
|
34
34
|
<a href="{% url 'agent_studio:system_list' %}"
|
|
35
|
-
class="bg-white hover:bg-
|
|
35
|
+
class="bg-white hover:bg-slate-50 border border-slate-200 rounded-xl p-5 transition-all hover:shadow-md hover:border-cyan group">
|
|
36
36
|
<div class="flex items-center space-x-3 mb-2">
|
|
37
|
-
<span class="text-2xl">🔗</span>
|
|
38
|
-
<span class="text-lg font-semibold text-
|
|
37
|
+
<span class="text-2xl group-hover:scale-110 transition-transform">🔗</span>
|
|
38
|
+
<span class="text-lg font-semibold text-navy">My Systems</span>
|
|
39
39
|
</div>
|
|
40
|
-
<p class="text-
|
|
40
|
+
<p class="text-slate-600 text-sm">View multi-agent systems</p>
|
|
41
41
|
</a>
|
|
42
42
|
|
|
43
43
|
<a href="{% url 'agent_studio:agent_list' %}"
|
|
44
|
-
class="bg-white hover:bg-
|
|
44
|
+
class="bg-white hover:bg-slate-50 border border-slate-200 rounded-xl p-5 transition-all hover:shadow-md hover:border-cyan group">
|
|
45
45
|
<div class="flex items-center space-x-3 mb-2">
|
|
46
|
-
<span class="text-2xl">📋</span>
|
|
47
|
-
<span class="text-lg font-semibold text-
|
|
46
|
+
<span class="text-2xl group-hover:scale-110 transition-transform">📋</span>
|
|
47
|
+
<span class="text-lg font-semibold text-navy">My Agents</span>
|
|
48
48
|
</div>
|
|
49
|
-
<p class="text-
|
|
49
|
+
<p class="text-slate-600 text-sm">View and manage agents</p>
|
|
50
50
|
</a>
|
|
51
51
|
|
|
52
|
-
<div class="bg-white
|
|
52
|
+
<div class="bg-white/50 border border-slate-200 border-dashed rounded-xl p-5 opacity-60 cursor-not-allowed">
|
|
53
53
|
<div class="flex items-center space-x-3 mb-2">
|
|
54
54
|
<span class="text-2xl">📚</span>
|
|
55
|
-
<span class="text-lg font-semibold text-
|
|
55
|
+
<span class="text-lg font-semibold text-slate-500">Templates</span>
|
|
56
56
|
</div>
|
|
57
|
-
<p class="text-
|
|
57
|
+
<p class="text-slate-400 text-sm">Coming soon</p>
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
60
60
|
|
|
61
61
|
<!-- Recent Systems -->
|
|
62
62
|
<div class="mb-8">
|
|
63
|
-
<
|
|
63
|
+
<div class="flex items-center justify-between mb-4">
|
|
64
|
+
<h2 class="text-xl font-semibold text-navy">Recent Systems</h2>
|
|
65
|
+
<a href="{% url 'agent_studio:system_list' %}" class="text-sm text-cyan hover:text-cyan-dark font-medium">View all →</a>
|
|
66
|
+
</div>
|
|
64
67
|
{% if recent_systems %}
|
|
65
68
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
66
69
|
{% for system in recent_systems %}
|
|
67
70
|
<a href="{% url 'agent_studio:system_test' system.id %}"
|
|
68
|
-
class="bg-white border border-
|
|
69
|
-
<div class="flex items-center space-x-3 mb-
|
|
70
|
-
<
|
|
71
|
-
|
|
71
|
+
class="bg-white border border-slate-200 rounded-xl p-5 hover:border-cyan hover:shadow-md transition-all group">
|
|
72
|
+
<div class="flex items-center space-x-3 mb-3">
|
|
73
|
+
<div class="w-10 h-10 bg-navy/10 rounded-lg flex items-center justify-center group-hover:bg-cyan/20 transition-colors">
|
|
74
|
+
<span class="text-xl">🔗</span>
|
|
75
|
+
</div>
|
|
76
|
+
<span class="font-semibold text-navy">{{ system.name }}</span>
|
|
72
77
|
</div>
|
|
73
|
-
<p class="text-sm text-
|
|
74
|
-
<div class="
|
|
75
|
-
<span
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
<p class="text-sm text-slate-500 line-clamp-2 mb-3">{{ system.description|default:"No description" }}</p>
|
|
79
|
+
<div class="flex items-center justify-between text-xs text-slate-400">
|
|
80
|
+
<span class="flex items-center gap-1">
|
|
81
|
+
<span>{{ system.entry_agent.icon|default:"🤖" }}</span>
|
|
82
|
+
<span>{{ system.entry_agent.name }}</span>
|
|
83
|
+
</span>
|
|
84
|
+
<span>{{ system.updated_at|timesince }} ago</span>
|
|
79
85
|
</div>
|
|
80
86
|
</a>
|
|
81
87
|
{% endfor %}
|
|
82
88
|
</div>
|
|
83
89
|
{% else %}
|
|
84
|
-
<div class="bg-
|
|
85
|
-
<
|
|
90
|
+
<div class="bg-white border border-slate-200 border-dashed rounded-xl p-8 text-center">
|
|
91
|
+
<div class="w-12 h-12 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-3">
|
|
92
|
+
<span class="text-2xl">🔗</span>
|
|
93
|
+
</div>
|
|
94
|
+
<p class="text-slate-500 text-sm mb-3">No systems yet. Systems combine multiple agents to work together.</p>
|
|
95
|
+
<a href="{% url 'agent_studio:system_create' %}" class="inline-flex items-center gap-2 text-sm font-medium text-cyan hover:text-cyan-dark">
|
|
96
|
+
Create your first system →
|
|
97
|
+
</a>
|
|
86
98
|
</div>
|
|
87
99
|
{% endif %}
|
|
88
100
|
</div>
|
|
@@ -90,17 +102,22 @@
|
|
|
90
102
|
<!-- Recent Agents -->
|
|
91
103
|
{% if recent_agents %}
|
|
92
104
|
<div class="mb-8">
|
|
93
|
-
<
|
|
105
|
+
<div class="flex items-center justify-between mb-4">
|
|
106
|
+
<h2 class="text-xl font-semibold text-navy">Recent Agents</h2>
|
|
107
|
+
<a href="{% url 'agent_studio:agent_list' %}" class="text-sm text-cyan hover:text-cyan-dark font-medium">View all →</a>
|
|
108
|
+
</div>
|
|
94
109
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
95
110
|
{% for agent in recent_agents %}
|
|
96
111
|
<a href="{% url 'agent_studio:agent_edit' agent.id %}"
|
|
97
|
-
class="bg-white border border-
|
|
98
|
-
<div class="flex items-center space-x-3 mb-
|
|
99
|
-
<
|
|
100
|
-
|
|
112
|
+
class="bg-white border border-slate-200 rounded-xl p-5 hover:border-cyan hover:shadow-md transition-all group">
|
|
113
|
+
<div class="flex items-center space-x-3 mb-3">
|
|
114
|
+
<div class="w-10 h-10 bg-cyan/10 rounded-lg flex items-center justify-center group-hover:bg-cyan/20 transition-colors">
|
|
115
|
+
<span class="text-xl">{{ agent.icon|default:"🤖" }}</span>
|
|
116
|
+
</div>
|
|
117
|
+
<span class="font-semibold text-navy">{{ agent.name }}</span>
|
|
101
118
|
</div>
|
|
102
|
-
<p class="text-sm text-
|
|
103
|
-
<div class="
|
|
119
|
+
<p class="text-sm text-slate-500 line-clamp-2 mb-3">{{ agent.description|default:"No description" }}</p>
|
|
120
|
+
<div class="text-xs text-slate-400">
|
|
104
121
|
Updated {{ agent.updated_at|timesince }} ago
|
|
105
122
|
</div>
|
|
106
123
|
</a>
|
|
@@ -112,15 +129,17 @@
|
|
|
112
129
|
<!-- Template Agents -->
|
|
113
130
|
{% if template_agents %}
|
|
114
131
|
<div>
|
|
115
|
-
<h2 class="text-xl font-semibold text-
|
|
132
|
+
<h2 class="text-xl font-semibold text-navy mb-4">Popular Templates</h2>
|
|
116
133
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
117
134
|
{% for agent in template_agents %}
|
|
118
|
-
<div class="bg-white border border-
|
|
119
|
-
<div class="flex items-center space-x-3 mb-
|
|
120
|
-
<
|
|
121
|
-
|
|
135
|
+
<div class="bg-white border border-slate-200 rounded-xl p-5 hover:border-cyan hover:shadow-md transition-all cursor-pointer group">
|
|
136
|
+
<div class="flex items-center space-x-3 mb-3">
|
|
137
|
+
<div class="w-10 h-10 bg-slate-100 rounded-lg flex items-center justify-center group-hover:bg-cyan/10 transition-colors">
|
|
138
|
+
<span class="text-xl">{{ agent.icon|default:"📄" }}</span>
|
|
139
|
+
</div>
|
|
140
|
+
<span class="font-semibold text-navy">{{ agent.name }}</span>
|
|
122
141
|
</div>
|
|
123
|
-
<p class="text-sm text-
|
|
142
|
+
<p class="text-sm text-slate-500 line-clamp-2">{{ agent.description|default:"No description" }}</p>
|
|
124
143
|
</div>
|
|
125
144
|
{% endfor %}
|
|
126
145
|
</div>
|
|
@@ -141,4 +160,3 @@ createApp({
|
|
|
141
160
|
}).use(primevue.config.default).mount('#app');
|
|
142
161
|
</script>
|
|
143
162
|
{% endblock %}
|
|
144
|
-
|