remove access code/token functionality
This commit is contained in:
parent
483d1e2209
commit
9e1bcae545
@ -1,21 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import httpx
|
|
||||||
|
|
||||||
|
|
||||||
async def validate_access_token(access_code: str):
|
|
||||||
async with httpx.AsyncClient() as client:
|
|
||||||
url = (
|
|
||||||
"https://backend.buildpicoapps.com/screenshot_to_code/validate_access_token"
|
|
||||||
)
|
|
||||||
data = json.dumps(
|
|
||||||
{
|
|
||||||
"access_code": access_code,
|
|
||||||
"secret": os.environ.get("PICO_BACKEND_SECRET"),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
headers = {"Content-Type": "application/json"}
|
|
||||||
|
|
||||||
response = await client.post(url, content=data, headers=headers)
|
|
||||||
response_data = response.json()
|
|
||||||
return response_data
|
|
||||||
@ -16,7 +16,6 @@ from mock_llm import mock_completion
|
|||||||
from typing import Dict, List, cast, get_args
|
from typing import Dict, List, cast, get_args
|
||||||
from image_generation import create_alt_url_mapping, generate_images
|
from image_generation import create_alt_url_mapping, generate_images
|
||||||
from prompts import assemble_imported_code_prompt, assemble_prompt
|
from prompts import assemble_imported_code_prompt, assemble_prompt
|
||||||
from access_token import validate_access_token
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
from prompts.claude_prompts import VIDEO_PROMPT
|
from prompts.claude_prompts import VIDEO_PROMPT
|
||||||
@ -98,27 +97,13 @@ async def stream_code(websocket: WebSocket):
|
|||||||
# Get the OpenAI API key from the request. Fall back to environment variable if not provided.
|
# Get the OpenAI API key from the request. Fall back to environment variable if not provided.
|
||||||
# If neither is provided, we throw an error.
|
# If neither is provided, we throw an error.
|
||||||
openai_api_key = None
|
openai_api_key = None
|
||||||
if "accessCode" in params and params["accessCode"]:
|
if params["openAiApiKey"]:
|
||||||
print("Access code - using platform API key")
|
openai_api_key = params["openAiApiKey"]
|
||||||
res = await validate_access_token(params["accessCode"])
|
print("Using OpenAI API key from client-side settings dialog")
|
||||||
if res["success"]:
|
|
||||||
openai_api_key = os.environ.get("PLATFORM_OPENAI_API_KEY")
|
|
||||||
else:
|
|
||||||
await websocket.send_json(
|
|
||||||
{
|
|
||||||
"type": "error",
|
|
||||||
"value": res["failure_reason"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
if params["openAiApiKey"]:
|
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
||||||
openai_api_key = params["openAiApiKey"]
|
if openai_api_key:
|
||||||
print("Using OpenAI API key from client-side settings dialog")
|
print("Using OpenAI API key from environment variable")
|
||||||
else:
|
|
||||||
openai_api_key = os.environ.get("OPENAI_API_KEY")
|
|
||||||
if openai_api_key:
|
|
||||||
print("Using OpenAI API key from environment variable")
|
|
||||||
|
|
||||||
if not openai_api_key and code_generation_model == "gpt_4_vision":
|
if not openai_api_key and code_generation_model == "gpt_4_vision":
|
||||||
print("OpenAI API key not found")
|
print("OpenAI API key not found")
|
||||||
|
|||||||
@ -66,7 +66,6 @@ function App() {
|
|||||||
codeGenerationModel: CodeGenerationModel.GPT_4_VISION,
|
codeGenerationModel: CodeGenerationModel.GPT_4_VISION,
|
||||||
// Only relevant for hosted version
|
// Only relevant for hosted version
|
||||||
isTermOfServiceAccepted: false,
|
isTermOfServiceAccepted: false,
|
||||||
accessCode: null,
|
|
||||||
},
|
},
|
||||||
"setting"
|
"setting"
|
||||||
);
|
);
|
||||||
@ -362,7 +361,7 @@ function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-2 dark:bg-black dark:text-white">
|
<div className="mt-2 dark:bg-black dark:text-white">
|
||||||
{IS_RUNNING_ON_CLOUD && <PicoBadge settings={settings} />}
|
{IS_RUNNING_ON_CLOUD && <PicoBadge />}
|
||||||
{IS_RUNNING_ON_CLOUD && (
|
{IS_RUNNING_ON_CLOUD && (
|
||||||
<TermsOfServiceDialog
|
<TermsOfServiceDialog
|
||||||
open={!settings.isTermOfServiceAccepted}
|
open={!settings.isTermOfServiceAccepted}
|
||||||
@ -394,10 +393,7 @@ function App() {
|
|||||||
|
|
||||||
{appState !== AppState.CODE_READY && <TipLink />}
|
{appState !== AppState.CODE_READY && <TipLink />}
|
||||||
|
|
||||||
{IS_RUNNING_ON_CLOUD &&
|
{IS_RUNNING_ON_CLOUD && !settings.openAiApiKey && <OnboardingNote />}
|
||||||
!(settings.openAiApiKey || settings.accessCode) && (
|
|
||||||
<OnboardingNote />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{IS_OPENAI_DOWN && (
|
{IS_OPENAI_DOWN && (
|
||||||
<div className="bg-black text-white dark:bg-white dark:text-black p-3 rounded">
|
<div className="bg-black text-white dark:bg-white dark:text-black p-3 rounded">
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
import { Settings } from "../types";
|
export function PicoBadge() {
|
||||||
|
|
||||||
export function PicoBadge({ settings }: { settings: Settings }) {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<a
|
<a
|
||||||
@ -14,26 +12,14 @@ export function PicoBadge({ settings }: { settings: Settings }) {
|
|||||||
feature requests?
|
feature requests?
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
{!settings.accessCode && (
|
<a href="https://picoapps.xyz?ref=screenshot-to-code" target="_blank">
|
||||||
<a href="https://picoapps.xyz?ref=screenshot-to-code" target="_blank">
|
<div
|
||||||
<div
|
className="fixed z-50 bottom-5 right-5 rounded-md shadow text-black
|
||||||
className="fixed z-50 bottom-5 right-5 rounded-md shadow text-black
|
|
||||||
bg-white px-4 text-xs py-3 cursor-pointer"
|
bg-white px-4 text-xs py-3 cursor-pointer"
|
||||||
>
|
>
|
||||||
an open source project by Pico
|
an open source project by Pico
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
)}
|
|
||||||
{settings.accessCode && (
|
|
||||||
<a href="mailto:support@picoapps.xyz" target="_blank">
|
|
||||||
<div
|
|
||||||
className="fixed z-50 bottom-5 right-5 rounded-md shadow text-black
|
|
||||||
bg-white px-4 text-xs py-3 cursor-pointer"
|
|
||||||
>
|
|
||||||
email support
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import {
|
|||||||
AccordionItem,
|
AccordionItem,
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "./ui/accordion";
|
} from "./ui/accordion";
|
||||||
import AccessCodeSection from "./settings/AccessCodeSection";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
@ -47,11 +46,6 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
|||||||
<DialogTitle className="mb-4">Settings</DialogTitle>
|
<DialogTitle className="mb-4">Settings</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
{/* Access code */}
|
|
||||||
{IS_RUNNING_ON_CLOUD && (
|
|
||||||
<AccessCodeSection settings={settings} setSettings={setSettings} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Label htmlFor="image-generation">
|
<Label htmlFor="image-generation">
|
||||||
<div>DALL-E Placeholder Image Generation</div>
|
<div>DALL-E Placeholder Image Generation</div>
|
||||||
|
|||||||
@ -1,142 +0,0 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
import { Settings } from "../../types";
|
|
||||||
import { Button } from "../ui/button";
|
|
||||||
import { Input } from "../ui/input";
|
|
||||||
import { Label } from "../ui/label";
|
|
||||||
import useThrottle from "../../hooks/useThrottle";
|
|
||||||
import { Progress } from "../ui/progress";
|
|
||||||
import { PICO_BACKEND_FORM_SECRET } from "../../config";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
settings: Settings;
|
|
||||||
setSettings: React.Dispatch<React.SetStateAction<Settings>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UsageResponse {
|
|
||||||
used_credits: number;
|
|
||||||
total_credits: number;
|
|
||||||
is_valid: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FetchState {
|
|
||||||
EMPTY = "EMPTY",
|
|
||||||
LOADING = "LOADING",
|
|
||||||
INVALID = "INVALID",
|
|
||||||
VALID = "VALID",
|
|
||||||
}
|
|
||||||
|
|
||||||
function AccessCodeSection({ settings, setSettings }: Props) {
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
const [isValid, setIsValid] = useState(false);
|
|
||||||
const [usedCredits, setUsedCredits] = useState(0);
|
|
||||||
const [totalCredits, setTotalCredits] = useState(0);
|
|
||||||
const throttledAccessCode = useThrottle(settings.accessCode || "", 500);
|
|
||||||
|
|
||||||
const fetchState = (() => {
|
|
||||||
if (!settings.accessCode) return FetchState.EMPTY;
|
|
||||||
if (isLoading) return FetchState.LOADING;
|
|
||||||
if (!isValid) return FetchState.INVALID;
|
|
||||||
return FetchState.VALID;
|
|
||||||
})();
|
|
||||||
|
|
||||||
async function fetchUsage(accessCode: string) {
|
|
||||||
const res = await fetch(
|
|
||||||
"https://backend.buildpicoapps.com/screenshot_to_code/get_access_code_usage",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
access_code: accessCode,
|
|
||||||
secret: PICO_BACKEND_FORM_SECRET,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const usage = (await res.json()) as UsageResponse;
|
|
||||||
|
|
||||||
if (!usage.is_valid) {
|
|
||||||
setIsValid(false);
|
|
||||||
} else {
|
|
||||||
setIsValid(true);
|
|
||||||
setUsedCredits(usage.used_credits);
|
|
||||||
setTotalCredits(usage.total_credits);
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Don't do anything if access code is empty
|
|
||||||
if (!throttledAccessCode) return;
|
|
||||||
|
|
||||||
setIsLoading(true);
|
|
||||||
setIsValid(true);
|
|
||||||
|
|
||||||
// Wait for 500 ms before fetching usage
|
|
||||||
setTimeout(async () => {
|
|
||||||
await fetchUsage(throttledAccessCode);
|
|
||||||
}, 500);
|
|
||||||
}, [throttledAccessCode]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col space-y-4 bg-slate-200 p-4 rounded dark:text-white dark:bg-slate-800">
|
|
||||||
<Label htmlFor="access-code">
|
|
||||||
<div>Access Code</div>
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
id="access-code"
|
|
||||||
className="border-gray-700 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
|
|
||||||
placeholder="Enter your Screenshot to Code access code"
|
|
||||||
value={settings.accessCode || ""}
|
|
||||||
onChange={(e) =>
|
|
||||||
setSettings((s) => ({
|
|
||||||
...s,
|
|
||||||
accessCode: e.target.value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{fetchState === "EMPTY" && (
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<a href="https://buy.stripe.com/8wM6sre70gBW1nqaEE" target="_blank">
|
|
||||||
<Button size="sm" variant="secondary">
|
|
||||||
Buy credits
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{fetchState === "LOADING" && (
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span className="text-xs text-gray-700">Loading...</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{fetchState === "INVALID" && (
|
|
||||||
<>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span className="text-xs text-gray-700">Invalid access code</span>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{fetchState === "VALID" && (
|
|
||||||
<>
|
|
||||||
<Progress value={(usedCredits / totalCredits) * 100} />
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span className="text-xs text-gray-700">
|
|
||||||
{usedCredits} out of {totalCredits} credits used
|
|
||||||
</span>
|
|
||||||
<a href="https://buy.stripe.com/8wM6sre70gBW1nqaEE" target="_blank">
|
|
||||||
<Button size="sm">Add credits</Button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccessCodeSection;
|
|
||||||
@ -16,7 +16,6 @@ export interface Settings {
|
|||||||
codeGenerationModel: CodeGenerationModel;
|
codeGenerationModel: CodeGenerationModel;
|
||||||
// Only relevant for hosted version
|
// Only relevant for hosted version
|
||||||
isTermOfServiceAccepted: boolean;
|
isTermOfServiceAccepted: boolean;
|
||||||
accessCode: string | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AppState {
|
export enum AppState {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user