@gravitee/ui-policy-studio-angular 16.0.1-apim-11657-adapt-ui-for-llm-a32a07d → 16.0.1-apim-11657-adapt-ui-for-llm-9594da4

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.
@@ -524,12 +524,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImpor
524
524
  * See the License for the specific language governing permissions and
525
525
  * limitations under the License.
526
526
  */
527
- const METHODS_AUTOCOMPLETE = ['ALL', ...HttpMethods];
527
+ const METHODS_AUTOCOMPLETE$1 = ['ALL', ...HttpMethods];
528
528
  class GioPolicyStudioFlowProxyFormDialogComponent {
529
529
  constructor(dialogRef, flowDialogData) {
530
530
  this.dialogRef = dialogRef;
531
531
  this.mode = 'create';
532
- this.methods = METHODS_AUTOCOMPLETE;
532
+ this.methods = METHODS_AUTOCOMPLETE$1;
533
533
  this.existingFlow = cloneDeep(flowDialogData?.flow);
534
534
  this.mode = this.existingFlow ? 'edit' : 'create';
535
535
  const httpSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'HTTP');
@@ -537,8 +537,8 @@ class GioPolicyStudioFlowProxyFormDialogComponent {
537
537
  this.flowFormGroup = new UntypedFormGroup({
538
538
  name: new UntypedFormControl(flowDialogData?.flow?.name ?? ''),
539
539
  pathOperator: new UntypedFormControl(httpSelector?.pathOperator ?? 'EQUALS'),
540
- path: new UntypedFormControl(sanitizePathFormValue(httpSelector?.path)),
541
- methods: new UntypedFormControl(sanitizeMethodFormValue(httpSelector?.methods)),
540
+ path: new UntypedFormControl(sanitizePathFormValue$1(httpSelector?.path)),
541
+ methods: new UntypedFormControl(sanitizeMethodFormValue$1(httpSelector?.methods)),
542
542
  condition: new UntypedFormControl(conditionSelector?.condition ?? ''),
543
543
  });
544
544
  }
@@ -547,7 +547,7 @@ class GioPolicyStudioFlowProxyFormDialogComponent {
547
547
  type: 'HTTP',
548
548
  path: sanitizePath(this.flowFormGroup?.get('path')?.value),
549
549
  pathOperator: this.flowFormGroup?.get('pathOperator')?.value,
550
- methods: sanitizeMethods(this.flowFormGroup?.get('methods')?.value),
550
+ methods: sanitizeMethods$1(this.flowFormGroup?.get('methods')?.value),
551
551
  };
552
552
  const conditionValue = this.flowFormGroup?.get('condition')?.value;
553
553
  const conditionSelectorToSave = conditionValue
@@ -573,7 +573,7 @@ class GioPolicyStudioFlowProxyFormDialogComponent {
573
573
  });
574
574
  }
575
575
  tagValidationHook(tag, validationCb) {
576
- validationCb(METHODS_AUTOCOMPLETE.map(m => `${m}`).includes(tag.toUpperCase()));
576
+ validationCb(METHODS_AUTOCOMPLETE$1.map(m => `${m}`).includes(tag.toUpperCase()));
577
577
  }
578
578
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: GioPolicyStudioFlowProxyFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
579
579
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: GioPolicyStudioFlowProxyFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-proxy-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2025 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n@if (flowFormGroup) {\n <mat-dialog-content class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>\n Flows allow you to apply different policies per HTTP path and/or method. For example you can reroute calls based on the URL specified.\n </p>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with path and method if left blank</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"pathOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Path operator</mat-hint>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <span matTextPrefix>/&nbsp;</span>\n <input matInput formControlName=\"path\" />\n <mat-hint>Path</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n <gio-el-assistant matSuffix />\n </mat-form-field>\n </div>\n </mat-dialog-content>\n}\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }, { kind: "component", type: i7.GioFormTagsInputComponent, selector: "gio-form-tags-input", inputs: ["aria-label", "addOnBlur", "tagValidationHook", "autocompleteOptions", "displayValueWith", "useAutocompleteOptionValueOnly", "placeholder", "required", "disabled"], outputs: ["tagClicked"] }, { kind: "component", type: GioElAssistantComponent, selector: "gio-el-assistant" }] }); }
@@ -598,12 +598,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImpor
598
598
  type: Inject,
599
599
  args: [MAT_DIALOG_DATA]
600
600
  }] }] });
