(function BotForm(
{
form.setValue('adapter_config', values, {
diff --git a/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx b/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx
index 8c66f787d..d8e64e79f 100644
--- a/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx
+++ b/web/src/app/home/components/dynamic-form/DynamicFormComponent.tsx
@@ -441,6 +441,7 @@ export default function DynamicFormComponent({
systemContext,
onValidate,
renderItem,
+ hiddenItemNames,
}: {
itemConfigList: IDynamicFormItemSchema[];
onSubmit?: (val: object) => unknown;
@@ -463,6 +464,8 @@ export default function DynamicFormComponent({
formValues: Record;
setFormValue: (name: string, value: unknown) => void;
}) => ReactNode | undefined;
+ /** Fields retained in form state but omitted from the rendered form. */
+ hiddenItemNames?: readonly string[];
}) {
const isInitialMount = useRef(true);
const previousInitialValues = useRef(initialValues);
@@ -628,6 +631,7 @@ export default function DynamicFormComponent({
externalDependentValues={externalDependentValues}
systemContext={systemContext}
renderItem={renderItem}
+ hiddenItemNames={hiddenItemNames}
/>
);
}
@@ -661,6 +665,7 @@ function DynamicFormFieldList({
externalDependentValues,
systemContext,
renderItem,
+ hiddenItemNames,
}: DynamicFormFieldsProps) {
type FormValues = Record;
const { t, i18n } = useTranslation();
@@ -725,6 +730,8 @@ function DynamicFormFieldList({
/>
{itemConfigList.map((config, index) => {
+ if (hiddenItemNames?.includes(config.name)) return null;
+
// Create a normalized config with type converted to frontend format
const normalizedConfig = {
...config,
diff --git a/web/tests/e2e/contextual-guides.spec.ts b/web/tests/e2e/contextual-guides.spec.ts
index ad6d3c808..d41d5e122 100644
--- a/web/tests/e2e/contextual-guides.spec.ts
+++ b/web/tests/e2e/contextual-guides.spec.ts
@@ -203,7 +203,8 @@ test('bot guide starts on the detail page after adapter-only creation', async ({
const adapterCard = page.locator('[data-slot="card"]').filter({
has: page.getByText('Adapter Configuration', { exact: true }),
});
- await expect(adapterCard.getByRole('switch')).toBeChecked();
+ await expect(adapterCard.getByRole('switch')).toHaveCount(0);
+ await expect(page.getByRole('radio', { name: /^Webhook/ })).toBeChecked();
await guide.getByRole('button', { name: 'Next' }).click();
await expect(
diff --git a/web/tests/unit/oss-cloud-ui-privacy.test.mjs b/web/tests/unit/oss-cloud-ui-privacy.test.mjs
index 4481aa18f..41a81e375 100644
--- a/web/tests/unit/oss-cloud-ui-privacy.test.mjs
+++ b/web/tests/unit/oss-cloud-ui-privacy.test.mjs
@@ -17,6 +17,9 @@ const homeSidebarSource = readSource(
const botFormSource = readSource(
'src/app/home/bots/components/bot-form/BotForm.tsx',
);
+const dynamicFormSource = readSource(
+ 'src/app/home/components/dynamic-form/DynamicFormComponent.tsx',
+);
const kbFormSource = readSource(
'src/app/home/knowledge/components/kb-form/KBForm.tsx',
);
@@ -52,6 +55,27 @@ test('keeps bot forms spaced with responsive setup and detail columns', () => {
assert.match(kbFormSource, /