@resolveio/server-lib 20.13.12 → 20.14.0

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 (58) hide show
  1. package/collections/ai-terminal-conversation.collection.d.ts +2 -0
  2. package/collections/ai-terminal-conversation.collection.js +133 -0
  3. package/collections/ai-terminal-conversation.collection.js.map +1 -0
  4. package/collections/ai-terminal-message.collection.d.ts +2 -0
  5. package/collections/ai-terminal-message.collection.js +113 -0
  6. package/collections/ai-terminal-message.collection.js.map +1 -0
  7. package/collections/communication-metric.collection.d.ts +2 -0
  8. package/collections/communication-metric.collection.js +133 -0
  9. package/collections/communication-metric.collection.js.map +1 -0
  10. package/collections/openai-usage-ledger.collection.d.ts +2 -0
  11. package/collections/openai-usage-ledger.collection.js +120 -0
  12. package/collections/openai-usage-ledger.collection.js.map +1 -0
  13. package/managers/communication-metric.manager.d.ts +16 -0
  14. package/managers/communication-metric.manager.js +134 -0
  15. package/managers/communication-metric.manager.js.map +1 -0
  16. package/managers/method.manager.d.ts +2 -0
  17. package/managers/method.manager.js +162 -45
  18. package/managers/method.manager.js.map +1 -1
  19. package/managers/openai-usage-ledger.manager.d.ts +14 -0
  20. package/managers/openai-usage-ledger.manager.js +137 -0
  21. package/managers/openai-usage-ledger.manager.js.map +1 -0
  22. package/managers/subscription.manager.js +2 -0
  23. package/managers/subscription.manager.js.map +1 -1
  24. package/methods/ai-terminal.d.ts +1 -0
  25. package/methods/ai-terminal.js +1200 -0
  26. package/methods/ai-terminal.js.map +1 -0
  27. package/methods/report-builder.js +741 -0
  28. package/methods/report-builder.js.map +1 -1
  29. package/methods.ts +27 -0
  30. package/models/ai-terminal-conversation.model.d.ts +16 -0
  31. package/models/ai-terminal-conversation.model.js +4 -0
  32. package/models/ai-terminal-conversation.model.js.map +1 -0
  33. package/models/ai-terminal-message.model.d.ts +22 -0
  34. package/models/ai-terminal-message.model.js +4 -0
  35. package/models/ai-terminal-message.model.js.map +1 -0
  36. package/models/communication-metric.model.d.ts +20 -0
  37. package/models/communication-metric.model.js +4 -0
  38. package/models/communication-metric.model.js.map +1 -0
  39. package/models/openai-usage-ledger.model.d.ts +14 -0
  40. package/models/openai-usage-ledger.model.js +4 -0
  41. package/models/openai-usage-ledger.model.js.map +1 -0
  42. package/package.json +5 -1
  43. package/public_api.d.ts +13 -0
  44. package/public_api.js +13 -0
  45. package/public_api.js.map +1 -1
  46. package/publications/ai-terminal.d.ts +1 -0
  47. package/publications/ai-terminal.js +58 -0
  48. package/publications/ai-terminal.js.map +1 -0
  49. package/publications.ts +6 -0
  50. package/services/codex-client.d.ts +81 -0
  51. package/services/codex-client.js +991 -0
  52. package/services/codex-client.js.map +1 -0
  53. package/services/openai-client.d.ts +46 -0
  54. package/services/openai-client.js +315 -0
  55. package/services/openai-client.js.map +1 -0
  56. package/util/tokenizer.d.ts +5 -0
  57. package/util/tokenizer.js +35 -0
  58. package/util/tokenizer.js.map +1 -0
@@ -71,17 +71,50 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
71
71
  }
72
72
  return to.concat(ar || Array.prototype.slice.call(from));
73
73
  };
74
+ var __values = (this && this.__values) || function(o) {
75
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
76
+ if (m) return m.call(o);
77
+ if (o && typeof o.length === "number") return {
78
+ next: function () {
79
+ if (o && i >= o.length) o = void 0;
80
+ return { value: o && o[i++], done: !o };
81
+ }
82
+ };
83
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
84
+ };
74
85
  Object.defineProperty(exports, "__esModule", { value: true });
75
86
  exports.loadReportBuilderMethods = loadReportBuilderMethods;
76
87
  var simpl_schema_1 = require("simpl-schema");
77
88
  var report_builder_report_collection_1 = require("../collections/report-builder-report.collection");
89
+ var user_collection_1 = require("../collections/user.collection");
90
+ var openai_usage_ledger_manager_1 = require("../managers/openai-usage-ledger.manager");
78
91
  var pagination_model_1 = require("../models/pagination.model");
79
92
  var resolveio_server_app_1 = require("../resolveio-server-app");
93
+ var openai_client_1 = require("../services/openai-client");
80
94
  var common_1 = require("../util/common");
81
95
  var report_builder_unwinds_1 = require("../util/report-builder-unwinds");
82
96
  var schema_report_builder_1 = require("../util/schema-report-builder");
