From 7b1e0294aa8668257827d2e3d68c4228b1e0add8 Mon Sep 17 00:00:00 2001 From: LukeGus Date: Sun, 27 Sep 2026 14:14:51 -0500 Subject: [PATCH] feat: add descriptions to plugin host enable toggles --- packages/plugin-sdk/schema/manifest.schema.json | 4 ++++ packages/plugin-sdk/src/manifest.ts | 9 +++++++++ plugins/docker/locales/en.json | 3 ++- plugins/docker/manifest.json | 1 + plugins/file-manager/locales/en.json | 3 ++- plugins/file-manager/manifest.json | 1 + plugins/session-recording/locales/en.json | 3 ++- plugins/session-recording/manifest.json | 1 + plugins/ssh-terminal/manifest.json | 1 + plugins/tmux-monitor/locales/en.json | 3 ++- plugins/tmux-monitor/manifest.json | 1 + plugins/tunnels/locales/en.json | 3 ++- plugins/tunnels/manifest.json | 1 + src/backend/plugins/settings.ts | 1 + .../tests/plugins/settings-manifest.test.ts | 15 +++++++++++++++ src/backend/tests/plugins/settings.test.ts | 7 ++++++- src/ui/api/plugins-api.ts | 1 + src/ui/settings/HostPluginSections.tsx | 1 + 18 files changed, 53 insertions(+), 6 deletions(-) diff --git a/packages/plugin-sdk/schema/manifest.schema.json b/packages/plugin-sdk/schema/manifest.schema.json index a495a8c4c..d98deed63 100644 --- a/packages/plugin-sdk/schema/manifest.schema.json +++ b/packages/plugin-sdk/schema/manifest.schema.json @@ -690,6 +690,10 @@ "type": "string", "minLength": 1 }, + "enableDescriptionKey": { + "type": "string", + "minLength": 1 + }, "fields": { "type": "array", "items": { diff --git a/packages/plugin-sdk/src/manifest.ts b/packages/plugin-sdk/src/manifest.ts index 6de760243..5ef2f31de 100644 --- a/packages/plugin-sdk/src/manifest.ts +++ b/packages/plugin-sdk/src/manifest.ts @@ -269,6 +269,7 @@ export interface PluginHostSettingsContribution { /** Boolean field rendered first, gating the rest of the section. */ enableKey?: string; enableLabelKey?: string; + enableDescriptionKey?: string; /** What the enable switch reads before a host saves it. Off by default. */ enableDefault?: boolean; /** Host editor strip the generated tab sits in. Defaults to "top". */ @@ -1143,6 +1144,7 @@ function validateSettings(settings: unknown, errors: string[]): void { [ "enableKey", "enableLabelKey", + "enableDescriptionKey", "enableDefault", "editorGroup", "editorOrder", @@ -1162,6 +1164,13 @@ function validateSettings(settings: unknown, errors: string[]): void { // An enable switch with no label is a blank row in the host editor. requireString(host.enableLabelKey, `${at}.enableLabelKey`, errors); } + if ("enableDescriptionKey" in host) { + requireString( + host.enableDescriptionKey, + `${at}.enableDescriptionKey`, + errors, + ); + } if ("enableDefault" in host && typeof host.enableDefault !== "boolean") { errors.push(`${at}.enableDefault must be a boolean`); } diff --git a/plugins/docker/locales/en.json b/plugins/docker/locales/en.json index ef2064ee7..bf17c9e19 100644 --- a/plugins/docker/locales/en.json +++ b/plugins/docker/locales/en.json @@ -123,7 +123,8 @@ "settings": { "host": { "enable": { - "label": "Enable Docker" + "label": "Enable Docker", + "description": "Manage containers on this host." }, "containerRuntime": { "label": "Container Runtime", diff --git a/plugins/docker/manifest.json b/plugins/docker/manifest.json index ac76d6ad9..b06dd7dc1 100644 --- a/plugins/docker/manifest.json +++ b/plugins/docker/manifest.json @@ -57,6 +57,7 @@ "editorOrder": 30, "enableKey": "enableDocker", "enableLabelKey": "settings.host.enable.label", + "enableDescriptionKey": "settings.host.enable.description", "fields": [ { "key": "containerRuntime", diff --git a/plugins/file-manager/locales/en.json b/plugins/file-manager/locales/en.json index cff1f29ff..b8742b96f 100644 --- a/plugins/file-manager/locales/en.json +++ b/plugins/file-manager/locales/en.json @@ -12,7 +12,8 @@ "settings": { "host": { "enable": { - "label": "Enable File Manager" + "label": "Enable File Manager", + "description": "Browse and edit files on this host over SFTP." }, "defaultPath": { "label": "Default Path" diff --git a/plugins/file-manager/manifest.json b/plugins/file-manager/manifest.json index 8e19edd8b..c07ac0b02 100644 --- a/plugins/file-manager/manifest.json +++ b/plugins/file-manager/manifest.json @@ -75,6 +75,7 @@ "editorOrder": 60, "enableKey": "enableFileManager", "enableLabelKey": "settings.host.enable.label", + "enableDescriptionKey": "settings.host.enable.description", "enableDefault": true, "fields": [ { diff --git a/plugins/session-recording/locales/en.json b/plugins/session-recording/locales/en.json index 9f11b7976..9933a7b4f 100644 --- a/plugins/session-recording/locales/en.json +++ b/plugins/session-recording/locales/en.json @@ -21,7 +21,8 @@ }, "host": { "enable": { - "label": "Enable session recording" + "label": "Enable session recording", + "description": "Record terminal output for this host so you can play it back or download it later." } } }, diff --git a/plugins/session-recording/manifest.json b/plugins/session-recording/manifest.json index 8db7d183a..1d21574e9 100644 --- a/plugins/session-recording/manifest.json +++ b/plugins/session-recording/manifest.json @@ -63,6 +63,7 @@ "editorOrder": 85, "enableKey": "enableSessionRecording", "enableLabelKey": "settings.host.enable.label", + "enableDescriptionKey": "settings.host.enable.description", "fields": [] } }, diff --git a/plugins/ssh-terminal/manifest.json b/plugins/ssh-terminal/manifest.json index 05c502fb2..38e7a2698 100644 --- a/plugins/ssh-terminal/manifest.json +++ b/plugins/ssh-terminal/manifest.json @@ -220,6 +220,7 @@ "editorOrder": 12, "enableKey": "enableTerminal", "enableLabelKey": "settings.host.enableTerminal.label", + "enableDescriptionKey": "settings.host.enableTerminal.description", "enableDefault": true, "fields": [ { diff --git a/plugins/tmux-monitor/locales/en.json b/plugins/tmux-monitor/locales/en.json index 2af1d06f1..54007538e 100644 --- a/plugins/tmux-monitor/locales/en.json +++ b/plugins/tmux-monitor/locales/en.json @@ -20,7 +20,8 @@ "settings": { "host": { "enable": { - "label": "Enable Tmux Monitor" + "label": "Enable Tmux Monitor", + "description": "Watch and attach to tmux sessions running on this host." } } }, diff --git a/plugins/tmux-monitor/manifest.json b/plugins/tmux-monitor/manifest.json index 94d28cbed..ce4646517 100644 --- a/plugins/tmux-monitor/manifest.json +++ b/plugins/tmux-monitor/manifest.json @@ -50,6 +50,7 @@ "host": { "enableKey": "enableTmuxMonitor", "enableLabelKey": "settings.host.enable.label", + "enableDescriptionKey": "settings.host.enable.description", "fields": [] } }, diff --git a/plugins/tunnels/locales/en.json b/plugins/tunnels/locales/en.json index 524f41a1b..f094a9999 100644 --- a/plugins/tunnels/locales/en.json +++ b/plugins/tunnels/locales/en.json @@ -153,7 +153,8 @@ "settings": { "host": { "enable": { - "label": "Enable tunnels" + "label": "Enable tunnels", + "description": "Set up SSH tunnels through this host." } } } diff --git a/plugins/tunnels/manifest.json b/plugins/tunnels/manifest.json index 9816c54a5..8ec03dc10 100644 --- a/plugins/tunnels/manifest.json +++ b/plugins/tunnels/manifest.json @@ -71,6 +71,7 @@ "host": { "enableKey": "enableTunnel", "enableLabelKey": "settings.host.enable.label", + "enableDescriptionKey": "settings.host.enable.description", "fields": [ { "key": "tunnelConnections", diff --git a/src/backend/plugins/settings.ts b/src/backend/plugins/settings.ts index 4e0667c49..64ce53980 100644 --- a/src/backend/plugins/settings.ts +++ b/src/backend/plugins/settings.ts @@ -175,6 +175,7 @@ export function declaredFields( key: host.enableKey, type: "boolean", labelKey: host.enableLabelKey, + descriptionKey: host.enableDescriptionKey, default: host.enableDefault ?? false, }, ] diff --git a/src/backend/tests/plugins/settings-manifest.test.ts b/src/backend/tests/plugins/settings-manifest.test.ts index ba4632c85..1af8bcea7 100644 --- a/src/backend/tests/plugins/settings-manifest.test.ts +++ b/src/backend/tests/plugins/settings-manifest.test.ts @@ -301,6 +301,21 @@ describe("contributes.settings", () => { expect(errors.join(" ")).toContain("enableLabelKey"); }); + it("accepts an enableDescriptionKey and rejects an empty one", () => { + const host = { enableKey: "enableThing", enableLabelKey: "k", fields: [] }; + + expect( + validateManifest( + withSettings({ host: { ...host, enableDescriptionKey: "d" } }), + ), + ).toEqual([]); + expect( + validateManifest( + withSettings({ host: { ...host, enableDescriptionKey: "" } }), + ).join(" "), + ).toContain("enableDescriptionKey"); + }); + it("rejects a key that would not be index-safe", () => { const errors = validateManifest( withSettings({ diff --git a/src/backend/tests/plugins/settings.test.ts b/src/backend/tests/plugins/settings.test.ts index 6f11be0e3..ae7e58ffd 100644 --- a/src/backend/tests/plugins/settings.test.ts +++ b/src/backend/tests/plugins/settings.test.ts @@ -183,13 +183,18 @@ describe("declaredFields", () => { host: { enableKey: "enableThing", enableLabelKey: "k", + enableDescriptionKey: "d", fields: [{ key: "port", type: "number", labelKey: "k" }], }, }); const fields = declaredFields(withHost, "host"); expect(fields.map((f) => f.key)).toEqual(["enableThing", "port"]); - expect(fields[0]).toMatchObject({ type: "boolean", default: false }); + expect(fields[0]).toMatchObject({ + type: "boolean", + default: false, + descriptionKey: "d", + }); }); it("finds a field by key", () => { diff --git a/src/ui/api/plugins-api.ts b/src/ui/api/plugins-api.ts index 9f34a410b..1969a58c1 100644 --- a/src/ui/api/plugins-api.ts +++ b/src/ui/api/plugins-api.ts @@ -41,6 +41,7 @@ export interface PluginSettingsField { export interface PluginHostSettingsContribution { enableKey?: string; enableLabelKey?: string; + enableDescriptionKey?: string; enableDefault?: boolean; editorGroup?: "top" | "ssh"; editorOrder?: number; diff --git a/src/ui/settings/HostPluginSections.tsx b/src/ui/settings/HostPluginSections.tsx index 5fccdf42f..905f92f77 100644 --- a/src/ui/settings/HostPluginSections.tsx +++ b/src/ui/settings/HostPluginSections.tsx @@ -192,6 +192,7 @@ function HostPluginSection({ key: enableKey, type: "boolean", labelKey: host.enableLabelKey, + descriptionKey: host.enableDescriptionKey, }} values={shown} setValue={setValue}