@intranefr/superbackend 1.5.2 → 1.6.3

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 (134) hide show
  1. package/cookies.txt +6 -0
  2. package/cookies1.txt +6 -0
  3. package/cookies2.txt +6 -0
  4. package/cookies3.txt +6 -0
  5. package/cookies4.txt +5 -0
  6. package/cookies_old.txt +5 -0
  7. package/cookies_old_test.txt +6 -0
  8. package/cookies_super.txt +5 -0
  9. package/cookies_super_test.txt +6 -0
  10. package/cookies_test.txt +6 -0
  11. package/index.js +9 -0
  12. package/manage.js +745 -0
  13. package/package.json +6 -2
  14. package/plugins/core-waiting-list-migration/README.md +118 -0
  15. package/plugins/core-waiting-list-migration/index.js +438 -0
  16. package/plugins/global-settings-presets/index.js +20 -0
  17. package/plugins/hello-cli/index.js +17 -0
  18. package/plugins/ui-components-seeder/components/suiAlert.js +212 -0
  19. package/plugins/ui-components-seeder/components/suiToast.js +186 -0
  20. package/plugins/ui-components-seeder/index.js +31 -0
  21. package/public/js/admin-ui-components-preview.js +281 -0
  22. package/public/js/admin-ui-components.js +408 -0
  23. package/public/js/llm-provider-model-picker.js +193 -0
  24. package/public/test-iframe-fix.html +63 -0
  25. package/public/test-iframe.html +14 -0
  26. package/src/admin/endpointRegistry.js +68 -0
  27. package/src/controllers/admin.controller.js +36 -10
  28. package/src/controllers/adminAgents.controller.js +37 -0
  29. package/src/controllers/adminDataCleanup.controller.js +45 -0
  30. package/src/controllers/adminLlm.controller.js +19 -8
  31. package/src/controllers/adminLogin.controller.js +269 -0
  32. package/src/controllers/adminMarkdowns.controller.js +157 -0
  33. package/src/controllers/adminPlugins.controller.js +55 -0
  34. package/src/controllers/adminRegistry.controller.js +106 -0
  35. package/src/controllers/adminScripts.controller.js +138 -0
  36. package/src/controllers/adminStats.controller.js +4 -4
  37. package/src/controllers/adminTelegram.controller.js +72 -0
  38. package/src/controllers/markdowns.controller.js +42 -0
  39. package/src/controllers/registry.controller.js +32 -0
  40. package/src/controllers/waitingList.controller.js +52 -74
  41. package/src/helpers/mongooseHelper.js +6 -6
  42. package/src/helpers/scriptBase.js +2 -2
  43. package/src/middleware/auth.js +71 -1
  44. package/src/middleware/rbac.js +62 -0
  45. package/src/middleware.js +584 -176
  46. package/src/models/Agent.js +105 -0
  47. package/src/models/AgentMessage.js +82 -0
  48. package/src/models/GlobalSetting.js +11 -1
  49. package/src/models/Markdown.js +75 -0
  50. package/src/models/ScriptRun.js +8 -0
  51. package/src/models/TelegramBot.js +42 -0
  52. package/src/models/UiComponent.js +2 -0
  53. package/src/models/User.js +1 -1
  54. package/src/routes/admin.routes.js +3 -3
  55. package/src/routes/adminAgents.routes.js +13 -0
  56. package/src/routes/adminAssets.routes.js +11 -11
  57. package/src/routes/adminBlog.routes.js +2 -2
  58. package/src/routes/adminBlogAi.routes.js +2 -2
  59. package/src/routes/adminBlogAutomation.routes.js +2 -2
  60. package/src/routes/adminCache.routes.js +2 -2
  61. package/src/routes/adminConsoleManager.routes.js +2 -2
  62. package/src/routes/adminCrons.routes.js +2 -2
  63. package/src/routes/adminDataCleanup.routes.js +26 -0
  64. package/src/routes/adminDbBrowser.routes.js +2 -2
  65. package/src/routes/adminEjsVirtual.routes.js +2 -2
  66. package/src/routes/adminFeatureFlags.routes.js +6 -6
  67. package/src/routes/adminHeadless.routes.js +2 -2
  68. package/src/routes/adminHealthChecks.routes.js +2 -2
  69. package/src/routes/adminI18n.routes.js +2 -2
  70. package/src/routes/adminJsonConfigs.routes.js +8 -8
  71. package/src/routes/adminLlm.routes.js +8 -7
  72. package/src/routes/adminLogin.routes.js +23 -0
  73. package/src/routes/adminMarkdowns.routes.js +10 -0
  74. package/src/routes/adminMigration.routes.js +12 -12
  75. package/src/routes/adminPages.routes.js +2 -2
  76. package/src/routes/adminPlugins.routes.js +15 -0
  77. package/src/routes/adminProxy.routes.js +2 -2
  78. package/src/routes/adminRateLimits.routes.js +8 -8
  79. package/src/routes/adminRbac.routes.js +2 -2
  80. package/src/routes/adminRegistry.routes.js +24 -0
  81. package/src/routes/adminScripts.routes.js +6 -3
  82. package/src/routes/adminSeoConfig.routes.js +10 -10
  83. package/src/routes/adminTelegram.routes.js +14 -0
  84. package/src/routes/adminTerminals.routes.js +2 -2
  85. package/src/routes/adminUiComponents.routes.js +2 -2
  86. package/src/routes/adminUploadNamespaces.routes.js +7 -7
  87. package/src/routes/blogInternal.routes.js +2 -2
  88. package/src/routes/experiments.routes.js +2 -2
  89. package/src/routes/formsAdmin.routes.js +6 -6
  90. package/src/routes/globalSettings.routes.js +8 -8
  91. package/src/routes/internalExperiments.routes.js +2 -2
  92. package/src/routes/markdowns.routes.js +16 -0
  93. package/src/routes/notificationAdmin.routes.js +7 -7
  94. package/src/routes/orgAdmin.routes.js +16 -16
  95. package/src/routes/pages.routes.js +3 -3
  96. package/src/routes/registry.routes.js +11 -0
  97. package/src/routes/stripeAdmin.routes.js +12 -12
  98. package/src/routes/userAdmin.routes.js +7 -7
  99. package/src/routes/waitingListAdmin.routes.js +2 -2
  100. package/src/routes/workflows.routes.js +3 -3
  101. package/src/services/agent.service.js +546 -0
  102. package/src/services/agentHistory.service.js +345 -0
  103. package/src/services/agentTools.service.js +578 -0
  104. package/src/services/dataCleanup.service.js +286 -0
  105. package/src/services/jsonConfigs.service.js +284 -10
  106. package/src/services/llm.service.js +219 -6
  107. package/src/services/markdowns.service.js +522 -0
  108. package/src/services/plugins.service.js +348 -0
  109. package/src/services/registry.service.js +452 -0
  110. package/src/services/scriptsRunner.service.js +328 -37
  111. package/src/services/telegram.service.js +130 -0
  112. package/src/services/uiComponents.service.js +180 -0
  113. package/src/services/waitingListJson.service.js +401 -0
  114. package/src/utils/rbac/rightsRegistry.js +118 -0
  115. package/test-access.js +63 -0
  116. package/test-iframe-fix.html +63 -0
  117. package/test-iframe.html +14 -0
  118. package/views/admin-403.ejs +92 -0
  119. package/views/admin-agents.ejs +273 -0
  120. package/views/admin-coolify-deploy.ejs +8 -8
  121. package/views/admin-dashboard-home.ejs +52 -2
  122. package/views/admin-dashboard.ejs +179 -7
  123. package/views/admin-data-cleanup.ejs +357 -0
  124. package/views/admin-experiments.ejs +1 -1
  125. package/views/admin-login.ejs +286 -0
  126. package/views/admin-markdowns.ejs +905 -0
  127. package/views/admin-plugins-system.ejs +223 -0
  128. package/views/admin-scripts.ejs +221 -4
  129. package/views/admin-telegram.ejs +269 -0
  130. package/views/admin-ui-components.ejs +82 -402
  131. package/views/admin-users.ejs +207 -11
  132. package/views/partials/dashboard/nav-items.ejs +5 -0
  133. package/views/partials/llm-provider-model-picker.ejs +0 -161
  134. package/analysis-only.skill +0 -0
