@praxisui/page-builder 8.0.0-beta.26 → 8.0.0-beta.28

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.
@@ -25,13 +25,13 @@ 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, firstValueFrom, from, concatMap, catchError, of, lastValueFrom } from 'rxjs';
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';
32
32
  import { MatTabsModule } from '@angular/material/tabs';
33
33
  import { HttpClient, HttpHeaders } from '@angular/common/http';
34
- import { AI_STREAM_EVENT_TYPES, toPraxisAssistantConversationMessages, PraxisAssistantTurnOrchestratorService, PraxisAssistantSessionRegistryService, PraxisAiAssistantShellComponent } from '@praxisui/ai';
34
+ import { AI_STREAM_EVENT_TYPES, toPraxisAssistantConversationMessages, PraxisAssistantTurnOrchestratorService, PraxisAssistantSessionRegistryService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
35
35
 
36
36
  const PLACEHOLDER = 1;
37
37
 
@@ -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': 'Author page-level layout, widgets and governed materialization.',
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': 'Tell me what you want to create or change. I will ask follow-up questions before applying the preview.',
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': '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 APIs that can feed this screen. Choose one before generating the preview.',
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} governed project knowledge signals were cited in sourceRefs.',
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': 'Autore layout, widgets e materialização governada no nível da página.',
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': 'Diga o que você quer criar ou alterar. Vou fazer perguntas antes de aplicar a pré-visualização.',
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': 'Ocioso',
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 APIs que podem alimentar esta tela. Escolha uma antes de gerar a pré-visualização.',
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} sinais de conhecimento governado foram citados em sourceRefs.',
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 = 60000;
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
  });
@@ -11345,10 +11404,11 @@ class PageBuilderAgenticAuthoringService {
11345
11404
  }
11346
11405
  createEventSource(url) {
11347
11406
  const factory = this.options?.eventSourceFactory;
11407
+ const options = { withCredentials: true };
11348
11408
  if (factory) {
11349
- return factory(url);
11409
+ return factory(url, options);
11350
11410
  }
11351
- return new EventSource(url);
11411
+ return new EventSource(url, options);
11352
11412
  }
11353
11413
  async probeTurnStreamEndpoint(url, abort) {
11354
11414
  if (typeof fetch === 'undefined') {
@@ -11543,7 +11603,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
11543
11603
  { name: 'pageChange', type: 'WidgetPageDefinition', description: 'Emitted after local apply/preview produces a renderable page.' },
11544
11604
  { name: 'agenticAuthoringEnableStreaming', type: 'boolean', description: 'Opt-in flag for the canonical streaming turn endpoints.' },
11545
11605
  { name: 'agenticAuthoringIncludeLlmDiagnostics', type: 'boolean', description: 'Opt-in flag that exposes governed diagnostics as cockpit evidence for validation and debugging.' },
11546
- { 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.' },
11547
11607
  ],
11548
11608
  editableTargets: [
11549
11609
  { kind: 'page', resolver: 'widget-page-definition-root', description: 'Root WidgetPageDefinition document: title, metadata, context and renderable page envelope.' },
@@ -12010,7 +12070,7 @@ function compileUiCompositionPlan(plan) {
12010
12070
  layoutPreset: plan.layoutPreset,
12011
12071
  canvas: clone(plan.canvas),
12012
12072
  state: clone(plan.state),
12013
- widgets: plan.widgets.map(toWidgetInstance),
12073
+ widgets: plan.widgets.map((widget) => toWidgetInstance(widget, plan.bindings ?? [])),
12014
12074
  composition: {
12015
12075
  version: '1.0.0',
12016
12076
  links: (plan.bindings ?? []).map(toCompositionLink),
@@ -12170,17 +12230,32 @@ function validateNestedPath(nestedPath, diagnostics, path) {
12170
12230
  });
12171
12231
  }
12172
12232
  }
12173
- function toWidgetInstance(widget) {
12233
+ function toWidgetInstance(widget, bindings) {
12234
+ const outputs = linkedTopLevelOutputs(widget.key, widget.outputs, bindings);
12174
12235
  return {
12175
12236
  key: widget.key,
12176
12237
  definition: {
12177
12238
  id: widget.componentId,
12178
12239
  bindingOrder: widget.bindingOrder,
12179
12240
  inputs: clone(widget.inputs ?? {}),
12180
- outputs: clone(widget.outputs ?? {}),
12241
+ outputs,
12181
12242
  },
12182
12243
  };
12183
12244
  }
12245
+ function linkedTopLevelOutputs(widgetKey, declaredOutputs, bindings) {
12246
+ const outputs = clone(declaredOutputs ?? {});
12247
+ for (const binding of bindings) {
12248
+ const endpoint = binding.from;
12249
+ if (endpoint.kind !== 'component-port'
12250
+ || endpoint.direction !== 'output'
12251
+ || endpoint.widget !== widgetKey
12252
+ || endpoint.nestedPath?.length) {
12253
+ continue;
12254
+ }
12255
+ outputs[endpoint.port] ??= 'emit';
12256
+ }
12257
+ return outputs;
12258
+ }
12184
12259
  function toCompositionLink(binding) {
12185
12260
  const transform = binding.transform ? toCompositionTransform(binding.transform) : undefined;
12186
12261
  return {
@@ -12312,6 +12387,84 @@ function clone(value) {
12312
12387
  }
12313
12388
  }
12314
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
+
12315
12468
  const LEGACY_OPTIONS_KEY = 'options';
12316
12469
  const LEGACY_LAYOUT_KEY = 'layout';
12317
12470
  class PageBuilderAiAdapter {
@@ -12436,7 +12589,8 @@ class PageBuilderAiAdapter {
12436
12589
  return page;
12437
12590
  const cloned = this.clone(page);
12438
12591
  const { [LEGACY_OPTIONS_KEY]: _legacyOptions, ...rest } = cloned;
12439
- const widgets = (cloned.widgets || []).map((w) => this.stripLegacyLayoutFields(w));
12592
+ const widgets = (cloned.widgets || [])
12593
+ .map((w) => normalizePageBuilderRuntimeWidget(this.stripLegacyLayoutFields(w)));
12440
12594
  return {
12441
12595
  ...rest,
12442
12596
  widgets,
@@ -12456,7 +12610,8 @@ class PageBuilderAiAdapter {
12456
12610
  return page;
12457
12611
  const cloned = this.clone(page);
12458
12612
  const { [LEGACY_OPTIONS_KEY]: _legacyOptions, ...rest } = cloned;
12459
- const widgets = (cloned.widgets || []).map((w) => this.stripLegacyLayoutFields(w));
12613
+ const widgets = (cloned.widgets || [])
12614
+ .map((w) => normalizePageBuilderRuntimeWidget(this.stripLegacyLayoutFields(w)));
12460
12615
  return {
12461
12616
  ...rest,
12462
12617
  widgets,
@@ -12830,6 +12985,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
12830
12985
  phase: 'capture',
12831
12986
  });
12832
12987
  }
12988
+ const contextualActionContext = this.contextualPreviewActionContextFromRequest(request);
12989
+ if (contextualActionContext) {
12990
+ return from(this.submitContextualPreviewAction(request, prompt, contextualActionContext));
12991
+ }
12833
12992
  if (this.context.enableTurnStream?.() === true && this.service.streamTurn) {
12834
12993
  return this.submitWithTurnStream(request, prompt);
12835
12994
  }
@@ -12847,9 +13006,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
12847
13006
  const componentCapabilities = await this.context.loadComponentCapabilities();
12848
13007
  const selectedWidgetKey = this.context.selectedWidgetKey();
12849
13008
  const intentResolution = await firstValueFrom(this.service.resolveIntent(this.buildIntentResolutionRequest(prompt, selectedWidgetKey, componentCapabilities, authoringContext)));
12850
- const intentAssistantMessage = this.resolveIntentAssistantMessage(intentResolution);
13009
+ const intentQuickReplies = this.resolveShellQuickReplies(intentResolution);
13010
+ const intentAssistantMessage = this.normalizeAssistantMessageForQuickReplies(this.resolveIntentAssistantMessage(intentResolution), intentQuickReplies);
12851
13011
  if (intentAssistantMessage) {
12852
- const quickReplies = this.toShellQuickReplies(intentResolution.quickReplies ?? []);
13012
+ const quickReplies = intentQuickReplies;
12853
13013
  const explicitPendingClarification = this.toShellPendingClarification(intentResolution.pendingClarification);
12854
13014
  const intentClarification = this.resolveIntentClarification(intentResolution);
12855
13015
  const routeRequiredClarification = this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, prompt), request.clientTurnId);
@@ -12857,10 +13017,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
12857
13017
  ?? (intentClarification
12858
13018
  ? this.buildPendingClarificationForNextTurn(request, this.resolveEffectivePrompt(intentResolution, prompt), intentClarification)
12859
13019
  : routeRequiredClarification);
13020
+ const consultativeCatalogIntent = this.isConsultativeCatalogIntent(intentResolution);
12860
13021
  const shouldAutoGenerateGuidedPreview = this.shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt) && !this.hasPendingClarificationQuestion(pendingClarification);
12861
- const mustPauseForClarification = (!this.isExecutableIntent(intentResolution) && !shouldAutoGenerateGuidedPreview)
13022
+ const mustPauseForClarification = (!this.isExecutableIntent(intentResolution, request) && !shouldAutoGenerateGuidedPreview)
12862
13023
  || this.hasPendingClarificationQuestion(pendingClarification);
12863
- if (mustPauseForClarification && !this.hasPendingClarificationQuestion(pendingClarification) && quickReplies.length === 0) {
13024
+ if (mustPauseForClarification
13025
+ && !this.hasPendingClarificationQuestion(pendingClarification)
13026
+ && (quickReplies.length === 0 || consultativeCatalogIntent)) {
12864
13027
  return {
12865
13028
  state: 'success',
12866
13029
  phase: 'summarize',
@@ -12909,7 +13072,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
12909
13072
  state: 'clarification',
12910
13073
  phase: 'clarify',
12911
13074
  assistantMessage: clarification,
12912
- quickReplies: this.toShellQuickReplies(intentResolution.quickReplies ?? []),
13075
+ quickReplies: this.resolveShellQuickReplies(intentResolution),
12913
13076
  canApply: false,
12914
13077
  statusText: '',
12915
13078
  errorText: '',
@@ -12937,7 +13100,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
12937
13100
  model: this.context.model(),
12938
13101
  apiKey: this.context.apiKey(),
12939
13102
  currentPage: this.context.currentPage(),
12940
- selectedWidgetKey,
13103
+ selectedWidgetKey: this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints),
12941
13104
  intentResolution,
12942
13105
  componentCapabilities,
12943
13106
  ...authoringContext,
@@ -12970,14 +13133,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
12970
13133
  };
12971
13134
  }
12972
13135
  const status = this.context.describePreviewStatus(preview);
12973
- const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
12974
13136
  return {
12975
13137
  state: 'review',
12976
13138
  phase: 'review',
12977
13139
  assistantMessage: status,
12978
13140
  quickReplies: [],
12979
13141
  canApply: true,
12980
- statusText,
13142
+ statusText: this.reviewStatusText(status, true),
12981
13143
  errorText: '',
12982
13144
  preview,
12983
13145
  diagnostics: { intentResolution },
@@ -13019,21 +13181,68 @@ class PageBuilderAgenticAuthoringTurnFlow {
13019
13181
  pendingPatch: null,
13020
13182
  };
13021
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
+ }
13022
13230
  async buildTurnStreamRequest(request, prompt) {
13023
13231
  const componentCapabilities = await this.context.loadComponentCapabilities();
13024
13232
  const selectedWidgetKey = this.context.selectedWidgetKey();
13233
+ const authoringContext = this.buildAuthoringContext(request);
13025
13234
  return {
13026
13235
  userPrompt: prompt,
13027
13236
  targetApp: this.context.targetApp,
13028
13237
  targetComponentId: this.context.targetComponentId,
13029
13238
  currentRoute: null,
13030
13239
  currentPage: this.context.currentPage(),
13031
- selectedWidgetKey,
13240
+ selectedWidgetKey: this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints),
13032
13241
  provider: this.context.provider(),
13033
13242
  model: this.context.model(),
13034
13243
  apiKey: this.context.apiKey(),
13035
13244
  componentCapabilities,
13036
- ...this.buildAuthoringContext(request),
13245
+ ...authoringContext,
13037
13246
  };
13038
13247
  }
13039
13248
  async toTurnResultFromStreamEvent(event, request, prompt) {
@@ -13092,14 +13301,21 @@ class PageBuilderAgenticAuthoringTurnFlow {
13092
13301
  preview: null,
13093
13302
  };
13094
13303
  }
13095
- const assistantMessage = this.readString(payload, 'assistantMessage')
13304
+ const rawAssistantMessage = this.readString(payload, 'assistantMessage')
13096
13305
  || this.resolveIntentAssistantMessage(intentResolution)
13097
13306
  || (preview ? this.context.describePreviewStatus(preview) : '');
13098
13307
  const rawQuickReplies = Array.isArray(payload['quickReplies'])
13099
13308
  ? payload['quickReplies']
13100
13309
  : intentResolution.quickReplies ?? [];
13101
- const quickReplies = this.toShellQuickReplies(rawQuickReplies);
13310
+ const quickReplies = this.resolveShellQuickReplies(intentResolution, rawQuickReplies);
13311
+ const assistantMessage = this.normalizeAssistantMessageForQuickReplies(rawAssistantMessage, quickReplies);
13102
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
+ }
13103
13319
  if (canApply
13104
13320
  && request
13105
13321
  && prompt
@@ -13107,17 +13323,54 @@ class PageBuilderAgenticAuthoringTurnFlow {
13107
13323
  return this.completeExecutableStreamPreview(request, prompt, intentResolution, undefined);
13108
13324
  }
13109
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
+ }
13110
13363
  const pendingClarification = this.toShellPendingClarification(intentResolution?.pendingClarification)
13111
13364
  ?? this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, assistantMessage));
