mindroot 9.3.0__py3-none-any.whl → 9.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. mindroot/coreplugins/admin/__init__.py +3 -1
  2. mindroot/coreplugins/admin/agent_router.py +250 -7
  3. mindroot/coreplugins/admin/asset_manager.py +164 -0
  4. mindroot/coreplugins/admin/command_router.py +236 -1
  5. mindroot/coreplugins/admin/mcp_catalog_routes.py +156 -0
  6. mindroot/coreplugins/admin/mcp_publish_routes.py +450 -0
  7. mindroot/coreplugins/admin/mcp_registry_routes.py +495 -0
  8. mindroot/coreplugins/admin/mcp_routes.py +216 -0
  9. mindroot/coreplugins/admin/mod.py +62 -0
  10. mindroot/coreplugins/admin/oauth_callback_router.py +84 -0
  11. mindroot/coreplugins/admin/persona_handler.py +15 -6
  12. mindroot/coreplugins/admin/persona_router.py +158 -2
  13. mindroot/coreplugins/admin/plugin_manager.py +63 -0
  14. mindroot/coreplugins/admin/plugin_router_fixed.py +23 -0
  15. mindroot/coreplugins/admin/plugin_router_new_not_working.py +145 -0
  16. mindroot/coreplugins/admin/plugin_routes.py +114 -0
  17. mindroot/coreplugins/admin/registry_settings_routes.py +140 -0
  18. mindroot/coreplugins/admin/router.py +116 -15
  19. mindroot/coreplugins/admin/service_models.py +1 -1
  20. mindroot/coreplugins/admin/settings_router.py +1 -0
  21. mindroot/coreplugins/admin/static/css/admin-custom.css +357 -2
  22. mindroot/coreplugins/admin/static/css/dark.css +1 -0
  23. mindroot/coreplugins/admin/static/css/default.css +4 -0
  24. mindroot/coreplugins/admin/static/js/about-info.js +367 -0
  25. mindroot/coreplugins/admin/static/js/agent-form.js +83 -3
  26. mindroot/coreplugins/admin/static/js/api-key-script.js +307 -0
  27. mindroot/coreplugins/admin/static/js/mcp-manager.js +348 -0
  28. mindroot/coreplugins/admin/static/js/mcp-publisher.js +780 -0
  29. mindroot/coreplugins/admin/static/js/persona-editor.js +34 -5
  30. mindroot/coreplugins/admin/static/js/plugin-toggle.js +1 -1
  31. mindroot/coreplugins/admin/static/js/recommended-plugin-install.js +63 -0
  32. mindroot/coreplugins/admin/static/js/registry-auth-section.js +132 -0
  33. mindroot/coreplugins/admin/static/js/registry-manager-base.js +613 -0
  34. mindroot/coreplugins/admin/static/js/registry-manager-old.js +385 -0
  35. mindroot/coreplugins/admin/static/js/registry-manager-publish-old-delete.js +166 -0
  36. mindroot/coreplugins/admin/static/js/registry-manager.js +351 -0
  37. mindroot/coreplugins/admin/static/js/registry-publish-section.js +377 -0
  38. mindroot/coreplugins/admin/static/js/registry-search-section.js +400 -0
  39. mindroot/coreplugins/admin/static/js/registry-search-section.js.bak +3 -0
  40. mindroot/coreplugins/admin/static/js/registry-settings.js +69 -0
  41. mindroot/coreplugins/admin/static/js/registry-shared-services.js +857 -0
  42. mindroot/coreplugins/admin/static/js/registry-simple-sections.js +85 -0
  43. mindroot/coreplugins/admin/static/js/secure-widget-manager.js +438 -0
  44. mindroot/coreplugins/admin/static/logo.png +0 -0
  45. mindroot/coreplugins/admin/templates/admin.jinja2 +275 -110
  46. mindroot/coreplugins/agent/Assistant/agent.json +27 -11
  47. mindroot/coreplugins/agent/agent.py +2 -2
  48. mindroot/coreplugins/agent/command_parser.py +25 -10
  49. mindroot/coreplugins/agent/templates/system.jinja2 +0 -12
  50. mindroot/coreplugins/chat/__init__.py +4 -1
  51. mindroot/coreplugins/chat/router.py +132 -20
  52. mindroot/coreplugins/chat/router_dedup_patch.py +20 -0
  53. mindroot/coreplugins/chat/services.py +31 -1
  54. mindroot/coreplugins/chat/static/css/action-fix.css +32 -0
  55. mindroot/coreplugins/chat/static/css/admin-custom.css +5 -3
  56. mindroot/coreplugins/chat/static/css/dark.css +24 -3
  57. mindroot/coreplugins/chat/static/css/default.css +24 -3
  58. mindroot/coreplugins/chat/static/css/main.css +1 -0
  59. mindroot/coreplugins/chat/static/js/action.js +137 -60
  60. mindroot/coreplugins/chat/static/js/chat-history.js +3 -0
  61. mindroot/coreplugins/chat/static/js/chat.js +59 -16
  62. mindroot/coreplugins/chat/static/js/chat.js.diff +221 -0
  63. mindroot/coreplugins/chat/static/js/chatform.js +2 -2
  64. mindroot/coreplugins/chat/static/site.webmanifest +1 -1
  65. mindroot/coreplugins/chat/templates/chat.jinja2 +3 -3
  66. mindroot/coreplugins/chat/widget_manager.py +139 -0
  67. mindroot/coreplugins/chat/widget_routes.py +287 -0
  68. mindroot/coreplugins/check_list/inject/admin.jinja2 +1 -1
  69. mindroot/coreplugins/email/__init__.py +2 -0
  70. mindroot/coreplugins/email/email_provider.py +2 -2
  71. mindroot/coreplugins/email/mod.py +100 -0
  72. mindroot/coreplugins/email/services.py +5 -3
  73. mindroot/coreplugins/email/smtp_handler.py +9 -3
  74. mindroot/coreplugins/email/test_email_service.py +75 -0
  75. mindroot/coreplugins/env_manager/mod.py +61 -25
  76. mindroot/coreplugins/home/router.py +37 -2
  77. mindroot/coreplugins/home/static/imgs/logo.png +0 -0
  78. mindroot/coreplugins/home/static/imgs/logo.png.bak +0 -0
  79. mindroot/coreplugins/home/static/imgs/logo_teal.png +0 -0
  80. mindroot/coreplugins/home/static/imgs/logo_teal2.png +0 -0
  81. mindroot/coreplugins/home/static/imgs/logo_teal_detailed.png +0 -0
  82. mindroot/coreplugins/home/static/imgs/logo_teal_python.png +0 -0
  83. mindroot/coreplugins/home/templates/home.jinja2 +15 -6
  84. mindroot/coreplugins/index/indices/default/index.json +6 -6
  85. mindroot/coreplugins/jwt_auth/middleware.py +47 -2
  86. mindroot/coreplugins/jwt_auth/mod.py +40 -17
  87. mindroot/coreplugins/l8n/__init__.py +6 -0
  88. mindroot/coreplugins/l8n/debug_loader.py +85 -0
  89. mindroot/coreplugins/l8n/debug_middleware.py +74 -0
  90. mindroot/coreplugins/l8n/l8n_constants.py +19 -0
  91. mindroot/coreplugins/l8n/language_detection.py +183 -0
  92. mindroot/coreplugins/l8n/middleware.py +151 -0
  93. mindroot/coreplugins/l8n/mod.py +277 -0
  94. mindroot/coreplugins/l8n/monkey_patch_to_delete.py +186 -0
  95. mindroot/coreplugins/l8n/test_enhanced.py +298 -0
  96. mindroot/coreplugins/l8n/test_l8n.py +95 -0
  97. mindroot/coreplugins/l8n/test_l8n_standalone.py +251 -0
  98. mindroot/coreplugins/l8n/test_middleware.py +272 -0
  99. mindroot/coreplugins/l8n/utils.py +232 -0
  100. mindroot/coreplugins/mcp_/__init__.py +14 -0
  101. mindroot/coreplugins/mcp_/catalog_commands.py +328 -0
  102. mindroot/coreplugins/mcp_/catalog_manager.py +263 -0
  103. mindroot/coreplugins/mcp_/dynamic_commands.py +154 -0
  104. mindroot/coreplugins/mcp_/mcp_manager.py +1031 -0
  105. mindroot/coreplugins/mcp_/mod.py +367 -0
  106. mindroot/coreplugins/mcp_/oauth_storage.py +144 -0
  107. mindroot/coreplugins/mcp_/server_installer.py +79 -0
  108. mindroot/coreplugins/mcp_/setup.py +26 -0
  109. mindroot/coreplugins/mcp_/test_dynamic_commands.py +134 -0
  110. mindroot/coreplugins/mcp_/testmcpclient.py +92 -0
  111. mindroot/coreplugins/persona/mod.py +12 -7
  112. mindroot/coreplugins/signup/templates/signup.jinja2 +1 -1
  113. mindroot/coreplugins/subscriptions/__init__.py +1 -0
  114. mindroot/coreplugins/subscriptions/mod.py +14 -3
  115. mindroot/coreplugins/subscriptions/router.py +3 -0
  116. mindroot/coreplugins/user_service/__init__.py +1 -2
  117. mindroot/coreplugins/user_service/admin_init.py +1 -0
  118. mindroot/coreplugins/user_service/email_service.py +72 -17
  119. mindroot/coreplugins/user_service/mod.py +10 -2
  120. mindroot/coreplugins/user_service/router.py +2 -0
  121. mindroot/lib/auth/api_key.py +28 -0
  122. mindroot/lib/cli/plugins.py +94 -0
  123. mindroot/lib/plugins/default_plugin_manifest.json +20 -0
  124. mindroot/lib/plugins/installation.py +5 -5
  125. mindroot/lib/plugins/l8n_static_handler.py +225 -0
  126. mindroot/lib/plugins/loader.py +33 -3
  127. mindroot/lib/plugins/loader_with_l8n.py +281 -0
  128. mindroot/lib/plugins/manifest.py +236 -24
  129. mindroot/lib/providers/commands.py +3 -1
  130. mindroot/lib/route_decorators.py +5 -5
  131. mindroot/lib/templates.py +183 -11
  132. mindroot/lib/utils/merge_arrays.py +1 -1
  133. mindroot/migrate.py +39 -20
  134. mindroot/registry/data_access.py +1 -1
  135. mindroot/server.py +42 -13
  136. mindroot/server_missing_normal_args.py +197 -0
  137. mindroot/server_prev.py +173 -0
  138. {mindroot-9.3.0.dist-info → mindroot-9.5.0.dist-info}/METADATA +7 -2
  139. {mindroot-9.3.0.dist-info → mindroot-9.5.0.dist-info}/RECORD +144 -112
  140. mindroot/coreplugins/admin/static/favicon/about.txt +0 -6
  141. mindroot/coreplugins/admin/static/favicon/android-chrome-512x512.png +0 -0
  142. mindroot/coreplugins/admin/static/favicon/apple-touch-icon.png +0 -0
  143. mindroot/coreplugins/admin/static/favicon/favicon-16x16.png +0 -0
  144. mindroot/coreplugins/admin/static/favicon/favicon-32x32.png +0 -0
  145. mindroot/coreplugins/admin/static/favicon/favicon.ico +0 -0
  146. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/about.txt +0 -6
  147. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
  148. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
  149. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
  150. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
  151. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
  152. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon.ico +0 -0
  153. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/site.webmanifest +0 -1
  154. mindroot/coreplugins/admin/static/favicon/logo.png +0 -0
  155. mindroot/coreplugins/admin/static/favicon/site.webmanifest +0 -1
  156. mindroot/coreplugins/admin/static/js/backup/agent-editor.js +0 -186
  157. mindroot/coreplugins/admin/static/js/backup/agent-form.js +0 -1133
  158. mindroot/coreplugins/admin/static/js/backup/agent-list.js +0 -94
  159. mindroot/coreplugins/chat/static/favicon/about.txt +0 -6
  160. mindroot/coreplugins/chat/static/favicon/android-chrome-192x192.png +0 -0
  161. mindroot/coreplugins/chat/static/favicon/android-chrome-512x512.png +0 -0
  162. mindroot/coreplugins/chat/static/favicon/apple-touch-icon.png +0 -0
  163. mindroot/coreplugins/chat/static/favicon/favicon-16x16.png +0 -0
  164. mindroot/coreplugins/chat/static/favicon/favicon-32x32.png +0 -0
  165. mindroot/coreplugins/chat/static/favicon/favicon.ico +0 -0
  166. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/about.txt +0 -6
  167. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
  168. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
  169. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
  170. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
  171. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
  172. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon.ico +0 -0
  173. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/site.webmanifest +0 -1
  174. mindroot/coreplugins/chat/static/favicon/logo.png +0 -0
  175. mindroot/coreplugins/chat/static/favicon/site.webmanifest +0 -1
  176. mindroot/coreplugins/index/default.json +0 -76
  177. mindroot/coreplugins/user_service/file_trigger_service.py +0 -12
  178. mindroot/coreplugins/user_service/hooks.py +0 -23
  179. /mindroot/coreplugins/{admin/static/favicon/android-chrome-192x192.png → home/static/imgs/backuplogo.png} +0 -0
  180. {mindroot-9.3.0.dist-info → mindroot-9.5.0.dist-info}/WHEEL +0 -0
  181. {mindroot-9.3.0.dist-info → mindroot-9.5.0.dist-info}/entry_points.txt +0 -0
  182. {mindroot-9.3.0.dist-info → mindroot-9.5.0.dist-info}/licenses/LICENSE +0 -0
  183. {mindroot-9.3.0.dist-info → mindroot-9.5.0.dist-info}/top_level.txt +0 -0