601
- const sanitizeMethods = (value) => {
601
+ const sanitizeMethods$1 = (value) => {
602
602
  if (!value || value.find(m => m === 'ALL'))
603
603
  return [];
604
604
  return value;
605
605
  };
606
- const sanitizeMethodFormValue = (methods) => {
606
+ const sanitizeMethodFormValue$1 = (methods) => {
607
607
  if (!methods || methods.length === 0)
608
608
  return ['ALL'];
609
609
  return methods;
@@ -614,7 +614,7 @@ const sanitizePath = (path) => {
614
614
  }
615
615
  return path;
616
616
  };
617
- const sanitizePathFormValue = (path) => {
617
+ const sanitizePathFormValue$1 = (path) => {
618
618
  if (path && path.startsWith('/')) {
619
619
  return path.substring(1);
620
620
  }
@@ -790,88 +790,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImpor
790
790
  * See the License for the specific language governing permissions and
791
791
  * limitations under the License.
792
792
  */
793
- const LLM_METHODS = [
794
- {
795
- groupLabel: 'Lifecycle Methods',
796
- groupOptions: [
797
- { value: 'initialize', label: 'initialize' },
798
- { value: 'notifications/initialized', label: 'notifications/initialized' },
799
- { value: 'ping', label: 'ping' },
800
- { value: 'notifications/progress', label: 'notifications/progress' },
801
- ],
802
- },
803
- {
804
- groupLabel: 'Tool Methods',
805
- groupOptions: [
806
- { value: 'tools/list', label: 'tools/list' },
807
- { value: 'tools/call', label: 'tools/call' },
808
- { value: 'notifications/tools/list_changed', label: 'notifications/tools/list_changed' },
809
- ],
810
- },
811
- {
812
- groupLabel: 'Resources Methods',
813
- groupOptions: [
814
- { value: 'resources/list', label: 'resources/list' },
815
- { value: 'resources/read', label: 'resources/read' },
816
- { value: 'notifications/resources/list_changed', label: 'notifications/resources/list_changed' },
817
- { value: 'notifications/resources/updated', label: 'notifications/resources/updated' },
818
- { value: 'resources/templates/list', label: 'resources/templates/list' },
819
- { value: 'resources/subscribe', label: 'resources/subscribe' },
820
- { value: 'resources/unsubscribe', label: 'resources/unsubscribe' },
821
- ],
822
- },
823
- {
824
- groupLabel: 'Prompt Methods',
825
- groupOptions: [
826
- { value: 'prompts/list', label: 'prompts/list' },
827
- { value: 'prompts/get', label: 'prompts/get' },
828
- { value: 'notifications/prompts/list_changed', label: 'notifications/prompts/list_changed' },
829
- { value: 'completion/complete', label: 'completion/complete' },
830
- ],
831
- },
832
- {
833
- groupLabel: 'Logging Methods',
834
- groupOptions: [
835
- { value: 'logging/setLevel', label: 'logging/setLevel' },
836
- { value: 'notifications/message', label: 'notifications/message' },
837
- ],
838
- },
839
- {
840
- groupLabel: 'Roots Methods',
841
- groupOptions: [
842
- { value: 'roots/list', label: 'roots/list' },
843
- { value: 'notifications/roots/list_changed', label: 'notifications/roots/list_changed' },
844
- ],
845
- },
846
- {
847
- groupLabel: 'Sampling Methods',
848
- groupOptions: [{ value: 'sampling/createMessage', label: 'sampling/createMessage' }],
849
- },
850
- {
851
- groupLabel: 'Elicitation Methods',
852
- groupOptions: [{ value: 'elicitation/create', label: 'elicitation/create' }],
853
- },
854
- ];
793
+ const METHODS_AUTOCOMPLETE = ['ALL', ...HttpMethods];
855
794
  class GioPolicyStudioFlowLlmFormDialogComponent {
856
795
  constructor(dialogRef, flowDialogData) {
857
796
  this.dialogRef = dialogRef;
858
797
  this.mode = 'create';
859
- this.methods = LLM_METHODS;
798
+ this.methods = METHODS_AUTOCOMPLETE;
860
799
  this.existingFlow = cloneDeep(flowDialogData?.flow);
861
800
  this.mode = this.existingFlow ? 'edit' : 'create';
862
- const llmSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'LLM');
801
+ const httpSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'HTTP');
863
802
  const conditionSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'CONDITION');
864
- this.flowFormGroup = new FormGroup({
865
- name: new FormControl(flowDialogData?.flow?.name ?? ''),
866
- llmMethods: new FormControl(llmSelector?.methods ?? []),
867
- condition: new FormControl(conditionSelector?.condition ?? ''),
803
+ this.flowFormGroup = new UntypedFormGroup({
804
+ name: new UntypedFormControl(flowDialogData?.flow?.name ?? ''),
805
+ pathOperator: new UntypedFormControl(httpSelector?.pathOperator ?? 'EQUALS'),
806
+ path: new UntypedFormControl(sanitizePathFormValue(httpSelector?.path)),
807
+ methods: new UntypedFormControl(sanitizeMethodFormValue(httpSelector?.methods)),
808
+ condition: new UntypedFormControl(conditionSelector?.condition ?? ''),
868
809
  });
869
810
  this.defaultFlowName = capitalize(flowDialogData.parentGroupName) + ' flow';
870
811
  }
871
812
  onSubmit() {
872
- const llmSelectorToSave = {
873
- type: 'LLM',
874
- methods: this.flowFormGroup?.get('llmMethods')?.value ?? undefined,
813
+ const httpSelectorToSave = {
814
+ type: 'HTTP',
815
+ path: sanitizePath(this.flowFormGroup?.get('path')?.value),
816
+ pathOperator: this.flowFormGroup?.get('pathOperator')?.value,
817
+ methods: sanitizeMethods(this.flowFormGroup?.get('methods')?.value),
875
818
  };
876
819
  const conditionValue = this.flowFormGroup?.get('condition')?.value ?? undefined;
877
820
  const conditionSelectorToSave = conditionValue
@@ -890,7 +833,7 @@ class GioPolicyStudioFlowLlmFormDialogComponent {
890
833
  // Add changes
891
834
  name: this.getFlowName(),
892
835
  enabled: this.existingFlow ? this.existingFlow.enabled : true,
893
- selectors: conditionSelectorToSave ? [llmSelectorToSave, conditionSelectorToSave] : [llmSelectorToSave],
836
+ selectors: conditionSelectorToSave ? [httpSelectorToSave, conditionSelectorToSave] : [httpSelectorToSave],
894
837
  };
895
838
  this.dialogRef.close({
896
839
  ...flowToSave,
@@ -901,12 +844,10 @@ class GioPolicyStudioFlowLlmFormDialogComponent {
901
844
  return isEmpty(inputName) ? this.defaultFlowName : inputName;
902
845
  }
903
846
  tagValidationHook(tag, validationCb) {
904
- validationCb(LLM_METHODS.flatMap(group => group.groupOptions.map(m => m.value))
905
- .map(m => `${m}`)
906
- .includes(tag));
847
+ validationCb(METHODS_AUTOCOMPLETE.map(m => `${m}`).includes(tag.toUpperCase()));
907
848
  }
908
849
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: GioPolicyStudioFlowLlmFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
909
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: GioPolicyStudioFlowLlmFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-llm-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2025 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n@if (flowFormGroup) {\n <mat-dialog-content class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies.</p>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>LLM Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"llmMethods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n <mat-hint>If no method is specified, the flow will match all LLM Methods</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n <gio-el-assistant matSuffix />\n </mat-form-field>\n </div>\n </mat-dialog-content>\n}\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}.title__closeBtn{top:0;right:-24px;float:right}.content__paramTitle{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;color:#5c5959}.content--params{margin-bottom:6px}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row__fullWidth{flex:1 1 auto}.button-with-icon{display:flex;align-items:center;justify-content:space-between}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }, { kind: "component", type: i7.GioFormTagsInputComponent, selector: "gio-form-tags-input", inputs: ["aria-label", "addOnBlur", "tagValidationHook", "autocompleteOptions", "displayValueWith", "useAutocompleteOptionValueOnly", "placeholder", "required", "disabled"], outputs: ["tagClicked"] }, { kind: "component", type: GioElAssistantComponent, selector: "gio-el-assistant" }] }); }
850
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.3", type: GioPolicyStudioFlowLlmFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-llm-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2025 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n@if (flowFormGroup) {\n <mat-dialog-content class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies.</p>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>LLM Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n <mat-hint>If no method is specified, the flow will match all LLM Methods</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n <gio-el-assistant matSuffix />\n </mat-form-field>\n </div>\n </mat-dialog-content>\n}\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}.title__closeBtn{top:0;right:-24px;float:right}.content__paramTitle{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;color:#5c5959}.content--params{margin-bottom:6px}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row__fullWidth{flex:1 1 auto}.button-with-icon{display:flex;align-items:center;justify-content:space-between}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }, { kind: "component", type: i7.GioFormTagsInputComponent, selector: "gio-form-tags-input", inputs: ["aria-label", "addOnBlur", "tagValidationHook", "autocompleteOptions", "displayValueWith", "useAutocompleteOptionValueOnly", "placeholder", "required", "disabled"], outputs: ["tagClicked"] }, { kind: "component", type: GioElAssistantComponent, selector: "gio-el-assistant" }] }); }
910
851
  }
911
852
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: GioPolicyStudioFlowLlmFormDialogComponent, decorators: [{
912
853
  type: Component,
@@ -923,11 +864,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImpor
923
864
  GioIconsModule,
924
865
  GioFormTagsInputModule,
925
866
  GioElAssistantComponent,
926
- ], selector: 'gio-ps-flow-llm-form-dialog', template: "<!--\n\n Copyright (C) 2025 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n@if (flowFormGroup) {\n <mat-dialog-content class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies.</p>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>LLM Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"llmMethods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n <mat-hint>If no method is specified, the flow will match all LLM Methods</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n <gio-el-assistant matSuffix />\n </mat-form-field>\n </div>\n </mat-dialog-content>\n}\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}.title__closeBtn{top:0;right:-24px;float:right}.content__paramTitle{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;color:#5c5959}.content--params{margin-bottom:6px}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row__fullWidth{flex:1 1 auto}.button-with-icon{display:flex;align-items:center;justify-content:space-between}\n"] }]
867
+ ], selector: 'gio-ps-flow-llm-form-dialog', template: "<!--\n\n Copyright (C) 2025 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n@if (flowFormGroup) {\n <mat-dialog-content class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies.</p>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>LLM Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n <mat-hint>If no method is specified, the flow will match all LLM Methods</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field class=\"content__row__fullWidth\">\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n <gio-el-assistant matSuffix />\n </mat-form-field>\n </div>\n </mat-dialog-content>\n}\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}.title__closeBtn{top:0;right:-24px;float:right}.content__paramTitle{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;color:#5c5959}.content--params{margin-bottom:6px}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row__fullWidth{flex:1 1 auto}.button-with-icon{display:flex;align-items:center;justify-content:space-between}\n"] }]
927
868
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
928
869
  type: Inject,
929
870
  args: [MAT_DIALOG_DATA]
930
871
  }] }] });