13112
13365
  if (!pendingClarification
13113
- && (this.isExecutableIntent(intentResolution)
13366
+ && (this.isExecutableIntent(intentResolution, request)
13114
13367
  || (!!prompt && this.shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt)))
13115
13368
  && !this.hasBlockingResourceQuickReply(quickReplies)
13116
13369
  && request
13117
13370
  && prompt) {
13118
13371
  return this.completeExecutableStreamPreview(request, prompt, intentResolution, preview);
13119
13372
  }
13120
- const requiresChoice = quickReplies.length > 0;
13373
+ const requiresChoice = quickReplies.length > 0 && !this.isConsultativeCatalogIntent(intentResolution);
13121
13374
  return {
13122
13375
  state: pendingClarification || requiresChoice ? 'clarification' : 'success',
13123
13376
  phase: pendingClarification || requiresChoice ? 'clarify' : 'summarize',
@@ -13146,14 +13399,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
13146
13399
  };
13147
13400
  }
13148
13401
  const status = assistantMessage || this.context.describePreviewStatus(preview);
13149
- const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
13150
13402
  return {
13151
13403
  state: 'review',
13152
13404
  phase: 'review',
13153
13405
  assistantMessage: status,
13154
- quickReplies: [],
13406
+ quickReplies,
13155
13407
  canApply: true,
13156
- statusText,
13408
+ statusText: this.reviewStatusText(status, true),
13157
13409
  errorText: '',
13158
13410
  preview,
13159
13411
  diagnostics: { intentResolution, preview },
@@ -13166,7 +13418,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
13166
13418
  return false;
13167
13419
  }
13168
13420
  const contextHints = this.toJsonObject(reply.contextHints);
13169
- return !!this.readString(contextHints, 'resourcePath');
13421
+ if (this.isContextualPreviewActionReply(reply, contextHints)) {
13422
+ return false;
13423
+ }
13424
+ return !!this.readString(contextHints, 'resourcePath') || this.isResourceQuickReply(reply);
13170
13425
  });
13171
13426
  }
13172
13427
  async completeExecutableStreamPreview(request, prompt, intentResolution, streamPreview) {
@@ -13174,6 +13429,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
13174
13429
  const authoringContext = this.buildAuthoringContext(request);
13175
13430
  const componentCapabilities = await this.context.loadComponentCapabilities();
13176
13431
  const selectedWidgetKey = this.context.selectedWidgetKey();
13432
+ const effectiveSelectedWidgetKey = this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints);
13177
13433
  const reusableStreamPreview = streamPreview?.valid
