@praxisui/page-builder 8.0.0-beta.27 → 8.0.0-beta.29
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 +1 -0
- package/fesm2022/praxisui-page-builder.mjs +1163 -82
- package/index.d.ts +20 -1
- package/package.json +4 -4
|
@@ -25,7 +25,7 @@ import * as i6$1 from '@angular/material/divider';
|
|
|
25
25
|
import { MatDividerModule } from '@angular/material/divider';
|
|
26
26
|
import * as i6$2 from '@angular/material/select';
|
|
27
27
|
import { MatSelectModule } from '@angular/material/select';
|
|
28
|
-
import { BehaviorSubject, merge, timeout, map, switchMap, Observable,
|
|
28
|
+
import { BehaviorSubject, merge, timeout, map, switchMap, Observable, from, firstValueFrom, concatMap, catchError, of, filter, take } from 'rxjs';
|
|
29
29
|
import { SETTINGS_PANEL_DATA } from '@praxisui/settings-panel';
|
|
30
30
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
31
31
|
import * as i7 from '@angular/material/tabs';
|
|
@@ -2401,13 +2401,14 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2401
2401
|
'praxis.pageBuilder.agentic.panelAria': 'AI page authoring',
|
|
2402
2402
|
'praxis.pageBuilder.agentic.title': 'Praxis semantic copilot',
|
|
2403
2403
|
'praxis.pageBuilder.agentic.subtitle': 'Author governed decisions with previews, confirmation, and runtime materialization.',
|
|
2404
|
-
'praxis.pageBuilder.agentic.header.title.page': 'Praxis page copilot',
|
|
2404
|
+
'praxis.pageBuilder.agentic.header.title.page': 'Praxis page decision copilot',
|
|
2405
2405
|
'praxis.pageBuilder.agentic.header.title.widget': 'Praxis widget copilot',
|
|
2406
2406
|
'praxis.pageBuilder.agentic.header.title.review': 'Praxis review copilot',
|
|
2407
2407
|
'praxis.pageBuilder.agentic.header.title.governed': 'Praxis governed copilot',
|
|
2408
|
-
'praxis.pageBuilder.agentic.header.subtitle.page': '
|
|
2408
|
+
'praxis.pageBuilder.agentic.header.subtitle.page': 'Turn intent into layout, widgets, and governed materializations.',
|
|
2409
2409
|
'praxis.pageBuilder.agentic.header.subtitle.route': 'Authoring page route {route}.',
|
|
2410
2410
|
'praxis.pageBuilder.agentic.header.subtitle.widget': 'Focused on {target}.',
|
|
2411
|
+
'praxis.pageBuilder.agentic.header.subtitle.reviewBlocked': 'Preview ready for governed review.',
|
|
2411
2412
|
'praxis.pageBuilder.agentic.header.subtitle.review': 'Preview ready for review and persistence.',
|
|
2412
2413
|
'praxis.pageBuilder.agentic.header.subtitle.governed': 'Continue the governed semantic-decision flow.',
|
|
2413
2414
|
'praxis.pageBuilder.agentic.header.mode.page': 'Page',
|
|
@@ -2429,7 +2430,9 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2429
2430
|
'praxis.pageBuilder.agentic.dock.summaryIdle': 'Conversation preserved. Continue where you stopped.',
|
|
2430
2431
|
'praxis.pageBuilder.agentic.promptLabel': 'Message',
|
|
2431
2432
|
'praxis.pageBuilder.agentic.promptPlaceholder': 'Describe the page, dashboard, form, or change you need.',
|
|
2432
|
-
'praxis.pageBuilder.agentic.emptyConversation': '
|
|
2433
|
+
'praxis.pageBuilder.agentic.emptyConversation': 'Describe the outcome you want. I will ground the context, prepare a governed preview, and wait for review before applying anything.',
|
|
2434
|
+
'praxis.pageBuilder.agentic.emptyConversation.blankGeneric': 'This host page is still blank. Tell me what decision or activity this app needs to support. I can suggest a dashboard, table, form, or review flow, then turn it into a governed preview for you to review before anything changes.',
|
|
2435
|
+
'praxis.pageBuilder.agentic.emptyConversation.existingPage': 'Tell me what you want to improve here. I can read the current layout, widgets, route, and governed context, then prepare a preview for you to review before anything changes.',
|
|
2433
2436
|
'praxis.pageBuilder.agentic.conversationAria': 'AI conversation',
|
|
2434
2437
|
'praxis.pageBuilder.agentic.quickRepliesAria': 'Quick replies',
|
|
2435
2438
|
'praxis.pageBuilder.agentic.contextAria': 'Active context',
|
|
@@ -2445,6 +2448,23 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2445
2448
|
'praxis.pageBuilder.agentic.context.governedDomainContextRequest': 'Requested context',
|
|
2446
2449
|
'praxis.pageBuilder.agentic.context.governedDomainContextSize': 'Grounding size',
|
|
2447
2450
|
'praxis.pageBuilder.agentic.context.sharedRuleTargetLayer': 'Target materialization',
|
|
2451
|
+
'praxis.pageBuilder.agentic.context.semanticDecisionResource': 'Source',
|
|
2452
|
+
'praxis.pageBuilder.agentic.context.semanticDecisionKind': 'Goal',
|
|
2453
|
+
'praxis.pageBuilder.agentic.context.semanticDecisionEvidence': 'Review',
|
|
2454
|
+
'praxis.pageBuilder.agentic.context.operationCreate': 'Create',
|
|
2455
|
+
'praxis.pageBuilder.agentic.context.operationUpdate': 'Adjust',
|
|
2456
|
+
'praxis.pageBuilder.agentic.context.operationRead': 'Explore',
|
|
2457
|
+
'praxis.pageBuilder.agentic.context.artifactDashboard': 'dashboard',
|
|
2458
|
+
'praxis.pageBuilder.agentic.context.artifactTable': 'table',
|
|
2459
|
+
'praxis.pageBuilder.agentic.context.artifactForm': 'form',
|
|
2460
|
+
'praxis.pageBuilder.agentic.context.artifactPage': 'screen',
|
|
2461
|
+
'praxis.pageBuilder.agentic.context.changeAnalytics': 'with analysis',
|
|
2462
|
+
'praxis.pageBuilder.agentic.context.changeDashboard': 'with dashboard view',
|
|
2463
|
+
'praxis.pageBuilder.agentic.context.changeTable': 'with details',
|
|
2464
|
+
'praxis.pageBuilder.agentic.context.changeForm': 'with editing',
|
|
2465
|
+
'praxis.pageBuilder.agentic.context.evidenceReviewRequired': 'Needs field review',
|
|
2466
|
+
'praxis.pageBuilder.agentic.context.evidenceLowConfidence': 'Needs source confirmation',
|
|
2467
|
+
'praxis.pageBuilder.agentic.context.evidenceGrounded': 'Source confirmed',
|
|
2448
2468
|
'praxis.pageBuilder.agentic.editMessage': 'Edit',
|
|
2449
2469
|
'praxis.pageBuilder.agentic.resendMessage': 'Resend',
|
|
2450
2470
|
'praxis.pageBuilder.agentic.removeAttachment': 'Remove attachment',
|
|
@@ -2454,7 +2474,7 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2454
2474
|
'praxis.pageBuilder.agentic.mode.diagnostic': 'Diagnostic',
|
|
2455
2475
|
'praxis.pageBuilder.agentic.mode.review': 'Review',
|
|
2456
2476
|
'praxis.pageBuilder.agentic.mode.inlineHelp': 'Help',
|
|
2457
|
-
'praxis.pageBuilder.agentic.state.idle': '
|
|
2477
|
+
'praxis.pageBuilder.agentic.state.idle': 'Ready',
|
|
2458
2478
|
'praxis.pageBuilder.agentic.state.listening': 'Ready',
|
|
2459
2479
|
'praxis.pageBuilder.agentic.state.processing': 'Processing',
|
|
2460
2480
|
'praxis.pageBuilder.agentic.state.clarification': 'Waiting for input',
|
|
@@ -2486,9 +2506,16 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2486
2506
|
'praxis.pageBuilder.agentic.exploratory.capability.table': 'tables',
|
|
2487
2507
|
'praxis.pageBuilder.agentic.exploratory.capability.form': 'forms',
|
|
2488
2508
|
'praxis.pageBuilder.agentic.exploratory.capability.masterDetail': 'master-detail pages',
|
|
2489
|
-
'praxis.pageBuilder.agentic.resourceDiscovery.found': 'I found
|
|
2509
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.found': 'I found {sourceCount} for this screen. I recommend starting with {first} because it is the best fit for charts, KPIs, and drill-down. Review the cards below to see what each source is good for, what it returns, and what I will create after you select it.',
|
|
2510
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.sourceCountSingular': '1 candidate source',
|
|
2511
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.sourceCountPlural': '{count} candidate sources',
|
|
2490
2512
|
'praxis.pageBuilder.agentic.resourceDiscovery.empty': 'I did not find a matching API yet. Describe the business data this screen should use.',
|
|
2491
2513
|
'praxis.pageBuilder.agentic.resourceDiscovery.useResource': 'Use {resourcePath}',
|
|
2514
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.defaultRecommendedLabel': 'the first option',
|
|
2515
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardDescription': 'Recommended source for turning {label} into a dashboard: helps choose charts, lists, filters, and formats before materializing the screen.',
|
|
2516
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardBestFor': 'Use when you want to understand whether {label} answers the business goal before creating widgets.',
|
|
2517
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardReturns': 'Suggests metrics, dimensions, filters, value formats, charts, and detail lists compatible with the source.',
|
|
2518
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardNextStep': 'Select it so I can propose a governed preview with rich cards, drill-down, and sensible default formats.',
|
|
2492
2519
|
'praxis.pageBuilder.agentic.diagnostics.title': 'LLM diagnostics',
|
|
2493
2520
|
'praxis.pageBuilder.agentic.diagnostics.badge': 'Debug',
|
|
2494
2521
|
'praxis.pageBuilder.agentic.diagnostics.description': 'Prompt, context bundle, and tool catalog returned by the backend for this turn.',
|
|
@@ -2510,10 +2537,12 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2510
2537
|
'praxis.pageBuilder.agentic.status.refinedCandidates': 'Reviewing the retrieved resources with the AI...',
|
|
2511
2538
|
'praxis.pageBuilder.agentic.status.projectKnowledgeRetrieved': 'Retrieved governed project knowledge for this authoring turn.',
|
|
2512
2539
|
'praxis.pageBuilder.agentic.status.projectKnowledgeRetrievedCount': 'Retrieved {count} governed project knowledge signals for this authoring turn.',
|
|
2513
|
-
'praxis.pageBuilder.agentic.status.projectKnowledgeAuditCited': '{cited} of {count}
|
|
2540
|
+
'praxis.pageBuilder.agentic.status.projectKnowledgeAuditCited': 'Governed knowledge cited: {cited} of {count}.',
|
|
2514
2541
|
'praxis.pageBuilder.agentic.status.previewing': 'Generating preview...',
|
|
2515
2542
|
'praxis.pageBuilder.agentic.status.previewCompile': 'Compiling preview...',
|
|
2516
2543
|
'praxis.pageBuilder.agentic.status.previewReady': 'Preview applied to the page.',
|
|
2544
|
+
'praxis.pageBuilder.agentic.status.reviewReady': 'Ready for review.',
|
|
2545
|
+
'praxis.pageBuilder.agentic.status.reviewNeedsAttention': 'Review the pending points before saving.',
|
|
2517
2546
|
'praxis.pageBuilder.agentic.status.acceptedAddLocalField': 'Local field added to the form.',
|
|
2518
2547
|
'praxis.pageBuilder.agentic.status.acceptedRemoveLocalField': 'Local field removed from the form.',
|
|
2519
2548
|
'praxis.pageBuilder.agentic.status.acceptedRelabelField': 'Field label updated.',
|
|
@@ -2820,9 +2849,10 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2820
2849
|
'praxis.pageBuilder.agentic.header.title.widget': 'Copiloto de componente Praxis',
|
|
2821
2850
|
'praxis.pageBuilder.agentic.header.title.review': 'Copiloto de revisão Praxis',
|
|
2822
2851
|
'praxis.pageBuilder.agentic.header.title.governed': 'Copiloto governado Praxis',
|
|
2823
|
-
'praxis.pageBuilder.agentic.header.subtitle.page': '
|
|
2852
|
+
'praxis.pageBuilder.agentic.header.subtitle.page': 'Transforme intenção em layout, widgets e materializações governadas.',
|
|
2824
2853
|
'praxis.pageBuilder.agentic.header.subtitle.route': 'Autoria da rota {route}.',
|
|
2825
2854
|
'praxis.pageBuilder.agentic.header.subtitle.widget': 'Foco em {target}.',
|
|
2855
|
+
'praxis.pageBuilder.agentic.header.subtitle.reviewBlocked': 'Prévia pronta para revisão governada.',
|
|
2826
2856
|
'praxis.pageBuilder.agentic.header.subtitle.review': 'Prévia pronta para revisão e persistência.',
|
|
2827
2857
|
'praxis.pageBuilder.agentic.header.subtitle.governed': 'Continue o fluxo governado de decisão semântica.',
|
|
2828
2858
|
'praxis.pageBuilder.agentic.header.mode.page': 'Página',
|
|
@@ -2844,7 +2874,9 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2844
2874
|
'praxis.pageBuilder.agentic.dock.summaryIdle': 'Conversa preservada. Continue de onde parou.',
|
|
2845
2875
|
'praxis.pageBuilder.agentic.promptLabel': 'Mensagem',
|
|
2846
2876
|
'praxis.pageBuilder.agentic.promptPlaceholder': 'Descreva a página, dashboard, formulário ou alteração que você precisa.',
|
|
2847
|
-
'praxis.pageBuilder.agentic.emptyConversation': '
|
|
2877
|
+
'praxis.pageBuilder.agentic.emptyConversation': 'Descreva o resultado que você quer. Vou fundamentar o contexto, preparar uma prévia governada e aguardar revisão antes de aplicar qualquer mudança.',
|
|
2878
|
+
'praxis.pageBuilder.agentic.emptyConversation.blankGeneric': 'Esta página do host ainda está em branco. Conte qual decisão ou atividade este app precisa apoiar. Posso sugerir um dashboard, tabela, formulário ou fluxo de revisão e transformar isso em uma prévia governada para você revisar antes de qualquer mudança.',
|
|
2879
|
+
'praxis.pageBuilder.agentic.emptyConversation.existingPage': 'Conte o que você quer melhorar aqui. Posso ler o layout atual, widgets, rota e contexto governado, depois preparar uma prévia para você revisar antes de qualquer mudança.',
|
|
2848
2880
|
'praxis.pageBuilder.agentic.conversationAria': 'Conversa com IA',
|
|
2849
2881
|
'praxis.pageBuilder.agentic.quickRepliesAria': 'Respostas rápidas',
|
|
2850
2882
|
'praxis.pageBuilder.agentic.contextAria': 'Contexto ativo',
|
|
@@ -2860,6 +2892,23 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2860
2892
|
'praxis.pageBuilder.agentic.context.governedDomainContextRequest': 'Contexto solicitado',
|
|
2861
2893
|
'praxis.pageBuilder.agentic.context.governedDomainContextSize': 'Tamanho do grounding',
|
|
2862
2894
|
'praxis.pageBuilder.agentic.context.sharedRuleTargetLayer': 'Materialização alvo',
|
|
2895
|
+
'praxis.pageBuilder.agentic.context.semanticDecisionResource': 'Fonte',
|
|
2896
|
+
'praxis.pageBuilder.agentic.context.semanticDecisionKind': 'Objetivo',
|
|
2897
|
+
'praxis.pageBuilder.agentic.context.semanticDecisionEvidence': 'Revisão',
|
|
2898
|
+
'praxis.pageBuilder.agentic.context.operationCreate': 'Criar',
|
|
2899
|
+
'praxis.pageBuilder.agentic.context.operationUpdate': 'Ajustar',
|
|
2900
|
+
'praxis.pageBuilder.agentic.context.operationRead': 'Consultar',
|
|
2901
|
+
'praxis.pageBuilder.agentic.context.artifactDashboard': 'dashboard',
|
|
2902
|
+
'praxis.pageBuilder.agentic.context.artifactTable': 'tabela',
|
|
2903
|
+
'praxis.pageBuilder.agentic.context.artifactForm': 'formulário',
|
|
2904
|
+
'praxis.pageBuilder.agentic.context.artifactPage': 'tela',
|
|
2905
|
+
'praxis.pageBuilder.agentic.context.changeAnalytics': 'com análise',
|
|
2906
|
+
'praxis.pageBuilder.agentic.context.changeDashboard': 'com visão gerencial',
|
|
2907
|
+
'praxis.pageBuilder.agentic.context.changeTable': 'com detalhes',
|
|
2908
|
+
'praxis.pageBuilder.agentic.context.changeForm': 'com edição',
|
|
2909
|
+
'praxis.pageBuilder.agentic.context.evidenceReviewRequired': 'Precisa revisar campos',
|
|
2910
|
+
'praxis.pageBuilder.agentic.context.evidenceLowConfidence': 'Precisa confirmar fonte',
|
|
2911
|
+
'praxis.pageBuilder.agentic.context.evidenceGrounded': 'Fonte confirmada',
|
|
2863
2912
|
'praxis.pageBuilder.agentic.editMessage': 'Editar',
|
|
2864
2913
|
'praxis.pageBuilder.agentic.resendMessage': 'Reenviar',
|
|
2865
2914
|
'praxis.pageBuilder.agentic.removeAttachment': 'Remover anexo',
|
|
@@ -2869,7 +2918,7 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2869
2918
|
'praxis.pageBuilder.agentic.mode.diagnostic': 'Diagnóstico',
|
|
2870
2919
|
'praxis.pageBuilder.agentic.mode.review': 'Revisão',
|
|
2871
2920
|
'praxis.pageBuilder.agentic.mode.inlineHelp': 'Ajuda',
|
|
2872
|
-
'praxis.pageBuilder.agentic.state.idle': '
|
|
2921
|
+
'praxis.pageBuilder.agentic.state.idle': 'Pronto',
|
|
2873
2922
|
'praxis.pageBuilder.agentic.state.listening': 'Pronto',
|
|
2874
2923
|
'praxis.pageBuilder.agentic.state.processing': 'Processando',
|
|
2875
2924
|
'praxis.pageBuilder.agentic.state.clarification': 'Aguardando resposta',
|
|
@@ -2901,9 +2950,16 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2901
2950
|
'praxis.pageBuilder.agentic.exploratory.capability.table': 'tabelas',
|
|
2902
2951
|
'praxis.pageBuilder.agentic.exploratory.capability.form': 'formulários',
|
|
2903
2952
|
'praxis.pageBuilder.agentic.exploratory.capability.masterDetail': 'páginas master-detail',
|
|
2904
|
-
'praxis.pageBuilder.agentic.resourceDiscovery.found': 'Encontrei
|
|
2953
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.found': 'Encontrei {sourceCount} para esta tela. Minha recomendação é começar por {first}, porque parece a melhor opção para gráficos, KPIs e drill-down. Revise os cards abaixo para entender quando usar cada fonte, o que ela retorna e o que eu vou criar depois da seleção.',
|
|
2954
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.sourceCountSingular': '1 fonte candidata',
|
|
2955
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.sourceCountPlural': '{count} fontes candidatas',
|
|
2905
2956
|
'praxis.pageBuilder.agentic.resourceDiscovery.empty': 'Ainda não encontrei uma API correspondente. Descreva quais dados de negócio esta tela deve usar.',
|
|
2906
2957
|
'praxis.pageBuilder.agentic.resourceDiscovery.useResource': 'Usar {resourcePath}',
|
|
2958
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.defaultRecommendedLabel': 'a primeira opção',
|
|
2959
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardDescription': 'Fonte recomendada para transformar {label} em painel: ajuda a escolher gráficos, listas, filtros e formatos antes de materializar a tela.',
|
|
2960
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardBestFor': 'Quando você quer entender se {label} responde ao objetivo de negócio antes de criar widgets.',
|
|
2961
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardReturns': 'Sugere métricas, dimensões, filtros, formatos de valor, gráficos e listas de detalhe compatíveis com a fonte.',
|
|
2962
|
+
'praxis.pageBuilder.agentic.resourceDiscovery.cardNextStep': 'Selecione para eu propor uma pré-visualização governada com cards ricos, drill-down e formatos adequados por padrão.',
|
|
2907
2963
|
'praxis.pageBuilder.agentic.diagnostics.title': 'Diagnóstico do LLM',
|
|
2908
2964
|
'praxis.pageBuilder.agentic.diagnostics.badge': 'Debug',
|
|
2909
2965
|
'praxis.pageBuilder.agentic.diagnostics.description': 'Prompt, pacote de contexto e catálogo de ferramentas retornados pelo backend para este turno.',
|
|
@@ -2925,10 +2981,12 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
2925
2981
|
'praxis.pageBuilder.agentic.status.refinedCandidates': 'Estou revisando os recursos encontrados com a IA...',
|
|
2926
2982
|
'praxis.pageBuilder.agentic.status.projectKnowledgeRetrieved': 'Recuperei conhecimento governado do projeto para este turno de autoria.',
|
|
2927
2983
|
'praxis.pageBuilder.agentic.status.projectKnowledgeRetrievedCount': 'Recuperei {count} sinais de conhecimento governado do projeto para este turno.',
|
|
2928
|
-
'praxis.pageBuilder.agentic.status.projectKnowledgeAuditCited': '{cited} de {count}
|
|
2984
|
+
'praxis.pageBuilder.agentic.status.projectKnowledgeAuditCited': 'Conhecimento governado citado: {cited} de {count}.',
|
|
2929
2985
|
'praxis.pageBuilder.agentic.status.previewing': 'Gerando pré-visualização...',
|
|
2930
2986
|
'praxis.pageBuilder.agentic.status.previewCompile': 'Compilando pré-visualização...',
|
|
2931
2987
|
'praxis.pageBuilder.agentic.status.previewReady': 'Pré-visualização aplicada à página.',
|
|
2988
|
+
'praxis.pageBuilder.agentic.status.reviewReady': 'Pronto para revisar.',
|
|
2989
|
+
'praxis.pageBuilder.agentic.status.reviewNeedsAttention': 'Revise os pontos pendentes antes de salvar.',
|
|
2932
2990
|
'praxis.pageBuilder.agentic.status.acceptedAddLocalField': 'Campo local adicionado ao formulário.',
|
|
2933
2991
|
'praxis.pageBuilder.agentic.status.acceptedRemoveLocalField': 'Campo local removido do formulário.',
|
|
2934
2992
|
'praxis.pageBuilder.agentic.status.acceptedRelabelField': 'Rótulo do campo atualizado.',
|
|
@@ -11134,7 +11192,7 @@ function providePageBuilderWidgetAiCatalogs() {
|
|
|
11134
11192
|
|
|
11135
11193
|
const DEFAULT_AGENTIC_AUTHORING_REQUEST_TIMEOUT_MS = 15000;
|
|
11136
11194
|
const DEFAULT_TURN_STREAM_START_TIMEOUT_MS = 10000;
|
|
11137
|
-
const DEFAULT_TURN_STREAM_TIMEOUT_MS =
|
|
11195
|
+
const DEFAULT_TURN_STREAM_TIMEOUT_MS = 240000;
|
|
11138
11196
|
const PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS = new InjectionToken('PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS');
|
|
11139
11197
|
class PageBuilderAgenticAuthoringService {
|
|
11140
11198
|
http = inject(HttpClient);
|
|
@@ -11166,6 +11224,7 @@ class PageBuilderAgenticAuthoringService {
|
|
|
11166
11224
|
scope: body.scope,
|
|
11167
11225
|
tags: body.tags,
|
|
11168
11226
|
compiledFormPatch: body.compiledFormPatch,
|
|
11227
|
+
semanticDecision: body.semanticDecision ?? null,
|
|
11169
11228
|
}, {
|
|
11170
11229
|
headers: this.buildHeaders(ifMatch ? { 'If-Match': this.formatEtag(ifMatch) } : undefined),
|
|
11171
11230
|
});
|
|
@@ -11544,7 +11603,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
|
|
|
11544
11603
|
{ name: 'pageChange', type: 'WidgetPageDefinition', description: 'Emitted after local apply/preview produces a renderable page.' },
|
|
11545
11604
|
{ name: 'agenticAuthoringEnableStreaming', type: 'boolean', description: 'Opt-in flag for the canonical streaming turn endpoints.' },
|
|
11546
11605
|
{ name: 'agenticAuthoringIncludeLlmDiagnostics', type: 'boolean', description: 'Opt-in flag that exposes governed diagnostics as cockpit evidence for validation and debugging.' },
|
|
11547
|
-
{ name: 'agenticAuthoringContextHints', type: 'Record<string, unknown>', description: 'Host-provided semantic hints, including governed domain-catalog references used to ground AI-authored decisions.' },
|
|
11606
|
+
{ name: 'agenticAuthoringContextHints', type: 'Record<string, unknown>', description: 'Host-provided semantic hints, including governed domain-catalog references and optional RAG-authored openingMessage used to ground AI-authored decisions.' },
|
|
11548
11607
|
],
|
|
11549
11608
|
editableTargets: [
|
|
11550
11609
|
{ kind: 'page', resolver: 'widget-page-definition-root', description: 'Root WidgetPageDefinition document: title, metadata, context and renderable page envelope.' },
|
|
@@ -12328,6 +12387,84 @@ function clone(value) {
|
|
|
12328
12387
|
}
|
|
12329
12388
|
}
|
|
12330
12389
|
|
|
12390
|
+
const RUNTIME_AUTHORING_METADATA_INPUTS = [
|
|
12391
|
+
'schemaVerification',
|
|
12392
|
+
'schemaEvidenceSource',
|
|
12393
|
+
'schemaEvidenceUrl',
|
|
12394
|
+
];
|
|
12395
|
+
function normalizePageBuilderRuntimePage(page) {
|
|
12396
|
+
if (!page?.widgets?.length) {
|
|
12397
|
+
return page;
|
|
12398
|
+
}
|
|
12399
|
+
return {
|
|
12400
|
+
...page,
|
|
12401
|
+
widgets: page.widgets.map((widget) => normalizePageBuilderRuntimeWidget(widget)),
|
|
12402
|
+
};
|
|
12403
|
+
}
|
|
12404
|
+
function normalizePageBuilderRuntimeWidget(widget) {
|
|
12405
|
+
const definition = widget.definition;
|
|
12406
|
+
if (!definition?.inputs) {
|
|
12407
|
+
return widget;
|
|
12408
|
+
}
|
|
12409
|
+
const inputs = { ...definition.inputs };
|
|
12410
|
+
for (const key of RUNTIME_AUTHORING_METADATA_INPUTS) {
|
|
12411
|
+
delete inputs[key];
|
|
12412
|
+
}
|
|
12413
|
+
if (definition.id === 'praxis-rich-content') {
|
|
12414
|
+
if (inputs['kpis'] !== undefined) {
|
|
12415
|
+
const document = isRecord(inputs['document']) ? inputs['document'] : {};
|
|
12416
|
+
inputs['document'] = {
|
|
12417
|
+
...document,
|
|
12418
|
+
kpis: document['kpis'] ?? inputs['kpis'],
|
|
12419
|
+
};
|
|
12420
|
+
}
|
|
12421
|
+
delete inputs['kpis'];
|
|
12422
|
+
delete inputs['resourcePath'];
|
|
12423
|
+
delete inputs['schemaUrl'];
|
|
12424
|
+
}
|
|
12425
|
+
if (definition.id === 'praxis-filter') {
|
|
12426
|
+
if (!String(inputs['resourcePath'] || '').trim()) {
|
|
12427
|
+
const inferredResourcePath = inferResourcePathFromSchemaUrl(inputs['schemaUrl']);
|
|
12428
|
+
if (inferredResourcePath) {
|
|
12429
|
+
inputs['resourcePath'] = inferredResourcePath;
|
|
12430
|
+
}
|
|
12431
|
+
}
|
|
12432
|
+
delete inputs['schemaUrl'];
|
|
12433
|
+
}
|
|
12434
|
+
if (definition.id === 'praxis-table') {
|
|
12435
|
+
delete inputs['title'];
|
|
12436
|
+
delete inputs['schemaUrl'];
|
|
12437
|
+
delete inputs['submitUrl'];
|
|
12438
|
+
delete inputs['submitMethod'];
|
|
12439
|
+
}
|
|
12440
|
+
return {
|
|
12441
|
+
...widget,
|
|
12442
|
+
definition: {
|
|
12443
|
+
...definition,
|
|
12444
|
+
inputs,
|
|
12445
|
+
},
|
|
12446
|
+
};
|
|
12447
|
+
}
|
|
12448
|
+
function inferResourcePathFromSchemaUrl(schemaUrl) {
|
|
12449
|
+
const raw = String(schemaUrl || '').trim();
|
|
12450
|
+
if (!raw)
|
|
12451
|
+
return undefined;
|
|
12452
|
+
try {
|
|
12453
|
+
const url = new URL(raw, 'http://praxis.local');
|
|
12454
|
+
const path = url.searchParams.get('path') || url.searchParams.get('resourcePath');
|
|
12455
|
+
if (path)
|
|
12456
|
+
return path;
|
|
12457
|
+
}
|
|
12458
|
+
catch {
|
|
12459
|
+
// Keep the fallback below for partial schema URLs.
|
|
12460
|
+
}
|
|
12461
|
+
const match = raw.match(/[?&](?:path|resourcePath)=([^&]+)/);
|
|
12462
|
+
return match?.[1] ? decodeURIComponent(match[1]) : undefined;
|
|
12463
|
+
}
|
|
12464
|
+
function isRecord(value) {
|
|
12465
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
12466
|
+
}
|
|
12467
|
+
|
|
12331
12468
|
const LEGACY_OPTIONS_KEY = 'options';
|
|
12332
12469
|
const LEGACY_LAYOUT_KEY = 'layout';
|
|
12333
12470
|
class PageBuilderAiAdapter {
|
|
@@ -12452,7 +12589,8 @@ class PageBuilderAiAdapter {
|
|
|
12452
12589
|
return page;
|
|
12453
12590
|
const cloned = this.clone(page);
|
|
12454
12591
|
const { [LEGACY_OPTIONS_KEY]: _legacyOptions, ...rest } = cloned;
|
|
12455
|
-
const widgets = (cloned.widgets || [])
|
|
12592
|
+
const widgets = (cloned.widgets || [])
|
|
12593
|
+
.map((w) => normalizePageBuilderRuntimeWidget(this.stripLegacyLayoutFields(w)));
|
|
12456
12594
|
return {
|
|
12457
12595
|
...rest,
|
|
12458
12596
|
widgets,
|
|
@@ -12472,7 +12610,8 @@ class PageBuilderAiAdapter {
|
|
|
12472
12610
|
return page;
|
|
12473
12611
|
const cloned = this.clone(page);
|
|
12474
12612
|
const { [LEGACY_OPTIONS_KEY]: _legacyOptions, ...rest } = cloned;
|
|
12475
|
-
const widgets = (cloned.widgets || [])
|
|
12613
|
+
const widgets = (cloned.widgets || [])
|
|
12614
|
+
.map((w) => normalizePageBuilderRuntimeWidget(this.stripLegacyLayoutFields(w)));
|
|
12476
12615
|
return {
|
|
12477
12616
|
...rest,
|
|
12478
12617
|
widgets,
|
|
@@ -12846,6 +12985,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
12846
12985
|
phase: 'capture',
|
|
12847
12986
|
});
|
|
12848
12987
|
}
|
|
12988
|
+
const contextualActionContext = this.contextualPreviewActionContextFromRequest(request);
|
|
12989
|
+
if (contextualActionContext) {
|
|
12990
|
+
return from(this.submitContextualPreviewAction(request, prompt, contextualActionContext));
|
|
12991
|
+
}
|
|
12849
12992
|
if (this.context.enableTurnStream?.() === true && this.service.streamTurn) {
|
|
12850
12993
|
return this.submitWithTurnStream(request, prompt);
|
|
12851
12994
|
}
|
|
@@ -12863,9 +13006,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
12863
13006
|
const componentCapabilities = await this.context.loadComponentCapabilities();
|
|
12864
13007
|
const selectedWidgetKey = this.context.selectedWidgetKey();
|
|
12865
13008
|
const intentResolution = await firstValueFrom(this.service.resolveIntent(this.buildIntentResolutionRequest(prompt, selectedWidgetKey, componentCapabilities, authoringContext)));
|
|
12866
|
-
const
|
|
13009
|
+
const intentQuickReplies = this.resolveShellQuickReplies(intentResolution);
|
|
13010
|
+
const intentAssistantMessage = this.normalizeAssistantMessageForQuickReplies(this.resolveIntentAssistantMessage(intentResolution), intentQuickReplies);
|
|
12867
13011
|
if (intentAssistantMessage) {
|
|
12868
|
-
const quickReplies =
|
|
13012
|
+
const quickReplies = intentQuickReplies;
|
|
12869
13013
|
const explicitPendingClarification = this.toShellPendingClarification(intentResolution.pendingClarification);
|
|
12870
13014
|
const intentClarification = this.resolveIntentClarification(intentResolution);
|
|
12871
13015
|
const routeRequiredClarification = this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, prompt), request.clientTurnId);
|
|
@@ -12873,10 +13017,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
12873
13017
|
?? (intentClarification
|
|
12874
13018
|
? this.buildPendingClarificationForNextTurn(request, this.resolveEffectivePrompt(intentResolution, prompt), intentClarification)
|
|
12875
13019
|
: routeRequiredClarification);
|
|
13020
|
+
const consultativeCatalogIntent = this.isConsultativeCatalogIntent(intentResolution);
|
|
12876
13021
|
const shouldAutoGenerateGuidedPreview = this.shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt) && !this.hasPendingClarificationQuestion(pendingClarification);
|
|
12877
|
-
const mustPauseForClarification = (!this.isExecutableIntent(intentResolution) && !shouldAutoGenerateGuidedPreview)
|
|
13022
|
+
const mustPauseForClarification = (!this.isExecutableIntent(intentResolution, request) && !shouldAutoGenerateGuidedPreview)
|
|
12878
13023
|
|| this.hasPendingClarificationQuestion(pendingClarification);
|
|
12879
|
-
if (mustPauseForClarification
|
|
13024
|
+
if (mustPauseForClarification
|
|
13025
|
+
&& !this.hasPendingClarificationQuestion(pendingClarification)
|
|
13026
|
+
&& (quickReplies.length === 0 || consultativeCatalogIntent)) {
|
|
12880
13027
|
return {
|
|
12881
13028
|
state: 'success',
|
|
12882
13029
|
phase: 'summarize',
|
|
@@ -12925,7 +13072,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
12925
13072
|
state: 'clarification',
|
|
12926
13073
|
phase: 'clarify',
|
|
12927
13074
|
assistantMessage: clarification,
|
|
12928
|
-
quickReplies: this.
|
|
13075
|
+
quickReplies: this.resolveShellQuickReplies(intentResolution),
|
|
12929
13076
|
canApply: false,
|
|
12930
13077
|
statusText: '',
|
|
12931
13078
|
errorText: '',
|
|
@@ -12953,7 +13100,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
12953
13100
|
model: this.context.model(),
|
|
12954
13101
|
apiKey: this.context.apiKey(),
|
|
12955
13102
|
currentPage: this.context.currentPage(),
|
|
12956
|
-
selectedWidgetKey,
|
|
13103
|
+
selectedWidgetKey: this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints),
|
|
12957
13104
|
intentResolution,
|
|
12958
13105
|
componentCapabilities,
|
|
12959
13106
|
...authoringContext,
|
|
@@ -12986,14 +13133,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
12986
13133
|
};
|
|
12987
13134
|
}
|
|
12988
13135
|
const status = this.context.describePreviewStatus(preview);
|
|
12989
|
-
const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
|
|
12990
13136
|
return {
|
|
12991
13137
|
state: 'review',
|
|
12992
13138
|
phase: 'review',
|
|
12993
13139
|
assistantMessage: status,
|
|
12994
13140
|
quickReplies: [],
|
|
12995
13141
|
canApply: true,
|
|
12996
|
-
statusText,
|
|
13142
|
+
statusText: this.reviewStatusText(status, true),
|
|
12997
13143
|
errorText: '',
|
|
12998
13144
|
preview,
|
|
12999
13145
|
diagnostics: { intentResolution },
|
|
@@ -13035,21 +13181,68 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13035
13181
|
pendingPatch: null,
|
|
13036
13182
|
};
|
|
13037
13183
|
}
|
|
13184
|
+
async submitContextualPreviewAction(request, prompt, contextHints) {
|
|
13185
|
+
const componentId = this.readString(contextHints, 'targetComponentId')
|
|
13186
|
+
|| this.readString(contextHints, 'selectedComponentId');
|
|
13187
|
+
const artifactKind = this.readString(contextHints, 'artifactKind')
|
|
13188
|
+
|| (componentId === 'praxis-table' ? 'table' : componentId === 'praxis-dynamic-form' ? 'form' : 'chart');
|
|
13189
|
+
const changeKind = this.readString(contextHints, 'changeKind') || 'contextual_component_action';
|
|
13190
|
+
const intentResolution = {
|
|
13191
|
+
valid: true,
|
|
13192
|
+
operationKind: 'modify',
|
|
13193
|
+
artifactKind,
|
|
13194
|
+
changeKind,
|
|
13195
|
+
authoringProfile: 'component-capability-catalog',
|
|
13196
|
+
targetApp: this.context.targetApp,
|
|
13197
|
+
targetComponentId: this.context.targetComponentId,
|
|
13198
|
+
target: componentId
|
|
13199
|
+
? {
|
|
13200
|
+
componentId,
|
|
13201
|
+
widgetKey: this.readString(contextHints, 'targetWidgetKey')
|
|
13202
|
+
|| this.readString(contextHints, 'selectedWidgetKey')
|
|
13203
|
+
|| this.context.selectedWidgetKey()
|
|
13204
|
+
|| '',
|
|
13205
|
+
resourcePath: this.readString(contextHints, 'resourcePath'),
|
|
13206
|
+
schemaUrl: this.readString(contextHints, 'schemaUrl'),
|
|
13207
|
+
submitUrl: this.readString(contextHints, 'submitUrl'),
|
|
13208
|
+
submitMethod: this.readString(contextHints, 'submitMethod'),
|
|
13209
|
+
}
|
|
13210
|
+
: null,
|
|
13211
|
+
selectedCandidate: this.contextualActionCandidate(contextHints),
|
|
13212
|
+
candidates: [],
|
|
13213
|
+
gate: {
|
|
13214
|
+
gateId: 'component-capability-catalog',
|
|
13215
|
+
status: 'eligible',
|
|
13216
|
+
messages: [],
|
|
13217
|
+
},
|
|
13218
|
+
effectivePrompt: prompt,
|
|
13219
|
+
assistantMessage: null,
|
|
13220
|
+
quickReplies: [],
|
|
13221
|
+
pendingClarification: null,
|
|
13222
|
+
clarificationQuestions: [],
|
|
13223
|
+
warnings: [],
|
|
13224
|
+
failureCodes: [],
|
|
13225
|
+
currentPageSummary: {},
|
|
13226
|
+
contextHints,
|
|
13227
|
+
};
|
|
13228
|
+
return this.completeExecutableStreamPreview(request, prompt, intentResolution, undefined);
|
|
13229
|
+
}
|
|
13038
13230
|
async buildTurnStreamRequest(request, prompt) {
|
|
13039
13231
|
const componentCapabilities = await this.context.loadComponentCapabilities();
|
|
13040
13232
|
const selectedWidgetKey = this.context.selectedWidgetKey();
|
|
13233
|
+
const authoringContext = this.buildAuthoringContext(request);
|
|
13041
13234
|
return {
|
|
13042
13235
|
userPrompt: prompt,
|
|
13043
13236
|
targetApp: this.context.targetApp,
|
|
13044
13237
|
targetComponentId: this.context.targetComponentId,
|
|
13045
13238
|
currentRoute: null,
|
|
13046
13239
|
currentPage: this.context.currentPage(),
|
|
13047
|
-
selectedWidgetKey,
|
|
13240
|
+
selectedWidgetKey: this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints),
|
|
13048
13241
|
provider: this.context.provider(),
|
|
13049
13242
|
model: this.context.model(),
|
|
13050
13243
|
apiKey: this.context.apiKey(),
|
|
13051
13244
|
componentCapabilities,
|
|
13052
|
-
...
|
|
13245
|
+
...authoringContext,
|
|
13053
13246
|
};
|
|
13054
13247
|
}
|
|
13055
13248
|
async toTurnResultFromStreamEvent(event, request, prompt) {
|
|
@@ -13108,14 +13301,21 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13108
13301
|
preview: null,
|
|
13109
13302
|
};
|
|
13110
13303
|
}
|
|
13111
|
-
const
|
|
13304
|
+
const rawAssistantMessage = this.readString(payload, 'assistantMessage')
|
|
13112
13305
|
|| this.resolveIntentAssistantMessage(intentResolution)
|
|
13113
13306
|
|| (preview ? this.context.describePreviewStatus(preview) : '');
|
|
13114
13307
|
const rawQuickReplies = Array.isArray(payload['quickReplies'])
|
|
13115
13308
|
? payload['quickReplies']
|
|
13116
13309
|
: intentResolution.quickReplies ?? [];
|
|
13117
|
-
const quickReplies = this.
|
|
13310
|
+
const quickReplies = this.resolveShellQuickReplies(intentResolution, rawQuickReplies);
|
|
13311
|
+
const assistantMessage = this.normalizeAssistantMessageForQuickReplies(rawAssistantMessage, quickReplies);
|
|
13118
13312
|
const canApply = payload['canApply'] === true && !!preview?.valid;
|
|
13313
|
+
const contextualExecutableIntent = request
|
|
13314
|
+
? this.toExecutableContextualComponentIntent(intentResolution, request)
|
|
13315
|
+
: null;
|
|
13316
|
+
if (!canApply && contextualExecutableIntent && request && prompt) {
|
|
13317
|
+
return this.completeExecutableStreamPreview(request, prompt, contextualExecutableIntent, preview);
|
|
13318
|
+
}
|
|
13119
13319
|
if (canApply
|
|
13120
13320
|
&& request
|
|
13121
13321
|
&& prompt
|
|
@@ -13123,17 +13323,54 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13123
13323
|
return this.completeExecutableStreamPreview(request, prompt, intentResolution, undefined);
|
|
13124
13324
|
}
|
|
13125
13325
|
if (!canApply) {
|
|
13326
|
+
if (preview && this.hasMaterializablePreview(preview) && this.isGovernedBlockedStreamPreview(payload, preview)) {
|
|
13327
|
+
const applied = await this.context.applyLocalPreview(preview);
|
|
13328
|
+
if (!applied.success) {
|
|
13329
|
+
const message = applied.error || this.context.tx('agentic.errors.applyLocal', 'Preview could not be applied.');
|
|
13330
|
+
return {
|
|
13331
|
+
state: 'error',
|
|
13332
|
+
phase: 'preview',
|
|
13333
|
+
assistantMessage: message,
|
|
13334
|
+
canApply: false,
|
|
13335
|
+
statusText: '',
|
|
13336
|
+
errorText: message,
|
|
13337
|
+
preview: null,
|
|
13338
|
+
diagnostics: {
|
|
13339
|
+
intentResolution,
|
|
13340
|
+
preview,
|
|
13341
|
+
decisionDiagnostics: this.toJsonObject(payload['decisionDiagnostics']),
|
|
13342
|
+
toolLoopTrace: Array.isArray(payload['toolLoopTrace']) ? payload['toolLoopTrace'] : undefined,
|
|
13343
|
+
},
|
|
13344
|
+
};
|
|
13345
|
+
}
|
|
13346
|
+
return {
|
|
13347
|
+
state: 'review',
|
|
13348
|
+
phase: 'review',
|
|
13349
|
+
assistantMessage,
|
|
13350
|
+
quickReplies,
|
|
13351
|
+
canApply: false,
|
|
13352
|
+
statusText: this.reviewStatusText(assistantMessage, false),
|
|
13353
|
+
errorText: '',
|
|
13354
|
+
preview,
|
|
13355
|
+
diagnostics: {
|
|
13356
|
+
intentResolution,
|
|
13357
|
+
preview,
|
|
13358
|
+
decisionDiagnostics: this.toJsonObject(payload['decisionDiagnostics']),
|
|
13359
|
+
toolLoopTrace: Array.isArray(payload['toolLoopTrace']) ? payload['toolLoopTrace'] : undefined,
|
|
13360
|
+
},
|
|
13361
|
+
};
|
|
13362
|
+
}
|
|
13126
13363
|
const pendingClarification = this.toShellPendingClarification(intentResolution?.pendingClarification)
|
|
13127
13364
|
?? this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, assistantMessage));
|
|
13128
13365
|
if (!pendingClarification
|
|
13129
|
-
&& (this.isExecutableIntent(intentResolution)
|
|
13366
|
+
&& (this.isExecutableIntent(intentResolution, request)
|
|
13130
13367
|
|| (!!prompt && this.shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt)))
|
|
13131
13368
|
&& !this.hasBlockingResourceQuickReply(quickReplies)
|
|
13132
13369
|
&& request
|
|
13133
13370
|
&& prompt) {
|
|
13134
13371
|
return this.completeExecutableStreamPreview(request, prompt, intentResolution, preview);
|
|
13135
13372
|
}
|
|
13136
|
-
const requiresChoice = quickReplies.length > 0;
|
|
13373
|
+
const requiresChoice = quickReplies.length > 0 && !this.isConsultativeCatalogIntent(intentResolution);
|
|
13137
13374
|
return {
|
|
13138
13375
|
state: pendingClarification || requiresChoice ? 'clarification' : 'success',
|
|
13139
13376
|
phase: pendingClarification || requiresChoice ? 'clarify' : 'summarize',
|
|
@@ -13162,14 +13399,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13162
13399
|
};
|
|
13163
13400
|
}
|
|
13164
13401
|
const status = assistantMessage || this.context.describePreviewStatus(preview);
|
|
13165
|
-
const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
|
|
13166
13402
|
return {
|
|
13167
13403
|
state: 'review',
|
|
13168
13404
|
phase: 'review',
|
|
13169
13405
|
assistantMessage: status,
|
|
13170
|
-
quickReplies
|
|
13406
|
+
quickReplies,
|
|
13171
13407
|
canApply: true,
|
|
13172
|
-
statusText,
|
|
13408
|
+
statusText: this.reviewStatusText(status, true),
|
|
13173
13409
|
errorText: '',
|
|
13174
13410
|
preview,
|
|
13175
13411
|
diagnostics: { intentResolution, preview },
|
|
@@ -13182,7 +13418,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13182
13418
|
return false;
|
|
13183
13419
|
}
|
|
13184
13420
|
const contextHints = this.toJsonObject(reply.contextHints);
|
|
13185
|
-
|
|
13421
|
+
if (this.isContextualPreviewActionReply(reply, contextHints)) {
|
|
13422
|
+
return false;
|
|
13423
|
+
}
|
|
13424
|
+
return !!this.readString(contextHints, 'resourcePath') || this.isResourceQuickReply(reply);
|
|
13186
13425
|
});
|
|
13187
13426
|
}
|
|
13188
13427
|
async completeExecutableStreamPreview(request, prompt, intentResolution, streamPreview) {
|
|
@@ -13190,6 +13429,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13190
13429
|
const authoringContext = this.buildAuthoringContext(request);
|
|
13191
13430
|
const componentCapabilities = await this.context.loadComponentCapabilities();
|
|
13192
13431
|
const selectedWidgetKey = this.context.selectedWidgetKey();
|
|
13432
|
+
const effectiveSelectedWidgetKey = this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints);
|
|
13193
13433
|
const reusableStreamPreview = streamPreview?.valid
|
|
13194
13434
|
&& !this.shouldRegenerateStreamPreview(intentResolution, streamPreview);
|
|
13195
13435
|
const preview = reusableStreamPreview
|
|
@@ -13200,7 +13440,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13200
13440
|
model: this.context.model(),
|
|
13201
13441
|
apiKey: this.context.apiKey(),
|
|
13202
13442
|
currentPage: this.context.currentPage(),
|
|
13203
|
-
selectedWidgetKey,
|
|
13443
|
+
selectedWidgetKey: effectiveSelectedWidgetKey,
|
|
13204
13444
|
intentResolution,
|
|
13205
13445
|
componentCapabilities,
|
|
13206
13446
|
...authoringContext,
|
|
@@ -13233,14 +13473,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13233
13473
|
};
|
|
13234
13474
|
}
|
|
13235
13475
|
const status = this.context.describePreviewStatus(preview);
|
|
13236
|
-
const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
|
|
13237
13476
|
return {
|
|
13238
13477
|
state: 'review',
|
|
13239
13478
|
phase: 'review',
|
|
13240
13479
|
assistantMessage: status,
|
|
13241
13480
|
quickReplies: [],
|
|
13242
13481
|
canApply: true,
|
|
13243
|
-
statusText,
|
|
13482
|
+
statusText: this.reviewStatusText(status, true),
|
|
13244
13483
|
errorText: '',
|
|
13245
13484
|
preview,
|
|
13246
13485
|
diagnostics: { intentResolution, preview },
|
|
@@ -13272,6 +13511,43 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13272
13511
|
}
|
|
13273
13512
|
return true;
|
|
13274
13513
|
}
|
|
13514
|
+
isGovernedBlockedStreamPreview(payload, preview) {
|
|
13515
|
+
const previewDiagnostics = this.toJsonObject(preview.diagnostics);
|
|
13516
|
+
const decisionDiagnostics = this.toJsonObject(payload['decisionDiagnostics'])
|
|
13517
|
+
?? this.toJsonObject(previewDiagnostics?.['decisionDiagnostics']);
|
|
13518
|
+
if (decisionDiagnostics) {
|
|
13519
|
+
if (decisionDiagnostics['requiresReview'] === true) {
|
|
13520
|
+
return true;
|
|
13521
|
+
}
|
|
13522
|
+
if (decisionDiagnostics['decisionValid'] === false) {
|
|
13523
|
+
return true;
|
|
13524
|
+
}
|
|
13525
|
+
if (this.readString(decisionDiagnostics, 'reviewReason')) {
|
|
13526
|
+
return true;
|
|
13527
|
+
}
|
|
13528
|
+
}
|
|
13529
|
+
const warnings = Array.isArray(preview.warnings)
|
|
13530
|
+
? preview.warnings.map((warning) => `${warning}`)
|
|
13531
|
+
: [];
|
|
13532
|
+
const failureCodes = Array.isArray(preview.failureCodes)
|
|
13533
|
+
? preview.failureCodes.map((code) => `${code}`)
|
|
13534
|
+
: [];
|
|
13535
|
+
return warnings.some((warning) => warning === 'semantic-preview-materialization-mismatch'
|
|
13536
|
+
|| warning === 'semantic-axis-schema-verification-pending')
|
|
13537
|
+
|| failureCodes.some((code) => code === 'semantic-decision-required'
|
|
13538
|
+
|| code.startsWith('semantic-preview-'));
|
|
13539
|
+
}
|
|
13540
|
+
hasMaterializablePreview(preview) {
|
|
13541
|
+
if (!preview) {
|
|
13542
|
+
return false;
|
|
13543
|
+
}
|
|
13544
|
+
if (preview.uiCompositionPlan) {
|
|
13545
|
+
return true;
|
|
13546
|
+
}
|
|
13547
|
+
const patch = this.toJsonObject(preview.compiledFormPatch)?.['patch'];
|
|
13548
|
+
const page = this.toJsonObject(patch)?.['page'];
|
|
13549
|
+
return !!this.toJsonObject(page);
|
|
13550
|
+
}
|
|
13275
13551
|
phaseForStreamPayload(payload) {
|
|
13276
13552
|
const phase = this.readString(payload, 'phase');
|
|
13277
13553
|
if (phase === 'intent.resolve')
|
|
@@ -13322,21 +13598,22 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13322
13598
|
}
|
|
13323
13599
|
return base;
|
|
13324
13600
|
}
|
|
13325
|
-
|
|
13326
|
-
const
|
|
13327
|
-
if (!
|
|
13328
|
-
return
|
|
13329
|
-
}
|
|
13330
|
-
const influenceCount = this.readNumber(audit, 'influenceCount');
|
|
13331
|
-
const citedCount = this.readNumber(audit, 'citedCount');
|
|
13332
|
-
if (!influenceCount || influenceCount <= 0 || citedCount === null || citedCount < 0) {
|
|
13333
|
-
return status;
|
|
13601
|
+
reviewStatusText(status, canApply) {
|
|
13602
|
+
const normalized = status.trim();
|
|
13603
|
+
if (normalized && !this.shouldReplaceReviewStatus(normalized)) {
|
|
13604
|
+
return normalized;
|
|
13334
13605
|
}
|
|
13335
|
-
|
|
13336
|
-
.tx('agentic.status.
|
|
13337
|
-
.
|
|
13338
|
-
|
|
13339
|
-
|
|
13606
|
+
return canApply
|
|
13607
|
+
? this.context.tx('agentic.status.reviewReady', 'Ready for review.')
|
|
13608
|
+
: this.context.tx('agentic.status.reviewNeedsAttention', 'Review the pending points before saving.');
|
|
13609
|
+
}
|
|
13610
|
+
shouldReplaceReviewStatus(status) {
|
|
13611
|
+
const normalized = status.toLocaleLowerCase();
|
|
13612
|
+
return status.length > 80
|
|
13613
|
+
|| normalized.includes('preview applied')
|
|
13614
|
+
|| normalized.includes('pré-visualização')
|
|
13615
|
+
|| normalized.includes('pre-visualizacao')
|
|
13616
|
+
|| normalized.includes('sourcerefs');
|
|
13340
13617
|
}
|
|
13341
13618
|
isBackendResourceDiscoveryPayload(payload) {
|
|
13342
13619
|
const diagnostics = this.toJsonObject(payload['diagnostics']);
|
|
@@ -13519,10 +13796,9 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13519
13796
|
const quickReplies = result.quickReplies?.length
|
|
13520
13797
|
? this.toShellQuickReplies(result.quickReplies)
|
|
13521
13798
|
: this.toResourceCandidateQuickReplies(result.candidates, result.artifactKind);
|
|
13522
|
-
const assistantMessage =
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
: this.context.tx('agentic.resourceDiscovery.empty', 'I did not find a matching API yet. Describe the business data this screen should use.'));
|
|
13799
|
+
const assistantMessage = quickReplies.length
|
|
13800
|
+
? this.resourceDiscoveryAssistantMessage(result.assistantMessage, quickReplies)
|
|
13801
|
+
: this.context.tx('agentic.resourceDiscovery.empty', 'I did not find a matching API yet. Describe the business data this screen should use.');
|
|
13526
13802
|
const intentResult = await this.resolveIntentAfterResourceDiscovery(request, request.pendingClarification?.sourcePrompt || prompt, contextHints, result, assistantMessage, quickReplies);
|
|
13527
13803
|
if (intentResult) {
|
|
13528
13804
|
return intentResult;
|
|
@@ -13569,12 +13845,16 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13569
13845
|
...authoringContext,
|
|
13570
13846
|
contextHints: this.resourceDiscoveryContextHints(contextHints, result),
|
|
13571
13847
|
})));
|
|
13572
|
-
const
|
|
13848
|
+
const resolvedAssistantMessage = this.resolveIntentAssistantMessage(intentResolution)
|
|
13573
13849
|
|| this.resolveIntentClarification(intentResolution)
|
|
13574
13850
|
|| fallbackAssistantMessage;
|
|
13575
13851
|
const quickReplies = intentResolution.quickReplies?.length
|
|
13576
13852
|
? this.toShellQuickReplies(intentResolution.quickReplies)
|
|
13577
13853
|
: fallbackQuickReplies;
|
|
13854
|
+
const assistantMessage = quickReplies.some((reply) => this.isResourceQuickReply(reply))
|
|
13855
|
+
&& this.isGenericResourceDiscoveryMessage(resolvedAssistantMessage)
|
|
13856
|
+
? fallbackAssistantMessage
|
|
13857
|
+
: resolvedAssistantMessage;
|
|
13578
13858
|
const explicitPendingClarification = this.toShellPendingClarification(intentResolution.pendingClarification);
|
|
13579
13859
|
const routeRequiredClarification = this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, prompt), request.clientTurnId);
|
|
13580
13860
|
const pendingClarification = explicitPendingClarification
|
|
@@ -13637,6 +13917,37 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13637
13917
|
const contextHints = this.toJsonObject(request.action?.contextHints);
|
|
13638
13918
|
return this.readString(contextHints, 'tool') === 'searchApiResources';
|
|
13639
13919
|
}
|
|
13920
|
+
resourceDiscoveryAssistantMessage(backendMessage, quickReplies) {
|
|
13921
|
+
const backendText = backendMessage?.trim() ?? '';
|
|
13922
|
+
if (backendText && !this.isGenericResourceDiscoveryMessage(backendText)) {
|
|
13923
|
+
return backendText;
|
|
13924
|
+
}
|
|
13925
|
+
const firstLabel = quickReplies[0]?.label?.trim()
|
|
13926
|
+
|| this.context.tx('agentic.resourceDiscovery.defaultRecommendedLabel', 'the first option');
|
|
13927
|
+
const sourceCount = this.resourceDiscoverySourceCountLabel(quickReplies.length);
|
|
13928
|
+
return this.context.tx('agentic.resourceDiscovery.found', 'I found {sourceCount} for this screen. I recommend starting with {first} because it is the best fit for charts, KPIs, and drill-down. Review the cards below to see what each source is good for, what it returns, and what I will create after you select it.')
|
|
13929
|
+
.replace('{sourceCount}', sourceCount)
|
|
13930
|
+
.replace('{first}', firstLabel);
|
|
13931
|
+
}
|
|
13932
|
+
resourceDiscoverySourceCountLabel(count) {
|
|
13933
|
+
const key = count === 1
|
|
13934
|
+
? 'agentic.resourceDiscovery.sourceCountSingular'
|
|
13935
|
+
: 'agentic.resourceDiscovery.sourceCountPlural';
|
|
13936
|
+
const fallback = count === 1 ? '1 candidate source' : '{count} candidate sources';
|
|
13937
|
+
return this.context.tx(key, fallback).replace('{count}', String(count));
|
|
13938
|
+
}
|
|
13939
|
+
normalizeAssistantMessageForQuickReplies(assistantMessage, quickReplies) {
|
|
13940
|
+
const message = assistantMessage?.trim() ?? '';
|
|
13941
|
+
return quickReplies.some((reply) => this.isResourceQuickReply(reply))
|
|
13942
|
+
? this.resourceDiscoveryAssistantMessage(message, quickReplies)
|
|
13943
|
+
: message;
|
|
13944
|
+
}
|
|
13945
|
+
isGenericResourceDiscoveryMessage(message) {
|
|
13946
|
+
return /(?:encontrei|found).*(?:apis?|fontes?|sources?).*(?:escolha|choose)/iu.test(message)
|
|
13947
|
+
|| /(?:encontrei|found).*(?:fontes?|sources?).*(?:candidatas?|candidate)/iu.test(message)
|
|
13948
|
+
|| /(?:fonte|source).*(?:encontrada|found).*(?:escolha|choose)/iu.test(message)
|
|
13949
|
+
|| /(?:fonte|source).*(?:encontrada|found).*(?:catalogo|catalog)/iu.test(message);
|
|
13950
|
+
}
|
|
13640
13951
|
toResourceCandidateQuickReplies(candidates, artifactKind) {
|
|
13641
13952
|
return candidates
|
|
13642
13953
|
.filter((candidate) => !!candidate.resourcePath?.trim())
|
|
@@ -13696,20 +14007,184 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13696
14007
|
const message = intentResolution.assistantMessage?.trim();
|
|
13697
14008
|
return message || null;
|
|
13698
14009
|
}
|
|
13699
|
-
isExecutableIntent(intentResolution) {
|
|
14010
|
+
isExecutableIntent(intentResolution, request) {
|
|
13700
14011
|
const operationKind = intentResolution.operationKind;
|
|
13701
14012
|
const artifactKind = intentResolution.artifactKind;
|
|
13702
14013
|
const allowsMaterializedArtifactOperation = operationKind === 'create'
|
|
13703
14014
|
|| operationKind === 'modify'
|
|
13704
14015
|
|| operationKind === 'remove';
|
|
13705
14016
|
return !!intentResolution.valid
|
|
13706
|
-
&& intentResolution
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
14017
|
+
&& (this.isExecutableContextualComponentIntent(intentResolution, request)
|
|
14018
|
+
|| (intentResolution.gate?.status === 'eligible'
|
|
14019
|
+
&& ((allowsMaterializedArtifactOperation
|
|
14020
|
+
&& !!intentResolution.selectedCandidate
|
|
14021
|
+
&& (artifactKind === 'form'
|
|
14022
|
+
|| artifactKind === 'dashboard'
|
|
14023
|
+
|| artifactKind === 'table'
|
|
14024
|
+
|| artifactKind === 'chart'))
|
|
14025
|
+
|| this.isExecutablePageCompositionIntent(intentResolution))));
|
|
14026
|
+
}
|
|
14027
|
+
isExecutableContextualComponentIntent(intentResolution, request) {
|
|
14028
|
+
const operationKind = intentResolution.operationKind;
|
|
14029
|
+
const requestContextHints = this.contextualPreviewActionContextFromRequest(request)
|
|
14030
|
+
?? this.toJsonObject(request?.action?.contextHints)
|
|
14031
|
+
?? this.toJsonObject(request?.contextHints);
|
|
14032
|
+
const requestIsContextualPreviewAction = this.isContextualPreviewActionContext(requestContextHints);
|
|
14033
|
+
if (!requestIsContextualPreviewAction
|
|
14034
|
+
&& operationKind !== 'create'
|
|
14035
|
+
&& operationKind !== 'modify'
|
|
14036
|
+
&& operationKind !== 'remove') {
|
|
14037
|
+
return false;
|
|
14038
|
+
}
|
|
14039
|
+
const contextHints = this.toJsonObject(intentResolution.contextHints)
|
|
14040
|
+
?? requestContextHints;
|
|
14041
|
+
if (!this.isContextualPreviewActionContext(contextHints) && !requestIsContextualPreviewAction) {
|
|
14042
|
+
return false;
|
|
14043
|
+
}
|
|
14044
|
+
const componentId = this.readString(contextHints, 'targetComponentId')
|
|
14045
|
+
|| this.readString(contextHints, 'selectedComponentId')
|
|
14046
|
+
|| this.readString(requestContextHints, 'targetComponentId')
|
|
14047
|
+
|| this.readString(requestContextHints, 'selectedComponentId')
|
|
14048
|
+
|| intentResolution.target?.componentId
|
|
14049
|
+
|| '';
|
|
14050
|
+
return componentId === 'praxis-chart'
|
|
14051
|
+
|| componentId === 'praxis-table'
|
|
14052
|
+
|| componentId === 'praxis-dynamic-form';
|
|
14053
|
+
}
|
|
14054
|
+
toExecutableContextualComponentIntent(intentResolution, request) {
|
|
14055
|
+
const requestContextHints = this.contextualPreviewActionContextFromRequest(request)
|
|
14056
|
+
?? this.toJsonObject(request.action?.contextHints)
|
|
14057
|
+
?? this.toJsonObject(request.contextHints);
|
|
14058
|
+
if (!this.isContextualPreviewActionContext(requestContextHints)) {
|
|
14059
|
+
return null;
|
|
14060
|
+
}
|
|
14061
|
+
const intentContextHints = this.toJsonObject(intentResolution.contextHints);
|
|
14062
|
+
const contextHints = {
|
|
14063
|
+
...(requestContextHints ?? {}),
|
|
14064
|
+
...(intentContextHints ?? {}),
|
|
14065
|
+
};
|
|
14066
|
+
const componentId = this.readString(contextHints, 'targetComponentId')
|
|
14067
|
+
|| this.readString(contextHints, 'selectedComponentId')
|
|
14068
|
+
|| intentResolution.target?.componentId
|
|
14069
|
+
|| '';
|
|
14070
|
+
if (componentId !== 'praxis-chart'
|
|
14071
|
+
&& componentId !== 'praxis-table'
|
|
14072
|
+
&& componentId !== 'praxis-dynamic-form') {
|
|
14073
|
+
return null;
|
|
14074
|
+
}
|
|
14075
|
+
const currentOperation = intentResolution.operationKind;
|
|
14076
|
+
const operationKind = currentOperation === 'create'
|
|
14077
|
+
|| currentOperation === 'modify'
|
|
14078
|
+
|| currentOperation === 'remove'
|
|
14079
|
+
? currentOperation
|
|
14080
|
+
: 'modify';
|
|
14081
|
+
const artifactKind = intentResolution.artifactKind
|
|
14082
|
+
|| this.readString(contextHints, 'artifactKind')
|
|
14083
|
+
|| (componentId === 'praxis-chart'
|
|
14084
|
+
? 'chart'
|
|
14085
|
+
: componentId === 'praxis-table'
|
|
14086
|
+
? 'table'
|
|
14087
|
+
: 'form');
|
|
14088
|
+
const changeKind = this.readString(contextHints, 'changeKind')
|
|
14089
|
+
|| intentResolution.changeKind
|
|
14090
|
+
|| 'contextual_component_action';
|
|
14091
|
+
return {
|
|
14092
|
+
...intentResolution,
|
|
14093
|
+
valid: true,
|
|
14094
|
+
operationKind,
|
|
14095
|
+
artifactKind,
|
|
14096
|
+
changeKind,
|
|
14097
|
+
gate: {
|
|
14098
|
+
...(intentResolution.gate ?? { gateId: '', status: '', messages: [] }),
|
|
14099
|
+
status: 'eligible',
|
|
14100
|
+
messages: [],
|
|
14101
|
+
},
|
|
14102
|
+
pendingClarification: null,
|
|
14103
|
+
clarificationQuestions: [],
|
|
14104
|
+
failureCodes: [],
|
|
14105
|
+
contextHints,
|
|
14106
|
+
};
|
|
14107
|
+
}
|
|
14108
|
+
isContextualPreviewActionContext(contextHints) {
|
|
14109
|
+
const hints = contextHints ?? null;
|
|
14110
|
+
const hintSource = this.readString(hints, 'source');
|
|
14111
|
+
const hintKind = this.readString(hints, 'kind');
|
|
14112
|
+
return hintSource === 'component-capability-catalog'
|
|
14113
|
+
|| hintKind === 'contextual-preview-action';
|
|
14114
|
+
}
|
|
14115
|
+
contextualPreviewActionContextFromRequest(request) {
|
|
14116
|
+
const explicit = this.toJsonObject(request?.action?.contextHints);
|
|
14117
|
+
if (this.isContextualPreviewActionContext(explicit)) {
|
|
14118
|
+
return explicit;
|
|
14119
|
+
}
|
|
14120
|
+
const actionId = request?.action?.id?.trim();
|
|
14121
|
+
if (!actionId) {
|
|
14122
|
+
return null;
|
|
14123
|
+
}
|
|
14124
|
+
const base = {
|
|
14125
|
+
source: 'component-capability-catalog',
|
|
14126
|
+
kind: 'contextual-preview-action',
|
|
14127
|
+
operationKind: 'modify',
|
|
14128
|
+
};
|
|
14129
|
+
if (actionId === 'chart-change-line' || actionId === 'chart-change-donut') {
|
|
14130
|
+
return {
|
|
14131
|
+
...base,
|
|
14132
|
+
artifactKind: 'chart',
|
|
14133
|
+
changeKind: 'set_chart_type',
|
|
14134
|
+
chartType: actionId === 'chart-change-donut' ? 'donut' : 'line',
|
|
14135
|
+
capabilityId: 'praxis-chart.type.set@0.1.0',
|
|
14136
|
+
targetComponentId: 'praxis-chart',
|
|
14137
|
+
selectedComponentId: 'praxis-chart',
|
|
14138
|
+
};
|
|
14139
|
+
}
|
|
14140
|
+
if (actionId === 'chart-add-detail-table' || actionId === 'chart-add-detail-modal') {
|
|
14141
|
+
return {
|
|
14142
|
+
...base,
|
|
14143
|
+
artifactKind: 'chart',
|
|
14144
|
+
changeKind: 'enable_chart_drilldown',
|
|
14145
|
+
capabilityId: 'praxis-chart.drilldown.enable@0.1.0',
|
|
14146
|
+
targetComponentId: 'praxis-chart',
|
|
14147
|
+
selectedComponentId: 'praxis-chart',
|
|
14148
|
+
...(actionId === 'chart-add-detail-modal'
|
|
14149
|
+
? {
|
|
14150
|
+
surfacePresentation: 'modal',
|
|
14151
|
+
surfaceActionId: 'surface.open',
|
|
14152
|
+
surfaceWidgetId: 'praxis-table',
|
|
14153
|
+
}
|
|
14154
|
+
: {}),
|
|
14155
|
+
};
|
|
14156
|
+
}
|
|
14157
|
+
if (actionId === 'table-export-selected-rows') {
|
|
14158
|
+
return {
|
|
14159
|
+
...base,
|
|
14160
|
+
artifactKind: 'table',
|
|
14161
|
+
changeKind: 'configure_export',
|
|
14162
|
+
capabilityId: 'praxis-table.export.selected-rows@0.1.0',
|
|
14163
|
+
targetComponentId: 'praxis-table',
|
|
14164
|
+
selectedComponentId: 'praxis-table',
|
|
14165
|
+
};
|
|
14166
|
+
}
|
|
14167
|
+
return null;
|
|
14168
|
+
}
|
|
14169
|
+
contextualActionCandidate(contextHints) {
|
|
14170
|
+
const resourcePath = this.readString(contextHints, 'resourcePath');
|
|
14171
|
+
if (!resourcePath) {
|
|
14172
|
+
return null;
|
|
14173
|
+
}
|
|
14174
|
+
const submitUrl = this.readString(contextHints, 'submitUrl') || resourcePath;
|
|
14175
|
+
const submitMethod = this.readString(contextHints, 'submitMethod')
|
|
14176
|
+
|| this.readString(contextHints, 'operation')
|
|
14177
|
+
|| 'get';
|
|
14178
|
+
return {
|
|
14179
|
+
resourcePath,
|
|
14180
|
+
operation: submitMethod,
|
|
14181
|
+
schemaUrl: this.readString(contextHints, 'schemaUrl'),
|
|
14182
|
+
submitUrl,
|
|
14183
|
+
submitMethod,
|
|
14184
|
+
score: 1,
|
|
14185
|
+
reason: 'component capability context',
|
|
14186
|
+
evidence: ['component-capability-catalog'],
|
|
14187
|
+
};
|
|
13713
14188
|
}
|
|
13714
14189
|
shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt) {
|
|
13715
14190
|
if (!this.isGuidedPreviewIntent(intentResolution)) {
|
|
@@ -13734,6 +14209,61 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13734
14209
|
return (artifactKind === 'dashboard' || artifactKind === 'page' || artifactKind === 'table' || artifactKind === 'form')
|
|
13735
14210
|
&& (intentResolution.operationKind === 'compose' || intentResolution.operationKind === 'explore');
|
|
13736
14211
|
}
|
|
14212
|
+
isConsultativeCatalogIntent(intentResolution) {
|
|
14213
|
+
if (!intentResolution) {
|
|
14214
|
+
return false;
|
|
14215
|
+
}
|
|
14216
|
+
const operationKind = intentResolution.operationKind;
|
|
14217
|
+
const changeKind = intentResolution.changeKind;
|
|
14218
|
+
return (operationKind === 'explore' || operationKind === 'explain')
|
|
14219
|
+
&& intentResolution.artifactKind === 'api_catalog'
|
|
14220
|
+
&& (changeKind === 'answer_api_catalog_question'
|
|
14221
|
+
|| changeKind === 'answer_catalog_question'
|
|
14222
|
+
|| changeKind === 'api_catalog_followup'
|
|
14223
|
+
|| intentResolution.authoringProfile === 'api-catalog-qa');
|
|
14224
|
+
}
|
|
14225
|
+
resolveShellQuickReplies(intentResolution, quickReplies = intentResolution.quickReplies ?? []) {
|
|
14226
|
+
const effectiveQuickReplies = this.isConsultativeCatalogIntent(intentResolution)
|
|
14227
|
+
? quickReplies.filter((reply) => !this.isResourceCandidateQuickReply(reply))
|
|
14228
|
+
: this.shouldSuppressWorkflowQuickReplies(intentResolution)
|
|
14229
|
+
? quickReplies.filter((reply) => !this.isWorkflowQuickReply(reply))
|
|
14230
|
+
: quickReplies;
|
|
14231
|
+
const shellQuickReplies = this.toShellQuickReplies(effectiveQuickReplies);
|
|
14232
|
+
if (shellQuickReplies.length) {
|
|
14233
|
+
return shellQuickReplies;
|
|
14234
|
+
}
|
|
14235
|
+
return this.contextualCapabilityFallbackQuickReplies(intentResolution);
|
|
14236
|
+
}
|
|
14237
|
+
shouldSuppressWorkflowQuickReplies(intentResolution) {
|
|
14238
|
+
if (intentResolution.selectedCandidate || this.isConsultativeCatalogIntent(intentResolution)) {
|
|
14239
|
+
return false;
|
|
14240
|
+
}
|
|
14241
|
+
const operationKind = (intentResolution.operationKind ?? '').trim().toLowerCase();
|
|
14242
|
+
const artifactKind = (intentResolution.artifactKind ?? '').trim().toLowerCase();
|
|
14243
|
+
const changeKind = (intentResolution.changeKind ?? '').trim().toLowerCase();
|
|
14244
|
+
return artifactKind === 'unknown'
|
|
14245
|
+
|| operationKind === 'unknown'
|
|
14246
|
+
|| changeKind === 'unknown';
|
|
14247
|
+
}
|
|
14248
|
+
isWorkflowQuickReply(reply) {
|
|
14249
|
+
const kind = (reply.kind ?? '').trim().toLowerCase();
|
|
14250
|
+
return kind === 'revise' || kind === 'cancel' || kind === 'confirm';
|
|
14251
|
+
}
|
|
14252
|
+
isResourceCandidateQuickReply(reply) {
|
|
14253
|
+
const kind = (reply.kind ?? '').trim().toLowerCase();
|
|
14254
|
+
if (kind !== 'suggestion') {
|
|
14255
|
+
return false;
|
|
14256
|
+
}
|
|
14257
|
+
const contextHints = this.toJsonObject(reply.contextHints);
|
|
14258
|
+
if (this.isContextualPreviewActionReply(reply, contextHints)) {
|
|
14259
|
+
return false;
|
|
14260
|
+
}
|
|
14261
|
+
return !!contextHints
|
|
14262
|
+
&& (!!contextHints['resourcePath']
|
|
14263
|
+
|| !!contextHints['resourceKey']
|
|
14264
|
+
|| !!contextHints['submitUrl']
|
|
14265
|
+
|| !!contextHints['schemaUrl']);
|
|
14266
|
+
}
|
|
13737
14267
|
isExplicitPreviewCreationPrompt(prompt) {
|
|
13738
14268
|
const normalized = prompt
|
|
13739
14269
|
.normalize('NFD')
|
|
@@ -13838,7 +14368,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13838
14368
|
toShellQuickReplies(quickReplies) {
|
|
13839
14369
|
return quickReplies
|
|
13840
14370
|
.filter((reply) => !!reply.id && !!reply.label && (!!reply.prompt || reply.kind === 'cancel'))
|
|
13841
|
-
.map((reply) => ({
|
|
14371
|
+
.map((reply) => this.enrichShellQuickReply({
|
|
13842
14372
|
id: reply.id,
|
|
13843
14373
|
kind: reply.kind,
|
|
13844
14374
|
label: reply.label,
|
|
@@ -13846,9 +14376,334 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13846
14376
|
description: reply.description,
|
|
13847
14377
|
icon: reply.icon,
|
|
13848
14378
|
tone: reply.tone,
|
|
14379
|
+
presentation: null,
|
|
13849
14380
|
contextHints: this.toJsonObject(reply.contextHints),
|
|
13850
14381
|
}));
|
|
13851
14382
|
}
|
|
14383
|
+
contextualCapabilityFallbackQuickReplies(intentResolution) {
|
|
14384
|
+
if (!this.shouldOfferContextualCapabilityActions(intentResolution)) {
|
|
14385
|
+
return [];
|
|
14386
|
+
}
|
|
14387
|
+
const componentContext = this.resolveCurrentComponentContext(intentResolution);
|
|
14388
|
+
if (componentContext?.componentId !== 'praxis-chart') {
|
|
14389
|
+
return [];
|
|
14390
|
+
}
|
|
14391
|
+
return [
|
|
14392
|
+
this.contextualCapabilityQuickReply({
|
|
14393
|
+
id: 'chart-change-line',
|
|
14394
|
+
label: this.context.tx('agentic.quickReplies.chartChangeLine.label', 'Trocar para linhas'),
|
|
14395
|
+
prompt: this.context.tx('agentic.quickReplies.chartChangeLine.prompt', 'Altere o gráfico selecionado para linhas.'),
|
|
14396
|
+
icon: 'show_chart',
|
|
14397
|
+
changeKind: 'set_chart_type',
|
|
14398
|
+
chartType: 'line',
|
|
14399
|
+
capabilityId: 'praxis-chart.type.set@0.1.0',
|
|
14400
|
+
widgetKey: componentContext.widgetKey,
|
|
14401
|
+
}),
|
|
14402
|
+
this.contextualCapabilityQuickReply({
|
|
14403
|
+
id: 'chart-change-donut',
|
|
14404
|
+
label: this.context.tx('agentic.quickReplies.chartChangeDonut.label', 'Ver como donut'),
|
|
14405
|
+
prompt: this.context.tx('agentic.quickReplies.chartChangeDonut.prompt', 'Altere o gráfico selecionado para donut.'),
|
|
14406
|
+
icon: 'donut_large',
|
|
14407
|
+
changeKind: 'set_chart_type',
|
|
14408
|
+
chartType: 'donut',
|
|
14409
|
+
capabilityId: 'praxis-chart.type.set@0.1.0',
|
|
14410
|
+
widgetKey: componentContext.widgetKey,
|
|
14411
|
+
}),
|
|
14412
|
+
this.contextualCapabilityQuickReply({
|
|
14413
|
+
id: 'chart-add-detail-table',
|
|
14414
|
+
label: this.context.tx('agentic.quickReplies.chartAddDetailTable.label', 'Detalhes em tabela'),
|
|
14415
|
+
prompt: this.context.tx('agentic.quickReplies.chartAddDetailTable.prompt', 'Adicione uma tabela de detalhes para a seleção do gráfico.'),
|
|
14416
|
+
icon: 'table_view',
|
|
14417
|
+
changeKind: 'enable_chart_drilldown',
|
|
14418
|
+
capabilityId: 'praxis-chart.drilldown.enable@0.1.0',
|
|
14419
|
+
widgetKey: componentContext.widgetKey,
|
|
14420
|
+
}),
|
|
14421
|
+
];
|
|
14422
|
+
}
|
|
14423
|
+
contextualCapabilityQuickReply(options) {
|
|
14424
|
+
return this.enrichContextualActionQuickReply({
|
|
14425
|
+
id: options.id,
|
|
14426
|
+
kind: 'suggestion',
|
|
14427
|
+
label: options.label,
|
|
14428
|
+
prompt: options.prompt,
|
|
14429
|
+
icon: options.icon,
|
|
14430
|
+
tone: 'analytics',
|
|
14431
|
+
contextHints: {
|
|
14432
|
+
source: 'component-capability-catalog',
|
|
14433
|
+
kind: 'contextual-preview-action',
|
|
14434
|
+
operationKind: 'modify',
|
|
14435
|
+
artifactKind: 'chart',
|
|
14436
|
+
changeKind: options.changeKind,
|
|
14437
|
+
...(options.chartType ? { chartType: options.chartType } : {}),
|
|
14438
|
+
capabilityId: options.capabilityId,
|
|
14439
|
+
targetComponentId: 'praxis-chart',
|
|
14440
|
+
selectedComponentId: 'praxis-chart',
|
|
14441
|
+
...(options.widgetKey ? { selectedWidgetKey: options.widgetKey } : {}),
|
|
14442
|
+
},
|
|
14443
|
+
});
|
|
14444
|
+
}
|
|
14445
|
+
shouldOfferContextualCapabilityActions(intentResolution) {
|
|
14446
|
+
if (this.isConsultativeCatalogIntent(intentResolution)) {
|
|
14447
|
+
return false;
|
|
14448
|
+
}
|
|
14449
|
+
const operationKind = (intentResolution.operationKind ?? '').trim().toLowerCase();
|
|
14450
|
+
const artifactKind = (intentResolution.artifactKind ?? '').trim().toLowerCase();
|
|
14451
|
+
const changeKind = (intentResolution.changeKind ?? '').trim().toLowerCase();
|
|
14452
|
+
if (operationKind !== 'explore' && operationKind !== 'explain') {
|
|
14453
|
+
return false;
|
|
14454
|
+
}
|
|
14455
|
+
if (artifactKind === 'chart') {
|
|
14456
|
+
return true;
|
|
14457
|
+
}
|
|
14458
|
+
return changeKind.includes('chart')
|
|
14459
|
+
|| changeKind.includes('component')
|
|
14460
|
+
|| !!this.resolveCurrentComponentContext(intentResolution);
|
|
14461
|
+
}
|
|
14462
|
+
resolveCurrentComponentContext(intentResolution) {
|
|
14463
|
+
const contextHints = this.toJsonObject(intentResolution.contextHints);
|
|
14464
|
+
const targetComponentId = this.readString(contextHints, 'targetComponentId')
|
|
14465
|
+
|| this.readString(contextHints, 'selectedComponentId')
|
|
14466
|
+
|| intentResolution.target?.componentId
|
|
14467
|
+
|| '';
|
|
14468
|
+
const targetWidgetKey = this.readString(contextHints, 'selectedWidgetKey')
|
|
14469
|
+
|| intentResolution.target?.widgetKey
|
|
14470
|
+
|| this.context.selectedWidgetKey()
|
|
14471
|
+
|| '';
|
|
14472
|
+
if (targetComponentId) {
|
|
14473
|
+
return { componentId: targetComponentId, widgetKey: targetWidgetKey || null };
|
|
14474
|
+
}
|
|
14475
|
+
const page = this.currentPageRecord();
|
|
14476
|
+
const widgets = Array.isArray(page?.['widgets']) ? page['widgets'] : [];
|
|
14477
|
+
const selectedWidget = targetWidgetKey
|
|
14478
|
+
? widgets.find((widget) => this.readWidgetKey(widget) === targetWidgetKey)
|
|
14479
|
+
: null;
|
|
14480
|
+
const selectedComponentId = selectedWidget ? this.readWidgetComponentId(selectedWidget) : '';
|
|
14481
|
+
if (selectedComponentId) {
|
|
14482
|
+
return { componentId: selectedComponentId, widgetKey: targetWidgetKey || null };
|
|
14483
|
+
}
|
|
14484
|
+
const chartWidget = widgets.find((widget) => this.readWidgetComponentId(widget) === 'praxis-chart');
|
|
14485
|
+
if (chartWidget) {
|
|
14486
|
+
return {
|
|
14487
|
+
componentId: 'praxis-chart',
|
|
14488
|
+
widgetKey: this.readWidgetKey(chartWidget) || null,
|
|
14489
|
+
};
|
|
14490
|
+
}
|
|
14491
|
+
return null;
|
|
14492
|
+
}
|
|
14493
|
+
currentPageRecord() {
|
|
14494
|
+
const page = this.context.currentPage();
|
|
14495
|
+
return page && typeof page === 'object' && !Array.isArray(page)
|
|
14496
|
+
? page
|
|
14497
|
+
: null;
|
|
14498
|
+
}
|
|
14499
|
+
readWidgetKey(widget) {
|
|
14500
|
+
const record = widget && typeof widget === 'object' && !Array.isArray(widget)
|
|
14501
|
+
? widget
|
|
14502
|
+
: null;
|
|
14503
|
+
const key = record?.['key'];
|
|
14504
|
+
return typeof key === 'string' ? key.trim() : '';
|
|
14505
|
+
}
|
|
14506
|
+
readWidgetComponentId(widget) {
|
|
14507
|
+
const record = widget && typeof widget === 'object' && !Array.isArray(widget)
|
|
14508
|
+
? widget
|
|
14509
|
+
: null;
|
|
14510
|
+
const definition = record?.['definition'];
|
|
14511
|
+
const definitionRecord = definition && typeof definition === 'object' && !Array.isArray(definition)
|
|
14512
|
+
? definition
|
|
14513
|
+
: null;
|
|
14514
|
+
const id = definitionRecord?.['id'];
|
|
14515
|
+
return typeof id === 'string' ? id.trim() : '';
|
|
14516
|
+
}
|
|
14517
|
+
enrichShellQuickReply(reply) {
|
|
14518
|
+
if (this.isContextualPreviewActionReply(reply, this.toJsonObject(reply.contextHints))) {
|
|
14519
|
+
return this.enrichContextualActionQuickReply(reply);
|
|
14520
|
+
}
|
|
14521
|
+
if (!this.isResourceQuickReply(reply)) {
|
|
14522
|
+
return reply;
|
|
14523
|
+
}
|
|
14524
|
+
const contextHints = { ...(reply.contextHints ?? {}) };
|
|
14525
|
+
if (!this.hasQuickReplyPresentation(contextHints)) {
|
|
14526
|
+
contextHints['presentation'] = this.resourceQuickReplyPresentation(reply);
|
|
14527
|
+
}
|
|
14528
|
+
return {
|
|
14529
|
+
...reply,
|
|
14530
|
+
description: this.resourceQuickReplyDescription(reply),
|
|
14531
|
+
icon: reply.icon || 'dataset',
|
|
14532
|
+
tone: reply.tone || 'resource',
|
|
14533
|
+
contextHints,
|
|
14534
|
+
};
|
|
14535
|
+
}
|
|
14536
|
+
enrichContextualActionQuickReply(reply) {
|
|
14537
|
+
const contextHints = this.toJsonObject(reply.contextHints) ?? {};
|
|
14538
|
+
const presentation = {
|
|
14539
|
+
kind: 'contextual-action',
|
|
14540
|
+
categoryLabel: this.context.tx('agentic.quickReplies.contextualAction.category', 'Ação sugerida'),
|
|
14541
|
+
description: this.contextualActionDescription(reply, contextHints),
|
|
14542
|
+
ctaLabel: this.context.tx('agentic.quickReplies.contextualAction.cta', 'Pré-visualizar ajuste'),
|
|
14543
|
+
icon: reply.icon || this.contextualActionIcon(reply, contextHints),
|
|
14544
|
+
tone: reply.tone || 'analytics',
|
|
14545
|
+
evidence: this.contextualActionEvidence(contextHints),
|
|
14546
|
+
};
|
|
14547
|
+
return {
|
|
14548
|
+
...reply,
|
|
14549
|
+
description: presentation.description,
|
|
14550
|
+
icon: presentation.icon,
|
|
14551
|
+
tone: presentation.tone,
|
|
14552
|
+
presentation,
|
|
14553
|
+
};
|
|
14554
|
+
}
|
|
14555
|
+
contextualActionDescription(reply, contextHints) {
|
|
14556
|
+
const existing = reply.description?.trim() ?? '';
|
|
14557
|
+
if (existing && !this.isGenericContextualActionDescription(existing)) {
|
|
14558
|
+
return existing;
|
|
14559
|
+
}
|
|
14560
|
+
const changeKind = this.readString(contextHints, 'changeKind');
|
|
14561
|
+
switch (changeKind) {
|
|
14562
|
+
case 'set_chart_type':
|
|
14563
|
+
return this.context.tx('agentic.quickReplies.contextualAction.chartType.description', 'Altera apenas a apresentação do gráfico selecionado e mantém a fonte de dados atual.');
|
|
14564
|
+
case 'enable_chart_drilldown':
|
|
14565
|
+
return this.context.tx('agentic.quickReplies.contextualAction.chartDrilldown.description', 'Adiciona uma superfície de detalhe a partir da seleção do gráfico, preservando o contexto do dado.');
|
|
14566
|
+
case 'configure_export':
|
|
14567
|
+
return this.context.tx('agentic.quickReplies.contextualAction.export.description', 'Configura uma ação operacional para exportar a seleção atual sem mudar a consulta base.');
|
|
14568
|
+
default:
|
|
14569
|
+
return this.context.tx('agentic.quickReplies.contextualAction.default.description', 'Prepara um ajuste compatível com as capacidades confirmadas do componente selecionado.');
|
|
14570
|
+
}
|
|
14571
|
+
}
|
|
14572
|
+
contextualActionIcon(reply, contextHints) {
|
|
14573
|
+
const changeKind = this.readString(contextHints, 'changeKind');
|
|
14574
|
+
const chartType = this.readString(contextHints, 'chartType')
|
|
14575
|
+
|| this.readString(contextHints, 'targetChartType');
|
|
14576
|
+
const actionId = reply.id?.trim() ?? '';
|
|
14577
|
+
if (changeKind === 'set_chart_type') {
|
|
14578
|
+
return chartType === 'donut' || actionId === 'chart-change-donut'
|
|
14579
|
+
? 'donut_large'
|
|
14580
|
+
: 'show_chart';
|
|
14581
|
+
}
|
|
14582
|
+
if (changeKind === 'enable_chart_drilldown')
|
|
14583
|
+
return 'table_view';
|
|
14584
|
+
if (changeKind === 'configure_export')
|
|
14585
|
+
return 'ios_share';
|
|
14586
|
+
return 'auto_fix_high';
|
|
14587
|
+
}
|
|
14588
|
+
contextualActionEvidence(contextHints) {
|
|
14589
|
+
const evidence = [];
|
|
14590
|
+
const targetComponentId = this.readString(contextHints, 'targetComponentId')
|
|
14591
|
+
|| this.readString(contextHints, 'selectedComponentId');
|
|
14592
|
+
const changeKind = this.readString(contextHints, 'changeKind');
|
|
14593
|
+
const capabilityId = this.readString(contextHints, 'capabilityId');
|
|
14594
|
+
const selectedWidgetKey = this.readString(contextHints, 'selectedWidgetKey');
|
|
14595
|
+
if (targetComponentId) {
|
|
14596
|
+
evidence.push({
|
|
14597
|
+
icon: 'widgets',
|
|
14598
|
+
value: this.shortTechnicalLabel(targetComponentId),
|
|
14599
|
+
ariaLabel: this.context.tx('agentic.quickReplies.contextualAction.componentEvidence', 'Componente {value}').replace('{value}', targetComponentId),
|
|
14600
|
+
});
|
|
14601
|
+
}
|
|
14602
|
+
if (changeKind) {
|
|
14603
|
+
evidence.push({
|
|
14604
|
+
icon: 'rule',
|
|
14605
|
+
value: this.shortTechnicalLabel(changeKind),
|
|
14606
|
+
ariaLabel: this.context.tx('agentic.quickReplies.contextualAction.changeEvidence', 'Mudança {value}').replace('{value}', changeKind),
|
|
14607
|
+
});
|
|
14608
|
+
}
|
|
14609
|
+
if (capabilityId) {
|
|
14610
|
+
evidence.push({
|
|
14611
|
+
icon: 'verified',
|
|
14612
|
+
value: this.context.tx('agentic.quickReplies.contextualAction.capabilityEvidence', 'capability'),
|
|
14613
|
+
ariaLabel: capabilityId,
|
|
14614
|
+
});
|
|
14615
|
+
}
|
|
14616
|
+
if (!capabilityId && selectedWidgetKey) {
|
|
14617
|
+
evidence.push({
|
|
14618
|
+
icon: 'ads_click',
|
|
14619
|
+
value: this.context.tx('agentic.quickReplies.contextualAction.selectionEvidence', 'seleção atual'),
|
|
14620
|
+
ariaLabel: selectedWidgetKey,
|
|
14621
|
+
});
|
|
14622
|
+
}
|
|
14623
|
+
return evidence.slice(0, 4);
|
|
14624
|
+
}
|
|
14625
|
+
isResourceQuickReply(reply) {
|
|
14626
|
+
const kind = (reply.kind || '').trim().toLowerCase();
|
|
14627
|
+
const id = (reply.id || '').trim().toLowerCase();
|
|
14628
|
+
const contextHints = this.toJsonObject(reply.contextHints);
|
|
14629
|
+
if (this.isContextualPreviewActionReply(reply, contextHints)) {
|
|
14630
|
+
return false;
|
|
14631
|
+
}
|
|
14632
|
+
return kind === 'resource'
|
|
14633
|
+
|| id.startsWith('resource-')
|
|
14634
|
+
|| !!this.readString(contextHints, 'resourcePath');
|
|
14635
|
+
}
|
|
14636
|
+
isContextualPreviewActionReply(reply, contextHints) {
|
|
14637
|
+
const hintSource = typeof contextHints?.['source'] === 'string'
|
|
14638
|
+
? contextHints['source'].trim()
|
|
14639
|
+
: '';
|
|
14640
|
+
const hintKind = typeof contextHints?.['kind'] === 'string'
|
|
14641
|
+
? contextHints['kind'].trim()
|
|
14642
|
+
: '';
|
|
14643
|
+
return hintSource === 'component-capability-catalog'
|
|
14644
|
+
|| hintKind === 'contextual-preview-action'
|
|
14645
|
+
|| (reply.id ?? '').startsWith('chart-')
|
|
14646
|
+
|| (reply.id ?? '').startsWith('table-export-');
|
|
14647
|
+
}
|
|
14648
|
+
hasQuickReplyPresentation(contextHints) {
|
|
14649
|
+
const presentation = contextHints['presentation'];
|
|
14650
|
+
if (!presentation || Array.isArray(presentation) || typeof presentation !== 'object') {
|
|
14651
|
+
return false;
|
|
14652
|
+
}
|
|
14653
|
+
return ['bestFor', 'returns', 'nextStep']
|
|
14654
|
+
.some((key) => typeof presentation[key] === 'string'
|
|
14655
|
+
&& !!String(presentation[key]).trim());
|
|
14656
|
+
}
|
|
14657
|
+
resourceQuickReplyDescription(reply) {
|
|
14658
|
+
const description = reply.description?.trim() ?? '';
|
|
14659
|
+
if (description
|
|
14660
|
+
&& !this.isTechnicalResourceDescription(description)
|
|
14661
|
+
&& !this.isGenericResourceDescription(description)) {
|
|
14662
|
+
return description;
|
|
14663
|
+
}
|
|
14664
|
+
return this.context.tx('agentic.resourceDiscovery.cardDescription', 'Fonte recomendada para transformar {label} em painel: ajuda a escolher graficos, listas, filtros e formatos antes de materializar a tela.').replace('{label}', reply.label);
|
|
14665
|
+
}
|
|
14666
|
+
resourceQuickReplyPresentation(reply) {
|
|
14667
|
+
const contextHints = this.toJsonObject(reply.contextHints);
|
|
14668
|
+
const artifactKind = this.readString(contextHints, 'artifactKind');
|
|
14669
|
+
if (artifactKind === 'table') {
|
|
14670
|
+
return {
|
|
14671
|
+
bestFor: `Boa quando voce quer transformar ${reply.label} em uma tabela navegavel.`,
|
|
14672
|
+
returns: 'Retorna uma pre-visualizacao com colunas, filtros e fonte semantica preservada.',
|
|
14673
|
+
nextStep: 'Clique para criar a tabela e revisar antes de salvar.',
|
|
14674
|
+
};
|
|
14675
|
+
}
|
|
14676
|
+
return {
|
|
14677
|
+
bestFor: this.context.tx('agentic.resourceDiscovery.cardBestFor', 'Quando voce quer entender se {label} responde ao objetivo de negocio antes de criar widgets.').replace('{label}', reply.label),
|
|
14678
|
+
returns: this.context.tx('agentic.resourceDiscovery.cardReturns', 'Sugere metricas, dimensoes, filtros, formatos de valor, graficos e listas de detalhe compativeis com a fonte.'),
|
|
14679
|
+
nextStep: this.context.tx('agentic.resourceDiscovery.cardNextStep', 'Selecione para eu propor uma pre-visualizacao governada com cards ricos, drill-down e formatos adequados por padrao.'),
|
|
14680
|
+
};
|
|
14681
|
+
}
|
|
14682
|
+
isTechnicalResourceDescription(description) {
|
|
14683
|
+
return /(?:^|\s)(?:GET|POST|PUT|PATCH|DELETE)\s+\//iu.test(description)
|
|
14684
|
+
|| /\/api\//iu.test(description)
|
|
14685
|
+
|| /\/schemas\//iu.test(description);
|
|
14686
|
+
}
|
|
14687
|
+
isGenericResourceDescription(description) {
|
|
14688
|
+
return /op(?:c|ç)ao encontrada no cat(?:a|á)logo sem(?:a|â)ntico/iu.test(description)
|
|
14689
|
+
|| /fonte candidata encontrada no cat(?:a|á)logo/iu.test(description);
|
|
14690
|
+
}
|
|
14691
|
+
isGenericContextualActionDescription(description) {
|
|
14692
|
+
const normalized = description
|
|
14693
|
+
.normalize('NFD')
|
|
14694
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
14695
|
+
.toLocaleLowerCase('pt-BR');
|
|
14696
|
+
return normalized.includes('acao sugerida')
|
|
14697
|
+
&& normalized.includes('capacidades confirmadas');
|
|
14698
|
+
}
|
|
14699
|
+
shortTechnicalLabel(value) {
|
|
14700
|
+
return value
|
|
14701
|
+
.trim()
|
|
14702
|
+
.replace(/^praxis-/u, '')
|
|
14703
|
+
.replace(/@.*$/u, '')
|
|
14704
|
+
.replace(/[_-]+/gu, ' ')
|
|
14705
|
+
.trim();
|
|
14706
|
+
}
|
|
13852
14707
|
buildPendingClarificationForNextTurn(request, sourcePrompt, clarification) {
|
|
13853
14708
|
return this.buildPendingClarification(sourcePrompt, clarification, request.clientTurnId);
|
|
13854
14709
|
}
|
|
@@ -13923,7 +14778,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13923
14778
|
targetApp: this.context.targetApp,
|
|
13924
14779
|
targetComponentId: this.context.targetComponentId,
|
|
13925
14780
|
currentPage: this.context.currentPage(),
|
|
13926
|
-
selectedWidgetKey,
|
|
14781
|
+
selectedWidgetKey: this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints),
|
|
13927
14782
|
provider: this.context.provider(),
|
|
13928
14783
|
model: this.context.model(),
|
|
13929
14784
|
apiKey: this.context.apiKey(),
|
|
@@ -13931,6 +14786,12 @@ class PageBuilderAgenticAuthoringTurnFlow {
|
|
|
13931
14786
|
...authoringContext,
|
|
13932
14787
|
};
|
|
13933
14788
|
}
|
|
14789
|
+
resolveSelectedWidgetKey(selectedWidgetKey, contextHints) {
|
|
14790
|
+
const hints = this.toJsonObject(contextHints) ?? null;
|
|
14791
|
+
return this.readString(hints, 'selectedWidgetKey')
|
|
14792
|
+
|| this.readString(hints, 'targetWidgetKey')
|
|
14793
|
+
|| selectedWidgetKey;
|
|
14794
|
+
}
|
|
13934
14795
|
buildContextHints(request) {
|
|
13935
14796
|
const base = this.toJsonObject(request.action?.contextHints)
|
|
13936
14797
|
?? this.toJsonObject(request.contextHints);
|
|
@@ -14173,6 +15034,8 @@ class DynamicPageBuilderComponent {
|
|
|
14173
15034
|
agenticAuthoringStatus = signal('', ...(ngDevMode ? [{ debugName: "agenticAuthoringStatus" }] : []));
|
|
14174
15035
|
agenticAuthoringError = signal('', ...(ngDevMode ? [{ debugName: "agenticAuthoringError" }] : []));
|
|
14175
15036
|
agenticAuthoringPreviewResult = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringPreviewResult" }] : []));
|
|
15037
|
+
agenticAuthoringSemanticDecision = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringSemanticDecision" }] : []));
|
|
15038
|
+
agenticAuthoringCanApply = signal(false, ...(ngDevMode ? [{ debugName: "agenticAuthoringCanApply" }] : []));
|
|
14176
15039
|
agenticAuthoringLastEtag = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringLastEtag" }] : []));
|
|
14177
15040
|
agenticAuthoringConversation = signal([], ...(ngDevMode ? [{ debugName: "agenticAuthoringConversation" }] : []));
|
|
14178
15041
|
agenticAuthoringQuickReplies = signal([], ...(ngDevMode ? [{ debugName: "agenticAuthoringQuickReplies" }] : []));
|
|
@@ -14198,12 +15061,12 @@ class DynamicPageBuilderComponent {
|
|
|
14198
15061
|
agenticAuthoringEditingMessageId = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringEditingMessageId" }] : []));
|
|
14199
15062
|
selectedWidgetKey = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetKey" }] : []));
|
|
14200
15063
|
agenticAuthoringWidgetContextKey = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringWidgetContextKey" }] : []));
|
|
14201
|
-
agenticAuthoringPanelLayout = signal({
|
|
14202
|
-
left: 16,
|
|
14203
|
-
top: 16,
|
|
15064
|
+
agenticAuthoringPanelLayout = signal(createPraxisAssistantViewportLayout({
|
|
14204
15065
|
width: 440,
|
|
14205
|
-
height:
|
|
14206
|
-
|
|
15066
|
+
height: 620,
|
|
15067
|
+
top: 96,
|
|
15068
|
+
margin: 24,
|
|
15069
|
+
}), ...(ngDevMode ? [{ debugName: "agenticAuthoringPanelLayout" }] : []));
|
|
14207
15070
|
previewMode = false;
|
|
14208
15071
|
agenticComponentCapabilities;
|
|
14209
15072
|
agenticComponentCapabilitiesPromise;
|
|
@@ -14429,7 +15292,7 @@ class DynamicPageBuilderComponent {
|
|
|
14429
15292
|
if (this.resolveSelectedWidgetKey()) {
|
|
14430
15293
|
return this.tx('agentic.header.title.widget', 'Praxis widget copilot');
|
|
14431
15294
|
}
|
|
14432
|
-
return this.tx('agentic.header.title.page', 'Praxis page copilot');
|
|
15295
|
+
return this.tx('agentic.header.title.page', 'Praxis page decision copilot');
|
|
14433
15296
|
}
|
|
14434
15297
|
agenticAuthoringHeaderSubtitle() {
|
|
14435
15298
|
const selectedWidgetLabel = this.resolveSelectedWidgetLabel();
|
|
@@ -14437,6 +15300,9 @@ class DynamicPageBuilderComponent {
|
|
|
14437
15300
|
return this.tx('agentic.header.subtitle.governed', 'Continue the governed semantic-decision flow.');
|
|
14438
15301
|
}
|
|
14439
15302
|
if (this.agenticAuthoringPreviewResult()?.valid) {
|
|
15303
|
+
if (!this.agenticAuthoringCanApply()) {
|
|
15304
|
+
return this.tx('agentic.header.subtitle.reviewBlocked', 'Preview ready for governed review.');
|
|
15305
|
+
}
|
|
14440
15306
|
return this.tx('agentic.header.subtitle.review', 'Preview ready for review and persistence.');
|
|
14441
15307
|
}
|
|
14442
15308
|
if (selectedWidgetLabel) {
|
|
@@ -14448,7 +15314,7 @@ class DynamicPageBuilderComponent {
|
|
|
14448
15314
|
return this.tx('agentic.header.subtitle.route', 'Authoring page route {route}.')
|
|
14449
15315
|
.replace('{route}', routePath);
|
|
14450
15316
|
}
|
|
14451
|
-
return this.tx('agentic.header.subtitle.page', '
|
|
15317
|
+
return this.tx('agentic.header.subtitle.page', 'Turn intent into layout, widgets, and governed materializations.');
|
|
14452
15318
|
}
|
|
14453
15319
|
agenticAuthoringHeaderModeLabel() {
|
|
14454
15320
|
if (this.agenticAuthoringSharedRuleHandoffState()) {
|
|
@@ -14466,7 +15332,7 @@ class DynamicPageBuilderComponent {
|
|
|
14466
15332
|
close: this.tx('agentic.minimize', 'Minimize'),
|
|
14467
15333
|
prompt: this.tx('agentic.promptLabel', 'Message'),
|
|
14468
15334
|
promptPlaceholder: this.tx('agentic.promptPlaceholder', 'Describe the page, dashboard, form or change you need.'),
|
|
14469
|
-
emptyConversation: this.
|
|
15335
|
+
emptyConversation: this.agenticAuthoringEmptyConversationMessage(),
|
|
14470
15336
|
submit: this.tx('agentic.preview', 'Generate preview'),
|
|
14471
15337
|
apply: this.tx('agentic.persist', 'Save'),
|
|
14472
15338
|
conversationAria: this.tx('agentic.conversationAria', 'AI conversation'),
|
|
@@ -14485,7 +15351,7 @@ class DynamicPageBuilderComponent {
|
|
|
14485
15351
|
modeDiagnostic: this.tx('agentic.mode.diagnostic', 'Diagnostic'),
|
|
14486
15352
|
modeReview: this.tx('agentic.mode.review', 'Review'),
|
|
14487
15353
|
modeInlineHelp: this.tx('agentic.mode.inlineHelp', 'Help'),
|
|
14488
|
-
stateIdle: this.tx('agentic.state.idle', '
|
|
15354
|
+
stateIdle: this.tx('agentic.state.idle', 'Ready'),
|
|
14489
15355
|
stateListening: this.tx('agentic.state.listening', 'Ready'),
|
|
14490
15356
|
stateProcessing: this.tx('agentic.state.processing', 'Processing'),
|
|
14491
15357
|
stateClarification: this.tx('agentic.state.clarification', 'Waiting for input'),
|
|
@@ -14495,6 +15361,39 @@ class DynamicPageBuilderComponent {
|
|
|
14495
15361
|
stateError: this.tx('agentic.state.error', 'Error'),
|
|
14496
15362
|
};
|
|
14497
15363
|
}
|
|
15364
|
+
agenticAuthoringEmptyConversationMessage() {
|
|
15365
|
+
const authoredOpening = this.resolveAgenticAuthoredOpeningMessage();
|
|
15366
|
+
if (authoredOpening) {
|
|
15367
|
+
return authoredOpening;
|
|
15368
|
+
}
|
|
15369
|
+
if (this.isAgenticAuthoringPageBlank()) {
|
|
15370
|
+
return this.tx('agentic.emptyConversation.blankGeneric', 'This host page is still blank. Tell me what decision or activity this app needs to support. I can suggest a dashboard, table, form, or review flow, then turn it into a governed preview for you to review before anything changes.');
|
|
15371
|
+
}
|
|
15372
|
+
return this.tx('agentic.emptyConversation.existingPage', 'Tell me what you want to improve here. I can read the current layout, widgets, route, and governed context, then prepare a preview for you to review before anything changes.');
|
|
15373
|
+
}
|
|
15374
|
+
resolveAgenticAuthoredOpeningMessage() {
|
|
15375
|
+
const hints = this.toRecord(this.agenticAuthoringContextHints);
|
|
15376
|
+
if (!hints)
|
|
15377
|
+
return null;
|
|
15378
|
+
const candidateRecords = [
|
|
15379
|
+
hints,
|
|
15380
|
+
this.toRecord(hints['domainOpening']),
|
|
15381
|
+
this.toRecord(hints['ragOpening']),
|
|
15382
|
+
this.toRecord(hints['opening']),
|
|
15383
|
+
this.toRecord(hints['domainSummary']),
|
|
15384
|
+
];
|
|
15385
|
+
for (const record of candidateRecords) {
|
|
15386
|
+
const message = this.trimmedString(record?.['openingMessage'])
|
|
15387
|
+
|| this.trimmedString(record?.['message']);
|
|
15388
|
+
if (message)
|
|
15389
|
+
return message;
|
|
15390
|
+
}
|
|
15391
|
+
return null;
|
|
15392
|
+
}
|
|
15393
|
+
isAgenticAuthoringPageBlank() {
|
|
15394
|
+
const widgets = this.currentPage().widgets;
|
|
15395
|
+
return !Array.isArray(widgets) || widgets.length === 0;
|
|
15396
|
+
}
|
|
14498
15397
|
agenticAuthoringSubmitAction() {
|
|
14499
15398
|
const label = this.tx('agentic.preview', 'Generate preview');
|
|
14500
15399
|
return {
|
|
@@ -14585,6 +15484,8 @@ class DynamicPageBuilderComponent {
|
|
|
14585
15484
|
this.agenticAuthoringStatus.set('');
|
|
14586
15485
|
this.agenticAuthoringError.set('');
|
|
14587
15486
|
this.agenticAuthoringPreviewResult.set(null);
|
|
15487
|
+
this.agenticAuthoringSemanticDecision.set(null);
|
|
15488
|
+
this.agenticAuthoringCanApply.set(false);
|
|
14588
15489
|
this.agenticAuthoringConversation.set([]);
|
|
14589
15490
|
this.agenticAuthoringQuickReplies.set([]);
|
|
14590
15491
|
this.agenticAuthoringAttachments.set([]);
|
|
@@ -14830,6 +15731,7 @@ class DynamicPageBuilderComponent {
|
|
|
14830
15731
|
});
|
|
14831
15732
|
}
|
|
14832
15733
|
}
|
|
15734
|
+
items.push(...this.agenticAuthoringSemanticDecisionContextItems());
|
|
14833
15735
|
const handoff = this.agenticAuthoringSharedRuleHandoffState();
|
|
14834
15736
|
if (handoff) {
|
|
14835
15737
|
items.push({
|
|
@@ -14921,6 +15823,138 @@ class DynamicPageBuilderComponent {
|
|
|
14921
15823
|
}
|
|
14922
15824
|
return items;
|
|
14923
15825
|
}
|
|
15826
|
+
agenticAuthoringSemanticDecisionContextItems() {
|
|
15827
|
+
const semanticDecision = this.toRecord(this.agenticAuthoringSemanticDecision());
|
|
15828
|
+
if (!semanticDecision) {
|
|
15829
|
+
return [];
|
|
15830
|
+
}
|
|
15831
|
+
const items = [];
|
|
15832
|
+
const selectedResource = this.toRecord(semanticDecision['selectedResource']);
|
|
15833
|
+
const resourcePath = this.trimmedString(selectedResource?.['resourcePath']);
|
|
15834
|
+
const operationKind = this.trimmedString(semanticDecision['operationKind']);
|
|
15835
|
+
const artifactKind = this.trimmedString(semanticDecision['artifactKind']);
|
|
15836
|
+
const changeKind = this.trimmedString(semanticDecision['changeKind']);
|
|
15837
|
+
if (this.shouldHideSemanticDecisionContextItems(operationKind, artifactKind, changeKind, resourcePath)) {
|
|
15838
|
+
return items;
|
|
15839
|
+
}
|
|
15840
|
+
if (resourcePath) {
|
|
15841
|
+
items.push({
|
|
15842
|
+
id: 'semantic-decision-resource',
|
|
15843
|
+
kind: 'custom',
|
|
15844
|
+
label: this.tx('agentic.context.semanticDecisionResource', 'Fonte'),
|
|
15845
|
+
value: this.humanizeAgenticResourcePath(resourcePath),
|
|
15846
|
+
icon: 'dataset',
|
|
15847
|
+
});
|
|
15848
|
+
}
|
|
15849
|
+
const decisionSummary = [operationKind, artifactKind, changeKind]
|
|
15850
|
+
.filter((value) => !!value)
|
|
15851
|
+
.join(' · ');
|
|
15852
|
+
if (decisionSummary) {
|
|
15853
|
+
items.push({
|
|
15854
|
+
id: 'semantic-decision-kind',
|
|
15855
|
+
kind: 'custom',
|
|
15856
|
+
label: this.tx('agentic.context.semanticDecisionKind', 'Objetivo'),
|
|
15857
|
+
value: this.humanizeAgenticDecisionSummary(operationKind ?? '', artifactKind ?? '', changeKind ?? ''),
|
|
15858
|
+
icon: 'account_tree',
|
|
15859
|
+
});
|
|
15860
|
+
}
|
|
15861
|
+
const retrievedEvidence = this.toRecord(semanticDecision['retrievedEvidence']);
|
|
15862
|
+
const retrievalEvidence = this.toRecord(semanticDecision['retrievalEvidence']);
|
|
15863
|
+
const retrievalSource = this.trimmedString(retrievedEvidence?.['retrievalSource'])
|
|
15864
|
+
|| this.trimmedString(retrievalEvidence?.['retrievalSource']);
|
|
15865
|
+
const reviewReason = this.trimmedString(semanticDecision['reviewReason']);
|
|
15866
|
+
const confidence = typeof semanticDecision['confidence'] === 'number'
|
|
15867
|
+
? semanticDecision['confidence']
|
|
15868
|
+
: null;
|
|
15869
|
+
const evidenceSummary = this.humanizeAgenticDecisionEvidence(retrievalSource ?? '', reviewReason ?? '', confidence);
|
|
15870
|
+
if (evidenceSummary) {
|
|
15871
|
+
items.push({
|
|
15872
|
+
id: 'semantic-decision-evidence',
|
|
15873
|
+
kind: 'custom',
|
|
15874
|
+
label: this.tx('agentic.context.semanticDecisionEvidence', 'Revisão'),
|
|
15875
|
+
value: evidenceSummary,
|
|
15876
|
+
icon: reviewReason ? 'policy' : 'verified',
|
|
15877
|
+
});
|
|
15878
|
+
}
|
|
15879
|
+
return items;
|
|
15880
|
+
}
|
|
15881
|
+
shouldHideSemanticDecisionContextItems(operationKind, artifactKind, changeKind, resourcePath) {
|
|
15882
|
+
const operation = (operationKind ?? '').trim().toLowerCase();
|
|
15883
|
+
const artifact = (artifactKind ?? '').trim().toLowerCase();
|
|
15884
|
+
const change = (changeKind ?? '').trim().toLowerCase();
|
|
15885
|
+
return artifact === 'unknown'
|
|
15886
|
+
|| artifact === 'api_catalog'
|
|
15887
|
+
|| operation === 'explore'
|
|
15888
|
+
|| operation === 'explain'
|
|
15889
|
+
|| change === 'answer_api_catalog_question'
|
|
15890
|
+
|| change === 'answer_catalog_question'
|
|
15891
|
+
|| change === 'api_catalog_followup';
|
|
15892
|
+
}
|
|
15893
|
+
humanizeAgenticResourcePath(resourcePath) {
|
|
15894
|
+
const lastSegment = resourcePath.split('?')[0].split('/').filter(Boolean).pop() || resourcePath;
|
|
15895
|
+
return lastSegment
|
|
15896
|
+
.replace(/^vw[-_]/i, '')
|
|
15897
|
+
.replace(/[-_]+/g, ' ')
|
|
15898
|
+
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
15899
|
+
}
|
|
15900
|
+
humanizeAgenticDecisionSummary(operationKind, artifactKind, changeKind) {
|
|
15901
|
+
const operation = this.humanizeAgenticOperationKind(operationKind);
|
|
15902
|
+
const artifact = this.humanizeAgenticArtifactKind(artifactKind);
|
|
15903
|
+
const change = this.humanizeAgenticChangeKind(changeKind);
|
|
15904
|
+
return [operation, artifact, change].filter((value) => !!value).join(' · ');
|
|
15905
|
+
}
|
|
15906
|
+
humanizeAgenticOperationKind(value) {
|
|
15907
|
+
const normalized = value.trim().toLowerCase();
|
|
15908
|
+
if (normalized === 'create')
|
|
15909
|
+
return this.tx('agentic.context.operationCreate', 'Criar');
|
|
15910
|
+
if (normalized === 'update')
|
|
15911
|
+
return this.tx('agentic.context.operationUpdate', 'Ajustar');
|
|
15912
|
+
if (normalized === 'read')
|
|
15913
|
+
return this.tx('agentic.context.operationRead', 'Consultar');
|
|
15914
|
+
return this.humanizeAgenticToken(value);
|
|
15915
|
+
}
|
|
15916
|
+
humanizeAgenticArtifactKind(value) {
|
|
15917
|
+
const normalized = value.trim().toLowerCase();
|
|
15918
|
+
if (normalized === 'dashboard')
|
|
15919
|
+
return this.tx('agentic.context.artifactDashboard', 'dashboard');
|
|
15920
|
+
if (normalized === 'table')
|
|
15921
|
+
return this.tx('agentic.context.artifactTable', 'tabela');
|
|
15922
|
+
if (normalized === 'form')
|
|
15923
|
+
return this.tx('agentic.context.artifactForm', 'formulário');
|
|
15924
|
+
if (normalized === 'page')
|
|
15925
|
+
return this.tx('agentic.context.artifactPage', 'tela');
|
|
15926
|
+
return this.humanizeAgenticToken(value).toLowerCase();
|
|
15927
|
+
}
|
|
15928
|
+
humanizeAgenticChangeKind(value) {
|
|
15929
|
+
const normalized = value.trim().toLowerCase();
|
|
15930
|
+
if (normalized.includes('analytics'))
|
|
15931
|
+
return this.tx('agentic.context.changeAnalytics', 'com análise');
|
|
15932
|
+
if (normalized.includes('dashboard'))
|
|
15933
|
+
return this.tx('agentic.context.changeDashboard', 'com visão gerencial');
|
|
15934
|
+
if (normalized.includes('table'))
|
|
15935
|
+
return this.tx('agentic.context.changeTable', 'com detalhes');
|
|
15936
|
+
if (normalized.includes('form'))
|
|
15937
|
+
return this.tx('agentic.context.changeForm', 'com edição');
|
|
15938
|
+
return this.humanizeAgenticToken(value).toLowerCase();
|
|
15939
|
+
}
|
|
15940
|
+
humanizeAgenticDecisionEvidence(retrievalSource, reviewReason, confidence) {
|
|
15941
|
+
if (reviewReason) {
|
|
15942
|
+
return this.tx('agentic.context.evidenceReviewRequired', 'Precisa revisar campos');
|
|
15943
|
+
}
|
|
15944
|
+
if (confidence !== null && confidence < 0.7) {
|
|
15945
|
+
return this.tx('agentic.context.evidenceLowConfidence', 'Precisa confirmar fonte');
|
|
15946
|
+
}
|
|
15947
|
+
if (retrievalSource) {
|
|
15948
|
+
return this.tx('agentic.context.evidenceGrounded', 'Fonte confirmada');
|
|
15949
|
+
}
|
|
15950
|
+
return '';
|
|
15951
|
+
}
|
|
15952
|
+
humanizeAgenticToken(value) {
|
|
15953
|
+
return value
|
|
15954
|
+
.trim()
|
|
15955
|
+
.replace(/[-_]+/g, ' ')
|
|
15956
|
+
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
15957
|
+
}
|
|
14924
15958
|
async previewAgenticAuthoring() {
|
|
14925
15959
|
const prompt = this.agenticAuthoringPrompt().trim();
|
|
14926
15960
|
if (!prompt || this.agenticAuthoringBusy())
|
|
@@ -14928,6 +15962,7 @@ class DynamicPageBuilderComponent {
|
|
|
14928
15962
|
this.agenticAuthoringBusy.set(true);
|
|
14929
15963
|
this.agenticAuthoringError.set('');
|
|
14930
15964
|
this.agenticAuthoringPreviewResult.set(null);
|
|
15965
|
+
this.agenticAuthoringCanApply.set(false);
|
|
14931
15966
|
this.agenticAuthoringSharedRuleHandoffState.set(null);
|
|
14932
15967
|
this.clearSharedRuleCockpitState();
|
|
14933
15968
|
this.clearProjectKnowledgeCockpitState();
|
|
@@ -14939,6 +15974,7 @@ class DynamicPageBuilderComponent {
|
|
|
14939
15974
|
? controller.submitEditedMessage(editingMessageId, prompt)
|
|
14940
15975
|
: controller.submitPrompt(prompt));
|
|
14941
15976
|
this.agenticAuthoringEditingMessageId.set(null);
|
|
15977
|
+
this.agenticAuthoringPrompt.set('');
|
|
14942
15978
|
}
|
|
14943
15979
|
catch (error) {
|
|
14944
15980
|
this.agenticAuthoringStatus.set('');
|
|
@@ -14975,6 +16011,7 @@ class DynamicPageBuilderComponent {
|
|
|
14975
16011
|
this.agenticAuthoringBusy.set(true);
|
|
14976
16012
|
this.agenticAuthoringError.set('');
|
|
14977
16013
|
this.agenticAuthoringPreviewResult.set(null);
|
|
16014
|
+
this.agenticAuthoringCanApply.set(false);
|
|
14978
16015
|
this.agenticAuthoringSharedRuleHandoffState.set(null);
|
|
14979
16016
|
this.clearSharedRuleCockpitState();
|
|
14980
16017
|
this.clearProjectKnowledgeCockpitState();
|
|
@@ -14992,6 +16029,7 @@ class DynamicPageBuilderComponent {
|
|
|
14992
16029
|
displayPrompt: visiblePrompt,
|
|
14993
16030
|
contextHints,
|
|
14994
16031
|
}));
|
|
16032
|
+
this.agenticAuthoringPrompt.set('');
|
|
14995
16033
|
}
|
|
14996
16034
|
catch (error) {
|
|
14997
16035
|
this.agenticAuthoringStatus.set('');
|
|
@@ -15095,9 +16133,25 @@ class DynamicPageBuilderComponent {
|
|
|
15095
16133
|
return visiblePrompt;
|
|
15096
16134
|
}
|
|
15097
16135
|
isResourceQuickReply(reply, contextHints) {
|
|
16136
|
+
if (this.isContextualPreviewActionQuickReply(reply, contextHints)) {
|
|
16137
|
+
return false;
|
|
16138
|
+
}
|
|
15098
16139
|
return this.hasResourceContextHint(contextHints)
|
|
15099
16140
|
&& !['cancel', 'revise'].includes((reply.kind || '').trim().toLowerCase());
|
|
15100
16141
|
}
|
|
16142
|
+
isContextualPreviewActionQuickReply(reply, contextHints) {
|
|
16143
|
+
const source = typeof contextHints?.['source'] === 'string'
|
|
16144
|
+
? contextHints['source'].trim()
|
|
16145
|
+
: '';
|
|
16146
|
+
const kind = typeof contextHints?.['kind'] === 'string'
|
|
16147
|
+
? contextHints['kind'].trim()
|
|
16148
|
+
: '';
|
|
16149
|
+
const id = (reply.id || '').trim();
|
|
16150
|
+
return source === 'component-capability-catalog'
|
|
16151
|
+
|| kind === 'contextual-preview-action'
|
|
16152
|
+
|| id.startsWith('chart-')
|
|
16153
|
+
|| id.startsWith('table-export-');
|
|
16154
|
+
}
|
|
15101
16155
|
isGovernedConfirmationQuickReply(reply, contextHints) {
|
|
15102
16156
|
return this.isConfirmationQuickReply(reply)
|
|
15103
16157
|
&& this.hasResourceContextHint(contextHints);
|
|
@@ -15165,6 +16219,7 @@ class DynamicPageBuilderComponent {
|
|
|
15165
16219
|
this.agenticAuthoringStatus.set(this.tx('agentic.status.resolvingIntent', 'Resolving intent...'));
|
|
15166
16220
|
this.agenticAuthoringError.set('');
|
|
15167
16221
|
this.agenticAuthoringPreviewResult.set(null);
|
|
16222
|
+
this.agenticAuthoringCanApply.set(false);
|
|
15168
16223
|
this.clearProjectKnowledgeCockpitState();
|
|
15169
16224
|
try {
|
|
15170
16225
|
await this.consumeAgenticTurn(this.ensureAgenticTurnController().resendMessage(message.id));
|
|
@@ -15205,6 +16260,8 @@ class DynamicPageBuilderComponent {
|
|
|
15205
16260
|
this.agenticAuthoringEditingMessageId.set(null);
|
|
15206
16261
|
this.agenticAuthoringPrompt.set('');
|
|
15207
16262
|
this.agenticAuthoringPreviewResult.set(null);
|
|
16263
|
+
this.agenticAuthoringSemanticDecision.set(null);
|
|
16264
|
+
this.agenticAuthoringCanApply.set(false);
|
|
15208
16265
|
this.agenticAuthoringSharedRuleHandoffState.set(null);
|
|
15209
16266
|
this.clearSharedRuleCockpitState();
|
|
15210
16267
|
this.clearProjectKnowledgeCockpitState();
|
|
@@ -15212,7 +16269,7 @@ class DynamicPageBuilderComponent {
|
|
|
15212
16269
|
}
|
|
15213
16270
|
async persistAgenticAuthoring() {
|
|
15214
16271
|
const preview = this.agenticAuthoringPreviewResult();
|
|
15215
|
-
if (!preview || this.agenticAuthoringBusy())
|
|
16272
|
+
if (!preview || !this.agenticAuthoringCanApply() || this.agenticAuthoringBusy())
|
|
15216
16273
|
return;
|
|
15217
16274
|
const componentId = this.resolveAgenticComponentId();
|
|
15218
16275
|
if (!componentId) {
|
|
@@ -15232,10 +16289,17 @@ class DynamicPageBuilderComponent {
|
|
|
15232
16289
|
tags: {
|
|
15233
16290
|
source: 'page-builder-agentic-authoring',
|
|
15234
16291
|
},
|
|
16292
|
+
semanticDecision: this.agenticAuthoringSemanticDecision(),
|
|
15235
16293
|
}));
|
|
15236
16294
|
this.agenticAuthoringLastEtag.set(result.etag ?? null);
|
|
15237
16295
|
this.agenticAuthoringApplied.emit(result);
|
|
16296
|
+
this.agenticAuthoringPreviewResult.set(null);
|
|
16297
|
+
this.agenticAuthoringSemanticDecision.set(null);
|
|
16298
|
+
this.agenticAuthoringCanApply.set(false);
|
|
16299
|
+
this.agenticAuthoringQuickReplies.set([]);
|
|
16300
|
+
this.agenticAuthoringPrompt.set('');
|
|
15238
16301
|
this.agenticAuthoringStatus.set(this.tx('agentic.status.saved', 'Page saved.'));
|
|
16302
|
+
this.syncAgenticAuthoringSession();
|
|
15239
16303
|
}
|
|
15240
16304
|
catch (error) {
|
|
15241
16305
|
this.agenticAuthoringStatus.set('');
|
|
@@ -15797,6 +16861,7 @@ class DynamicPageBuilderComponent {
|
|
|
15797
16861
|
this.agenticAuthoringStatus.set(this.tx('agentic.status.sharedRuleTargetSelected', 'Shared-rule target selected. Continue by creating the governed definition.'));
|
|
15798
16862
|
this.agenticAuthoringError.set('');
|
|
15799
16863
|
this.agenticAuthoringPreviewResult.set(null);
|
|
16864
|
+
this.agenticAuthoringCanApply.set(false);
|
|
15800
16865
|
this.agenticAuthoringSharedRuleHandoffState.set(next);
|
|
15801
16866
|
this.agenticAuthoringSharedRuleHandoff.emit(next);
|
|
15802
16867
|
this.appendAgenticMessage('user', visiblePrompt);
|
|
@@ -16063,12 +17128,14 @@ class DynamicPageBuilderComponent {
|
|
|
16063
17128
|
const handoff = this.resolveAgenticSharedRuleHandoff(state);
|
|
16064
17129
|
const previousHandoff = this.agenticAuthoringSharedRuleHandoffState();
|
|
16065
17130
|
this.agenticAuthoringConversation.set(state.messages);
|
|
16066
|
-
this.agenticAuthoringQuickReplies.set(
|
|
17131
|
+
this.agenticAuthoringQuickReplies.set(state.quickReplies);
|
|
16067
17132
|
this.agenticAuthoringStatus.set(handoff && !preview?.valid
|
|
16068
17133
|
? this.tx('agentic.status.sharedRuleHandoff', 'Continue this request in the shared-rules flow.')
|
|
16069
17134
|
: state.statusText);
|
|
16070
17135
|
this.agenticAuthoringError.set(state.errorText);
|
|
16071
17136
|
this.agenticAuthoringPreviewResult.set(preview);
|
|
17137
|
+
this.agenticAuthoringSemanticDecision.set(this.resolveAgenticSemanticDecision(state.diagnostics));
|
|
17138
|
+
this.agenticAuthoringCanApply.set(!!preview?.valid && !!state.canApply);
|
|
16072
17139
|
this.moveAgenticAuthoringPanelToReviewSidecar(preview);
|
|
16073
17140
|
this.agenticAuthoringAttachments.set(state.attachments);
|
|
16074
17141
|
if (!this.sameSharedRuleHandoffIdentity(previousHandoff, handoff)) {
|
|
@@ -16124,7 +17191,7 @@ class DynamicPageBuilderComponent {
|
|
|
16124
17191
|
}
|
|
16125
17192
|
this.agenticAuthoringPanelLayout.set(createPraxisAssistantViewportLayout({
|
|
16126
17193
|
width: 440,
|
|
16127
|
-
height:
|
|
17194
|
+
height: 620,
|
|
16128
17195
|
top: 96,
|
|
16129
17196
|
margin: 24,
|
|
16130
17197
|
}));
|
|
@@ -16266,7 +17333,14 @@ class DynamicPageBuilderComponent {
|
|
|
16266
17333
|
return Object.keys(merged).length ? merged : undefined;
|
|
16267
17334
|
}
|
|
16268
17335
|
consumeAgenticTurn(states$) {
|
|
16269
|
-
return
|
|
17336
|
+
return firstValueFrom(states$.pipe(concatMap((state) => from(this.applyAgenticTurnState(state)).pipe(map(() => state))), filter((state) => this.isAgenticTurnTerminalState(state)), take(1)));
|
|
17337
|
+
}
|
|
17338
|
+
isAgenticTurnTerminalState(state) {
|
|
17339
|
+
return state.state === 'review'
|
|
17340
|
+
|| state.state === 'clarification'
|
|
17341
|
+
|| state.state === 'error'
|
|
17342
|
+
|| state.state === 'success'
|
|
17343
|
+
|| state.state === 'listening';
|
|
16270
17344
|
}
|
|
16271
17345
|
agenticAuthoringDiagnosticsTop() {
|
|
16272
17346
|
return Math.max(16, this.agenticAuthoringPanelLayout().top);
|
|
@@ -16285,6 +17359,11 @@ class DynamicPageBuilderComponent {
|
|
|
16285
17359
|
const intentResolution = this.toRecord(diagnostics?.['intentResolution']);
|
|
16286
17360
|
return this.toRecord(intentResolution?.['llmDiagnostics']);
|
|
16287
17361
|
}
|
|
17362
|
+
resolveAgenticSemanticDecision(diagnostics) {
|
|
17363
|
+
const intentResolution = this.toRecord(diagnostics?.['intentResolution']);
|
|
17364
|
+
const semanticDecision = this.toRecord(intentResolution?.['semanticDecision']);
|
|
17365
|
+
return semanticDecision ? semanticDecision : null;
|
|
17366
|
+
}
|
|
16288
17367
|
cloneAgenticContextHints(contextHints) {
|
|
16289
17368
|
if (!contextHints || typeof contextHints !== 'object' || Array.isArray(contextHints)) {
|
|
16290
17369
|
return undefined;
|
|
@@ -16330,8 +17409,10 @@ class DynamicPageBuilderComponent {
|
|
|
16330
17409
|
}
|
|
16331
17410
|
resolvePreviewCompiledFormPatch(preview) {
|
|
16332
17411
|
if (preview.uiCompositionPlan || preview.compiledFormPatch?.patch?.page) {
|
|
17412
|
+
const planDiagnostics = this.toRecord(this.toRecord(preview.uiCompositionPlan)?.['diagnostics']);
|
|
16333
17413
|
return {
|
|
16334
17414
|
...preview.compiledFormPatch,
|
|
17415
|
+
diagnostics: planDiagnostics ?? preview.compiledFormPatch?.['diagnostics'],
|
|
16335
17416
|
patch: {
|
|
16336
17417
|
...(preview.compiledFormPatch?.patch ?? {}),
|
|
16337
17418
|
page: this.clonePage(this.currentPage()),
|
|
@@ -16359,7 +17440,7 @@ class DynamicPageBuilderComponent {
|
|
|
16359
17440
|
return this.clonePage(input);
|
|
16360
17441
|
}
|
|
16361
17442
|
clonePage(page) {
|
|
16362
|
-
return JSON.parse(JSON.stringify(page));
|
|
17443
|
+
return normalizePageBuilderRuntimePage(JSON.parse(JSON.stringify(page)));
|
|
16363
17444
|
}
|
|
16364
17445
|
clearSelectedWidgetIfMissing(page) {
|
|
16365
17446
|
const selected = this.selectedWidgetKey();
|
|
@@ -16580,7 +17661,7 @@ class DynamicPageBuilderComponent {
|
|
|
16580
17661
|
[statusText]="agenticAuthoringStatus()"
|
|
16581
17662
|
[errorText]="agenticAuthoringError()"
|
|
16582
17663
|
[busy]="agenticAuthoringBusy()"
|
|
16583
|
-
[canApply]="
|
|
17664
|
+
[canApply]="agenticAuthoringCanApply()"
|
|
16584
17665
|
[primaryAction]="agenticAuthoringSubmitAction()"
|
|
16585
17666
|
[showAttachAction]="false"
|
|
16586
17667
|
[enablePastedAttachments]="false"
|
|
@@ -17004,7 +18085,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
17004
18085
|
[statusText]="agenticAuthoringStatus()"
|
|
17005
18086
|
[errorText]="agenticAuthoringError()"
|
|
17006
18087
|
[busy]="agenticAuthoringBusy()"
|
|
17007
|
-
[canApply]="
|
|
18088
|
+
[canApply]="agenticAuthoringCanApply()"
|
|
17008
18089
|
[primaryAction]="agenticAuthoringSubmitAction()"
|
|
17009
18090
|
[showAttachAction]="false"
|
|
17010
18091
|
[enablePastedAttachments]="false"
|