@praxisui/table 8.0.0-beta.82 → 8.0.0-beta.84

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.
@@ -34844,37 +34844,54 @@ class PraxisFilter {
34844
34844
  controlTypeToken === normalizeControlTypeToken(INLINE_SENTIMENT_CONTROL_TYPE);
34845
34845
  const isInlineColorLabelExplicit = controlType === INLINE_COLOR_LABEL_CONTROL_TYPE ||
34846
34846
  controlTypeToken === normalizeControlTypeToken(INLINE_COLOR_LABEL_CONTROL_TYPE);
34847
- const shouldUseInlineSearchableSelect = this.useInlineSearchableSelectVariant && isSearchableSelect;
34848
- const shouldUseInlineAsyncSelect = this.useInlineSearchableSelectVariant && (isAsyncSelect || (isSelect && hasRemoteOptions));
34849
- const shouldUseInlineAutocomplete = this.useInlineSearchableSelectVariant && isAutocomplete;
34847
+ const isMultipleSelection = meta?.multiple === true ||
34848
+ normalizeControlTypeToken(meta?.selectionMode || '') === 'multiple';
34849
+ const shouldUseInlineSearchableSelect = this.useInlineSearchableSelectVariant &&
34850
+ !isMultipleSelection &&
34851
+ isSearchableSelect;
34852
+ const shouldUseInlineAsyncSelect = this.useInlineSearchableSelectVariant &&
34853
+ !isMultipleSelection &&
34854
+ (isAsyncSelect || (isSelect && hasRemoteOptions));
34855
+ const shouldUseInlineAutocomplete = this.useInlineSearchableSelectVariant &&
34856
+ !isMultipleSelection &&
34857
+ isAutocomplete;
34850
34858
  const shouldUseInlineEntityLookup = isEntityLookup;
34851
34859
  const shouldUseInlineSelect = this.useInlineSelectVariant &&
34860
+ !isMultipleSelection &&
34852
34861
  isSelect &&
34853
34862
  !hasRemoteOptions;
34854
34863
  const shouldUseInlineMultiSelect = this.useInlineMultiSelectVariant &&
34855
34864
  (controlType === FieldControlType.MULTI_SELECT ||
34856
34865
  controlTypeToken === 'multiselect');
34857
34866
  const shouldUseInlineInput = this.useInlineInputVariant &&
34867
+ !isMultipleSelection &&
34858
34868
  (controlType === FieldControlType.INPUT ||
34859
34869
  controlType === FieldControlType.SEARCH_INPUT ||
34860
34870
  normalizedControlType === 'input' ||
34861
34871
  normalizedControlType === 'search' ||
34862
34872
  controlTypeToken === 'searchinput');
34863
- const shouldUseInlineNumber = this.useInlineInputVariant && isNumeric && !isCurrency && !isPriceRange;
34864
- const shouldUseInlineCurrency = this.useInlineInputVariant && isCurrency;
34865
- const shouldUseInlineCurrencyRange = this.useInlineRangeVariant && isPriceRange;
34873
+ const shouldUseInlineNumber = this.useInlineInputVariant &&
34874
+ !isMultipleSelection &&
34875
+ isNumeric &&
34876
+ !isCurrency &&
34877
+ !isPriceRange;
34878
+ const shouldUseInlineCurrency = this.useInlineInputVariant && !isMultipleSelection && isCurrency;
34879
+ const shouldUseInlineCurrencyRange = this.useInlineRangeVariant && !isMultipleSelection && isPriceRange;
34866
34880
  const shouldUseInlineRating = isInlineRatingExplicit;
34867
34881
  const shouldUseInlineDistanceRadius = isInlineDistanceRadiusExplicit;
34868
34882
  const shouldUseInlineToggle = this.useInlineToggleVariant &&
34883
+ !isMultipleSelection &&
34869
34884
  (controlType === FieldControlType.TOGGLE ||
34870
34885
  normalizedControlType === 'toggle' ||
34871
34886
  controlTypeToken === 'switch');
34872
34887
  const shouldUseInlineYearRange = isInlineYearRangeExplicit ||
34873
34888
  (this.useInlineRangeVariant &&
34889
+ !isMultipleSelection &&
34874
34890
  isYearRange &&
34875
34891
  normalizeControlTypeToken(meta?.mode || '') === 'range');
34876
34892
  const shouldUseInlineMonthRange = isInlineMonthRangeExplicit ||
34877
34893
  (this.useInlineRangeVariant &&
34894
+ !isMultipleSelection &&
34878
34895
  isMonthRange &&
34879
34896
  normalizeControlTypeToken(meta?.mode || '') === 'range');
34880
34897
  const periodRangeGranularity = isInlinePeriodRangeExplicit
@@ -34888,9 +34905,11 @@ class PraxisFilter {
34888
34905
  shouldUseInlineYearRange ||
34889
34906
  shouldUseInlineMonthRange;
34890
34907
  const shouldUseInlineRange = this.useInlineRangeVariant &&
34908
+ !isMultipleSelection &&
34891
34909
  (controlType === FieldControlType.RANGE_SLIDER ||
34892
34910
  controlTypeToken === 'rangeslider');
34893
34911
  const shouldUseInlineDate = this.useInlineDateVariant &&
34912
+ !isMultipleSelection &&
34894
34913
  (controlType === FieldControlType.DATE_PICKER ||
34895
34914
  controlType === FieldControlType.DATE_INPUT ||
34896
34915
  normalizedControlType === 'date' ||
@@ -34901,6 +34920,7 @@ class PraxisFilter {
34901
34920
  controlTypeToken === 'datepicker' ||
34902
34921
  controlTypeToken === 'materialdatepicker');
34903
34922
  const shouldUseInlineDateRange = this.useInlineDateRangeVariant &&
34923
+ !isMultipleSelection &&
34904
34924
  (controlType === FieldControlType.DATE_RANGE ||
34905
34925
  controlType === FieldControlType.DATE_TIME_RANGE ||
34906
34926
  normalizedControlType === 'daterange' ||
@@ -35005,7 +35025,7 @@ class PraxisFilter {
35005
35025
  inlineQuickPresets,
35006
35026
  inlineQuickPresetsApplyMode,
35007
35027
  shortcuts,
35008
- updateOn: 'change',
35028
+ updateOn: isMultipleSelection ? (meta.updateOn ?? 'blur') : 'change',
35009
35029
  density: 'compact',
35010
35030
  });
35011
35031
  };
@@ -38734,12 +38754,12 @@ class PraxisTable {
38734
38754
  }
38735
38755
  }
38736
38756
  async ensureAiAssistantRecordSurfaceContext() {
38737
- const selectedRows = this.getSelectedRowsSnapshot()
38757
+ const candidateRows = this.getAiAssistantRecordSurfaceProbeRows()
38738
38758
  .slice(0, PraxisTable.AI_SELECTION_ROW_LIMIT);
38739
- if (!selectedRows.length) {
38759
+ if (!candidateRows.length) {
38740
38760
  return;
38741
38761
  }
38742
- await Promise.all(selectedRows.map((row) => this.ensureAiAssistantRowCapabilitySnapshot(row)));
38762
+ await Promise.all(candidateRows.map((row) => this.ensureAiAssistantRowCapabilitySnapshot(row)));
38743
38763
  }
38744
38764
  getAiAssistantRecordSurfacesContext() {
38745
38765
  const configuredPack = this.aiContext?.recordSurfaces ?? null;
@@ -38880,12 +38900,12 @@ class PraxisTable {
38880
38900
  };
38881
38901
  }
38882
38902
  buildAiAssistantResourceSurfaceContexts() {
38883
- const selectedRows = this.getSelectedRowsSnapshot();
38884
- if (!selectedRows.length || !this.resourcePath) {
38903
+ const candidateRows = this.getAiAssistantRecordSurfaceProbeRows();
38904
+ if (!candidateRows.length || !this.resourcePath) {
38885
38905
  return [];
38886
38906
  }
38887
38907
  const surfacesById = new Map();
38888
- for (const row of selectedRows) {
38908
+ for (const row of candidateRows) {
38889
38909
  const snapshot = this.getCachedRowCapabilitySnapshot(row);
38890
38910
  for (const surface of snapshot?.surfaces ?? []) {
38891
38911
  if (!this.isRowSurfaceAction(surface)) {
@@ -38900,6 +38920,15 @@ class PraxisTable {
38900
38920
  }
38901
38921
  return [...surfacesById.values()];
38902
38922
  }
38923
+ getAiAssistantRecordSurfaceProbeRows() {
38924
+ const selectedRows = this.getSelectedRowsSnapshot();
38925
+ if (selectedRows.length) {
38926
+ return selectedRows;
38927
+ }
38928
+ return Array.isArray(this.dataSource?.data)
38929
+ ? this.dataSource.data.filter(Boolean).slice(0, PraxisTable.AI_SELECTION_ROW_LIMIT)
38930
+ : [];
38931
+ }
38903
38932
  buildRecordRelatedSurfaceContextFromResourceSurface(surface, sourceWidget = this.resolveAiAssistantOwnerId()) {
38904
38933
  const id = String(surface.id || '').trim();
38905
38934
  return {
@@ -39578,7 +39607,7 @@ class PraxisTable {
39578
39607
  if (this.aiAdapter || this.aiAdapterLoadStarted)
39579
39608
  return;
39580
39609
  this.aiAdapterLoadStarted = true;
39581
- import('./praxisui-table-table-ai.adapter-OIjGp0kj.mjs')
39610
+ import('./praxisui-table-table-ai.adapter-BJA9_YlX.mjs')
39582
39611
  .then(({ TableAiAdapter }) => {
39583
39612
  this.aiAdapter = new TableAiAdapter(this);
39584
39613
  this.initializeAiAssistantController();
@@ -39760,7 +39789,7 @@ class PraxisTable {
39760
39789
  initializeAiAssistantController() {
39761
39790
  if (!this.aiAdapter || this.aiAssistantController)
39762
39791
  return;
39763
- import('./praxisui-table-table-agentic-authoring-turn-flow-Bdi7IIY2.mjs')
39792
+ import('./praxisui-table-table-agentic-authoring-turn-flow-DMglW7f1.mjs')
39764
39793
  .then(({ TableAgenticAuthoringTurnFlow }) => {
39765
39794
  if (this.aiAssistantController || !this.aiAdapter)
39766
39795
  return;
@@ -44120,12 +44149,20 @@ class PraxisTable {
44120
44149
  action,
44121
44150
  selected: rows.length,
44122
44151
  }, { actionId: action, throttleKey: `praxis-table:toolbar-bulk-emit:${action}` });
44152
+ const selectedIds = rows
44153
+ .map((row) => this.getRowId(row))
44154
+ .filter((id) => id !== undefined && id !== null);
44123
44155
  if (this.resolveActionGlobalActionRef(safeActionConfig)) {
44124
44156
  await this.executeConfiguredGlobalAction(safeActionConfig, {
44125
44157
  sourceId: this.tableId || this.componentInstanceId || 'praxis-table',
44126
44158
  output: 'bulkAction',
44127
44159
  payload: rows,
44128
- runtime: { selection: rows },
44160
+ runtime: {
44161
+ selection: rows,
44162
+ selectedRows: rows,
44163
+ selectedIds,
44164
+ idField: this.getIdField(),
44165
+ },
44129
44166
  meta: { actionId: action, actionConfig: safeActionConfig },
44130
44167
  });
44131
44168
  if (!this.shouldEmitLocalForGlobalAction(safeActionConfig)) {
@@ -56458,9 +56495,9 @@ const PRAXIS_TABLE_COMPONENT_METADATA = {
56458
56495
  },
56459
56496
  {
56460
56497
  name: 'aiContext',
56461
- type: '{ recordSurfaces?: RecordRelatedSurfaceContextPack | null } | null',
56498
+ type: 'TableAiContext | null',
56462
56499
  label: 'Contexto semântico para IA',
56463
- description: 'Contexto governado pelo host para grounding do assistente, incluindo superfícies relacionadas ao registro derivadas da composição dinâmica.',
56500
+ description: 'Contexto governado pelo host para grounding do assistente, incluindo superfícies relacionadas ao registro e destinos de navegação declarados pelo host.',
56464
56501
  default: null,
56465
56502
  },
56466
56503
  {
@@ -57425,8 +57462,9 @@ const TABLE_AI_CAPABILITIES = {
57425
57462
  { path: 'actions.row.actions[].effects[].globalAction.payload', category: 'actions', valueKind: 'object', description: 'Payload estruturado da GlobalActionRef dentro do efeito runtime por linha.', dependsOn: 'actions.row.actions[].effects[].globalAction.[actionId]' },
57426
57463
  { path: 'actions.bulk.enabled', category: 'actions', valueKind: 'boolean', description: 'Habilita ações em lote.', critical: true, intentExamples: ['ativar ações em lote', 'permitir excluir em massa'], safetyNotes: 'Combine com selection.persistSelection e limites de maxSelections.' },
57427
57464
  { path: 'actions.bulk.position', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.bulkActionPosition, description: 'Posição das ações em lote.', dependsOn: 'actions.bulk.enabled' },
57465
+ { path: 'actions.bulk.actions[]', category: 'actions', valueKind: 'array', description: 'Ações curadas para operar sobre a seleção atual da tabela. Use para criar botões em lote com GlobalActionRef governada.', dependsOn: 'actions.bulk.enabled', intentExamples: ['adicionar botão para agir sobre selecionados', 'criar ação em lote para abrir rota com a seleção atual'] },
57428
57466
  { path: 'actions.bulk.actions[].globalAction.[actionId]', category: 'actions', valueKind: 'string', description: 'Identificador canônico de global action para a ação em lote.', dependsOn: 'actions.bulk.enabled', intentExamples: ['disparar ação global com a seleção atual', 'abrir surface corporativa a partir do bulk action'] },
57429
- { path: 'actions.bulk.actions[].globalAction.payload', category: 'actions', valueKind: 'object', description: 'Payload estruturado da global action em lote. Deve permanecer alinhado ao schema da action escolhida e ao contexto da seleção atual.', dependsOn: 'actions.bulk.actions[].globalAction.[actionId]' },
57467
+ { path: 'actions.bulk.actions[].globalAction.payload', category: 'actions', valueKind: 'object', description: 'Payload estruturado da global action em lote. Deve permanecer alinhado ao schema da action escolhida e ao contexto da seleção atual; para `navigation.openRoute`, use templates como `${runtime.selectedIds}` quando precisar enviar os IDs selecionados.', dependsOn: 'actions.bulk.actions[].globalAction.[actionId]' },
57430
57468
  { path: 'actions.bulk.actions[].effects', category: 'actions', valueKind: 'array', description: 'Array canonico de efeitos runtime da acao em lote, alinhado com PraxisRuntimeGlobalActionEffect.', dependsOn: 'actions.bulk.enabled' },
57431
57469
  { path: 'actions.bulk.actions[].effects[].kind', category: 'actions', valueKind: 'enum', allowedValues: ['global-action'], description: 'Tipo de efeito runtime da acao em lote. Neste corte, apenas global-action e suportado.', dependsOn: 'actions.bulk.actions[].effects' },
57432
57470
  { path: 'actions.bulk.actions[].effects[].globalAction.[actionId]', category: 'actions', valueKind: 'string', description: 'Identificador canonico da GlobalActionRef dentro do efeito runtime em lote.', dependsOn: 'actions.bulk.actions[].effects[].kind' },
@@ -57752,6 +57790,7 @@ const TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS = [
57752
57790
  'configure_toolbar',
57753
57791
  'add_toolbar_action',
57754
57792
  'add_row_action',
57793
+ 'add_bulk_action',
57755
57794
  'configure_export',
57756
57795
  'set_table_density',
57757
57796
  'set_toolbar_visibility',
@@ -57786,6 +57825,7 @@ const TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS = [
57786
57825
  'toolbar.configure',
57787
57826
  'toolbar.action.add',
57788
57827
  'rowAction.add',
57828
+ 'bulkAction.add',
57789
57829
  'export.configure',
57790
57830
  'appearance.density.set',
57791
57831
  'toolbar.visibility.set',
@@ -57821,6 +57861,7 @@ const TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS = {
57821
57861
  configure_toolbar: 'toolbar',
57822
57862
  add_toolbar_action: 'toolbar.actions[]',
57823
57863
  add_row_action: 'actions.row.actions[]',
57864
+ add_bulk_action: 'actions.bulk.actions[]',
57824
57865
  configure_export: 'export',
57825
57866
  set_table_density: 'appearance.density',
57826
57867
  set_toolbar_visibility: 'toolbar.visible',
@@ -57855,6 +57896,7 @@ const TABLE_COMPONENT_EDIT_PLAN_OPERATION_ID_TO_CHANGE_KIND = {
57855
57896
  'toolbar.configure': 'configure_toolbar',
57856
57897
  'toolbar.action.add': 'add_toolbar_action',
57857
57898
  'rowAction.add': 'add_row_action',
57899
+ 'bulkAction.add': 'add_bulk_action',
57858
57900
  'export.configure': 'configure_export',
57859
57901
  'appearance.density.set': 'set_table_density',
57860
57902
  'toolbar.visibility.set': 'set_toolbar_visibility',
@@ -57889,6 +57931,7 @@ const TABLE_COMPONENT_EDIT_PLAN_OPERATION_VALUE_KEYS = {
57889
57931
  'toolbar.configure': '',
57890
57932
  'toolbar.action.add': '',
57891
57933
  'rowAction.add': '',
57934
+ 'bulkAction.add': '',
57892
57935
  'export.configure': '',
57893
57936
  'appearance.density.set': 'density',
57894
57937
  'toolbar.visibility.set': 'visible',
@@ -58324,6 +58367,27 @@ function compileTableComponentEditPlan(plan, currentConfig) {
58324
58367
  failureCodes,
58325
58368
  };
58326
58369
  }
58370
+ if (plan.changeKind === 'add_bulk_action') {
58371
+ const action = valueValidation.value;
58372
+ const currentBulkActions = currentConfig.actions?.bulk;
58373
+ const existingActions = Array.isArray(currentBulkActions?.actions)
58374
+ ? [...currentBulkActions.actions]
58375
+ : [];
58376
+ return {
58377
+ patch: {
58378
+ actions: {
58379
+ bulk: {
58380
+ ...currentBulkActions,
58381
+ enabled: true,
58382
+ actions: mergeActionPatchesById(existingActions, [action]),
58383
+ },
58384
+ },
58385
+ },
58386
+ explanation: plan.explanation || defaultExplanation(plan.changeKind, field, valueValidation.value),
58387
+ warnings,
58388
+ failureCodes,
58389
+ };
58390
+ }
58327
58391
  if (plan.changeKind === 'configure_advanced_filters') {
58328
58392
  return {
58329
58393
  patch: {
@@ -58970,6 +59034,9 @@ function validateValueForChangeKind(changeKind, rawValue, allowedValues) {
58970
59034
  if (changeKind === 'add_row_action') {
58971
59035
  return validateRowActionValue(rawValue);
58972
59036
  }
59037
+ if (changeKind === 'add_bulk_action') {
59038
+ return validateBulkActionValue(rawValue);
59039
+ }
58973
59040
  if (changeKind === 'configure_export') {
58974
59041
  return validateObjectValue(rawValue, 'export configuration');
58975
59042
  }
@@ -59057,6 +59124,35 @@ function validateRowActionValue(rawValue) {
59057
59124
  failureCodes: [],
59058
59125
  };
59059
59126
  }
59127
+ function validateBulkActionValue(rawValue) {
59128
+ const value = coerceRecord(rawValue);
59129
+ if (!value) {
59130
+ return { failureCodes: ['bulk action must be object'] };
59131
+ }
59132
+ const id = normalizeText(value['id']);
59133
+ const label = normalizeText(value['label']);
59134
+ const action = normalizeText(value['action']);
59135
+ const failureCodes = [];
59136
+ if (!id)
59137
+ failureCodes.push('bulk action id is required');
59138
+ if (!label)
59139
+ failureCodes.push('bulk action label is required');
59140
+ if (!action)
59141
+ failureCodes.push('bulk action action is required');
59142
+ if (failureCodes.length > 0) {
59143
+ return { failureCodes };
59144
+ }
59145
+ return {
59146
+ value: {
59147
+ icon: normalizeText(value['icon']) || 'done_all',
59148
+ ...value,
59149
+ id,
59150
+ label,
59151
+ action,
59152
+ },
59153
+ failureCodes: [],
59154
+ };
59155
+ }
59060
59156
  function validateRecordSurfaceValue(rawValue) {
59061
59157
  const surface = coerceRecord(rawValue);
59062
59158
  if (!surface)
@@ -59282,6 +59378,10 @@ function defaultExplanation(changeKind, field, value) {
59282
59378
  const action = coerceRecord(value);
59283
59379
  return `Acao ${normalizeText(action?.['label']) || normalizeText(action?.['id']) || 'de linha'} adicionada as linhas da tabela.`;
59284
59380
  }
59381
+ if (changeKind === 'add_bulk_action') {
59382
+ const action = coerceRecord(value);
59383
+ return `Acao ${normalizeText(action?.['label']) || normalizeText(action?.['id']) || 'em lote'} adicionada a selecao da tabela.`;
59384
+ }
59285
59385
  if (changeKind === 'set_table_density') {
59286
59386
  return `Densidade da tabela atualizada para ${String(value)}.`;
59287
59387
  }
@@ -266,8 +266,7 @@ class TableAgenticAuthoringTurnFlow {
266
266
  || this.shouldUseSelectedRecordSurfaceSnapshotFallback(contextHints));
267
267
  }
268
268
  shouldUseSelectedRecordSurfaceSnapshotFallback(contextHints) {
269
- return this.selectedRecordsCountForTurn > 0
270
- && this.selectedRecordSurfaces(contextHints).length > 0;
269
+ return this.selectedRecordSurfaces(contextHints).length > 0;
271
270
  }
272
271
  selectedRecordSurfaces(contextHints) {
273
272
  const authoringContract = this.toRecord(contextHints?.['authoringContract']);
@@ -561,13 +560,14 @@ class TableAgenticAuthoringTurnFlow {
561
560
  ? this.adapter.compileAiResponse?.(response)
562
561
  : null;
563
562
  if (compiledExecutable?.patch && Object.keys(compiledExecutable.patch).length > 0) {
563
+ const normalizedExecutable = this.normalizeBulkRouteSelectionPayload(compiledExecutable, request);
564
564
  const warnings = [
565
565
  ...(response.warnings ?? []),
566
- ...(compiledExecutable.warnings ?? []),
566
+ ...(normalizedExecutable.warnings ?? []),
567
567
  ];
568
568
  const executableResponse = {
569
569
  ...response,
570
- patch: compiledExecutable.patch,
570
+ patch: normalizedExecutable.patch,
571
571
  warnings: warnings.length ? warnings : undefined,
572
572
  };
573
573
  delete executableResponse.type;
@@ -578,6 +578,10 @@ class TableAgenticAuthoringTurnFlow {
578
578
  if (continuedInvalidExecutable) {
579
579
  return continuedInvalidExecutable;
580
580
  }
581
+ const continuedBulkRouteAction = this.bulkRouteActionPlanForInvalidExecutable(response, request, compiledExecutable.warnings);
582
+ if (continuedBulkRouteAction) {
583
+ return this.compileAdapterResponse(continuedBulkRouteAction, request);
584
+ }
581
585
  return {
582
586
  type: 'error',
583
587
  message: compiledExecutable.message || 'O componentEditPlan da tabela nao passou na validacao de capacidades.',
@@ -592,12 +596,24 @@ class TableAgenticAuthoringTurnFlow {
592
596
  if (continuedSurfaceRuntimeOperation) {
593
597
  return continuedSurfaceRuntimeOperation;
594
598
  }
599
+ const continuedBulkRouteNarrative = this.bulkRouteActionPlanForNonExecutableNarrative(response, request);
600
+ if (continuedBulkRouteNarrative) {
601
+ return this.compileAdapterResponse(continuedBulkRouteNarrative, request);
602
+ }
603
+ const continuedBulkRouteAction = this.bulkRouteActionPlanForClarification(response, request);
604
+ if (continuedBulkRouteAction) {
605
+ return this.compileAdapterResponse(continuedBulkRouteAction, request);
606
+ }
595
607
  const continuedSurfaceRowAction = this.selectedRecordSurfaceRowActionPlanForClarification(response, request);
596
608
  if (continuedSurfaceRowAction) {
597
609
  return this.compileAdapterResponse(continuedSurfaceRowAction, request);
598
610
  }
599
611
  return response;
600
612
  }
613
+ const rowActionGuidance = this.recordSurfaceRowActionGuidanceForConsult(response, request);
614
+ if (rowActionGuidance) {
615
+ return rowActionGuidance;
616
+ }
601
617
  const compiled = this.adapter.compileAiResponse?.(response);
602
618
  if (!compiled && response.patch && Object.keys(response.patch).length > 0) {
603
619
  return {
@@ -610,9 +626,17 @@ class TableAgenticAuthoringTurnFlow {
610
626
  };
611
627
  }
612
628
  if (!compiled) {
629
+ const continuedBulkRouteNarrative = this.bulkRouteActionPlanForNonExecutableNarrative(response, request);
630
+ if (continuedBulkRouteNarrative) {
631
+ return this.compileAdapterResponse(continuedBulkRouteNarrative, request);
632
+ }
613
633
  return response;
614
634
  }
615
635
  if (compiled.type === 'error') {
636
+ const continuedBulkRouteAction = this.bulkRouteActionPlanForInvalidExecutable(response, request, compiled.warnings);
637
+ if (continuedBulkRouteAction) {
638
+ return this.compileAdapterResponse(continuedBulkRouteAction, request);
639
+ }
616
640
  const continuedInvalidExecutable = this.selectedRecordSurfaceRuntimeOperationForInvalidExecutable(response, request, compiled.warnings);
617
641
  if (continuedInvalidExecutable) {
618
642
  return continuedInvalidExecutable.componentEditPlan
@@ -645,17 +669,253 @@ class TableAgenticAuthoringTurnFlow {
645
669
  if (implicitSelectedFilterClarification) {
646
670
  return implicitSelectedFilterClarification;
647
671
  }
672
+ const normalizedCompiled = this.normalizeBulkRouteSelectionPayload(compiled, request);
648
673
  const warnings = [
649
674
  ...(response.warnings ?? []),
650
- ...(compiled.warnings ?? []),
675
+ ...(normalizedCompiled.warnings ?? []),
651
676
  ];
652
677
  return {
653
678
  ...response,
654
- ...compiled,
655
- patch: compiled.patch,
679
+ ...normalizedCompiled,
680
+ patch: normalizedCompiled.patch,
656
681
  warnings: warnings.length ? warnings : undefined,
657
682
  };
658
683
  }
684
+ normalizeBulkRouteSelectionPayload(compiled, request) {
685
+ if (!compiled?.patch || !request)
686
+ return compiled;
687
+ const text = this.normalizeLabel([
688
+ ...(request.messages ?? [])
689
+ .filter((message) => message?.role === 'user')
690
+ .slice(-2)
691
+ .map((message) => message?.text ?? ''),
692
+ request.prompt ?? '',
693
+ ].join(' '));
694
+ if (!this.textMentionsBulkActionRequest(text))
695
+ return compiled;
696
+ const routePath = this.extractRoutePath(text);
697
+ const patch = this.cloneJson(compiled.patch);
698
+ const componentEditPlan = compiled.componentEditPlan
699
+ ? this.cloneJson(compiled.componentEditPlan)
700
+ : undefined;
701
+ const bulkActions = patch?.actions?.bulk?.actions;
702
+ let changed = false;
703
+ if (Array.isArray(bulkActions)) {
704
+ for (const action of bulkActions) {
705
+ if (!action || typeof action !== 'object')
706
+ continue;
707
+ if (this.ensureBulkRouteActionSelectionQuery(action, routePath)) {
708
+ changed = true;
709
+ }
710
+ }
711
+ }
712
+ if (componentEditPlan && this.ensureBulkRouteActionSelectionQueryOnPlan(componentEditPlan, routePath)) {
713
+ changed = true;
714
+ }
715
+ if (!Array.isArray(bulkActions) && !componentEditPlan)
716
+ return compiled;
717
+ if (!changed)
718
+ return compiled;
719
+ return {
720
+ ...compiled,
721
+ ...(componentEditPlan ? { componentEditPlan } : {}),
722
+ patch,
723
+ warnings: [
724
+ ...(compiled.warnings ?? []),
725
+ 'bulk-route-action-selection-query-normalized',
726
+ ],
727
+ };
728
+ }
729
+ ensureBulkRouteActionSelectionQueryOnPlan(plan, routePath) {
730
+ if (!plan || typeof plan !== 'object')
731
+ return false;
732
+ let changed = false;
733
+ for (const key of ['input', 'value']) {
734
+ if (this.ensureBulkRouteActionSelectionQuery(plan[key], routePath)) {
735
+ changed = true;
736
+ }
737
+ }
738
+ if (Array.isArray(plan.operations)) {
739
+ for (const operation of plan.operations) {
740
+ if (!operation || typeof operation !== 'object')
741
+ continue;
742
+ for (const key of ['input', 'value']) {
743
+ if (this.ensureBulkRouteActionSelectionQuery(operation[key], routePath)) {
744
+ changed = true;
745
+ }
746
+ }
747
+ }
748
+ }
749
+ return changed;
750
+ }
751
+ ensureBulkRouteActionSelectionQuery(action, routePath) {
752
+ if (!action || typeof action !== 'object')
753
+ return false;
754
+ let changed = false;
755
+ if (this.ensureBulkRouteActionGlobalRouteRef(action, routePath)) {
756
+ changed = true;
757
+ }
758
+ if (this.ensureGlobalRouteActionSelectionQuery(action.globalAction)) {
759
+ changed = true;
760
+ }
761
+ if (Array.isArray(action.effects)) {
762
+ for (const effect of action.effects) {
763
+ if (effect?.kind === 'global-action' && this.ensureGlobalRouteActionSelectionQuery(effect.globalAction)) {
764
+ changed = true;
765
+ }
766
+ }
767
+ }
768
+ return changed;
769
+ }
770
+ ensureBulkRouteActionGlobalRouteRef(action, routePath) {
771
+ if (!routePath)
772
+ return false;
773
+ if (this.hasGlobalRouteActionRef(action))
774
+ return false;
775
+ const configuredAction = this.stringValue(action.action);
776
+ const looksLikeRouteAction = configuredAction === 'navigation.openRoute'
777
+ || configuredAction === 'navigation.open route'
778
+ || this.stringValue(action.globalAction?.actionId) === 'navigation.openRoute';
779
+ const hasRoutePayload = this.stringValue(action.payload?.path)
780
+ || this.stringValue(action.globalAction?.payload?.path)
781
+ || routePath;
782
+ if (!looksLikeRouteAction && !hasRoutePayload)
783
+ return false;
784
+ const globalAction = {
785
+ actionId: 'navigation.openRoute',
786
+ payload: {
787
+ path: this.stringValue(action.payload?.path)
788
+ || this.stringValue(action.globalAction?.payload?.path)
789
+ || routePath,
790
+ query: { ids: '${runtime.selectedIds}' },
791
+ },
792
+ };
793
+ action.globalAction = globalAction;
794
+ action.effects = [{ kind: 'global-action', globalAction }];
795
+ if (!this.stringValue(action.action)) {
796
+ action.action = 'navigation.openRoute';
797
+ }
798
+ return true;
799
+ }
800
+ hasGlobalRouteActionRef(action) {
801
+ if (this.stringValue(action?.globalAction?.actionId) === 'navigation.openRoute') {
802
+ return true;
803
+ }
804
+ if (!Array.isArray(action?.effects))
805
+ return false;
806
+ return action.effects.some((effect) => effect?.kind === 'global-action'
807
+ && this.stringValue(effect.globalAction?.actionId) === 'navigation.openRoute');
808
+ }
809
+ ensureGlobalRouteActionSelectionQuery(globalAction) {
810
+ if (!globalAction || typeof globalAction !== 'object')
811
+ return false;
812
+ if (globalAction.actionId !== 'navigation.openRoute')
813
+ return false;
814
+ const payload = globalAction.payload;
815
+ if (!payload || typeof payload !== 'object')
816
+ return false;
817
+ if (!this.stringValue(payload.path))
818
+ return false;
819
+ if (!payload.query || typeof payload.query !== 'object' || Array.isArray(payload.query)) {
820
+ payload.query = {};
821
+ }
822
+ if (payload.query.ids !== undefined && payload.query.ids !== null && payload.query.ids !== '') {
823
+ return false;
824
+ }
825
+ payload.query.ids = '${runtime.selectedIds}';
826
+ return true;
827
+ }
828
+ recordSurfaceRowActionGuidanceForConsult(response, request) {
829
+ if (!request || !this.promptAsksRowActionCapabilities(request))
830
+ return null;
831
+ if (!this.responseCarriesRowActionAddPlan(response))
832
+ return null;
833
+ const surfaces = this.selectedRecordSurfaces(this.contextHintsFor(request));
834
+ if (!surfaces.length)
835
+ return null;
836
+ const labels = [...new Set(surfaces
837
+ .map((surface) => {
838
+ const resourceSurface = this.toRecord(surface['resourceSurface']);
839
+ return this.stringValue(surface['label'])
840
+ || this.stringValue(resourceSurface?.['title'])
841
+ || this.stringValue(surface['id']);
842
+ })
843
+ .filter((label) => !!label))];
844
+ if (!labels.length)
845
+ return null;
846
+ return {
847
+ type: 'info',
848
+ message: [
849
+ 'Você pode adicionar botões de linha para superfícies relacionadas declaradas para este recurso.',
850
+ `Opções disponíveis agora: ${labels.map((label) => `**${label}**`).join(', ')}.`,
851
+ 'Quando quiser materializar uma delas, peça algo como "adicione um botão na linha para abrir Histórico de folha".',
852
+ ].join(' '),
853
+ warnings: [
854
+ 'row-action-capability-question-preserved-as-consult',
855
+ 'Residual consult guard acted only after the LLM proposed rowAction.add for a row-action capability-discovery question while declared recordSurfaces were available.',
856
+ ],
857
+ };
858
+ }
859
+ promptAsksRowActionCapabilities(request) {
860
+ const currentPrompt = this.normalizeLabel(request.prompt ?? '');
861
+ const recentUserContext = this.normalizeLabel((request.messages ?? [])
862
+ .filter((message) => message?.role === 'user')
863
+ .slice(-2)
864
+ .map((message) => message?.text ?? '')
865
+ .join(' '));
866
+ const text = [recentUserContext, currentPrompt].filter(Boolean).join(' ');
867
+ if (!this.textMentionsRowActionRequest(text))
868
+ return false;
869
+ const asksAvailability = [
870
+ 'quais',
871
+ 'qual',
872
+ 'o que',
873
+ 'que botoes',
874
+ 'que botões',
875
+ 'botoes posso',
876
+ 'botões posso',
877
+ 'acoes disponiveis',
878
+ 'ações disponíveis',
879
+ 'acoes estao disponiveis',
880
+ 'ações estão disponíveis',
881
+ 'posso adicionar',
882
+ 'can i add',
883
+ 'available',
884
+ 'what actions',
885
+ 'which actions',
886
+ 'which buttons',
887
+ ].some((needle) => text.includes(this.normalizeLabel(needle)));
888
+ if (!asksAvailability)
889
+ return false;
890
+ const explicitMaterialization = [
891
+ 'adicione',
892
+ 'adicionar agora',
893
+ 'crie',
894
+ 'criar agora',
895
+ 'coloque',
896
+ 'aplique',
897
+ 'materialize',
898
+ 'create a',
899
+ 'add a',
900
+ ].some((needle) => currentPrompt.includes(this.normalizeLabel(needle)));
901
+ return !explicitMaterialization;
902
+ }
903
+ responseCarriesRowActionAddPlan(response) {
904
+ const record = response;
905
+ return [
906
+ this.toRecord(record['componentEditPlan']),
907
+ this.toRecord(this.toRecord(record['patch'])?.['componentEditPlan']),
908
+ this.toRecord(record['tableEditPlan']),
909
+ this.toRecord(record['editPlan']),
910
+ ].some((plan) => {
911
+ if (!plan)
912
+ return false;
913
+ if (this.stringValue(plan['operationId']) === 'rowAction.add')
914
+ return true;
915
+ const operations = Array.isArray(plan['operations']) ? plan['operations'] : [];
916
+ return operations.some((operation) => this.stringValue(this.toRecord(operation)?.['operationId']) === 'rowAction.add');
917
+ });
918
+ }
659
919
  responseCarriesClarificationChoices(response) {
660
920
  if (response.type !== 'clarification')
661
921
  return false;
@@ -936,7 +1196,7 @@ class TableAgenticAuthoringTurnFlow {
936
1196
  ...(request.messages ?? []).slice(-8).map((message) => message?.text ?? ''),
937
1197
  request.prompt ?? '',
938
1198
  ].join(' '));
939
- if (!this.textMentionsRowActionRequest(normalizedPrompt || normalizedConversation)) {
1199
+ if (!this.textMentionsRowActionRequest(`${normalizedPrompt} ${normalizedConversation}`)) {
940
1200
  return null;
941
1201
  }
942
1202
  const clarificationKind = this.selectedRecordSurfaceRowActionClarificationKind(response);
@@ -956,11 +1216,19 @@ class TableAgenticAuthoringTurnFlow {
956
1216
  if (!ranked.length || (ranked.length > 1 && ranked[0].score === ranked[1].score)) {
957
1217
  return null;
958
1218
  }
959
- const rowActionResponse = this.buildSelectedRecordSurfaceRowActionResponse(ranked[0].surface, 'selected-record-surface-row-action-continued-from-clarification', clarificationKind === 'technical'
960
- ? 'selected-record-surface-row-action-continued-from-technical-clarification'
961
- : 'selected-record-surface-row-action-continued-from-generic-clarification', clarificationKind === 'technical'
962
- ? 'Residual continuity guard acted only after LLM asked for technical row-action details while declared recordSurfaces and conversation history already grounded the target surface.'
963
- : 'Residual continuity guard acted only after LLM asked a generic dataset/listing clarification while declared recordSurfaces and a row-action request already grounded the target surface.');
1219
+ const hasSelectedRecords = this.selectedRecordsCountForTurn > 0;
1220
+ const source = hasSelectedRecords
1221
+ ? 'selected-record-surface-row-action-continued-from-clarification'
1222
+ : 'record-surface-row-action-continued-from-clarification';
1223
+ const warning = hasSelectedRecords
1224
+ ? (clarificationKind === 'technical'
1225
+ ? 'selected-record-surface-row-action-continued-from-technical-clarification'
1226
+ : 'selected-record-surface-row-action-continued-from-generic-clarification')
1227
+ : 'record-surface-row-action-continued-from-clarification';
1228
+ const warningDetail = clarificationKind === 'technical'
1229
+ ? `Residual continuity guard acted only after LLM asked for technical row-action details while declared recordSurfaces${hasSelectedRecords ? ' and conversation history' : ''} already grounded the target surface.`
1230
+ : 'Residual continuity guard acted only after LLM asked a generic dataset/listing clarification while declared recordSurfaces and a row-action request already grounded the target surface.';
1231
+ const rowActionResponse = this.buildSelectedRecordSurfaceRowActionResponse(ranked[0].surface, source, warning, warningDetail);
964
1232
  if (!rowActionResponse)
965
1233
  return null;
966
1234
  // Residual continuity guard: this runs only after the LLM returned a
@@ -978,7 +1246,7 @@ class TableAgenticAuthoringTurnFlow {
978
1246
  ...(request.messages ?? []).slice(-8).map((message) => message?.text ?? ''),
979
1247
  request.prompt ?? '',
980
1248
  ].join(' '));
981
- if (!this.textMentionsRowActionRequest(normalizedPrompt || normalizedConversation)) {
1249
+ if (!this.textMentionsRowActionRequest(`${normalizedPrompt} ${normalizedConversation}`)) {
982
1250
  return null;
983
1251
  }
984
1252
  const responseText = this.normalizeLabel([
@@ -1073,9 +1341,14 @@ class TableAgenticAuthoringTurnFlow {
1073
1341
  if (!request || !this.responseMayContainExecutableEnvelope(response))
1074
1342
  return null;
1075
1343
  const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
1076
- if (!this.textMentionsRecordSurfaceOpenRequest(normalizedPrompt))
1344
+ const normalizedConversation = this.normalizeLabel([
1345
+ ...(request.messages ?? []).slice(-8).map((message) => message?.text ?? ''),
1346
+ request.prompt ?? '',
1347
+ ].join(' '));
1348
+ const requestText = `${normalizedPrompt} ${normalizedConversation}`;
1349
+ if (!this.textMentionsRecordSurfaceOpenRequest(requestText))
1077
1350
  return null;
1078
- if (this.promptRequestsSimilarRecords(normalizedPrompt))
1351
+ if (this.promptRequestsSimilarRecords(requestText))
1079
1352
  return null;
1080
1353
  const contextHints = this.contextHintsFor(request);
1081
1354
  const surfaces = this.selectedRecordSurfaces(contextHints);
@@ -1091,14 +1364,14 @@ class TableAgenticAuthoringTurnFlow {
1091
1364
  const ranked = surfaces
1092
1365
  .map((surface) => ({
1093
1366
  surface,
1094
- score: this.selectedRecordSurfacePromptScore(`${normalizedPrompt} ${responseEvidence}`, surface),
1367
+ score: this.selectedRecordSurfacePromptScore(`${requestText} ${responseEvidence}`, surface),
1095
1368
  }))
1096
1369
  .filter((entry) => entry.score >= 2)
1097
1370
  .sort((left, right) => right.score - left.score);
1098
1371
  if (!ranked.length || (ranked.length > 1 && ranked[0].score === ranked[1].score)) {
1099
1372
  return null;
1100
1373
  }
1101
- if (this.textMentionsRowActionRequest(normalizedPrompt)) {
1374
+ if (this.textMentionsRowActionRequest(requestText)) {
1102
1375
  const rowActionResponse = this.buildSelectedRecordSurfaceRowActionResponse(ranked[0].surface, 'selected-record-surface-row-action-invalid-executable-continuity-guard', 'selected-record-surface-row-action-continued-from-invalid-executable', 'Residual continuity guard acted only after LLM emitted an executable envelope that failed table component capability validation for a row-action request while a declared recordSurface uniquely matched the selected-record request.');
1103
1376
  if (rowActionResponse)
1104
1377
  return rowActionResponse;
@@ -1173,6 +1446,116 @@ class TableAgenticAuthoringTurnFlow {
1173
1446
  warnings: [warning, warningDetail],
1174
1447
  };
1175
1448
  }
1449
+ bulkRouteActionPlanForClarification(response, request) {
1450
+ if (response.type !== 'clarification' || !request)
1451
+ return null;
1452
+ const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
1453
+ if (!this.textMentionsBulkActionRequest(normalizedPrompt))
1454
+ return null;
1455
+ if (!this.textMentionsRecordSurfaceOpenRequest(normalizedPrompt))
1456
+ return null;
1457
+ const routePath = this.extractRoutePath(request.prompt ?? '');
1458
+ if (!routePath)
1459
+ return null;
1460
+ const clarificationKind = this.globalActionClarificationKind(response);
1461
+ if (!clarificationKind)
1462
+ return null;
1463
+ return this.buildBulkRouteActionPlan(routePath, 'bulk-route-action-continued-from-clarification', [
1464
+ 'bulk-route-action-continued-from-technical-clarification',
1465
+ 'Residual continuity guard acted only after LLM asked for technical bulk route details while a route path and selected-record bulk action intent were already grounded.',
1466
+ ]);
1467
+ }
1468
+ bulkRouteActionPlanForInvalidExecutable(response, request, validationWarnings = []) {
1469
+ if (!request)
1470
+ return null;
1471
+ if (!response.componentEditPlan && !response.patch)
1472
+ return null;
1473
+ const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
1474
+ if (!this.textMentionsBulkActionRequest(normalizedPrompt))
1475
+ return null;
1476
+ if (!this.textMentionsRecordSurfaceOpenRequest(normalizedPrompt))
1477
+ return null;
1478
+ const routePath = this.extractRoutePath(request.prompt ?? '');
1479
+ if (!routePath)
1480
+ return null;
1481
+ return this.buildBulkRouteActionPlan(routePath, 'bulk-route-action-continued-from-invalid-executable', [
1482
+ ...validationWarnings,
1483
+ 'bulk-route-action-continued-from-invalid-executable',
1484
+ 'Residual continuity guard acted only after LLM proposed an invalid executable table plan while route path and selected-record bulk action intent were already grounded.',
1485
+ ]);
1486
+ }
1487
+ bulkRouteActionPlanForNonExecutableNarrative(response, request) {
1488
+ if (!request)
1489
+ return null;
1490
+ const normalizedPrompt = this.normalizeLabel(request.prompt ?? '');
1491
+ if (!this.textMentionsBulkActionRequest(normalizedPrompt))
1492
+ return null;
1493
+ if (!this.textMentionsRecordSurfaceOpenRequest(normalizedPrompt))
1494
+ return null;
1495
+ const routePath = this.extractRoutePath(request.prompt ?? '');
1496
+ if (!routePath)
1497
+ return null;
1498
+ const narrative = this.normalizeLabel([
1499
+ response.message ?? '',
1500
+ response.explanation ?? '',
1501
+ ...(response.warnings ?? []),
1502
+ ].join(' '));
1503
+ const hasCanonicalDecision = this.normalizedTextIncludesAny(narrative, ['componentEditPlan', 'component edit plan'])
1504
+ && this.normalizedTextIncludesAny(narrative, ['bulkAction.add', 'bulk action.add'])
1505
+ && this.normalizedTextIncludesAny(narrative, ['navigation.openRoute', 'navigation.open route'])
1506
+ && this.normalizedTextIncludesAny(narrative, ['selectedIds', 'selected ids', 'runtime.selectedIds']);
1507
+ if (!hasCanonicalDecision)
1508
+ return null;
1509
+ return this.buildBulkRouteActionPlan(routePath, 'bulk-route-action-continued-from-non-executable-narrative', [
1510
+ 'bulk-route-action-continued-from-non-executable-narrative',
1511
+ 'Residual continuity guard acted only after LLM described the canonical bulkAction.add/navigation.openRoute decision without returning an executable componentEditPlan envelope.',
1512
+ ]);
1513
+ }
1514
+ buildBulkRouteActionPlan(routePath, source, warnings) {
1515
+ const actionId = `open-${this.slugifyActionId(routePath)}-selected`;
1516
+ const label = this.humanizeBulkRouteActionLabel(routePath);
1517
+ const globalAction = {
1518
+ actionId: 'navigation.openRoute',
1519
+ payload: {
1520
+ path: routePath,
1521
+ query: { ids: '${runtime.selectedIds}' },
1522
+ },
1523
+ };
1524
+ const bulkAction = {
1525
+ id: actionId,
1526
+ label,
1527
+ action: 'navigation.openRoute',
1528
+ icon: 'route',
1529
+ globalAction,
1530
+ effects: [
1531
+ {
1532
+ kind: 'global-action',
1533
+ globalAction,
1534
+ },
1535
+ ],
1536
+ };
1537
+ // Residual continuity guard: this executes only after the LLM already
1538
+ // resolved the turn as a clarification, while the user-provided route path
1539
+ // and the declared bulkAction.add/globalAction contract are sufficient to
1540
+ // materialize the operation. It grounds payload details in canonical runtime
1541
+ // selection templates instead of using local text as primary intent routing.
1542
+ return {
1543
+ type: 'patch',
1544
+ componentEditPlan: {
1545
+ kind: 'praxis.table.component-edit-plan',
1546
+ version: '1.0',
1547
+ componentId: 'praxis-table',
1548
+ operationId: 'bulkAction.add',
1549
+ changeKind: 'add_bulk_action',
1550
+ capabilityPath: 'actions.bulk.actions[]',
1551
+ input: bulkAction,
1552
+ value: bulkAction,
1553
+ source,
1554
+ },
1555
+ explanation: `Vou adicionar a ação ${label} para os registros selecionados.`,
1556
+ warnings,
1557
+ };
1558
+ }
1176
1559
  selectedRecordSurfaceRowActionClarificationKind(response) {
1177
1560
  const text = this.normalizeLabel([
1178
1561
  response.message ?? '',
@@ -1186,6 +1569,30 @@ class TableAgenticAuthoringTurnFlow {
1186
1569
  'mais detalhes sobre surface',
1187
1570
  'mais detalhes sobre button',
1188
1571
  'mais detalhes sobre placement',
1572
+ 'mais detalhes sobre openmode',
1573
+ 'mais detalhes sobre open mode',
1574
+ 'mais detalhes sobre iconorstyle',
1575
+ 'mais detalhes sobre appliesto',
1576
+ 'mais detalhes sobre actionlabel',
1577
+ 'mais detalhes sobre openbehavior',
1578
+ 'mais detalhes sobre actionbehavior',
1579
+ 'mais detalhes sobre destinationsurface',
1580
+ 'mais detalhes sobre iconlabel',
1581
+ 'qual condicao deve ser usada',
1582
+ 'qual condição deve ser usada',
1583
+ 'mais detalhes sobre action behavior',
1584
+ 'o alvo do ajuste',
1585
+ 'nome que voce prefere',
1586
+ 'nome que você prefere',
1587
+ 'openmode',
1588
+ 'open mode',
1589
+ 'iconorstyle',
1590
+ 'appliesto',
1591
+ 'actionlabel',
1592
+ 'openbehavior',
1593
+ 'actionbehavior',
1594
+ 'destinationsurface',
1595
+ 'iconlabel',
1189
1596
  ].some((needle) => text.includes(needle))) {
1190
1597
  return 'technical';
1191
1598
  }
@@ -1202,16 +1609,68 @@ class TableAgenticAuthoringTurnFlow {
1202
1609
  }
1203
1610
  return null;
1204
1611
  }
1612
+ globalActionClarificationKind(response) {
1613
+ const text = this.normalizeLabel([
1614
+ response.message ?? '',
1615
+ response.explanation ?? '',
1616
+ ...(response.questions ?? []),
1617
+ ].join(' '));
1618
+ if ([
1619
+ 'recordidparamname',
1620
+ 'record id param name',
1621
+ 'o alvo do ajuste',
1622
+ 'qual formato aplicar',
1623
+ 'mais detalhes sobre target',
1624
+ 'mais detalhes sobre payload',
1625
+ 'mais detalhes sobre route',
1626
+ 'mais detalhes sobre openmode',
1627
+ 'mais detalhes sobre open mode',
1628
+ ].some((needle) => text.includes(this.normalizeLabel(needle)))) {
1629
+ return 'technical';
1630
+ }
1631
+ return null;
1632
+ }
1205
1633
  textMentionsRowActionRequest(normalizedText) {
1206
1634
  return [
1207
1635
  'botao',
1208
1636
  'acao de linha',
1209
1637
  'acoes de linha',
1638
+ 'acao por registro',
1639
+ 'acoes por registro',
1210
1640
  'nas linhas',
1211
1641
  'por linha',
1212
1642
  'em cada linha',
1213
1643
  ].some((needle) => normalizedText.includes(needle));
1214
1644
  }
1645
+ textMentionsBulkActionRequest(normalizedText) {
1646
+ return [
1647
+ 'acao em lote',
1648
+ 'acoes em lote',
1649
+ 'registros selecionados',
1650
+ 'linhas selecionadas',
1651
+ 'selecionados',
1652
+ 'bulk action',
1653
+ ].some((needle) => normalizedText.includes(this.normalizeLabel(needle)));
1654
+ }
1655
+ normalizedTextIncludesAny(normalizedText, needles) {
1656
+ return needles.some((needle) => normalizedText.includes(this.normalizeLabel(needle)));
1657
+ }
1658
+ extractRoutePath(text) {
1659
+ const match = String(text || '').match(/(?:^|\s)(\/[A-Za-z0-9._~:/?#[\]@!$&'()*+,;=%-]+)(?=$|\s|[,.])/u);
1660
+ return match?.[1]?.replace(/[,.]$/u, '') ?? '';
1661
+ }
1662
+ humanizeBulkRouteActionLabel(path) {
1663
+ const segments = path
1664
+ .split(/[?#]/u)[0]
1665
+ .split('/')
1666
+ .map((segment) => segment.trim())
1667
+ .filter(Boolean);
1668
+ const lastSegments = segments.slice(-2);
1669
+ const label = lastSegments
1670
+ .map((segment) => this.humanizeField(segment))
1671
+ .join(' - ');
1672
+ return label ? `Abrir ${label}` : 'Abrir rota dos selecionados';
1673
+ }
1215
1674
  textMentionsRecordSurfaceOpenRequest(normalizedText) {
1216
1675
  return [
1217
1676
  'abrir',
@@ -2031,6 +2490,9 @@ class TableAgenticAuthoringTurnFlow {
2031
2490
  case 'rowAction.add':
2032
2491
  case 'add_row_action':
2033
2492
  return `Vou criar um botao em cada linha para abrir **${this.stringValue(input['label']) || this.stringValue(input['id']) || 'a opcao solicitada'}**.`;
2493
+ case 'bulkAction.add':
2494
+ case 'add_bulk_action':
2495
+ return `Vou adicionar a acao **${this.stringValue(input['label']) || this.stringValue(input['id']) || 'solicitada'}** para os registros selecionados.`;
2034
2496
  case 'export.configure':
2035
2497
  return this.describeExportConfigure(input);
2036
2498
  case 'appearance.density.set':
@@ -3056,6 +3518,14 @@ class TableAgenticAuthoringTurnFlow {
3056
3518
  return {};
3057
3519
  }
3058
3520
  }
3521
+ cloneJson(value) {
3522
+ try {
3523
+ return JSON.parse(JSON.stringify(value));
3524
+ }
3525
+ catch {
3526
+ return value;
3527
+ }
3528
+ }
3059
3529
  toRecord(value) {
3060
3530
  return value && typeof value === 'object' && !Array.isArray(value)
3061
3531
  ? value
@@ -1,7 +1,7 @@
1
1
  import { firstValueFrom } from 'rxjs';
2
2
  import { BaseAiAdapter, createComponentAuthoringContext } from '@praxisui/ai';
3
- import { deepMerge } from '@praxisui/core';
4
- import { z as TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS, k as PRAXIS_TABLE_AUTHORING_MANIFEST, T as TABLE_AI_CAPABILITIES, R as coerceTableComponentEditPlans, W as compileTableComponentEditPlans, G as TASK_PRESETS, $ as getTableComponentEditPlanCapabilities, w as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, u as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, x as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, E as TABLE_COMPONENT_EDIT_PLAN_VERSION, v as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, y as TABLE_COMPONENT_EDIT_PLAN_KIND } from './praxisui-table-praxisui-table-28INRbt6.mjs';
3
+ import { PRAXIS_GLOBAL_ACTION_CATALOG, deepMerge } from '@praxisui/core';
4
+ import { z as TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS, k as PRAXIS_TABLE_AUTHORING_MANIFEST, T as TABLE_AI_CAPABILITIES, R as coerceTableComponentEditPlans, W as compileTableComponentEditPlans, G as TASK_PRESETS, $ as getTableComponentEditPlanCapabilities, w as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, u as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, x as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, E as TABLE_COMPONENT_EDIT_PLAN_VERSION, v as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, y as TABLE_COMPONENT_EDIT_PLAN_KIND } from './praxisui-table-praxisui-table-mlOL4l4b.mjs';
5
5
 
6
6
  const TABLE_COMPONENT_CONTEXT_PACK = {
7
7
  version: 'v1',
@@ -1985,6 +1985,8 @@ class TableAiAdapter extends BaseAiAdapter {
1985
1985
  const selectedRowsContext = this.getSelectedRowsAuthoringContext();
1986
1986
  const resourceCapabilities = this.getResourceCapabilityAuthoringContext();
1987
1987
  const recordSurfaces = this.getRecordSurfaceAuthoringContext();
1988
+ const globalActionCatalog = this.getGlobalActionAuthoringCatalog();
1989
+ const navigationDestinations = this.getNavigationDestinationAuthoringContext();
1988
1990
  const filterExpressionSupported = resourceCapabilities?.filterExpressionSupported === true;
1989
1991
  const runtimeExportFormats = this.getRuntimeExportFormats();
1990
1992
  const runtimeOperations = [
@@ -2048,6 +2050,8 @@ class TableAiAdapter extends BaseAiAdapter {
2048
2050
  useWhen: [
2049
2051
  'The user asks how the current table is configured or connected.',
2050
2052
  'The user asks which resourcePath, endpoint, schema fields, capabilities, styling options, or computed-column patterns are available.',
2053
+ 'The user asks which row buttons, row options, or per-record actions can be added or are available, without asking to apply the change now.',
2054
+ 'The user asks which toolbar actions, global actions, route buttons, bulk actions, or table action buttons can be added, without asking to apply the change now.',
2051
2055
  'The user asks for an explanation, documentation-style answer, or how-to guidance without requesting an immediate change.',
2052
2056
  ],
2053
2057
  rules: [
@@ -2064,6 +2068,9 @@ class TableAiAdapter extends BaseAiAdapter {
2064
2068
  'When the user asks how selected records can drive advanced filters or export, bridge the selected records to declared filterFieldCatalog fields and export scopes conceptually; ask for clarification when the shared property or export scope is ambiguous.',
2065
2069
  'For ambiguous selected-record bridge requests that can become a real table operation, prefer type "clarification" with concise user-facing options grounded in filterFieldCatalog labels or export scopes; do not answer with a long documentation-style explanation.',
2066
2070
  'Keep selected-record bridge responses human-facing: mention selected record count and meaningful labels, but do not expose raw ids, endpoint paths, operationIds, internal field names, schema keys, or payload examples unless the user explicitly asks for technical details.',
2071
+ 'When the user asks which row buttons or per-record actions can be added, answer from declared recordSurfaces and capability labels as guidance; do not emit rowAction.add until the user explicitly asks to add, create, or apply one.',
2072
+ 'When the user asks which toolbar, global, route, or bulk actions can be added, answer from globalActionCatalog, navigationDestinations, and table action capability labels as guidance; do not emit toolbar.action.add, rowAction.add, or bulkAction.add until the user explicitly asks to add, create, or apply one.',
2073
+ 'When navigationDestinations exists and the user asks which route or navigation buttons can be added, use its human-facing labels, descriptions, and paths as the declared destination catalog.',
2067
2074
  'For how-to or documentation-style turns, explain the governed operation shape and give a safe example instead of collecting missing edit parameters.',
2068
2075
  'Do not return clarification for missing target fields, labels, formats, colors, conditions, or columns unless the selected response mode is edit/componentEditPlan.',
2069
2076
  'Only produce componentEditPlan when the user asks to apply or materialize a table change.',
@@ -2077,9 +2084,16 @@ class TableAiAdapter extends BaseAiAdapter {
2077
2084
  'The user asks to change table configuration, visual rules, renderers, columns, behavior, actions, or appearance.',
2078
2085
  ],
2079
2086
  rules: [
2087
+ 'Do not use rowAction.add for capability-discovery questions such as which row buttons or actions can be added; those belong to consult mode until the user explicitly asks to add one.',
2088
+ 'Do not use toolbar.action.add or bulkAction.add for capability-discovery questions such as which global actions, toolbar buttons, route buttons, or bulk buttons can be added; those belong to consult mode until the user explicitly asks to add one.',
2080
2089
  'When the user asks to add a row button, row option, or action in each row for a declared record surface, use rowAction.add with capabilityPath "actions.row.actions[]".',
2081
2090
  'For a rowAction.add that opens a declared record surface, set action id/label for the row button and preserve the declared surface under value.recordSurface; never overwrite the canonical recordSurface.id with the row action id.',
2082
2091
  'Use human-facing labels from recordSurfaces for row action labels; do not ask for technical fields such as surface to open, button label, or placement in row when the conversation already grounded one declared surface.',
2092
+ 'When the user explicitly asks to add a global action button in the table toolbar, use toolbar.action.add with capabilityPath "toolbar.actions[]".',
2093
+ 'When the user explicitly asks to add a global action for selected rows or batch operation, use bulkAction.add with capabilityPath "actions.bulk.actions[]".',
2094
+ 'When the user explicitly asks for a bulk action to open an internal route and provides the route path, use bulkAction.add with globalAction.actionId "navigation.openRoute" and globalAction.payload { path, query: { ids: "${runtime.selectedIds}" } }; do not ask for recordIdParamName, target, or output format.',
2095
+ 'For navigation.openRoute requests, ground payload.path in consultativeContext.navigationDestinations.destinations[].path when navigationDestinations exists; if the user asks for a route not declared there, ask a concise confirmation or clarification instead of claiming the route is available.',
2096
+ 'Choose action ids from consultativeContext.globalActionCatalog.actions[].id. For required payload fields such as navigation.openRoute payload.path, ask a concise clarification only when the user did not provide a value.',
2083
2097
  ],
2084
2098
  },
2085
2099
  {
@@ -2113,6 +2127,8 @@ class TableAiAdapter extends BaseAiAdapter {
2113
2127
  ...(resourceCapabilities ? { resourceCapabilities } : {}),
2114
2128
  ...(selectedRowsContext ? { selectedRecordsContext: selectedRowsContext } : {}),
2115
2129
  ...(recordSurfaces ? { recordSurfaces } : {}),
2130
+ ...(navigationDestinations ? { navigationDestinations } : {}),
2131
+ globalActionCatalog,
2116
2132
  answerableQuestionKinds: [
2117
2133
  'current-resource-path',
2118
2134
  'current-endpoint',
@@ -2120,6 +2136,11 @@ class TableAiAdapter extends BaseAiAdapter {
2120
2136
  'selected-records',
2121
2137
  'selection-derived-filter-candidates',
2122
2138
  'record-related-surfaces',
2139
+ 'table-global-actions',
2140
+ 'navigation-destinations',
2141
+ 'toolbar-actions',
2142
+ 'row-actions',
2143
+ 'bulk-actions',
2123
2144
  'selection-derived-export-scope',
2124
2145
  'styling-capabilities',
2125
2146
  'conditional-renderers',
@@ -2145,6 +2166,10 @@ class TableAiAdapter extends BaseAiAdapter {
2145
2166
  'For column.order.set, use a zero-based visual index from currentStateDigest.columnOrder; when the user says after a column, use that column index + 1, and when the user says before a column, use that column index.',
2146
2167
  'Use Json Logic objects for computed expressions and conditional rules.',
2147
2168
  'For selected-record bridge requests, configure available table capabilities such as filter.advanced.configure, filter.advanced.fields.add, toolbar.action.add, or export.configure; do not invent a runtime apply-filter or run-export operation unless it is declared in the contract.',
2169
+ 'For action authoring requests, use consultativeContext.globalActionCatalog as the canonical action catalog; choose toolbar.action.add for toolbar buttons, rowAction.add for per-record buttons, and bulkAction.add for selected-row/batch buttons.',
2170
+ 'For global actions with payloadSchema.required fields, populate the structured globalAction.payload only from user-provided values, declared surfaces, or runtime context templates; ask clarification when required payload cannot be grounded.',
2171
+ 'For bulk route actions over selected rows, the canonical selected-id template is "${runtime.selectedIds}" and the human-facing default is to send those IDs in query.ids when the user already provided the route path.',
2172
+ 'When materializing a global action, preserve both value.globalAction and an effects[] entry with kind "global-action" when the operation supports effects.',
2148
2173
  'Do not invent fields, operationIds, changeKinds, capabilityPaths, formats, badge variants, or colors outside the provided contract.',
2149
2174
  ],
2150
2175
  operationRegistryCoverage: TABLE_AUTHORING_REGISTRY_COVERAGE,
@@ -2185,6 +2210,64 @@ class TableAiAdapter extends BaseAiAdapter {
2185
2210
  ? format
2186
2211
  : null;
2187
2212
  }
2213
+ getGlobalActionAuthoringCatalog() {
2214
+ return {
2215
+ source: 'praxis-global-action-catalog',
2216
+ surfaces: ['toolbar.actions[]', 'actions.row.actions[]', 'actions.bulk.actions[]'],
2217
+ actions: PRAXIS_GLOBAL_ACTION_CATALOG.map((entry) => this.sanitizeGlobalActionCatalogEntry(entry)),
2218
+ };
2219
+ }
2220
+ getNavigationDestinationAuthoringContext() {
2221
+ const context = this.table.aiContext?.navigationDestinations;
2222
+ if (!context || typeof context !== 'object')
2223
+ return null;
2224
+ const destinations = Array.isArray(context.destinations) ? context.destinations : [];
2225
+ const sanitized = destinations
2226
+ .map((destination) => this.sanitizeNavigationDestination(destination))
2227
+ .filter((destination) => !!destination);
2228
+ if (!sanitized.length)
2229
+ return null;
2230
+ return {
2231
+ source: context.source || 'host-ai-context',
2232
+ destinations: sanitized,
2233
+ };
2234
+ }
2235
+ sanitizeNavigationDestination(value) {
2236
+ const destination = this.toRecord(value);
2237
+ if (!destination)
2238
+ return null;
2239
+ const path = this.stringValue(destination['path']);
2240
+ if (!path)
2241
+ return null;
2242
+ const tags = this.compactStringArray(destination['tags']);
2243
+ return {
2244
+ path,
2245
+ ...(this.stringValue(destination['id']) ? { id: this.stringValue(destination['id']) } : {}),
2246
+ ...(this.stringValue(destination['label']) ? { label: this.stringValue(destination['label']) } : {}),
2247
+ ...(this.stringValue(destination['description']) ? { description: this.stringValue(destination['description']) } : {}),
2248
+ ...(this.stringValue(destination['source']) ? { source: this.stringValue(destination['source']) } : {}),
2249
+ ...(tags.length ? { tags } : {}),
2250
+ ...(typeof destination['materialized'] === 'boolean' ? { materialized: destination['materialized'] } : {}),
2251
+ };
2252
+ }
2253
+ sanitizeGlobalActionCatalogEntry(entry) {
2254
+ const payloadSchema = entry.payloadSchema
2255
+ ? {
2256
+ type: entry.payloadSchema.type,
2257
+ required: Array.isArray(entry.payloadSchema.required) ? [...entry.payloadSchema.required] : [],
2258
+ properties: entry.payloadSchema.properties ?? {},
2259
+ ...(entry.payloadSchema.example !== undefined ? { example: entry.payloadSchema.example } : {}),
2260
+ }
2261
+ : undefined;
2262
+ return {
2263
+ id: entry.id,
2264
+ label: entry.label,
2265
+ ...(entry.description ? { description: entry.description } : {}),
2266
+ ...(entry.icon ? { icon: entry.icon } : {}),
2267
+ ...(payloadSchema ? { payloadSchema } : {}),
2268
+ ...(entry.param ? { param: entry.param } : {}),
2269
+ };
2270
+ }
2188
2271
  getSelectedRowsAuthoringContext() {
2189
2272
  try {
2190
2273
  const selection = this.table.getAiAssistantSelectedRowsContext?.();
@@ -1 +1 @@
1
- export { A as AnalyticsTableConfigAdapterService, a as AnalyticsTableContractService, b as AnalyticsTableStatsApiService, B as BOOLEAN_PRESETS, c as BehaviorConfigEditorComponent, C as CURRENCY_PRESETS, d as ColumnsConfigEditorComponent, D as DATE_PRESETS, e as DataFormatterComponent, f as DataFormattingService, F as FORMULA_TEMPLATES, g as FilterConfigService, h as FilterSettingsComponent, i as FormulaGeneratorService, J as JsonConfigEditorComponent, M as MessagesLocalizationEditorComponent, N as NUMBER_PRESETS, P as PERCENTAGE_PRESETS, j as PRAXIS_FILTER_COMPONENT_METADATA, k as PRAXIS_TABLE_AUTHORING_MANIFEST, l as PRAXIS_TABLE_COMPONENT_METADATA, m as PraxisFilter, n as PraxisFilterWidgetConfigEditor, o as PraxisTable, p as PraxisTableConfigEditor, q as PraxisTableInlineAuthoringEditorComponent, r as PraxisTableToolbar, s as PraxisTableWidgetConfigEditor, S as STRING_PRESETS, T as TABLE_AI_CAPABILITIES, t as TABLE_COMPONENT_AI_CAPABILITIES, u as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, v as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, w as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, x as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, y as TABLE_COMPONENT_EDIT_PLAN_KIND, E as TABLE_COMPONENT_EDIT_PLAN_VERSION, G as TASK_PRESETS, H as TableDefaultsProvider, I as TableRulesEditorComponent, K as ToolbarActionsEditorComponent, V as ValueMappingEditorComponent, L as VisualFormulaBuilderComponent, O as buildTableApplyPlan, Q as coerceTableComponentEditPlan, R as coerceTableComponentEditPlans, U as compileTableComponentEditPlan, W as compileTableComponentEditPlans, X as createTableAuthoringDocument, Y as getActionId, Z as getEnum, _ as getTableCapabilities, $ as getTableComponentEditPlanCapabilities, a0 as isTableRendererSupportedByRichContentP0, a1 as mapTableRendererToRichContentP0, a2 as normalizeTableAuthoringDocument, a3 as parseLegacyOrTableDocument, a4 as providePraxisFilterMetadata, a5 as providePraxisTableMetadata, a6 as serializeTableAuthoringDocument, a7 as toCanonicalTableConfig, a8 as validateTableAuthoringDocument } from './praxisui-table-praxisui-table-28INRbt6.mjs';
1
+ export { A as AnalyticsTableConfigAdapterService, a as AnalyticsTableContractService, b as AnalyticsTableStatsApiService, B as BOOLEAN_PRESETS, c as BehaviorConfigEditorComponent, C as CURRENCY_PRESETS, d as ColumnsConfigEditorComponent, D as DATE_PRESETS, e as DataFormatterComponent, f as DataFormattingService, F as FORMULA_TEMPLATES, g as FilterConfigService, h as FilterSettingsComponent, i as FormulaGeneratorService, J as JsonConfigEditorComponent, M as MessagesLocalizationEditorComponent, N as NUMBER_PRESETS, P as PERCENTAGE_PRESETS, j as PRAXIS_FILTER_COMPONENT_METADATA, k as PRAXIS_TABLE_AUTHORING_MANIFEST, l as PRAXIS_TABLE_COMPONENT_METADATA, m as PraxisFilter, n as PraxisFilterWidgetConfigEditor, o as PraxisTable, p as PraxisTableConfigEditor, q as PraxisTableInlineAuthoringEditorComponent, r as PraxisTableToolbar, s as PraxisTableWidgetConfigEditor, S as STRING_PRESETS, T as TABLE_AI_CAPABILITIES, t as TABLE_COMPONENT_AI_CAPABILITIES, u as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, v as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, w as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, x as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, y as TABLE_COMPONENT_EDIT_PLAN_KIND, E as TABLE_COMPONENT_EDIT_PLAN_VERSION, G as TASK_PRESETS, H as TableDefaultsProvider, I as TableRulesEditorComponent, K as ToolbarActionsEditorComponent, V as ValueMappingEditorComponent, L as VisualFormulaBuilderComponent, O as buildTableApplyPlan, Q as coerceTableComponentEditPlan, R as coerceTableComponentEditPlans, U as compileTableComponentEditPlan, W as compileTableComponentEditPlans, X as createTableAuthoringDocument, Y as getActionId, Z as getEnum, _ as getTableCapabilities, $ as getTableComponentEditPlanCapabilities, a0 as isTableRendererSupportedByRichContentP0, a1 as mapTableRendererToRichContentP0, a2 as normalizeTableAuthoringDocument, a3 as parseLegacyOrTableDocument, a4 as providePraxisFilterMetadata, a5 as providePraxisTableMetadata, a6 as serializeTableAuthoringDocument, a7 as toCanonicalTableConfig, a8 as validateTableAuthoringDocument } from './praxisui-table-praxisui-table-mlOL4l4b.mjs';
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@praxisui/table",
3
- "version": "8.0.0-beta.82",
3
+ "version": "8.0.0-beta.84",
4
4
  "description": "Advanced data table for Angular (Praxis UI) with editing, filtering, sorting, virtualization, and settings panel integration.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
- "@praxisui/ai": "^8.0.0-beta.82",
9
- "@praxisui/core": "^8.0.0-beta.82",
10
- "@praxisui/dynamic-fields": "^8.0.0-beta.82",
11
- "@praxisui/dynamic-form": "^8.0.0-beta.82",
12
- "@praxisui/metadata-editor": "^8.0.0-beta.82",
13
- "@praxisui/rich-content": "^8.0.0-beta.82",
14
- "@praxisui/settings-panel": "^8.0.0-beta.82",
15
- "@praxisui/table-rule-builder": "^8.0.0-beta.82",
8
+ "@praxisui/ai": "^8.0.0-beta.84",
9
+ "@praxisui/core": "^8.0.0-beta.84",
10
+ "@praxisui/dynamic-fields": "^8.0.0-beta.84",
11
+ "@praxisui/dynamic-form": "^8.0.0-beta.84",
12
+ "@praxisui/metadata-editor": "^8.0.0-beta.84",
13
+ "@praxisui/rich-content": "^8.0.0-beta.84",
14
+ "@praxisui/settings-panel": "^8.0.0-beta.84",
15
+ "@praxisui/table-rule-builder": "^8.0.0-beta.84",
16
16
  "@angular/cdk": "^21.0.0",
17
17
  "@angular/forms": "^21.0.0",
18
18
  "@angular/material": "^21.0.0",
19
19
  "@angular/router": "^21.0.0",
20
- "@praxisui/dialog": "^8.0.0-beta.82",
20
+ "@praxisui/dialog": "^8.0.0-beta.84",
21
21
  "rxjs": "~7.8.0"
22
22
  },
23
23
  "dependencies": {
@@ -830,6 +830,23 @@ declare class AnalyticsTableStatsApiService {
830
830
  static ɵprov: i0.ɵɵInjectableDeclaration<AnalyticsTableStatsApiService>;
831
831
  }
832
832
 
833
+ interface TableAiNavigationDestinationContext {
834
+ id?: string;
835
+ path: string;
836
+ label?: string;
837
+ description?: string;
838
+ source?: string;
839
+ tags?: string[];
840
+ materialized?: boolean;
841
+ }
842
+ interface TableAiNavigationContextPack {
843
+ source?: string;
844
+ destinations: TableAiNavigationDestinationContext[];
845
+ }
846
+ interface TableAiContext {
847
+ recordSurfaces?: RecordRelatedSurfaceContextPack | null;
848
+ navigationDestinations?: TableAiNavigationContextPack | null;
849
+ }
833
850
  type SchemaFieldHint = {
834
851
  name: string;
835
852
  label?: string;
@@ -986,9 +1003,7 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterCont
986
1003
  crudContext: any;
987
1004
  filterCriteria: Record<string, any>;
988
1005
  queryContext: PraxisDataQueryContextBridge | null;
989
- aiContext: {
990
- recordSurfaces?: RecordRelatedSurfaceContextPack | null;
991
- } | null;
1006
+ aiContext: TableAiContext | null;
992
1007
  advancedFilterValue: Record<string, any>;
993
1008
  advancedFilterRuntimeVisibleFields: string[];
994
1009
  private advancedFilterAlwaysVisibleCacheKey;
@@ -1194,6 +1209,7 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterCont
1194
1209
  private ensureAiAssistantRowCapabilitySnapshot;
1195
1210
  private buildCapabilitySnapshotFromSurfaceCatalog;
1196
1211
  private buildAiAssistantResourceSurfaceContexts;
1212
+ private getAiAssistantRecordSurfaceProbeRows;
1197
1213
  private buildRecordRelatedSurfaceContextFromResourceSurface;
1198
1214
  private humanizeResourceSurfaceLabel;
1199
1215
  aiAdapter: any;
@@ -4103,9 +4119,9 @@ type ComponentEditPlanCapability = {
4103
4119
  declare const TABLE_COMPONENT_EDIT_PLAN_KIND = "praxis.table.component-edit-plan";
4104
4120
  declare const TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND = "praxis.table.component-edit-plan.batch";
4105
4121
  declare const TABLE_COMPONENT_EDIT_PLAN_VERSION = "1.0";
4106
- type TableComponentEditChangeKind = 'add_column' | 'set_column_format' | 'set_column_header' | 'set_column_visibility' | 'set_column_filterable' | 'set_column_sortable' | 'set_column_width' | 'set_column_order' | 'set_column_align' | 'set_column_style' | 'set_column_header_style' | 'set_column_sticky' | 'set_column_conditional_style' | 'set_row_conditional_style' | 'set_column_computed' | 'set_column_value_mapping' | 'set_column_renderer' | 'set_column_badge_renderer' | 'set_column_conditional_badge_renderers' | 'set_row_conditional_renderer' | 'configure_table_filtering' | 'configure_advanced_filters' | 'add_advanced_filter_fields' | 'remove_advanced_filter_fields' | 'configure_table_pagination' | 'configure_table_selection' | 'configure_table_sorting' | 'configure_toolbar' | 'add_toolbar_action' | 'add_row_action' | 'configure_export' | 'set_table_density' | 'set_toolbar_visibility';
4107
- type TableComponentEditOperationId = 'column.add' | 'column.format.set' | 'column.header.set' | 'column.visibility.set' | 'column.filterable.set' | 'column.sortable.set' | 'column.width.set' | 'column.order.set' | 'column.align.set' | 'column.style.set' | 'column.headerStyle.set' | 'column.sticky.set' | 'column.renderer.set' | 'column.valueMapping.set' | 'column.conditionalStyle.add' | 'row.styleRule.add' | 'column.conditionalRenderer.add' | 'column.computed.add' | 'row.conditionalRenderer.add' | 'behavior.filtering.configure' | 'filter.advanced.configure' | 'filter.advanced.fields.add' | 'filter.advanced.fields.remove' | 'behavior.pagination.configure' | 'behavior.selection.configure' | 'behavior.sorting.configure' | 'toolbar.configure' | 'toolbar.action.add' | 'rowAction.add' | 'export.configure' | 'appearance.density.set' | 'toolbar.visibility.set';
4108
- declare const TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS: readonly ["add_column", "set_column_format", "set_column_header", "set_column_visibility", "set_column_filterable", "set_column_sortable", "set_column_width", "set_column_order", "set_column_align", "set_column_style", "set_column_header_style", "set_column_sticky", "set_column_conditional_style", "set_row_conditional_style", "set_column_computed", "set_column_value_mapping", "set_column_renderer", "set_column_badge_renderer", "set_column_conditional_badge_renderers", "set_row_conditional_renderer", "configure_table_filtering", "configure_advanced_filters", "add_advanced_filter_fields", "remove_advanced_filter_fields", "configure_table_pagination", "configure_table_selection", "configure_table_sorting", "configure_toolbar", "add_toolbar_action", "add_row_action", "configure_export", "set_table_density", "set_toolbar_visibility"];
4122
+ type TableComponentEditChangeKind = 'add_column' | 'set_column_format' | 'set_column_header' | 'set_column_visibility' | 'set_column_filterable' | 'set_column_sortable' | 'set_column_width' | 'set_column_order' | 'set_column_align' | 'set_column_style' | 'set_column_header_style' | 'set_column_sticky' | 'set_column_conditional_style' | 'set_row_conditional_style' | 'set_column_computed' | 'set_column_value_mapping' | 'set_column_renderer' | 'set_column_badge_renderer' | 'set_column_conditional_badge_renderers' | 'set_row_conditional_renderer' | 'configure_table_filtering' | 'configure_advanced_filters' | 'add_advanced_filter_fields' | 'remove_advanced_filter_fields' | 'configure_table_pagination' | 'configure_table_selection' | 'configure_table_sorting' | 'configure_toolbar' | 'add_toolbar_action' | 'add_row_action' | 'add_bulk_action' | 'configure_export' | 'set_table_density' | 'set_toolbar_visibility';
4123
+ type TableComponentEditOperationId = 'column.add' | 'column.format.set' | 'column.header.set' | 'column.visibility.set' | 'column.filterable.set' | 'column.sortable.set' | 'column.width.set' | 'column.order.set' | 'column.align.set' | 'column.style.set' | 'column.headerStyle.set' | 'column.sticky.set' | 'column.renderer.set' | 'column.valueMapping.set' | 'column.conditionalStyle.add' | 'row.styleRule.add' | 'column.conditionalRenderer.add' | 'column.computed.add' | 'row.conditionalRenderer.add' | 'behavior.filtering.configure' | 'filter.advanced.configure' | 'filter.advanced.fields.add' | 'filter.advanced.fields.remove' | 'behavior.pagination.configure' | 'behavior.selection.configure' | 'behavior.sorting.configure' | 'toolbar.configure' | 'toolbar.action.add' | 'rowAction.add' | 'bulkAction.add' | 'export.configure' | 'appearance.density.set' | 'toolbar.visibility.set';
4124
+ declare const TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS: readonly ["add_column", "set_column_format", "set_column_header", "set_column_visibility", "set_column_filterable", "set_column_sortable", "set_column_width", "set_column_order", "set_column_align", "set_column_style", "set_column_header_style", "set_column_sticky", "set_column_conditional_style", "set_row_conditional_style", "set_column_computed", "set_column_value_mapping", "set_column_renderer", "set_column_badge_renderer", "set_column_conditional_badge_renderers", "set_row_conditional_renderer", "configure_table_filtering", "configure_advanced_filters", "add_advanced_filter_fields", "remove_advanced_filter_fields", "configure_table_pagination", "configure_table_selection", "configure_table_sorting", "configure_toolbar", "add_toolbar_action", "add_row_action", "add_bulk_action", "configure_export", "set_table_density", "set_toolbar_visibility"];
4109
4125
  declare const TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS: Record<TableComponentEditChangeKind, string>;
4110
4126
  interface TableComponentEditPlan {
4111
4127
  kind?: typeof TABLE_COMPONENT_EDIT_PLAN_KIND;
@@ -4147,7 +4163,7 @@ declare const TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA: {
4147
4163
  readonly $defs: {
4148
4164
  readonly changeKind: {
4149
4165
  readonly type: "string";
4150
- readonly enum: readonly ["add_column", "set_column_format", "set_column_header", "set_column_visibility", "set_column_filterable", "set_column_sortable", "set_column_width", "set_column_order", "set_column_align", "set_column_style", "set_column_header_style", "set_column_sticky", "set_column_conditional_style", "set_row_conditional_style", "set_column_computed", "set_column_value_mapping", "set_column_renderer", "set_column_badge_renderer", "set_column_conditional_badge_renderers", "set_row_conditional_renderer", "configure_table_filtering", "configure_advanced_filters", "add_advanced_filter_fields", "remove_advanced_filter_fields", "configure_table_pagination", "configure_table_selection", "configure_table_sorting", "configure_toolbar", "add_toolbar_action", "add_row_action", "configure_export", "set_table_density", "set_toolbar_visibility"];
4166
+ readonly enum: readonly ["add_column", "set_column_format", "set_column_header", "set_column_visibility", "set_column_filterable", "set_column_sortable", "set_column_width", "set_column_order", "set_column_align", "set_column_style", "set_column_header_style", "set_column_sticky", "set_column_conditional_style", "set_row_conditional_style", "set_column_computed", "set_column_value_mapping", "set_column_renderer", "set_column_badge_renderer", "set_column_conditional_badge_renderers", "set_row_conditional_renderer", "configure_table_filtering", "configure_advanced_filters", "add_advanced_filter_fields", "remove_advanced_filter_fields", "configure_table_pagination", "configure_table_selection", "configure_table_sorting", "configure_toolbar", "add_toolbar_action", "add_row_action", "add_bulk_action", "configure_export", "set_table_density", "set_toolbar_visibility"];
4151
4167
  };
4152
4168
  readonly capabilityPath: {
4153
4169
  readonly type: "string";
@@ -4228,7 +4244,7 @@ declare const TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA: {
4228
4244
  readonly const: "praxis-table";
4229
4245
  };
4230
4246
  readonly operationId: {
4231
- readonly enum: readonly ["column.add", "column.format.set", "column.header.set", "column.visibility.set", "column.filterable.set", "column.sortable.set", "column.width.set", "column.order.set", "column.align.set", "column.style.set", "column.headerStyle.set", "column.sticky.set", "column.renderer.set", "column.valueMapping.set", "column.conditionalStyle.add", "row.styleRule.add", "column.conditionalRenderer.add", "column.computed.add", "row.conditionalRenderer.add", "behavior.filtering.configure", "filter.advanced.configure", "filter.advanced.fields.add", "filter.advanced.fields.remove", "behavior.pagination.configure", "behavior.selection.configure", "behavior.sorting.configure", "toolbar.configure", "toolbar.action.add", "rowAction.add", "export.configure", "appearance.density.set", "toolbar.visibility.set"];
4247
+ readonly enum: readonly ["column.add", "column.format.set", "column.header.set", "column.visibility.set", "column.filterable.set", "column.sortable.set", "column.width.set", "column.order.set", "column.align.set", "column.style.set", "column.headerStyle.set", "column.sticky.set", "column.renderer.set", "column.valueMapping.set", "column.conditionalStyle.add", "row.styleRule.add", "column.conditionalRenderer.add", "column.computed.add", "row.conditionalRenderer.add", "behavior.filtering.configure", "filter.advanced.configure", "filter.advanced.fields.add", "filter.advanced.fields.remove", "behavior.pagination.configure", "behavior.selection.configure", "behavior.sorting.configure", "toolbar.configure", "toolbar.action.add", "rowAction.add", "bulkAction.add", "export.configure", "appearance.density.set", "toolbar.visibility.set"];
4232
4248
  };
4233
4249
  readonly target: true;
4234
4250
  readonly input: true;
@@ -4424,4 +4440,4 @@ declare function compileTableComponentEditPlans(plans: TableComponentEditPlan[],
4424
4440
  declare function compileTableComponentEditPlan(plan: TableComponentEditPlan, currentConfig: TableConfig): TableComponentEditPlanCompileResult;
4425
4441
 
4426
4442
  export { AnalyticsTableConfigAdapterService, AnalyticsTableContractService, AnalyticsTableStatsApiService, BOOLEAN_PRESETS, BehaviorConfigEditorComponent, CURRENCY_PRESETS, ColumnsConfigEditorComponent, DATE_PRESETS, DataFormatterComponent, DataFormattingService, FORMULA_TEMPLATES, FilterConfigService, FilterSettingsComponent, FormulaGeneratorService, JsonConfigEditorComponent, MessagesLocalizationEditorComponent, NUMBER_PRESETS, PERCENTAGE_PRESETS, PRAXIS_FILTER_COMPONENT_METADATA, PRAXIS_TABLE_AUTHORING_MANIFEST, PRAXIS_TABLE_COMPONENT_METADATA, PraxisFilter, PraxisFilterWidgetConfigEditor, PraxisTable, PraxisTableConfigEditor, PraxisTableInlineAuthoringEditorComponent, PraxisTableToolbar, PraxisTableWidgetConfigEditor, STRING_PRESETS, TABLE_AI_CAPABILITIES, TABLE_COMPONENT_AI_CAPABILITIES, TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, TABLE_COMPONENT_EDIT_PLAN_KIND, TABLE_COMPONENT_EDIT_PLAN_VERSION, TASK_PRESETS, TableDefaultsProvider, TableRulesEditorComponent, ToolbarActionsEditorComponent, ValueMappingEditorComponent, VisualFormulaBuilderComponent, buildTableApplyPlan, coerceTableComponentEditPlan, coerceTableComponentEditPlans, compileTableComponentEditPlan, compileTableComponentEditPlans, createTableAuthoringDocument, getActionId, getEnum, getTableCapabilities, getTableComponentEditPlanCapabilities, isTableRendererSupportedByRichContentP0, mapTableRendererToRichContentP0, normalizeTableAuthoringDocument, parseLegacyOrTableDocument, providePraxisFilterMetadata, providePraxisTableMetadata, serializeTableAuthoringDocument, toCanonicalTableConfig, validateTableAuthoringDocument };
4427
- export type { ActionLike, AnalyticsTableConfigAdapterOptions, AnalyticsTableContractDefinition, AnalyticsTableContractLoadOptions, AnalyticsTableContractLoadResult, AnalyticsTableContractSource, AnalyticsTableRow, AnalyticsTableViewModel, ArithmeticParams, BehaviorConfigChange, BooleanFormatterOptions, BulkAction, Capability$1 as Capability, CapabilityCatalog$1 as CapabilityCatalog, CapabilityCategory$1 as CapabilityCategory, ColumnChange, ColumnDataType$1 as ColumnDataType, ConcatenationParams, ConditionalMappingParams, CurrencyFormatterOptions, DataFormattingOptions, DataMode, DateFormatterOptions, DefaultValueParams, EditorDiagnostic, EditorDocument, FieldSchema, FilterConfig, FilterTag, FormatPreset, FormatterConfig, FormulaDefinition, FormulaParameterSchema, FormulaParams, FormulaTemplate, FormulaType, I18n, JsonEditorEvent, JsonValidationResult, MessagesLocalizationChange, NestedPropertyParams, NumberFormatterOptions, PercentageFormatterOptions, PraxisFilterWidgetEditorInputs, PraxisFilterWidgetEditorValue, PraxisTableWidgetEditorInputs, PraxisTableWidgetEditorValue, ResourcePathIntent, RowAction, RowExpansionChangeBase, RowExpansionChangeEvent, RowExpansionReasonCode, RowExpansionTrigger, StringFormatterOptions, TableApplyPlan, TableAuthoringDocument, TableBindings, Capability as TableComponentCapability, CapabilityCatalog as TableComponentCapabilityCatalog, CapabilityCategory as TableComponentCapabilityCategory, TableComponentEditChangeKind, TableComponentEditPlan, TableComponentEditPlanCompileResult, ValueKind as TableComponentValueKind, TableHorizontalScroll, TableProjectionContext, TableRichContentP0Node, TableRuntimeContext, TableValidationContext, ToolbarAction, ToolbarActionsChange, ValueKind$1 as ValueKind, ValueMappingPair };
4443
+ export type { ActionLike, AnalyticsTableConfigAdapterOptions, AnalyticsTableContractDefinition, AnalyticsTableContractLoadOptions, AnalyticsTableContractLoadResult, AnalyticsTableContractSource, AnalyticsTableRow, AnalyticsTableViewModel, ArithmeticParams, BehaviorConfigChange, BooleanFormatterOptions, BulkAction, Capability$1 as Capability, CapabilityCatalog$1 as CapabilityCatalog, CapabilityCategory$1 as CapabilityCategory, ColumnChange, ColumnDataType$1 as ColumnDataType, ConcatenationParams, ConditionalMappingParams, CurrencyFormatterOptions, DataFormattingOptions, DataMode, DateFormatterOptions, DefaultValueParams, EditorDiagnostic, EditorDocument, FieldSchema, FilterConfig, FilterTag, FormatPreset, FormatterConfig, FormulaDefinition, FormulaParameterSchema, FormulaParams, FormulaTemplate, FormulaType, I18n, JsonEditorEvent, JsonValidationResult, MessagesLocalizationChange, NestedPropertyParams, NumberFormatterOptions, PercentageFormatterOptions, PraxisFilterWidgetEditorInputs, PraxisFilterWidgetEditorValue, PraxisTableWidgetEditorInputs, PraxisTableWidgetEditorValue, ResourcePathIntent, RowAction, RowExpansionChangeBase, RowExpansionChangeEvent, RowExpansionReasonCode, RowExpansionTrigger, StringFormatterOptions, TableAiContext, TableAiNavigationContextPack, TableAiNavigationDestinationContext, TableApplyPlan, TableAuthoringDocument, TableBindings, Capability as TableComponentCapability, CapabilityCatalog as TableComponentCapabilityCatalog, CapabilityCategory as TableComponentCapabilityCategory, TableComponentEditChangeKind, TableComponentEditPlan, TableComponentEditPlanCompileResult, ValueKind as TableComponentValueKind, TableHorizontalScroll, TableProjectionContext, TableRichContentP0Node, TableRuntimeContext, TableValidationContext, ToolbarAction, ToolbarActionsChange, ValueKind$1 as ValueKind, ValueMappingPair };