13178
13434
  && !this.shouldRegenerateStreamPreview(intentResolution, streamPreview);
13179
13435
  const preview = reusableStreamPreview
@@ -13184,7 +13440,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
13184
13440
  model: this.context.model(),
13185
13441
  apiKey: this.context.apiKey(),
13186
13442
  currentPage: this.context.currentPage(),
13187
- selectedWidgetKey,
13443
+ selectedWidgetKey: effectiveSelectedWidgetKey,
13188
13444
  intentResolution,
13189
13445
  componentCapabilities,
13190
13446
  ...authoringContext,
@@ -13217,14 +13473,13 @@ class PageBuilderAgenticAuthoringTurnFlow {
13217
13473
  };
13218
13474
  }
13219
13475
  const status = this.context.describePreviewStatus(preview);
13220
- const statusText = this.withProjectKnowledgeAuditStatus(status, preview);
13221
13476
  return {
13222
13477
  state: 'review',
13223
13478
  phase: 'review',
13224
13479
  assistantMessage: status,
13225
13480
  quickReplies: [],
13226
13481
  canApply: true,
13227
- statusText,
13482
+ statusText: this.reviewStatusText(status, true),
13228
13483
  errorText: '',
13229
13484
  preview,
13230
13485
  diagnostics: { intentResolution, preview },
@@ -13256,6 +13511,43 @@ class PageBuilderAgenticAuthoringTurnFlow {
13256
13511
  }
13257
13512
  return true;
13258
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
+ }
13259
13551
  phaseForStreamPayload(payload) {
13260
13552
  const phase = this.readString(payload, 'phase');
13261
13553
  if (phase === 'intent.resolve')
@@ -13306,21 +13598,22 @@ class PageBuilderAgenticAuthoringTurnFlow {
13306
13598
  }
13307
13599
  return base;
13308
13600
  }