872
+ const sanitizePathFormValue = (path) => {
873
+ if (path && path.startsWith('/')) {
874
+ return path.substring(1);
875
+ }
876
+ return path ?? '';
877
+ };
878
+ const sanitizeMethods = (value) => {
879
+ if (!value || value.find(m => m === 'ALL'))
880
+ return [];
881
+ return value;
882
+ };
883
+ const sanitizeMethodFormValue = (methods) => {
884
+ if (!methods || methods.length === 0)
885
+ return ['ALL'];
886
+ return methods;
887
+ };
931
888
 
932
889
  /*
933
890
  * Copyright (C) 2022 The Gravitee team (http://gravitee.io)
@@ -1041,29 +998,6 @@ class GioPolicyStudioFlowsMenuComponent {
1041
998
  }
1042
999
  pathOrChannelLabel = '';
1043
1000
  }
1044
- // LLM Proxy
1045
- const llmSelector = flow.selectors?.find(s => s.type === 'LLM');
1046
- if (llmSelector) {
1047
- if (llmSelector.methods && llmSelector.methods.length > 0) {
1048
- // Keep only 2 first methods and add +X badge if there are more
1049
- const methodsToKeep = llmSelector.methods.slice(0, 2);
1050
- const methodsLength = llmSelector.methods.length;
1051
- badges.push(...methodsToKeep.map(method => ({ label: method, class: `gio-badge-neutral` })));
1052
- if (methodsLength > 2) {
1053
- badges.push({
1054
- label: `+${methodsLength - 2}`,
1055
- class: 'gio-badge-neutral',
1056
- });
1057
- }
1058
- }
1059
- else {
1060
- badges.push({
1061
- label: 'All Methods',
1062
- class: 'gio-badge-neutral',
1063
- });
1064
- }
1065
- pathOrChannelLabel = '';
1066
- }
1067
1001
  const conditionSelector = flow.selectors?.find(s => s.type === 'CONDITION');
1068
1002
  if (conditionSelector && conditionSelector.condition) {
1069
1003
  hasCondition = true;
@@ -2288,13 +2222,13 @@ class GioPolicyStudioDetailsInfoBarComponent {
2288
2222
  get llmMethods() {
2289
2223
  if (this._llmMethods === undefined && this.flow) {
2290
2224
  //TODO need to add the type of the LLM selector
2291
- const llmSelector = this.flow.selectors?.find(s => s.type === 'LLM');
2292
- if (!llmSelector) {
2225
+ const httpSelector = this.flow.selectors?.find(s => s.type === 'HTTP');
2226
+ if (!httpSelector) {
2293
2227
  this._llmMethods = null; // Cache null to avoid recomputation
2294
2228
  return undefined;
2295
2229
  }
2296
- this._llmMethods = llmSelector?.methods?.length
2297
- ? llmSelector.methods.map(m => ({ name: m, class: `gio-badge-neutral` }))
2230
+ this._llmMethods = httpSelector?.methods?.length
2231
+ ? httpSelector.methods.map(m => ({ name: m, class: `gio-badge-neutral` }))
2298
2232
  : [{ name: 'All Methods', class: 'gio-badge-neutral' }];
2299
2233
  }
2300
2234
  return this._llmMethods === null ? undefined : this._llmMethods;