@resolveio/server-lib 20.14.1 → 20.14.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.
- package/methods/ai-terminal.js +55 -6
- package/methods/ai-terminal.js.map +1 -1
- package/methods/report-builder.js +145 -57
- package/methods/report-builder.js.map +1 -1
- package/package.json +1 -1
- package/services/codex-client.d.ts +1 -1
- package/services/codex-client.js +1 -1
- package/services/codex-client.js.map +1 -1
|
@@ -90,11 +90,14 @@ var user_collection_1 = require("../collections/user.collection");
|
|
|
90
90
|
var openai_usage_ledger_manager_1 = require("../managers/openai-usage-ledger.manager");
|
|
91
91
|
var pagination_model_1 = require("../models/pagination.model");
|
|
92
92
|
var resolveio_server_app_1 = require("../resolveio-server-app");
|
|
93
|
-
var
|
|
93
|
+
var codex_client_1 = require("../services/codex-client");
|
|
94
94
|
var common_1 = require("../util/common");
|
|
95
95
|
var report_builder_unwinds_1 = require("../util/report-builder-unwinds");
|
|
96
96
|
var schema_report_builder_1 = require("../util/schema-report-builder");
|
|
97
97
|
var tokenizer_1 = require("../util/tokenizer");
|
|
98
|
+
var DEFAULT_REPORT_BUILDER_CODEX_MODEL = 'gpt-5.2-codex';
|
|
99
|
+
var DEFAULT_REPORT_BUILDER_CODEX_TIMEOUT_MS = 60000;
|
|
100
|
+
var reportBuilderCodexClient = null;
|
|
98
101
|
function loadReportBuilderMethods(methodManager) {
|
|
99
102
|
methodManager.methods({
|
|
100
103
|
reportBuilderAiSuggest: {
|
|
@@ -1660,10 +1663,9 @@ function expandLayoutColumnFilters(filters, selectedFields) {
|
|
|
1660
1663
|
}
|
|
1661
1664
|
function executeReportBuilderAi(payload, context) {
|
|
1662
1665
|
return __awaiter(this, void 0, void 0, function () {
|
|
1663
|
-
var input, prompt, isSuperAdmin, guardrailsEnabled, guardrail, reportType, collectionRoot, collectionJoins, collections, resolvedFields, fieldLimit, trimmedFields, systemPrompt, userPrompt,
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
switch (_b.label) {
|
|
1666
|
+
var input, prompt, isSuperAdmin, guardrailsEnabled, guardrail, reportType, collectionRoot, collectionJoins, collections, resolvedFields, fieldLimit, trimmedFields, arraySummary, systemPrompt, userPrompt, codexModel, codexClient, codexPrompt, runOptions, responseText, usage, parsed, sanitizeContext, patch, summaryNotes, idClient;
|
|
1667
|
+
return __generator(this, function (_a) {
|
|
1668
|
+
switch (_a.label) {
|
|
1667
1669
|
case 0:
|
|
1668
1670
|
input = payload || {};
|
|
1669
1671
|
prompt = normalizeOptionalString(input.prompt);
|
|
@@ -1672,7 +1674,7 @@ function executeReportBuilderAi(payload, context) {
|
|
|
1672
1674
|
}
|
|
1673
1675
|
return [4 /*yield*/, resolveIsSuperAdmin(context === null || context === void 0 ? void 0 : context.id_user)];
|
|
1674
1676
|
case 1:
|
|
1675
|
-
isSuperAdmin =
|
|
1677
|
+
isSuperAdmin = _a.sent();
|
|
1676
1678
|
guardrailsEnabled = input.guardrails !== false && !isSuperAdmin;
|
|
1677
1679
|
if (guardrailsEnabled) {
|
|
1678
1680
|
guardrail = evaluateReportBuilderGuardrails(prompt);
|
|
@@ -1687,6 +1689,7 @@ function executeReportBuilderAi(payload, context) {
|
|
|
1687
1689
|
resolvedFields = sanitizeFields(input.available_fields || []);
|
|
1688
1690
|
fieldLimit = normalizeFieldLimit(input.field_limit);
|
|
1689
1691
|
trimmedFields = trimFieldsForPrompt(resolvedFields, fieldLimit);
|
|
1692
|
+
arraySummary = buildArrayFieldSummary(trimmedFields.fields);
|
|
1690
1693
|
systemPrompt = buildReportBuilderSystemPrompt(reportType);
|
|
1691
1694
|
userPrompt = buildReportBuilderUserPrompt({
|
|
1692
1695
|
prompt: prompt,
|
|
@@ -1697,22 +1700,29 @@ function executeReportBuilderAi(payload, context) {
|
|
|
1697
1700
|
idDateField: normalizeOptionalString(input.id_date_field),
|
|
1698
1701
|
dateInterval: normalizeOptionalString(input.date_interval),
|
|
1699
1702
|
collections: collections,
|
|
1700
|
-
fields: trimmedFields.fields
|
|
1703
|
+
fields: trimmedFields.fields,
|
|
1704
|
+
fieldMeta: {
|
|
1705
|
+
truncated: trimmedFields.truncated,
|
|
1706
|
+
total: trimmedFields.total,
|
|
1707
|
+
used: trimmedFields.fields.length
|
|
1708
|
+
},
|
|
1709
|
+
arraySummary: arraySummary
|
|
1701
1710
|
});
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1711
|
+
codexModel = resolveReportBuilderCodexModel(input.config);
|
|
1712
|
+
codexClient = getReportBuilderCodexClient();
|
|
1713
|
+
codexPrompt = buildReportBuilderCodexPrompt(systemPrompt, userPrompt);
|
|
1714
|
+
runOptions = {
|
|
1715
|
+
timeoutMs: resolveReportBuilderCodexTimeoutMs(input.config),
|
|
1716
|
+
threadOptions: resolveReportBuilderCodexThreadOptions(input.config, codexModel)
|
|
1717
|
+
};
|
|
1718
|
+
return [4 /*yield*/, codexClient.run(codexPrompt, runOptions)];
|
|
1709
1719
|
case 2:
|
|
1710
|
-
|
|
1711
|
-
usage =
|
|
1720
|
+
responseText = _a.sent();
|
|
1721
|
+
usage = estimateUsage([
|
|
1712
1722
|
{ role: 'system', content: systemPrompt },
|
|
1713
1723
|
{ role: 'user', content: userPrompt }
|
|
1714
|
-
],
|
|
1715
|
-
parsed = safeJsonParse(
|
|
1724
|
+
], responseText, codexModel);
|
|
1725
|
+
parsed = safeJsonParse(responseText);
|
|
1716
1726
|
if (!parsed || typeof parsed !== 'object') {
|
|
1717
1727
|
throw new Error('AI response was not valid JSON.');
|
|
1718
1728
|
}
|
|
@@ -1726,20 +1736,20 @@ function executeReportBuilderAi(payload, context) {
|
|
|
1726
1736
|
});
|
|
1727
1737
|
return [4 /*yield*/, resolveClientId(input.id_client, context === null || context === void 0 ? void 0 : context.id_user)];
|
|
1728
1738
|
case 3:
|
|
1729
|
-
idClient =
|
|
1739
|
+
idClient = _a.sent();
|
|
1730
1740
|
if (!idClient) return [3 /*break*/, 5];
|
|
1731
1741
|
return [4 /*yield*/, (0, openai_usage_ledger_manager_1.recordOpenAIUsage)({
|
|
1732
1742
|
id_client: idClient,
|
|
1733
|
-
model:
|
|
1743
|
+
model: codexModel || 'unknown',
|
|
1734
1744
|
input_tokens: usage.inputTokens,
|
|
1735
1745
|
output_tokens: usage.outputTokens,
|
|
1736
1746
|
total_tokens: usage.totalTokens,
|
|
1737
1747
|
category: 'report-builder-ai',
|
|
1738
|
-
id_request:
|
|
1748
|
+
id_request: ''
|
|
1739
1749
|
})];
|
|
1740
1750
|
case 4:
|
|
1741
|
-
|
|
1742
|
-
|
|
1751
|
+
_a.sent();
|
|
1752
|
+
_a.label = 5;
|
|
1743
1753
|
case 5: return [2 /*return*/, {
|
|
1744
1754
|
patch: patch,
|
|
1745
1755
|
notes: summaryNotes,
|
|
@@ -1748,7 +1758,7 @@ function executeReportBuilderAi(payload, context) {
|
|
|
1748
1758
|
output_tokens: usage.outputTokens,
|
|
1749
1759
|
total_tokens: usage.totalTokens
|
|
1750
1760
|
},
|
|
1751
|
-
model:
|
|
1761
|
+
model: codexModel
|
|
1752
1762
|
}];
|
|
1753
1763
|
}
|
|
1754
1764
|
});
|
|
@@ -1771,7 +1781,17 @@ function buildReportBuilderSystemPrompt(reportType) {
|
|
|
1771
1781
|
'- id_date_field (string)',
|
|
1772
1782
|
'- date_interval (Seconds|Minutes|Hours|Daily|Weekly|Monthly|Quarterly|Yearly)',
|
|
1773
1783
|
'- notes (string)',
|
|
1774
|
-
'Use only provided collections and field_path values.',
|
|
1784
|
+
'Use only provided collections and field_path values (they reflect the current models/collections).',
|
|
1785
|
+
'Always set collection_root to the best matching collection from available_collections.',
|
|
1786
|
+
'Prefer exact field_path values from available_fields; never invent field paths.',
|
|
1787
|
+
'Use field_type to guide filters/totals (numeric fields for totals, date fields for date_interval, boolean fields for boolean_value).',
|
|
1788
|
+
'If field_summary.truncated is true, only use provided fields and note missing needs in notes.',
|
|
1789
|
+
'If you need joined data, add collection_joins with an alias and use the alias in field_path.',
|
|
1790
|
+
'array_summary lists array roots and candidate key_fields for linking arrays.',
|
|
1791
|
+
'If you select fields from multiple array roots, add links that align the arrays using key_fields.',
|
|
1792
|
+
'Avoid mixing unrelated array roots without links; prefer a single array root or non-array fields to prevent duplicate rows.',
|
|
1793
|
+
'Return a single valid JSON object with double quotes and no trailing commas.',
|
|
1794
|
+
'Omit keys you cannot confidently fill.',
|
|
1775
1795
|
'Conditions allowed: eq, ne, lt, lte, gt, gte, bw, nnull, null, regex.',
|
|
1776
1796
|
"Report type: ".concat(reportType || 'List', ". Ensure groups_row is set for Group/Dated reports."),
|
|
1777
1797
|
'If unsure, leave a section empty instead of guessing.'
|
|
@@ -1789,32 +1809,62 @@ function buildReportBuilderUserPrompt(input) {
|
|
|
1789
1809
|
},
|
|
1790
1810
|
available_collections: input.collections || [],
|
|
1791
1811
|
available_fields: input.fields || [],
|
|
1812
|
+
field_summary: input.fieldMeta || undefined,
|
|
1813
|
+
array_summary: input.arraySummary || [],
|
|
1792
1814
|
request: input.prompt
|
|
1793
1815
|
};
|
|
1794
1816
|
return JSON.stringify(context);
|
|
1795
1817
|
}
|
|
1796
|
-
function
|
|
1797
|
-
var
|
|
1818
|
+
function resolveReportBuilderCodexTimeoutMs(config) {
|
|
1819
|
+
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
1820
|
+
var raw = normalizeOptionalNumber((config === null || config === void 0 ? void 0 : config.timeout_ms)
|
|
1821
|
+
|| serverConfig['REPORT_BUILDER_CODEX_TIMEOUT_MS']
|
|
1822
|
+
|| process.env.REPORT_BUILDER_CODEX_TIMEOUT_MS);
|
|
1823
|
+
if (raw && raw > 0) {
|
|
1824
|
+
return (0, common_1.round)(raw);
|
|
1825
|
+
}
|
|
1826
|
+
return DEFAULT_REPORT_BUILDER_CODEX_TIMEOUT_MS;
|
|
1827
|
+
}
|
|
1828
|
+
function resolveReportBuilderCodexModel(config) {
|
|
1829
|
+
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
1830
|
+
var overrideModel = normalizeOptionalString(config === null || config === void 0 ? void 0 : config.model);
|
|
1831
|
+
var raw = overrideModel
|
|
1832
|
+
|| normalizeOptionalString(serverConfig['REPORT_BUILDER_CODEX_MODEL'] || process.env.REPORT_BUILDER_CODEX_MODEL)
|
|
1833
|
+
|| normalizeOptionalString(serverConfig['AI_DASHBOARD_CODEX_MODEL'] || process.env.AI_DASHBOARD_CODEX_MODEL)
|
|
1834
|
+
|| normalizeOptionalString(serverConfig['AI_TERMINAL_CODEX_MODEL'] || process.env.AI_TERMINAL_CODEX_MODEL)
|
|
1835
|
+
|| normalizeOptionalString(serverConfig['AI_ASSISTANT_CODEX_MODEL'] || process.env.AI_ASSISTANT_CODEX_MODEL);
|
|
1836
|
+
return raw || DEFAULT_REPORT_BUILDER_CODEX_MODEL;
|
|
1837
|
+
}
|
|
1838
|
+
function resolveReportBuilderCodexSettings() {
|
|
1798
1839
|
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
1799
1840
|
var apiKey = (serverConfig['OPENAI_API_KEY'] || process.env.OPENAI_API_KEY || '').trim();
|
|
1800
1841
|
if (!apiKey) {
|
|
1801
1842
|
throw new Error('OpenAI API key missing. Add OPENAI_API_KEY to server config.');
|
|
1802
1843
|
}
|
|
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
1844
|
return {
|
|
1809
1845
|
apiKey: apiKey,
|
|
1810
1846
|
baseUrl: (serverConfig['OPENAI_BASE_URL'] || process.env.OPENAI_BASE_URL || '').trim() || undefined,
|
|
1811
|
-
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),
|
|
1847
|
+
model: resolveReportBuilderCodexModel(),
|
|
1814
1848
|
maxRetries: normalizeOptionalNumber(serverConfig['OPENAI_MAX_RETRIES'] || process.env.OPENAI_MAX_RETRIES),
|
|
1815
1849
|
retryDelayMs: normalizeOptionalNumber(serverConfig['OPENAI_RETRY_DELAY_MS'] || process.env.OPENAI_RETRY_DELAY_MS)
|
|
1816
1850
|
};
|
|
1817
1851
|
}
|
|
1852
|
+
function resolveReportBuilderCodexThreadOptions(config, model) {
|
|
1853
|
+
var serverConfig = resolveio_server_app_1.ResolveIOServer.getServerConfig() || {};
|
|
1854
|
+
var effort = normalizeReasoningEffort((config === null || config === void 0 ? void 0 : config.reasoning_effort)
|
|
1855
|
+
|| serverConfig['REPORT_BUILDER_CODEX_REASONING_EFFORT']
|
|
1856
|
+
|| process.env.REPORT_BUILDER_CODEX_REASONING_EFFORT) || 'low';
|
|
1857
|
+
return __assign(__assign({}, (model ? { model: model } : {})), { sandboxMode: 'read-only', skipGitRepoCheck: true, modelReasoningEffort: effort, networkAccessEnabled: false, webSearchMode: 'disabled', webSearchEnabled: false, approvalPolicy: 'never' });
|
|
1858
|
+
}
|
|
1859
|
+
function getReportBuilderCodexClient() {
|
|
1860
|
+
if (!reportBuilderCodexClient) {
|
|
1861
|
+
reportBuilderCodexClient = new codex_client_1.CodexClient(resolveReportBuilderCodexSettings());
|
|
1862
|
+
}
|
|
1863
|
+
return reportBuilderCodexClient;
|
|
1864
|
+
}
|
|
1865
|
+
function buildReportBuilderCodexPrompt(systemPrompt, userPrompt) {
|
|
1866
|
+
return "System:\n".concat(systemPrompt, "\n\nUser:\n").concat(userPrompt).trim();
|
|
1867
|
+
}
|
|
1818
1868
|
function normalizeReportType(value) {
|
|
1819
1869
|
var normalized = normalizeOptionalString(value);
|
|
1820
1870
|
if (normalized.toLowerCase() === 'group') {
|
|
@@ -1833,28 +1883,10 @@ function normalizeOptionalNumber(value) {
|
|
|
1833
1883
|
var parsed = Number(value);
|
|
1834
1884
|
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1835
1885
|
}
|
|
1836
|
-
function
|
|
1837
|
-
|
|
1838
|
-
|
|
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;
|
|
1886
|
+
function normalizeReasoningEffort(value) {
|
|
1887
|
+
var normalized = normalizeOptionalString(value).toLowerCase();
|
|
1888
|
+
var allowed = new Set(['minimal', 'low', 'medium', 'high', 'xhigh']);
|
|
1889
|
+
return allowed.has(normalized) ? normalized : undefined;
|
|
1858
1890
|
}
|
|
1859
1891
|
function normalizeFieldLimit(value) {
|
|
1860
1892
|
var parsed = Number(value);
|
|
@@ -1924,6 +1956,31 @@ function trimFieldsForPrompt(fields, limit) {
|
|
|
1924
1956
|
var trimmed = fields.slice(0, limit);
|
|
1925
1957
|
return { fields: trimmed, truncated: true, total: fields.length };
|
|
1926
1958
|
}
|
|
1959
|
+
function buildArrayFieldSummary(fields) {
|
|
1960
|
+
var roots = new Map();
|
|
1961
|
+
(fields || []).forEach(function (field) {
|
|
1962
|
+
var fieldPath = normalizeOptionalString(field === null || field === void 0 ? void 0 : field.field_path);
|
|
1963
|
+
if (!fieldPath || !fieldPath.includes('.$')) {
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
var root = resolveArrayRoot(fieldPath);
|
|
1967
|
+
if (!root) {
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
var entry = roots.get(root);
|
|
1971
|
+
if (!entry) {
|
|
1972
|
+
entry = { root_path: root, key_fields: [], sample_fields: [] };
|
|
1973
|
+
roots.set(root, entry);
|
|
1974
|
+
}
|
|
1975
|
+
if (!entry.sample_fields.includes(fieldPath) && entry.sample_fields.length < 8) {
|
|
1976
|
+
entry.sample_fields.push(fieldPath);
|
|
1977
|
+
}
|
|
1978
|
+
if (isLinkCandidateFieldPath(fieldPath) && !entry.key_fields.includes(fieldPath) && entry.key_fields.length < 8) {
|
|
1979
|
+
entry.key_fields.push(fieldPath);
|
|
1980
|
+
}
|
|
1981
|
+
});
|
|
1982
|
+
return Array.from(roots.values());
|
|
1983
|
+
}
|
|
1927
1984
|
function buildSanitizerContext(collections, fields) {
|
|
1928
1985
|
var collectionIndex = new Map();
|
|
1929
1986
|
var fieldIndex = new Map();
|
|
@@ -2259,6 +2316,37 @@ function normalizeKey(value) {
|
|
|
2259
2316
|
function normalizePathKey(value) {
|
|
2260
2317
|
return normalizeOptionalString(value).toLowerCase();
|
|
2261
2318
|
}
|
|
2319
|
+
function resolveArrayRoot(path) {
|
|
2320
|
+
var raw = normalizeOptionalString(path);
|
|
2321
|
+
if (!raw) {
|
|
2322
|
+
return '';
|
|
2323
|
+
}
|
|
2324
|
+
var idx = raw.indexOf('.$');
|
|
2325
|
+
if (idx === -1) {
|
|
2326
|
+
return '';
|
|
2327
|
+
}
|
|
2328
|
+
return raw.slice(0, idx);
|
|
2329
|
+
}
|
|
2330
|
+
function isLinkCandidateFieldPath(path) {
|
|
2331
|
+
var normalized = normalizeOptionalString(path).toLowerCase();
|
|
2332
|
+
if (!normalized) {
|
|
2333
|
+
return false;
|
|
2334
|
+
}
|
|
2335
|
+
var last = (normalized.split('.').pop() || '').replace(/\$/g, '');
|
|
2336
|
+
if (!last) {
|
|
2337
|
+
return false;
|
|
2338
|
+
}
|
|
2339
|
+
if (last === 'id' || last === '_id') {
|
|
2340
|
+
return true;
|
|
2341
|
+
}
|
|
2342
|
+
if (last.endsWith('_id') || last.endsWith('_uuid') || last.endsWith('_guid')) {
|
|
2343
|
+
return true;
|
|
2344
|
+
}
|
|
2345
|
+
if (last.startsWith('id_')) {
|
|
2346
|
+
return true;
|
|
2347
|
+
}
|
|
2348
|
+
return false;
|
|
2349
|
+
}
|
|
2262
2350
|
function safeJsonParse(value) {
|
|
2263
2351
|
if (!value) {
|
|
2264
2352
|
return null;
|