Local .Env Manager

This commit is contained in:
Krishav Raj Singh 2025-07-16 21:34:34 +05:30
parent d098ebd435
commit e31dc7f8e8
10 changed files with 75 additions and 103 deletions

View File

@ -187,8 +187,8 @@ api_router.include_router(workflows_router, prefix="/workflows")
from pipedream import api as pipedream_api from pipedream import api as pipedream_api
api_router.include_router(pipedream_api.router) api_router.include_router(pipedream_api.router)
from local_llm import api as local_llm_api from local_env_manager import api as local_env_manager_api
api_router.include_router(local_llm_api.router) api_router.include_router(local_env_manager_api.router)
@api_router.get("/health") @api_router.get("/health")
async def health_check(): async def health_check():

View File

@ -0,0 +1,44 @@
from fastapi import APIRouter
from utils.config import config, EnvMode
from fastapi import HTTPException
from typing import Dict
from dotenv import load_dotenv, set_key, find_dotenv, dotenv_values
from utils.logger import logger
router = APIRouter(tags=["local-env-manager"])
@router.get("/env-vars")
def get_env_vars() -> Dict[str, str]:
if config.ENV_MODE != EnvMode.LOCAL:
raise HTTPException(status_code=403, detail="Env vars management only available in local mode")
try:
env_path = find_dotenv()
if not env_path:
logger.error("Could not find .env file")
return {}
return dotenv_values(env_path)
except Exception as e:
logger.error(f"Failed to get env vars: {e}")
raise HTTPException(status_code=500, detail=f"Failed to get env variables: {e}")
@router.post("/env-vars")
def save_env_vars(request: Dict[str, str]) -> Dict[str, str]:
if config.ENV_MODE != EnvMode.LOCAL:
raise HTTPException(status_code=403, detail="Env vars management only available in local mode")
try:
env_path = find_dotenv()
if not env_path:
raise HTTPException(status_code=500, detail="Could not find .env file")
for key, value in request.items():
set_key(env_path, key, value)
load_dotenv(override=True)
logger.info(f"Env variables saved successfully: {request}")
return {"message": "Env variables saved successfully"}
except Exception as e:
logger.error(f"Failed to save env variables: {e}")
raise HTTPException(status_code=500, detail=f"Failed to save env variables: {e}")

View File

@ -1,29 +0,0 @@
from fastapi import APIRouter
from utils.local_api_keys import save_local_api_keys, get_local_api_keys
from utils.config import config, EnvMode
from fastapi import HTTPException
from typing import Dict
from utils.constants import PROVIDERS
router = APIRouter(tags=["local-llm-keys"])
@router.get("/local-llm-keys")
def get_llm_keys() -> Dict[str, str]:
if config.ENV_MODE != EnvMode.LOCAL:
raise HTTPException(status_code=403, detail="API key management only available in local mode")
providers = [f"{provider}_API_KEY" for provider in PROVIDERS]
llm_keys = get_local_api_keys(providers)
return llm_keys
@router.post("/local-llm-keys")
def save_local_llm_keys(request: Dict[str, str]) -> Dict[str, str]:
if config.ENV_MODE != EnvMode.LOCAL:
raise HTTPException(status_code=403, detail="API key management only available in local mode")
key_saved = save_local_api_keys(request)
if key_saved:
return {"message": "API keys saved successfully"}
else:
raise HTTPException(status_code=500, detail="Failed to save API keys")

View File

