@praxisui/table 8.0.0-beta.86 → 8.0.0-beta.88
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/README.md +2 -0
- package/fesm2022/{praxisui-table-praxisui-table-CpSv6jWv.mjs → praxisui-table-praxisui-table-OCU_Au66.mjs} +95 -16
- package/fesm2022/{praxisui-table-table-agentic-authoring-turn-flow-Dhte2er9.mjs → praxisui-table-table-agentic-authoring-turn-flow-4Deh8QJU.mjs} +879 -10
- package/fesm2022/{praxisui-table-table-ai.adapter-BvgPN7wY.mjs → praxisui-table-table-ai.adapter-C8qa8APT.mjs} +117 -6
- package/fesm2022/praxisui-table.mjs +1 -1
- package/package.json +10 -10
- package/types/praxisui-table.d.ts +5 -0
|
@@ -301,6 +301,9 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
301
301
|
return this.selectedRecordSurfaces(contextHints).length > 0;
|
|
302
302
|
}
|
|
303
303
|
localRecommendedIntentResponse(request, contextHints) {
|
|
304
|
+
const declaredFilterConfirmation = this.localDeclaredFilterConfirmationResponse(request, contextHints);
|
|
305
|
+
if (declaredFilterConfirmation)
|
|
306
|
+
return declaredFilterConfirmation;
|
|
304
307
|
const declaredFilterClarification = this.localDeclaredFilterClarificationCompletionResponse(request, contextHints);
|
|
305
308
|
if (declaredFilterClarification)
|
|
306
309
|
return declaredFilterClarification;
|
|
@@ -559,6 +562,76 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
559
562
|
],
|
|
560
563
|
};
|
|
561
564
|
}
|
|
565
|
+
localDeclaredFilterConfirmationResponse(request, contextHints) {
|
|
566
|
+
const pendingClarification = request.pendingClarification
|
|
567
|
+
?? this.recoverDeclaredFilterConfirmationPendingClarificationFromMessages(request);
|
|
568
|
+
if (!pendingClarification)
|
|
569
|
+
return null;
|
|
570
|
+
if (request.action?.kind && !['clarify', 'submit'].includes(request.action.kind))
|
|
571
|
+
return null;
|
|
572
|
+
if (!this.runtimeOperationAllowed(contextHints, 'table.filter.apply'))
|
|
573
|
+
return null;
|
|
574
|
+
if (!this.pendingClarificationCanContinueDeclaredFilterApply(pendingClarification))
|
|
575
|
+
return null;
|
|
576
|
+
const normalizedPrompt = this.normalizeLabel([
|
|
577
|
+
request.action?.displayPrompt,
|
|
578
|
+
request.action?.value,
|
|
579
|
+
request.prompt,
|
|
580
|
+
].map((value) => this.stringValue(value)).filter(Boolean).join(' '));
|
|
581
|
+
if (!normalizedPrompt)
|
|
582
|
+
return null;
|
|
583
|
+
if (this.isShortNegativeClarificationAnswer(normalizedPrompt)) {
|
|
584
|
+
return {
|
|
585
|
+
type: 'info',
|
|
586
|
+
sessionId: request.sessionId,
|
|
587
|
+
message: 'Tudo bem, não alterei a tabela.',
|
|
588
|
+
warnings: [
|
|
589
|
+
'declared-filter-confirmation-cancelled-by-short-negative',
|
|
590
|
+
],
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
if (!this.isShortAffirmativeClarificationAnswer(normalizedPrompt))
|
|
594
|
+
return null;
|
|
595
|
+
const sourcePrompt = this.declaredFilterClarificationSourcePrompt(pendingClarification);
|
|
596
|
+
const normalizedGroundingPrompt = this.normalizeLabel([
|
|
597
|
+
sourcePrompt,
|
|
598
|
+
pendingClarification.assistantMessage,
|
|
599
|
+
].filter(Boolean).join(' '));
|
|
600
|
+
if (!normalizedGroundingPrompt || !this.promptRequestsRuntimeFilter(normalizedGroundingPrompt))
|
|
601
|
+
return null;
|
|
602
|
+
if (this.promptRequestsVisualOrStructuralEdit(normalizedGroundingPrompt))
|
|
603
|
+
return null;
|
|
604
|
+
const criteria = this.resolveDeclaredFilterConfirmationCriteria(normalizedGroundingPrompt, pendingClarification, contextHints);
|
|
605
|
+
if (!criteria || !Object.keys(criteria).length)
|
|
606
|
+
return null;
|
|
607
|
+
const completedCriteria = this.dedupeRuntimeFilterCriteriaAgainstDiscreteDimensions(this.completeRuntimeFilterCriteriaWithSelectedCandidates(criteria, {
|
|
608
|
+
...request,
|
|
609
|
+
prompt: sourcePrompt || pendingClarification.assistantMessage || request.prompt,
|
|
610
|
+
}));
|
|
611
|
+
return {
|
|
612
|
+
type: 'patch',
|
|
613
|
+
sessionId: request.sessionId,
|
|
614
|
+
patch: {
|
|
615
|
+
tableRuntimeOperations: {
|
|
616
|
+
kind: 'praxis.table.runtime-operation.batch',
|
|
617
|
+
source: 'declared-filter-confirmation-continuation',
|
|
618
|
+
operations: [{
|
|
619
|
+
operationId: 'table.filter.apply',
|
|
620
|
+
input: {
|
|
621
|
+
criteria: completedCriteria,
|
|
622
|
+
criteriaSemantics: 'simple-conjunction',
|
|
623
|
+
source: 'declared-filter-confirmation',
|
|
624
|
+
},
|
|
625
|
+
}],
|
|
626
|
+
},
|
|
627
|
+
},
|
|
628
|
+
explanation: 'Filtro confirmado a partir da clarificação anterior.',
|
|
629
|
+
warnings: [
|
|
630
|
+
'declared-filter-confirmation-continuation-materialized',
|
|
631
|
+
'A resposta curta confirmou uma clarificacao anterior ja ancorada em table.filter.apply e no filterFieldCatalog.',
|
|
632
|
+
],
|
|
633
|
+
};
|
|
634
|
+
}
|
|
562
635
|
localDeclaredFilterClarificationCompletionResponse(request, contextHints) {
|
|
563
636
|
const pendingClarification = request.pendingClarification
|
|
564
637
|
?? this.recoverDeclaredFilterPendingClarificationFromMessages(request);
|
|
@@ -568,7 +641,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
568
641
|
return null;
|
|
569
642
|
if (!this.runtimeOperationAllowed(contextHints, 'table.filter.apply'))
|
|
570
643
|
return null;
|
|
571
|
-
const sourcePrompt =
|
|
644
|
+
const sourcePrompt = this.declaredFilterClarificationSourcePrompt(pendingClarification);
|
|
572
645
|
if (!sourcePrompt)
|
|
573
646
|
return null;
|
|
574
647
|
const normalizedSourcePrompt = this.normalizeLabel(sourcePrompt);
|
|
@@ -578,9 +651,15 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
578
651
|
return null;
|
|
579
652
|
if (!this.pendingClarificationAsksForDeclaredFilter(request, pendingClarification))
|
|
580
653
|
return null;
|
|
654
|
+
if (this.declaredFilterClarificationResponseIsNewFilterRequest(request, contextHints))
|
|
655
|
+
return null;
|
|
581
656
|
const selectedEntry = this.filterFieldCatalogEntryForClarificationResponse(request, sourcePrompt);
|
|
582
|
-
if (!selectedEntry)
|
|
657
|
+
if (!selectedEntry) {
|
|
658
|
+
const unresolvedShortResponse = this.unresolvedDeclaredFilterShortConfirmationResponse(request, pendingClarification, sourcePrompt);
|
|
659
|
+
if (unresolvedShortResponse)
|
|
660
|
+
return unresolvedShortResponse;
|
|
583
661
|
return null;
|
|
662
|
+
}
|
|
584
663
|
const criteria = this.resolveDeclaredFilterCriteriaFromPrompt(normalizedSourcePrompt, contextHints) ?? {};
|
|
585
664
|
const clarified = this.resolveClarifiedFilterCriterionFromSourcePrompt(normalizedSourcePrompt, selectedEntry, contextHints, criteria);
|
|
586
665
|
if (!clarified)
|
|
@@ -616,6 +695,119 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
616
695
|
],
|
|
617
696
|
};
|
|
618
697
|
}
|
|
698
|
+
unresolvedDeclaredFilterShortConfirmationResponse(request, pendingClarification, sourcePrompt) {
|
|
699
|
+
const normalizedPrompt = this.normalizeLabel([
|
|
700
|
+
request.action?.displayPrompt,
|
|
701
|
+
request.action?.value,
|
|
702
|
+
request.prompt,
|
|
703
|
+
].map((value) => this.stringValue(value)).filter(Boolean).join(' '));
|
|
704
|
+
if (!normalizedPrompt)
|
|
705
|
+
return null;
|
|
706
|
+
if (this.isShortNegativeClarificationAnswer(normalizedPrompt)) {
|
|
707
|
+
return {
|
|
708
|
+
type: 'info',
|
|
709
|
+
sessionId: request.sessionId,
|
|
710
|
+
message: 'Tudo bem, não alterei a tabela. Você pode escolher um filtro ou fazer um novo pedido.',
|
|
711
|
+
warnings: [
|
|
712
|
+
'declared-filter-clarification-cancelled-by-short-negative',
|
|
713
|
+
],
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
if (!this.isShortAffirmativeClarificationAnswer(normalizedPrompt))
|
|
717
|
+
return null;
|
|
718
|
+
const optionPayloads = this.declaredFilterClarificationReminderOptionPayloads(request, pendingClarification, sourcePrompt);
|
|
719
|
+
if (optionPayloads.length <= 1)
|
|
720
|
+
return null;
|
|
721
|
+
return {
|
|
722
|
+
type: 'clarification',
|
|
723
|
+
sessionId: request.sessionId,
|
|
724
|
+
message: 'Ainda preciso que você escolha qual filtro deve receber esse critério antes de alterar a tabela.',
|
|
725
|
+
questions: ['Escolha uma das opções abaixo para continuar.'],
|
|
726
|
+
optionPayloads,
|
|
727
|
+
diagnostics: {
|
|
728
|
+
tableDeclaredFilterClarification: {
|
|
729
|
+
sourcePrompt,
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
warnings: [
|
|
733
|
+
'declared-filter-short-affirmative-needs-explicit-field-choice',
|
|
734
|
+
],
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
declaredFilterClarificationSourcePrompt(pendingClarification) {
|
|
738
|
+
const diagnostics = this.toRecord(pendingClarification?.diagnostics);
|
|
739
|
+
const declaredFilter = this.toRecord(diagnostics?.['tableDeclaredFilterClarification']);
|
|
740
|
+
const diagnosticSourcePrompt = this.stringValue(declaredFilter?.['sourcePrompt']).trim();
|
|
741
|
+
if (diagnosticSourcePrompt)
|
|
742
|
+
return diagnosticSourcePrompt;
|
|
743
|
+
return pendingClarification?.sourcePrompt?.trim() ?? '';
|
|
744
|
+
}
|
|
745
|
+
isShortAffirmativeClarificationAnswer(normalizedPrompt) {
|
|
746
|
+
return ['sim', 's', 'ok', 'okay', 'isso', 'pode', 'confirmo', 'confirmar']
|
|
747
|
+
.includes(normalizedPrompt);
|
|
748
|
+
}
|
|
749
|
+
isShortNegativeClarificationAnswer(normalizedPrompt) {
|
|
750
|
+
return ['nao', 'não', 'n', 'cancelar', 'cancela', 'deixa', 'deixa pra la', 'deixa pra lá']
|
|
751
|
+
.includes(normalizedPrompt);
|
|
752
|
+
}
|
|
753
|
+
declaredFilterClarificationReminderOptionPayloads(request, pendingClarification, sourcePrompt) {
|
|
754
|
+
const normalizedSourcePrompt = this.normalizeLabel(sourcePrompt);
|
|
755
|
+
const labels = [
|
|
756
|
+
...(pendingClarification?.questions ?? []).flatMap((question) => (question.options ?? []).map((option) => option.label || option.value || option.id)),
|
|
757
|
+
...this.declaredFilterQuickReplyOptions(normalizedSourcePrompt, {
|
|
758
|
+
...request,
|
|
759
|
+
prompt: sourcePrompt,
|
|
760
|
+
}),
|
|
761
|
+
]
|
|
762
|
+
.map((label) => this.stringValue(label).trim())
|
|
763
|
+
.filter((label) => !!label);
|
|
764
|
+
const seen = new Set();
|
|
765
|
+
return labels
|
|
766
|
+
.map((label) => this.filterFieldCatalogEntryForClarificationLabel(label) ?? {
|
|
767
|
+
name: label,
|
|
768
|
+
label: this.humanizeClarificationOptionLabel(label),
|
|
769
|
+
})
|
|
770
|
+
.filter((entry) => {
|
|
771
|
+
const key = this.normalizeLabel(entry.name || entry.label);
|
|
772
|
+
if (!key || seen.has(key))
|
|
773
|
+
return false;
|
|
774
|
+
seen.add(key);
|
|
775
|
+
return true;
|
|
776
|
+
})
|
|
777
|
+
.map((entry) => ({
|
|
778
|
+
label: entry.label,
|
|
779
|
+
value: entry.name,
|
|
780
|
+
contextHints: {
|
|
781
|
+
tableFilterClarification: {
|
|
782
|
+
source: 'declared-filter-field',
|
|
783
|
+
field: entry.name,
|
|
784
|
+
label: entry.label,
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
}));
|
|
788
|
+
}
|
|
789
|
+
declaredFilterClarificationResponseIsNewFilterRequest(request, contextHints) {
|
|
790
|
+
if (this.toRecord(request.action?.contextHints?.['tableFilterClarification']))
|
|
791
|
+
return false;
|
|
792
|
+
if (request.action?.kind === 'clarify')
|
|
793
|
+
return false;
|
|
794
|
+
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
795
|
+
if (!normalizedPrompt || !this.promptRequestsRuntimeFilter(normalizedPrompt))
|
|
796
|
+
return false;
|
|
797
|
+
if (this.promptRequestsVisualOrStructuralEdit(normalizedPrompt))
|
|
798
|
+
return false;
|
|
799
|
+
if (this.normalizedTextHasStandaloneToken(normalizedPrompt, 'agora'))
|
|
800
|
+
return true;
|
|
801
|
+
if (this.promptHasCompensationRangeIntent(normalizedPrompt) || this.promptHasDateRangeComparison(normalizedPrompt)) {
|
|
802
|
+
return true;
|
|
803
|
+
}
|
|
804
|
+
if (this.promptHasNumericRangeComparison(normalizedPrompt)
|
|
805
|
+
&& this.filterFieldCatalogEntries.filter((entry) => this.isNumericRangeFilterEntry(entry)).length === 1) {
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
const criteria = this.resolveDeclaredFilterCriteriaFromPrompt(normalizedPrompt, contextHints);
|
|
809
|
+
return !!criteria && Object.keys(criteria).length > 0;
|
|
810
|
+
}
|
|
619
811
|
pendingClarificationAsksForDeclaredFilter(request, pending) {
|
|
620
812
|
const hinted = this.toRecord(request.action?.contextHints?.['tableFilterClarification']);
|
|
621
813
|
if (hinted)
|
|
@@ -661,6 +853,78 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
661
853
|
}
|
|
662
854
|
return null;
|
|
663
855
|
}
|
|
856
|
+
recoverDeclaredFilterConfirmationPendingClarificationFromMessages(request) {
|
|
857
|
+
const messages = [...(request.messages ?? [])];
|
|
858
|
+
if (messages.length < 2)
|
|
859
|
+
return null;
|
|
860
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
861
|
+
const message = messages[index];
|
|
862
|
+
if (message.role !== 'assistant')
|
|
863
|
+
continue;
|
|
864
|
+
if (!this.pendingClarificationCanContinueDeclaredFilterApply({
|
|
865
|
+
assistantMessage: message.text,
|
|
866
|
+
sourcePrompt: '',
|
|
867
|
+
questions: [],
|
|
868
|
+
}))
|
|
869
|
+
continue;
|
|
870
|
+
const sourcePrompt = [...messages.slice(0, index)]
|
|
871
|
+
.reverse()
|
|
872
|
+
.find((candidate) => candidate.role === 'user')
|
|
873
|
+
?.text?.trim();
|
|
874
|
+
if (!sourcePrompt)
|
|
875
|
+
return null;
|
|
876
|
+
return {
|
|
877
|
+
sourcePrompt,
|
|
878
|
+
assistantMessage: message.text,
|
|
879
|
+
questions: [],
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
return null;
|
|
883
|
+
}
|
|
884
|
+
pendingClarificationConfirmsDeclaredFilterApply(pending) {
|
|
885
|
+
const text = this.normalizeLabel([
|
|
886
|
+
pending?.assistantMessage,
|
|
887
|
+
...(pending?.questions ?? []).map((question) => [
|
|
888
|
+
question.label,
|
|
889
|
+
...(question.options ?? []).map((option) => option.label),
|
|
890
|
+
].flat().join(' ')),
|
|
891
|
+
].filter(Boolean).join(' '));
|
|
892
|
+
if (!text)
|
|
893
|
+
return false;
|
|
894
|
+
const asksConfirmation = text.includes('confirma')
|
|
895
|
+
|| text.includes('confirmar')
|
|
896
|
+
|| text.includes('posso filtrar')
|
|
897
|
+
|| text.includes('aplique esse filtro')
|
|
898
|
+
|| text.includes('aplicar esse filtro');
|
|
899
|
+
const mentionsRuntimeFilter = text.includes('filtrar')
|
|
900
|
+
|| text.includes('filtro')
|
|
901
|
+
|| text.includes('apenas funcionarios')
|
|
902
|
+
|| text.includes('apenas funcionários');
|
|
903
|
+
return asksConfirmation && mentionsRuntimeFilter;
|
|
904
|
+
}
|
|
905
|
+
pendingClarificationCanContinueDeclaredFilterApply(pending) {
|
|
906
|
+
return this.pendingClarificationConfirmsDeclaredFilterApply(pending)
|
|
907
|
+
|| this.pendingClarificationDeclaresDeclaredFilterApply(pending);
|
|
908
|
+
}
|
|
909
|
+
pendingClarificationDeclaresDeclaredFilterApply(pending) {
|
|
910
|
+
const text = this.normalizeLabel([
|
|
911
|
+
pending?.assistantMessage,
|
|
912
|
+
...(pending?.questions ?? []).map((question) => [
|
|
913
|
+
question.label,
|
|
914
|
+
...(question.options ?? []).map((option) => option.label),
|
|
915
|
+
].flat().join(' ')),
|
|
916
|
+
].filter(Boolean).join(' '));
|
|
917
|
+
if (!text)
|
|
918
|
+
return false;
|
|
919
|
+
const declaresRuntimeOperation = text.includes('table.filter.apply')
|
|
920
|
+
|| text.includes('operacao table filter apply')
|
|
921
|
+
|| text.includes('operação table filter apply');
|
|
922
|
+
const declaresFiltering = text.includes('vou filtrar')
|
|
923
|
+
|| text.includes('filtrar a tabela')
|
|
924
|
+
|| text.includes('executando operacao')
|
|
925
|
+
|| text.includes('executando operação');
|
|
926
|
+
return declaresRuntimeOperation && declaresFiltering;
|
|
927
|
+
}
|
|
664
928
|
filterFieldCatalogEntryForClarificationResponse(request, sourcePrompt) {
|
|
665
929
|
const hinted = this.toRecord(request.action?.contextHints?.['tableFilterClarification']);
|
|
666
930
|
const hintedField = this.stringValue(hinted?.['field']);
|
|
@@ -746,12 +1010,60 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
746
1010
|
const token = this.ungroundedFilterValueTokens(normalizedSourcePrompt, entry, criteria)[0];
|
|
747
1011
|
return token ? this.restoreFilterValueToken(token, normalizedSourcePrompt) : '';
|
|
748
1012
|
}
|
|
1013
|
+
resolveImplicitTextCriteriaFromValueHints(normalizedPrompt, criteria) {
|
|
1014
|
+
if (!normalizedPrompt)
|
|
1015
|
+
return;
|
|
1016
|
+
const matches = this.filterFieldCatalogEntries
|
|
1017
|
+
.filter((entry) => criteria[entry.name] === undefined)
|
|
1018
|
+
.filter((entry) => this.isTextualFilterCriterion(entry))
|
|
1019
|
+
.map((entry) => ({
|
|
1020
|
+
entry,
|
|
1021
|
+
match: this.bestFilterValueHintMatch(normalizedPrompt, entry),
|
|
1022
|
+
}))
|
|
1023
|
+
.filter((candidate) => !!candidate.match)
|
|
1024
|
+
.sort((left, right) => right.match.score - left.match.score || left.entry.label.localeCompare(right.entry.label));
|
|
1025
|
+
if (!matches.length)
|
|
1026
|
+
return;
|
|
1027
|
+
const topScore = matches[0].match.score;
|
|
1028
|
+
const winners = matches.filter((candidate) => candidate.match.score === topScore);
|
|
1029
|
+
if (winners.length !== 1)
|
|
1030
|
+
return;
|
|
1031
|
+
criteria[winners[0].entry.name] = this.normalizeRuntimeFilterCriterionForCatalogEntry(winners[0].match.value, winners[0].entry);
|
|
1032
|
+
}
|
|
1033
|
+
bestFilterValueHintMatch(normalizedPrompt, entry) {
|
|
1034
|
+
let best = null;
|
|
1035
|
+
for (const hint of entry.valueHints) {
|
|
1036
|
+
for (const candidate of this.filterValueHintCandidates(hint)) {
|
|
1037
|
+
const normalizedCandidate = this.normalizeLabel(candidate);
|
|
1038
|
+
if (!normalizedCandidate || normalizedCandidate.length < 4)
|
|
1039
|
+
continue;
|
|
1040
|
+
if (!this.normalizedTextContainsApproxPhrase(normalizedPrompt, normalizedCandidate))
|
|
1041
|
+
continue;
|
|
1042
|
+
const score = normalizedCandidate.split(/\s+/u).length * 25 + normalizedCandidate.length;
|
|
1043
|
+
if (!best || score > best.score) {
|
|
1044
|
+
best = { value: candidate, score };
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
return best;
|
|
1049
|
+
}
|
|
1050
|
+
filterValueHintCandidates(hint) {
|
|
1051
|
+
const trimmed = hint.trim();
|
|
1052
|
+
if (!trimmed)
|
|
1053
|
+
return [];
|
|
1054
|
+
const candidates = new Set([trimmed]);
|
|
1055
|
+
const prefix = trimmed.split(/\s+-\s+/u)[0]?.trim();
|
|
1056
|
+
if (prefix && prefix.length >= 4)
|
|
1057
|
+
candidates.add(prefix);
|
|
1058
|
+
return [...candidates];
|
|
1059
|
+
}
|
|
749
1060
|
ungroundedFilterValueTokens(normalizedPrompt, entry, criteria) {
|
|
750
1061
|
const ignoredTokens = new Set([
|
|
751
1062
|
'filtra',
|
|
752
1063
|
'filtrar',
|
|
753
1064
|
'filtre',
|
|
754
1065
|
'filtro',
|
|
1066
|
+
'agora',
|
|
755
1067
|
'quero',
|
|
756
1068
|
'ver',
|
|
757
1069
|
'mostra',
|
|
@@ -762,6 +1074,26 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
762
1074
|
'busca',
|
|
763
1075
|
'procura',
|
|
764
1076
|
'procurar',
|
|
1077
|
+
'confirma',
|
|
1078
|
+
'confirmar',
|
|
1079
|
+
'aplique',
|
|
1080
|
+
'aplicar',
|
|
1081
|
+
'posso',
|
|
1082
|
+
'para',
|
|
1083
|
+
'eu',
|
|
1084
|
+
'esse',
|
|
1085
|
+
'essa',
|
|
1086
|
+
'tabela',
|
|
1087
|
+
'funcionario',
|
|
1088
|
+
'funcionarios',
|
|
1089
|
+
'funcionário',
|
|
1090
|
+
'funcionários',
|
|
1091
|
+
'qualquer',
|
|
1092
|
+
'qq',
|
|
1093
|
+
'depto',
|
|
1094
|
+
'departamento',
|
|
1095
|
+
'departamentos',
|
|
1096
|
+
'serve',
|
|
765
1097
|
'de',
|
|
766
1098
|
'do',
|
|
767
1099
|
'da',
|
|
@@ -805,6 +1137,18 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
805
1137
|
'admitidas',
|
|
806
1138
|
'admitiu',
|
|
807
1139
|
'admitiram',
|
|
1140
|
+
'ganha',
|
|
1141
|
+
'ganham',
|
|
1142
|
+
'ganhando',
|
|
1143
|
+
'recebe',
|
|
1144
|
+
'recebem',
|
|
1145
|
+
'recebendo',
|
|
1146
|
+
'remuneracao',
|
|
1147
|
+
'remuneração',
|
|
1148
|
+
'pagamento',
|
|
1149
|
+
'folha',
|
|
1150
|
+
'salario',
|
|
1151
|
+
'salário',
|
|
808
1152
|
].map((token) => this.normalizeLabel(token)));
|
|
809
1153
|
const fieldMentionTokens = new Set([
|
|
810
1154
|
entry.name,
|
|
@@ -848,8 +1192,41 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
848
1192
|
}
|
|
849
1193
|
unresolvedFilterCriterionOptions(normalizedPrompt, criteria) {
|
|
850
1194
|
const usedFields = new Set(Object.keys(criteria));
|
|
851
|
-
const
|
|
1195
|
+
const hasSymbolicFilterValue = normalizedPrompt
|
|
1196
|
+
.split(/\s+/u)
|
|
1197
|
+
.some((token) => token.length >= 2
|
|
1198
|
+
&& /[&/+.]/u.test(token)
|
|
1199
|
+
&& !this.tokenIsGroundedByAppliedCriteria(token, criteria));
|
|
1200
|
+
const hasUnresolvedDiscreteFilter = this.promptContainsMentionedUnresolvedDiscreteFilter(normalizedPrompt, criteria);
|
|
1201
|
+
const narrowsByValueShape = !hasSymbolicFilterValue
|
|
1202
|
+
&& !hasUnresolvedDiscreteFilter
|
|
1203
|
+
&& (this.promptHasCompensationRangeIntent(normalizedPrompt)
|
|
1204
|
+
|| this.promptHasNumericRangeComparison(normalizedPrompt)
|
|
1205
|
+
|| this.promptHasDateRangeComparison(normalizedPrompt));
|
|
1206
|
+
const candidateEntries = this.filterFieldCatalogEntries
|
|
852
1207
|
.filter((entry) => !usedFields.has(entry.name))
|
|
1208
|
+
.filter((entry) => !this.promptMentionsFilterFieldAsNonRestrictiveScope(normalizedPrompt, entry))
|
|
1209
|
+
.filter((entry) => {
|
|
1210
|
+
if (!narrowsByValueShape)
|
|
1211
|
+
return true;
|
|
1212
|
+
if (this.promptHasCompensationRangeIntent(normalizedPrompt)) {
|
|
1213
|
+
return this.isCompensationRangeFilterEntry(entry);
|
|
1214
|
+
}
|
|
1215
|
+
if (this.promptHasNumericRangeComparison(normalizedPrompt)) {
|
|
1216
|
+
return this.isNumericRangeFilterEntry(entry);
|
|
1217
|
+
}
|
|
1218
|
+
if (this.promptHasDateRangeComparison(normalizedPrompt)) {
|
|
1219
|
+
return this.isDateRangeFilterEntry(entry);
|
|
1220
|
+
}
|
|
1221
|
+
return true;
|
|
1222
|
+
});
|
|
1223
|
+
if (narrowsByValueShape && !candidateEntries.length) {
|
|
1224
|
+
return [];
|
|
1225
|
+
}
|
|
1226
|
+
const fallbackEntries = this.filterFieldCatalogEntries
|
|
1227
|
+
.filter((entry) => !usedFields.has(entry.name))
|
|
1228
|
+
.filter((entry) => !this.promptMentionsFilterFieldAsNonRestrictiveScope(normalizedPrompt, entry));
|
|
1229
|
+
const ranked = (candidateEntries.length ? candidateEntries : fallbackEntries)
|
|
853
1230
|
.map((entry) => ({
|
|
854
1231
|
entry,
|
|
855
1232
|
score: this.selectedRecordFilterValuePromptScore(entry, normalizedPrompt)
|
|
@@ -920,6 +1297,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
920
1297
|
...entry.aliases,
|
|
921
1298
|
...entry.relatedColumnFields,
|
|
922
1299
|
...entry.relatedColumnLabels,
|
|
1300
|
+
...entry.valueHints,
|
|
923
1301
|
...displayValues,
|
|
924
1302
|
];
|
|
925
1303
|
return values.some((value) => value && this.promptContainsAnyVariant(token, value));
|
|
@@ -937,7 +1315,9 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
937
1315
|
'filtrar',
|
|
938
1316
|
'filtre',
|
|
939
1317
|
'filtro',
|
|
1318
|
+
'agora',
|
|
940
1319
|
'quero',
|
|
1320
|
+
'quem',
|
|
941
1321
|
'ver',
|
|
942
1322
|
'mostra',
|
|
943
1323
|
'mostrar',
|
|
@@ -947,6 +1327,26 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
947
1327
|
'busca',
|
|
948
1328
|
'procura',
|
|
949
1329
|
'procurar',
|
|
1330
|
+
'confirma',
|
|
1331
|
+
'confirmar',
|
|
1332
|
+
'aplique',
|
|
1333
|
+
'aplicar',
|
|
1334
|
+
'posso',
|
|
1335
|
+
'para',
|
|
1336
|
+
'eu',
|
|
1337
|
+
'esse',
|
|
1338
|
+
'essa',
|
|
1339
|
+
'tabela',
|
|
1340
|
+
'funcionario',
|
|
1341
|
+
'funcionarios',
|
|
1342
|
+
'funcionário',
|
|
1343
|
+
'funcionários',
|
|
1344
|
+
'qualquer',
|
|
1345
|
+
'qq',
|
|
1346
|
+
'depto',
|
|
1347
|
+
'departamento',
|
|
1348
|
+
'departamentos',
|
|
1349
|
+
'serve',
|
|
950
1350
|
'de',
|
|
951
1351
|
'do',
|
|
952
1352
|
'da',
|
|
@@ -990,6 +1390,18 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
990
1390
|
'admitidas',
|
|
991
1391
|
'admitiu',
|
|
992
1392
|
'admitiram',
|
|
1393
|
+
'ganha',
|
|
1394
|
+
'ganham',
|
|
1395
|
+
'ganhando',
|
|
1396
|
+
'recebe',
|
|
1397
|
+
'recebem',
|
|
1398
|
+
'recebendo',
|
|
1399
|
+
'remuneracao',
|
|
1400
|
+
'remuneração',
|
|
1401
|
+
'pagamento',
|
|
1402
|
+
'folha',
|
|
1403
|
+
'salario',
|
|
1404
|
+
'salário',
|
|
993
1405
|
].map((token) => this.normalizeLabel(token)));
|
|
994
1406
|
const fieldMentionTokens = new Set([
|
|
995
1407
|
entry.name,
|
|
@@ -1023,12 +1435,14 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1023
1435
|
? selectedCandidate['displayValues'].map((value) => this.stringValue(value)).filter((value) => !!value)
|
|
1024
1436
|
: [];
|
|
1025
1437
|
return [
|
|
1438
|
+
this.stringValue(criteria[field]),
|
|
1026
1439
|
entry.name,
|
|
1027
1440
|
entry.label,
|
|
1028
1441
|
this.humanizeFilterField(entry.name),
|
|
1029
1442
|
...entry.aliases,
|
|
1030
1443
|
...entry.relatedColumnFields,
|
|
1031
1444
|
...entry.relatedColumnLabels,
|
|
1445
|
+
...entry.valueHints,
|
|
1032
1446
|
...displayValues,
|
|
1033
1447
|
].some((value) => value && this.promptContainsAnyVariant(token, value));
|
|
1034
1448
|
});
|
|
@@ -1046,6 +1460,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1046
1460
|
'buscar',
|
|
1047
1461
|
'procura',
|
|
1048
1462
|
'procurar',
|
|
1463
|
+
'quem',
|
|
1049
1464
|
'mostra',
|
|
1050
1465
|
'mostrar',
|
|
1051
1466
|
'liste',
|
|
@@ -1062,6 +1477,19 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1062
1477
|
'apos',
|
|
1063
1478
|
'após',
|
|
1064
1479
|
'desde',
|
|
1480
|
+
'mais de',
|
|
1481
|
+
'mais que',
|
|
1482
|
+
'menos de',
|
|
1483
|
+
'menos que',
|
|
1484
|
+
'ganha',
|
|
1485
|
+
'ganham',
|
|
1486
|
+
'ganhando',
|
|
1487
|
+
'recebe',
|
|
1488
|
+
'recebem',
|
|
1489
|
+
'remuneracao',
|
|
1490
|
+
'remuneração',
|
|
1491
|
+
'salario',
|
|
1492
|
+
'salário',
|
|
1065
1493
|
].some((token) => normalizedPrompt.includes(this.normalizeLabel(token)));
|
|
1066
1494
|
}
|
|
1067
1495
|
promptRequestsVisualOrStructuralEdit(normalizedPrompt) {
|
|
@@ -1101,8 +1529,31 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1101
1529
|
this.completeImplicitBooleanCriteriaFromPrompt(normalizedPrompt, criteria);
|
|
1102
1530
|
this.completeImplicitDateRangeCriteriaFromPrompt(normalizedPrompt, criteria);
|
|
1103
1531
|
this.completeImplicitNumericRangeCriteriaFromPrompt(normalizedPrompt, criteria);
|
|
1532
|
+
if (!Object.keys(criteria).length) {
|
|
1533
|
+
this.resolveImplicitTextCriteriaFromValueHints(normalizedPrompt, criteria);
|
|
1534
|
+
}
|
|
1104
1535
|
return Object.keys(criteria).length ? criteria : null;
|
|
1105
1536
|
}
|
|
1537
|
+
resolveDeclaredFilterConfirmationCriteria(normalizedGroundingPrompt, pendingClarification, contextHints) {
|
|
1538
|
+
const criteria = this.resolveDeclaredFilterCriteriaFromPrompt(normalizedGroundingPrompt, contextHints);
|
|
1539
|
+
if (criteria && Object.keys(criteria).length)
|
|
1540
|
+
return criteria;
|
|
1541
|
+
const assistantText = this.normalizeLabel(pendingClarification?.assistantMessage ?? '');
|
|
1542
|
+
if (!assistantText)
|
|
1543
|
+
return null;
|
|
1544
|
+
const confirmedCriteria = {};
|
|
1545
|
+
for (const entry of this.filterFieldCatalogEntries) {
|
|
1546
|
+
if (!this.isTextualFilterCriterion(entry))
|
|
1547
|
+
continue;
|
|
1548
|
+
if (!this.promptMentionsFilterField(assistantText, entry.name))
|
|
1549
|
+
continue;
|
|
1550
|
+
const textValue = this.extractClarifiedTextFilterValue(assistantText, entry, confirmedCriteria);
|
|
1551
|
+
if (textValue) {
|
|
1552
|
+
confirmedCriteria[entry.name] = this.normalizeRuntimeFilterCriterionForCatalogEntry(textValue, entry);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
return Object.keys(confirmedCriteria).length ? confirmedCriteria : null;
|
|
1556
|
+
}
|
|
1106
1557
|
completeImplicitBooleanCriteriaFromPrompt(normalizedPrompt, criteria) {
|
|
1107
1558
|
if (!this.promptHasBooleanFilterValue(normalizedPrompt))
|
|
1108
1559
|
return;
|
|
@@ -1202,13 +1653,33 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1202
1653
|
const candidates = this.filterFieldCatalogEntries
|
|
1203
1654
|
.filter((entry) => criteria[entry.name] === undefined)
|
|
1204
1655
|
.filter((entry) => this.isNumericRangeFilterEntry(entry));
|
|
1205
|
-
|
|
1656
|
+
const mentioned = candidates.filter((entry) => this.promptMentionsFilterField(normalizedPrompt, entry.name));
|
|
1657
|
+
const compensation = mentioned.length ? [] : candidates.filter((entry) => this.isCompensationRangeFilterEntry(entry));
|
|
1658
|
+
const eligible = mentioned.length ? mentioned : (this.promptHasCompensationRangeIntent(normalizedPrompt) ? compensation : candidates);
|
|
1659
|
+
if (eligible.length !== 1)
|
|
1206
1660
|
return;
|
|
1207
|
-
const criterion = this.resolveRangeFilterValue(normalizedPrompt,
|
|
1661
|
+
const criterion = this.resolveRangeFilterValue(normalizedPrompt, eligible[0]);
|
|
1208
1662
|
if (criterion !== undefined) {
|
|
1209
|
-
criteria[
|
|
1663
|
+
criteria[eligible[0].name] = criterion;
|
|
1210
1664
|
}
|
|
1211
1665
|
}
|
|
1666
|
+
promptHasCompensationRangeIntent(normalizedPrompt) {
|
|
1667
|
+
return this.promptHasNumericRangeComparison(normalizedPrompt)
|
|
1668
|
+
&& [
|
|
1669
|
+
'ganha',
|
|
1670
|
+
'ganham',
|
|
1671
|
+
'ganhando',
|
|
1672
|
+
'recebe',
|
|
1673
|
+
'recebem',
|
|
1674
|
+
'recebendo',
|
|
1675
|
+
'remuneracao',
|
|
1676
|
+
'remuneração',
|
|
1677
|
+
'pagamento',
|
|
1678
|
+
'folha',
|
|
1679
|
+
'salario',
|
|
1680
|
+
'salário',
|
|
1681
|
+
].some((token) => this.normalizedTextContainsApproxPhrase(normalizedPrompt, this.normalizeLabel(token)));
|
|
1682
|
+
}
|
|
1212
1683
|
promptHasNumericRangeComparison(normalizedPrompt) {
|
|
1213
1684
|
return /\b\d+(?:[,.]\d+)?(?:\s*(?:mil|k))?\b/u.test(normalizedPrompt)
|
|
1214
1685
|
&& this.promptHasAnyToken(normalizedPrompt, [
|
|
@@ -1257,6 +1728,34 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1257
1728
|
|| valueShape.includes('number');
|
|
1258
1729
|
return isRange && isNumericLike && !isDateLike;
|
|
1259
1730
|
}
|
|
1731
|
+
isCompensationRangeFilterEntry(entry) {
|
|
1732
|
+
if (!this.isNumericRangeFilterEntry(entry))
|
|
1733
|
+
return false;
|
|
1734
|
+
const text = this.normalizeLabel([
|
|
1735
|
+
entry.name,
|
|
1736
|
+
entry.label,
|
|
1737
|
+
this.humanizeFilterField(entry.name),
|
|
1738
|
+
entry.controlType,
|
|
1739
|
+
entry.criterionKind,
|
|
1740
|
+
entry.criterionValueShape,
|
|
1741
|
+
...entry.aliases,
|
|
1742
|
+
...entry.relatedColumnFields,
|
|
1743
|
+
...entry.relatedColumnLabels,
|
|
1744
|
+
].join(' '));
|
|
1745
|
+
return [
|
|
1746
|
+
'salario',
|
|
1747
|
+
'salário',
|
|
1748
|
+
'salary',
|
|
1749
|
+
'remuneracao',
|
|
1750
|
+
'remuneração',
|
|
1751
|
+
'compensacao',
|
|
1752
|
+
'compensação',
|
|
1753
|
+
'pagamento',
|
|
1754
|
+
'folha',
|
|
1755
|
+
'wage',
|
|
1756
|
+
'pay',
|
|
1757
|
+
].some((token) => this.normalizedTextContainsApproxPhrase(text, this.normalizeLabel(token)));
|
|
1758
|
+
}
|
|
1260
1759
|
resolveDeclaredFilterCriterionValue(normalizedPrompt, entry, contextHints) {
|
|
1261
1760
|
const type = this.normalizeLabel(entry.type ?? '');
|
|
1262
1761
|
const controlType = this.normalizeLabel(entry.controlType ?? '');
|
|
@@ -1671,16 +2170,24 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1671
2170
|
if (response.type === 'clarification') {
|
|
1672
2171
|
const questions = this.toClarificationQuestions(response, request);
|
|
1673
2172
|
const diagnostics = this.buildClarificationDiagnostics(response);
|
|
2173
|
+
const sourcePrompt = this.pendingClarificationSourcePromptForTurn(request, diagnostics);
|
|
2174
|
+
const assistantMessage = response.message || 'Preciso de mais detalhes para continuar.';
|
|
1674
2175
|
return {
|
|
1675
2176
|
state: 'clarification',
|
|
1676
2177
|
phase: 'clarify',
|
|
1677
2178
|
sessionId: response.sessionId ?? request.sessionId,
|
|
1678
2179
|
observationId: response.observationId ?? request.observationId ?? null,
|
|
1679
|
-
assistantMessage
|
|
2180
|
+
assistantMessage,
|
|
1680
2181
|
clarificationQuestions: questions,
|
|
1681
2182
|
quickReplies: this.toQuickReplies(response, request),
|
|
1682
2183
|
canApply: false,
|
|
1683
2184
|
diagnostics,
|
|
2185
|
+
pendingClarification: {
|
|
2186
|
+
sourcePrompt,
|
|
2187
|
+
assistantMessage,
|
|
2188
|
+
questions,
|
|
2189
|
+
diagnostics,
|
|
2190
|
+
},
|
|
1684
2191
|
};
|
|
1685
2192
|
}
|
|
1686
2193
|
if (response.type === 'info') {
|
|
@@ -1765,6 +2272,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1765
2272
|
if (continuedEarlyColumnPlan) {
|
|
1766
2273
|
return this.compileAdapterResponse(continuedEarlyColumnPlan, request);
|
|
1767
2274
|
}
|
|
2275
|
+
const continuedColumnVisibilityPlan = this.columnVisibilityPlanForGroundedClarification(response, request);
|
|
2276
|
+
if (continuedColumnVisibilityPlan) {
|
|
2277
|
+
return this.compileAdapterResponse(continuedColumnVisibilityPlan, request);
|
|
2278
|
+
}
|
|
1768
2279
|
const compiledExecutable = !this.responseCarriesClarificationChoices(response)
|
|
1769
2280
|
&& this.responseMayContainExecutableEnvelope(response)
|
|
1770
2281
|
? this.adapter.compileAiResponse?.(response)
|
|
@@ -1784,6 +2295,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1784
2295
|
warnings: warnings.length ? warnings : undefined,
|
|
1785
2296
|
};
|
|
1786
2297
|
delete executableResponse.type;
|
|
2298
|
+
const columnVisibilitySurfaceMismatch = this.columnVisibilityPlanForMisroutedSurfaceRuntime(executableResponse, request);
|
|
2299
|
+
if (columnVisibilitySurfaceMismatch) {
|
|
2300
|
+
return this.compileAdapterResponse(columnVisibilitySurfaceMismatch, request);
|
|
2301
|
+
}
|
|
1787
2302
|
const visualSurfaceMismatch = this.visualPresentationSurfaceRuntimeMismatch(executableResponse, request);
|
|
1788
2303
|
if (visualSurfaceMismatch) {
|
|
1789
2304
|
return visualSurfaceMismatch;
|
|
@@ -1795,6 +2310,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1795
2310
|
return executableResponse;
|
|
1796
2311
|
}
|
|
1797
2312
|
if (compiledExecutable?.type === 'error') {
|
|
2313
|
+
const continuedColumnVisibilityError = this.columnVisibilityPlanForMisroutedSurfaceError(response, request, compiledExecutable);
|
|
2314
|
+
if (continuedColumnVisibilityError) {
|
|
2315
|
+
return this.compileAdapterResponse(continuedColumnVisibilityError, request);
|
|
2316
|
+
}
|
|
1798
2317
|
const continuedInvalidExecutable = this.selectedRecordSurfaceRuntimeOperationForInvalidExecutable(response, request, compiledExecutable.warnings);
|
|
1799
2318
|
if (continuedInvalidExecutable) {
|
|
1800
2319
|
return continuedInvalidExecutable;
|
|
@@ -1809,6 +2328,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1809
2328
|
warnings: compiledExecutable.warnings,
|
|
1810
2329
|
};
|
|
1811
2330
|
}
|
|
2331
|
+
const continuedColumnVisibilityNarrative = this.columnVisibilityPlanForGroundedNarrative(response, request);
|
|
2332
|
+
if (continuedColumnVisibilityNarrative) {
|
|
2333
|
+
return this.compileAdapterResponse(continuedColumnVisibilityNarrative, request);
|
|
2334
|
+
}
|
|
1812
2335
|
const continuedSurfaceRowActionFromInfo = this.selectedRecordSurfaceRowActionPlanForInfo(response, request);
|
|
1813
2336
|
if (continuedSurfaceRowActionFromInfo) {
|
|
1814
2337
|
return this.compileAdapterResponse(continuedSurfaceRowActionFromInfo, request);
|
|
@@ -1887,6 +2410,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1887
2410
|
};
|
|
1888
2411
|
}
|
|
1889
2412
|
if (!compiled) {
|
|
2413
|
+
const continuedColumnVisibilityNarrative = this.columnVisibilityPlanForGroundedNarrative(response, request);
|
|
2414
|
+
if (continuedColumnVisibilityNarrative) {
|
|
2415
|
+
return this.compileAdapterResponse(continuedColumnVisibilityNarrative, request);
|
|
2416
|
+
}
|
|
1890
2417
|
const continuedColumnFormatNarrative = this.columnFormatPlanForNonExecutableNarrative(response, request);
|
|
1891
2418
|
if (continuedColumnFormatNarrative) {
|
|
1892
2419
|
return this.compileAdapterResponse(continuedColumnFormatNarrative, request);
|
|
@@ -1898,6 +2425,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1898
2425
|
return response;
|
|
1899
2426
|
}
|
|
1900
2427
|
if (compiled.type === 'error') {
|
|
2428
|
+
const continuedColumnVisibilityError = this.columnVisibilityPlanForMisroutedSurfaceError(response, request, compiled);
|
|
2429
|
+
if (continuedColumnVisibilityError) {
|
|
2430
|
+
return this.compileAdapterResponse(continuedColumnVisibilityError, request);
|
|
2431
|
+
}
|
|
1901
2432
|
const continuedBulkRouteAction = this.bulkRouteActionPlanForInvalidExecutable(response, request, compiled.warnings);
|
|
1902
2433
|
if (continuedBulkRouteAction) {
|
|
1903
2434
|
return this.compileAdapterResponse(continuedBulkRouteAction, request);
|
|
@@ -1953,6 +2484,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1953
2484
|
patch: normalizedCompiled.patch,
|
|
1954
2485
|
warnings: warnings.length ? warnings : undefined,
|
|
1955
2486
|
};
|
|
2487
|
+
const columnVisibilitySurfaceMismatch = this.columnVisibilityPlanForMisroutedSurfaceRuntime(compiledResponse, request);
|
|
2488
|
+
if (columnVisibilitySurfaceMismatch) {
|
|
2489
|
+
return this.compileAdapterResponse(columnVisibilitySurfaceMismatch, request);
|
|
2490
|
+
}
|
|
1956
2491
|
const visualSurfaceMismatch = this.visualPresentationSurfaceRuntimeMismatch(compiledResponse, request);
|
|
1957
2492
|
if (visualSurfaceMismatch) {
|
|
1958
2493
|
return visualSurfaceMismatch;
|
|
@@ -4100,6 +4635,28 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4100
4635
|
?? this.booleanSimNaoOperationsFromGroundedClarification(prompt, responseText, columns)
|
|
4101
4636
|
?? this.booleanSimNaoOperationsFromSingleGroundedBooleanColumn(prompt, responseText, columns)
|
|
4102
4637
|
?? this.booleanSimNaoOperationsFromGroundedResponseField(prompt, responseText, columns);
|
|
4638
|
+
const promptRequestsSimNao = this.normalizedTextIncludesAny(this.normalizeLabel(prompt), [
|
|
4639
|
+
'sim nao',
|
|
4640
|
+
'sim/nao',
|
|
4641
|
+
'sim não',
|
|
4642
|
+
'sim/não',
|
|
4643
|
+
'sim ou nao',
|
|
4644
|
+
'sim ou não',
|
|
4645
|
+
]);
|
|
4646
|
+
const responseGroundsBooleanSimNao = this.normalizedTextIncludesAny(normalizedResponse, [
|
|
4647
|
+
'sim quando true',
|
|
4648
|
+
'sim quando verdadeiro',
|
|
4649
|
+
'nao quando false',
|
|
4650
|
+
'não quando false',
|
|
4651
|
+
'nao quando falso',
|
|
4652
|
+
'não quando falso',
|
|
4653
|
+
'sim para true',
|
|
4654
|
+
'sim para verdadeiro',
|
|
4655
|
+
'nao para false',
|
|
4656
|
+
'não para false',
|
|
4657
|
+
'nao para falso',
|
|
4658
|
+
'não para falso',
|
|
4659
|
+
]);
|
|
4103
4660
|
const booleanFormatClarification = !!booleanOperations?.length && this.normalizedTextIncludesAny(normalizedResponse, [
|
|
4104
4661
|
'sim nao',
|
|
4105
4662
|
'sim / nao',
|
|
@@ -4110,7 +4667,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4110
4667
|
'badges com textos sim nao',
|
|
4111
4668
|
'mostrar apenas texto sim nao',
|
|
4112
4669
|
'valores booleanos como sim ou nao',
|
|
4113
|
-
]);
|
|
4670
|
+
]) || (!!booleanOperations?.length && promptRequestsSimNao && responseGroundsBooleanSimNao);
|
|
4114
4671
|
if (booleanOperations?.length && (booleanInfo || booleanFormatClarification)) {
|
|
4115
4672
|
return this.componentEditPlanResponse(booleanOperations, 'Vou mostrar o booleano como Sim/Nao na coluna indicada.', [
|
|
4116
4673
|
...(response.warnings ?? []),
|
|
@@ -4882,6 +5439,199 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4882
5439
|
],
|
|
4883
5440
|
};
|
|
4884
5441
|
}
|
|
5442
|
+
columnVisibilityPlanForMisroutedSurfaceRuntime(response, request) {
|
|
5443
|
+
if (!request)
|
|
5444
|
+
return null;
|
|
5445
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5446
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5447
|
+
return null;
|
|
5448
|
+
if (!this.patchContainsRuntimeOperationId(response.patch, 'dynamicPage.surface.open'))
|
|
5449
|
+
return null;
|
|
5450
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5451
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5452
|
+
? currentConfig['columns']
|
|
5453
|
+
.map((column) => this.toRecord(column))
|
|
5454
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5455
|
+
: [];
|
|
5456
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5457
|
+
if (!operations.length) {
|
|
5458
|
+
return {
|
|
5459
|
+
type: 'clarification',
|
|
5460
|
+
sessionId: request.sessionId,
|
|
5461
|
+
message: 'Entendi que o pedido é sobre ocultar ou exibir colunas, não sobre abrir uma superfície do registro.',
|
|
5462
|
+
questions: ['Quais colunas você quer ocultar ou exibir?'],
|
|
5463
|
+
options: columns
|
|
5464
|
+
.slice(0, 8)
|
|
5465
|
+
.map((column) => this.stringValue(column['header']) || this.stringValue(column['field']))
|
|
5466
|
+
.filter((label) => !!label),
|
|
5467
|
+
warnings: [
|
|
5468
|
+
...(response.warnings ?? []),
|
|
5469
|
+
'column-visibility-request-blocked-surface-runtime-operation',
|
|
5470
|
+
],
|
|
5471
|
+
};
|
|
5472
|
+
}
|
|
5473
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5474
|
+
...(response.warnings ?? []),
|
|
5475
|
+
'column-visibility-continued-from-surface-runtime-misroute',
|
|
5476
|
+
'Residual continuity guard acted only after the LLM proposed dynamicPage.surface.open for a column visibility/privacy request grounded in declared table columns.',
|
|
5477
|
+
]);
|
|
5478
|
+
}
|
|
5479
|
+
columnVisibilityPlanForGroundedClarification(response, request) {
|
|
5480
|
+
if (!request)
|
|
5481
|
+
return null;
|
|
5482
|
+
if (response.type !== 'clarification')
|
|
5483
|
+
return null;
|
|
5484
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5485
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5486
|
+
return null;
|
|
5487
|
+
const questionText = [
|
|
5488
|
+
response.message,
|
|
5489
|
+
...(response.questions ?? []),
|
|
5490
|
+
...(response.options ?? []),
|
|
5491
|
+
].join(' ');
|
|
5492
|
+
const asksForColumn = this.normalizedTextIncludesAny(this.normalizeLabel(questionText), [
|
|
5493
|
+
'qual coluna',
|
|
5494
|
+
'quais colunas',
|
|
5495
|
+
'coluna devo usar',
|
|
5496
|
+
'colunas devo usar',
|
|
5497
|
+
]);
|
|
5498
|
+
const asksForVisibilityScope = this.normalizedTextIncludesAny(this.normalizeLabel(questionText), [
|
|
5499
|
+
'globalmente',
|
|
5500
|
+
'todos os usuarios',
|
|
5501
|
+
'todos os usuários',
|
|
5502
|
+
'apresentacao publica',
|
|
5503
|
+
'apresentação pública',
|
|
5504
|
+
'visualizacao publica',
|
|
5505
|
+
'visualização pública',
|
|
5506
|
+
'vista padrao',
|
|
5507
|
+
'vista padrão',
|
|
5508
|
+
'confirma qual opcao',
|
|
5509
|
+
'confirma qual opção',
|
|
5510
|
+
]);
|
|
5511
|
+
if (!asksForColumn && !asksForVisibilityScope)
|
|
5512
|
+
return null;
|
|
5513
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5514
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5515
|
+
? currentConfig['columns']
|
|
5516
|
+
.map((column) => this.toRecord(column))
|
|
5517
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5518
|
+
: [];
|
|
5519
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5520
|
+
if (!operations.length)
|
|
5521
|
+
return null;
|
|
5522
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5523
|
+
...(response.warnings ?? []),
|
|
5524
|
+
'column-visibility-continued-from-grounded-clarification',
|
|
5525
|
+
'Residual continuity guard acted only after the LLM asked which column to use even though the column visibility request was grounded in declared table columns.',
|
|
5526
|
+
]);
|
|
5527
|
+
}
|
|
5528
|
+
columnVisibilityPlanForGroundedNarrative(response, request) {
|
|
5529
|
+
if (!request)
|
|
5530
|
+
return null;
|
|
5531
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5532
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5533
|
+
return null;
|
|
5534
|
+
const responseText = this.normalizeLabel([
|
|
5535
|
+
response.message,
|
|
5536
|
+
response.explanation,
|
|
5537
|
+
response.code,
|
|
5538
|
+
].join(' '));
|
|
5539
|
+
const narratesVisibilityPlan = this.normalizedTextIncludesAny(responseText, [
|
|
5540
|
+
'componenteditplan',
|
|
5541
|
+
'column.visibility.set',
|
|
5542
|
+
'visible false',
|
|
5543
|
+
'invisivel',
|
|
5544
|
+
'invisível',
|
|
5545
|
+
'ocultar a coluna',
|
|
5546
|
+
'ocultar as colunas',
|
|
5547
|
+
]);
|
|
5548
|
+
if (!narratesVisibilityPlan)
|
|
5549
|
+
return null;
|
|
5550
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5551
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5552
|
+
? currentConfig['columns']
|
|
5553
|
+
.map((column) => this.toRecord(column))
|
|
5554
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5555
|
+
: [];
|
|
5556
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5557
|
+
if (!operations.length)
|
|
5558
|
+
return null;
|
|
5559
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5560
|
+
...(response.warnings ?? []),
|
|
5561
|
+
'column-visibility-continued-from-non-executable-narrative',
|
|
5562
|
+
'Residual continuity guard acted only after the LLM narrated a column visibility plan without returning an executable envelope.',
|
|
5563
|
+
]);
|
|
5564
|
+
}
|
|
5565
|
+
columnVisibilityPlanForMisroutedSurfaceError(response, request, compiledError) {
|
|
5566
|
+
if (!request)
|
|
5567
|
+
return null;
|
|
5568
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5569
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5570
|
+
return null;
|
|
5571
|
+
const errorText = this.normalizeLabel([
|
|
5572
|
+
response.message,
|
|
5573
|
+
response.explanation,
|
|
5574
|
+
compiledError.message,
|
|
5575
|
+
compiledError.explanation,
|
|
5576
|
+
...(compiledError.warnings ?? []),
|
|
5577
|
+
].join(' '));
|
|
5578
|
+
if (!this.normalizedTextIncludesAny(errorText, [
|
|
5579
|
+
'dynamicpage.surface.open',
|
|
5580
|
+
'surface.open',
|
|
5581
|
+
'superficie',
|
|
5582
|
+
'superfície',
|
|
5583
|
+
]))
|
|
5584
|
+
return null;
|
|
5585
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5586
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5587
|
+
? currentConfig['columns']
|
|
5588
|
+
.map((column) => this.toRecord(column))
|
|
5589
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5590
|
+
: [];
|
|
5591
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5592
|
+
if (!operations.length)
|
|
5593
|
+
return null;
|
|
5594
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5595
|
+
...(response.warnings ?? []),
|
|
5596
|
+
...(compiledError.warnings ?? []),
|
|
5597
|
+
'column-visibility-continued-from-surface-runtime-error',
|
|
5598
|
+
'Residual continuity guard acted only after a misrouted surface runtime operation failed validation for a column visibility request.',
|
|
5599
|
+
]);
|
|
5600
|
+
}
|
|
5601
|
+
columnVisibilityPromptForTurn(request) {
|
|
5602
|
+
const currentPrompt = (request.prompt ?? '').trim();
|
|
5603
|
+
if (this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(currentPrompt))) {
|
|
5604
|
+
return currentPrompt;
|
|
5605
|
+
}
|
|
5606
|
+
const previousVisibilityPrompt = [...(request.messages ?? [])]
|
|
5607
|
+
.reverse()
|
|
5608
|
+
.filter((message) => message.role === 'user')
|
|
5609
|
+
.map((message) => message.text.trim())
|
|
5610
|
+
.find((message) => this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(message)));
|
|
5611
|
+
return [previousVisibilityPrompt, currentPrompt]
|
|
5612
|
+
.filter((part) => !!part)
|
|
5613
|
+
.join(' ');
|
|
5614
|
+
}
|
|
5615
|
+
columnVisibilityOperationsFromPrompt(prompt, columns) {
|
|
5616
|
+
const hide = !this.normalizedTextIncludesAny(this.normalizeLabel(prompt), [
|
|
5617
|
+
'exibir',
|
|
5618
|
+
'mostrar coluna',
|
|
5619
|
+
'mostra coluna',
|
|
5620
|
+
'revelar',
|
|
5621
|
+
]);
|
|
5622
|
+
const operations = [];
|
|
5623
|
+
for (const column of columns) {
|
|
5624
|
+
const field = this.stringValue(column['field']);
|
|
5625
|
+
if (!field || !this.textMentionsColumn(prompt, column))
|
|
5626
|
+
continue;
|
|
5627
|
+
operations.push({
|
|
5628
|
+
operationId: 'column.visibility.set',
|
|
5629
|
+
target: { kind: 'column', field },
|
|
5630
|
+
input: { visible: !hide },
|
|
5631
|
+
});
|
|
5632
|
+
}
|
|
5633
|
+
return operations;
|
|
5634
|
+
}
|
|
4885
5635
|
requestCarriesVisualPresentationContext(request) {
|
|
4886
5636
|
const actionHints = this.toRecord(request.action?.contextHints);
|
|
4887
5637
|
const requestHints = this.toRecord(request.contextHints);
|
|
@@ -4907,6 +5657,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4907
5657
|
if (!normalizedPrompt)
|
|
4908
5658
|
return false;
|
|
4909
5659
|
const entry = this.filterFieldCatalogEntries.find((candidate) => candidate.name === fieldName);
|
|
5660
|
+
if (entry && this.promptMentionsFilterFieldAsNonRestrictiveScope(normalizedPrompt, entry))
|
|
5661
|
+
return false;
|
|
4910
5662
|
const rawCandidates = [
|
|
4911
5663
|
fieldName,
|
|
4912
5664
|
this.humanizeFilterField(fieldName),
|
|
@@ -4919,6 +5671,59 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4919
5671
|
.flatMap((candidate) => this.filterFieldMentionVariants(candidate ?? ''))
|
|
4920
5672
|
.some((candidate) => candidate && this.normalizedTextContainsApproxPhrase(normalizedPrompt, candidate));
|
|
4921
5673
|
}
|
|
5674
|
+
promptMentionsFilterFieldAsNonRestrictiveScope(normalizedPrompt, entry) {
|
|
5675
|
+
const variants = [
|
|
5676
|
+
entry.name,
|
|
5677
|
+
entry.label,
|
|
5678
|
+
this.humanizeFilterField(entry.name),
|
|
5679
|
+
...entry.aliases,
|
|
5680
|
+
...entry.relatedColumnFields,
|
|
5681
|
+
...entry.relatedColumnLabels,
|
|
5682
|
+
].flatMap((candidate) => this.filterFieldMentionVariants(candidate ?? ''));
|
|
5683
|
+
return variants.some((variant) => {
|
|
5684
|
+
if (!variant)
|
|
5685
|
+
return false;
|
|
5686
|
+
return [
|
|
5687
|
+
`qualquer ${variant}`,
|
|
5688
|
+
`qq ${variant}`,
|
|
5689
|
+
`tanto faz ${variant}`,
|
|
5690
|
+
`${variant} tanto faz`,
|
|
5691
|
+
`${variant} qualquer`,
|
|
5692
|
+
`independente de ${variant}`,
|
|
5693
|
+
`nao importa ${variant}`,
|
|
5694
|
+
`${variant} nao importa`,
|
|
5695
|
+
].some((phrase) => this.normalizedTextContainsExactPhrase(normalizedPrompt, this.normalizeLabel(phrase)));
|
|
5696
|
+
});
|
|
5697
|
+
}
|
|
5698
|
+
removeNonRestrictiveFilterFieldClauses(value) {
|
|
5699
|
+
let normalized = value.trim();
|
|
5700
|
+
if (!normalized)
|
|
5701
|
+
return '';
|
|
5702
|
+
const fieldTerms = this.filterFieldCatalogEntries
|
|
5703
|
+
.flatMap((entry) => [
|
|
5704
|
+
entry.name,
|
|
5705
|
+
entry.label,
|
|
5706
|
+
this.humanizeFilterField(entry.name),
|
|
5707
|
+
...entry.aliases,
|
|
5708
|
+
...entry.relatedColumnFields,
|
|
5709
|
+
...entry.relatedColumnLabels,
|
|
5710
|
+
])
|
|
5711
|
+
.flatMap((term) => this.filterFieldMentionVariants(term ?? ''))
|
|
5712
|
+
.filter((term, index, terms) => !!term && terms.indexOf(term) === index);
|
|
5713
|
+
for (const term of fieldTerms) {
|
|
5714
|
+
const escaped = term.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
5715
|
+
normalized = normalized
|
|
5716
|
+
.replace(new RegExp(`(?:,|;)?\\s*(?:tanto faz|qualquer|qq|independente de|nao importa|não importa)\\s+${escaped}\\b`, 'giu'), '')
|
|
5717
|
+
.replace(new RegExp(`(?:,|;)?\\s*${escaped}\\s+(?:tanto faz|qualquer|nao importa|não importa)\\b`, 'giu'), '');
|
|
5718
|
+
}
|
|
5719
|
+
return normalized.trim();
|
|
5720
|
+
}
|
|
5721
|
+
normalizedTextContainsExactPhrase(normalizedText, normalizedPhrase) {
|
|
5722
|
+
if (!normalizedText || !normalizedPhrase)
|
|
5723
|
+
return false;
|
|
5724
|
+
const escaped = normalizedPhrase.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&').replace(/\s+/gu, '\\s+');
|
|
5725
|
+
return new RegExp(`(^|[^a-z0-9])${escaped}($|[^a-z0-9])`, 'u').test(normalizedText);
|
|
5726
|
+
}
|
|
4922
5727
|
selectedRecordFilterPromptGroundingScore(prompt, candidate) {
|
|
4923
5728
|
const fieldName = this.stringValue(candidate['field']);
|
|
4924
5729
|
if (!fieldName)
|
|
@@ -5471,7 +6276,20 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
5471
6276
|
}
|
|
5472
6277
|
buildClarificationDiagnostics(response) {
|
|
5473
6278
|
const continuation = this.extractPendingComponentEditContinuation(response);
|
|
5474
|
-
|
|
6279
|
+
const responseDiagnostics = this.toRecord(response.diagnostics);
|
|
6280
|
+
if (!continuation && !responseDiagnostics)
|
|
6281
|
+
return undefined;
|
|
6282
|
+
return {
|
|
6283
|
+
...(responseDiagnostics ?? {}),
|
|
6284
|
+
...(continuation ? { tableComponentEditContinuation: continuation } : {}),
|
|
6285
|
+
};
|
|
6286
|
+
}
|
|
6287
|
+
pendingClarificationSourcePromptForTurn(request, diagnostics) {
|
|
6288
|
+
const declaredFilter = this.toRecord(diagnostics?.['tableDeclaredFilterClarification']);
|
|
6289
|
+
return this.stringValue(declaredFilter?.['sourcePrompt']).trim()
|
|
6290
|
+
|| request.pendingClarification?.sourcePrompt?.trim()
|
|
6291
|
+
|| request.prompt?.trim()
|
|
6292
|
+
|| '';
|
|
5475
6293
|
}
|
|
5476
6294
|
buildReviewDiagnostics(response, warnings) {
|
|
5477
6295
|
const memory = this.extractComponentEditDecisionMemory(response);
|
|
@@ -6355,6 +7173,9 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6355
7173
|
const normalizedOptions = new Set(options
|
|
6356
7174
|
.map((option) => this.normalizeLabel(option))
|
|
6357
7175
|
.filter((option) => !!option));
|
|
7176
|
+
if (this.promptRequestsColumnVisibilityEdit(prompt)) {
|
|
7177
|
+
return null;
|
|
7178
|
+
}
|
|
6358
7179
|
const promptLooksLikeFilter = this.promptRequestsRuntimeFilter(prompt)
|
|
6359
7180
|
|| ['filtro', 'filtrar', 'busca', 'buscar', 'procura', 'procurar', 'mostra', 'mostrar'].some((token) => this.normalizedTextContainsApproxToken(prompt, token));
|
|
6360
7181
|
const responseLooksFilterFieldClarification = responseText.includes('filtro declarado')
|
|
@@ -6516,7 +7337,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6516
7337
|
return quoted;
|
|
6517
7338
|
const match = trimmed.match(/\b(?:de|da|do|dos|das|por|com|contendo|contem|contém)\s+(.{2,})$/iu);
|
|
6518
7339
|
const candidate = (match?.[1] ?? '').trim();
|
|
6519
|
-
return candidate
|
|
7340
|
+
return this.removeNonRestrictiveFilterFieldClauses(candidate)
|
|
6520
7341
|
.replace(/[?.!,;:]+$/u, '')
|
|
6521
7342
|
.trim();
|
|
6522
7343
|
}
|
|
@@ -6554,6 +7375,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6554
7375
|
};
|
|
6555
7376
|
});
|
|
6556
7377
|
}
|
|
7378
|
+
return [];
|
|
6557
7379
|
}
|
|
6558
7380
|
if ((response.type === 'clarification' || response.type === 'info')
|
|
6559
7381
|
&& this.shouldCurateVisibilityClarificationQuickReplies(response, prompt)) {
|
|
@@ -6662,6 +7484,49 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6662
7484
|
// semantic scope choices the user needs to answer.
|
|
6663
7485
|
return true;
|
|
6664
7486
|
}
|
|
7487
|
+
promptRequestsColumnVisibilityEdit(normalizedPrompt) {
|
|
7488
|
+
if (!normalizedPrompt)
|
|
7489
|
+
return false;
|
|
7490
|
+
const asksVisibilityOrPrivacy = [
|
|
7491
|
+
'ocultacao',
|
|
7492
|
+
'ocultação',
|
|
7493
|
+
'oculta',
|
|
7494
|
+
'ocultar',
|
|
7495
|
+
'esconde',
|
|
7496
|
+
'esconder',
|
|
7497
|
+
'remova a coluna',
|
|
7498
|
+
'remover a coluna',
|
|
7499
|
+
'remova as colunas',
|
|
7500
|
+
'remover as colunas',
|
|
7501
|
+
'tirar da visualizacao',
|
|
7502
|
+
'tirar da visualização',
|
|
7503
|
+
'publico',
|
|
7504
|
+
'público',
|
|
7505
|
+
'privacidade',
|
|
7506
|
+
'sensivel',
|
|
7507
|
+
'sensível',
|
|
7508
|
+
].some((token) => this.normalizedTextContainsApproxPhrase(normalizedPrompt, token));
|
|
7509
|
+
if (!asksVisibilityOrPrivacy)
|
|
7510
|
+
return false;
|
|
7511
|
+
const mentionsColumnScope = [
|
|
7512
|
+
'coluna',
|
|
7513
|
+
'colunas',
|
|
7514
|
+
'visualizacao',
|
|
7515
|
+
'visualização',
|
|
7516
|
+
'tabela',
|
|
7517
|
+
'email',
|
|
7518
|
+
'e-mail',
|
|
7519
|
+
'salario',
|
|
7520
|
+
'salário',
|
|
7521
|
+
'cpf',
|
|
7522
|
+
'documento',
|
|
7523
|
+
'telefone',
|
|
7524
|
+
].some((token) => this.normalizedTextContainsApproxPhrase(normalizedPrompt, token));
|
|
7525
|
+
// Residual guard only: the LLM/authoring contract still decides the primary
|
|
7526
|
+
// intent. Once a turn is already in a column-visibility scope, filter
|
|
7527
|
+
// quick-reply curation must not reinterpret it as row filtering.
|
|
7528
|
+
return mentionsColumnScope;
|
|
7529
|
+
}
|
|
6665
7530
|
visibilityClarificationQuickReplyOptions() {
|
|
6666
7531
|
return [
|
|
6667
7532
|
{
|
|
@@ -6706,6 +7571,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6706
7571
|
const optionCount = response.options?.length ?? 0;
|
|
6707
7572
|
if (payloadCount <= 0 && optionCount <= 0)
|
|
6708
7573
|
return false;
|
|
7574
|
+
if (this.promptRequestsColumnVisibilityEdit(normalizedPrompt))
|
|
7575
|
+
return false;
|
|
7576
|
+
if (payloadCount > 0 && normalizedPrompt && !this.promptRequestsRuntimeFilter(normalizedPrompt))
|
|
7577
|
+
return false;
|
|
6709
7578
|
if (this.responseAsksForDeclaredFilterField(response))
|
|
6710
7579
|
return true;
|
|
6711
7580
|
if (!normalizedPrompt || !this.promptRequestsRuntimeFilter(normalizedPrompt))
|