97
+ var tokenizer_1 = require("../util/tokenizer");
83
98
  function loadReportBuilderMethods(methodManager) {
84
99
  methodManager.methods({
100
+ reportBuilderAiSuggest: {
101
+ check: new simpl_schema_1.default({
102
+ payload: {
103
+ type: Object,
104
+ blackbox: true
105
+ }
106
+ }),
107
+ function: function (payload) {
108
+ return __awaiter(this, void 0, void 0, function () {
109
+ return __generator(this, function (_a) {
110
+ switch (_a.label) {
111
+ case 0: return [4 /*yield*/, executeReportBuilderAi(payload || {}, this)];
112
+ case 1: return [2 /*return*/, _a.sent()];
113
+ }
114
+ });
115
+ });
116
+ }
117
+ },
85
118
  reportbuilderreportWithId: {
86
119
  check: new simpl_schema_1.default({
87
120
  id: {
@@ -1625,5 +1658,713 @@ function expandLayoutColumnFilters(filters, selectedFields) {
1625
1658
  };
1626
1659
  return (filters || []).map(expandFilterObject);
1627
1660
  }
1661
+ function executeReportBuilderAi(payload, context) {
1662
+ return __awaiter(this, void 0, void 0, function () {
1663
+ var input, prompt, isSuperAdmin, guardrailsEnabled, guardrail, reportType, collectionRoot, collectionJoins, collections, resolvedFields, fieldLimit, trimmedFields, systemPrompt, userPrompt, openaiSettings, client, responseFormat, response, usage, parsed, sanitizeContext, patch, summaryNotes, idClient;
1664
+ var _a;
1665
+ return __generator(this, function (_b) {
1666
+ switch (_b.label) {
1667
+ case 0:
1668
+ input = payload || {};
1669
+ prompt = normalizeOptionalString(input.prompt);
1670
+ if (!prompt) {
1671
+ throw new Error('Prompt is required.');
1672
+ }
1673
+ return [4 /*yield*/, resolveIsSuperAdmin(context === null || context === void 0 ? void 0 : context.id_user)];
1674
+ case 1:
1675
+ isSuperAdmin = _b.sent();
1676
+ guardrailsEnabled = input.guardrails !== false && !isSuperAdmin;
1677
+ if (guardrailsEnabled) {
1678
+ guardrail = evaluateReportBuilderGuardrails(prompt);
1679
+ if (guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked) {
1680
+ return [2 /*return*/, guardrail];
1681
+ }
1682
+ }
1683
+ reportType = normalizeReportType(input.report_type);
1684
+ collectionRoot = normalizeOptionalString(input.collection_root);
1685
+ collectionJoins = Array.isArray(input.collection_joins) ? input.collection_joins : [];
1686
+ collections = sanitizeCollections(input.available_collections || []);
1687
+ resolvedFields = sanitizeFields(input.available_fields || []);
1688
+ fieldLimit = normalizeFieldLimit(input.field_limit);
1689
+ trimmedFields = trimFieldsForPrompt(resolvedFields, fieldLimit);
1690
+ systemPrompt = buildReportBuilderSystemPrompt(reportType);
1691
+ userPrompt = buildReportBuilderUserPrompt({
1692
+ prompt: prompt,
1693
+ reportType: reportType,
1694
+ reportName: normalizeOptionalString(input.report_name),
1695
+ collectionRoot: collectionRoot,
1696
+ collectionJoins: collectionJoins,
1697
+ idDateField: normalizeOptionalString(input.id_date_field),
1698
+ dateInterval: normalizeOptionalString(input.date_interval),
1699
+ collections: collections,
1700
+ fields: trimmedFields.fields
1701
+ });
1702
+ openaiSettings = resolveReportBuilderOpenAISettings(input.config);
1703
+ client = new openai_client_1.OpenAIClient(openaiSettings);
1704
+ responseFormat = normalizeOpenAIResponseFormat((_a = input.config) === null || _a === void 0 ? void 0 : _a.response_format) || 'json';
1705
+ return [4 /*yield*/, client.chat([
1706
+ { role: 'system', content: systemPrompt },
1707
+ { role: 'user', content: userPrompt }
1708
+ ], { timeoutMs: 60000, responseFormat: responseFormat })];
1709
+ case 2:
1710
+ response = _b.sent();
1711
+ usage = response.usage || estimateUsage([
1712
+ { role: 'system', content: systemPrompt },
1713
+ { role: 'user', content: userPrompt }
1714
+ ], response.content, response.model || openaiSettings.model);
1715
+ parsed = safeJsonParse(response.content);
1716
+ if (!parsed || typeof parsed !== 'object') {
1717
+ throw new Error('AI response was not valid JSON.');
1718
+ }
1719
+ sanitizeContext = buildSanitizerContext(collections, resolvedFields);
1720
+ patch = sanitizeReportBuilderPatch(parsed, sanitizeContext);
1721
+ summaryNotes = buildPatchNotes(patch, {
1722
+ reportType: reportType,
1723
+ truncated: trimmedFields.truncated,
1724
+ totalFields: trimmedFields.total,
1725
+ usedFields: trimmedFields.fields.length
1726
+ });
1727
+ return [4 /*yield*/, resolveClientId(input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
1728
+ case 3:
1729
+ idClient = _b.sent();
1730
+ if (!idClient) return [3 /*break*/, 5];
1731
+ return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
1732
+ id_client: idClient,
1733
+ model: response.model || openaiSettings.model || 'unknown',
1734
+ input_tokens: usage.inputTokens,
1735
+ output_tokens: usage.outputTokens,
1736
+ total_tokens: usage.totalTokens,
1737
+ category: 'report-builder-ai',
1738
+ id_request: response.requestId || ''
1739
+ })];
1740
+ case 4:
1741
+ _b.sent();
1742
+ _b.label = 5;
1743
+ case 5: return [2 /*return*/, {
1744
+ patch: patch,
1745
+ notes: summaryNotes,
1746
+ usage: {
1747
+ input_tokens: usage.inputTokens,
1748
+ output_tokens: usage.outputTokens,
1749
+ total_tokens: usage.totalTokens
1750
+ },
1751
+ model: response.model || openaiSettings.model
1752
+ }];
1753
+ }
1754
+ });
1755
+ });
1756
+ }
1757
+ function buildReportBuilderSystemPrompt(reportType) {
1758
+ return [
1759
+ 'You are a report builder configuration assistant.',
1760
+ 'Return ONLY a JSON object (no markdown).',
1761
+ 'Schema keys:',
1762
+ '- report_name (string)',
1763
+ '- collection_root (string)',
1764
+ '- collection_joins (array of { collection, alias })',
1765
+ '- layout_columns (array of { header, field_path, collection, mode, text, leaf_value_type, leaf_format_type, show })',
1766
+ '- groups_row (array of field_path strings)',
1767
+ '- filters (array of { field_path, condition, value, high_value, boolean_value, is_rolling, rolling_interval })',
1768
+ '- sort (array of { field_path, order })',
1769
+ '- totals (array of { type, fields })',
1770
+ '- links (array of { field_first, field_second })',
1771
+ '- id_date_field (string)',
1772
+ '- date_interval (Seconds|Minutes|Hours|Daily|Weekly|Monthly|Quarterly|Yearly)',
1773
+ '- notes (string)',
1774
+ 'Use only provided collections and field_path values.',
1775
+ 'Conditions allowed: eq, ne, lt, lte, gt, gte, bw, nnull, null, regex.',
1776
+ "Report type: ".concat(reportType || 'List', ". Ensure groups_row is set for Group/Dated reports."),
1777
+ 'If unsure, leave a section empty instead of guessing.'
1778
+ ].join('\n');
1779
+ }
1780
+ function buildReportBuilderUserPrompt(input) {
1781
+ var context = {
1782
+ report_type: input.reportType || 'List',
1783
+ current: {
1784
+ report_name: input.reportName || '',
1785
+ collection_root: input.collectionRoot || '',
1786
+ collection_joins: input.collectionJoins || [],
1787
+ id_date_field: input.idDateField || '',
1788
+ date_interval: input.dateInterval || ''
1789
+ },
1790
+ available_collections: input.collections || [],
1791
+ available_fields: input.fields || [],
1792
+ request: input.prompt
1793
+ };
1794
+ return JSON.stringify(context);
1795
+ }
1796
+ function resolveReportBuilderOpenAISettings(config) {
1797
+ var _a;
1798
+ var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
1799
+ var apiKey = (serverConfig['OPENAI_API_KEY'] || process.env.OPENAI_API_KEY || '').trim();
1800
+ if (!apiKey) {
1801
+ throw new Error('OpenAI API key missing. Add OPENAI_API_KEY to server config.');
1802
+ }
1803
+ var overrideModel = normalizeOptionalString(config === null || config === void 0 ? void 0 : config.model);
1804
+ var model = overrideModel
1805
+ || normalizeOptionalString(serverConfig['REPORT_BUILDER_OPENAI_MODEL'] || process.env.REPORT_BUILDER_OPENAI_MODEL)
1806
+ || normalizeOptionalString(serverConfig['OPENAI_MODEL'] || process.env.OPENAI_MODEL)
1807
+ || 'gpt-5.1';
1808
+ return {
1809
+ apiKey: apiKey,
1810
+ baseUrl: (serverConfig['OPENAI_BASE_URL'] || process.env.OPENAI_BASE_URL || '').trim() || undefined,
1811
+ model: model,
1812
+ temperature: (_a = normalizeOptionalNumber(config === null || config === void 0 ? void 0 : config.temperature)) !== null && _a !== void 0 ? _a : 0.2,
1813
+ maxTokens: normalizeOptionalNumber(config === null || config === void 0 ? void 0 : config.max_tokens),
1814
+ maxRetries: normalizeOptionalNumber(serverConfig['OPENAI_MAX_RETRIES'] || process.env.OPENAI_MAX_RETRIES),
1815
+ retryDelayMs: normalizeOptionalNumber(serverConfig['OPENAI_RETRY_DELAY_MS'] || process.env.OPENAI_RETRY_DELAY_MS)
1816
+ };
1817
+ }
1818
+ function normalizeReportType(value) {
1819
+ var normalized = normalizeOptionalString(value);
1820
+ if (normalized.toLowerCase() === 'group') {
1821
+ return 'Group';
1822
+ }
1823
+ if (normalized.toLowerCase() === 'dated') {
1824
+ return 'Dated';
1825
+ }
1826
+ return normalized ? (0, common_1.toTitleCase)(normalized) : 'List';
1827
+ }
1828
+ function normalizeOptionalString(value) {
1829
+ var raw = typeof value === 'string' ? value.trim() : '';
1830
+ return raw || '';
1831
+ }
1832
+ function normalizeOptionalNumber(value) {
1833
+ var parsed = Number(value);
1834
+ return Number.isFinite(parsed) ? parsed : undefined;
1835
+ }
1836
+ function normalizeOpenAIResponseFormat(value) {
1837
+ if (!value) {
1838
+ return undefined;
1839
+ }
1840
+ if (typeof value === 'string') {
1841
+ var normalized = value.trim().toLowerCase();
1842
+ if (!normalized) {
1843
+ return undefined;
1844
+ }
1845
+ if (normalized === 'text' || normalized === 'json' || normalized === 'json_object') {
1846
+ return normalized;
1847
+ }
1848
+ return { type: normalized };
1849
+ }
1850
+ if (typeof value === 'object') {
1851
+ var typeValue = normalizeOptionalString(value.type);
1852
+ if (!typeValue) {
1853
+ return undefined;
1854
+ }
1855
+ return __assign(__assign({}, value), { type: typeValue });
1856
+ }
1857
+ return undefined;
1858
+ }
1859
+ function normalizeFieldLimit(value) {
1860
+ var parsed = Number(value);
1861
+ if (!Number.isFinite(parsed)) {
1862
+ return 600;
1863
+ }
1864
+ return Math.max(50, Math.min((0, common_1.round)(parsed), 2000));
1865
+ }
1866
+ function estimateUsage(messages, responseText, model) {
1867
+ var inputTokens = (0, tokenizer_1.countChatTokens)(messages, model);
1868
+ var outputTokens = (0, tokenizer_1.countTokens)(responseText || '', model);
1869
+ return {
1870
+ inputTokens: inputTokens,
1871
+ outputTokens: outputTokens,
1872
+ totalTokens: inputTokens + outputTokens
1873
+ };
1874
+ }
1875
+ function sanitizeCollections(raw) {
1876
+ var out = [];
1877
+ var seen = new Set();
1878
+ (raw || []).forEach(function (entry) {
1879
+ var collection = normalizeOptionalString(entry === null || entry === void 0 ? void 0 : entry.collection);
1880
+ if (!collection) {
1881
+ return;
1882
+ }
1883
+ var key = collection.toLowerCase();
1884
+ if (seen.has(key)) {
1885
+ return;
1886
+ }
1887
+ seen.add(key);
1888
+ out.push({
1889
+ collection: collection,
1890
+ name: normalizeOptionalString(entry === null || entry === void 0 ? void 0 : entry.name) || (0, common_1.toTitleCase)(collection.replace(/[-_]/g, ' '))
1891
+ });
1892
+ });
1893
+ return out;
1894
+ }
1895
+ function sanitizeFields(raw) {
1896
+ var out = [];
1897
+ var seen = new Set();
1898
+ (raw || []).forEach(function (entry) {
1899
+ var fieldPath = normalizeOptionalString((entry === null || entry === void 0 ? void 0 : entry.field_path) || (entry === null || entry === void 0 ? void 0 : entry.fieldPath));
1900
+ if (!fieldPath) {
1901
+ return;
1902
+ }
1903
+ var key = fieldPath.toLowerCase();
1904
+ if (seen.has(key)) {
1905
+ return;
1906
+ }
1907
+ seen.add(key);
1908
+ out.push({
1909
+ field_path: fieldPath,
1910
+ field_path_name: normalizeOptionalString((entry === null || entry === void 0 ? void 0 : entry.field_path_name) || (entry === null || entry === void 0 ? void 0 : entry.fieldPathName) || (entry === null || entry === void 0 ? void 0 : entry.field_name)) || fieldPath,
1911
+ field_type: normalizeOptionalString((entry === null || entry === void 0 ? void 0 : entry.field_type) || (entry === null || entry === void 0 ? void 0 : entry.fieldType) || (entry === null || entry === void 0 ? void 0 : entry.field_type_name) || (entry === null || entry === void 0 ? void 0 : entry.fieldTypeName)) || 'String',
1912
+ collection_name: normalizeOptionalString((entry === null || entry === void 0 ? void 0 : entry.collection_name) || (entry === null || entry === void 0 ? void 0 : entry.collectionName) || (entry === null || entry === void 0 ? void 0 : entry.collection)) || ''
1913
+ });
1914
+ });
1915
+ return out;
1916
+ }
1917
+ function trimFieldsForPrompt(fields, limit) {
1918
+ if (!fields || !fields.length) {
1919
+ return { fields: [], truncated: false, total: 0 };
1920
+ }
1921
+ if (fields.length <= limit) {
1922
+ return { fields: fields, truncated: false, total: fields.length };
1923
+ }
1924
+ var trimmed = fields.slice(0, limit);
1925
+ return { fields: trimmed, truncated: true, total: fields.length };
1926
+ }
1927
+ function buildSanitizerContext(collections, fields) {
1928
+ var collectionIndex = new Map();
1929
+ var fieldIndex = new Map();
1930
+ var fieldNameIndex = new Map();
1931
+ collections.forEach(function (col) {
1932
+ var key = normalizeKey(col.collection);
1933
+ if (key) {
1934
+ collectionIndex.set(key, col);
1935
+ }
1936
+ var nameKey = normalizeKey(col.name);
1937
+ if (nameKey) {
1938
+ collectionIndex.set(nameKey, col);
1939
+ }
1940
+ });
1941
+ fields.forEach(function (field) {
1942
+ var pathKey = normalizePathKey(field.field_path);
1943
+ if (pathKey) {
1944
+ fieldIndex.set(pathKey, field);
1945
+ }
1946
+ var nameKey = normalizeKey(field.field_path_name);
1947
+ if (nameKey && !fieldNameIndex.has(nameKey)) {
1948
+ fieldNameIndex.set(nameKey, field.field_path);
1949
+ }
1950
+ });
1951
+ return { collectionIndex: collectionIndex, fieldIndex: fieldIndex, fieldNameIndex: fieldNameIndex };
1952
+ }
1953
+ function sanitizeReportBuilderPatch(raw, ctx) {
1954
+ var patch = {};
1955
+ if (!raw || typeof raw !== 'object') {
1956
+ return patch;
1957
+ }
1958
+ var reportName = normalizeOptionalString(raw.report_name || raw.reportName || raw.title);
1959
+ if (reportName) {
1960
+ patch.report_name = reportName.slice(0, 120);
1961
+ }
1962
+ var collectionRoot = resolveCollectionName(raw.collection_root || raw.collectionRoot, ctx);
1963
+ if (collectionRoot) {
1964
+ patch.collection_root = collectionRoot;
1965
+ }
1966
+ var joinsRaw = Array.isArray(raw.collection_joins || raw.joins) ? (raw.collection_joins || raw.joins) : [];
1967
+ var joins = [];
1968
+ joinsRaw.forEach(function (join) {
1969
+ var collection = resolveCollectionName((join === null || join === void 0 ? void 0 : join.collection) || (join === null || join === void 0 ? void 0 : join.name), ctx);
1970
+ if (!collection) {
1971
+ return;
1972
+ }
1973
+ var alias = sanitizeAlias(join === null || join === void 0 ? void 0 : join.alias);
1974
+ joins.push(__assign({ collection: collection }, (alias ? { alias: alias } : {})));
1975
+ });
1976
+ if (joins.length) {
1977
+ patch.collection_joins = joins;
1978
+ }
1979
+ var layoutColumnsRaw = Array.isArray(raw.layout_columns || raw.columns || raw.layout) ? (raw.layout_columns || raw.columns || raw.layout) : [];
1980
+ var layoutColumns = [];
1981
+ layoutColumnsRaw.forEach(function (col) {
1982
+ if (!col || typeof col !== 'object') {
1983
+ return;
1984
+ }
1985
+ var header = normalizeOptionalString(col.header || col.title || col.name);
1986
+ var fieldPath = resolveFieldPath(col.field_path || col.fieldPath, ctx);
1987
+ var mappingsRaw = Array.isArray(col.mappings) ? col.mappings : [];
1988
+ var mappings = [];
1989
+ mappingsRaw.forEach(function (map) {
1990
+ var mappedField = resolveFieldPath((map === null || map === void 0 ? void 0 : map.field_path) || (map === null || map === void 0 ? void 0 : map.fieldPath), ctx);
1991
+ var mode = normalizeLayoutMode(map === null || map === void 0 ? void 0 : map.mode);
1992
+ var text = normalizeOptionalString(map === null || map === void 0 ? void 0 : map.text);
1993
+ var collection = resolveCollectionName(map === null || map === void 0 ? void 0 : map.collection, ctx);
1994
+ if (mode === 'text') {
1995
+ mappings.push({
1996
+ mode: mode,
1997
+ text: text,
1998
+ collection: collection
1999
+ });
2000
+ }
2001
+ else if (mappedField) {
2002
+ mappings.push({
2003
+ mode: mode,
2004
+ field_path: mappedField,
2005
+ collection: collection,
2006
+ leaf_value_type: normalizeOptionalString((map === null || map === void 0 ? void 0 : map.leaf_value_type) || (map === null || map === void 0 ? void 0 : map.leafValueType)),
2007
+ leaf_format_type: normalizeOptionalString((map === null || map === void 0 ? void 0 : map.leaf_format_type) || (map === null || map === void 0 ? void 0 : map.leafFormatType)),
2008
+ show: typeof (map === null || map === void 0 ? void 0 : map.show) === 'boolean' ? map.show : undefined
2009
+ });
2010
+ }
2011
+ });
2012
+ if (!mappings.length && fieldPath) {
2013
+ mappings.push({ field_path: fieldPath, mode: normalizeLayoutMode(col.mode) });
2014
+ }
2015
+ if (!header && !mappings.length) {
2016
+ return;
2017
+ }
2018
+ layoutColumns.push({
2019
+ header: header || '',
2020
+ field_path: fieldPath || '',
2021
+ collection: resolveCollectionName(col.collection, ctx),
2022
+ mode: normalizeLayoutMode(col.mode),
2023
+ text: normalizeOptionalString(col.text),
2024
+ mappings: mappings
2025
+ });
2026
+ });
2027
+ if (!layoutColumns.length && Array.isArray(raw.selected_fields)) {
2028
+ (raw.selected_fields || []).forEach(function (field) {
2029
+ var fieldPath = resolveFieldPath(field, ctx);
2030
+ if (!fieldPath) {
2031
+ return;
2032
+ }
2033
+ layoutColumns.push({
2034
+ header: '',
2035
+ field_path: fieldPath,
2036
+ mappings: [{ field_path: fieldPath }]
2037
+ });
2038
+ });
2039
+ }
2040
+ if (layoutColumns.length) {
2041
+ patch.layout_columns = layoutColumns;
2042
+ }
2043
+ var groupsRowRaw = Array.isArray(raw.groups_row) ? raw.groups_row : [];
2044
+ var groupsRow = groupsRowRaw.map(function (entry) { return resolveFieldPath(entry, ctx); }).filter(Boolean);
2045
+ if (groupsRow.length) {
2046
+ patch.groups_row = groupsRow;
2047
+ }
2048
+ var filtersRaw = Array.isArray(raw.filters) ? raw.filters : [];
2049
+ var filters = [];
2050
+ filtersRaw.forEach(function (filter) {
2051
+ var fieldPath = resolveFieldPath((filter === null || filter === void 0 ? void 0 : filter.field_path) || (filter === null || filter === void 0 ? void 0 : filter.fieldPath), ctx);
2052
+ if (!fieldPath) {
2053
+ return;
2054
+ }
2055
+ var fieldMeta = ctx.fieldIndex.get(normalizePathKey(fieldPath));
2056
+ var condition = normalizeFilterCondition(filter === null || filter === void 0 ? void 0 : filter.condition);
2057
+ if (!condition) {
2058
+ return;
2059
+ }
2060
+ var value = normalizeFilterValue(filter === null || filter === void 0 ? void 0 : filter.value, fieldMeta === null || fieldMeta === void 0 ? void 0 : fieldMeta.field_type);
2061
+ var highValue = normalizeFilterValue(filter === null || filter === void 0 ? void 0 : filter.high_value, fieldMeta === null || fieldMeta === void 0 ? void 0 : fieldMeta.field_type);
2062
+ var booleanValue = normalizeBooleanValue(filter === null || filter === void 0 ? void 0 : filter.boolean_value);
2063
+ filters.push({
2064
+ field_path: fieldPath,
2065
+ condition: condition,
2066
+ value: value,
2067
+ high_value: highValue,
2068
+ boolean_value: booleanValue,
2069
+ is_rolling: typeof (filter === null || filter === void 0 ? void 0 : filter.is_rolling) === 'boolean' ? filter.is_rolling : undefined,
2070
+ rolling_interval: normalizeOptionalString(filter === null || filter === void 0 ? void 0 : filter.rolling_interval)
2071
+ });
2072
+ });
2073
+ if (filters.length) {
2074
+ patch.filters = filters;
2075
+ }
2076
+ var sortRaw = Array.isArray(raw.sort) ? raw.sort : [];
2077
+ var sort = [];
2078
+ sortRaw.forEach(function (entry) {
2079
+ var fieldPath = resolveFieldPath((entry === null || entry === void 0 ? void 0 : entry.field_path) || (entry === null || entry === void 0 ? void 0 : entry.fieldPath), ctx);
2080
+ if (!fieldPath) {
2081
+ return;
2082
+ }
2083
+ sort.push({
2084
+ field_path: fieldPath,
2085
+ order: normalizeSortOrder(entry === null || entry === void 0 ? void 0 : entry.order)
2086
+ });
2087
+ });
2088
+ if (sort.length) {
2089
+ patch.sort = sort;
2090
+ }
2091
+ var totalsRaw = Array.isArray(raw.totals) ? raw.totals : [];
2092
+ var totals = [];
2093
+ totalsRaw.forEach(function (total) {
2094
+ var type = normalizeTotalType(total === null || total === void 0 ? void 0 : total.type);
2095
+ var fields = Array.isArray(total === null || total === void 0 ? void 0 : total.fields) ? total.fields : [];
2096
+ var mappedFields = fields.map(function (field) { return resolveFieldPath(field, ctx); }).filter(Boolean);
2097
+ if (!type || !mappedFields.length) {
2098
+ return;
2099
+ }
2100
+ totals.push({ type: type, fields: mappedFields });
2101
+ });
2102
+ if (totals.length) {
2103
+ patch.totals = totals;
2104
+ }
2105
+ var linksRaw = Array.isArray(raw.links) ? raw.links : [];
2106
+ var links = [];
2107
+ linksRaw.forEach(function (link) {
2108
+ var first = resolveFieldPath((link === null || link === void 0 ? void 0 : link.field_first) || (link === null || link === void 0 ? void 0 : link.fieldFirst), ctx);
2109
+ var second = resolveFieldPath((link === null || link === void 0 ? void 0 : link.field_second) || (link === null || link === void 0 ? void 0 : link.fieldSecond), ctx);
2110
+ if (!first || !second) {
2111
+ return;
2112
+ }
2113
+ links.push({ field_first: first, field_second: second });
2114
+ });
2115
+ if (links.length) {
2116
+ patch.links = links;
2117
+ }
2118
+ var dateField = resolveFieldPath(raw.id_date_field || raw.date_field || raw.dateField, ctx);
2119
+ if (dateField) {
2120
+ patch.id_date_field = dateField;
2121
+ }
2122
+ var dateInterval = normalizeDateInterval(raw.date_interval || raw.dateInterval);
2123
+ if (dateInterval) {
2124
+ patch.date_interval = dateInterval;
2125
+ }
2126
+ var notes = normalizeOptionalString(raw.notes || raw.summary || raw.message);
2127
+ if (notes) {
2128
+ patch.notes = notes.slice(0, 400);
2129
+ }
2130
+ return patch;
2131
+ }
2132
+ function buildPatchNotes(patch, meta) {
2133
+ var columns = Array.isArray(patch === null || patch === void 0 ? void 0 : patch.layout_columns) ? patch.layout_columns.length : 0;
2134
+ var groups = Array.isArray(patch === null || patch === void 0 ? void 0 : patch.groups_row) ? patch.groups_row.length : 0;
2135
+ var filters = Array.isArray(patch === null || patch === void 0 ? void 0 : patch.filters) ? patch.filters.length : 0;
2136
+ var joins = Array.isArray(patch === null || patch === void 0 ? void 0 : patch.collection_joins) ? patch.collection_joins.length : 0;
2137
+ var parts = [
2138
+ "AI suggested ".concat(columns, " column").concat(columns === 1 ? '' : 's'),
2139
+ groups ? "".concat(groups, " group").concat(groups === 1 ? '' : 's') : '',
2140
+ filters ? "".concat(filters, " filter").concat(filters === 1 ? '' : 's') : '',
2141
+ joins ? "".concat(joins, " join").concat(joins === 1 ? '' : 's') : ''
2142
+ ].filter(Boolean);
2143
+ var note = parts.length ? parts.join(', ') + '.' : 'AI suggestions ready.';
2144
+ if (patch === null || patch === void 0 ? void 0 : patch.notes) {
2145
+ note += " ".concat(patch.notes);
2146
+ }
2147
+ if (meta.truncated) {
2148
+ note += " Field list trimmed to ".concat(meta.usedFields, " of ").concat(meta.totalFields, " available fields.");
2149
+ }
2150
+ return note;
2151
+ }
2152
+ function normalizeLayoutMode(value) {
2153
+ var normalized = normalizeOptionalString(value).toLowerCase();
2154
+ return normalized === 'text' ? 'text' : 'variable';
2155
+ }
2156
+ function normalizeFilterCondition(value) {
2157
+ var allowed = new Set(['eq', 'ne', 'lt', 'lte', 'gt', 'gte', 'bw', 'nnull', 'null', 'regex']);
2158
+ var normalized = normalizeOptionalString(value).toLowerCase();
2159
+ return allowed.has(normalized) ? normalized : '';
2160
+ }
2161
+ function normalizeSortOrder(value) {
2162
+ var normalized = normalizeOptionalString(value).toLowerCase();
2163
+ return normalized === 'dsc' || normalized === 'desc' ? 'dsc' : 'asc';
2164
+ }
2165
+ function normalizeTotalType(value) {
2166
+ var normalized = normalizeOptionalString(value).toLowerCase();
2167
+ if (normalized === 'avg' || normalized === 'sum') {
2168
+ return normalized;
2169
+ }
2170
+ return '';
2171
+ }
2172
+ function normalizeDateInterval(value) {
2173
+ var normalized = normalizeOptionalString(value);
2174
+ if (!normalized) {
2175
+ return '';
2176
+ }
2177
+ var map = {
2178
+ seconds: 'Seconds',
2179
+ minutes: 'Minutes',
2180
+ hours: 'Hours',
2181
+ daily: 'Daily',
2182
+ weekly: 'Weekly',
2183
+ monthly: 'Monthly',
2184
+ quarterly: 'Quarterly',
2185
+ yearly: 'Yearly'
2186
+ };
2187
+ var key = normalized.toLowerCase();
2188
+ return map[key] || '';
2189
+ }
2190
+ function normalizeFilterValue(value, fieldType) {
2191
+ if (fieldType === 'Number') {
2192
+ var num = Number(value);
2193
+ return Number.isFinite(num) ? num : value;
2194
+ }
2195
+ if (fieldType === 'Boolean') {
2196
+ if (value === true || value === false) {
2197
+ return value;
2198
+ }
2199
+ if (typeof value === 'string') {
2200
+ return value.toLowerCase() === 'true';
2201
+ }
2202
+ return value;
2203
+ }
2204
+ if (fieldType === 'Date') {
2205
+ if (value instanceof Date) {
2206
+ return value;
2207
+ }
2208
+ if (typeof value === 'string') {
2209
+ var parsed = new Date(value);
2210
+ return isNaN(parsed.getTime()) ? value : parsed.toISOString();
2211
+ }
2212
+ }
2213
+ return value;
2214
+ }
2215
+ function normalizeBooleanValue(value) {
2216
+ if (value === true || value === false) {
2217
+ return value;
2218
+ }
2219
+ if (typeof value === 'string') {
2220
+ if (value.toLowerCase() === 'true') {
2221
+ return true;
2222
+ }
2223
+ if (value.toLowerCase() === 'false') {
2224
+ return false;
2225
+ }
2226
+ }
2227
+ return undefined;
2228
+ }
2229
+ function resolveCollectionName(value, ctx) {
2230
+ var key = normalizeKey(value);
2231
+ if (!key) {
2232
+ return '';
2233
+ }
2234
+ var found = ctx.collectionIndex.get(key);
2235
+ return found ? found.collection : '';
2236
+ }
2237
+ function resolveFieldPath(value, ctx) {
2238
+ var _a;
2239
+ var pathKey = normalizePathKey(value);
2240
+ if (pathKey && ctx.fieldIndex.has(pathKey)) {
2241
+ return ((_a = ctx.fieldIndex.get(pathKey)) === null || _a === void 0 ? void 0 : _a.field_path) || '';
2242
+ }
2243
+ var nameKey = normalizeKey(value);
2244
+ if (nameKey && ctx.fieldNameIndex.has(nameKey)) {
2245
+ return ctx.fieldNameIndex.get(nameKey) || '';
2246
+ }
2247
+ return '';
2248
+ }
2249
+ function sanitizeAlias(value) {
2250
+ var alias = normalizeOptionalString(value);
2251
+ if (!alias) {
2252
+ return '';
2253
+ }
2254
+ return alias.replace(/[^\w\- ]/g, '').trim().slice(0, 40);
2255
+ }
2256
+ function normalizeKey(value) {
2257
+ return normalizeOptionalString(value).toLowerCase().replace(/[^a-z0-9]+/g, '');
2258
+ }
2259
+ function normalizePathKey(value) {
2260
+ return normalizeOptionalString(value).toLowerCase();
2261
+ }
2262
+ function safeJsonParse(value) {
2263
+ if (!value) {
2264
+ return null;
2265
+ }
2266
+ try {
2267
+ return JSON.parse(value);
2268
+ }
2269
+ catch (_a) {
2270
+ var match = value.match(/\{[\s\S]*\}/);
2271
+ if (!match) {
2272
+ return null;
2273
+ }
2274
+ try {
2275
+ return JSON.parse(match[0]);
2276
+ }
2277
+ catch (_b) {
2278
+ return null;
2279
+ }
2280
+ }
2281
+ }
2282
+ function evaluateReportBuilderGuardrails(message) {
2283
+ var e_1, _a;
2284
+ var normalized = String(message || '').toLowerCase();
2285
+ var patterns = [
2286
+ { pattern: /\b(source\s*code|full\s*code|entire\s*code|repo\s*dump|repository|git\s*clone)\b/i, reason: 'Code access is restricted.' },
2287
+ { pattern: /\b(credentials?|passwords?|secrets?|tokens?)\b/i, reason: 'Credentials and secrets are restricted.' },
2288
+ { pattern: /\b(delete|drop|truncate)\s+(database|db|schema|table)\b/i, reason: 'Database operations are restricted.' },
2289
+ { pattern: /\b(shell|terminal|ssh|sudo|rm\s+-rf|chmod|chown)\b/i, reason: 'Server operations are restricted.' },
2290
+ { pattern: /\b(exploit|bypass|malware|phishing|ransomware|ddos|sql\s*injection)\b/i, reason: 'Security abuse is restricted.' },
2291
+ { pattern: /\b(credit\s*card|social\s*security|ssn|bank\s*account)\b/i, reason: 'Sensitive personal data is restricted.' }
2292
+ ];
2293
+ try {
2294
+ for (var patterns_1 = __values(patterns), patterns_1_1 = patterns_1.next(); !patterns_1_1.done; patterns_1_1 = patterns_1.next()) {
2295
+ var entry = patterns_1_1.value;
2296
+ if (entry.pattern.test(normalized)) {
2297
+ return {
2298
+ blocked: true,
2299
+ reason: entry.reason,
2300
+ response: 'I can’t help with that request because it could access restricted systems or data. Please describe the report you need (fields, filters, timeframe) and I can configure it safely.'
2301
+ };
2302
+ }
2303
+ }
2304
+ }
2305
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2306
+ finally {
2307
+ try {
2308
+ if (patterns_1_1 && !patterns_1_1.done && (_a = patterns_1.return)) _a.call(patterns_1);
2309
+ }
2310
+ finally { if (e_1) throw e_1.error; }
2311
+ }
2312
+ return null;
2313
+ }
2314
+ function resolveIsSuperAdmin(id_user) {
2315
+ return __awaiter(this, void 0, void 0, function () {
2316
+ var user, _a;
2317
+ var _b;
2318
+ return __generator(this, function (_c) {
2319
+ switch (_c.label) {
2320
+ case 0:
2321
+ if (!id_user) {
2322
+ return [2 /*return*/, false];
2323
+ }
2324
+ _c.label = 1;
2325
+ case 1:
2326
+ _c.trys.push([1, 3, , 4]);
2327
+ return [4 /*yield*/, user_collection_1.Users.findById(id_user)];
2328
+ case 2:
2329
+ user = _c.sent();
2330
+ return [2 /*return*/, !!((_b = user === null || user === void 0 ? void 0 : user.roles) === null || _b === void 0 ? void 0 : _b.super_admin)];
2331
+ case 3:
2332
+ _a = _c.sent();
2333
+ return [2 /*return*/, false];
2334
+ case 4: return [2 /*return*/];
2335
+ }
2336
+ });
2337
+ });
2338
+ }
2339
+ function resolveClientId(idClientInput, idUser) {
2340
+ return __awaiter(this, void 0, void 0, function () {
2341
+ var normalized, user, fromOther, _a;
2342
+ var _b, _c;
2343
+ return __generator(this, function (_d) {
2344
+ switch (_d.label) {
2345
+ case 0:
2346
+ normalized = normalizeOptionalString(idClientInput);
2347
+ if (normalized) {
2348
+ return [2 /*return*/, normalized];
2349
+ }
2350
+ if (!idUser) {
2351
+ return [2 /*return*/, ''];
2352
+ }
2353
+ _d.label = 1;
2354
+ case 1:
2355
+ _d.trys.push([1, 3, , 4]);
2356
+ return [4 /*yield*/, user_collection_1.Users.findById(idUser)];
2357
+ case 2:
2358
+ user = _d.sent();
2359
+ fromOther = normalizeOptionalString(((_b = user === null || user === void 0 ? void 0 : user.other) === null || _b === void 0 ? void 0 : _b.id_client) || ((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.idClient));
2360
+ return [2 /*return*/, fromOther];
2361
+ case 3:
2362
+ _a = _d.sent();
2363
+ return [2 /*return*/, ''];
2364
+ case 4: return [2 /*return*/];
2365
+ }
2366
+ });
2367
+ });
2368
+ }
1628
2369
 
1629
2370
  //# sourceMappingURL=report-builder.js.map