@@ -1,1133 +0,0 @@
1
- import { LitElement, html, css } from './lit-core.min.js';
2
- import { BaseEl } from './base.js';
3
- import './toggle-switch.js';
4
- import { unsafeHTML } from '../../../chat/static/js/lit-html/directives/unsafe-html.js';
5
- import './missing-commands.js';
6
- import {markdownRenderer} from './markdown-renderer.js';
7
- import showNotification from './notification.js';
8
- import './indexed-agents.js';
9
-
10
- class AgentForm extends BaseEl {
11
- static properties = {
12
- agent: { type: Object },
13
- newAgent: { type: Boolean },
14
- loading: { type: Boolean },
15
- personas: { type: Array },
16
- commands: { type: Object },
17
- serviceModels: { type: Object },
18
- missingCommands: { type: Object },
19
- pendingPlugins: { type: Array },
20
- showInstructionsEditor: { type: Boolean },
21
- showTechnicalInstructionsEditor: { type: Boolean },
22
- indexedAgentsVisible: { type: Boolean }
23
- };
24
-
25
- static styles = css`
26
- :host {
27
- display: block;
28
- margin-top: 20px;
29
- }
30
-
31
- .agent-form {
32
- padding: 15px;
33
- border: 1px solid rgba(255, 255, 255, 0.1);
34
- border-radius: 8px;
35
- background: rgba(255, 255, 255, 0.02);
36
- }
37
-
38
- .form-group {
39
- margin-bottom: 15px;
40
- }
41
-
42
- .form-group label {
43
- display: block;
44
- margin-bottom: 5px;
45
- color: #f0f0f0;
46
- }
47
-
48
- .required::after {
49
- content: " *";
50
- color: #e57373;
51
- }
52
-
53
- summary::before {
54
- content: "\u25b6";
55
- display: inline-block;
56
- margin-right: 5px;
57
- transition: transform 0.2s;
58
- }
59
-
60
- details[open] > summary::before { transform: rotate(90deg); }
61
-
62
- details > * :not(summary) {
63
- user-select: none;
64
- }
65
-
66
- .form-group-header {
67
- display: flex;
68
- align-items: center;
69
- justify-content: space-between;
70
- margin-bottom: 5px;
71
- }
72
-
73
- .form-group-actions {
74
- display: flex;
75
- gap: 8px;
76
- }
77
-
78
- .markdown-preview {
79
- background: rgba(255, 255, 255, 0.05);
80
- border: 1px solid rgba(255, 255, 255, 0.1);
81
- border-radius: 6px;
82
- padding: 12px;
83
- min-height: 100px;
84
- color: #f0f0f0;
85
- margin-bottom: 10px;
86
- max-height: 400px;
87
- overflow-y: auto;
88
- overflow-x: hidden;
89
- }
90
-
91
- .markdown-preview ul {
92
- padding-left: 20px;
93
- }
94
-
95
- .markdown-preview li {
96
- margin-bottom: 5px;
97
- }
98
-
99
- .markdown-preview ul {
100
- list-style-type: none;
101
- padding-left: 0;
102
- }
103
-
104
- .markdown-preview input[type="checkbox"] {
105
- margin-right: 8px;
106
- }
107
-
108
- .markdown-preview h1, .markdown-preview h2, .markdown-preview h3,
109
- .markdown-preview h4, .markdown-preview h5, .markdown-preview h6 {
110
- background: transparent;
111
- border: none;
112
- padding: 0;
113
- margin-top: 1em;
114
- margin-bottom: 0.5em;
115
- font-weight: bold;
116
- }
117
-
118
- /* Edit button for full-width display */
119
- .edit-button {
120
- background: transparent;
121
- border: 1px solid rgba(255, 255, 255, 0.2);
122
- color: #f0f0f0;
123
- border-radius: 4px;
124
- padding: 4px 8px;
125
- cursor: pointer;
126
- display: flex;
127
- align-items: center;
128
- gap: 5px;
129
- margin-bottom: 10px;
130
- }
131
-
132
- /* Icon button for header */
133
- .icon-button {
134
- background: transparent;
135
- border: 1px solid rgba(255, 255, 255, 0.2);
136
- color: #f0f0f0;
137
- border-radius: 4px;
138
- padding: 4px;
139
- cursor: pointer;
140
- display: flex;
141
- align-items: center;
142
- justify-content: center;
143
- width: 30px;
144
- height: 30px;
145
- }
146
-
147
- .edit-button:hover {
148
- background: rgba(255, 255, 255, 0.1);
149
- }
150
-
151
- .icon-button:hover {
152
- background: rgba(255, 255, 255, 0.1);
153
- }
154
-
155
- input[type="text"],
156
- select,
157
- textarea {
158
- width: 100%;
159
- padding: 8px 12px;
160
- background: rgba(255, 255, 255, 0.05);
161
- border: 1px solid rgba(255, 255, 255, 0.1);
162
- border-radius: 6px;
163
- color: #f0f0f0;
164
- font-size: 0.95rem;
165
- }
166
-
167
- textarea {
168
- min-height: 60vh;
169
- max-height: 60vh;
170
- font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
171
- }
172
-
173
- textarea::-webkit-scrollbar {
174
- width: 8px; /* Medium-thin width */
175
- }
176
-
177
- textarea::-webkit-scrollbar-track {
178
- background: #222; /* Dark background */
179
- }
180
-
181
- textarea::-webkit-scrollbar-thumb {
182
- background: #666; /* Medium gray scrollbar handle */
183
- border-radius: 4px;
184
- }
185
-
186
- textarea::-webkit-scrollbar-thumb:hover {
187
- background: #999; /* Lighter on hover */
188
- }
189
-
190
- textarea {
191
- scrollbar-width: thin;
192
- scrollbar-color: #666 #222;
193
- }
194
-
195
- input[type="text"]:focus,
196
- select:focus,
197
- textarea:focus {
198
- outline: none;
199
- border-color: rgba(255, 255, 255, 0.2);
200
- background: rgba(255, 255, 255, 0.08);
201
- }
202
-
203
- .commands-section {
204
- margin-top: 20px;
205
- }
206
-
207
- .commands-category {
208
- margin-bottom: 20px;
209
- background: rgba(255, 255, 255, 0.02);
210
- border-radius: 8px;
211
- padding: 15px;
212
- }
213
-
214
- .commands-category h4 {
215
- margin-bottom: 15px;
216
- color: #f0f0f0;
217
- font-size: 1.1rem;
218
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
219
- padding-bottom: 8px;
220
- }
221
-
222
- .commands-grid {
223
- display: grid;
224
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
225
- gap: 12px;
226
- }
227
-
228
- .command-item {
229
- display: flex;
230
- align-items: center;
231
- justify-content: space-between;
232
- padding: 8px 12px;
233
- background: rgba(255, 255, 255, 0.05);
234
- border: 1px solid rgba(255, 255, 255, 0.1);
235
- border-radius: 6px;
236
- cursor: pointer;
237
- transition: all 0.2s;
238
- }
239
-
240
- .command-item:hover {
241
- background: rgba(255, 255, 255, 0.08);
242
- border-color: rgba(255, 255, 255, 0.2);
243
- }
244
-
245
- .command-info {
246
- flex: 1;
247
- margin-right: 12px;
248
- position: relative;
249
- }
250
-
251
- .command-name {
252
- color: #f0f0f0;
253
- font-weight: 500;
254
- }
255
-
256
- .tooltip-text {
257
- visibility: hidden;
258
- position: absolute;
259
- z-index: 1;
260
- left: 0;
261
- top: 100%;
262
- margin-top: 10px;
263
- width: 250px;
264
- background-color: rgba(0, 0, 0, 0.9);
265
- color: #fff;
266
- text-align: left;
267
- padding: 8px 12px;
268
- border-radius: 6px;
269
- font-size: 0.9em;
270
- line-height: 1.4;
271
- white-space: normal;
272
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
273
- }
274
-
275
- .command-info:hover .tooltip-text {
276
- visibility: visible;
277
- }
278
-
279
- .btn {
280
- padding: 8px 16px;
281
- background: #2196F3;
282
- border: none;
283
- border-radius: 4px;
284
- color: white;
285
- cursor: pointer;
286
- font-size: 0.95rem;
287
- transition: all 0.2s;
288
- }
289
-
290
- .btn:hover {
291
- background: #1976D2;
292
- }
293
-
294
- .btn:disabled {
295
- opacity: 0.5;
296
- cursor: not-allowed;
297
- }
298
- `;
299
-
300
- constructor() {
301
- super();
302
- this.attachShadow({mode: 'open'});
303
- this.personas = [];
304
- this.commands = {};
305
- this.showInstructionsEditor = false;
306
- this.loading = false;
307
- this.plugins = [];
308
- this.providerMapping = {}; // Map display names to module names
309
- this.agent = {
310
- commands: [],
311
- name: '',
312
- hashver: '',
313
- preferred_providers: [],
314
- thinking_level: 'off', // Default to medium
315
- persona: '',
316
- recommended_plugins: []
317
- };
318
- this.showTechnicalInstructionsEditor = false;
319
- this.newAgent = false;
320
- this.pendingPlugins = [];
321
- this.fetchPersonas();
322
- this.resetEditors();
323
- this.fetchCommands();
324
- this.fetchServiceModels();
325
- this.fetchPlugins();
326
- }
327
-
328
- async fetchMissingCommands() {
329
- if (!this.agent.name) return;
330
-
331
- // Skip API call for new agents that haven't been saved yet
332
- if (this.newAgent) {
333
- this.missingCommands = {};
334
- return;
335
- }
336
-
337
- try {
338
- const response = await fetch(`/admin/missing-commands/${this.agent.name}`);
339
- if (!response.ok) throw new Error('Failed to fetch missing commands');
340
- this.missingCommands = await response.json();
341
- console.log('Fetched missing commands:', this.missingCommands);
342
- this.requestUpdate();
343
- } catch (error) {
344
- this.missingCommands = {};
345
- console.log(`Error fetching missing commands: ${error.message}`);
346
- }
347
- }
348
-
349
- updated(changedProperties) {
350
- // Handle newAgent property changes
351
- if (changedProperties.has('newAgent')) {
352
- console.log('newAgent changed to:', this.newAgent);
353
- if (this.newAgent) {
354
- // Initialize empty agent with defaults for new agent
355
- this.agent = {
356
- ...this.agent,
357
- commands: this.agent.commands || [],
358
- preferred_providers: this.agent.preferred_providers || [],
359
- recommended_plugins: this.agent.recommended_plugins || []
360
- };
361
- }
362
- }
363
-
364
- console.log('Updated with changes:', changedProperties);
365
- super.updated(changedProperties);
366
- if (changedProperties.has('agent')) {
367
- console.log('Agent updated:', this.agent);
368
- // Force select element to update
369
- const select = this.shadowRoot.querySelector('select[name="persona"]');
370
- if (select && this.agent.persona) {
371
- select.value = this.agent.persona;
372
- }
373
-
374
- if (this.agent.name) {
375
- this.fetchMissingCommands();
376
- this.checkRecommendedPlugins();
377
- }
378
- }
379
- }
380
-
381
- resetEditors() {
382
- this.showInstructionsEditor = false;
383
- this.showTechnicalInstructionsEditor = false;
384
- }
385
-
386
- async fetchServiceModels() {
387
- try {
388
- const response = await fetch('/service-models');
389
- if (!response.ok) throw new Error('Failed to fetch service models');
390
- const data = await response.json();
391
- this.serviceModels = data;
392
- console.log('Fetched service models:', this.serviceModels);
393
- // now re-render everything (force)
394
- this.requestUpdate();
395
- } catch (error) {
396
- showNotification('error', `Error loading service models: ${error.message}`);
397
- }
398
- }
399
-
400
- // Fetch available personas
401
- async fetchPersonas() {
402
- try {
403
- const response = await fetch('/personas/local');
404
- if (!response.ok) throw new Error('Failed to fetch personas');
405
- this.personas = await response.json();
406
- console.log('Fetched personas:', this.personas);
407
- console.log('Current agent persona:', this.agent.persona);
408
- } catch (error) {
409
- showNotification('error', `Error loading personas: ${error.message}`);
410
- }
411
- }
412
-
413
- async fetchPlugins() {
414
- try {
415
- const response = await fetch('/plugin-manager/get-all-plugins');
416
- if (!response.ok) throw new Error('Failed to fetch plugins');
417
- const result = await response.json();
418
- this.plugins = result.data.filter(plugin => plugin.enabled);
419
- console.log('Fetched plugins:', this.plugins);
420
-
421
- // Add category (module name) for each plugin if available
422
- for (const plugin of this.plugins) {
423
- let name = plugin.name;
424
- if (plugin.source_path) {
425
- plugin.source = plugin.source_path
426
- name = plugin.source_path.split('/').filter(Boolean).pop();
427
- }
428
- if (plugin.github_url) {
429
- plugin.source = plugin.github_url
430
- }
431
- const uniqueId = name.replace(/[^a-zA-Z0-9]/g, '_');
432
- name = uniqueId;
433
- plugin.name = name
434
- plugin._uniqueId = uniqueId;
435
- plugin._id = uniqueId
436
-
437
- }
438
-
439
- } catch (error) {
440
- showNotification('error', `Error loading plugins: ${error.message}`);
441
- }
442
- }
443
-
444
- renderMarkdown(text) {
445
- return markdownRenderer.parse(text);
446
- }
447
-
448
-
449
- async checkRecommendedPlugins() {
450
- if (!this.agent.name || !this.agent.recommended_plugins || this.agent.recommended_plugins.length === 0) {
451
- this.pendingPlugins = [];
452
- return;
453
- }
454
-
455
- // Skip API call for new agents that haven't been saved yet
456
- if (this.newAgent) {
457
- this.pendingPlugins = [];
458
- return;
459
- }
460
-
461
- try {
462
- // Check which recommended plugins are not installed
463
- const response = await fetch(`/admin/check-recommended-plugins/${this.agent.name}`);
464
- if (!response.ok) throw new Error('Failed to check recommended plugins');
465
- const result = await response.json();
466
-
467
- if (result.pending_plugins) {
468
- this.pendingPlugins = result.pending_plugins;
469
- } else {
470
- this.pendingPlugins = [];
471
- }
472
-
473
- console.log('Pending plugins:', this.pendingPlugins);
474
- this.requestUpdate();
475
- } catch (error) {
476
- console.log(`Error checking recommended plugins: ${error.message}`);
477
- this.pendingPlugins = [];
478
- }
479
- }
480
-
481
- async installRecommendedPlugins() {
482
- const response = await fetch(`/admin/install-recommended-plugins/${this.agent.name}`, {
483
- method: 'POST'
484
- });
485
- const result = await response.json();
486
- showNotification('success', 'Recommended plugins installed. Please refresh the page to see the changes.');
487
- this.checkRecommendedPlugins();
488
- }
489
-
490
- async fetchCommands() {
491
- try {
492
- const response = await fetch('/commands');
493
- if (!response.ok) throw new Error('Failed to fetch commands');
494
- const data = await response.json();
495
- this.commands = this.organizeCommands(data);
496
- } catch (error) {
497
- showNotification('error', `Error loading commands: ${error.message}`);
498
- }
499
- }
500
-
501
- organizeCommands(commands) {
502
- const grouped = {};
503
- for (const [cmdName, cmdInfoArray] of Object.entries(commands)) {
504
- const cmdInfo = cmdInfoArray[0];
505
- const provider = cmdInfo.provider || 'Other';
506
- if (!grouped[provider]) {
507
- grouped[provider] = [];
508
- this.plugins.push(provider)
509
- }
510
- grouped[provider].push({
511
- name: cmdName,
512
- provider,
513
- providerName: provider,
514
- docstring: cmdInfo.docstring,
515
- flags: cmdInfo.flags,
516
- uniqueId: `${cmdName}_${provider}`.replace(/[^a-zA-Z0-9]/g, '_')
517
- });
518
-
519
- this.providerMapping[provider] = provider;
520
- }
521
- return grouped;
522
- }
523
-
524
- handleInputChange(event) {
525
- const { name, value, type, checked } = event.target;
526
- console.log({name, value, type})
527
- if (name === 'commands') {
528
- if (!Array.isArray(this.agent.commands)) {
529
- this.agent.commands = [];
530
- }
531
- if (checked) {
532
- this.agent.commands.push(value);
533
- } else {
534
- this.agent.commands = this.agent.commands.filter(command => command !== value);
535
- }
536
-
537
- // Update the entire agent object WITHOUT overwriting commands
538
- this.agent = { ...this.agent };
539
- return;
540
- }
541
-
542
- // Handle required_plugins similar to commands
543
- if (name === 'recommended_plugins') {
544
- if (!this.agent.recommended_plugins || !Array.isArray(this.agent.recommended_plugins)) {
545
- this.agent.recommended_plugins = [];
546
- }
547
- if (checked) {
548
- this.agent.recommended_plugins.push(value);
549
- } else {
550
- this.agent.recommended_plugins = this.agent.recommended_plugins.filter(plugin => plugin !== value);
551
- }
552
-
553
- this.agent = { ...this.agent };
554
- return;
555
- }
556
- console.log('before',this.agent)
557
- // Handle all other inputs
558
- const inputValue = type === 'checkbox' ? checked : value;
559
- this.agent = { ...this.agent, [name]: inputValue };
560
- console.log('after', this.agent)
561
- }
562
-
563
- handlePreferredProviderChange(e) {
564
- const { value, checked, id } = e.detail || e.target;
565
- console.log(`Preferred provider change: ID=${id || 'unknown'} Value=${value}, Checked=${checked}`);
566
-
567
- // Ensure preferred_providers is always an array
568
- if (!Array.isArray(this.agent.preferred_providers)) {
569
- this.agent.preferred_providers = [];
570
- }
571
-
572
- let preferred_providers = [...this.agent.preferred_providers];
573
-
574
- if (checked) {
575
- if (!preferred_providers.includes(id)) {
576
- preferred_providers.push(id);
577
- console.log(`Added ${id} to preferred_providers: ${preferred_providers.join(', ')}`);
578
- }
579
- } else {
580
- const index = preferred_providers.indexOf(id);
581
- if (index !== -1) preferred_providers.splice(index, 1);
582
- console.log(`Removed ${id} from preferred_providers: ${preferred_providers.join(', ')}`);
583
- }
584
-
585
- this.agent = { ...this.agent, preferred_providers };
586
- }
587
-
588
- validateForm() {
589
- // Get current form values to ensure we're validating the latest state
590
- const nameInput = this.shadowRoot.querySelector('input[name="name"]');
591
- const personaSelect = this.shadowRoot.querySelector('select[name="persona"]');
592
- const instructionsTextarea = this.shadowRoot.querySelector('textarea[name="instructions"]');
593
-
594
- const currentName = nameInput?.value || this.agent.name;
595
- const currentPersona = personaSelect?.value || this.agent.persona;
596
- const currentInstructions = instructionsTextarea?.value || this.agent.instructions;
597
-
598
- if (!currentName?.trim()) {
599
- showNotification('error', 'Name is required');
600
- return false;
601
- }
602
- if (!currentPersona?.trim()) {
603
- showNotification('error', 'Persona is required');
604
- return false;
605
- }
606
- if (!currentInstructions?.trim()) {
607
- showNotification('error', 'Instructions are required');
608
- return false;
609
- }
610
- return true;
611
- }
612
-
613
- async handleSubmit(event) { // Complete replacement of method
614
- event?.preventDefault();
615
-
616
- // Check if this is a partial save (from instruction save buttons)
617
- const isPartialSave = event?.submitter?.classList.contains('partial-save') ||
618
- (event?.target?.classList.contains('icon-button') &&
619
- (this.showInstructionsEditor || this.showTechnicalInstructionsEditor));
620
-
621
- // For partial saves, update the agent with current textarea values before saving
622
- if (isPartialSave) {
623
- if (this.showInstructionsEditor) {
624
- const instructionsTextarea = this.shadowRoot.querySelector('textarea[name="instructions"]');
625
- if (instructionsTextarea) this.agent.instructions = instructionsTextarea.value;
626
- }
627
- if (this.showTechnicalInstructionsEditor) {
628
- const techInstructionsTextarea = this.shadowRoot.querySelector('textarea[name="technicalInstructions"]');
629
- if (techInstructionsTextarea) this.agent.technicalInstructions = techInstructionsTextarea.value;
630
- }
631
- }
632
-
633
- // Store current form state before any operations
634
- const formState = {
635
- name: this.agent.name,
636
- persona: this.agent.persona,
637
- instructions: this.agent.instructions,
638
- technicalInstructions: this.agent.technicalInstructions,
639
- commands: [...(this.agent.commands || [])],
640
- recommended_plugins: [...(this.agent.recommended_plugins || [])],
641
- preferred_providers: [...(this.agent.preferred_providers || [])]
642
- };
643
-
644
- // Skip full validation for partial saves
645
- if (!isPartialSave && !this.validateForm()) {
646
- // Restore form state on validation error
647
- this.agent = {
648
- ...this.agent,
649
- ...formState
650
- };
651
- // Force update to refresh the form
652
- this.requestUpdate();
653
- return;
654
- }
655
-
656
- // For new agents, ensure we have default values
657
- if (this.newAgent) {
658
- this.agent.commands = this.agent.commands || [];
659
- this.agent.preferred_providers = this.agent.preferred_providers || [];
660
- this.agent.recommended_plugins = this.agent.recommended_plugins || [];
661
- }
662
-
663
- try {
664
- this.loading = true;
665
- const method = this.newAgent ? 'POST' : 'PUT';
666
- const url = this.newAgent ? '/agents/local' : `/agents/local/${this.agent.name}`;
667
-
668
- const cmdSwitches = this.shadowRoot.querySelectorAll('.toggle-command')
669
- console.log({cmdSwitches})
670
- let cmdsOn = []
671
- for (const cmdSwitch of cmdSwitches) {
672
- console.log({cmdSwitch})
673
- if (cmdSwitch.checked) {
674
- cmdsOn.push(cmdSwitch.id.replace('cmd-', ''))
675
- }
676
- }
677
- if (cmdsOn.length > 0) {
678
- this.agent.commands = cmdsOn
679
- }
680
- for (let cmd in this.missingCommands) {
681
- if (!this.agent.commands.includes(cmd)) {
682
- this.agent.commands.push(cmd)
683
- }
684
- }
685
-
686
- console.log('Saving, commands are:', this.agent.commands)
687
-
688
- const selectedModelsEls = this.shadowRoot.querySelectorAll('.service-model-select');
689
- console.log('Selected models:', selectedModelsEls, this.agent.service_models);
690
- for (const select of selectedModelsEls) {
691
- const selectedValue = select.value;
692
- const serviceName = select.name;
693
- if (selectedValue) {
694
- console.log(`Selected value for ${serviceName}:`, selectedValue);
695
- const [provider, model] = selectedValue.split('__');
696
- if (!this.agent.service_models) {
697
- this.agent.service_models = {};
698
- }
699
- this.agent.service_models[serviceName] = { provider, model }
700
- }
701
- }
702
-
703
- console.log('Agent before saving:', this.agent);
704
- const formData = new FormData();
705
- const agentData = { ...this.agent };
706
-
707
- agentData.flags = [];
708
- if (this.agent.uncensored) {
709
- // Make sure flags is an array
710
- if (!Array.isArray(agentData.flags)) {
711
- agentData.flags = [];
712
- }
713
- agentData.flags.push('uncensored');
714
- }
715
-
716
- formData.append('agent', JSON.stringify(agentData));
717
-
718
- const response = await fetch(url, {
719
- method,
720
- body: formData
721
- });
722
-
723
- if (!response.ok) {
724
- throw new Error('Failed to save agent');
725
- }
726
-
727
- // Get the saved agent data from response and update local state
728
- const savedAgent = await response.json();
729
-
730
- // For partial saves, just update with saved data and preserve current agent state
731
- if (isPartialSave) {
732
- // Store the current edited values before merging
733
- const currentInstructions = this.agent.instructions;
734
- const currentTechnicalInstructions = this.agent.technicalInstructions;
735
-
736
- this.agent = {
737
- ...this.agent,
738
- ...savedAgent
739
- };
740
-
741
- // Restore the edited field values to prevent server response from overwriting them
742
- if (this.showInstructionsEditor) {
743
- this.agent.instructions = currentInstructions;
744
- }
745
- if (this.showTechnicalInstructionsEditor) {
746
- this.agent.technicalInstructions = currentTechnicalInstructions;
747
- }
748
- } else {
749
- // For full saves, merge with current form values
750
- this.agent = {
751
- ...savedAgent,
752
- name: this.shadowRoot.querySelector('input[name="name"]')?.value || savedAgent.name,
753
- persona: this.shadowRoot.querySelector('select[name="persona"]')?.value || savedAgent.persona,
754
- thinking_level: this.shadowRoot.querySelector('select[name="thinking_level"]')?.value || savedAgent.thinking_level
755
- };
756
- }
757
-
758
- // Reset editors after partial save (from icon buttons)
759
- if (isPartialSave) {
760
- this.showInstructionsEditor = false;
761
- this.showTechnicalInstructionsEditor = false;
762
- }
763
-
764
- showNotification('success', `Agent ${this.agent.name} saved successfully`);
765
-
766
- // Dispatch event with merged data to preserve form state
767
- this.dispatchEvent(new CustomEvent('agent-saved', {
768
- detail: { ...this.agent, isPartialSave }, // Include the partial save flag
769
- bubbles: true,
770
- composed: true
771
- }));
772
- } catch (error) {
773
- showNotification('error', `Error saving agent: ${error.message}`);
774
-
775
- // Restore form state on error
776
- this.agent = {
777
- ...this.agent,
778
- ...formState
779
- };
780
-
781
- // Force update to refresh the form with restored data
782
- this.requestUpdate();
783
- } finally {
784
- this.loading = false;
785
- }
786
- }
787
-
788
- renderRequiredPlugins() {
789
- // Ensure required_plugins is always an array
790
- if (!Array.isArray(this.agent.recommended_plugins)) {
791
- this.agent.recommended_plugins = [];
792
- }
793
-
794
- if (!this.plugins || this.plugins.length === 0) {
795
- // Fetch plugins if not already loaded
796
- if (!this.pluginsFetched) {
797
- this.pluginsFetched = true;
798
- this.fetchPlugins();
799
- }
800
- return html`<div>Loading plugins...</div>`;
801
- }
802
-
803
- return html`
804
- <div class="commands-category">
805
- <h4>Recommended Plugins</h4>
806
- <div class="commands-grid">
807
- ${this.plugins.map(plugin => {
808
-
809
- const toggleId = `req_${plugin._uniqueId}`;
810
- let source = plugin.remote_source
811
- if (!source) source = plugin.github_url
812
- if (!source) return null;
813
-
814
- return html`
815
- <div class="command-item">
816
- <div class="command-info">
817
- <div class="command-name">${source}</div>
818
- </div>
819
- <toggle-switch
820
- .checked=${Boolean(this.agent.recommended_plugins.includes(source))}
821
- id="${toggleId}"
822
- @toggle-change=${(e) => this.handleInputChange({
823
- target: {
824
- plugin: plugin,
825
- name: 'recommended_plugins',
826
- value: source,
827
- type: 'checkbox',
828
- checked: e.detail.checked
829
- }
830
- })}>
831
- </toggle-switch>
832
- </div>
833
- `;})}
834
- </div>
835
- </div>
836
- `;
837
- }
838
-
839
- renderCommands() {
840
- return Object.entries(this.commands).map(([provider, commands]) => html`
841
- <div class="commands-category">
842
- <details>
843
- <summary>${provider}</summary>
844
- <div class="commands-grid">
845
- ${commands.map(command => html`
846
- <div class="command-item">
847
- <div class="command-info">
848
- <div class="command-name">${command.name}</div>
849
- ${command.docstring ? html`
850
- <div class="tooltip-text">${command.docstring}</div>
851
- ` : ''}
852
- </div>
853
- <toggle-switch
854
- class="toggle-command"
855
- .checked=${this.agent.commands?.includes(command.name) || false}
856
- id="cmd-${command.name}"
857
- @toggle-change=${(e) => this.handleInputChange({
858
- target: {
859
- name: 'commands',
860
- value: command.name,
861
- type: 'checkbox',
862
- checked: e.detail.checked
863
- }
864
- })}>
865
- </toggle-switch>
866
- </div>
867
- `)}
868
- </div>
869
- </details>
870
- </div>
871
- `);
872
- }
873
-
874
- renderServiceModels() {
875
- if (this.serviceModels === undefined || Object.keys(this.serviceModels).length === 0) {
876
- return html`<div>Loading service models...</div>`;
877
- }
878
-
879
- console.log('Service models:', this.serviceModels);
880
- console.log('Agent service models:', this.agent.service_models);
881
- return html`
882
- <div class="commands-category">
883
- <h4>Service Models</h4>
884
- <div class="commands-grid">
885
- ${Object.entries(this.serviceModels).map(([serviceName, providers]) => html`
886
- <div class="command-item">
887
- <div class="command-info">
888
- <div class="command-name">${serviceName}</div>
889
- </div>
890
- <select name="${serviceName}"
891
- class="service-model-select"
892
- @change=${this.handleInputChange}>
893
- ${Object.entries(providers).map(([provider, models]) => html`
894
- <optgroup label="${provider}">
895
- ${models.map(model => html`
896
- <option
897
- ?selected=${this.agent.service_models &&
898
- this.agent.service_models[serviceName] &&
899
- this.agent.service_models[serviceName].provider == provider &&
900
- this.agent.service_models[serviceName].model == model}
901
- value="${provider}__${model}">${model}</option>
902
- `)}
903
- </optgroup>
904
- `)}
905
- </select>
906
- </div>
907
- `)}
908
- </div>
909
- `
910
- }
911
-
912
-
913
- renderPreferredProviders() {
914
- // Ensure preferred_providers is always an array
915
- if (!Array.isArray(this.agent.preferred_providers)) {
916
- this.agent.preferred_providers = [];
917
- }
918
- console.log('Preferred providers:', this.agent.preferred_providers);
919
- return html`
920
- <div class="commands-category">
921
- <h4>Preferred Providers</h4>
922
- <div class="commands-grid">
923
- ${this.plugins.map(plugin => {
924
- // Use provider name (module name) as the value
925
- // Create a unique ID for each toggle
926
- const toggleId = `pref_${plugin.name}`
927
- console.log(`Rendering preferred provider for plugin: ${plugin.name}`)
928
- return html`
929
- <div class="command-item" data-provider="${plugin.name}">
930
- <div class="command-info">
931
- <div class="command-name">${plugin.name}</div>
932
- </div>
933
- <toggle-switch
934
- .checked=${this.agent.preferred_providers?.includes(plugin.name) || false}
935
- id="${toggleId}"
936
- @toggle-change=${(e) => this.handlePreferredProviderChange({
937
- detail: {
938
- plugin: plugin.name,
939
- value: plugin.name,
940
- id: plugin.name,
941
- checked: e.detail.checked
942
- }
943
- })}>
944
- </toggle-switch>
945
- </div>
946
- `;})}
947
- </div>
948
- </div>
949
- `;
950
- }
951
-
952
- renderPendingPlugins() {
953
- if (!this.pendingPlugins || this.pendingPlugins.length === 0) {
954
- return html``;
955
- }
956
-
957
- return html`
958
- <div class="form-group commands-section">
959
- <div class="commands-category">
960
- <h4>Pending Recommended Plugins</h4>
961
- <p>This agent recommends the following plugins that are not yet installed:</p>
962
- <ul>
963
- ${this.pendingPlugins.map(plugin => html`<li>${plugin}</li>`)}
964
- </ul>
965
- <button class="btn" @click=${this.installRecommendedPlugins}>
966
- Install Recommended Plugins
967
- </button>
968
- </div>
969
- </div>
970
- `;
971
- }
972
-
973
- _render() {
974
- return html`
975
- <form class="agent-form" @submit=${this.handleSubmit}>
976
- <div class="form-group">
977
- <label class="required">Name:</label>
978
- <input type="text" name="name"
979
- .value=${this.agent.name || ''}
980
- @input=${this.handleInputChange}>
981
- </div>
982
-
983
- <div class="form-group">
984
- <label class="required">Persona:</label>
985
- <select name="persona"
986
- value=${this.agent.persona || ''}
987
- @change=${this.handleInputChange}>
988
- <option value="">Select a persona</option>
989
- ${this.personas.map(persona => html`
990
- <option value="${persona.name}" ?selected=${persona.name === this.agent.persona}>${persona.name}</option>
991
- `)}
992
- </select>
993
- </div>
994
-
995
- <div class="form-group">
996
- <div class="form-group-header">
997
- <label class="required">Instructions:</label>
998
- <div class="form-group-actions">
999
- ${this.showInstructionsEditor ? html`
1000
- <button type="button" class="icon-button partial-save" @click=${async (e) => { e.preventDefault(); await this.handleSubmit(e); }}>
1001
- <span class="material-icons">save</span>
1002
- </button>
1003
- ` : html`
1004
- <button type="button" class="icon-button" @click=${() => this.showInstructionsEditor = true}>
1005
- <span class="material-icons">edit</span>
1006
- </button>
1007
- `}
1008
- </div>
1009
- </div>
1010
- ${this.showInstructionsEditor ? html`
1011
- <textarea name="instructions"
1012
- .value=${this.agent.instructions || ''}></textarea>
1013
- ` : html`
1014
- <div class="markdown-preview">
1015
- ${unsafeHTML(this.renderMarkdown(this.agent.instructions || ''))}
1016
- </div>
1017
- `}
1018
- </div>
1019
-
1020
- <div class="form-group">
1021
- <div class="form-group-header">
1022
- <label>Technical Instructions:</label>
1023
- <div class="form-group-actions">
1024
- ${this.showTechnicalInstructionsEditor ? html`
1025
- <button type="button" class="icon-button partial-save" @click=${async (e) => { e.preventDefault(); await this.handleSubmit(e); }}>
1026
- <span class="material-icons">save</span>
1027
- </button>
1028
- ` : html`
1029
- <button type="button" class="icon-button" @click=${() => this.showTechnicalInstructionsEditor = true}>
1030
- <span class="material-icons">edit</span>
1031
- </button>
1032
- `}
1033
- </div>
1034
- </div>
1035
- ${this.showTechnicalInstructionsEditor ? html`
1036
- <textarea name="technicalInstructions"
1037
- .value=${this.agent.technicalInstructions || ''}></textarea>
1038
- ` : html`
1039
- <div class="markdown-preview">
1040
- ${unsafeHTML(this.renderMarkdown(this.agent.technicalInstructions || ''))}
1041
- </div>
1042
- `}
1043
- </div>
1044
-
1045
- <div class="form-group">
1046
- <label>
1047
- Uncensored:
1048
- <toggle-switch
1049
- .checked=${this.agent.uncensored || false}
1050
- @toggle-change=${(e) => this.handleInputChange({
1051
- target: {
1052
- name: 'uncensored',
1053
- type: 'checkbox',
1054
- checked: e.detail.checked
1055
- }
1056
- })}>
1057
- </toggle-switch>
1058
- </label>
1059
- </div>
1060
-
1061
- <div class="form-group reasoning-level-group">
1062
- <label>Reasoning Effort:</label>
1063
- <select name="thinking_level"
1064
- value=${this.agent.thinking_level || 'off'}
1065
- @change=${this.handleInputChange}>
1066
- <option value="off"
1067
- ?selected=${(this.agent.thinking_level || 'off') === 'off'}>
1068
- Off
1069
- </option>
1070
- <option value="low"
1071
- ?selected=${(this.agent.thinking_level || 'off') === 'low'}>
1072
- Low
1073
- </option>
1074
- <option value="medium"
1075
- ?selected=${(this.agent.thinking_level || 'off') === 'medium'}>
1076
- Medium
1077
- </option>
1078
- <option value="high"
1079
- ?selected=${(this.agent.thinking_level || 'off') === 'high'}>
1080
- High
1081
- </option>
1082
- </select>
1083
- </div>
1084
-
1085
- ${this.renderPendingPlugins()}
1086
-
1087
- <div class="form-group commands-section">
1088
- <details>
1089
- <summary>Preferred Providers</summary>
1090
- ${this.renderPreferredProviders()}
1091
- </details>
1092
- </div>
1093
-
1094
- <div class="form-group commands-section">
1095
- <details>
1096
- <summary>Select Models</summary>
1097
- ${this.renderServiceModels()}
1098
- </details>
1099
- </div>
1100
-
1101
- <div class="form-group commands-section">
1102
- <details>
1103
- <summary>Recommended Plugins</summary>
1104
- ${this.renderRequiredPlugins()}
1105
- </details>
1106
- </div>
1107
-
1108
- ${this.agent.name && this.missingCommands && Object.keys(this.missingCommands).length > 0 ? html`
1109
- <div class="form-group commands-section">
1110
- <details>
1111
- <summary>Missing Commands (${Object.keys(this.missingCommands).length})</summary>
1112
- <missing-commands .agentName=${this.agent.name}></missing-commands>
1113
- </details>
1114
- </div>
1115
- ` : ''}
1116
-
1117
- <div class="form-group commands-section">
1118
- <details><summary>Available Commands</summary>
1119
- ${this.renderCommands()}
1120
- </details>
1121
- </div>
1122
-
1123
- <div class="agent-insert-end"></div>
1124
- <button class="btn" type="submit" ?disabled=${this.loading}>
1125
- ${this.loading ? 'Saving...' : 'Save'}
1126
- </button>
1127
-
1128
- </form>
1129
- `;
1130
- }
1131
- }
1132
-
1133
- customElements.define('agent-form', AgentForm);