@resolveio/server-lib 22.0.7 → 22.0.8
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 +264 -47
- package/methods/ai-terminal.js.map +1 -1
- package/methods/report-builder.js +7 -2
- package/methods/report-builder.js.map +1 -1
- package/methods.ts +6 -0
- package/package.json +1 -1
package/methods/ai-terminal.js
CHANGED
|
@@ -366,12 +366,65 @@ var AI_ASSISTANT_TERM_SYNONYMS = [
|
|
|
366
366
|
expansions: ['invoice', 'invoices', 'paid invoices', 'invoice payments', 'billing', 'sales']
|
|
367
367
|
}
|
|
368
368
|
];
|
|
369
|
+
var AI_ASSISTANT_REPORT_BUILDER_EXPERT_PLAYBOOK = [
|
|
370
|
+
'Report Builder Bridge Expert Playbook (execute in order for every data request):',
|
|
371
|
+
'1) Determine if data is required.',
|
|
372
|
+
'- If user asks for counts, lists, totals, trends, rankings, or "recent/last", run a report builder directive before answering.',
|
|
373
|
+
'',
|
|
374
|
+
'Report style mapping (always apply):',
|
|
375
|
+
'- Dated report: any breakdown over time (per day/week/month/quarter/year, trends, time-series comparisons).',
|
|
376
|
+
'- Grouped report: any nested headers, grouped buckets, grouped totals, or multi-level grouping dimensions.',
|
|
377
|
+
'- List report: simple flat records without grouped buckets or time-series grouping.',
|
|
378
|
+
'',
|
|
379
|
+
'2) Resolve the target dataset safely.',
|
|
380
|
+
'- Map user wording to internal collection names using routes, collection hints, field hints, and synonym expansion.',
|
|
381
|
+
'- Prefer report-* collections when permissionView is under /report.',
|
|
382
|
+
'- Never use *.versions unless user explicitly requests bug-history/version investigation.',
|
|
383
|
+
'- Never invent collection names or fields.',
|
|
384
|
+
'',
|
|
385
|
+
'3) Enforce permissions and scope in the directive.',
|
|
386
|
+
'- Always include permissionView.',
|
|
387
|
+
'- Assume non-super-admin unless explicitly told otherwise.',
|
|
388
|
+
'- Invoice-like collections require invoice view access.',
|
|
389
|
+
'- Customer portal users must stay in their own customer scope.',
|
|
390
|
+
'',
|
|
391
|
+
'4) Choose the right bridge tool.',
|
|
392
|
+
'- Use REPORT_BUILDER_READ for record lists, snapshots, detail lookups, and simple totals/counts.',
|
|
393
|
+
'- Use REPORT_BUILDER_AGG for grouped summaries, trends over time, rankings, and breakdowns.',
|
|
394
|
+
'',
|
|
395
|
+
'5) Build a minimal, high-signal query.',
|
|
396
|
+
'- Keep projection tight and limit rows (default 20 unless user asks for more).',
|
|
397
|
+
'- Add sort for deterministic output.',
|
|
398
|
+
'- Always sort by popular keys when available: name, company, item (then title/label/customer as fallbacks), ascending unless the user asks for a different order.',
|
|
399
|
+
'- If no popular key exists, use a stable fallback sort (createdAt/date_created then _id).',
|
|
400
|
+
'- Build filters with explicit boolean logic: use $and for required constraints and $or for alternate text/name matches.',
|
|
401
|
+
'- Use custom/calculated fields when the user asks for derived metrics (ratios, rates, margins, computed totals).',
|
|
402
|
+
'- Use collection joins/lookups when selected fields live across related collections.',
|
|
403
|
+
'- If multiple arrays are selected, link them by shared identifiers (_id or id_<x>) so rows are aligned and not duplicated by cartesian expansion.',
|
|
404
|
+
'- For relative dates, include an upper bound <= $$NOW unless user explicitly asks for future ranges.',
|
|
405
|
+
'- For invoice revenue, prefer paid_total fallback grand_total and paid/closed states when applicable.',
|
|
406
|
+
'',
|
|
407
|
+
'6) Reliability fallback sequence when result is empty.',
|
|
408
|
+
'- Re-check collection and date fields (date_created/createdAt/date_completed/date_paid variants).',
|
|
409
|
+
'- Run tiny probe (limit 1-3) to validate shape before concluding "no data".',
|
|
410
|
+
'- For name filters, verify date-only first; then apply tokenized regex and id/name lookup fallback.',
|
|
411
|
+
'',
|
|
412
|
+
'7) Output behavior after bridge response.',
|
|
413
|
+
'- Summarize the answer first in plain language.',
|
|
414
|
+
'- Then provide a markdown table with clean columns.',
|
|
415
|
+
'- Do not dump raw JSON.',
|
|
416
|
+
'- Do not claim certainty when data could not be fetched.',
|
|
417
|
+
'',
|
|
418
|
+
'8) Directive formatting requirement.',
|
|
419
|
+
'- End with exactly one REPORT_BUILDER_READ or REPORT_BUILDER_AGG line when data fetch is needed.',
|
|
420
|
+
'- Do not include extra directive lines or mixed directive types in one response.'
|
|
421
|
+
].join('\n');
|
|
369
422
|
var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
370
423
|
'You are the ResolveIO in-app AI assistant running with read-only access to the codebase.',
|
|
371
424
|
'Core rules:',
|
|
372
425
|
'- Never share code or file contents. All code is proprietary.',
|
|
373
426
|
'- Do not modify files, run destructive commands, or access databases directly.',
|
|
374
|
-
'- Read-only
|
|
427
|
+
'- Read-only data access is allowed only via the REPORT_BUILDER_READ/REPORT_BUILDER_AGG directives (see below).',
|
|
375
428
|
'- Do not access secrets, credentials, or user data.',
|
|
376
429
|
'- If the user has a customer portal scope (other.id_customer), only discuss that customer\'s data and what is visible in their customer portal. Never reference other customers or internal/admin-only data. If asked for anything outside the portal, say it isn\'t available.',
|
|
377
430
|
'- Do not assist with hacking, bypassing security, or abuse.',
|
|
@@ -382,14 +435,14 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
382
435
|
'- If permissionView starts with /report/, prefer the report-* collection when both report and base collections exist.',
|
|
383
436
|
'- Map user wording to internal collections/fields yourself. Do not ask for property names unless required to run a query.',
|
|
384
437
|
'- Use term hints from context (synonym expansions) when mapping user language to collections.',
|
|
385
|
-
'- Do not guess or invent collections/fields. If unsure, verify in the codebase or run a small
|
|
386
|
-
'- Prefer running a small
|
|
387
|
-
'- For any data request (counts, lists, breakdowns, recent/last items), you MUST run a
|
|
438
|
+
'- Do not guess or invent collections/fields. If unsure, verify in the codebase or run a small REPORT_BUILDER_READ probe (limit 1-5) to learn the shape.',
|
|
439
|
+
'- Prefer running a small REPORT_BUILDER_READ probe over asking multiple questions.',
|
|
440
|
+
'- For any data request (counts, lists, breakdowns, recent/last items), you MUST run a REPORT_BUILDER_READ or REPORT_BUILDER_AGG before answering.',
|
|
388
441
|
'- Ask at most one clarifying question only when required to run a query or resolve missing details.',
|
|
389
442
|
'- If a field starts with id_ and refers to another collection, treat it as a foreign key and look up the related record when needed.',
|
|
390
443
|
'- When resolving id_* fields, prefer lookup definitions from collection schemas/report-builder lookup tables to choose the target collection and name fields.',
|
|
391
444
|
'- When the user provides a customer, well, or chemical name, use case-insensitive regex matching to find it. Assume the name exists and try to match it before asking questions.',
|
|
392
|
-
'- Use the codebase context to choose correct collections/fields/workflows and use
|
|
445
|
+
'- Use the codebase context to choose correct collections/fields/workflows and use REPORT_BUILDER_READ/REPORT_BUILDER_AGG to answer with real data when needed.',
|
|
393
446
|
'- Process (fast path): Queue -> Planning -> Grabbing Data -> Drafting response. Use regex/keyword matching to identify collections/models, draft a minimal query, run the tool, then format a table. This should be fast; avoid extra narration.',
|
|
394
447
|
'- Assume a relevant collection exists; if verification reads return zero data, report no data found instead of interrogating the user.',
|
|
395
448
|
'- Never claim "no data exists" unless you resolved a collection and executed a legitimate query (with fallback date fields when needed) that returned zero rows.',
|
|
@@ -429,11 +482,11 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
429
482
|
'- SUPPORT_TICKET_CREATE: <one-line summary>',
|
|
430
483
|
'- Only include that line when the user clearly wants a ticket created. Do not claim a ticket is created unless you include that line.',
|
|
431
484
|
'- Do not end responses with tentative phrasing like "I could" or "I’m going to." Complete the request or state what is required to proceed.',
|
|
432
|
-
'
|
|
485
|
+
'Report builder bridge directives:',
|
|
433
486
|
'- If you need database data to answer, end your response with a single line exactly in this format:',
|
|
434
|
-
'-
|
|
487
|
+
'- REPORT_BUILDER_READ: {"collection":"<name>","query":{...},"options":{"projection":{...},"sort":{...},"limit":20},"permissionView":"</route>"}',
|
|
435
488
|
'- If you need grouped/aggregated data (totals by user, rankings, trends), end your response with a single line exactly in this format:',
|
|
436
|
-
'-
|
|
489
|
+
'- REPORT_BUILDER_AGG: {"collection":"<name>","pipeline":[...],"options":{"allowDiskUse":true,"limit":20},"permissionView":"</route>"}',
|
|
437
490
|
'- For invoice data, set permissionView to an invoice route (ex: /invoice/list or /report/invoice).',
|
|
438
491
|
'- For revenue/sales/billing questions, use invoices and sum paid_total (fallback to grand_total) with date_paid and Paid/Closed status when available.',
|
|
439
492
|
'- For relative date ranges (last/past/recent), include an upper bound <= $$NOW unless the user specifies a future end date.',
|
|
@@ -441,16 +494,18 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
|
|
|
441
494
|
'- Assume you are not a super admin unless explicitly told otherwise.',
|
|
442
495
|
'- Only request data when the user has permission for that module; invoice data requires invoice view access.',
|
|
443
496
|
'- If the user lacks permission, answer without data and explain how to view it in the app or request access.',
|
|
444
|
-
'- For simple counts or time-range totals, use
|
|
497
|
+
'- For simple counts or time-range totals, use REPORT_BUILDER_READ (includeTotal). For breakdowns, rankings, or sums grouped by a field, use REPORT_BUILDER_AGG.',
|
|
445
498
|
'- For performance, keep pipelines minimal: avoid $push arrays or large fields unless the user explicitly asks for them.',
|
|
446
499
|
'- For completion metrics (ex: "completed per day"), filter by completed status when applicable and use completion date fields; if completion dates are missing, fall back to createdAt/date_created and note the fallback.',
|
|
447
|
-
'- Before issuing
|
|
500
|
+
'- Before issuing REPORT_BUILDER_READ or REPORT_BUILDER_AGG, verify the collection name and key fields by checking collection/model definitions in the current app (look for "collectionName:" and date fields like date_created/date_completed/createdAt). Do not invent collection names.',
|
|
448
501
|
'- For creation-date questions when both date_created and createdAt exist, match both with $or so results are not missed.',
|
|
449
502
|
'- When grouping by fields that can be arrays (drivers, deliveries, routes, chemicals), $unwind first and group by both id and name when available.',
|
|
450
|
-
'- Use
|
|
503
|
+
'- Use REPORT_BUILDER_READ/REPORT_BUILDER_AGG only to produce summaries/snapshots/health checks (not raw dumps) when permitted.',
|
|
451
504
|
'- If the user explicitly asks for IDs, set options.includeIds: true.',
|
|
452
505
|
'- If a data question returns zero results, verify the collection/date field with a tiny read (limit 1-5) or a date field fallback before concluding there is no data.',
|
|
453
|
-
'- Keep responses concise and use the configured reasoning effort level (default low).'
|
|
506
|
+
'- Keep responses concise and use the configured reasoning effort level (default low).',
|
|
507
|
+
'',
|
|
508
|
+
AI_ASSISTANT_REPORT_BUILDER_EXPERT_PLAYBOOK
|
|
454
509
|
].join('\n');
|
|
455
510
|
var AI_ASSISTANT_PLANNER_SYSTEM_PROMPT = [
|
|
456
511
|
'You are ResolveIO Assistant Planner. Your job is to produce a permissions-aware execution plan for the user\'s request.',
|
|
@@ -987,6 +1042,42 @@ function loadAiTerminalMethods(methodManager) {
|
|
|
987
1042
|
});
|
|
988
1043
|
}
|
|
989
1044
|
},
|
|
1045
|
+
aiAssistantReportBuilderRead: {
|
|
1046
|
+
check: new simpl_schema_1.default({
|
|
1047
|
+
payload: {
|
|
1048
|
+
type: Object,
|
|
1049
|
+
blackbox: true
|
|
1050
|
+
}
|
|
1051
|
+
}),
|
|
1052
|
+
function: function (payload) {
|
|
1053
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1054
|
+
return __generator(this, function (_a) {
|
|
1055
|
+
switch (_a.label) {
|
|
1056
|
+
case 0: return [4 /*yield*/, executeAiAssistantMongoRead(payload, this)];
|
|
1057
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
},
|
|
1063
|
+
aiAssistantReportBuilderAggregate: {
|
|
1064
|
+
check: new simpl_schema_1.default({
|
|
1065
|
+
payload: {
|
|
1066
|
+
type: Object,
|
|
1067
|
+
blackbox: true
|
|
1068
|
+
}
|
|
1069
|
+
}),
|
|
1070
|
+
function: function (payload) {
|
|
1071
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1072
|
+
return __generator(this, function (_a) {
|
|
1073
|
+
switch (_a.label) {
|
|
1074
|
+
case 0: return [4 /*yield*/, executeAiAssistantMongoAggregate(payload, this)];
|
|
1075
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
},
|
|
990
1081
|
aiCoderTerminalDeployTest: {
|
|
991
1082
|
check: new simpl_schema_1.default({
|
|
992
1083
|
id_conversation: {
|
|
@@ -1645,11 +1736,11 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1645
1736
|
_x.trys.push([22, 31, , 32]);
|
|
1646
1737
|
toolStart = Date.now();
|
|
1647
1738
|
if (!(effectiveDirective.type === 'aggregate')) return [3 /*break*/, 24];
|
|
1648
|
-
return [4 /*yield*/,
|
|
1739
|
+
return [4 /*yield*/, executeAiAssistantReportBuilderAggregate(toolRequest, context)];
|
|
1649
1740
|
case 23:
|
|
1650
1741
|
_e = _x.sent();
|
|
1651
1742
|
return [3 /*break*/, 26];
|
|
1652
|
-
case 24: return [4 /*yield*/,
|
|
1743
|
+
case 24: return [4 /*yield*/, executeAiAssistantReportBuilderRead(toolRequest, context)];
|
|
1653
1744
|
case 25:
|
|
1654
1745
|
_e = _x.sent();
|
|
1655
1746
|
_x.label = 26;
|
|
@@ -1809,9 +1900,29 @@ function executeAiAssistantCodexRun(payload, context) {
|
|
|
1809
1900
|
});
|
|
1810
1901
|
});
|
|
1811
1902
|
}
|
|
1903
|
+
function executeAiAssistantReportBuilderRead(payload, context) {
|
|
1904
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1905
|
+
return __generator(this, function (_a) {
|
|
1906
|
+
switch (_a.label) {
|
|
1907
|
+
case 0: return [4 /*yield*/, executeAiAssistantMongoRead(payload, context)];
|
|
1908
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
1909
|
+
}
|
|
1910
|
+
});
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
function executeAiAssistantReportBuilderAggregate(payload, context) {
|
|
1914
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1915
|
+
return __generator(this, function (_a) {
|
|
1916
|
+
switch (_a.label) {
|
|
1917
|
+
case 0: return [4 /*yield*/, executeAiAssistantMongoAggregate(payload, context)];
|
|
1918
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1812
1923
|
function executeAiAssistantMongoRead(payload, context) {
|
|
1813
1924
|
return __awaiter(this, void 0, void 0, function () {
|
|
1814
|
-
var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, strippedClient, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, probeDocs, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, nameFallback, fallbackDocs, _c, chemicalLookup, fallbackDocs, queryFields, _d, aliases, rewrittenQuery, fallbackDocs, _e, idLookup, fallbackDocs, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, nameFields, dateFields, diagnostics, queryNoName, _f, queryNoDate, _g, _h, _j, _k, allCollections, base, alt, altCount, _l, total, sanitizedDocuments, requestedFields, missingFields, _m, projectionAliases, expandedProjection, refreshedDocs, includeIds, fieldAliases, displayDocs, idLookupDisplay, priorityFields, display;
|
|
1925
|
+
var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, strippedClient, clientScopedQuery, scopedQuery, normalized, findOptions, documents, executedQuery, probeDocs, dateFallback, fallbackQuery, fallbackDocs, expanded, fallbackDocs, nameFallback, fallbackDocs, _c, chemicalLookup, fallbackDocs, queryFields, _d, aliases, rewrittenQuery, fallbackDocs, _e, idLookup, fallbackDocs, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, nameFields, dateFields, diagnostics, queryNoName, _f, queryNoDate, _g, _h, _j, _k, allCollections, base, alt, altCount, _l, total, sanitizedDocuments, requestedFields, missingFields, _m, projectionAliases, expandedProjection, refreshedDocs, includeIds, fieldAliases, displayDocs, idLookupDisplay, priorityFields, display;
|
|
1815
1926
|
var _o, _p;
|
|
1816
1927
|
return __generator(this, function (_q) {
|
|
1817
1928
|
switch (_q.label) {
|
|
@@ -1819,7 +1930,7 @@ function executeAiAssistantMongoRead(payload, context) {
|
|
|
1819
1930
|
input = payload || {};
|
|
1820
1931
|
rawCollection = normalizeOptionalString(input.collection);
|
|
1821
1932
|
if (!rawCollection) {
|
|
1822
|
-
throw new Error('AI assistant
|
|
1933
|
+
throw new Error('AI assistant report builder bridge: Collection is required.');
|
|
1823
1934
|
}
|
|
1824
1935
|
dbName = resolveAssistantDatabaseName(input.database, input.mongo);
|
|
1825
1936
|
db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
|
|
@@ -1827,15 +1938,26 @@ function executeAiAssistantMongoRead(payload, context) {
|
|
|
1827
1938
|
case 1:
|
|
1828
1939
|
collectionResolution = _q.sent();
|
|
1829
1940
|
collection = collectionResolution.name || rawCollection;
|
|
1941
|
+
bridgeCollection = resolveAssistantReportBuilderBridgeCollection(collection);
|
|
1942
|
+
if (bridgeCollection.fallbackFrom) {
|
|
1943
|
+
collection = bridgeCollection.collection;
|
|
1944
|
+
}
|
|
1830
1945
|
schemaFields = getCollectionSchemaFieldNames(collection);
|
|
1831
1946
|
return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
|
|
1832
1947
|
case 2:
|
|
1833
1948
|
_a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
|
|
1834
1949
|
if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
|
|
1835
|
-
throw new Error('AI assistant
|
|
1950
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
1836
1951
|
}
|
|
1837
1952
|
customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
|
|
1838
1953
|
fallbackMeta = {};
|
|
1954
|
+
if (bridgeCollection.fallbackFrom) {
|
|
1955
|
+
fallbackMeta.reportBuilderBridge = {
|
|
1956
|
+
from: bridgeCollection.fallbackFrom,
|
|
1957
|
+
to: collection,
|
|
1958
|
+
used: true
|
|
1959
|
+
};
|
|
1960
|
+
}
|
|
1839
1961
|
baseQuery = normalizeMongoQuery(input.query);
|
|
1840
1962
|
if (!isSuperAdmin && customerId) {
|
|
1841
1963
|
stripped = stripQueryFieldPathsDeepWithMeta(baseQuery, ['id_customer', 'other.id_customer']);
|
|
@@ -1849,7 +1971,7 @@ function executeAiAssistantMongoRead(payload, context) {
|
|
|
1849
1971
|
if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
|
|
1850
1972
|
userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
|
|
1851
1973
|
if (!userId) {
|
|
1852
|
-
throw new Error('AI assistant
|
|
1974
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
1853
1975
|
}
|
|
1854
1976
|
baseQuery = {
|
|
1855
1977
|
$and: [baseQuery, { _id: userId }]
|
|
@@ -2262,6 +2384,7 @@ function executeAiAssistantMongoRead(payload, context) {
|
|
|
2262
2384
|
collectionMatched: collectionResolution.matched,
|
|
2263
2385
|
collectionCandidates: collectionResolution.candidates,
|
|
2264
2386
|
collectionScore: collectionResolution.score,
|
|
2387
|
+
bridge: 'report-builder',
|
|
2265
2388
|
database: dbName,
|
|
2266
2389
|
query: executedQuery,
|
|
2267
2390
|
options: normalized.findOptions,
|
|
@@ -2275,7 +2398,7 @@ function executeAiAssistantMongoRead(payload, context) {
|
|
|
2275
2398
|
}
|
|
2276
2399
|
function executeAiAssistantMongoAggregate(payload, context) {
|
|
2277
2400
|
return __awaiter(this, void 0, void 0, function () {
|
|
2278
|
-
var input, rawCollection, dbName, db, collectionResolution, collection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
|
|
2401
|
+
var input, rawCollection, dbName, db, collectionResolution, collection, bridgeCollection, schemaFields, _a, user, isSuperAdmin, customerId, fallbackMeta, baseQuery, stripped, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalizedPipeline, sanitizedPipeline, strippedPipeline, pipelineWithScope, normalizedOptions, limitedPipeline, dateField, aggregateOptions, documents, executedPipeline, probeDocs, fallback, fallbackPipeline, fallbackDocs, createdFallback, createdPipeline, createdDocs, expanded, expandedDocs, completionFallback, fallbackPipeline, fallbackDocs, completionExprFallback, fallbackPipeline, fallbackDocs, unwindFallback, shouldUnwind, _c, _d, fallbackPipeline, fallbackDocs, nameFallback, fallbackPipeline, fallbackDocs, _e, _loop_1, i, state_1, matchFields_1, _f, aliases, rewrittenPipeline, fallbackDocs, _loop_2, i, state_2, baseCollection, fallbackPayload, fallbackResult, existingFallbacks, matchStages, diagnostics, combinedMatch, nameFields, dateFields, queryNoName, _g, queryNoDate, _h, _j, _k, _l, allCollections, base, alt, altCount, _m, sanitizedDocuments, includeIds, displayDocs, idLookupDisplay, display;
|
|
2279
2402
|
var _o, _p;
|
|
2280
2403
|
return __generator(this, function (_q) {
|
|
2281
2404
|
switch (_q.label) {
|
|
@@ -2283,7 +2406,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2283
2406
|
input = payload || {};
|
|
2284
2407
|
rawCollection = normalizeOptionalString(input.collection);
|
|
2285
2408
|
if (!rawCollection) {
|
|
2286
|
-
throw new Error('AI assistant
|
|
2409
|
+
throw new Error('AI assistant report builder bridge: Collection is required.');
|
|
2287
2410
|
}
|
|
2288
2411
|
dbName = resolveAssistantDatabaseName(input.database, input.mongo);
|
|
2289
2412
|
db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
|
|
@@ -2291,15 +2414,26 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2291
2414
|
case 1:
|
|
2292
2415
|
collectionResolution = _q.sent();
|
|
2293
2416
|
collection = collectionResolution.name || rawCollection;
|
|
2417
|
+
bridgeCollection = resolveAssistantReportBuilderBridgeCollection(collection);
|
|
2418
|
+
if (bridgeCollection.fallbackFrom) {
|
|
2419
|
+
collection = bridgeCollection.collection;
|
|
2420
|
+
}
|
|
2294
2421
|
schemaFields = getCollectionSchemaFieldNames(collection);
|
|
2295
2422
|
return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
|
|
2296
2423
|
case 2:
|
|
2297
2424
|
_a = _q.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
|
|
2298
2425
|
if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
|
|
2299
|
-
throw new Error('AI assistant
|
|
2426
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
2300
2427
|
}
|
|
2301
2428
|
customerId = normalizeOptionalString((_o = user === null || user === void 0 ? void 0 : user.other) === null || _o === void 0 ? void 0 : _o.id_customer);
|
|
2302
2429
|
fallbackMeta = {};
|
|
2430
|
+
if (bridgeCollection.fallbackFrom) {
|
|
2431
|
+
fallbackMeta.reportBuilderBridge = {
|
|
2432
|
+
from: bridgeCollection.fallbackFrom,
|
|
2433
|
+
to: collection,
|
|
2434
|
+
used: true
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2303
2437
|
baseQuery = normalizeMongoQuery(input.query);
|
|
2304
2438
|
if (!isSuperAdmin && customerId) {
|
|
2305
2439
|
stripped = stripQueryFieldPathsDeepWithMeta(baseQuery, ['id_customer', 'other.id_customer']);
|
|
@@ -2313,7 +2447,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2313
2447
|
if (!isSuperAdmin && (collection === 'users' || collection === 'user-versions')) {
|
|
2314
2448
|
userId = normalizeOptionalString(user === null || user === void 0 ? void 0 : user._id);
|
|
2315
2449
|
if (!userId) {
|
|
2316
|
-
throw new Error('AI assistant
|
|
2450
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
2317
2451
|
}
|
|
2318
2452
|
baseQuery = {
|
|
2319
2453
|
$and: [baseQuery, { _id: userId }]
|
|
@@ -2350,7 +2484,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2350
2484
|
limitedPipeline = applyAssistantAggregateLimit(pipelineWithScope, normalizedOptions.limit, normalizedOptions.maxLimit, normalizedOptions.defaultLimit);
|
|
2351
2485
|
dateField = findAggregateDateField(limitedPipeline);
|
|
2352
2486
|
if (containsForbiddenMongoOperators(limitedPipeline)) {
|
|
2353
|
-
throw new Error('AI assistant
|
|
2487
|
+
throw new Error('AI assistant report builder bridge: Pipeline contains restricted operators.');
|
|
2354
2488
|
}
|
|
2355
2489
|
aggregateOptions = __assign(__assign({}, normalizedOptions.aggregateOptions), { readPreference: AI_ASSISTANT_READ_PREFERENCE });
|
|
2356
2490
|
return [4 /*yield*/, db.collection(collection)
|
|
@@ -2878,6 +3012,7 @@ function executeAiAssistantMongoAggregate(payload, context) {
|
|
|
2878
3012
|
collectionMatched: collectionResolution.matched,
|
|
2879
3013
|
collectionCandidates: collectionResolution.candidates,
|
|
2880
3014
|
collectionScore: collectionResolution.score,
|
|
3015
|
+
bridge: 'report-builder',
|
|
2881
3016
|
database: dbName,
|
|
2882
3017
|
query: scopedQuery,
|
|
2883
3018
|
options: normalizedOptions.aggregateOptions,
|
|
@@ -2899,6 +3034,21 @@ function extractAssistantMongoDirective(content) {
|
|
|
2899
3034
|
lines.forEach(function (line, index) {
|
|
2900
3035
|
var normalized = line.trim().replace(/^[-*]+\s*/, '');
|
|
2901
3036
|
var upper = normalized.toUpperCase();
|
|
3037
|
+
if (upper.startsWith('REPORT_BUILDER_READ:')) {
|
|
3038
|
+
directiveIndexes.add(index);
|
|
3039
|
+
directiveIndex = index;
|
|
3040
|
+
directiveLine = normalized;
|
|
3041
|
+
directiveType = 'read';
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
3044
|
+
if (upper.startsWith('REPORT_BUILDER_AGG:') || upper.startsWith('REPORT_BUILDER_AGGREGATE:')) {
|
|
3045
|
+
directiveIndexes.add(index);
|
|
3046
|
+
directiveIndex = index;
|
|
3047
|
+
directiveLine = normalized;
|
|
3048
|
+
directiveType = 'aggregate';
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
// Backward compatibility for existing assistant responses.
|
|
2902
3052
|
if (upper.startsWith('MONGO_READ:')) {
|
|
2903
3053
|
directiveIndexes.add(index);
|
|
2904
3054
|
directiveIndex = index;
|
|
@@ -3018,7 +3168,7 @@ function buildAssistantCodexToolFollowupPrompt(message, attachmentText, historyT
|
|
|
3018
3168
|
var trimmedHistory = normalizeOptionalString(historyText);
|
|
3019
3169
|
var historyBlock = trimmedHistory ? "\n\nConversation so far:\n".concat(trimmedHistory) : '';
|
|
3020
3170
|
var toolBlock = toolResultText ? "\n\nTool Result:\n".concat(toolResultText) : '';
|
|
3021
|
-
var instruction = '\n\nInstruction:\nNow answer the user. Do NOT output another
|
|
3171
|
+
var instruction = '\n\nInstruction:\nNow answer the user. Do NOT output another REPORT_BUILDER_* directive. Output plain Markdown. Summarize first, then include a Markdown table.';
|
|
3022
3172
|
return "System:\n".concat(AI_ASSISTANT_SYSTEM_PROMPT).concat(contextBlock).concat(historyBlock, "\n\nUser:\n").concat(message).concat(attachmentText || '').concat(toolBlock).concat(instruction).trim();
|
|
3023
3173
|
}
|
|
3024
3174
|
function buildAssistantToolFallbackResponse(result) {
|
|
@@ -3038,13 +3188,13 @@ function buildAssistantToolFallbackResponse(result) {
|
|
|
3038
3188
|
return lines.join('\n').trim();
|
|
3039
3189
|
}
|
|
3040
3190
|
function buildAssistantDebugPayload(params) {
|
|
3041
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
|
|
3191
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
|
|
3042
3192
|
var notes = [];
|
|
3043
3193
|
if (params.dataQuestion) {
|
|
3044
3194
|
notes.push('Detected a data request; tool call required.');
|
|
3045
3195
|
}
|
|
3046
3196
|
if (params.directiveSource === 'forced') {
|
|
3047
|
-
notes.push('Assistant response omitted a
|
|
3197
|
+
notes.push('Assistant response omitted a REPORT_BUILDER_* directive; ran a directive-only pass.');
|
|
3048
3198
|
}
|
|
3049
3199
|
if ((_a = params.collectionOverride) === null || _a === void 0 ? void 0 : _a.to) {
|
|
3050
3200
|
var from = params.collectionOverride.from ? "\"".concat(params.collectionOverride.from, "\"") : '(none)';
|
|
@@ -3139,19 +3289,24 @@ function buildAssistantDebugPayload(params) {
|
|
|
3139
3289
|
var collection = fallbackInfo.chemicalLookup.collection ? " in ".concat(fallbackInfo.chemicalLookup.collection) : '';
|
|
3140
3290
|
notes.push("Applied chemical lookup".concat(collection, "."));
|
|
3141
3291
|
}
|
|
3142
|
-
if ((_u = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.
|
|
3292
|
+
if ((_u = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportBuilderBridge) === null || _u === void 0 ? void 0 : _u.used) {
|
|
3293
|
+
var from = fallbackInfo.reportBuilderBridge.from || 'unknown';
|
|
3294
|
+
var to = fallbackInfo.reportBuilderBridge.to || 'unknown';
|
|
3295
|
+
notes.push("Report builder bridge collection: ".concat(from, " -> ").concat(to, "."));
|
|
3296
|
+
}
|
|
3297
|
+
if ((_v = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.reportFallback) === null || _v === void 0 ? void 0 : _v.used) {
|
|
3143
3298
|
var from = fallbackInfo.reportFallback.from || 'report';
|
|
3144
3299
|
var to = fallbackInfo.reportFallback.to || 'base';
|
|
3145
3300
|
notes.push("Report fallback: ".concat(from, " -> ").concat(to, "."));
|
|
3146
3301
|
}
|
|
3147
|
-
if ((
|
|
3302
|
+
if ((_w = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idLookup) === null || _w === void 0 ? void 0 : _w.used) {
|
|
3148
3303
|
var field = fallbackInfo.idLookup.field || 'id';
|
|
3149
3304
|
var strategy = fallbackInfo.idLookup.strategy || 'lookup';
|
|
3150
3305
|
var collection = fallbackInfo.idLookup.collection ? " in ".concat(fallbackInfo.idLookup.collection) : '';
|
|
3151
3306
|
var detail = fallbackInfo.idLookup.nameField ? " via ".concat(fallbackInfo.idLookup.nameField) : '';
|
|
3152
3307
|
notes.push("Resolved ".concat(field, " by ").concat(strategy).concat(collection).concat(detail, "."));
|
|
3153
3308
|
}
|
|
3154
|
-
if ((
|
|
3309
|
+
if ((_x = fallbackInfo === null || fallbackInfo === void 0 ? void 0 : fallbackInfo.idDisplayLookup) === null || _x === void 0 ? void 0 : _x.used) {
|
|
3155
3310
|
var lookups = Array.isArray(fallbackInfo.idDisplayLookup.lookups)
|
|
3156
3311
|
? fallbackInfo.idDisplayLookup.lookups
|
|
3157
3312
|
: [];
|
|
@@ -3162,7 +3317,7 @@ function buildAssistantDebugPayload(params) {
|
|
|
3162
3317
|
notes.push(summary ? "Resolved id lookups for display: ".concat(summary, ".") : 'Resolved id lookups for display.');
|
|
3163
3318
|
}
|
|
3164
3319
|
if (params.toolError) {
|
|
3165
|
-
var errorMessage = ((
|
|
3320
|
+
var errorMessage = ((_y = params.toolError) === null || _y === void 0 ? void 0 : _y.message) || String(params.toolError || '');
|
|
3166
3321
|
if (errorMessage) {
|
|
3167
3322
|
notes.push("Tool error: ".concat(errorMessage));
|
|
3168
3323
|
}
|
|
@@ -3183,13 +3338,13 @@ function buildAssistantDebugPayload(params) {
|
|
|
3183
3338
|
collectionResolved: resolvedCollection || undefined,
|
|
3184
3339
|
collectionMatched: matchedCollection,
|
|
3185
3340
|
collectionCandidates: candidateCollections.length ? candidateCollections : undefined,
|
|
3186
|
-
collectionScore: typeof ((
|
|
3341
|
+
collectionScore: typeof ((_z = params.toolResponseDebug) === null || _z === void 0 ? void 0 : _z.collectionScore) === 'number'
|
|
3187
3342
|
? params.toolResponseDebug.collectionScore
|
|
3188
3343
|
: undefined,
|
|
3189
|
-
query: ((
|
|
3190
|
-
pipeline: ((
|
|
3191
|
-
options: ((
|
|
3192
|
-
fallbacks: ((
|
|
3344
|
+
query: ((_0 = params.toolResponseDebug) === null || _0 === void 0 ? void 0 : _0.query) || undefined,
|
|
3345
|
+
pipeline: ((_1 = params.toolResponseDebug) === null || _1 === void 0 ? void 0 : _1.executedPipeline) || ((_2 = params.toolResponseDebug) === null || _2 === void 0 ? void 0 : _2.originalPipeline) || undefined,
|
|
3346
|
+
options: ((_3 = params.toolResponseDebug) === null || _3 === void 0 ? void 0 : _3.options) || undefined,
|
|
3347
|
+
fallbacks: ((_4 = params.toolResponseDebug) === null || _4 === void 0 ? void 0 : _4.fallbacks) || undefined,
|
|
3193
3348
|
notes: notes
|
|
3194
3349
|
};
|
|
3195
3350
|
if (params.trace && typeof params.trace === 'object') {
|
|
@@ -3222,6 +3377,9 @@ function buildAssistantToolErrorMessage(error, directive, request) {
|
|
|
3222
3377
|
if (normalized.includes('database access denied')) {
|
|
3223
3378
|
return "Database access is restricted for that request. ".concat(routeLine);
|
|
3224
3379
|
}
|
|
3380
|
+
if (normalized.includes('report builder bridge') && normalized.includes('not configured')) {
|
|
3381
|
+
return "That dataset is not configured for report builder access yet. ".concat(routeLine);
|
|
3382
|
+
}
|
|
3225
3383
|
if (normalized.includes('collection is required')) {
|
|
3226
3384
|
return 'I need a valid collection to read from. Please specify which screen or dataset you want.';
|
|
3227
3385
|
}
|
|
@@ -4916,30 +5074,30 @@ function ensureAssistantReadAccess(context, permissionView, collection) {
|
|
|
4916
5074
|
case 0:
|
|
4917
5075
|
idUser = context === null || context === void 0 ? void 0 : context.id_user;
|
|
4918
5076
|
if (!idUser) {
|
|
4919
|
-
throw new Error('AI assistant
|
|
5077
|
+
throw new Error('AI assistant report builder bridge: Unauthorized.');
|
|
4920
5078
|
}
|
|
4921
5079
|
return [4 /*yield*/, user_collection_1.Users.findById(idUser)];
|
|
4922
5080
|
case 1:
|
|
4923
5081
|
user = _b.sent();
|
|
4924
5082
|
if (!user) {
|
|
4925
|
-
throw new Error('AI assistant
|
|
5083
|
+
throw new Error('AI assistant report builder bridge: Unauthorized.');
|
|
4926
5084
|
}
|
|
4927
5085
|
isSuperAdmin = !!((_a = user === null || user === void 0 ? void 0 : user.roles) === null || _a === void 0 ? void 0 : _a.super_admin);
|
|
4928
5086
|
normalizedPermission = normalizeOptionalString(permissionView);
|
|
4929
5087
|
if (!isSuperAdmin) {
|
|
4930
5088
|
if (!normalizedPermission) {
|
|
4931
|
-
throw new Error('AI assistant
|
|
5089
|
+
throw new Error('AI assistant report builder bridge: Permission scope required.');
|
|
4932
5090
|
}
|
|
4933
5091
|
if (!userHasViewPermission(user, normalizedPermission)) {
|
|
4934
|
-
throw new Error('AI assistant
|
|
5092
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
4935
5093
|
}
|
|
4936
5094
|
normalizedCollection = normalizeOptionalString(collection);
|
|
4937
5095
|
if (normalizedCollection && requiresInvoicePermission(normalizedCollection) && !userHasInvoiceAccess(user)) {
|
|
4938
|
-
throw new Error('AI assistant
|
|
5096
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
4939
5097
|
}
|
|
4940
5098
|
}
|
|
4941
5099
|
else if (normalizedPermission && !userHasViewPermission(user, normalizedPermission)) {
|
|
4942
|
-
throw new Error('AI assistant
|
|
5100
|
+
throw new Error('AI assistant report builder bridge: Access denied.');
|
|
4943
5101
|
}
|
|
4944
5102
|
return [2 /*return*/, { user: user, isSuperAdmin: isSuperAdmin }];
|
|
4945
5103
|
}
|
|
@@ -4951,17 +5109,17 @@ function resolveAssistantDatabaseName(database, mongoConfig) {
|
|
|
4951
5109
|
var defaultDb = normalizeOptionalString(mongoConfig === null || mongoConfig === void 0 ? void 0 : mongoConfig.database) || ((_a = resolveio_server_app_1.ResolveIOServer.getServerConfig()) === null || _a === void 0 ? void 0 : _a.DATABASE) || '';
|
|
4952
5110
|
var dbName = normalizeOptionalString(database) || defaultDb;
|
|
4953
5111
|
if (!dbName) {
|
|
4954
|
-
throw new Error('AI assistant
|
|
5112
|
+
throw new Error('AI assistant report builder bridge: Database is required.');
|
|
4955
5113
|
}
|
|
4956
5114
|
var allowedFromConfig = Array.isArray(mongoConfig === null || mongoConfig === void 0 ? void 0 : mongoConfig.databases)
|
|
4957
5115
|
? mongoConfig === null || mongoConfig === void 0 ? void 0 : mongoConfig.databases.map(function (value) { return normalizeOptionalString(value); }).filter(Boolean)
|
|
4958
5116
|
: [];
|
|
4959
5117
|
if (allowedFromConfig.length && !allowedFromConfig.includes(dbName)) {
|
|
4960
|
-
throw new Error('AI assistant
|
|
5118
|
+
throw new Error('AI assistant report builder bridge: Database access denied.');
|
|
4961
5119
|
}
|
|
4962
5120
|
var allowedDatabases = ((_b = resolveio_server_app_1.ResolveIOServer.getMongoManager()) === null || _b === void 0 ? void 0 : _b.getWatchedDatabases()) || [];
|
|
4963
5121
|
if (allowedDatabases.length && !allowedDatabases.includes(dbName)) {
|
|
4964
|
-
throw new Error('AI assistant
|
|
5122
|
+
throw new Error('AI assistant report builder bridge: Database access denied.');
|
|
4965
5123
|
}
|
|
4966
5124
|
return dbName;
|
|
4967
5125
|
}
|
|
@@ -6806,7 +6964,7 @@ function replaceAggregateDateField(pipeline, fromField, toField) {
|
|
|
6806
6964
|
function normalizeMongoQuery(query) {
|
|
6807
6965
|
var normalized = query && typeof query === 'object' ? query : {};
|
|
6808
6966
|
if (containsForbiddenMongoOperators(normalized)) {
|
|
6809
|
-
throw new Error('AI assistant
|
|
6967
|
+
throw new Error('AI assistant report builder bridge: Query contains restricted operators.');
|
|
6810
6968
|
}
|
|
6811
6969
|
var rewritten = rewriteEmbeddedMatchObjects(normalized);
|
|
6812
6970
|
return applyAssistantNameRegexToQuery(rewritten);
|
|
@@ -7073,9 +7231,33 @@ function expandAssistantTermSynonyms(text) {
|
|
|
7073
7231
|
});
|
|
7074
7232
|
return { expanded: expanded, matches: matches };
|
|
7075
7233
|
}
|
|
7234
|
+
function listAssistantReportBuilderCollectionsFromManager() {
|
|
7235
|
+
var _a;
|
|
7236
|
+
var manager = (_a = resolveio_server_app_1.ResolveIOServer.getMongoManager) === null || _a === void 0 ? void 0 : _a.call(resolveio_server_app_1.ResolveIOServer);
|
|
7237
|
+
var collectionModels = manager && typeof manager.collections === 'function'
|
|
7238
|
+
? manager.collections()
|
|
7239
|
+
: [];
|
|
7240
|
+
if (!Array.isArray(collectionModels) || !collectionModels.length) {
|
|
7241
|
+
return [];
|
|
7242
|
+
}
|
|
7243
|
+
var seen = new Set();
|
|
7244
|
+
var names = [];
|
|
7245
|
+
collectionModels.forEach(function (model) {
|
|
7246
|
+
if (!(model === null || model === void 0 ? void 0 : model.useRB)) {
|
|
7247
|
+
return;
|
|
7248
|
+
}
|
|
7249
|
+
var name = normalizeOptionalString(model === null || model === void 0 ? void 0 : model.collectionName);
|
|
7250
|
+
if (!name || seen.has(name)) {
|
|
7251
|
+
return;
|
|
7252
|
+
}
|
|
7253
|
+
seen.add(name);
|
|
7254
|
+
names.push(name);
|
|
7255
|
+
});
|
|
7256
|
+
return names;
|
|
7257
|
+
}
|
|
7076
7258
|
function listAssistantCollections(db, dbName) {
|
|
7077
7259
|
return __awaiter(this, void 0, void 0, function () {
|
|
7078
|
-
var cacheKey, cached, now, collections, names, _a;
|
|
7260
|
+
var cacheKey, cached, now, reportBuilderCollections, collections, names, _a;
|
|
7079
7261
|
return __generator(this, function (_b) {
|
|
7080
7262
|
switch (_b.label) {
|
|
7081
7263
|
case 0:
|
|
@@ -7085,6 +7267,11 @@ function listAssistantCollections(db, dbName) {
|
|
|
7085
7267
|
if (cached && now - cached.updatedAt < AI_ASSISTANT_COLLECTION_CACHE_TTL_MS) {
|
|
7086
7268
|
return [2 /*return*/, cached.names];
|
|
7087
7269
|
}
|
|
7270
|
+
reportBuilderCollections = listAssistantReportBuilderCollectionsFromManager().sort(function (a, b) { return a.localeCompare(b); });
|
|
7271
|
+
if (reportBuilderCollections.length) {
|
|
7272
|
+
AI_ASSISTANT_COLLECTION_CACHE.set(cacheKey, { names: reportBuilderCollections, updatedAt: now });
|
|
7273
|
+
return [2 /*return*/, reportBuilderCollections];
|
|
7274
|
+
}
|
|
7088
7275
|
_b.label = 1;
|
|
7089
7276
|
case 1:
|
|
7090
7277
|
_b.trys.push([1, 3, , 4]);
|
|
@@ -7491,6 +7678,36 @@ function resolveAssistantCollectionName(db, dbName, requested) {
|
|
|
7491
7678
|
});
|
|
7492
7679
|
});
|
|
7493
7680
|
}
|
|
7681
|
+
function resolveAssistantReportBuilderBridgeCollection(collection) {
|
|
7682
|
+
var _a;
|
|
7683
|
+
var normalized = normalizeOptionalString(collection);
|
|
7684
|
+
if (!normalized) {
|
|
7685
|
+
throw new Error('AI assistant report builder bridge: Collection is required.');
|
|
7686
|
+
}
|
|
7687
|
+
var manager = (_a = resolveio_server_app_1.ResolveIOServer.getMongoManager) === null || _a === void 0 ? void 0 : _a.call(resolveio_server_app_1.ResolveIOServer);
|
|
7688
|
+
if (!manager || typeof manager.collection !== 'function') {
|
|
7689
|
+
throw new Error('AI assistant report builder bridge: Mongo manager unavailable.');
|
|
7690
|
+
}
|
|
7691
|
+
var directModel = manager.collection(normalized);
|
|
7692
|
+
if (directModel === null || directModel === void 0 ? void 0 : directModel.useRB) {
|
|
7693
|
+
return { collection: normalized };
|
|
7694
|
+
}
|
|
7695
|
+
var base = stripVersionSuffix(normalized.startsWith('report-') ? normalized.slice('report-'.length) : normalized);
|
|
7696
|
+
var reportCandidate = base ? "report-".concat(base) : '';
|
|
7697
|
+
if (reportCandidate && reportCandidate !== normalized) {
|
|
7698
|
+
var reportModel = manager.collection(reportCandidate);
|
|
7699
|
+
if (reportModel === null || reportModel === void 0 ? void 0 : reportModel.useRB) {
|
|
7700
|
+
return { collection: reportCandidate, fallbackFrom: normalized };
|
|
7701
|
+
}
|
|
7702
|
+
}
|
|
7703
|
+
if (base && base !== normalized) {
|
|
7704
|
+
var baseModel = manager.collection(base);
|
|
7705
|
+
if (baseModel === null || baseModel === void 0 ? void 0 : baseModel.useRB) {
|
|
7706
|
+
return { collection: base, fallbackFrom: normalized };
|
|
7707
|
+
}
|
|
7708
|
+
}
|
|
7709
|
+
throw new Error('AI assistant report builder bridge: Collection is not configured for report builder.');
|
|
7710
|
+
}
|
|
7494
7711
|
function findQueryDateField(query) {
|
|
7495
7712
|
var e_22, _a, e_23, _b;
|
|
7496
7713
|
if (!query || typeof query !== 'object') {
|
|
@@ -8555,7 +8772,7 @@ function buildAssistantCodexDirectivePrompt(message, attachmentText, historyText
|
|
|
8555
8772
|
var contextBlock = trimmedContext ? "\n\nContext:\n".concat(trimmedContext) : '';
|
|
8556
8773
|
var trimmedHistory = normalizeOptionalString(historyText);
|
|
8557
8774
|
var historyBlock = trimmedHistory ? "\n\nConversation so far:\n".concat(trimmedHistory) : '';
|
|
8558
|
-
var instruction = '\n\nInstruction:\nReturn ONLY a single
|
|
8775
|
+
var instruction = '\n\nInstruction:\nReturn ONLY a single REPORT_BUILDER_READ or REPORT_BUILDER_AGG directive line. Do not include any other text.';
|
|
8559
8776
|
return "System:\n".concat(AI_ASSISTANT_SYSTEM_PROMPT).concat(contextBlock).concat(historyBlock, "\n\nUser:\n").concat(message).concat(attachmentText || '').concat(instruction).trim();
|
|
8560
8777
|
}
|
|
8561
8778
|
function buildAssistantCodexPrompt(message, attachmentText, historyText, contextText) {
|