@ -1,45 +0,0 @@
"""
Local API key management for LLMs.
This module provides functionality to manage API keys in local mode
by reading and writing to the .env file.
"""
import os
from typing import Dict, Optional, List
from utils.logger import logger
from utils.config import config, EnvMode
from dotenv import load_dotenv, set_key, find_dotenv
from utils.constants import PROVIDERS
def get_local_api_keys(providers: List[str]) -> Dict[str, str]:
"""Get API keys from .env file in local mode."""
try:
# Load current env vars
load_dotenv(override=True)
return {provider: os.getenv(provider) or "" for provider in providers}
except Exception as e:
logger.error(f"Failed to get local API keys: {e}")
return {}
def save_local_api_keys(api_keys: Dict[str, str]) -> bool:
"""Save API keys to .env file in local mode."""
try:
# Find .env file
env_path = find_dotenv()
if not env_path:
logger.error("Could not find .env file")
return False
# Update each API key
for key, value in api_keys.items():
set_key(env_path, key, value)
logger.info(f"Updated {key} in .env file")
return True
except Exception as e:
logger.error(f"Failed to save local API keys: {e}")
return False

View File

@ -0,0 +1,9 @@
import { isLocalMode } from "@/lib/config";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Shield } from "lucide-react";
import { LocalEnvManager } from "@/components/env-manager/local-env-manager";
export default function LocalEnvManagerPage() {
return <LocalEnvManager />
}

View File