13309
- withProjectKnowledgeAuditStatus(status, preview) {
13310
- const audit = this.toJsonObject(preview?.diagnostics?.projectKnowledgeAudit);
13311
- if (!audit) {
13312
- return status;
13313
- }
13314
- const influenceCount = this.readNumber(audit, 'influenceCount');
13315
- const citedCount = this.readNumber(audit, 'citedCount');
13316
- if (!influenceCount || influenceCount <= 0 || citedCount === null || citedCount < 0) {
13317
- return status;
13601
+ reviewStatusText(status, canApply) {
13602
+ const normalized = status.trim();
13603
+ if (normalized && !this.shouldReplaceReviewStatus(normalized)) {
13604
+ return normalized;
13318
13605
  }
13319
- const auditStatus = this.context
13320
- .tx('agentic.status.projectKnowledgeAuditCited', '{cited} of {count} governed project knowledge signals were cited in sourceRefs.')
13321
- .replace('{cited}', String(citedCount))
13322
- .replace('{count}', String(influenceCount));
13323
- return [status, auditStatus].filter((part) => !!part.trim()).join(' ');
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');
13324
13617
  }
13325
13618
  isBackendResourceDiscoveryPayload(payload) {
13326
13619
  const diagnostics = this.toJsonObject(payload['diagnostics']);
@@ -13358,7 +13651,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
13358
13651
  }
13359
13652
  shouldFallbackFromTurnStreamError(error) {
13360
13653
  if (this.isTurnStreamConnectionError(error)) {
13361
- return false;
13654
+ return true;
13362
13655
  }
13363
13656
  if (this.isTurnStreamStartTimeout(error)) {
13364
13657
  return true;
@@ -13503,10 +13796,9 @@ class PageBuilderAgenticAuthoringTurnFlow {
13503
13796
  const quickReplies = result.quickReplies?.length
13504
13797
  ? this.toShellQuickReplies(result.quickReplies)
13505
13798
  : this.toResourceCandidateQuickReplies(result.candidates, result.artifactKind);
13506
- const assistantMessage = result.assistantMessage?.trim()
13507
- || (quickReplies.length
13508
- ? this.context.tx('agentic.resourceDiscovery.found', 'I found APIs that can feed this screen. Choose one before generating the preview.')
13509
- : 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.');
13510
13802
  const intentResult = await this.resolveIntentAfterResourceDiscovery(request, request.pendingClarification?.sourcePrompt || prompt, contextHints, result, assistantMessage, quickReplies);
13511
13803
  if (intentResult) {
13512
13804
  return intentResult;
@@ -13553,12 +13845,16 @@ class PageBuilderAgenticAuthoringTurnFlow {
13553
13845
  ...authoringContext,
13554
13846
  contextHints: this.resourceDiscoveryContextHints(contextHints, result),
13555
13847
  })));
13556
- const assistantMessage = this.resolveIntentAssistantMessage(intentResolution)
13848
+ const resolvedAssistantMessage = this.resolveIntentAssistantMessage(intentResolution)
13557
13849
  || this.resolveIntentClarification(intentResolution)
13558
13850
  || fallbackAssistantMessage;
13559
13851
  const quickReplies = intentResolution.quickReplies?.length
13560
13852
  ? this.toShellQuickReplies(intentResolution.quickReplies)
13561
13853
  : fallbackQuickReplies;
13854
+ const assistantMessage = quickReplies.some((reply) => this.isResourceQuickReply(reply))
13855
+ && this.isGenericResourceDiscoveryMessage(resolvedAssistantMessage)
13856
+ ? fallbackAssistantMessage
13857
+ : resolvedAssistantMessage;
13562
13858
  const explicitPendingClarification = this.toShellPendingClarification(intentResolution.pendingClarification);
13563
13859
  const routeRequiredClarification = this.resolveSharedRuleRouteClarification(intentResolution, this.resolveEffectivePrompt(intentResolution, prompt), request.clientTurnId);
13564
13860
  const pendingClarification = explicitPendingClarification
@@ -13621,6 +13917,37 @@ class PageBuilderAgenticAuthoringTurnFlow {
13621
13917
  const contextHints = this.toJsonObject(request.action?.contextHints);
13622
13918
  return this.readString(contextHints, 'tool') === 'searchApiResources';
13623
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
+ }
13624
13951
  toResourceCandidateQuickReplies(candidates, artifactKind) {
13625
13952
  return candidates
13626
13953
  .filter((candidate) => !!candidate.resourcePath?.trim())
@@ -13680,20 +14007,184 @@ class PageBuilderAgenticAuthoringTurnFlow {
13680
14007
  const message = intentResolution.assistantMessage?.trim();
13681
14008
  return message || null;
13682
14009
  }
13683
- isExecutableIntent(intentResolution) {
14010
+ isExecutableIntent(intentResolution, request) {
13684
14011
  const operationKind = intentResolution.operationKind;
13685
14012
  const artifactKind = intentResolution.artifactKind;
13686
14013
  const allowsMaterializedArtifactOperation = operationKind === 'create'
13687
14014
  || operationKind === 'modify'
13688
14015
  || operationKind === 'remove';
13689
14016
  return !!intentResolution.valid
13690
- && intentResolution.gate?.status === 'eligible'
13691
- && !!intentResolution.selectedCandidate
13692
- && ((allowsMaterializedArtifactOperation
13693
- && (artifactKind === 'form'
13694
- || artifactKind === 'dashboard'
13695
- || artifactKind === 'table'))
13696
- || this.isExecutablePageCompositionIntent(intentResolution));
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
+ };
13697
14188
  }
13698
14189
  shouldAutoGenerateGuidedPreview(intentResolution, quickReplies, prompt) {
13699
14190
  if (!this.isGuidedPreviewIntent(intentResolution)) {
@@ -13705,16 +14196,74 @@ class PageBuilderAgenticAuthoringTurnFlow {
13705
14196
  return this.isExplicitPreviewCreationPrompt(prompt);
13706
14197
  }
13707
14198
  isGuidedPreviewIntent(intentResolution) {
13708
- if (!intentResolution.valid || intentResolution.gate?.status !== 'eligible' || !intentResolution.selectedCandidate) {
14199
+ if (!intentResolution.valid || intentResolution.gate?.status !== 'eligible') {
13709
14200
  return false;
13710
14201
  }
13711
14202
  if (this.isExecutableIntent(intentResolution)) {
13712
14203
  return true;
13713
14204
  }
14205
+ if (!intentResolution.selectedCandidate) {
14206
+ return false;
14207
+ }
13714
14208
  const artifactKind = intentResolution.artifactKind;
13715
14209
  return (artifactKind === 'dashboard' || artifactKind === 'page' || artifactKind === 'table' || artifactKind === 'form')
13716
14210
  && (intentResolution.operationKind === 'compose' || intentResolution.operationKind === 'explore');
13717
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
+ }
13718
14267
  isExplicitPreviewCreationPrompt(prompt) {
13719
14268
  const normalized = prompt
13720
14269
  .normalize('NFD')
@@ -13759,9 +14308,19 @@ class PageBuilderAgenticAuthoringTurnFlow {
13759
14308
  return action && artifact;
13760
14309
  }
13761
14310
  isExecutablePageCompositionIntent(intentResolution) {
13762
- return intentResolution.artifactKind === 'page'
13763
- && intentResolution.operationKind === 'compose'
13764
- && intentResolution.authoringProfile === 'ui-composition-plan@0.1.0';
14311
+ if (intentResolution.artifactKind !== 'page') {
14312
+ return false;
14313
+ }
14314
+ if ((intentResolution.operationKind === 'compose' || intentResolution.operationKind === 'modify')
14315
+ && intentResolution.authoringProfile === 'ui-composition-plan@0.1.0') {
14316
+ return true;
14317
+ }
14318
+ if (intentResolution.operationKind !== 'create') {
14319
+ return false;
14320
+ }
14321
+ return intentResolution.changeKind === 'create_master_detail'
14322
+ || intentResolution.changeKind === 'create_tabbed_master_detail_form'
14323
+ || intentResolution.changeKind === 'create_artifact';
13765
14324
  }
13766
14325
  resolveIntentClarification(intentResolution) {
13767
14326
  const questions = this.readIntentResolutionStringList(intentResolution?.clarificationQuestions);
@@ -13809,7 +14368,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
13809
14368
  toShellQuickReplies(quickReplies) {
13810
14369
  return quickReplies
13811
14370
  .filter((reply) => !!reply.id && !!reply.label && (!!reply.prompt || reply.kind === 'cancel'))
13812
- .map((reply) => ({
14371
+ .map((reply) => this.enrichShellQuickReply({
13813
14372
  id: reply.id,
13814
14373
  kind: reply.kind,
13815
14374
  label: reply.label,
@@ -13817,9 +14376,334 @@ class PageBuilderAgenticAuthoringTurnFlow {
13817
14376
  description: reply.description,
13818
14377
  icon: reply.icon,
13819
14378
  tone: reply.tone,
14379
+ presentation: null,
13820
14380
  contextHints: this.toJsonObject(reply.contextHints),
13821
14381
  }));
13822
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
+ }
13823
14707
  buildPendingClarificationForNextTurn(request, sourcePrompt, clarification) {
13824
14708
  return this.buildPendingClarification(sourcePrompt, clarification, request.clientTurnId);
13825
14709
  }
@@ -13894,7 +14778,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
13894
14778
  targetApp: this.context.targetApp,
13895
14779
  targetComponentId: this.context.targetComponentId,
13896
14780
  currentPage: this.context.currentPage(),
13897
- selectedWidgetKey,
14781
+ selectedWidgetKey: this.resolveSelectedWidgetKey(selectedWidgetKey, authoringContext.contextHints),
13898
14782
  provider: this.context.provider(),
13899
14783
  model: this.context.model(),
13900
14784
  apiKey: this.context.apiKey(),
@@ -13902,6 +14786,12 @@ class PageBuilderAgenticAuthoringTurnFlow {
13902
14786
  ...authoringContext,
13903
14787
  };
13904
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
+ }
13905
14795
  buildContextHints(request) {
13906
14796
  const base = this.toJsonObject(request.action?.contextHints)
13907
14797
  ?? this.toJsonObject(request.contextHints);
@@ -14094,6 +14984,7 @@ function projectKnowledgeTarget(changeSet, conceptKey) {
14094
14984
  };
14095
14985
  }
14096
14986
 
14987
+ const AGENTIC_PAGE_COMPOSITION_REQUEST_OUTPUT = 'agenticPageCompositionRequested';
14097
14988
  class DynamicPageBuilderComponent {
14098
14989
  dialog;
14099
14990
  settingsPanel;
@@ -14129,6 +15020,7 @@ class DynamicPageBuilderComponent {
14129
15020
  pageLifecycleBusy = false;
14130
15021
  pageLifecycleResetRevision = null;
14131
15022
  pageChange = new EventEmitter();
15023
+ pageSaveRequested = new EventEmitter();
14132
15024
  agenticAuthoringApplied = new EventEmitter();
14133
15025
  agenticAuthoringSharedRuleHandoff = new EventEmitter();
14134
15026
  pageRestart = new EventEmitter();
@@ -14142,6 +15034,8 @@ class DynamicPageBuilderComponent {
14142
15034
  agenticAuthoringStatus = signal('', ...(ngDevMode ? [{ debugName: "agenticAuthoringStatus" }] : []));
14143
15035
  agenticAuthoringError = signal('', ...(ngDevMode ? [{ debugName: "agenticAuthoringError" }] : []));
14144
15036
  agenticAuthoringPreviewResult = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringPreviewResult" }] : []));
15037
+ agenticAuthoringSemanticDecision = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringSemanticDecision" }] : []));
15038
+ agenticAuthoringCanApply = signal(false, ...(ngDevMode ? [{ debugName: "agenticAuthoringCanApply" }] : []));
14145
15039
  agenticAuthoringLastEtag = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringLastEtag" }] : []));
14146
15040
  agenticAuthoringConversation = signal([], ...(ngDevMode ? [{ debugName: "agenticAuthoringConversation" }] : []));
14147
15041
  agenticAuthoringQuickReplies = signal([], ...(ngDevMode ? [{ debugName: "agenticAuthoringQuickReplies" }] : []));
@@ -14167,17 +15061,18 @@ class DynamicPageBuilderComponent {
14167
15061
  agenticAuthoringEditingMessageId = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringEditingMessageId" }] : []));
14168
15062
  selectedWidgetKey = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetKey" }] : []));
14169
15063
  agenticAuthoringWidgetContextKey = signal(null, ...(ngDevMode ? [{ debugName: "agenticAuthoringWidgetContextKey" }] : []));
14170
- agenticAuthoringPanelLayout = signal({
14171
- left: 16,
14172
- top: 16,
15064
+ agenticAuthoringPanelLayout = signal(createPraxisAssistantViewportLayout({
14173
15065
  width: 440,
14174
- height: 560,
14175
- }, ...(ngDevMode ? [{ debugName: "agenticAuthoringPanelLayout" }] : []));
15066
+ height: 620,
15067
+ top: 96,
15068
+ margin: 24,
15069
+ }), ...(ngDevMode ? [{ debugName: "agenticAuthoringPanelLayout" }] : []));
14176
15070
  previewMode = false;
14177
15071
  agenticComponentCapabilities;
14178
15072
  agenticComponentCapabilitiesPromise;
14179
15073
  agenticTurnController;
14180
15074
  sharedRuleHandoffRevision = 0;
15075
+ agenticAuthoringPanelLayoutTouched = false;
14181
15076
  constructor(dialog, settingsPanel) {
14182
15077
  this.dialog = dialog;
14183
15078
  this.settingsPanel = settingsPanel;
@@ -14206,6 +15101,24 @@ class DynamicPageBuilderComponent {
14206
15101
  this.clearSelectedWidgetIfMissing(cloned);
14207
15102
  this.pageChange.emit(cloned);
14208
15103
  }
15104
+ onRuntimeWidgetEvent(event) {
15105
+ if (event.output !== AGENTIC_PAGE_COMPOSITION_REQUEST_OUTPUT) {
15106
+ return;
15107
+ }
15108
+ const payload = this.toRecord(event.payload);
15109
+ const prompt = typeof payload?.['prompt'] === 'string' ? payload['prompt'].trim() : '';
15110
+ if (!prompt) {
15111
+ return;
15112
+ }
15113
+ const ownerWidgetKey = typeof event.ownerWidgetKey === 'string' ? event.ownerWidgetKey.trim() : '';
15114
+ if (ownerWidgetKey && this.resolveWidgetByKey(ownerWidgetKey)) {
15115
+ this.selectedWidgetKey.set(ownerWidgetKey);
15116
+ this.agenticAuthoringWidgetContextKey.set(ownerWidgetKey);
15117
+ }
15118
+ this.agenticAuthoringPrompt.set(prompt);
15119
+ this.openAgenticAuthoring();
15120
+ void this.previewAgenticAuthoring();
15121
+ }
14209
15122
  onConnectionEditorPageChange(next) {
14210
15123
  const cloned = this.clonePage(next);
14211
15124
  this.currentPage.set(cloned);
@@ -14214,7 +15127,7 @@ class DynamicPageBuilderComponent {
14214
15127
  }
14215
15128
  onRuntimeWidgetSelectionChange(widgetKey) {
14216
15129
  this.selectedWidgetKey.set(widgetKey);
14217
- if (this.agenticAuthoringWidgetContextKey()) {
15130
+ if (widgetKey && this.agenticAuthoringWidgetContextKey()) {
14218
15131
  this.agenticAuthoringWidgetContextKey.set(widgetKey);
14219
15132
  }
14220
15133
  }
@@ -14257,7 +15170,7 @@ class DynamicPageBuilderComponent {
14257
15170
  const type = resolved.componentId;
14258
15171
  const next = this.clonePage(this.currentPage());
14259
15172
  const key = `${type}-${generateId()}`;
14260
- const inputs = this.defaultInputsFor(type, resolved.inputs);
15173
+ const inputs = this.defaultInputsFor(type, resolved.inputs, key);
14261
15174
  const widgets = [...(next.widgets || []), { key, definition: { id: type, inputs } }];
14262
15175
  next.widgets = widgets;
14263
15176
  if (next.canvas) {
@@ -14284,9 +15197,11 @@ class DynamicPageBuilderComponent {
14284
15197
  this.runtime?.openPageSettings();
14285
15198
  }
14286
15199
  saveCurrentPage() {
14287
- const cloned = this.clonePage(this.currentPage());
15200
+ const runtimeSnapshot = this.runtime?.getPageSnapshot();
15201
+ const cloned = this.clonePage(runtimeSnapshot || this.currentPage());
14288
15202
  this.currentPage.set(cloned);
14289
15203
  this.pageChange.emit(cloned);
15204
+ this.pageSaveRequested.emit(this.clonePage(cloned));
14290
15205
  }
14291
15206
  applyConfigFromAdapter(config) {
14292
15207
  if (!config.page)
@@ -14338,6 +15253,17 @@ class DynamicPageBuilderComponent {
14338
15253
  this.agenticAuthoringError.set('');
14339
15254
  this.syncAgenticAuthoringSession('minimized');
14340
15255
  }
15256
+ onAgenticAuthoringLayoutChange(layout) {
15257
+ this.agenticAuthoringPanelLayoutTouched = true;
15258
+ this.agenticAuthoringPanelLayout.set(layout);
15259
+ }
15260
+ agenticAuthoringReviewRailActive() {
15261
+ return this.showSettings()
15262
+ && this.enableAgenticAuthoring
15263
+ && this.agenticAuthoringOpen()
15264
+ && !!this.agenticAuthoringPreviewResult()?.valid
15265
+ && !this.agenticAuthoringPanelLayoutTouched;
15266
+ }
14341
15267
  showAgenticAuthoringDock() {
14342
15268
  return this.showSettings()
14343
15269
  && this.enableAgenticAuthoring
@@ -14366,7 +15292,7 @@ class DynamicPageBuilderComponent {
14366
15292
  if (this.resolveSelectedWidgetKey()) {
14367
15293
  return this.tx('agentic.header.title.widget', 'Praxis widget copilot');
14368
15294
  }
14369
- return this.tx('agentic.header.title.page', 'Praxis page copilot');
15295
+ return this.tx('agentic.header.title.page', 'Praxis page decision copilot');
14370
15296
  }
14371
15297
  agenticAuthoringHeaderSubtitle() {
14372
15298
  const selectedWidgetLabel = this.resolveSelectedWidgetLabel();
@@ -14374,6 +15300,9 @@ class DynamicPageBuilderComponent {
14374
15300
  return this.tx('agentic.header.subtitle.governed', 'Continue the governed semantic-decision flow.');
14375
15301
  }
14376
15302
  if (this.agenticAuthoringPreviewResult()?.valid) {
15303
+ if (!this.agenticAuthoringCanApply()) {
15304
+ return this.tx('agentic.header.subtitle.reviewBlocked', 'Preview ready for governed review.');
15305
+ }
14377
15306
  return this.tx('agentic.header.subtitle.review', 'Preview ready for review and persistence.');
14378
15307
  }
14379
15308
  if (selectedWidgetLabel) {
@@ -14385,7 +15314,7 @@ class DynamicPageBuilderComponent {
14385
15314
  return this.tx('agentic.header.subtitle.route', 'Authoring page route {route}.')
14386
15315
  .replace('{route}', routePath);
14387
15316
  }
14388
- return this.tx('agentic.header.subtitle.page', 'Author page-level layout, widgets and governed materialization.');
15317
+ return this.tx('agentic.header.subtitle.page', 'Turn intent into layout, widgets, and governed materializations.');
14389
15318
  }
14390
15319
  agenticAuthoringHeaderModeLabel() {
14391
15320
  if (this.agenticAuthoringSharedRuleHandoffState()) {
@@ -14403,7 +15332,7 @@ class DynamicPageBuilderComponent {
14403
15332
  close: this.tx('agentic.minimize', 'Minimize'),
14404
15333
  prompt: this.tx('agentic.promptLabel', 'Message'),
14405
15334
  promptPlaceholder: this.tx('agentic.promptPlaceholder', 'Describe the page, dashboard, form or change you need.'),
14406
- emptyConversation: this.tx('agentic.emptyConversation', 'Tell me what you want to create or change. I will ask follow-up questions before applying the preview.'),
15335
+ emptyConversation: this.agenticAuthoringEmptyConversationMessage(),
14407
15336
  submit: this.tx('agentic.preview', 'Generate preview'),
14408
15337
  apply: this.tx('agentic.persist', 'Save'),
14409
15338
  conversationAria: this.tx('agentic.conversationAria', 'AI conversation'),
@@ -14422,7 +15351,7 @@ class DynamicPageBuilderComponent {
14422
15351
  modeDiagnostic: this.tx('agentic.mode.diagnostic', 'Diagnostic'),
14423
15352
  modeReview: this.tx('agentic.mode.review', 'Review'),
14424
15353
  modeInlineHelp: this.tx('agentic.mode.inlineHelp', 'Help'),
14425
- stateIdle: this.tx('agentic.state.idle', 'Idle'),
15354
+ stateIdle: this.tx('agentic.state.idle', 'Ready'),
14426
15355
  stateListening: this.tx('agentic.state.listening', 'Ready'),
14427
15356
  stateProcessing: this.tx('agentic.state.processing', 'Processing'),
14428
15357
  stateClarification: this.tx('agentic.state.clarification', 'Waiting for input'),
@@ -14432,6 +15361,39 @@ class DynamicPageBuilderComponent {
14432
15361
  stateError: this.tx('agentic.state.error', 'Error'),
14433
15362
  };
14434
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
+ }
14435
15397
  agenticAuthoringSubmitAction() {
14436
15398
  const label = this.tx('agentic.preview', 'Generate preview');
14437
15399
  return {
@@ -14522,6 +15484,8 @@ class DynamicPageBuilderComponent {
14522
15484
  this.agenticAuthoringStatus.set('');
14523
15485
  this.agenticAuthoringError.set('');
14524
15486
  this.agenticAuthoringPreviewResult.set(null);
15487
+ this.agenticAuthoringSemanticDecision.set(null);
15488
+ this.agenticAuthoringCanApply.set(false);
14525
15489
  this.agenticAuthoringConversation.set([]);
14526
15490
  this.agenticAuthoringQuickReplies.set([]);
14527
15491
  this.agenticAuthoringAttachments.set([]);
@@ -14767,6 +15731,7 @@ class DynamicPageBuilderComponent {
14767
15731
  });
14768
15732
  }
14769
15733
  }
15734
+ items.push(...this.agenticAuthoringSemanticDecisionContextItems());
14770
15735
  const handoff = this.agenticAuthoringSharedRuleHandoffState();
14771
15736
  if (handoff) {
14772
15737
  items.push({
@@ -14858,6 +15823,138 @@ class DynamicPageBuilderComponent {
14858
15823
  }
14859
15824
  return items;
14860
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
+ }
14861
15958
  async previewAgenticAuthoring() {
14862
15959
  const prompt = this.agenticAuthoringPrompt().trim();
14863
15960
  if (!prompt || this.agenticAuthoringBusy())
@@ -14865,6 +15962,7 @@ class DynamicPageBuilderComponent {
14865
15962
  this.agenticAuthoringBusy.set(true);
14866
15963
  this.agenticAuthoringError.set('');
14867
15964
  this.agenticAuthoringPreviewResult.set(null);
15965
+ this.agenticAuthoringCanApply.set(false);
14868
15966
  this.agenticAuthoringSharedRuleHandoffState.set(null);
14869
15967
  this.clearSharedRuleCockpitState();
14870
15968
  this.clearProjectKnowledgeCockpitState();
@@ -14876,6 +15974,7 @@ class DynamicPageBuilderComponent {
14876
15974
  ? controller.submitEditedMessage(editingMessageId, prompt)
14877
15975
  : controller.submitPrompt(prompt));
14878
15976
  this.agenticAuthoringEditingMessageId.set(null);
15977
+ this.agenticAuthoringPrompt.set('');
14879
15978
  }
14880
15979
  catch (error) {
14881
15980
  this.agenticAuthoringStatus.set('');
@@ -14912,6 +16011,7 @@ class DynamicPageBuilderComponent {
14912
16011
  this.agenticAuthoringBusy.set(true);
14913
16012
  this.agenticAuthoringError.set('');
14914
16013
  this.agenticAuthoringPreviewResult.set(null);
16014
+ this.agenticAuthoringCanApply.set(false);
14915
16015
  this.agenticAuthoringSharedRuleHandoffState.set(null);
14916
16016
  this.clearSharedRuleCockpitState();
14917
16017
  this.clearProjectKnowledgeCockpitState();
@@ -14929,6 +16029,7 @@ class DynamicPageBuilderComponent {
14929
16029
  displayPrompt: visiblePrompt,
14930
16030
  contextHints,
14931
16031
  }));
16032
+ this.agenticAuthoringPrompt.set('');
14932
16033
  }
14933
16034
  catch (error) {
14934
16035
  this.agenticAuthoringStatus.set('');
@@ -14975,9 +16076,10 @@ class DynamicPageBuilderComponent {
14975
16076
  if (this.isGenericDataSourceQuickReplyPrompt(prompt) && this.isConfirmationQuickReply(reply)) {
14976
16077
  return this.agenticQuickReplyGovernedConfirmationPrompt(contextHints, visiblePrompt);
14977
16078
  }
14978
- return this.isHumanSafeResourceQuickReplyPrompt(prompt, contextHints)
14979
- ? prompt
14980
- : visiblePrompt;
16079
+ if (this.isHumanSafeResourceQuickReplyPrompt(prompt, contextHints)) {
16080
+ return prompt;
16081
+ }
16082
+ return this.agenticQuickReplyClarificationConfirmationPrompt(pendingClarification, visiblePrompt);
14981
16083
  }
14982
16084
  agenticQuickReplyClarificationConfirmationPrompt(pendingClarification, confirmationText) {
14983
16085
  const sourcePrompt = (pendingClarification?.sourcePrompt || '').trim();
@@ -15031,9 +16133,25 @@ class DynamicPageBuilderComponent {
15031
16133
  return visiblePrompt;
15032
16134
  }
15033
16135
  isResourceQuickReply(reply, contextHints) {
16136
+ if (this.isContextualPreviewActionQuickReply(reply, contextHints)) {
16137
+ return false;
16138
+ }
15034
16139
  return this.hasResourceContextHint(contextHints)
15035
16140
  && !['cancel', 'revise'].includes((reply.kind || '').trim().toLowerCase());
15036
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
+ }
15037
16155
  isGovernedConfirmationQuickReply(reply, contextHints) {
15038
16156
  return this.isConfirmationQuickReply(reply)
15039
16157
  && this.hasResourceContextHint(contextHints);
@@ -15101,6 +16219,7 @@ class DynamicPageBuilderComponent {
15101
16219
  this.agenticAuthoringStatus.set(this.tx('agentic.status.resolvingIntent', 'Resolving intent...'));
15102
16220
  this.agenticAuthoringError.set('');
15103
16221
  this.agenticAuthoringPreviewResult.set(null);
16222
+ this.agenticAuthoringCanApply.set(false);
15104
16223
  this.clearProjectKnowledgeCockpitState();
15105
16224
  try {
15106
16225
  await this.consumeAgenticTurn(this.ensureAgenticTurnController().resendMessage(message.id));
@@ -15141,6 +16260,8 @@ class DynamicPageBuilderComponent {
15141
16260
  this.agenticAuthoringEditingMessageId.set(null);
15142
16261
  this.agenticAuthoringPrompt.set('');
15143
16262
  this.agenticAuthoringPreviewResult.set(null);
16263
+ this.agenticAuthoringSemanticDecision.set(null);
16264
+ this.agenticAuthoringCanApply.set(false);
15144
16265
  this.agenticAuthoringSharedRuleHandoffState.set(null);
15145
16266
  this.clearSharedRuleCockpitState();
15146
16267
  this.clearProjectKnowledgeCockpitState();
@@ -15148,7 +16269,7 @@ class DynamicPageBuilderComponent {
15148
16269
  }
15149
16270
  async persistAgenticAuthoring() {
15150
16271
  const preview = this.agenticAuthoringPreviewResult();
15151
- if (!preview || this.agenticAuthoringBusy())
16272
+ if (!preview || !this.agenticAuthoringCanApply() || this.agenticAuthoringBusy())
15152
16273
  return;
15153
16274
  const componentId = this.resolveAgenticComponentId();
15154
16275
  if (!componentId) {
@@ -15168,10 +16289,17 @@ class DynamicPageBuilderComponent {
15168
16289
  tags: {
15169
16290
  source: 'page-builder-agentic-authoring',
15170
16291
  },
16292
+ semanticDecision: this.agenticAuthoringSemanticDecision(),
15171
16293
  }));
15172
16294
  this.agenticAuthoringLastEtag.set(result.etag ?? null);
15173
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('');
15174
16301
  this.agenticAuthoringStatus.set(this.tx('agentic.status.saved', 'Page saved.'));
16302
+ this.syncAgenticAuthoringSession();
15175
16303
  }
15176
16304
  catch (error) {
15177
16305
  this.agenticAuthoringStatus.set('');
@@ -15733,6 +16861,7 @@ class DynamicPageBuilderComponent {
15733
16861
  this.agenticAuthoringStatus.set(this.tx('agentic.status.sharedRuleTargetSelected', 'Shared-rule target selected. Continue by creating the governed definition.'));
15734
16862
  this.agenticAuthoringError.set('');
15735
16863
  this.agenticAuthoringPreviewResult.set(null);
16864
+ this.agenticAuthoringCanApply.set(false);
15736
16865
  this.agenticAuthoringSharedRuleHandoffState.set(next);
15737
16866
  this.agenticAuthoringSharedRuleHandoff.emit(next);
15738
16867
  this.appendAgenticMessage('user', visiblePrompt);
@@ -15999,12 +17128,15 @@ class DynamicPageBuilderComponent {
15999
17128
  const handoff = this.resolveAgenticSharedRuleHandoff(state);
16000
17129
  const previousHandoff = this.agenticAuthoringSharedRuleHandoffState();
16001
17130
  this.agenticAuthoringConversation.set(state.messages);
16002
- this.agenticAuthoringQuickReplies.set(preview?.valid ? [] : state.quickReplies);
17131
+ this.agenticAuthoringQuickReplies.set(state.quickReplies);
16003
17132
  this.agenticAuthoringStatus.set(handoff && !preview?.valid
16004
17133
  ? this.tx('agentic.status.sharedRuleHandoff', 'Continue this request in the shared-rules flow.')
16005
17134
  : state.statusText);
16006
17135
  this.agenticAuthoringError.set(state.errorText);
16007
17136
  this.agenticAuthoringPreviewResult.set(preview);
17137
+ this.agenticAuthoringSemanticDecision.set(this.resolveAgenticSemanticDecision(state.diagnostics));
17138
+ this.agenticAuthoringCanApply.set(!!preview?.valid && !!state.canApply);
17139
+ this.moveAgenticAuthoringPanelToReviewSidecar(preview);
16008
17140
  this.agenticAuthoringAttachments.set(state.attachments);
16009
17141
  if (!this.sameSharedRuleHandoffIdentity(previousHandoff, handoff)) {
16010
17142
  this.clearSharedRuleCockpitState();
@@ -16053,6 +17185,17 @@ class DynamicPageBuilderComponent {
16053
17185
  this.agenticAuthoringSharedRuleHandoff.emit(resolved);
16054
17186
  }
16055
17187
  }
17188
+ moveAgenticAuthoringPanelToReviewSidecar(preview) {
17189
+ if (!preview?.valid || this.agenticAuthoringPanelLayoutTouched) {
17190
+ return;
17191
+ }
17192
+ this.agenticAuthoringPanelLayout.set(createPraxisAssistantViewportLayout({
17193
+ width: 440,
17194
+ height: 620,
17195
+ top: 96,
17196
+ margin: 24,
17197
+ }));
17198
+ }
16056
17199
  resolveAgenticSharedRuleHandoff(state) {
16057
17200
  const diagnostics = this.toRecord(state.diagnostics);
16058
17201
  const intentResolution = this.toRecord(diagnostics?.['intentResolution']);
@@ -16190,7 +17333,14 @@ class DynamicPageBuilderComponent {
16190
17333
  return Object.keys(merged).length ? merged : undefined;
16191
17334
  }
16192
17335
  consumeAgenticTurn(states$) {
16193
- return lastValueFrom(states$.pipe(concatMap((state) => from(this.applyAgenticTurnState(state)).pipe(map(() => state)))));
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';
16194
17344
  }
16195
17345
  agenticAuthoringDiagnosticsTop() {
16196
17346
  return Math.max(16, this.agenticAuthoringPanelLayout().top);
@@ -16209,6 +17359,11 @@ class DynamicPageBuilderComponent {
16209
17359
  const intentResolution = this.toRecord(diagnostics?.['intentResolution']);
16210
17360
  return this.toRecord(intentResolution?.['llmDiagnostics']);
16211
17361
  }
17362
+ resolveAgenticSemanticDecision(diagnostics) {
17363
+ const intentResolution = this.toRecord(diagnostics?.['intentResolution']);
17364
+ const semanticDecision = this.toRecord(intentResolution?.['semanticDecision']);
17365
+ return semanticDecision ? semanticDecision : null;
17366
+ }
16212
17367
  cloneAgenticContextHints(contextHints) {
16213
17368
  if (!contextHints || typeof contextHints !== 'object' || Array.isArray(contextHints)) {
16214
17369
  return undefined;
@@ -16254,8 +17409,10 @@ class DynamicPageBuilderComponent {
16254
17409
  }
16255
17410
  resolvePreviewCompiledFormPatch(preview) {
16256
17411
  if (preview.uiCompositionPlan || preview.compiledFormPatch?.patch?.page) {
17412
+ const planDiagnostics = this.toRecord(this.toRecord(preview.uiCompositionPlan)?.['diagnostics']);
16257
17413
  return {
16258
17414
  ...preview.compiledFormPatch,
17415
+ diagnostics: planDiagnostics ?? preview.compiledFormPatch?.['diagnostics'],
16259
17416
  patch: {
16260
17417
  ...(preview.compiledFormPatch?.patch ?? {}),
16261
17418
  page: this.clonePage(this.currentPage()),
@@ -16283,7 +17440,7 @@ class DynamicPageBuilderComponent {
16283
17440
  return this.clonePage(input);
16284
17441
  }
16285
17442
  clonePage(page) {
16286
- return JSON.parse(JSON.stringify(page));
17443
+ return normalizePageBuilderRuntimePage(JSON.parse(JSON.stringify(page)));
16287
17444
  }
16288
17445
  clearSelectedWidgetIfMissing(page) {
16289
17446
  const selected = this.selectedWidgetKey();
@@ -16295,7 +17452,7 @@ class DynamicPageBuilderComponent {
16295
17452
  this.agenticAuthoringWidgetContextKey.set(null);
16296
17453
  }
16297
17454
  }
16298
- defaultInputsFor(type, presetInputs) {
17455
+ defaultInputsFor(type, presetInputs, widgetKey) {
16299
17456
  const metadata = this.componentMetadata.get(type);
16300
17457
  const inputs = {};
16301
17458
  for (const input of metadata?.inputs ?? []) {
@@ -16303,6 +17460,12 @@ class DynamicPageBuilderComponent {
16303
17460
  inputs[input.name] = this.cloneValue(input.default);
16304
17461
  }
16305
17462
  }
17463
+ if (metadata?.authoringManifestRef?.componentId
17464
+ && metadata.inputs?.some((input) => input.name === 'enableCustomization')
17465
+ && presetInputs?.['enableCustomization'] === undefined) {
17466
+ inputs['enableCustomization'] = true;
17467
+ }
17468
+ this.applyWidgetIdentityDefaults(metadata?.inputs, inputs, presetInputs, widgetKey);
16306
17469
  if (!presetInputs) {
16307
17470
  return inputs;
16308
17471
  }
@@ -16311,6 +17474,18 @@ class DynamicPageBuilderComponent {
16311
17474
  ...this.cloneValue(presetInputs),
16312
17475
  };
16313
17476
  }
17477
+ applyWidgetIdentityDefaults(metadataInputs, inputs, presetInputs, widgetKey) {
17478
+ if (!metadataInputs?.length || !widgetKey)
17479
+ return;
17480
+ const inputNames = new Set(metadataInputs.map((input) => input.name));
17481
+ for (const identityInput of ['componentInstanceId', 'tabsId', 'formId']) {
17482
+ if (inputNames.has(identityInput)
17483
+ && inputs[identityInput] === undefined
17484
+ && presetInputs?.[identityInput] === undefined) {
17485
+ inputs[identityInput] = widgetKey;
17486
+ }
17487
+ }
17488
+ }
16314
17489
  resolveAgenticComponentId() {
16315
17490
  const explicit = this.agenticAuthoringComponentId?.trim();
16316
17491
  if (explicit)
@@ -16321,9 +17496,9 @@ class DynamicPageBuilderComponent {
16321
17496
  return null;
16322
17497
  }
16323
17498
  resolveSelectedWidgetKey() {
16324
- const selected = this.agenticAuthoringWidgetContextKey();
16325
- if (selected && this.resolveWidgetByKey(selected)) {
16326
- return selected;
17499
+ const pinnedSelection = this.agenticAuthoringWidgetContextKey();
17500
+ if (pinnedSelection && this.resolveWidgetByKey(pinnedSelection)) {
17501
+ return pinnedSelection;
16327
17502
  }
16328
17503
  return null;
16329
17504
  }
@@ -16435,17 +17610,20 @@ class DynamicPageBuilderComponent {
16435
17610
  return resolvePraxisPageBuilderText(this.i18n, key, fallback);
16436
17611
  }
16437
17612
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageBuilderComponent, deps: [{ token: i1.MatDialog }, { token: SETTINGS_PANEL_BRIDGE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
16438
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringContextHints: "agenticAuthoringContextHints", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { pageChange: "pageChange", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
17613
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: DynamicPageBuilderComponent, isStandalone: true, selector: "praxis-dynamic-page-builder", inputs: { page: "page", context: "context", strictValidation: "strictValidation", autoPersist: "autoPersist", enableCustomization: "enableCustomization", showSettingsButton: "showSettingsButton", pageIdentity: "pageIdentity", componentInstanceId: "componentInstanceId", pageEditorComponent: "pageEditorComponent", enableAgenticAuthoring: "enableAgenticAuthoring", agenticAuthoringProvider: "agenticAuthoringProvider", agenticAuthoringModel: "agenticAuthoringModel", agenticAuthoringApiKey: "agenticAuthoringApiKey", agenticAuthoringComponentId: "agenticAuthoringComponentId", agenticAuthoringScope: "agenticAuthoringScope", agenticAuthoringEtag: "agenticAuthoringEtag", agenticAuthoringIncludeLlmDiagnostics: "agenticAuthoringIncludeLlmDiagnostics", agenticAuthoringEnableStreaming: "agenticAuthoringEnableStreaming", agenticAuthoringContextHints: "agenticAuthoringContextHints", showPageLifecycleActions: "showPageLifecycleActions", canDeleteSavedPage: "canDeleteSavedPage", pageLifecycleBusy: "pageLifecycleBusy", pageLifecycleResetRevision: "pageLifecycleResetRevision" }, outputs: { pageChange: "pageChange", pageSaveRequested: "pageSaveRequested", agenticAuthoringApplied: "agenticAuthoringApplied", agenticAuthoringSharedRuleHandoff: "agenticAuthoringSharedRuleHandoff", pageRestart: "pageRestart", savedPageDeleteRequested: "savedPageDeleteRequested" }, providers: [
16439
17614
  providePraxisPageBuilderI18n(),
16440
17615
  { provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
16441
17616
  ], viewQueries: [{ propertyName: "runtime", first: true, predicate: ["runtime"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
16442
- <div class="builder-shell">
17617
+ <div
17618
+ class="builder-shell"
17619
+ [class.builder-shell--agentic-review-rail]="agenticAuthoringReviewRailActive()"
17620
+ >
16443
17621
  <praxis-dynamic-page
16444
17622
  #runtime
16445
17623
  [page]="currentPage()"
16446
17624
  [context]="context"
16447
17625
  [strictValidation]="strictValidation"
16448
- [autoPersist]="autoPersist"
17626
+ [autoPersist]="false"
16449
17627
  [enableCustomization]="showSettings()"
16450
17628
  [showPageSettingsButton]="false"
16451
17629
  [pageIdentity]="pageIdentity"
@@ -16453,6 +17631,7 @@ class DynamicPageBuilderComponent {
16453
17631
  [pageEditorComponent]="pageEditorComponent"
16454
17632
  [showWidgetAssistantButton]="enableAgenticAuthoring"
16455
17633
  (pageChange)="onRuntimePageChange($event)"
17634
+ (widgetEvent)="onRuntimeWidgetEvent($event)"
16456
17635
  (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
16457
17636
  (widgetAssistantRequested)="openAgenticAuthoringForWidget($event)"
16458
17637
  />
@@ -16482,7 +17661,7 @@ class DynamicPageBuilderComponent {
16482
17661
  [statusText]="agenticAuthoringStatus()"
16483
17662
  [errorText]="agenticAuthoringError()"
16484
17663
  [busy]="agenticAuthoringBusy()"
16485
- [canApply]="!!agenticAuthoringPreviewResult()?.valid"
17664
+ [canApply]="agenticAuthoringCanApply()"
16486
17665
  [primaryAction]="agenticAuthoringSubmitAction()"
16487
17666
  [showAttachAction]="false"
16488
17667
  [enablePastedAttachments]="false"
@@ -16500,7 +17679,7 @@ class DynamicPageBuilderComponent {
16500
17679
  (removeAttachment)="removeAgenticAttachment($event)"
16501
17680
  (editMessage)="editAgenticMessage($event)"
16502
17681
  (resendMessage)="resendAgenticMessage($event)"
16503
- (layoutChange)="agenticAuthoringPanelLayout.set($event)"
17682
+ (layoutChange)="onAgenticAuthoringLayoutChange($event)"
16504
17683
  (close)="minimizeAgenticAuthoring()"
16505
17684
  />
16506
17685
 
@@ -16778,7 +17957,7 @@ class DynamicPageBuilderComponent {
16778
17957
  [visible]="showSettings()"
16779
17958
  [canUndo]="false"
16780
17959
  [canRedo]="false"
16781
- [showSave]="autoPersist && hasPageWidgets()"
17960
+ [showSave]="hasPageWidgets()"
16782
17961
  [showPreview]="hasPageWidgets()"
16783
17962
  (add)="onAddComponent()"
16784
17963
  (settings)="openPageSettings()"
@@ -16841,7 +18020,7 @@ class DynamicPageBuilderComponent {
16841
18020
  </button>
16842
18021
  </praxis-floating-toolbar>
16843
18022
  </div>
16844
- `, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "layoutChange"] }] });
18023
+ `, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "layoutChange"] }] });
16845
18024
  }
16846
18025
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DynamicPageBuilderComponent, decorators: [{
16847
18026
  type: Component,
@@ -16859,13 +18038,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16859
18038
  providePraxisPageBuilderI18n(),
16860
18039
  { provide: DYNAMIC_PAGE_SHELL_EDITOR, useValue: WidgetShellEditorComponent },
16861
18040
  ], template: `
16862
- <div class="builder-shell">
18041
+ <div
18042
+ class="builder-shell"
18043
+ [class.builder-shell--agentic-review-rail]="agenticAuthoringReviewRailActive()"
18044
+ >
16863
18045
  <praxis-dynamic-page
16864
18046
  #runtime
16865
18047
  [page]="currentPage()"
16866
18048
  [context]="context"
16867
18049
  [strictValidation]="strictValidation"
16868
- [autoPersist]="autoPersist"
18050
+ [autoPersist]="false"
16869
18051
  [enableCustomization]="showSettings()"
16870
18052
  [showPageSettingsButton]="false"
16871
18053
  [pageIdentity]="pageIdentity"
@@ -16873,6 +18055,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16873
18055
  [pageEditorComponent]="pageEditorComponent"
16874
18056
  [showWidgetAssistantButton]="enableAgenticAuthoring"
16875
18057
  (pageChange)="onRuntimePageChange($event)"
18058
+ (widgetEvent)="onRuntimeWidgetEvent($event)"
16876
18059
  (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
16877
18060
  (widgetAssistantRequested)="openAgenticAuthoringForWidget($event)"
16878
18061
  />
@@ -16902,7 +18085,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16902
18085
  [statusText]="agenticAuthoringStatus()"
16903
18086
  [errorText]="agenticAuthoringError()"
16904
18087
  [busy]="agenticAuthoringBusy()"
16905
- [canApply]="!!agenticAuthoringPreviewResult()?.valid"
18088
+ [canApply]="agenticAuthoringCanApply()"
16906
18089
  [primaryAction]="agenticAuthoringSubmitAction()"
16907
18090
  [showAttachAction]="false"
16908
18091
  [enablePastedAttachments]="false"
@@ -16920,7 +18103,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
16920
18103
  (removeAttachment)="removeAgenticAttachment($event)"
16921
18104
  (editMessage)="editAgenticMessage($event)"
16922
18105
  (resendMessage)="resendAgenticMessage($event)"
16923
- (layoutChange)="agenticAuthoringPanelLayout.set($event)"
18106
+ (layoutChange)="onAgenticAuthoringLayoutChange($event)"
16924
18107
  (close)="minimizeAgenticAuthoring()"
16925
18108
  />
16926
18109
 
@@ -17198,7 +18381,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
17198
18381
  [visible]="showSettings()"
17199
18382
  [canUndo]="false"
17200
18383
  [canRedo]="false"
17201
- [showSave]="autoPersist && hasPageWidgets()"
18384
+ [showSave]="hasPageWidgets()"
17202
18385
  [showPreview]="hasPageWidgets()"
17203
18386
  (add)="onAddComponent()"
17204
18387
  (settings)="openPageSettings()"
@@ -17261,7 +18444,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
17261
18444
  </button>
17262
18445
  </praxis-floating-toolbar>
17263
18446
  </div>
17264
- `, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"] }]
18447
+ `, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:relative;z-index:140}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"] }]
17265
18448
  }], ctorParameters: () => [{ type: i1.MatDialog }, { type: undefined, decorators: [{
17266
18449
  type: Optional
17267
18450
  }, {
@@ -17318,6 +18501,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
17318
18501
  type: Input
17319
18502
  }], pageChange: [{
17320
18503
  type: Output
18504
+ }], pageSaveRequested: [{
18505
+ type: Output
17321
18506
  }], agenticAuthoringApplied: [{
17322
18507
  type: Output
17323
18508
  }], agenticAuthoringSharedRuleHandoff: [{