Spaces:
Running
Running
GitHub Action
commited on
Commit
·
b453cca
1
Parent(s):
3f80c6a
Sync ling-space changes from GitHub commit 225a47b
Browse files- code_kit/agent_code_generator.py +104 -60
- code_kit/code_examples.py +6 -1
- code_kit/code_trimmer.py +23 -0
- config.py +21 -3
- tab_code.py +28 -20
- tab_code_prompts/framework_system_prompts.py +165 -0
code_kit/agent_code_generator.py
CHANGED
|
@@ -2,14 +2,16 @@ import gradio as gr
|
|
| 2 |
import time
|
| 3 |
import logging
|
| 4 |
import os
|
|
|
|
| 5 |
from model_handler import ModelHandler
|
| 6 |
-
from
|
|
|
|
|
|
|
| 7 |
|
| 8 |
# Configure logging
|
| 9 |
logger = logging.getLogger(__name__)
|
| 10 |
|
| 11 |
# Read the content of the JavaScript file for error catching
|
| 12 |
-
# Assuming the script is run from the project root or ling-space root.
|
| 13 |
try:
|
| 14 |
with open("static/catch-error.js", "r", encoding="utf-8") as f:
|
| 15 |
CATCH_ERROR_JS_SCRIPT = f.read()
|
|
@@ -39,10 +41,42 @@ def get_spinner_html():
|
|
| 39 |
</style>
|
| 40 |
"""
|
| 41 |
|
| 42 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
"""Generate code and provide a preview, updating a log stream chatbot."""
|
| 44 |
logger.info(f"--- [Code Generation] Start ---")
|
| 45 |
-
logger.info(f"Code Type: {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
if not user_prompt:
|
| 48 |
chatbot_history.append({"role": "assistant", "content": "🚨 **错误**: 请输入提示词。"})
|
|
@@ -54,7 +88,7 @@ def code_generation_agent(code_type, model_choice, user_prompt, color_palette, d
|
|
| 54 |
|
| 55 |
if user_prompt == "create an error" or user_prompt == "创建一个报错示例":
|
| 56 |
error_code = f"""<h1>This will create an error</h1><script>{CATCH_ERROR_JS_SCRIPT}</script><script>nonExistentFunction();</script>"""
|
| 57 |
-
escaped_code = error_code.replace("'", "'").replace('"',
|
| 58 |
final_preview_html = f"""
|
| 59 |
<div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
|
| 60 |
<iframe srcdoc='{escaped_code}'
|
|
@@ -84,63 +118,73 @@ def code_generation_agent(code_type, model_choice, user_prompt, color_palette, d
|
|
| 84 |
start_time = time.time()
|
| 85 |
model_handler = ModelHandler()
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
|
|
|
|
|
|
| 93 |
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
else:
|
| 105 |
-
break
|
| 106 |
else:
|
| 107 |
-
|
| 108 |
-
if start_index != -1:
|
| 109 |
-
part_to_add = buffer[:start_index]
|
| 110 |
-
full_code_for_preview += part_to_add
|
| 111 |
-
is_thinking = True
|
| 112 |
-
buffer = buffer[start_index:]
|
| 113 |
-
else:
|
| 114 |
-
full_code_for_preview += buffer
|
| 115 |
-
buffer = ""
|
| 116 |
-
break
|
| 117 |
-
|
| 118 |
-
elapsed_time = time.time() - start_time
|
| 119 |
-
generated_length = len(full_code_with_think)
|
| 120 |
-
speed = generated_length / elapsed_time if elapsed_time > 0 else 0
|
| 121 |
-
|
| 122 |
-
log_message = f"""
|
| 123 |
-
**⏳ 正在生成中...**
|
| 124 |
-
- **时间:** {elapsed_time:.2f}s
|
| 125 |
-
- **长度:** {generated_length} chars
|
| 126 |
-
- **速度:** {speed:.2f} char/s
|
| 127 |
-
"""
|
| 128 |
-
|
| 129 |
-
if len(chatbot_history) > 0 and "正在生成中" in chatbot_history[-1]["content"]:
|
| 130 |
-
chatbot_history[-1] = {"role": "assistant", "content": log_message}
|
| 131 |
else:
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
|
|
|
|
|
|
| 143 |
"""
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import time
|
| 3 |
import logging
|
| 4 |
import os
|
| 5 |
+
import re
|
| 6 |
from model_handler import ModelHandler
|
| 7 |
+
from config import CODE_FRAMEWORK_SPECS, STATIC_PAGE
|
| 8 |
+
from tab_code_prompts.framework_system_prompts import get_framework_system_prompt
|
| 9 |
+
from code_kit.code_trimmer import trim_html_markdown_blocks # Import the trimmer
|
| 10 |
|
| 11 |
# Configure logging
|
| 12 |
logger = logging.getLogger(__name__)
|
| 13 |
|
| 14 |
# Read the content of the JavaScript file for error catching
|
|
|
|
| 15 |
try:
|
| 16 |
with open("static/catch-error.js", "r", encoding="utf-8") as f:
|
| 17 |
CATCH_ERROR_JS_SCRIPT = f.read()
|
|
|
|
| 41 |
</style>
|
| 42 |
"""
|
| 43 |
|
| 44 |
+
def inject_error_catcher(html_code):
|
| 45 |
+
"""
|
| 46 |
+
Injects the error catching script into the HTML code.
|
| 47 |
+
It tries to insert it after the <head> tag.
|
| 48 |
+
If <head> is not found, it prepends it to the code (fallback).
|
| 49 |
+
"""
|
| 50 |
+
if not CATCH_ERROR_JS_SCRIPT:
|
| 51 |
+
return html_code
|
| 52 |
+
|
| 53 |
+
script_tag = f"<script>{CATCH_ERROR_JS_SCRIPT}</script>"
|
| 54 |
+
|
| 55 |
+
# Try to find <head> (case insensitive)
|
| 56 |
+
head_match = re.search(r"<head>", html_code, re.IGNORECASE)
|
| 57 |
+
if head_match:
|
| 58 |
+
# Insert after <head>
|
| 59 |
+
insert_pos = head_match.end()
|
| 60 |
+
return html_code[:insert_pos] + script_tag + html_code[insert_pos:]
|
| 61 |
+
|
| 62 |
+
# Try to find <body> (case insensitive)
|
| 63 |
+
body_match = re.search(r"<body>", html_code, re.IGNORECASE)
|
| 64 |
+
if body_match:
|
| 65 |
+
# Insert before <body>
|
| 66 |
+
insert_pos = body_match.start()
|
| 67 |
+
return html_code[:insert_pos] + script_tag + html_code[insert_pos:]
|
| 68 |
+
|
| 69 |
+
# Fallback: Just prepend if it looks somewhat like HTML or empty
|
| 70 |
+
return script_tag + html_code
|
| 71 |
+
|
| 72 |
+
def code_generation_agent(code_type_display_name, model_choice, user_prompt, color_palette, decoration_style, overall_style, chatbot_history):
|
| 73 |
"""Generate code and provide a preview, updating a log stream chatbot."""
|
| 74 |
logger.info(f"--- [Code Generation] Start ---")
|
| 75 |
+
logger.info(f"Code Type (Display Name): {code_type_display_name}, Model: {model_choice}, Prompt: '{user_prompt}'")
|
| 76 |
+
|
| 77 |
+
# Map display name back to constant key
|
| 78 |
+
code_framework_key = next((k for k, v in CODE_FRAMEWORK_SPECS.items() if v["display_name"] == code_type_display_name), STATIC_PAGE)
|
| 79 |
+
logger.info(f"Mapped Code Framework Key: {code_framework_key}")
|
| 80 |
|
| 81 |
if not user_prompt:
|
| 82 |
chatbot_history.append({"role": "assistant", "content": "🚨 **错误**: 请输入提示词。"})
|
|
|
|
| 88 |
|
| 89 |
if user_prompt == "create an error" or user_prompt == "创建一个报错示例":
|
| 90 |
error_code = f"""<h1>This will create an error</h1><script>{CATCH_ERROR_JS_SCRIPT}</script><script>nonExistentFunction();</script>"""
|
| 91 |
+
escaped_code = error_code.replace("'", "'").replace('"', """)
|
| 92 |
final_preview_html = f"""
|
| 93 |
<div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
|
| 94 |
<iframe srcdoc='{escaped_code}'
|
|
|
|
| 118 |
start_time = time.time()
|
| 119 |
model_handler = ModelHandler()
|
| 120 |
|
| 121 |
+
# Get the system prompt based on the selected framework AND specific color palette
|
| 122 |
+
# Passing color_palette allows it to be baked into the system prompt instructions
|
| 123 |
+
system_prompt = get_framework_system_prompt(code_framework_key, color_palette)
|
| 124 |
+
|
| 125 |
+
full_code_with_think = ""
|
| 126 |
+
full_code_for_preview = ""
|
| 127 |
+
buffer = ""
|
| 128 |
+
is_thinking = False
|
| 129 |
|
| 130 |
+
for code_chunk in model_handler.generate_code(system_prompt, full_user_prompt, model_choice):
|
| 131 |
+
full_code_with_think += code_chunk
|
| 132 |
+
buffer += code_chunk
|
| 133 |
+
|
| 134 |
+
while True:
|
| 135 |
+
if is_thinking:
|
| 136 |
+
end_index = buffer.find("</think>")
|
| 137 |
+
if end_index != -1:
|
| 138 |
+
is_thinking = False
|
| 139 |
+
buffer = buffer[end_index + len("</think>"):]
|
|
|
|
|
|
|
| 140 |
else:
|
| 141 |
+
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
else:
|
| 143 |
+
start_index = buffer.find("<think>")
|
| 144 |
+
if start_index != -1:
|
| 145 |
+
part_to_add = buffer[:start_index]
|
| 146 |
+
full_code_for_preview += part_to_add
|
| 147 |
+
is_thinking = True
|
| 148 |
+
buffer = buffer[start_index:]
|
| 149 |
+
else:
|
| 150 |
+
full_code_for_preview += buffer
|
| 151 |
+
buffer = ""
|
| 152 |
+
break
|
| 153 |
|
| 154 |
+
elapsed_time = time.time() - start_time
|
| 155 |
+
generated_length = len(full_code_with_think)
|
| 156 |
+
speed = generated_length / elapsed_time if elapsed_time > 0 else 0
|
| 157 |
+
|
| 158 |
+
log_message = f"""
|
| 159 |
+
**⏳ 正在生成中...**
|
| 160 |
+
- **时间:** {elapsed_time:.2f}s
|
| 161 |
+
- **长度:** {generated_length} chars
|
| 162 |
+
- **速度:** {speed:.2f} char/s
|
| 163 |
"""
|
| 164 |
+
|
| 165 |
+
if len(chatbot_history) > 0 and "正在生成中" in chatbot_history[-1]["content"]:
|
| 166 |
+
chatbot_history[-1] = {"role": "assistant", "content": log_message}
|
| 167 |
+
else:
|
| 168 |
+
chatbot_history.append({"role": "assistant", "content": log_message})
|
| 169 |
+
|
| 170 |
+
yield full_code_with_think, gr.update(), chatbot_history, gr.update()
|
| 171 |
+
|
| 172 |
+
# Apply trimming to the final generated code
|
| 173 |
+
trimmed_full_code_with_think = trim_html_markdown_blocks(full_code_with_think)
|
| 174 |
+
trimmed_full_code_for_preview = trim_html_markdown_blocks(full_code_for_preview)
|
| 175 |
+
|
| 176 |
+
# Inject error catching script before final render
|
| 177 |
+
final_code_with_error_catcher = inject_error_catcher(trimmed_full_code_for_preview)
|
| 178 |
+
|
| 179 |
+
escaped_code = final_code_with_error_catcher.replace("'", "'").replace('"', """)
|
| 180 |
+
final_preview_html = f"""
|
| 181 |
+
<div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
|
| 182 |
+
<iframe srcdoc='{escaped_code}'
|
| 183 |
+
style="position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; border: none;">
|
| 184 |
+
</iframe>
|
| 185 |
+
</div>
|
| 186 |
+
"""
|
| 187 |
+
chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 代码生成完成!"})
|
| 188 |
+
# Yield the trimmed code for display in the "Generated Source Code" tab
|
| 189 |
+
yield trimmed_full_code_with_think, gr.HTML(final_preview_html), chatbot_history, gr.Tabs(selected=0)
|
| 190 |
+
logger.info("Code generation streaming finished.")
|
code_kit/code_examples.py
CHANGED
|
@@ -34,5 +34,10 @@ CODE_EXAMPLES = [
|
|
| 34 |
"task": "报错测试",
|
| 35 |
"model": get_model_display_name(LING_FLASH_2_0),
|
| 36 |
"user_prompt": "创建一个报错示例"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
}
|
| 38 |
-
]
|
|
|
|
| 34 |
"task": "报错测试",
|
| 35 |
"model": get_model_display_name(LING_FLASH_2_0),
|
| 36 |
"user_prompt": "创建一个报错示例"
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"task": "生成错误-React",
|
| 40 |
+
"model": get_model_display_name(LING_FLASH_2_0),
|
| 41 |
+
"user_prompt": "Write a React component that deliberately throws an error during rendering to test the error boundary mechanism."
|
| 42 |
}
|
| 43 |
+
]
|
code_kit/code_trimmer.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
|
| 3 |
+
def trim_html_markdown_blocks(code_string: str) -> str:
|
| 4 |
+
"""
|
| 5 |
+
Trims Markdown HTML code block delimiters (```html and ```) from the start and end of a string.
|
| 6 |
+
Also removes any leading/trailing whitespace/newlines.
|
| 7 |
+
"""
|
| 8 |
+
if not code_string:
|
| 9 |
+
return ""
|
| 10 |
+
|
| 11 |
+
# Pattern to match ```html or ``` followed by optional whitespace/newlines
|
| 12 |
+
# and capture the actual code content.
|
| 13 |
+
# It attempts to match the opening ```html block
|
| 14 |
+
# and the closing ``` block at the very beginning and end of the string.
|
| 15 |
+
|
| 16 |
+
# Trim leading ```html or ```
|
| 17 |
+
trimmed_code = re.sub(r"^\s*```(html)?\s*\n", "", code_string, flags=re.IGNORECASE)
|
| 18 |
+
# Trim trailing ```
|
| 19 |
+
trimmed_code = re.sub(r"\n\s*```\s*$", "", trimmed_code)
|
| 20 |
+
|
| 21 |
+
return trimmed_code.strip()
|
| 22 |
+
|
| 23 |
+
|
config.py
CHANGED
|
@@ -86,12 +86,31 @@ CHAT_MODEL_SPECS = {
|
|
| 86 |
|
| 87 |
# Constants for easy referencing of code frameworks
|
| 88 |
STATIC_PAGE = "static_page"
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
CODE_FRAMEWORK_SPECS = {
|
| 92 |
STATIC_PAGE: {
|
| 93 |
"display_name": "静态页面",
|
| 94 |
"description": "生成一个独立的、响应式的 HTML 文件,包含所有必要的 CSS 和 JavaScript。适合快速原型和简单的网页展示。"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
}
|
| 96 |
}
|
| 97 |
|
|
@@ -121,5 +140,4 @@ def get_model_display_name(model_constant: str) -> str:
|
|
| 121 |
Retrieves the display name for a given model constant.
|
| 122 |
This is what's shown in the UI.
|
| 123 |
"""
|
| 124 |
-
return CHAT_MODEL_SPECS.get(model_constant, {}).get("display_name", model_constant)
|
| 125 |
-
|
|
|
|
| 86 |
|
| 87 |
# Constants for easy referencing of code frameworks
|
| 88 |
STATIC_PAGE = "static_page"
|
| 89 |
+
REACT_TAILWIND = "react_tailwind"
|
| 90 |
+
REACT_TAILWIND_CHARTJS = "react_tailwind_chartjs" # Added new constant
|
| 91 |
+
REACT_THREE_FIBER = "react_three_fiber"
|
| 92 |
+
OLD_SCHOOL_HTML = "old_school_html"
|
| 93 |
|
| 94 |
CODE_FRAMEWORK_SPECS = {
|
| 95 |
STATIC_PAGE: {
|
| 96 |
"display_name": "静态页面",
|
| 97 |
"description": "生成一个独立的、响应式的 HTML 文件,包含所有必要的 CSS 和 JavaScript。适合快速原型和简单的网页展示。"
|
| 98 |
+
},
|
| 99 |
+
REACT_TAILWIND: {
|
| 100 |
+
"display_name": "React + Tailwind",
|
| 101 |
+
"description": "使用 React 和 Tailwind CSS 构建的现代单页应用。生成内容将是一个单 HTML 文件(使用 CDN)。"
|
| 102 |
+
},
|
| 103 |
+
REACT_TAILWIND_CHARTJS: { # Added new framework spec
|
| 104 |
+
"display_name": "React + Tailwind + Chart.js",
|
| 105 |
+
"description": "使用 React, Tailwind CSS 和 Chart.js 构建数据可视化单页应用。生成内容将是一个单 HTML 文件(使用 CDN)。"
|
| 106 |
+
},
|
| 107 |
+
REACT_THREE_FIBER: {
|
| 108 |
+
"display_name": "React 3D (R3F)",
|
| 109 |
+
"description": "基于 React Three Fiber 的 3D 场景,配合 Tailwind CSS。适合酷炫的 3D 交互效果。"
|
| 110 |
+
},
|
| 111 |
+
OLD_SCHOOL_HTML: {
|
| 112 |
+
"display_name": "90s 复古风格",
|
| 113 |
+
"description": "90 年代风格的纯 HTML + CSS,无 JavaScript。致敬 Web 1.0 时代,适合怀旧风格。"
|
| 114 |
}
|
| 115 |
}
|
| 116 |
|
|
|
|
| 140 |
Retrieves the display name for a given model constant.
|
| 141 |
This is what's shown in the UI.
|
| 142 |
"""
|
| 143 |
+
return CHAT_MODEL_SPECS.get(model_constant, {}).get("display_name", model_constant)
|
|
|
tab_code.py
CHANGED
|
@@ -10,26 +10,34 @@ from code_kit.code_examples import CODE_EXAMPLES
|
|
| 10 |
# Configure logging
|
| 11 |
logger = logging.getLogger(__name__)
|
| 12 |
|
| 13 |
-
def refresh_preview(
|
| 14 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
logger.info(f"--- [Manual Refresh] Start ---")
|
| 16 |
-
logger.info(f"Code Type: {
|
| 17 |
-
|
| 18 |
-
if
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
def toggle_fullscreen(is_fullscreen):
|
| 35 |
is_fullscreen = not is_fullscreen
|
|
@@ -161,4 +169,4 @@ def create_code_tab():
|
|
| 161 |
fn=log_js_error,
|
| 162 |
inputs=[js_error_channel, log_chatbot],
|
| 163 |
outputs=log_chatbot
|
| 164 |
-
)
|
|
|
|
| 10 |
# Configure logging
|
| 11 |
logger = logging.getLogger(__name__)
|
| 12 |
|
| 13 |
+
def refresh_preview(code_type_display_name, current_code, chatbot_history):
|
| 14 |
+
"""
|
| 15 |
+
Refresh the preview and add a log entry.
|
| 16 |
+
Refactored to rely solely on the HTML content for preview, assuming all frameworks
|
| 17 |
+
produce a single-file HTML output that works in an iframe.
|
| 18 |
+
"""
|
| 19 |
logger.info(f"--- [Manual Refresh] Start ---")
|
| 20 |
+
logger.info(f"Code Type: {code_type_display_name}")
|
| 21 |
+
|
| 22 |
+
# Simple validation: Check if code seems to be HTML
|
| 23 |
+
if not current_code or not isinstance(current_code, str):
|
| 24 |
+
chatbot_history.append({"role": "assistant", "content": "⚠️ **警告**: 没有代码可供刷新。"})
|
| 25 |
+
return gr.update(), chatbot_history
|
| 26 |
+
|
| 27 |
+
# For all currently supported frameworks (Static, React+Tailwind, R3F, Old School),
|
| 28 |
+
# the output is a self-contained HTML string.
|
| 29 |
+
# So we can process them uniformly.
|
| 30 |
+
escaped_code = current_code.replace("'", "'").replace('"', '"')
|
| 31 |
+
final_preview_html = f"""
|
| 32 |
+
<div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
|
| 33 |
+
<iframe srcdoc='{escaped_code}'
|
| 34 |
+
style="position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; border: none;">
|
| 35 |
+
</iframe>
|
| 36 |
+
</div>
|
| 37 |
+
"""
|
| 38 |
+
chatbot_history.append({"role": "assistant", "content": "🔄 **状态**: 预览已手动刷新。"})
|
| 39 |
+
logger.info("Refreshed preview.")
|
| 40 |
+
return gr.HTML(final_preview_html), chatbot_history
|
| 41 |
|
| 42 |
def toggle_fullscreen(is_fullscreen):
|
| 43 |
is_fullscreen = not is_fullscreen
|
|
|
|
| 169 |
fn=log_js_error,
|
| 170 |
inputs=[js_error_channel, log_chatbot],
|
| 171 |
outputs=log_chatbot
|
| 172 |
+
)
|
tab_code_prompts/framework_system_prompts.py
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from config import STATIC_PAGE, REACT_TAILWIND, REACT_TAILWIND_CHARTJS, REACT_THREE_FIBER, OLD_SCHOOL_HTML
|
| 2 |
+
|
| 3 |
+
def get_framework_system_prompt(framework_type, color_palette=None):
|
| 4 |
+
"""
|
| 5 |
+
Returns the system prompt specific to the selected framework.
|
| 6 |
+
Optionally incorporates specific color palette instructions directly into the system prompt.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
base_role = "You are an expert front-end developer."
|
| 10 |
+
|
| 11 |
+
# Construct dynamic palette instruction
|
| 12 |
+
palette_instruction = "**Color Palette:** If a color palette is provided in the user prompt, **YOU MUST** use those specific hex codes."
|
| 13 |
+
if color_palette:
|
| 14 |
+
palette_instruction = f"**Color Palette (MANDATORY):** You have been assigned the following color palette. **YOU MUST** use these specific hex codes for the corresponding roles:\n {color_palette}\n Use Tailwind's arbitrary value syntax (e.g., `bg-[#FF5733]`) to apply them."
|
| 15 |
+
|
| 16 |
+
if framework_type == REACT_TAILWIND:
|
| 17 |
+
return f"""
|
| 18 |
+
{base_role}
|
| 19 |
+
Create a single-file HTML application using **React** and **Tailwind CSS**.
|
| 20 |
+
|
| 21 |
+
**Technical Constraints & Libraries:**
|
| 22 |
+
1. **Library Loading:** Use unpkg/cdnjs for imports.
|
| 23 |
+
* React: `https://unpkg.com/react@18/umd/react.development.js`
|
| 24 |
+
* ReactDOM: `https://unpkg.com/react-dom@18/umd/react-dom.development.js`
|
| 25 |
+
* Babel: `https://unpkg.com/@babel/standalone/babel.min.js`
|
| 26 |
+
* Tailwind: `https://cdn.tailwindcss.com`
|
| 27 |
+
2. **Structure:**
|
| 28 |
+
* Load Tailwind via script tag.
|
| 29 |
+
* Load React/ReactDOM/Babel via script tags.
|
| 30 |
+
* Write your React components inside `<script type="text/babel">`.
|
| 31 |
+
* Mount the main component to a root div.
|
| 32 |
+
3. **Visual Style & Theming:**
|
| 33 |
+
* **Strictly follow** any "Visual Style Requirements" (Decoration, Theme) provided in the user prompt.
|
| 34 |
+
* {palette_instruction}
|
| 35 |
+
* **Decoration:** Reflect the requested decoration style (e.g., rounded corners, shadows, borders) using Tailwind classes.
|
| 36 |
+
4. **Common Pitfalls to Avoid:**
|
| 37 |
+
* Do NOT use `import` statements (ES modules) for React in this single-file setup. Use the global `React` and `ReactDOM` variables.
|
| 38 |
+
* Ensure valid JSX syntax.
|
| 39 |
+
* Remember to use `className` instead of `class`.
|
| 40 |
+
* Close all self-closing tags (e.g., `<img />`, `<br />`).
|
| 41 |
+
|
| 42 |
+
**Output Format:**
|
| 43 |
+
Return ONLY the raw HTML code. No markdown explanations.
|
| 44 |
+
"""
|
| 45 |
+
|
| 46 |
+
elif framework_type == REACT_TAILWIND_CHARTJS:
|
| 47 |
+
# Specific instruction for Chart.js palette usage
|
| 48 |
+
chart_palette_instr = palette_instruction
|
| 49 |
+
if color_palette:
|
| 50 |
+
chart_palette_instr = f"**Color Palette (MANDATORY):** You have been assigned the following color palette:\n {color_palette}\n **CRITICAL:** Apply these exact colors to your Chart.js `backgroundColor` and `borderColor` datasets, and use them for UI elements via Tailwind arbitrary values."
|
| 51 |
+
|
| 52 |
+
return f"""
|
| 53 |
+
{base_role}
|
| 54 |
+
Create a single-file HTML application using **React**, **Tailwind CSS**, and **Chart.js** for data visualization.
|
| 55 |
+
|
| 56 |
+
**Technical Constraints & Libraries:**
|
| 57 |
+
1. **Library Loading:** Use unpkg/cdnjs for imports.
|
| 58 |
+
* React: `https://unpkg.com/react@18/umd/react.development.js`
|
| 59 |
+
* ReactDOM: `https://unpkg.com/react-dom@18/umd/react-dom.development.js`
|
| 60 |
+
* Babel: `https://unpkg.com/@babel/standalone/babel.min.js`
|
| 61 |
+
* Tailwind: `https://cdn.tailwindcss.com`
|
| 62 |
+
* Chart.js: `https://cdn.jsdelivr.net/npm/chart.js`
|
| 63 |
+
2. **Structure:**
|
| 64 |
+
* Load Tailwind via script tag.
|
| 65 |
+
* Load React/ReactDOM/Babel via script tags.
|
| 66 |
+
* Load Chart.js via script tag (before your React script that uses it).
|
| 67 |
+
* Write your React components inside `<script type="text/babel">`.
|
| 68 |
+
* Mount the main component to a root div.
|
| 69 |
+
* Use a `<canvas>` element for Chart.js charts and get its 2D context within a React ref or a direct DOM query in `useEffect`.
|
| 70 |
+
3. **Visual Style & Theming (CRITICAL):**
|
| 71 |
+
* **Strictly follow** any "Visual Style Requirements" provided in the user prompt.
|
| 72 |
+
* {chart_palette_instr}
|
| 73 |
+
* **Decoration:** Apply the requested decoration style using appropriate Tailwind utilities.
|
| 74 |
+
4. **Common Pitfalls to Avoid:**
|
| 75 |
+
* Do NOT use `import` statements (ES modules) for React/ReactDOM/Babel/Chart.js in this single-file setup. Use the global `React`, `ReactDOM`, `Chart` variables.
|
| 76 |
+
* Ensure valid JSX syntax.
|
| 77 |
+
* Remember to use `className` instead of `class`.
|
| 78 |
+
* Close all self-closing tags.
|
| 79 |
+
* For Chart.js, ensure the canvas context is properly obtained (`canvasRef.current.getContext('2d')`).
|
| 80 |
+
* Manage Chart.js instances within React's `useEffect` hook: create the chart on mount and destroy it on unmount to prevent memory leaks.
|
| 81 |
+
* Ensure Chart.js data and options objects are correctly structured.
|
| 82 |
+
|
| 83 |
+
**Output Format:**
|
| 84 |
+
Return ONLY the raw HTML code. No markdown explanations.
|
| 85 |
+
"""
|
| 86 |
+
|
| 87 |
+
elif framework_type == REACT_THREE_FIBER:
|
| 88 |
+
r3f_palette_instr = palette_instruction
|
| 89 |
+
if color_palette:
|
| 90 |
+
r3f_palette_instr = f"**Color Palette (MANDATORY):** You have been assigned the following color palette:\n {color_palette}\n Use these hex codes for 3D materials (`color='#hex'`), lights, background, and UI overlays."
|
| 91 |
+
|
| 92 |
+
return f"""
|
| 93 |
+
{base_role}
|
| 94 |
+
Create a 3D interactive scene using **React Three Fiber (R3F)**, **React Drei**, and **Tailwind CSS**.
|
| 95 |
+
|
| 96 |
+
**Technical Constraints & Libraries:**
|
| 97 |
+
1. **Library Loading:** Use ES Modules via `importmap` for R3F, as it usually requires a module system.
|
| 98 |
+
* Add an `<script type="importmap">` block defining 'react', 'react-dom/client', 'three', '@react-three/fiber', '@react-three/drei'.
|
| 99 |
+
* Use `https://esm.sh/` for reliable module imports.
|
| 100 |
+
* Example: "react": "https://esm.sh/react@18.2.0"
|
| 101 |
+
* Load Tailwind CSS via `https://cdn.tailwindcss.com`.
|
| 102 |
+
2. **Structure:**
|
| 103 |
+
* Use `<script type="module">` for your React logic.
|
| 104 |
+
* Import specific components from the libraries.
|
| 105 |
+
* Setup a `<Canvas>` from `@react-three/fiber`.
|
| 106 |
+
3. **Visual Style & Theming:**
|
| 107 |
+
* **Strictly follow** any "Visual Style Requirements" provided in the user prompt.
|
| 108 |
+
* {r3f_palette_instr}
|
| 109 |
+
4. **Common Pitfalls to Avoid:**
|
| 110 |
+
* Ensure `three` version compatibility with `@react-three/fiber`.
|
| 111 |
+
* Do not mix UMD globals with ES module imports. Stick to the module approach for this stack.
|
| 112 |
+
* Set the canvas height (e.g., `h-screen` or fixed height) via Tailwind, otherwise it might be 0px.
|
| 113 |
+
|
| 114 |
+
**Output Format:**
|
| 115 |
+
Return ONLY the raw HTML code. No markdown explanations.
|
| 116 |
+
"""
|
| 117 |
+
|
| 118 |
+
elif framework_type == OLD_SCHOOL_HTML:
|
| 119 |
+
old_school_palette_instr = "**Color Palette:** If a palette is provided, use those specific hex codes for `bgcolor` attributes, `font color`, or inline styles."
|
| 120 |
+
if color_palette:
|
| 121 |
+
old_school_palette_instr = f"**Color Palette (MANDATORY):** You MUST use these specific colors:\n {color_palette}\n Apply them using `bgcolor` attributes, `<font color='...'>`, or inline `style='color: ...'`."
|
| 122 |
+
|
| 123 |
+
return f"""
|
| 124 |
+
{base_role}
|
| 125 |
+
Create a **90s/Early 2000s style** web page.
|
| 126 |
+
|
| 127 |
+
**Technical Constraints & Style:**
|
| 128 |
+
1. **Technology:** Pure HTML 4.01 style (transitional) and CSS. **NO JavaScript**.
|
| 129 |
+
2. **Visual Style (The Vibe):**
|
| 130 |
+
* {old_school_palette_instr}
|
| 131 |
+
* Use web-safe colors, tiling backgrounds, and extensive HTML tables (`<table>`) for layout.
|
| 132 |
+
* Use `<marquee>` tags, `<blink>` tags (or CSS simulation), and specific fonts like Times New Roman or Comic Sans MS.
|
| 133 |
+
* Beveled buttons and borders (CSS `border-style: outset`).
|
| 134 |
+
3. **Common Pitfalls to Avoid:**
|
| 135 |
+
* Do NOT use Flexbox or Grid.
|
| 136 |
+
* Do NOT use modern CSS variables or shadows.
|
| 137 |
+
* Do NOT use any external CSS frameworks.
|
| 138 |
+
|
| 139 |
+
**Output Format:**
|
| 140 |
+
Return ONLY the raw HTML code. No markdown explanations.
|
| 141 |
+
"""
|
| 142 |
+
|
| 143 |
+
else: # Default to STATIC_PAGE
|
| 144 |
+
static_palette_instr = "**Color Palette:** If provided, use the specified hex codes for your CSS styles."
|
| 145 |
+
if color_palette:
|
| 146 |
+
static_palette_instr = f"**Color Palette (MANDATORY):** You MUST use these specific colors for your CSS variables or styles:\n {color_palette}"
|
| 147 |
+
|
| 148 |
+
return f"""
|
| 149 |
+
{base_role}
|
| 150 |
+
Create a complete, modern, and responsive single HTML file based on the user's request.
|
| 151 |
+
|
| 152 |
+
**Technical Constraints:**
|
| 153 |
+
1. **Self-Contained:** Include all necessary HTML, CSS, and JavaScript in the file.
|
| 154 |
+
2. **Libraries:** If you need external libraries (like jQuery, Bootstrap, FontAwesome), use standard CDNs (cdnjs/unpkg).
|
| 155 |
+
3. **Visual Style:**
|
| 156 |
+
* **Strictly follow** any "Visual Style Requirements" (Decoration, Theme) provided in the user prompt.
|
| 157 |
+
* {static_palette_instr}
|
| 158 |
+
4. **Structure:**
|
| 159 |
+
* Use semantic HTML5.
|
| 160 |
+
* Use modern CSS (Flexbox, Grid).
|
| 161 |
+
* Keep scripts at the end of the body.
|
| 162 |
+
|
| 163 |
+
**Output Format:**
|
| 164 |
+
Return ONLY the raw HTML code. No markdown explanations.
|
| 165 |
+
"""
|