@ -3,6 +3,7 @@
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import Link from 'next/link'; import Link from 'next/link';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import { isLocalMode } from '@/lib/config';
export default function PersonalAccountSettingsPage({ export default function PersonalAccountSettingsPage({
children, children,
@ -15,7 +16,7 @@ export default function PersonalAccountSettingsPage({
// { name: "Teams", href: "/settings/teams" }, // { name: "Teams", href: "/settings/teams" },
{ name: 'Billing', href: '/settings/billing' }, { name: 'Billing', href: '/settings/billing' },
{ name: 'Usage Logs', href: '/settings/usage-logs' }, { name: 'Usage Logs', href: '/settings/usage-logs' },
{ name: 'LLM API Keys', href: '/settings/llm-api-keys' }, ...(isLocalMode() ? [{ name: 'Local .Env Manager', href: '/settings/env-manager' }] : []),
]; ];
return ( return (
<> <>

View File

@ -1,9 +0,0 @@
import { isLocalMode } from "@/lib/config";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Shield } from "lucide-react";
import { LLMApiKeys } from "@/components/api-keys/llm-api-keys";
export default function LLMKeysPage() {
return <LLMApiKeys />
}

View File

@ -16,15 +16,16 @@ interface APIKeyForm {
[key: string]: string; [key: string]: string;
} }
export function LLMApiKeys() { export function LocalEnvManager() {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [visibleKeys, setVisibleKeys] = useState<Record<string, boolean>>({}); const [visibleKeys, setVisibleKeys] = useState<Record<string, boolean>>({});
const {data: apiKeys, isLoading} = useQuery({ const {data: apiKeys, isLoading} = useQuery({
queryKey: ['api-keys'], queryKey: ['api-keys'],
queryFn: async() => { queryFn: async() => {
const response = await backendApi.get('/local-llm-keys'); const response = await backendApi.get('/env-vars');
return response.data; return response.data;
}, },
enabled: isLocalMode()
}); });
const { register, handleSubmit, formState: { errors, isDirty }, reset } = useForm<APIKeyForm>({ const { register, handleSubmit, formState: { errors, isDirty }, reset } = useForm<APIKeyForm>({
@ -36,7 +37,7 @@ export function LLMApiKeys() {
} }
const updateApiKeys = useMutation({ const updateApiKeys = useMutation({
mutationFn: async (data: APIKeyForm) => { mutationFn: async (data: APIKeyForm) => {
const response = await backendApi.post('/local-llm-keys', data); const response = await backendApi.post('/env-vars', data);
await queryClient.invalidateQueries({ queryKey: ['api-keys'] }); await queryClient.invalidateQueries({ queryKey: ['api-keys'] });
return response.data; return response.data;
}, },
@ -50,7 +51,7 @@ export function LLMApiKeys() {
const keysArray = apiKeys ? Object.entries(apiKeys).map(([key, value]) => ({ const keysArray = apiKeys ? Object.entries(apiKeys).map(([key, value]) => ({
id: key, id: key,
name: key.replace(/_/g, " ").replace("KEY", "Key"), name: key,
value: value value: value
})) : []; })) : [];
@ -70,7 +71,7 @@ export function LLMApiKeys() {
if (isLoading) { if (isLoading) {
return <Card> return <Card>
<CardHeader> <CardHeader>
<CardTitle>API Keys</CardTitle> <CardTitle>Local .Env Manager</CardTitle>
<CardDescription>Loading...</CardDescription> <CardDescription>Loading...</CardDescription>
</CardHeader> </CardHeader>
</Card>; </Card>;
@ -78,15 +79,15 @@ export function LLMApiKeys() {
return <Card> return <Card>
<CardHeader> <CardHeader>
<CardTitle>API Keys</CardTitle> <CardTitle>Local .Env Manager</CardTitle>
<CardDescription> <CardDescription>
{isLocalMode() ? ( {isLocalMode() ? (
<> <>
Manage your API keys for various Language Model providers. Manage your local environment variables
</> </>
) : ( ) : (
<> <>
API key management is only available in local mode. Local .Env Manager is only available in local mode.
</> </>
)} )}
</CardDescription> </CardDescription>
@ -95,7 +96,7 @@ export function LLMApiKeys() {
{isLocalMode() && ( {isLocalMode() && (
<CardContent> <CardContent>
<form onSubmit={handleSubmit(handleSave)} className="space-y-4"> <form onSubmit={handleSubmit(handleSave)} className="space-y-4">
{keysArray && keysArray?.map((key: any) => ( {keysArray && keysArray?.map(key => (
<div key={key.id} className="space-y-2"> <div key={key.id} className="space-y-2">
<Label htmlFor={key.id}>{key.name}</Label> <Label htmlFor={key.id}>{key.name}</Label>

View File

@ -17,7 +17,7 @@ import {
AudioWaveform, AudioWaveform,
Sun, Sun,
Moon, Moon,
Key, KeyRound,
} from 'lucide-react'; } from 'lucide-react';
import { useAccounts } from '@/hooks/use-accounts'; import { useAccounts } from '@/hooks/use-accounts';
import NewTeamForm from '@/components/basejump/new-team-form'; import NewTeamForm from '@/components/basejump/new-team-form';
@ -289,9 +289,9 @@ export function NavUserWithTeams({
</Link> </Link>
</DropdownMenuItem> </DropdownMenuItem>
{isLocalMode() && <DropdownMenuItem asChild> {isLocalMode() && <DropdownMenuItem asChild>
<Link href="/settings/llm-api-keys"> <Link href="/settings/env-manager">
<Key className="h-4 w-4" /> <KeyRound className="h-4 w-4" />
LLM API Keys Local .Env Manager
</Link> </Link>
</DropdownMenuItem>} </DropdownMenuItem>}
{/* <DropdownMenuItem asChild> {/* <DropdownMenuItem asChild>

View File

@ -14,7 +14,7 @@ import {
TooltipTrigger, TooltipTrigger,
} from '@/components/ui/tooltip'; } from '@/components/ui/tooltip';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Check, ChevronDown, Search, AlertTriangle, Crown, ArrowUpRight, Brain, Plus, Edit, Trash, Cpu, Key } from 'lucide-react'; import { Check, ChevronDown, Search, AlertTriangle, Crown, ArrowUpRight, Brain, Plus, Edit, Trash, Cpu, Key, KeyRound } from 'lucide-react';
import { import {
ModelOption, ModelOption,
SubscriptionStatus, SubscriptionStatus,
@ -680,14 +680,14 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Link <Link
href="/settings/llm-api-keys" href="/settings/env-manager"
className="h-6 w-6 p-0 flex items-center justify-center" className="h-6 w-6 p-0 flex items-center justify-center"
> >
<Key className="h-3.5 w-3.5" /> <KeyRound className="h-3.5 w-3.5" />
</Link> </Link>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="bottom" className="text-xs"> <TooltipContent side="bottom" className="text-xs">
Manage API Keys Local .Env Manager
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>