Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 96 additions & 103 deletions apps/web/src/components/settings/ProviderSettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ import {
} from "@t3tools/shared/backgroundActivitySettings";
import * as Arr from "effect/Array";
import * as Duration from "effect/Duration";
import * as Equal from "effect/Equal";
import * as Result from "effect/Result";
import { PlusIcon } from "lucide-react";
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import { useRef, useState, type ReactNode } from "react";

import { isDesktopLocalConnectionTarget } from "../../connection/desktopLocal";
import {
Expand Down Expand Up @@ -292,10 +291,10 @@ function ProviderSettingsPanelContent(target: ProviderSettingsTarget) {
const { environments, isReady } = useEnvironments();
const primaryEnvironmentId = usePrimaryEnvironmentId();
const searchTargetId = useSettingsSearchTargetId();
const options = useMemo(
() =>
buildProviderEnvironmentOptions(environments, primaryEnvironmentId, target.environmentIds),
[environments, primaryEnvironmentId, target.environmentIds],
const options = buildProviderEnvironmentOptions(
environments,
primaryEnvironmentId,
target.environmentIds,
);
const [selectedEnvironmentId, setSelectedEnvironmentId] = useState<EnvironmentId | null>(
target.environmentId ?? primaryEnvironmentId,
Expand Down Expand Up @@ -330,34 +329,33 @@ function ProviderSettingsPanelContent(target: ProviderSettingsTarget) {
hasServerConfig: true,
}),
)?.environmentId;
useEffect(() => {
// A search jump to a setting the selected device cannot show switches to one that can.
let searchRedirectEnvironmentId: EnvironmentId | undefined;
{
if (
!target.scoped &&
searchTargetId === searchableSetting("cursor-keychain-usage").id &&
(!selectedEnvironmentCanRenderSettings ||
selectedEnvironment?.serverConfig?.environment.platform.os !== "darwin") &&
searchableCursorEnvironmentId !== undefined
) {
setSelectedEnvironmentId(searchableCursorEnvironmentId);
return;
}
if (
searchRedirectEnvironmentId = searchableCursorEnvironmentId;
} else if (
!target.scoped &&
(searchTargetId === searchableSetting("provider-health-check-interval").id ||
searchTargetId === searchableSetting("usage-providers").id) &&
!selectedEnvironmentCanRenderSettings &&
searchableEnvironmentId !== undefined
) {
setSelectedEnvironmentId(searchableEnvironmentId);
searchRedirectEnvironmentId = searchableEnvironmentId;
}
}, [
searchTargetId,
searchableCursorEnvironmentId,
searchableEnvironmentId,
selectedEnvironment,
selectedEnvironmentCanRenderSettings,
target.scoped,
]);
}
if (
searchRedirectEnvironmentId !== undefined &&
searchRedirectEnvironmentId !== selectedEnvironmentId
) {
setSelectedEnvironmentId(searchRedirectEnvironmentId);
}
const onlyPrimaryDevice =
options.length === 1 && options[0]?.entry.target._tag === "PrimaryConnectionTarget";
const deviceTabs =
Expand Down Expand Up @@ -538,13 +536,15 @@ function AccessGatedProviderSettings({
);
}

const NO_PROJECT_IDS: readonly ProjectId[] = [];

export function EnvironmentProviderSettings({
environmentId,
environmentLabel,
readOnly = false,
deviceTabs,
targetInstanceId,
projectIds = [],
projectIds = NO_PROJECT_IDS,
}: {
readonly environmentId: EnvironmentId;
readonly environmentLabel: string;
Expand Down Expand Up @@ -593,42 +593,38 @@ export function EnvironmentProviderSettings({
const refreshingRef = useRef(false);
const updatingInstanceIdsRef = useRef<Set<ProviderInstanceId>>(new Set());

const acceptUrlAuthentication = useCallback(
(instanceId: ProviderInstanceId, action: AcpRegistryUrlAuthAction) => {
void acceptAcpRegistryUrlAuth({
environmentId,
input: { instanceId, elicitationId: action.elicitationId },
}).then((result) => {
if (result._tag === "Success" && !result.value.accepted) {
toastManager.add({
type: "warning",
title: "Authentication request expired",
description: "Refresh the provider and start the authentication flow again.",
});
return;
}
if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) {
const error = squashAtomCommandFailure(result);
toastManager.add({
type: "error",
title: "Could not continue authentication",
description:
error instanceof Error ? error.message : "The authentication request expired.",
});
}
});
},
[acceptAcpRegistryUrlAuth, environmentId],
);
const acceptUrlAuthentication = (
instanceId: ProviderInstanceId,
action: AcpRegistryUrlAuthAction,
) => {
void acceptAcpRegistryUrlAuth({
environmentId,
input: { instanceId, elicitationId: action.elicitationId },
}).then((result) => {
if (result._tag === "Success" && !result.value.accepted) {
toastManager.add({
type: "warning",
title: "Authentication request expired",
description: "Refresh the provider and start the authentication flow again.",
});
return;
}
if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) {
const error = squashAtomCommandFailure(result);
toastManager.add({
type: "error",
title: "Could not continue authentication",
description:
error instanceof Error ? error.message : "The authentication request expired.",
});
}
});
};

const providerUpdateCandidateByInstanceId = useMemo(
() =>
new Map(
serverProviders
.filter(isProviderSettingsUpdateCandidate)
.map((candidate) => [candidate.instanceId, candidate]),
),
[serverProviders],
const providerUpdateCandidateByInstanceId = new Map(
serverProviders
.filter(isProviderSettingsUpdateCandidate)
.map((candidate) => [candidate.instanceId, candidate]),
);
const visibleProviderSettings = PROVIDER_SETTINGS.filter(
(providerSettings) =>
Expand Down Expand Up @@ -656,7 +652,7 @@ export function EnvironmentProviderSettings({
)
: null;

const refreshProviders = useCallback(() => {
const refreshProviders = () => {
if (refreshingRef.current || !readEnvironmentScope(environmentId, AuthOrchestrationReadScope))
return;
refreshingRef.current = true;
Expand All @@ -676,55 +672,52 @@ export function EnvironmentProviderSettings({
});
}
})();
}, [environmentId, refreshServerProviders]);
};

const runProviderUpdate = useCallback(
async (
candidate: Pick<ProviderSettingsUpdateCandidate, "driver" | "instanceId">,
targetVersion?: string,
) => {
if (!readEnvironmentScope(environmentId, AuthProvidersManageScope)) return;
// Ref-based re-entry guard, mirroring refreshProviders: a state updater
// may run after this function returns, so it cannot gate the dispatch.
if (updatingInstanceIdsRef.current.has(candidate.instanceId)) {
return;
}
updatingInstanceIdsRef.current.add(candidate.instanceId);
setUpdatingProviderInstanceIds((previous) => new Set(previous).add(candidate.instanceId));
const runProviderUpdate = async (
candidate: Pick<ProviderSettingsUpdateCandidate, "driver" | "instanceId">,
targetVersion?: string,
) => {
if (!readEnvironmentScope(environmentId, AuthProvidersManageScope)) return;
// Ref-based re-entry guard, mirroring refreshProviders: a state updater
// may run after this function returns, so it cannot gate the dispatch.
if (updatingInstanceIdsRef.current.has(candidate.instanceId)) {
return;
}
updatingInstanceIdsRef.current.add(candidate.instanceId);
setUpdatingProviderInstanceIds((previous) => new Set(previous).add(candidate.instanceId));

const result = await updateProvider({
environmentId,
input: {
provider: candidate.driver,
instanceId: candidate.instanceId,
...(targetVersion ? { targetVersion } : {}),
},
});
if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) {
const error = squashAtomCommandFailure(result);
toastManager.add(
stackedThreadToast({
type: "error",
title: `Could not update ${PROVIDER_DISPLAY_NAMES[candidate.driver] ?? candidate.driver}`,
description:
error instanceof Error
? error.message
: "The provider update command could not be started.",
}),
);
const result = await updateProvider({
environmentId,
input: {
provider: candidate.driver,
instanceId: candidate.instanceId,
...(targetVersion ? { targetVersion } : {}),
},
});
if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) {
const error = squashAtomCommandFailure(result);
toastManager.add(
stackedThreadToast({
type: "error",
title: `Could not update ${PROVIDER_DISPLAY_NAMES[candidate.driver] ?? candidate.driver}`,
description:
error instanceof Error
? error.message
: "The provider update command could not be started.",
}),
);
}
updatingInstanceIdsRef.current.delete(candidate.instanceId);
setUpdatingProviderInstanceIds((previous) => {
if (!previous.has(candidate.instanceId)) {
return previous;
}
updatingInstanceIdsRef.current.delete(candidate.instanceId);
setUpdatingProviderInstanceIds((previous) => {
if (!previous.has(candidate.instanceId)) {
return previous;
}
const next = new Set(previous);
next.delete(candidate.instanceId);
return next;
});
},
[environmentId, updateProvider],
);
const next = new Set(previous);
next.delete(candidate.instanceId);
return next;
});
};

interface InstanceRow {
readonly instanceId: ProviderInstanceId;
Expand Down
Loading