@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
@@ -15,6 +15,22 @@ let cache = {
15
15
  const CACHE_TTL = 60000;
16
16
 
17
17
 
18
+ const logger = {
19
+ log: (...args) => {
20
+ if (process.env.DEBUG_LLM === 'true' && process.env.NODE_ENV !== 'test') {
21
+ if (!process.env.TUI_MODE) console.log(...args);
22
+ }
23
+ },
24
+ warn: (...args) => {
25
+ if (process.env.DEBUG_LLM === 'true' && process.env.NODE_ENV !== 'test') {
26
+ if (!process.env.TUI_MODE) console.warn(...args);
27
+ }
28
+ },
29
+ error: (...args) => {
30
+ console.error(...args);
31
+ }
32
+ };
33
+
18
34
  function computeCompletionURL(baseUrl) {
19
35
  const trimmed = baseUrl.replace(/\/$/, "");
20
36
 
@@ -294,6 +310,8 @@ async function call(promptKey, variables = {}, runtimeOptions = {}) {
294
310
  "stop",
295
311
  "n",
296
312
  "stream",
313
+ "tools",
314
+ "tool_choice",
297
315
  ];
298
316
 
299
317
  for (const key of allowedOptions) {
@@ -313,7 +331,7 @@ async function call(promptKey, variables = {}, runtimeOptions = {}) {
313
331
  `-H "Content-Type: application/json"`,
314
332
  ...Object.entries(provider.extraHeaders || {}).map(([k, v]) => `-H "${k}: ${v}"`),
315
333
  ].join(' ');
316
- console.log(`[llm.service] curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
334
+ logger.log(`[llm.service] curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
317
335
 
318
336
  response = await axios.post(url, body, {
319
337
  headers: {
@@ -394,6 +412,40 @@ async function call(promptKey, variables = {}, runtimeOptions = {}) {
394
412
  };
395
413
  }
396
414
 
415
+ let modelMetadataCache = {
416
+ data: {},
417
+ ts: 0
418
+ };
419
+ const MODEL_CACHE_TTL = 3600000;
420
+
421
+ async function getModelContextLength(modelId, providerKey) {
422
+ if (modelMetadataCache.ts && Date.now() - modelMetadataCache.ts < MODEL_CACHE_TTL) {
423
+ if (modelMetadataCache.data[modelId]) return modelMetadataCache.data[modelId];
424
+ }
425
+
426
+ if (providerKey !== 'openrouter') return 200000;
427
+
428
+ try {
429
+ const { providers } = await loadConfig();
430
+ const provider = providers[providerKey];
431
+ if (!provider || !provider.apiKey) return 200000;
432
+
433
+ const res = await axios.get(`https://openrouter.ai/api/v1/models/${modelId}`, {
434
+ headers: { 'Authorization': `Bearer ${provider.apiKey}` }
435
+ });
436
+
437
+ const contextLength = res?.data?.data?.context_length || 200000;
438
+
439
+ modelMetadataCache.data[modelId] = contextLength;
440
+ modelMetadataCache.ts = Date.now();
441
+
442
+ return contextLength;
443
+ } catch (e) {
444
+ logger.warn(`[llm.service] Failed to fetch context length for ${modelId}:`, e.message);
445
+ return 200000;
446
+ }
447
+ }
448
+
397
449
  async function callAdhoc(
398
450
  {
399
451
  providerKey,
@@ -409,9 +461,9 @@ async function callAdhoc(
409
461
  const key = String(providerKey || "").trim();
410
462
  let provider = providers[key];
411
463
 
412
- console.log('[llm.service] callAdhoc providerKey:', key);
413
- console.log('[llm.service] callAdhoc available provider keys:', Object.keys(providers));
414
- console.log('[llm.service] callAdhoc found provider:', !!provider, provider ? { enabled: provider.enabled, hasApiKey: !!provider.apiKey } : null);
464
+ logger.log('[llm.service] callAdhoc providerKey:', key);
465
+ logger.log('[llm.service] callAdhoc available provider keys:', Object.keys(providers));
466
+ logger.log('[llm.service] callAdhoc found provider:', !!provider, provider ? { enabled: provider.enabled, hasApiKey: !!provider.apiKey } : null);
415
467
 
416
468
  // Apply runtime overrides for provider if possible
417
469
  if (runtimeOptions.apiKey || runtimeOptions.baseUrl) {
@@ -456,6 +508,8 @@ async function callAdhoc(
456
508
  "stop",
457
509
  "n",
458
510
  "stream",
511
+ "tools",
512
+ "tool_choice",
459
513
  ];
460
514
 
461
515
  for (const key of allowedOptions) {
@@ -467,6 +521,7 @@ async function callAdhoc(
467
521
  let response;
468
522
  let text = "";
469
523
  let usage = null;
524
+ let toolCalls = null;
470
525
 
471
526
  try {
472
527
  // Debug: log curl equivalent
@@ -475,7 +530,7 @@ async function callAdhoc(
475
530
  `-H "Content-Type: application/json"`,
476
531
  ...Object.entries(provider.extraHeaders || {}).map(([k, v]) => `-H "${k}: ${v}"`),
477
532
  ].join(' ');
478
- console.log(`[llm.service] adhoc curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
533
+ logger.log(`[llm.service] adhoc curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
479
534
 
480
535
  response = await axios.post(url, body, {
481
536
  headers: {
@@ -495,6 +550,10 @@ async function callAdhoc(
495
550
  choice && choice.message && typeof choice.message.content === "string"
496
551
  ? choice.message.content
497
552
  : "";
553
+
554
+ toolCalls = choice && choice.message && Array.isArray(choice.message.tool_calls)
555
+ ? choice.message.tool_calls
556
+ : null;
498
557
 
499
558
  const rawUsage = data.usage || null;
500
559
  const normalized = normalizeUsage(rawUsage);
@@ -550,6 +609,7 @@ async function callAdhoc(
550
609
 
551
610
  return {
552
611
  content: text,
612
+ toolCalls,
553
613
  model: resolvedModel,
554
614
  providerKey: provider.key,
555
615
  usage,
@@ -634,7 +694,7 @@ async function stream(promptKey, variables = {}, runtimeOptions = {}, { onToken
634
694
  `-H "Content-Type: application/json"`,
635
695
  ...Object.entries(provider.extraHeaders || {}).map(([k, v]) => `-H "${k}: ${v}"`),
636
696
  ].join(' ');
637
- console.log(`[llm.service] streaming curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
697
+ logger.log(`[llm.service] streaming curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
638
698
 
639
699
  const response = await axios.post(url, body, {
640
700
  headers: {
@@ -741,9 +801,162 @@ async function stream(promptKey, variables = {}, runtimeOptions = {}, { onToken
741
801
  }
742
802
  }
743
803
 
804
+ async function streamAdhoc(
805
+ {
806
+ providerKey,
807
+ model,
808
+ messages,
809
+ promptKeyForAudit,
810
+ },
811
+ runtimeOptions = {},
812
+ { onToken, onReasoning } = {}
813
+ ) {
814
+ const { providers: rawProviders } = await loadConfig();
815
+ const providers = normalizeProviderConfig(rawProviders);
816
+
817
+ const key = String(providerKey || "").trim();
818
+ let provider = providers[key];
819
+
820
+ if (runtimeOptions.apiKey || runtimeOptions.baseUrl) {
821
+ provider = {
822
+ ...(provider || { key: key || 'custom', enabled: true, baseUrl: 'https://openrouter.ai/api/v1' }),
823
+ ...(runtimeOptions.apiKey ? { apiKey: runtimeOptions.apiKey } : {}),
824
+ ...(runtimeOptions.baseUrl ? { baseUrl: runtimeOptions.baseUrl } : {}),
825
+ };
826
+ }
827
+
828
+ if (!provider || provider.enabled === false || !provider.apiKey) {
829
+ throw new Error("Provider not found, disabled, or missing apiKey");
830
+ }
831
+
832
+ const resolvedModel = String(model || runtimeOptions.model || provider.defaultModel || "google/gemini-2.5-flash-lite").trim();
833
+ const inputMessages = Array.isArray(messages) ? messages : [];
834
+ if (!inputMessages.length) throw new Error("messages is required");
835
+
836
+ const url = computeCompletionURL(provider.baseUrl);
837
+ const body = {
838
+ model: resolvedModel,
839
+ messages: inputMessages,
840
+ stream: true
841
+ };
842
+
843
+ const allowedOptions = ["temperature", "top_p", "max_tokens", "presence_penalty", "frequency_penalty", "stop", "n", "tools", "tool_choice"];
844
+ for (const key of allowedOptions) {
845
+ if (runtimeOptions[key] !== undefined) body[key] = runtimeOptions[key];
846
+ }
847
+
848
+ let fullText = "";
849
+ let fullReasoning = "";
850
+ let lastUsage = null;
851
+ let toolCalls = [];
852
+
853
+ const curlHeaders = [
854
+ `-H "Authorization: Bearer ${provider.apiKey}"`,
855
+ `-H "Content-Type: application/json"`,
856
+ ...Object.entries(provider.extraHeaders || {}).map(([k, v]) => `-H "${k}: ${v}"`),
857
+ ].join(' ');
858
+ logger.log(`[llm.service] streamAdhoc curl equivalent:\n curl -X POST ${url} ${curlHeaders} -d '${JSON.stringify(body)}'\n`);
859
+
860
+ const response = await axios.post(url, body, {
861
+ headers: {
862
+ Authorization: `Bearer ${provider.apiKey}`,
863
+ "Content-Type": "application/json",
864
+ ...provider.extraHeaders,
865
+ },
866
+ timeout: provider.timeoutMs,
867
+ responseType: "stream",
868
+ });
869
+
870
+ await new Promise((resolve, reject) => {
871
+ let buffer = "";
872
+ response.data.on("data", (chunk) => {
873
+ buffer += chunk.toString("utf8");
874
+ const lines = buffer.split(/\r?\n/);
875
+ buffer = lines.pop() || "";
876
+
877
+ for (const line of lines) {
878
+ const trimmed = line.trim();
879
+ if (!trimmed || !trimmed.startsWith("data:")) continue;
880
+ const payload = trimmed.slice(5).trim();
881
+ if (payload === "[DONE]") continue;
882
+
883
+ try {
884
+ const parsed = JSON.parse(payload);
885
+ if (parsed.usage) lastUsage = parsed.usage;
886
+
887
+ const choice = parsed.choices?.[0];
888
+ if (!choice) {
889
+ const topReasoning = parsed.reasoning_content || parsed.reasoning || parsed.thinking;
890
+ if (topReasoning) {
891
+ fullReasoning += topReasoning;
892
+ if (onReasoning) onReasoning(topReasoning);
893
+ }
894
+ continue;
895
+ }
896
+
897
+ const delta = choice.delta || {};
898
+
899
+ if (delta.content) {
900
+ fullText += delta.content;
901
+ if (onToken) onToken(delta.content);
902
+ }
903
+
904
+ const reasoning = delta.reasoning_content || delta.reasoning || delta.thinking || choice.reasoning_content || choice.reasoning;
905
+ if (reasoning) {
906
+ fullReasoning += reasoning;
907
+ if (onReasoning) onReasoning(reasoning);
908
+ }
909
+
910
+ if (delta.tool_calls) {
911
+ for (const tc of delta.tool_calls) {
912
+ if (tc.index === undefined) tc.index = 0;
913
+ if (!toolCalls[tc.index]) {
914
+ toolCalls[tc.index] = {
915
+ id: tc.id,
916
+ type: 'function',
917
+ function: { name: '', arguments: '' }
918
+ };
919
+ }
920
+ if (tc.id) toolCalls[tc.index].id = tc.id;
921
+ if (tc.function?.name) toolCalls[tc.index].function.name += tc.function.name;
922
+ if (tc.function?.arguments) toolCalls[tc.index].function.arguments += tc.function.arguments;
923
+ }
924
+ }
925
+ } catch (e) {}
926
+ }
927
+ });
928
+
929
+ response.data.on("end", () => resolve());
930
+ response.data.on("error", (err) => reject(err));
931
+ });
932
+
933
+ const finalUsage = normalizeUsage(lastUsage);
934
+
935
+ await logAuditEntry({
936
+ promptKey: String(promptKeyForAudit || "adhoc_stream"),
937
+ providerKey: provider.key,
938
+ model: resolvedModel,
939
+ variables: {},
940
+ requestOptions: runtimeOptions,
941
+ outcome: "success",
942
+ usage: finalUsage,
943
+ });
944
+
945
+ return {
946
+ content: fullText,
947
+ reasoning: fullReasoning,
948
+ toolCalls: toolCalls.length > 0 ? toolCalls : null,
949
+ model: resolvedModel,
950
+ providerKey: provider.key,
951
+ usage: finalUsage
952
+ };
953
+ }
954
+
744
955
  module.exports = {
745
956
  call,
746
957
  testPrompt,
747
958
  callAdhoc,
959
+ streamAdhoc,
748
960
  stream,
961
+ getModelContextLength
749
962
  };