@@ -0,0 +1,345 @@
1
+ const mongoose = require('mongoose');
2
+ const AgentMessage = require('../models/AgentMessage');
3
+ const jsonConfigsService = require('./jsonConfigs.service');
4
+ const JsonConfig = require('../models/JsonConfig');
5
+
6
+ const HISTORY_JSON_CONFIG_PREFIX = 'agent-history-';
7
+
8
+ async function getHistoryJsonConfigKey(agentId, chatId) {
9
+ return `${HISTORY_JSON_CONFIG_PREFIX}${agentId}-${chatId}`;
10
+ }
11
+
12
+ /**
13
+ * Transform OpenAI tool calls format to Schema format
14
+ * OpenAI: { id, type, function: { name, arguments } }
15
+ * Schema: { name, arguments: Mixed, toolCallId }
16
+ */
17
+ function transformOpenAIToolCallsToSchema(toolCalls) {
18
+ if (!Array.isArray(toolCalls)) return [];
19
+
20
+ return toolCalls.map(tc => {
21
+ // If it's already in schema format (has toolCallId), return as is
22
+ if (tc.toolCallId) return tc;
23
+
24
+ // If it's in OpenAI format
25
+ if (tc.id && tc.function) {
26
+ let args = tc.function.arguments;
27
+ // Try to parse arguments if they are a string
28
+ if (typeof args === 'string') {
29
+ try {
30
+ args = JSON.parse(args);
31
+ } catch (e) {
32
+ // Keep as string if parsing fails
33
+ }
34
+ }
35
+
36
+ return {
37
+ name: tc.function.name,
38
+ arguments: args,
39
+ toolCallId: tc.id
40
+ };
41
+ }
42
+
43
+ // Fallback/Unknown format
44
+ return tc;
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Transform Schema tool calls format to OpenAI format
50
+ * Schema: { name, arguments: Mixed, toolCallId }
51
+ * OpenAI: { id, type, function: { name, arguments } }
52
+ */
53
+ function transformSchemaToolCallsToOpenAI(toolCalls) {
54
+ if (!Array.isArray(toolCalls)) return undefined;
55
+ if (toolCalls.length === 0) return undefined; // OpenAI prefers undefined over empty array for some models
56
+
57
+ return toolCalls.map(tc => {
58
+ // If it's already in OpenAI format (has id and function), return as is
59
+ if (tc.id && tc.function) return tc;
60
+
61
+ // If it's in Schema format (has toolCallId)
62
+ if (tc.toolCallId) {
63
+ return {
64
+ id: tc.toolCallId,
65
+ type: 'function',
66
+ function: {
67
+ name: tc.name,
68
+ arguments: typeof tc.arguments === 'object' ? JSON.stringify(tc.arguments) : String(tc.arguments || '')
69
+ }
70
+ };
71
+ }
72
+
73
+ // Fallback
74
+ return tc;
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Helper to migrate history from JsonConfig to AgentMessage
80
+ */
81
+ async function migrateSessionHistory(agentId, chatId) {
82
+ try {
83
+ const jsonConfigKey = await getHistoryJsonConfigKey(agentId, chatId);
84
+ const normalizedKey = jsonConfigKey.replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
85
+
86
+ const config = await JsonConfig.findOne({
87
+ $or: [
88
+ { slug: normalizedKey },
89
+ { alias: normalizedKey }
90
+ ]
91
+ }).lean();
92
+
93
+ if (!config || !config.jsonRaw) return false;
94
+
95
+ const historyData = JSON.parse(config.jsonRaw);
96
+ if (!historyData.history || !Array.isArray(historyData.history) || historyData.history.length === 0) {
97
+ return false;
98
+ }
99
+
100
+ const messages = historyData.history.map((msg, index) => ({
101
+ agentId,
102
+ chatId,
103
+ role: msg.role,
104
+ content: msg.content,
105
+ toolCalls: transformOpenAIToolCallsToSchema(msg.toolCalls || msg.tool_calls || []),
106
+ toolCallId: msg.toolCallId || msg.tool_call_id,
107
+ metadata: msg.metadata || {
108
+ tokens: msg.tokens || 0,
109
+ timestamp: config.createdAt || new Date()
110
+ },
111
+ // Stagger timestamps if not present
112
+ createdAt: new Date(Date.now() - (historyData.history.length - index) * 1000),
113
+ updatedAt: new Date()
114
+ }));
115
+
116
+ await AgentMessage.insertMany(messages);
117
+ console.log(`[agent.service] Migrated ${messages.length} messages from JsonConfig for ${chatId}`);
118
+ return true;
119
+ } catch (err) {
120
+ console.error(`[agent.service] Failed to migrate history for ${chatId}:`, err);
121
+ return false;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Append new messages to session history
127
+ * Handles lazy migration if needed
128
+ */
129
+ async function appendMessages(agentId, chatId, messages) {
130
+ try {
131
+ if (!Array.isArray(messages) || messages.length === 0) {
132
+ return { success: true, insertedCount: 0 };
133
+ }
134
+
135
+ // Check if we need to migrate existing history first
136
+ const existingCount = await AgentMessage.countDocuments({ agentId, chatId });
137
+ if (existingCount === 0) {
138
+ await migrateSessionHistory(agentId, chatId);
139
+ }
140
+
141
+ const messagesWithMetadata = messages.map(msg => ({
142
+ agentId,
143
+ chatId,
144
+ role: msg.role,
145
+ content: msg.content,
146
+ toolCalls: transformOpenAIToolCallsToSchema(msg.toolCalls || msg.tool_calls || []),
147
+ toolCallId: msg.toolCallId || msg.tool_call_id,
148
+ metadata: msg.metadata || {},
149
+ createdAt: new Date(),
150
+ updatedAt: new Date()
151
+ }));
152
+
153
+ const result = await AgentMessage.insertMany(messagesWithMetadata);
154
+
155
+ return {
156
+ success: true,
157
+ insertedCount: result.length,
158
+ messages: result
159
+ };
160
+ } catch (err) {
161
+ console.error('Error appending messages to history:', err);
162
+ throw err;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Get recent messages for LLM context window
168
+ */
169
+ async function getHistory(agentId, chatId, limit = 20) {
170
+ try {
171
+ // Try AgentMessage first
172
+ let messages = await AgentMessage.find({ agentId, chatId })
173
+ .sort({ createdAt: 1 })
174
+ .lean();
175
+
176
+ // If no messages found, try legacy JsonConfig
177
+ if (messages.length === 0) {
178
+ const jsonConfigKey = await getHistoryJsonConfigKey(agentId, chatId);
179
+ const normalizedKey = jsonConfigKey.replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
180
+ const legacyConfig = await jsonConfigsService.getJsonConfig(normalizedKey).catch(() => null);
181
+
182
+ if (legacyConfig && legacyConfig.history) {
183
+ console.log(`[agent.service] Serving legacy history from JsonConfig for ${chatId}`);
184
+ // Apply limit to legacy history
185
+ const startIndex = Math.max(0, legacyConfig.history.length - limit);
186
+ return legacyConfig.history.slice(startIndex);
187
+ }
188
+ return [];
189
+ }
190
+
191
+ // Apply limit to the result
192
+ const startIndex = Math.max(0, messages.length - limit);
193
+ messages = messages.slice(startIndex);
194
+
195
+ return messages.map(msg => {
196
+ const out = {
197
+ role: msg.role,
198
+ content: msg.content || (msg.role === 'assistant' && msg.toolCalls?.length ? null : '')
199
+ };
200
+
201
+ if (msg.role === 'assistant' && msg.toolCalls?.length > 0) {
202
+ out.tool_calls = transformSchemaToolCallsToOpenAI(msg.toolCalls);
203
+ }
204
+
205
+ if (msg.role === 'tool') {
206
+ out.tool_call_id = msg.toolCallId;
207
+ }
208
+
209
+ if (msg.metadata) {
210
+ out.metadata = msg.metadata;
211
+ }
212
+
213
+ return out;
214
+ });
215
+ } catch (err) {
216
+ console.error('Error loading history:', err);
217
+ return [];
218
+ }
219
+ }
220
+
221
+ async function getFullHistory(agentId, chatId, skip = 0, limit = 100) {
222
+ try {
223
+ const [messages, total] = await Promise.all([
224
+ AgentMessage.find({ agentId, chatId })
225
+ .sort({ createdAt: 1 })
226
+ .skip(skip)
227
+ .limit(limit)
228
+ .lean(),
229
+ AgentMessage.countDocuments({ agentId, chatId })
230
+ ]);
231
+
232
+ return {
233
+ messages: messages.map(msg => ({
234
+ role: msg.role,
235
+ content: msg.content,
236
+ tool_calls: transformSchemaToolCallsToOpenAI(msg.toolCalls),
237
+ toolCalls: transformSchemaToolCallsToOpenAI(msg.toolCalls),
238
+ tool_call_id: msg.toolCallId,
239
+ toolCallId: msg.toolCallId,
240
+ metadata: msg.metadata,
241
+ createdAt: msg.createdAt
242
+ })),
243
+ pagination: {
244
+ total,
245
+ skip,
246
+ limit,
247
+ hasMore: skip + limit < total
248
+ }
249
+ };
250
+ } catch (err) {
251
+ console.error('Error loading full history:', err);
252
+ return { messages: [], pagination: { total: 0, skip, limit, hasMore: false } };
253
+ }
254
+ }
255
+
256
+ async function searchHistory(agentId, chatId, query, options = {}) {
257
+ try {
258
+ const { limit = 20, skip = 0 } = options;
259
+
260
+ const messages = await AgentMessage.find({
261
+ agentId,
262
+ chatId,
263
+ $text: { $search: query }
264
+ })
265
+ .sort({ createdAt: -1 })
266
+ .skip(skip)
267
+ .limit(limit)
268
+ .lean();
269
+
270
+ return messages.map(msg => ({
271
+ role: msg.role,
272
+ content: msg.content,
273
+ createdAt: msg.createdAt,
274
+ matchScore: msg.score
275
+ }));
276
+ } catch (err) {
277
+ console.error('Error searching history:', err);
278
+ return [];
279
+ }
280
+ }
281
+
282
+ async function deleteHistory(agentId, chatId) {
283
+ try {
284
+ const result = await AgentMessage.deleteMany({ agentId, chatId });
285
+ return { success: true, deletedCount: result.deletedCount };
286
+ } catch (err) {
287
+ console.error('Error deleting history:', err);
288
+ throw err;
289
+ }
290
+ }
291
+
292
+ async function getHistoryStats(agentId, chatId) {
293
+ try {
294
+ const stats = await AgentMessage.aggregate([
295
+ { $match: { agentId: new mongoose.Types.ObjectId(agentId), chatId } },
296
+ {
297
+ $group: {
298
+ _id: null,
299
+ totalMessages: { $sum: 1 },
300
+ userMessages: { $sum: { $cond: [{ $eq: ['$role', 'user'] }, 1, 0] } },
301
+ assistantMessages: { $sum: { $cond: [{ $eq: ['$role', 'assistant'] }, 1, 0] } },
302
+ toolMessages: { $sum: { $cond: [{ $eq: ['$role', 'tool'] }, 1, 0] } },
303
+ totalTokens: { $sum: '$metadata.tokens' },
304
+ avgResponseTime: { $avg: '$metadata.processingTime' },
305
+ firstMessage: { $min: '$createdAt' },
306
+ lastMessage: { $max: '$createdAt' }
307
+ }
308
+ }
309
+ ]);
310
+
311
+ return stats[0] || null;
312
+ } catch (err) {
313
+ console.error('Error getting history stats:', err);
314
+ return null;
315
+ }
316
+ }
317
+
318
+ // Deprecated functions for backward compatibility
319
+ async function saveHistory(agentId, chatId, history) {
320
+ console.warn('[agent.service] Deprecated saveHistory called. Use appendMessages instead.');
321
+ // We can't safely implement overwrite with append-only model without deleting everything first.
322
+ return { success: false, error: 'Deprecated' };
323
+ }
324
+
325
+ // Alias loadHistory to getHistory for backward compatibility
326
+ const loadHistory = getHistory;
327
+
328
+ async function migrateCacheOnlyHistories() {
329
+ return { migrated: 0, failed: 0, deprecated: true };
330
+ }
331
+
332
+ module.exports = {
333
+ getHistoryJsonConfigKey,
334
+ appendMessages,
335
+ getHistory,
336
+ getFullHistory,
337
+ searchHistory,
338
+ deleteHistory,
339
+ getHistoryStats,
340
+ saveHistory,
341
+ loadHistory,
342
+ migrateCacheOnlyHistories,
343
+ transformOpenAIToolCallsToSchema,
344
+ transformSchemaToolCallsToOpenAI
345
+ };