fix: remove global extension toggles

Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
This commit is contained in:
morgmart
2026-04-30 18:52:26 -07:00
parent 9150ad1965
commit 46f7464055
7 changed files with 7 additions and 83 deletions
@@ -38,14 +38,3 @@ export async function removeExtension(configKey: string): Promise<void> {
const client = await getClient();
await client.goose.GooseConfigExtensionsRemove({ configKey });
}
export async function setExtensionEnabled(
configKey: string,
enabled: boolean,
): Promise<void> {
const client = await getClient();
await client.goose.GooseConfigExtensionsToggle({
configKey,
enabled,
});
}
@@ -1,18 +1,13 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import {
addExtension,
listExtensions,
removeExtension,
setExtensionEnabled,
} from "../api/extensions";
import { nameToKey } from "../lib/extensionKeys";
import {
getDisplayName,
type ExtensionConfig,
type ExtensionEntry,
} from "../types";
import type { ExtensionConfig, ExtensionEntry } from "../types";
type ExtensionModalMode = "add" | "edit" | null;
@@ -23,7 +18,6 @@ export function useExtensionsSettings() {
const [modalMode, setModalMode] = useState<ExtensionModalMode>(null);
const [editingExtension, setEditingExtension] =
useState<ExtensionEntry | null>(null);
const toggleVersions = useRef<Record<string, number>>({});
const fetchExtensions = useCallback(async () => {
setIsLoading(true);
@@ -95,42 +89,6 @@ export function useExtensionsSettings() {
[fetchExtensions, t],
);
const handleToggleEnabled = useCallback(
async (extension: ExtensionEntry, enabled: boolean) => {
const configKey = extension.config_key;
const version = (toggleVersions.current[configKey] ?? 0) + 1;
toggleVersions.current[configKey] = version;
setExtensions((current) =>
current.map((item) =>
item.config_key === configKey ? { ...item, enabled } : item,
),
);
try {
await setExtensionEnabled(configKey, enabled);
if (toggleVersions.current[configKey] === version) {
await fetchExtensions();
}
} catch {
if (toggleVersions.current[configKey] !== version) return;
setExtensions((current) =>
current.map((item) =>
item.config_key === configKey
? { ...item, enabled: extension.enabled }
: item,
),
);
toast.error(
t("extensions.errors.toggleFailed", {
name: getDisplayName(extension),
}),
);
}
},
[fetchExtensions, t],
);
const handleModalClose = useCallback(() => {
setModalMode(null);
setEditingExtension(null);
@@ -145,7 +103,6 @@ export function useExtensionsSettings() {
handleConfigure,
handleSubmit,
handleDelete,
handleToggleEnabled,
handleModalClose,
};
}
@@ -2,13 +2,11 @@ import { useTranslation } from "react-i18next";
import { IconSettings } from "@tabler/icons-react";
import { cn } from "@/shared/lib/cn";
import { Button } from "@/shared/ui/button";
import { Switch } from "@/shared/ui/switch";
import { getDisplayName, type ExtensionEntry } from "../types";
interface ExtensionItemProps {
extension: ExtensionEntry;
onConfigure?: (extension: ExtensionEntry) => void;
onToggleEnabled?: (extension: ExtensionEntry, enabled: boolean) => void;
className?: string;
}
@@ -32,12 +30,10 @@ function isEditable(ext: ExtensionEntry): boolean {
export function ExtensionItem({
extension,
onConfigure,
onToggleEnabled,
className,
}: ExtensionItemProps) {
const { t } = useTranslation("settings");
const editable = isEditable(extension);
const toggleable = isUserManagedExtension(extension);
const displayName = getDisplayName(extension);
return (
@@ -56,16 +52,6 @@ export function ExtensionItem({
</p>
</div>
<div className="flex shrink-0 items-center gap-2">
{toggleable && onToggleEnabled ? (
<Switch
checked={extension.enabled}
onCheckedChange={(enabled) => onToggleEnabled(extension, enabled)}
aria-label={t(
extension.enabled ? "extensions.disable" : "extensions.enable",
{ name: displayName },
)}
/>
) : null}
{editable && onConfigure && (
<Button
variant="ghost"
@@ -48,7 +48,6 @@ export function ExtensionsSettings() {
handleConfigure,
handleSubmit,
handleDelete,
handleToggleEnabled,
handleModalClose,
} = useExtensionsSettings();
const [searchTerm, setSearchTerm] = useState("");
@@ -105,7 +104,6 @@ export function ExtensionsSettings() {
key={ext.config_key}
extension={ext}
onConfigure={handleConfigure}
onToggleEnabled={handleToggleEnabled}
/>
))}
</div>
@@ -39,10 +39,7 @@ const extensions: ExtensionEntry[] = [
];
describe("ExtensionsSettings", () => {
let handleToggleEnabled: ReturnType<typeof vi.fn>;
beforeEach(() => {
handleToggleEnabled = vi.fn();
mockUseExtensionsSettings.mockReturnValue({
extensions,
isLoading: false,
@@ -52,7 +49,6 @@ describe("ExtensionsSettings", () => {
handleConfigure: vi.fn(),
handleSubmit: vi.fn(),
handleDelete: vi.fn(),
handleToggleEnabled,
handleModalClose: vi.fn(),
});
});
@@ -73,10 +69,14 @@ describe("ExtensionsSettings", () => {
).not.toBeInTheDocument();
});
it("does not show global enable toggles for Goose capabilities", async () => {
it("does not show global enable toggles", async () => {
const user = userEvent.setup();
render(<ExtensionsSettings />);
expect(
screen.queryByRole("switch", { name: /disable github/i }),
).not.toBeInTheDocument();
await user.type(screen.getByRole("searchbox"), "summarize");
expect(
@@ -82,8 +82,6 @@
"editExtension": "Edit Extension",
"deleteExtension": "Delete Extension",
"configure": "Configure {{name}}",
"enable": "Enable {{name}}",
"disable": "Disable {{name}}",
"save": "Save",
"cancel": "Cancel",
"fields": {
@@ -126,7 +124,6 @@
"errors": {
"saveFailed": "Failed to save extension. Please try again.",
"deleteFailed": "Failed to delete extension. Please try again.",
"toggleFailed": "Failed to update {{name}}. Please try again.",
"nameConflict": "An extension named \"{{name}}\" already exists."
}
},
@@ -82,8 +82,6 @@
"editExtension": "Editar extensión",
"deleteExtension": "Eliminar extensión",
"configure": "Configurar {{name}}",
"enable": "Activar {{name}}",
"disable": "Desactivar {{name}}",
"save": "Guardar",
"cancel": "Cancelar",
"fields": {
@@ -126,7 +124,6 @@
"errors": {
"saveFailed": "Error al guardar la extensión. Inténtalo de nuevo.",
"deleteFailed": "Error al eliminar la extensión. Inténtalo de nuevo.",
"toggleFailed": "Error al actualizar {{name}}. Inténtalo de nuevo.",
"nameConflict": "Ya existe una extensión llamada \"{{name}}\"."
}
},