@praxisui/table 8.0.0-beta.87 → 8.0.0-beta.89
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-DDQAk0TJ.mjs → praxisui-table-praxisui-table-Dl9IfFPG.mjs} +95 -16
- package/fesm2022/{praxisui-table-table-agentic-authoring-turn-flow-oJhkMALs.mjs → praxisui-table-table-agentic-authoring-turn-flow-CJG-Gjzu.mjs} +935 -9
- package/fesm2022/{praxisui-table-table-ai.adapter-yEPQ8xBc.mjs → praxisui-table-table-ai.adapter-D-NfNb_E.mjs} +43 -11
- 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
|
|
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
|
|
852
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,14 @@ 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
|
+
}
|
|
2335
|
+
const continuedColumnVisibilitySurfaceNarrative = this.columnVisibilityPlanForMisroutedSurfaceNarrative(response, request);
|
|
2336
|
+
if (continuedColumnVisibilitySurfaceNarrative) {
|
|
2337
|
+
return this.compileAdapterResponse(continuedColumnVisibilitySurfaceNarrative, request);
|
|
2338
|
+
}
|
|
1812
2339
|
const continuedSurfaceRowActionFromInfo = this.selectedRecordSurfaceRowActionPlanForInfo(response, request);
|
|
1813
2340
|
if (continuedSurfaceRowActionFromInfo) {
|
|
1814
2341
|
return this.compileAdapterResponse(continuedSurfaceRowActionFromInfo, request);
|
|
@@ -1887,6 +2414,14 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1887
2414
|
};
|
|
1888
2415
|
}
|
|
1889
2416
|
if (!compiled) {
|
|
2417
|
+
const continuedColumnVisibilityNarrative = this.columnVisibilityPlanForGroundedNarrative(response, request);
|
|
2418
|
+
if (continuedColumnVisibilityNarrative) {
|
|
2419
|
+
return this.compileAdapterResponse(continuedColumnVisibilityNarrative, request);
|
|
2420
|
+
}
|
|
2421
|
+
const continuedColumnVisibilitySurfaceNarrative = this.columnVisibilityPlanForMisroutedSurfaceNarrative(response, request);
|
|
2422
|
+
if (continuedColumnVisibilitySurfaceNarrative) {
|
|
2423
|
+
return this.compileAdapterResponse(continuedColumnVisibilitySurfaceNarrative, request);
|
|
2424
|
+
}
|
|
1890
2425
|
const continuedColumnFormatNarrative = this.columnFormatPlanForNonExecutableNarrative(response, request);
|
|
1891
2426
|
if (continuedColumnFormatNarrative) {
|
|
1892
2427
|
return this.compileAdapterResponse(continuedColumnFormatNarrative, request);
|
|
@@ -1898,6 +2433,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1898
2433
|
return response;
|
|
1899
2434
|
}
|
|
1900
2435
|
if (compiled.type === 'error') {
|
|
2436
|
+
const continuedColumnVisibilityError = this.columnVisibilityPlanForMisroutedSurfaceError(response, request, compiled);
|
|
2437
|
+
if (continuedColumnVisibilityError) {
|
|
2438
|
+
return this.compileAdapterResponse(continuedColumnVisibilityError, request);
|
|
2439
|
+
}
|
|
1901
2440
|
const continuedBulkRouteAction = this.bulkRouteActionPlanForInvalidExecutable(response, request, compiled.warnings);
|
|
1902
2441
|
if (continuedBulkRouteAction) {
|
|
1903
2442
|
return this.compileAdapterResponse(continuedBulkRouteAction, request);
|
|
@@ -1953,6 +2492,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
1953
2492
|
patch: normalizedCompiled.patch,
|
|
1954
2493
|
warnings: warnings.length ? warnings : undefined,
|
|
1955
2494
|
};
|
|
2495
|
+
const columnVisibilitySurfaceMismatch = this.columnVisibilityPlanForMisroutedSurfaceRuntime(compiledResponse, request);
|
|
2496
|
+
if (columnVisibilitySurfaceMismatch) {
|
|
2497
|
+
return this.compileAdapterResponse(columnVisibilitySurfaceMismatch, request);
|
|
2498
|
+
}
|
|
1956
2499
|
const visualSurfaceMismatch = this.visualPresentationSurfaceRuntimeMismatch(compiledResponse, request);
|
|
1957
2500
|
if (visualSurfaceMismatch) {
|
|
1958
2501
|
return visualSurfaceMismatch;
|
|
@@ -3432,6 +3975,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3432
3975
|
return score;
|
|
3433
3976
|
}
|
|
3434
3977
|
selectedRecordSurfaceOperationForMisgroundedFilter(normalizedPrompt, request) {
|
|
3978
|
+
if (request && this.turnRequestsColumnVisibilityEdit(request))
|
|
3979
|
+
return null;
|
|
3435
3980
|
if (this.promptRequestsSimilarRecords(normalizedPrompt))
|
|
3436
3981
|
return null;
|
|
3437
3982
|
const contextHints = this.contextHintsFor(request);
|
|
@@ -3483,6 +4028,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3483
4028
|
selectedRecordSurfaceRowActionPlanForClarification(response, request) {
|
|
3484
4029
|
if (!request)
|
|
3485
4030
|
return null;
|
|
4031
|
+
if (this.turnRequestsColumnVisibilityEdit(request))
|
|
4032
|
+
return null;
|
|
3486
4033
|
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
3487
4034
|
const normalizedConversation = this.normalizeLabel([
|
|
3488
4035
|
...(request.messages ?? []).slice(-8).map((message) => message?.text ?? ''),
|
|
@@ -3533,6 +4080,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3533
4080
|
selectedRecordSurfaceRowActionPlanForInfo(response, request) {
|
|
3534
4081
|
if (response.type !== 'info' || !request)
|
|
3535
4082
|
return null;
|
|
4083
|
+
if (this.turnRequestsColumnVisibilityEdit(request))
|
|
4084
|
+
return null;
|
|
3536
4085
|
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
3537
4086
|
const normalizedConversation = this.normalizeLabel([
|
|
3538
4087
|
...(request.messages ?? []).slice(-8).map((message) => message?.text ?? ''),
|
|
@@ -3577,6 +4126,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3577
4126
|
selectedRecordSurfaceRuntimeOperationForInfo(response, request) {
|
|
3578
4127
|
if (response.type !== 'info' || !request)
|
|
3579
4128
|
return null;
|
|
4129
|
+
if (this.turnRequestsColumnVisibilityEdit(request))
|
|
4130
|
+
return null;
|
|
3580
4131
|
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
3581
4132
|
if (!this.textMentionsRecordSurfaceOpenRequest(normalizedPrompt))
|
|
3582
4133
|
return null;
|
|
@@ -3638,6 +4189,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3638
4189
|
selectedRecordSurfaceRuntimeOperationForGroundedInfo(response, request) {
|
|
3639
4190
|
if ((response.type !== 'info' && response.type !== 'clarification') || !request)
|
|
3640
4191
|
return null;
|
|
4192
|
+
if (this.turnRequestsColumnVisibilityEdit(request))
|
|
4193
|
+
return null;
|
|
3641
4194
|
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
3642
4195
|
if (!this.textMentionsRecordSurfaceOpenRequest(normalizedPrompt))
|
|
3643
4196
|
return null;
|
|
@@ -3698,6 +4251,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3698
4251
|
selectedRecordSurfaceRuntimeOperationForInvalidExecutable(response, request, warnings = []) {
|
|
3699
4252
|
if (!request || !this.responseMayContainExecutableEnvelope(response))
|
|
3700
4253
|
return null;
|
|
4254
|
+
if (this.turnRequestsColumnVisibilityEdit(request))
|
|
4255
|
+
return null;
|
|
3701
4256
|
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
3702
4257
|
const normalizedConversation = this.normalizeLabel([
|
|
3703
4258
|
...(request.messages ?? []).slice(-8).map((message) => message?.text ?? ''),
|
|
@@ -3767,6 +4322,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
3767
4322
|
selectedRecordSurfaceRuntimeOperationForOpenOnlyExecutable(response, request) {
|
|
3768
4323
|
if (!request)
|
|
3769
4324
|
return null;
|
|
4325
|
+
if (this.turnRequestsColumnVisibilityEdit(request))
|
|
4326
|
+
return null;
|
|
3770
4327
|
const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
|
|
3771
4328
|
if (!this.promptExplicitlyRequestsRecordSurfaceOpenOnly(normalizedPrompt))
|
|
3772
4329
|
return null;
|
|
@@ -4904,6 +5461,256 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4904
5461
|
],
|
|
4905
5462
|
};
|
|
4906
5463
|
}
|
|
5464
|
+
columnVisibilityPlanForMisroutedSurfaceRuntime(response, request) {
|
|
5465
|
+
if (!request)
|
|
5466
|
+
return null;
|
|
5467
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5468
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5469
|
+
return null;
|
|
5470
|
+
if (!this.patchContainsRuntimeOperationId(response.patch, 'dynamicPage.surface.open'))
|
|
5471
|
+
return null;
|
|
5472
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5473
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5474
|
+
? currentConfig['columns']
|
|
5475
|
+
.map((column) => this.toRecord(column))
|
|
5476
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5477
|
+
: [];
|
|
5478
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5479
|
+
if (!operations.length) {
|
|
5480
|
+
return {
|
|
5481
|
+
type: 'clarification',
|
|
5482
|
+
sessionId: request.sessionId,
|
|
5483
|
+
message: 'Entendi que o pedido é sobre ocultar ou exibir colunas, não sobre abrir uma superfície do registro.',
|
|
5484
|
+
questions: ['Quais colunas você quer ocultar ou exibir?'],
|
|
5485
|
+
options: columns
|
|
5486
|
+
.slice(0, 8)
|
|
5487
|
+
.map((column) => this.stringValue(column['header']) || this.stringValue(column['field']))
|
|
5488
|
+
.filter((label) => !!label),
|
|
5489
|
+
warnings: [
|
|
5490
|
+
...(response.warnings ?? []),
|
|
5491
|
+
'column-visibility-request-blocked-surface-runtime-operation',
|
|
5492
|
+
],
|
|
5493
|
+
};
|
|
5494
|
+
}
|
|
5495
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5496
|
+
...(response.warnings ?? []),
|
|
5497
|
+
'column-visibility-continued-from-surface-runtime-misroute',
|
|
5498
|
+
'Residual continuity guard acted only after the LLM proposed dynamicPage.surface.open for a column visibility/privacy request grounded in declared table columns.',
|
|
5499
|
+
]);
|
|
5500
|
+
}
|
|
5501
|
+
columnVisibilityPlanForGroundedClarification(response, request) {
|
|
5502
|
+
if (!request)
|
|
5503
|
+
return null;
|
|
5504
|
+
if (response.type !== 'clarification')
|
|
5505
|
+
return null;
|
|
5506
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5507
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5508
|
+
return null;
|
|
5509
|
+
const questionText = [
|
|
5510
|
+
response.message,
|
|
5511
|
+
...(response.questions ?? []),
|
|
5512
|
+
...(response.options ?? []),
|
|
5513
|
+
].join(' ');
|
|
5514
|
+
const asksForColumn = this.normalizedTextIncludesAny(this.normalizeLabel(questionText), [
|
|
5515
|
+
'qual coluna',
|
|
5516
|
+
'quais colunas',
|
|
5517
|
+
'coluna devo usar',
|
|
5518
|
+
'colunas devo usar',
|
|
5519
|
+
]);
|
|
5520
|
+
const asksForVisibilityScope = this.normalizedTextIncludesAny(this.normalizeLabel(questionText), [
|
|
5521
|
+
'globalmente',
|
|
5522
|
+
'todos os usuarios',
|
|
5523
|
+
'todos os usuários',
|
|
5524
|
+
'apresentacao publica',
|
|
5525
|
+
'apresentação pública',
|
|
5526
|
+
'visualizacao publica',
|
|
5527
|
+
'visualização pública',
|
|
5528
|
+
'vista padrao',
|
|
5529
|
+
'vista padrão',
|
|
5530
|
+
'confirma qual opcao',
|
|
5531
|
+
'confirma qual opção',
|
|
5532
|
+
]);
|
|
5533
|
+
if (!asksForColumn && !asksForVisibilityScope)
|
|
5534
|
+
return null;
|
|
5535
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5536
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5537
|
+
? currentConfig['columns']
|
|
5538
|
+
.map((column) => this.toRecord(column))
|
|
5539
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5540
|
+
: [];
|
|
5541
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5542
|
+
if (!operations.length)
|
|
5543
|
+
return null;
|
|
5544
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5545
|
+
...(response.warnings ?? []),
|
|
5546
|
+
'column-visibility-continued-from-grounded-clarification',
|
|
5547
|
+
'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.',
|
|
5548
|
+
]);
|
|
5549
|
+
}
|
|
5550
|
+
columnVisibilityPlanForGroundedNarrative(response, request) {
|
|
5551
|
+
if (!request)
|
|
5552
|
+
return null;
|
|
5553
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5554
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5555
|
+
return null;
|
|
5556
|
+
const responseText = this.normalizeLabel([
|
|
5557
|
+
response.message,
|
|
5558
|
+
response.explanation,
|
|
5559
|
+
response.code,
|
|
5560
|
+
].join(' '));
|
|
5561
|
+
const narratesVisibilityPlan = this.normalizedTextIncludesAny(responseText, [
|
|
5562
|
+
'componenteditplan',
|
|
5563
|
+
'column.visibility.set',
|
|
5564
|
+
'visible false',
|
|
5565
|
+
'invisivel',
|
|
5566
|
+
'invisível',
|
|
5567
|
+
'ocultar a coluna',
|
|
5568
|
+
'ocultar as colunas',
|
|
5569
|
+
]);
|
|
5570
|
+
if (!narratesVisibilityPlan)
|
|
5571
|
+
return null;
|
|
5572
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5573
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5574
|
+
? currentConfig['columns']
|
|
5575
|
+
.map((column) => this.toRecord(column))
|
|
5576
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5577
|
+
: [];
|
|
5578
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5579
|
+
if (!operations.length)
|
|
5580
|
+
return null;
|
|
5581
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5582
|
+
...(response.warnings ?? []),
|
|
5583
|
+
'column-visibility-continued-from-non-executable-narrative',
|
|
5584
|
+
'Residual continuity guard acted only after the LLM narrated a column visibility plan without returning an executable envelope.',
|
|
5585
|
+
]);
|
|
5586
|
+
}
|
|
5587
|
+
columnVisibilityPlanForMisroutedSurfaceNarrative(response, request) {
|
|
5588
|
+
if (!request)
|
|
5589
|
+
return null;
|
|
5590
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5591
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5592
|
+
return null;
|
|
5593
|
+
const responseText = this.normalizeLabel([
|
|
5594
|
+
response.message,
|
|
5595
|
+
response.explanation,
|
|
5596
|
+
response.code,
|
|
5597
|
+
...(response.warnings ?? []),
|
|
5598
|
+
].join(' '));
|
|
5599
|
+
const narratesSurfaceOpen = this.normalizedTextIncludesAny(responseText, [
|
|
5600
|
+
'dynamicpage surface open',
|
|
5601
|
+
'dynamicpage.surface.open',
|
|
5602
|
+
'surface open',
|
|
5603
|
+
'surface.open',
|
|
5604
|
+
'abrir a superficie',
|
|
5605
|
+
'abrir a superfície',
|
|
5606
|
+
'vou abrir',
|
|
5607
|
+
'superficie relacionada',
|
|
5608
|
+
'superfície relacionada',
|
|
5609
|
+
]);
|
|
5610
|
+
if (!narratesSurfaceOpen)
|
|
5611
|
+
return null;
|
|
5612
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5613
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5614
|
+
? currentConfig['columns']
|
|
5615
|
+
.map((column) => this.toRecord(column))
|
|
5616
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5617
|
+
: [];
|
|
5618
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5619
|
+
if (!operations.length) {
|
|
5620
|
+
return {
|
|
5621
|
+
type: 'clarification',
|
|
5622
|
+
sessionId: request.sessionId,
|
|
5623
|
+
message: 'Entendi que o pedido é sobre ocultar ou exibir colunas, não sobre abrir uma superfície do registro.',
|
|
5624
|
+
questions: ['Quais colunas você quer ocultar ou exibir?'],
|
|
5625
|
+
options: columns
|
|
5626
|
+
.slice(0, 8)
|
|
5627
|
+
.map((column) => this.stringValue(column['header']) || this.stringValue(column['field']))
|
|
5628
|
+
.filter((label) => !!label),
|
|
5629
|
+
warnings: [
|
|
5630
|
+
...(response.warnings ?? []),
|
|
5631
|
+
'column-visibility-request-blocked-surface-narrative',
|
|
5632
|
+
],
|
|
5633
|
+
};
|
|
5634
|
+
}
|
|
5635
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5636
|
+
...(response.warnings ?? []),
|
|
5637
|
+
'column-visibility-continued-from-surface-narrative-misroute',
|
|
5638
|
+
'Residual continuity guard acted only after the LLM narrated opening a related surface for a column visibility/privacy request grounded in declared table columns.',
|
|
5639
|
+
]);
|
|
5640
|
+
}
|
|
5641
|
+
columnVisibilityPlanForMisroutedSurfaceError(response, request, compiledError) {
|
|
5642
|
+
if (!request)
|
|
5643
|
+
return null;
|
|
5644
|
+
const prompt = this.columnVisibilityPromptForTurn(request);
|
|
5645
|
+
if (!this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(prompt)))
|
|
5646
|
+
return null;
|
|
5647
|
+
const errorText = this.normalizeLabel([
|
|
5648
|
+
response.message,
|
|
5649
|
+
response.explanation,
|
|
5650
|
+
compiledError.message,
|
|
5651
|
+
compiledError.explanation,
|
|
5652
|
+
...(compiledError.warnings ?? []),
|
|
5653
|
+
].join(' '));
|
|
5654
|
+
if (!this.normalizedTextIncludesAny(errorText, [
|
|
5655
|
+
'dynamicpage.surface.open',
|
|
5656
|
+
'surface.open',
|
|
5657
|
+
'superficie',
|
|
5658
|
+
'superfície',
|
|
5659
|
+
]))
|
|
5660
|
+
return null;
|
|
5661
|
+
const currentConfig = this.adapter.getCurrentConfig?.();
|
|
5662
|
+
const columns = Array.isArray(currentConfig?.['columns'])
|
|
5663
|
+
? currentConfig['columns']
|
|
5664
|
+
.map((column) => this.toRecord(column))
|
|
5665
|
+
.filter((column) => !!column && !!this.stringValue(column['field']))
|
|
5666
|
+
: [];
|
|
5667
|
+
const operations = this.columnVisibilityOperationsFromPrompt(prompt, columns);
|
|
5668
|
+
if (!operations.length)
|
|
5669
|
+
return null;
|
|
5670
|
+
return this.componentEditPlanResponse(operations, 'Vou ocultar as colunas indicadas para a visualizacao solicitada.', [
|
|
5671
|
+
...(response.warnings ?? []),
|
|
5672
|
+
...(compiledError.warnings ?? []),
|
|
5673
|
+
'column-visibility-continued-from-surface-runtime-error',
|
|
5674
|
+
'Residual continuity guard acted only after a misrouted surface runtime operation failed validation for a column visibility request.',
|
|
5675
|
+
]);
|
|
5676
|
+
}
|
|
5677
|
+
columnVisibilityPromptForTurn(request) {
|
|
5678
|
+
const currentPrompt = (request.prompt ?? '').trim();
|
|
5679
|
+
if (this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(currentPrompt))) {
|
|
5680
|
+
return currentPrompt;
|
|
5681
|
+
}
|
|
5682
|
+
const previousVisibilityPrompt = [...(request.messages ?? [])]
|
|
5683
|
+
.reverse()
|
|
5684
|
+
.filter((message) => message.role === 'user')
|
|
5685
|
+
.map((message) => message.text.trim())
|
|
5686
|
+
.find((message) => this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(message)));
|
|
5687
|
+
return [previousVisibilityPrompt, currentPrompt]
|
|
5688
|
+
.filter((part) => !!part)
|
|
5689
|
+
.join(' ');
|
|
5690
|
+
}
|
|
5691
|
+
turnRequestsColumnVisibilityEdit(request) {
|
|
5692
|
+
return this.promptRequestsColumnVisibilityEdit(this.normalizeLabel(this.columnVisibilityPromptForTurn(request)));
|
|
5693
|
+
}
|
|
5694
|
+
columnVisibilityOperationsFromPrompt(prompt, columns) {
|
|
5695
|
+
const hide = !this.normalizedTextIncludesAny(this.normalizeLabel(prompt), [
|
|
5696
|
+
'exibir',
|
|
5697
|
+
'mostrar coluna',
|
|
5698
|
+
'mostra coluna',
|
|
5699
|
+
'revelar',
|
|
5700
|
+
]);
|
|
5701
|
+
const operations = [];
|
|
5702
|
+
for (const column of columns) {
|
|
5703
|
+
const field = this.stringValue(column['field']);
|
|
5704
|
+
if (!field || !this.textMentionsColumn(prompt, column))
|
|
5705
|
+
continue;
|
|
5706
|
+
operations.push({
|
|
5707
|
+
operationId: 'column.visibility.set',
|
|
5708
|
+
target: { kind: 'column', field },
|
|
5709
|
+
input: { visible: !hide },
|
|
5710
|
+
});
|
|
5711
|
+
}
|
|
5712
|
+
return operations;
|
|
5713
|
+
}
|
|
4907
5714
|
requestCarriesVisualPresentationContext(request) {
|
|
4908
5715
|
const actionHints = this.toRecord(request.action?.contextHints);
|
|
4909
5716
|
const requestHints = this.toRecord(request.contextHints);
|
|
@@ -4929,6 +5736,8 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4929
5736
|
if (!normalizedPrompt)
|
|
4930
5737
|
return false;
|
|
4931
5738
|
const entry = this.filterFieldCatalogEntries.find((candidate) => candidate.name === fieldName);
|
|
5739
|
+
if (entry && this.promptMentionsFilterFieldAsNonRestrictiveScope(normalizedPrompt, entry))
|
|
5740
|
+
return false;
|
|
4932
5741
|
const rawCandidates = [
|
|
4933
5742
|
fieldName,
|
|
4934
5743
|
this.humanizeFilterField(fieldName),
|
|
@@ -4941,6 +5750,59 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
4941
5750
|
.flatMap((candidate) => this.filterFieldMentionVariants(candidate ?? ''))
|
|
4942
5751
|
.some((candidate) => candidate && this.normalizedTextContainsApproxPhrase(normalizedPrompt, candidate));
|
|
4943
5752
|
}
|
|
5753
|
+
promptMentionsFilterFieldAsNonRestrictiveScope(normalizedPrompt, entry) {
|
|
5754
|
+
const variants = [
|
|
5755
|
+
entry.name,
|
|
5756
|
+
entry.label,
|
|
5757
|
+
this.humanizeFilterField(entry.name),
|
|
5758
|
+
...entry.aliases,
|
|
5759
|
+
...entry.relatedColumnFields,
|
|
5760
|
+
...entry.relatedColumnLabels,
|
|
5761
|
+
].flatMap((candidate) => this.filterFieldMentionVariants(candidate ?? ''));
|
|
5762
|
+
return variants.some((variant) => {
|
|
5763
|
+
if (!variant)
|
|
5764
|
+
return false;
|
|
5765
|
+
return [
|
|
5766
|
+
`qualquer ${variant}`,
|
|
5767
|
+
`qq ${variant}`,
|
|
5768
|
+
`tanto faz ${variant}`,
|
|
5769
|
+
`${variant} tanto faz`,
|
|
5770
|
+
`${variant} qualquer`,
|
|
5771
|
+
`independente de ${variant}`,
|
|
5772
|
+
`nao importa ${variant}`,
|
|
5773
|
+
`${variant} nao importa`,
|
|
5774
|
+
].some((phrase) => this.normalizedTextContainsExactPhrase(normalizedPrompt, this.normalizeLabel(phrase)));
|
|
5775
|
+
});
|
|
5776
|
+
}
|
|
5777
|
+
removeNonRestrictiveFilterFieldClauses(value) {
|
|
5778
|
+
let normalized = value.trim();
|
|
5779
|
+
if (!normalized)
|
|
5780
|
+
return '';
|
|
5781
|
+
const fieldTerms = this.filterFieldCatalogEntries
|
|
5782
|
+
.flatMap((entry) => [
|
|
5783
|
+
entry.name,
|
|
5784
|
+
entry.label,
|
|
5785
|
+
this.humanizeFilterField(entry.name),
|
|
5786
|
+
...entry.aliases,
|
|
5787
|
+
...entry.relatedColumnFields,
|
|
5788
|
+
...entry.relatedColumnLabels,
|
|
5789
|
+
])
|
|
5790
|
+
.flatMap((term) => this.filterFieldMentionVariants(term ?? ''))
|
|
5791
|
+
.filter((term, index, terms) => !!term && terms.indexOf(term) === index);
|
|
5792
|
+
for (const term of fieldTerms) {
|
|
5793
|
+
const escaped = term.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
5794
|
+
normalized = normalized
|
|
5795
|
+
.replace(new RegExp(`(?:,|;)?\\s*(?:tanto faz|qualquer|qq|independente de|nao importa|não importa)\\s+${escaped}\\b`, 'giu'), '')
|
|
5796
|
+
.replace(new RegExp(`(?:,|;)?\\s*${escaped}\\s+(?:tanto faz|qualquer|nao importa|não importa)\\b`, 'giu'), '');
|
|
5797
|
+
}
|
|
5798
|
+
return normalized.trim();
|
|
5799
|
+
}
|
|
5800
|
+
normalizedTextContainsExactPhrase(normalizedText, normalizedPhrase) {
|
|
5801
|
+
if (!normalizedText || !normalizedPhrase)
|
|
5802
|
+
return false;
|
|
5803
|
+
const escaped = normalizedPhrase.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&').replace(/\s+/gu, '\\s+');
|
|
5804
|
+
return new RegExp(`(^|[^a-z0-9])${escaped}($|[^a-z0-9])`, 'u').test(normalizedText);
|
|
5805
|
+
}
|
|
4944
5806
|
selectedRecordFilterPromptGroundingScore(prompt, candidate) {
|
|
4945
5807
|
const fieldName = this.stringValue(candidate['field']);
|
|
4946
5808
|
if (!fieldName)
|
|
@@ -5493,7 +6355,20 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
5493
6355
|
}
|
|
5494
6356
|
buildClarificationDiagnostics(response) {
|
|
5495
6357
|
const continuation = this.extractPendingComponentEditContinuation(response);
|
|
5496
|
-
|
|
6358
|
+
const responseDiagnostics = this.toRecord(response.diagnostics);
|
|
6359
|
+
if (!continuation && !responseDiagnostics)
|
|
6360
|
+
return undefined;
|
|
6361
|
+
return {
|
|
6362
|
+
...(responseDiagnostics ?? {}),
|
|
6363
|
+
...(continuation ? { tableComponentEditContinuation: continuation } : {}),
|
|
6364
|
+
};
|
|
6365
|
+
}
|
|
6366
|
+
pendingClarificationSourcePromptForTurn(request, diagnostics) {
|
|
6367
|
+
const declaredFilter = this.toRecord(diagnostics?.['tableDeclaredFilterClarification']);
|
|
6368
|
+
return this.stringValue(declaredFilter?.['sourcePrompt']).trim()
|
|
6369
|
+
|| request.pendingClarification?.sourcePrompt?.trim()
|
|
6370
|
+
|| request.prompt?.trim()
|
|
6371
|
+
|| '';
|
|
5497
6372
|
}
|
|
5498
6373
|
buildReviewDiagnostics(response, warnings) {
|
|
5499
6374
|
const memory = this.extractComponentEditDecisionMemory(response);
|
|
@@ -6377,6 +7252,9 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6377
7252
|
const normalizedOptions = new Set(options
|
|
6378
7253
|
.map((option) => this.normalizeLabel(option))
|
|
6379
7254
|
.filter((option) => !!option));
|
|
7255
|
+
if (this.promptRequestsColumnVisibilityEdit(prompt)) {
|
|
7256
|
+
return null;
|
|
7257
|
+
}
|
|
6380
7258
|
const promptLooksLikeFilter = this.promptRequestsRuntimeFilter(prompt)
|
|
6381
7259
|
|| ['filtro', 'filtrar', 'busca', 'buscar', 'procura', 'procurar', 'mostra', 'mostrar'].some((token) => this.normalizedTextContainsApproxToken(prompt, token));
|
|
6382
7260
|
const responseLooksFilterFieldClarification = responseText.includes('filtro declarado')
|
|
@@ -6538,7 +7416,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6538
7416
|
return quoted;
|
|
6539
7417
|
const match = trimmed.match(/\b(?:de|da|do|dos|das|por|com|contendo|contem|contém)\s+(.{2,})$/iu);
|
|
6540
7418
|
const candidate = (match?.[1] ?? '').trim();
|
|
6541
|
-
return candidate
|
|
7419
|
+
return this.removeNonRestrictiveFilterFieldClauses(candidate)
|
|
6542
7420
|
.replace(/[?.!,;:]+$/u, '')
|
|
6543
7421
|
.trim();
|
|
6544
7422
|
}
|
|
@@ -6576,6 +7454,7 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6576
7454
|
};
|
|
6577
7455
|
});
|
|
6578
7456
|
}
|
|
7457
|
+
return [];
|
|
6579
7458
|
}
|
|
6580
7459
|
if ((response.type === 'clarification' || response.type === 'info')
|
|
6581
7460
|
&& this.shouldCurateVisibilityClarificationQuickReplies(response, prompt)) {
|
|
@@ -6684,6 +7563,49 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6684
7563
|
// semantic scope choices the user needs to answer.
|
|
6685
7564
|
return true;
|
|
6686
7565
|
}
|
|
7566
|
+
promptRequestsColumnVisibilityEdit(normalizedPrompt) {
|
|
7567
|
+
if (!normalizedPrompt)
|
|
7568
|
+
return false;
|
|
7569
|
+
const asksVisibilityOrPrivacy = [
|
|
7570
|
+
'ocultacao',
|
|
7571
|
+
'ocultação',
|
|
7572
|
+
'oculta',
|
|
7573
|
+
'ocultar',
|
|
7574
|
+
'esconde',
|
|
7575
|
+
'esconder',
|
|
7576
|
+
'remova a coluna',
|
|
7577
|
+
'remover a coluna',
|
|
7578
|
+
'remova as colunas',
|
|
7579
|
+
'remover as colunas',
|
|
7580
|
+
'tirar da visualizacao',
|
|
7581
|
+
'tirar da visualização',
|
|
7582
|
+
'publico',
|
|
7583
|
+
'público',
|
|
7584
|
+
'privacidade',
|
|
7585
|
+
'sensivel',
|
|
7586
|
+
'sensível',
|
|
7587
|
+
].some((token) => this.normalizedTextContainsApproxPhrase(normalizedPrompt, token));
|
|
7588
|
+
if (!asksVisibilityOrPrivacy)
|
|
7589
|
+
return false;
|
|
7590
|
+
const mentionsColumnScope = [
|
|
7591
|
+
'coluna',
|
|
7592
|
+
'colunas',
|
|
7593
|
+
'visualizacao',
|
|
7594
|
+
'visualização',
|
|
7595
|
+
'tabela',
|
|
7596
|
+
'email',
|
|
7597
|
+
'e-mail',
|
|
7598
|
+
'salario',
|
|
7599
|
+
'salário',
|
|
7600
|
+
'cpf',
|
|
7601
|
+
'documento',
|
|
7602
|
+
'telefone',
|
|
7603
|
+
].some((token) => this.normalizedTextContainsApproxPhrase(normalizedPrompt, token));
|
|
7604
|
+
// Residual guard only: the LLM/authoring contract still decides the primary
|
|
7605
|
+
// intent. Once a turn is already in a column-visibility scope, filter
|
|
7606
|
+
// quick-reply curation must not reinterpret it as row filtering.
|
|
7607
|
+
return mentionsColumnScope;
|
|
7608
|
+
}
|
|
6687
7609
|
visibilityClarificationQuickReplyOptions() {
|
|
6688
7610
|
return [
|
|
6689
7611
|
{
|
|
@@ -6728,6 +7650,10 @@ class TableAgenticAuthoringTurnFlow {
|
|
|
6728
7650
|
const optionCount = response.options?.length ?? 0;
|
|
6729
7651
|
if (payloadCount <= 0 && optionCount <= 0)
|
|
6730
7652
|
return false;
|
|
7653
|
+
if (this.promptRequestsColumnVisibilityEdit(normalizedPrompt))
|
|
7654
|
+
return false;
|
|
7655
|
+
if (payloadCount > 0 && normalizedPrompt && !this.promptRequestsRuntimeFilter(normalizedPrompt))
|
|
7656
|
+
return false;
|
|
6731
7657
|
if (this.responseAsksForDeclaredFilterField(response))
|
|
6732
7658
|
return true;
|
|
6733
7659
|
if (!normalizedPrompt || !this.promptRequestsRuntimeFilter(normalizedPrompt))
|