Compare commits
2 Commits
main
...
generate-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ec4bf59d3 | ||
|
|
d13ae72c06 |
@ -4,4 +4,5 @@ from typing import Literal
|
|||||||
InputMode = Literal[
|
InputMode = Literal[
|
||||||
"image",
|
"image",
|
||||||
"video",
|
"video",
|
||||||
|
"text",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -5,6 +5,7 @@ from llm import Llm
|
|||||||
|
|
||||||
from prompts.imported_code_prompts import IMPORTED_CODE_SYSTEM_PROMPTS
|
from prompts.imported_code_prompts import IMPORTED_CODE_SYSTEM_PROMPTS
|
||||||
from prompts.screenshot_system_prompts import SYSTEM_PROMPTS
|
from prompts.screenshot_system_prompts import SYSTEM_PROMPTS
|
||||||
|
from prompts.text_prompts import SYSTEM_PROMPTS as TEXT_SYSTEM_PROMPTS
|
||||||
from prompts.types import Stack
|
from prompts.types import Stack
|
||||||
|
|
||||||
|
|
||||||
@ -87,3 +88,22 @@ def assemble_prompt(
|
|||||||
"content": user_content,
|
"content": user_content,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def assemble_text_prompt(
|
||||||
|
text_prompt: str,
|
||||||
|
stack: Stack,
|
||||||
|
) -> List[ChatCompletionMessageParam]:
|
||||||
|
|
||||||
|
system_content = TEXT_SYSTEM_PROMPTS[stack]
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": system_content,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "Generate UI for " + text_prompt,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|||||||
37
backend/prompts/test_text_prompts.py
Normal file
37
backend/prompts/test_text_prompts.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import unittest
|
||||||
|
from prompts.text_prompts import HTML_TAILWIND_SYSTEM_PROMPT
|
||||||
|
|
||||||
|
|
||||||
|
class TestTextPrompts(unittest.TestCase):
|
||||||
|
def test_html_tailwind_system_prompt(self):
|
||||||
|
self.maxDiff = None
|
||||||
|
|
||||||
|
print(HTML_TAILWIND_SYSTEM_PROMPT)
|
||||||
|
|
||||||
|
expected_prompt = """
|
||||||
|
You are an expert Tailwind developer.
|
||||||
|
|
||||||
|
|
||||||
|
- Make sure to make it look modern and sleek.
|
||||||
|
- Use modern, professional fonts and colors.
|
||||||
|
- Follow UX best practices.
|
||||||
|
- Do not add comments in the code such as "<!-- Add other navigation links as needed -->" and "<!-- ... other news items ... -->" in place of writing the full code. WRITE THE FULL CODE.
|
||||||
|
- For images, use placeholder images from https://placehold.co and include a detailed description of the image in the alt text so that an image generation AI can generate the image later.
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
|
||||||
|
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
|
||||||
|
- You can use Google Fonts
|
||||||
|
- Font Awesome for icons: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"></link>
|
||||||
|
|
||||||
|
|
||||||
|
Return only the full code in <html></html> tags.
|
||||||
|
Do not include markdown "```" or "```html" at the start or end.
|
||||||
|
Reply with only the code, and no text/explanation before and after the code.
|
||||||
|
"""
|
||||||
|
self.assertEqual(HTML_TAILWIND_SYSTEM_PROMPT.strip(), expected_prompt.strip())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
126
backend/prompts/text_prompts.py
Normal file
126
backend/prompts/text_prompts.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
from prompts.types import SystemPrompts
|
||||||
|
|
||||||
|
GENERAL_INSTRUCTIONS = """
|
||||||
|
- Make sure to make it look modern and sleek.
|
||||||
|
- Use modern, professional fonts and colors.
|
||||||
|
- Follow UX best practices.
|
||||||
|
- Do not add comments in the code such as "<!-- Add other navigation links as needed -->" and "<!-- ... other news items ... -->" in place of writing the full code. WRITE THE FULL CODE.
|
||||||
|
- For images, use placeholder images from https://placehold.co and include a detailed description of the image in the alt text so that an image generation AI can generate the image later."""
|
||||||
|
|
||||||
|
LIBRARY_INSTRUCTIONS = """
|
||||||
|
- You can use Google Fonts
|
||||||
|
- Font Awesome for icons: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"></link>"""
|
||||||
|
|
||||||
|
FORMAT_INSTRUCTIONS = """
|
||||||
|
Return only the full code in <html></html> tags.
|
||||||
|
Do not include markdown "```" or "```html" at the start or end.
|
||||||
|
Reply with only the code, and no text/explanation before and after the code.
|
||||||
|
"""
|
||||||
|
|
||||||
|
HTML_TAILWIND_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert Tailwind developer.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
|
||||||
|
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
{LIBRARY_INSTRUCTIONS}
|
||||||
|
|
||||||
|
{FORMAT_INSTRUCTIONS}
|
||||||
|
"""
|
||||||
|
|
||||||
|
HTML_CSS_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert HTML, CSS and JS developer.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
{LIBRARY_INSTRUCTIONS}
|
||||||
|
|
||||||
|
{FORMAT_INSTRUCTIONS}
|
||||||
|
"""
|
||||||
|
|
||||||
|
REACT_TAILWIND_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert React/Tailwind developer.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
- Use these script to include React so that it can run on a standalone page:
|
||||||
|
<script src="https://unpkg.com/react/umd/react.development.js"></script>
|
||||||
|
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
|
||||||
|
<script src="https://unpkg.com/@babel/standalone/babel.js"></script>
|
||||||
|
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
{LIBRARY_INSTRUCTIONS}
|
||||||
|
|
||||||
|
{FORMAT_INSTRUCTIONS}
|
||||||
|
"""
|
||||||
|
|
||||||
|
BOOTSTRAP_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert Bootstrap, HTML and JS developer.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
- Use this script to include Bootstrap: <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||||
|
{LIBRARY_INSTRUCTIONS}
|
||||||
|
|
||||||
|
{FORMAT_INSTRUCTIONS}
|
||||||
|
"""
|
||||||
|
|
||||||
|
IONIC_TAILWIND_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert Ionic/Tailwind developer.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
- Use these script to include Ionic so that it can run on a standalone page:
|
||||||
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
|
||||||
|
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" />
|
||||||
|
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
- You can use Google Fonts
|
||||||
|
- ionicons for icons, add the following <script > tags near the end of the page, right before the closing </body> tag:
|
||||||
|
<script type="module">
|
||||||
|
import ionicons from 'https://cdn.jsdelivr.net/npm/ionicons/+esm'
|
||||||
|
</script>
|
||||||
|
<script nomodule src="https://cdn.jsdelivr.net/npm/ionicons/dist/esm/ionicons.min.js"></script>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/ionicons/dist/collection/components/icon/icon.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
{FORMAT_INSTRUCTIONS}
|
||||||
|
"""
|
||||||
|
|
||||||
|
VUE_TAILWIND_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert Vue/Tailwind developer.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
In terms of libraries,
|
||||||
|
- Use these script to include Vue so that it can run on a standalone page:
|
||||||
|
<script src="https://registry.npmmirror.com/vue/3.3.11/files/dist/vue.global.js"></script>
|
||||||
|
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
{LIBRARY_INSTRUCTIONS}
|
||||||
|
|
||||||
|
{FORMAT_INSTRUCTIONS}
|
||||||
|
"""
|
||||||
|
|
||||||
|
SVG_SYSTEM_PROMPT = f"""
|
||||||
|
You are an expert at building SVGs.
|
||||||
|
|
||||||
|
{GENERAL_INSTRUCTIONS}
|
||||||
|
|
||||||
|
Return only the full code in <svg></svg> tags.
|
||||||
|
Do not include markdown "```" or "```svg" at the start or end.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
SYSTEM_PROMPTS = SystemPrompts(
|
||||||
|
html_css=HTML_CSS_SYSTEM_PROMPT,
|
||||||
|
html_tailwind=HTML_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
react_tailwind=REACT_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
bootstrap=BOOTSTRAP_SYSTEM_PROMPT,
|
||||||
|
ionic_tailwind=IONIC_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
vue_tailwind=VUE_TAILWIND_SYSTEM_PROMPT,
|
||||||
|
svg=SVG_SYSTEM_PROMPT,
|
||||||
|
)
|
||||||
@ -16,7 +16,7 @@ from openai.types.chat import ChatCompletionMessageParam
|
|||||||
from mock_llm import mock_completion
|
from mock_llm import mock_completion
|
||||||
from typing import Dict, List, Union, cast, get_args
|
from typing import Dict, List, Union, 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, assemble_text_prompt
|
||||||
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
|
||||||
@ -185,12 +185,18 @@ async def stream_code(websocket: WebSocket):
|
|||||||
else:
|
else:
|
||||||
# Assemble the prompt
|
# Assemble the prompt
|
||||||
try:
|
try:
|
||||||
if params.get("resultImage") and params["resultImage"]:
|
if validated_input_mode == "image":
|
||||||
prompt_messages = assemble_prompt(
|
if params.get("resultImage") and params["resultImage"]:
|
||||||
params["image"], valid_stack, params["resultImage"]
|
prompt_messages = assemble_prompt(
|
||||||
)
|
params["image"], valid_stack, params["resultImage"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
prompt_messages = assemble_prompt(params["image"], valid_stack)
|
||||||
|
elif validated_input_mode == "text":
|
||||||
|
prompt_messages = assemble_text_prompt(params["image"], valid_stack)
|
||||||
else:
|
else:
|
||||||
prompt_messages = assemble_prompt(params["image"], valid_stack)
|
await throw_error("Invalid input mode")
|
||||||
|
return
|
||||||
except:
|
except:
|
||||||
await websocket.send_json(
|
await websocket.send_json(
|
||||||
{
|
{
|
||||||
@ -201,8 +207,8 @@ async def stream_code(websocket: WebSocket):
|
|||||||
await websocket.close()
|
await websocket.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Transform the history tree into message format for updates
|
||||||
if params["generationType"] == "update":
|
if params["generationType"] == "update":
|
||||||
# Transform the history tree into message format
|
|
||||||
# TODO: Move this to frontend
|
# TODO: Move this to frontend
|
||||||
for index, text in enumerate(params["history"]):
|
for index, text in enumerate(params["history"]):
|
||||||
if index % 2 == 0:
|
if index % 2 == 0:
|
||||||
|
|||||||
@ -42,6 +42,7 @@ import useBrowserTabIndicator from "./hooks/useBrowserTabIndicator";
|
|||||||
import TipLink from "./components/core/TipLink";
|
import TipLink from "./components/core/TipLink";
|
||||||
import SelectAndEditModeToggleButton from "./components/select-and-edit/SelectAndEditModeToggleButton";
|
import SelectAndEditModeToggleButton from "./components/select-and-edit/SelectAndEditModeToggleButton";
|
||||||
import { useAppStore } from "./store/app-store";
|
import { useAppStore } from "./store/app-store";
|
||||||
|
import GenerateFromText from "./components/generate-from-text/GenerateFromText";
|
||||||
|
|
||||||
const IS_OPENAI_DOWN = false;
|
const IS_OPENAI_DOWN = false;
|
||||||
|
|
||||||
@ -49,7 +50,11 @@ function App() {
|
|||||||
const [appState, setAppState] = useState<AppState>(AppState.INITIAL);
|
const [appState, setAppState] = useState<AppState>(AppState.INITIAL);
|
||||||
const [generatedCode, setGeneratedCode] = useState<string>("");
|
const [generatedCode, setGeneratedCode] = useState<string>("");
|
||||||
|
|
||||||
const [inputMode, setInputMode] = useState<"image" | "video">("image");
|
const [inputMode, setInputMode] = useState<"image" | "video" | "text">(
|
||||||
|
"image"
|
||||||
|
);
|
||||||
|
|
||||||
|
const [initialPrompt, setInitialPrompt] = useState<string>("");
|
||||||
|
|
||||||
const [referenceImages, setReferenceImages] = useState<string[]>([]);
|
const [referenceImages, setReferenceImages] = useState<string[]>([]);
|
||||||
const [executionConsole, setExecutionConsole] = useState<string[]>([]);
|
const [executionConsole, setExecutionConsole] = useState<string[]>([]);
|
||||||
@ -156,6 +161,7 @@ function App() {
|
|||||||
setAppState(AppState.INITIAL);
|
setAppState(AppState.INITIAL);
|
||||||
setGeneratedCode("");
|
setGeneratedCode("");
|
||||||
setReferenceImages([]);
|
setReferenceImages([]);
|
||||||
|
setInitialPrompt("");
|
||||||
setExecutionConsole([]);
|
setExecutionConsole([]);
|
||||||
setUpdateInstruction("");
|
setUpdateInstruction("");
|
||||||
setIsImportedFromCode(false);
|
setIsImportedFromCode(false);
|
||||||
@ -181,7 +187,12 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Re-run the create
|
// Re-run the create
|
||||||
doCreate(referenceImages, inputMode);
|
if (inputMode === "image" || inputMode === "video") {
|
||||||
|
doCreate(referenceImages, inputMode);
|
||||||
|
} else {
|
||||||
|
// TODO: Fix this
|
||||||
|
doCreateFromText(initialPrompt);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancelCodeGeneration = () => {
|
const cancelCodeGeneration = () => {
|
||||||
@ -225,14 +236,25 @@ function App() {
|
|||||||
(code) => {
|
(code) => {
|
||||||
setGeneratedCode(code);
|
setGeneratedCode(code);
|
||||||
if (params.generationType === "create") {
|
if (params.generationType === "create") {
|
||||||
setAppHistory([
|
if (inputMode === "image" || inputMode === "video") {
|
||||||
{
|
setAppHistory([
|
||||||
type: "ai_create",
|
{
|
||||||
parentIndex: null,
|
type: "ai_create",
|
||||||
code,
|
parentIndex: null,
|
||||||
inputs: { image_url: referenceImages[0] },
|
code,
|
||||||
},
|
inputs: { image_url: referenceImages[0] },
|
||||||
]);
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setAppHistory([
|
||||||
|
{
|
||||||
|
type: "ai_create",
|
||||||
|
parentIndex: null,
|
||||||
|
code,
|
||||||
|
inputs: { text: params.image },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
setCurrentVersion(0);
|
setCurrentVersion(0);
|
||||||
} else {
|
} else {
|
||||||
setAppHistory((prev) => {
|
setAppHistory((prev) => {
|
||||||
@ -294,6 +316,22 @@ function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doCreateFromText(text: string) {
|
||||||
|
// Reset any existing state
|
||||||
|
reset();
|
||||||
|
|
||||||
|
setInputMode("text");
|
||||||
|
setInitialPrompt(text);
|
||||||
|
doGenerateCode(
|
||||||
|
{
|
||||||
|
generationType: "create",
|
||||||
|
inputMode: "text",
|
||||||
|
image: text,
|
||||||
|
},
|
||||||
|
currentVersion
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Subsequent updates
|
// Subsequent updates
|
||||||
async function doUpdate(
|
async function doUpdate(
|
||||||
updateInstruction: string,
|
updateInstruction: string,
|
||||||
@ -351,7 +389,7 @@ function App() {
|
|||||||
{
|
{
|
||||||
generationType: "update",
|
generationType: "update",
|
||||||
inputMode,
|
inputMode,
|
||||||
image: referenceImages[0],
|
image: inputMode === "text" ? initialPrompt : referenceImages[0],
|
||||||
history: updatedHistory,
|
history: updatedHistory,
|
||||||
isImportedFromCode,
|
isImportedFromCode,
|
||||||
},
|
},
|
||||||
@ -462,6 +500,10 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{appState === AppState.INITIAL && (
|
||||||
|
<GenerateFromText doCreateFromText={doCreateFromText} />
|
||||||
|
)}
|
||||||
|
|
||||||
{(appState === AppState.CODING ||
|
{(appState === AppState.CODING ||
|
||||||
appState === AppState.CODE_READY) && (
|
appState === AppState.CODE_READY) && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
import { useState, useRef, useEffect } from "react";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Textarea } from "../ui/textarea";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
|
||||||
|
interface GenerateFromTextProps {
|
||||||
|
doCreateFromText: (text: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GenerateFromText({ doCreateFromText }: GenerateFromTextProps) {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen && textareaRef.current) {
|
||||||
|
textareaRef.current.focus();
|
||||||
|
}
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const handleGenerate = () => {
|
||||||
|
if (text.trim() === "") {
|
||||||
|
// Assuming there's a toast function available in the context
|
||||||
|
toast.error("Please enter a prompt to generate from");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doCreateFromText(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4">
|
||||||
|
{!isOpen ? (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<Button variant="secondary" onClick={() => setIsOpen(true)}>
|
||||||
|
Generate from text prompt [BETA]
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Textarea
|
||||||
|
ref={textareaRef}
|
||||||
|
rows={2}
|
||||||
|
placeholder="A Saas admin dashboard"
|
||||||
|
className="w-full mb-4"
|
||||||
|
value={text}
|
||||||
|
onChange={(e) => setText(e.target.value)}
|
||||||
|
/>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Button onClick={handleGenerate}>Generate</Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GenerateFromText;
|
||||||
@ -8,7 +8,7 @@ type CommonHistoryItem = {
|
|||||||
export type HistoryItem =
|
export type HistoryItem =
|
||||||
| ({
|
| ({
|
||||||
type: "ai_create";
|
type: "ai_create";
|
||||||
inputs: AiCreateInputs;
|
inputs: AiCreateInputs | AiCreateInputsText;
|
||||||
} & CommonHistoryItem)
|
} & CommonHistoryItem)
|
||||||
| ({
|
| ({
|
||||||
type: "ai_edit";
|
type: "ai_edit";
|
||||||
@ -23,6 +23,10 @@ export type AiCreateInputs = {
|
|||||||
image_url: string;
|
image_url: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AiCreateInputsText = {
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type AiEditInputs = {
|
export type AiEditInputs = {
|
||||||
prompt: string;
|
prompt: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export enum ScreenRecorderState {
|
|||||||
|
|
||||||
export interface CodeGenerationParams {
|
export interface CodeGenerationParams {
|
||||||
generationType: "create" | "update";
|
generationType: "create" | "update";
|
||||||
inputMode: "image" | "video";
|
inputMode: "image" | "video" | "text";
|
||||||
image: string;
|
image: string;
|
||||||
resultImage?: string;
|
resultImage?: string;
|
||||||
history?: string[];
|
history?: string[];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user