Skip to content
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import {
type AtomCommandResult,
} from "@t3tools/client-runtime/state/runtime";
import type { ProviderAuthResponse, ServerProvider } from "@t3tools/contracts";
import { useAtomValue } from "@effect/atom-react";
import { useRef, useState } from "react";
import { Linking, Pressable, ScrollView, TextInput, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";

import { AppText as Text } from "../../components/ui/AppText";
import { ScreenScrollView } from "../../components/ui/ScreenScrollView";
import { environmentPresentations } from "../../state/presentation";
import { useEnvironmentQuery } from "../../state/query";
import { serverEnvironment } from "../../state/server";
import { useAtomCommand } from "../../state/use-atom-command";
Expand All @@ -25,6 +27,7 @@ import { useSettingsEnvironmentFilter, type SettingsTarget } from "./settings-en

export function SettingsProviderAccountsRouteScreen() {
const { selectedTargets } = useSettingsEnvironmentFilter();
const providersByEnvironment = useAtomValue(environmentPresentations.providersByEnvironmentAtom);
const insets = useSafeAreaInsets();
return (
<>
Expand All @@ -41,7 +44,7 @@ export function SettingsProviderAccountsRouteScreen() {
) : (
selectedTargets.map((environment) => (
<SettingsSection key={environment.environmentId} title={environment.label}>
{environment.serverConfig.providers
{(providersByEnvironment.get(environment.environmentId) ?? [])
.filter(
(provider) =>
provider.setup?.canAuthenticate ||
Expand All @@ -54,7 +57,7 @@ export function SettingsProviderAccountsRouteScreen() {
provider={provider}
/>
))}
{!environment.serverConfig.providers.some(
{!(providersByEnvironment.get(environment.environmentId) ?? []).some(
(provider) =>
provider.setup?.canAuthenticate ||
(provider.driver === "acpRegistry" && provider.installed),
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/features/usage/ChatGptUsageSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function ChatGptUsageSummary({
}: {
selectedEnvironmentIds: ReadonlySet<EnvironmentId> | null;
}) {
const presentations = useAtomValue(environmentPresentations.presentationsAtom);
const presentations = useAtomValue(environmentPresentations.presentationsWithProvidersAtom);
const selected =
selectedEnvironmentIds === null
? presentations
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/src/features/usage/UsageLimitsPooled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export function UsageLimitsSection({
readonly selectedEnvironmentIds: ReadonlySet<EnvironmentId> | null;
readonly cursorPrompt?: ReactNode;
}) {
const presentations = useAtomValue(environmentPresentations.presentationsAtom);
const presentations = useAtomValue(environmentPresentations.presentationsWithProvidersAtom);
const selected =
selectedEnvironmentIds === null
? presentations
Expand Down Expand Up @@ -345,7 +345,7 @@ type AccountScreenProps = StaticScreenProps<{

export function UsageLimitAccountScreen({ route }: AccountScreenProps) {
const insets = useSafeAreaInsets();
const presentations = useAtomValue(environmentPresentations.presentationsAtom);
const presentations = useAtomValue(environmentPresentations.presentationsWithProvidersAtom);
const { accountKey, windowId, windowKind, environmentIds, now } = route.params;
const selectedIds =
environmentIds === null ? null : new Set(environmentIds.map((id) => EnvironmentId.make(id)));
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/widgets/SubscriptionUsageCoordinator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { buildSubscriptionUsageSnapshot } from "./subscriptionUsageSnapshot";
// Isolate quota changes from the much busier thread/config presentation stream.
const snapshotAtom = Atom.make((get) =>
buildSubscriptionUsageSnapshot(
get(environmentPresentations.presentationsAtom),
get(environmentPresentations.presentationsWithProvidersAtom),
Linking.createURL("settings/usage", { queryParams: { tab: "limits" } }),
Platform.OS === "android" ? Infinity : 6,
),
Expand Down
45 changes: 27 additions & 18 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ import { useProjectClone } from "../state/projectClones";
import { projectCloneDisplayName, projectCloneProgressSummary } from "@t3tools/contracts";
import {
type EnvironmentPresentation,
useEnvironmentProviders,
useEnvironments,
usePrimaryEnvironment,
} from "../state/environments";
Expand Down Expand Up @@ -1092,6 +1093,7 @@ export default function ChatView(props: ChatViewProps) {
});
const openPreview = useAtomCommand(previewEnvironment.open, { reportFailure: false });
const { environments } = useEnvironments();
const providersByEnvironment = useEnvironmentProviders();
const primaryEnvironment = usePrimaryEnvironment();
const retryEnvironment = useAtomCommand(environmentCatalog.retryNow, { reportFailure: false });
const setEnvironmentEnabled = useAtomCommand(environmentCatalog.setEnabled, {
Expand Down Expand Up @@ -2221,7 +2223,12 @@ export default function ChatView(props: ChatViewProps) {
const serverConfig = activeThread
? (activeEnvironment?.serverConfig ?? null)
: (primaryEnvironment?.serverConfig ?? null);
const providerStatuses = serverConfig?.providers ?? EMPTY_PROVIDERS;
const providerEnvironmentId = (activeThread ? activeEnvironment : primaryEnvironment)
?.environmentId;
const providerStatuses =
(providerEnvironmentId === undefined
? undefined
: providersByEnvironment.get(providerEnvironmentId)) ?? EMPTY_PROVIDERS;
const selectedProviderByThreadId = composerActiveProvider ?? null;
const threadProvider =
activeThread?.modelSelection.instanceId ??
Expand Down Expand Up @@ -3185,23 +3192,25 @@ export default function ChatView(props: ChatViewProps) {
return (
environment?.connection.phase === "connected" &&
(loadBalancingSettings.loadBalancingWeights[candidate.environmentId] ?? 50) > 0 &&
environment.serverConfig?.providers.some(
(provider) =>
(activeProviderInstanceId === null ||
provider.instanceId === activeProviderInstanceId) &&
provider.driver === selectedProvider &&
(environment.serverConfig?.settings
? resolveProjectProviderInstanceEnabled(
environment.serverConfig.settings,
candidate.projectId,
provider.instanceId,
)
: provider.enabled) &&
provider.installed &&
provider.status !== "error" &&
provider.auth.status !== "unauthenticated" &&
provider.availability !== "unavailable",
)
providersByEnvironment
.get(candidate.environmentId)
?.some(
(provider) =>
(activeProviderInstanceId === null ||
provider.instanceId === activeProviderInstanceId) &&
provider.driver === selectedProvider &&
(environment.serverConfig?.settings
? resolveProjectProviderInstanceEnabled(
environment.serverConfig.settings,
candidate.projectId,
provider.instanceId,
)
: provider.enabled) &&
provider.installed &&
provider.status !== "error" &&
provider.auth.status !== "unauthenticated" &&
provider.availability !== "unavailable",
)
);
})
.map((candidate) => candidate.environmentId)
Expand Down
15 changes: 10 additions & 5 deletions apps/web/src/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ import { useAtomQueryRunner } from "../state/use-atom-query-runner";
import { useScratchProject } from "../hooks/useScratchProject";
import { useNewProject } from "../hooks/useNewProject";
import { isScratchProject } from "@t3tools/client-runtime/state/projects";
import { useEnvironments, usePrimaryEnvironmentId } from "../state/environments";
import {
useEnvironmentProviders,
useEnvironments,
usePrimaryEnvironmentId,
} from "../state/environments";
import { useProjects, useServerConfigs, useThreadShells, waitForProject } from "../state/entities";
import { useThreadSearch } from "../state/queries";
import { resolveThreadActionProjectRef, startNewThreadFromContext } from "../lib/chatThreadActions";
Expand Down Expand Up @@ -818,11 +822,12 @@ function OpenCommandPaletteDialog(props: {
const environmentThemes = useEnvironmentThemeDefinitions();
const themeCards = useThemeCards(customThemes, environmentThemes);
const providers = useAtomValue(primaryServerProvidersAtom);
const providersByEnvironment = useEnvironmentProviders();
const providerEntryByEnvironmentAndInstanceId = new Map<string, ProviderInstanceEntry>(
environments.flatMap((environment) => {
const serverConfig = environment.serverConfig;
const derived = deriveProviderInstanceEntries(
serverConfig?.providers ??
providersByEnvironment.get(environment.environmentId) ??
(environment.environmentId === primaryEnvironmentId ? providers : []),
);
const entries = serverConfig
Expand Down Expand Up @@ -1680,9 +1685,9 @@ function OpenCommandPaletteDialog(props: {
project.id === promptLinkProjectRef.projectId,
),
providers:
environments.find(
(environment) => environment.environmentId === promptLinkProjectRef?.environmentId,
)?.serverConfig?.providers ?? [],
(promptLinkProjectRef
? providersByEnvironment.get(promptLinkProjectRef.environmentId)
: undefined) ?? [],
threadModelSelection: activeThread?.modelSelection ?? null,
};
const plainPromptLink = promptLinkInput
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { ConnectionCatalogEntry } from "@t3tools/client-runtime/connection";
import type { ServerConfig } from "@t3tools/contracts";

import { useEnvironments, usePrimaryEnvironmentId } from "~/state/environments";
import {
useEnvironmentProviders,
useEnvironments,
usePrimaryEnvironmentId,
} from "~/state/environments";
import { isDesktopLocalConnectionTarget } from "~/connection/desktopLocal";
import {
buildLocalEnvironmentUpdateGroups,
Expand Down Expand Up @@ -37,6 +40,7 @@ export function useLocalEnvironmentUpdateGroups(): {
readonly isAnySettling: boolean;
} {
const { environments } = useEnvironments();
const providersByEnvironment = useEnvironmentProviders();
const primaryEnvironmentId = usePrimaryEnvironmentId();

const inputs: LocalEnvironmentProvidersInput[] = [];
Expand All @@ -47,7 +51,7 @@ export function useLocalEnvironmentUpdateGroups(): {
}

const isPrimary = environment.environmentId === primaryEnvironmentId;
const serverConfig: ServerConfig | null = environment.serverConfig;
const serverConfig = environment.serverConfig;

inputs.push({
environmentId: environment.environmentId,
Expand All @@ -61,7 +65,7 @@ export function useLocalEnvironmentUpdateGroups(): {
: environment.label,
isPrimary,
connectionState: isPrimary ? "ready" : normalizeConnectionState(environment.connection.phase),
providers: serverConfig?.providers ?? [],
providers: providersByEnvironment.get(environment.environmentId) ?? [],
});
}

Expand Down
5 changes: 3 additions & 2 deletions apps/web/src/components/ProviderUpdatesAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PROVIDER_DISPLAY_NAMES } from "@t3tools/contracts";
import { settlePromise } from "@t3tools/client-runtime/state/runtime";
import { useRef, useState } from "react";

import { useEnvironments } from "~/state/environments";
import { useEnvironmentProviders, useEnvironments } from "~/state/environments";
import { serverEnvironment } from "~/state/server";
import { useAtomCommand } from "~/state/use-atom-command";
import {
Expand All @@ -17,11 +17,12 @@ import { Tooltip, TooltipPopup, TooltipTrigger } from "./ui/tooltip";

export function useProviderUpdates() {
const { environments } = useEnvironments();
const providersByEnvironment = useEnvironmentProviders();
const updateProvider = useAtomCommand(serverEnvironment.updateProvider, {
reportFailure: false,
});
const machines = environments.flatMap((environment) => {
const providers = environment.serverConfig?.providers ?? [];
const providers = providersByEnvironment.get(environment.environmentId) ?? [];
if (environment.connection.phase !== "connected") {
return [];
}
Expand Down
Loading
Loading