From 98d56ea314811515a30c4e5c1b055dbdb06abf93 Mon Sep 17 00:00:00 2001 From: ravindu somawansa Date: Thu, 8 Oct 2026 16:54:47 +0200 Subject: [PATCH 1/2] feat(inference): note that plugin policies need their package installed --- frontend/src/components/landing/InferenceModal.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/components/landing/InferenceModal.tsx b/frontend/src/components/landing/InferenceModal.tsx index c537c5a1f..da83dcb7c 100644 --- a/frontend/src/components/landing/InferenceModal.tsx +++ b/frontend/src/components/landing/InferenceModal.tsx @@ -176,6 +176,10 @@ const InferenceModal: React.FC = ({ Pick a checkpoint and confirm hardware. The selected policy will drive the follower autonomously for the configured duration. +

+ Running a plugin policy? Its package must be installed alongside + lelab, or the run will fail to load the policy. +

From b5c42a272edc1f823333e592abadef3a970fcf38 Mon Sep 17 00:00:00 2001 From: Nicolas Rabault Date: Thu, 29 Oct 2026 14:33:58 +0100 Subject: [PATCH 2/2] feat(inference): show the plugin note only for policy types LeRobot does not register --- .../landing/InferenceModal.test.tsx | 12 +++++++ .../src/components/landing/InferenceModal.tsx | 32 ++++++++++++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/landing/InferenceModal.test.tsx b/frontend/src/components/landing/InferenceModal.test.tsx index a8ad8a242..313cbb2a2 100644 --- a/frontend/src/components/landing/InferenceModal.test.tsx +++ b/frontend/src/components/landing/InferenceModal.test.tsx @@ -90,6 +90,18 @@ test("an unsaved camera permits a manual rotation with a training-data reminder" expect(request.cameras.wrist).toMatchObject({ camera_index: 3, rotation: 90, width: 640, height: 480 }); }); +test("the plugin package note shows only for a policy type LeRobot does not register", async () => { + await render(); + expect(container.textContent).not.toContain("plugin policy"); + act(() => root.unmount()); root = createRoot(container); + const builtin = mocks.fetcher.getMockImplementation()!; + mocks.fetcher.mockImplementation(async (url: string, init?: RequestInit) => url.endsWith("/policy-config") + ? new Response(JSON.stringify({ policy_type: "my_plugin", requires_task: true, image_features: {} })) + : builtin(url, init)); + await render(); + expect(container.textContent).toContain("This is a plugin policy"); +}); + test("an invalid saved rotation blocks inference and gives a visible correction instruction", async () => { await render({ ...robot, cameras: [{ ...robot.cameras[0], rotation: 45 as never }] }); expect(container.textContent).toContain("Correct the camera settings in Calibration"); diff --git a/frontend/src/components/landing/InferenceModal.tsx b/frontend/src/components/landing/InferenceModal.tsx index da83dcb7c..d7b3ad031 100644 --- a/frontend/src/components/landing/InferenceModal.tsx +++ b/frontend/src/components/landing/InferenceModal.tsx @@ -37,6 +37,28 @@ interface Props { } const DEFAULT_FPS = 30; +// Policy types LeRobot (v0.6.1) registers itself; any other type comes from a plugin package. +const BUILTIN_POLICY_TYPES = new Set([ + "act", + "diffusion", + "eo1", + "evo1", + "fastwam", + "gaussian_actor", + "groot", + "lingbot_va", + "molmoact2", + "multi_task_dit", + "pi0", + "pi05", + "pi0_fast", + "smolvla", + "tdmpc", + "vla_jepa", + "vqbet", + "wall_x", + "xvla", +]); const InferenceModal: React.FC = ({ open, @@ -176,10 +198,12 @@ const InferenceModal: React.FC = ({ Pick a checkpoint and confirm hardware. The selected policy will drive the follower autonomously for the configured duration. -

- Running a plugin policy? Its package must be installed alongside - lelab, or the run will fail to load the policy. -

+ {policyConfig && !BUILTIN_POLICY_TYPES.has(policyConfig.policy_type ?? "") && ( +

+ This is a plugin policy: its package must be installed alongside + lelab, or the run will fail to load the policy. +

+ )}