GitHub Action commited on
Commit
3f80c6a
·
1 Parent(s): 40b06b6

Sync ling-space changes from GitHub commit 2ca584b

Browse files
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 💍
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: gradio
7
- sdk_version: 5.49.1
8
  python_version: 3.13.7
9
  app_file: app.py
10
  pinned: false
 
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: gradio
7
+ sdk_version: 6.0.1
8
  python_version: 3.13.7
9
  app_file: app.py
10
  pinned: false
app.py CHANGED
@@ -1,6 +1,7 @@
1
  import gradio as gr
2
  import uuid
3
  from datetime import datetime
 
4
  import pandas as pd
5
  from model_handler import ModelHandler
6
  from tab_chat import create_chat_tab
@@ -64,10 +65,7 @@ if __name__ == "__main__":
64
  # Instantiate the model handler with the configuration
65
  model_handler = ModelHandler()
66
 
67
- with gr.Blocks(theme=gr.themes.Soft(),
68
- css=CSS,
69
- head="",
70
- head_paths=['./static/toastify.html', './static/app.html'],
71
  fill_height=True,
72
  fill_width=True) as demo:
73
  with gr.Tabs(elem_id='indicator-space-app') as tabs:
@@ -112,4 +110,7 @@ if __name__ == "__main__":
112
  )
113
 
114
  # Launch the Gradio application
115
- demo.launch()
 
 
 
 
1
  import gradio as gr
2
  import uuid
3
  from datetime import datetime
4
+ from gradio.analytics import ANALYTICS_URL
5
  import pandas as pd
6
  from model_handler import ModelHandler
7
  from tab_chat import create_chat_tab
 
65
  # Instantiate the model handler with the configuration
66
  model_handler = ModelHandler()
67
 
68
+ with gr.Blocks(analytics_enabled=False,
 
 
 
69
  fill_height=True,
70
  fill_width=True) as demo:
71
  with gr.Tabs(elem_id='indicator-space-app') as tabs:
 
110
  )
111
 
112
  # Launch the Gradio application
113
+ demo.launch(theme=gr.themes.Default(),
114
+ css=CSS,
115
+ head="",
116
+ head_paths=['./static/toastify.html', './static/app.html'])
code_kit/__init__.py ADDED
File without changes
code_kit/agent_code_generator.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import time
3
+ import logging
4
+ import os
5
+ from model_handler import ModelHandler
6
+ from tab_code_prompts.html_system_prompt import get_html_system_prompt
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()
16
+ except FileNotFoundError:
17
+ logger.error("Error: static/catch-error.js not found. The error catching overlay will not work.")
18
+ CATCH_ERROR_JS_SCRIPT = ""
19
+
20
+ def get_spinner_html():
21
+ """Return HTML with a CSS spinner animation"""
22
+ return """
23
+ <div style="width: 100%; height: 600px; display: flex; justify-content: center; align-items: center; border: 1px solid #ddd; background-color: #f9f9f9;">
24
+ <div class="spinner"></div>
25
+ </div>
26
+ <style>
27
+ .spinner {
28
+ border: 4px solid rgba(0, 0, 0, 0.1);
29
+ width: 36px;
30
+ height: 36px;
31
+ border-radius: 50%;
32
+ border-left-color: #09f;
33
+ animation: spin 1s ease infinite;
34
+ }
35
+ @keyframes spin {
36
+ 0% { transform: rotate(0deg); }
37
+ 100% { transform: rotate(360deg); }
38
+ }
39
+ </style>
40
+ """
41
+
42
+ def code_generation_agent(code_type, model_choice, user_prompt, color_palette, decoration_style, overall_style, chatbot_history):
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: {code_type}, Model: {model_choice}, Prompt: '{user_prompt}'")
46
+
47
+ if not user_prompt:
48
+ chatbot_history.append({"role": "assistant", "content": "🚨 **错误**: 请输入提示词。"})
49
+ yield "", gr.update(value="<p>预览将在此处显示。</p>"), chatbot_history, gr.update()
50
+ return
51
+
52
+ chatbot_history.append({"role": "assistant", "content": "⏳ 开始生成代码..."})
53
+ yield "", gr.HTML(get_spinner_html()), chatbot_history, gr.update()
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("'", "&apos;").replace('"', '&quot;')
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}'
61
+ style="position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; border: none;">
62
+ </iframe>
63
+ </div>
64
+ """
65
+ chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 已生成一个用于测试的错误页面。"})
66
+ yield error_code, gr.update(value=final_preview_html), chatbot_history, gr.Tabs(selected=0)
67
+ return
68
+
69
+ # --- Append Style Prompt ---
70
+ full_user_prompt = user_prompt
71
+
72
+ if color_palette or decoration_style or overall_style:
73
+ full_user_prompt += "\n\n--- Visual Style Requirements (Strictly Follow These) ---\n"
74
+ if overall_style:
75
+ full_user_prompt += f"Overall Theme/Vibe: {overall_style}\n"
76
+ if decoration_style:
77
+ full_user_prompt += f"UI Decoration Style: {decoration_style}\n"
78
+ if color_palette:
79
+ full_user_prompt += f"Color Palette Mapping (Use these colors for their assigned roles): {color_palette}\n"
80
+
81
+ logger.info(f"Full Prompt with Style: {full_user_prompt}")
82
+ # ---------------------------
83
+
84
+ start_time = time.time()
85
+ model_handler = ModelHandler()
86
+
87
+ if code_type == "静态页面":
88
+ system_prompt = get_html_system_prompt()
89
+ full_code_with_think = ""
90
+ full_code_for_preview = ""
91
+ buffer = ""
92
+ is_thinking = False
93
+
94
+ for code_chunk in model_handler.generate_code(system_prompt, full_user_prompt, model_choice):
95
+ full_code_with_think += code_chunk
96
+ buffer += code_chunk
97
+
98
+ while True:
99
+ if is_thinking:
100
+ end_index = buffer.find("</think>")
101
+ if end_index != -1:
102
+ is_thinking = False
103
+ buffer = buffer[end_index + len("</think>"):]
104
+ else:
105
+ break
106
+ else:
107
+ start_index = buffer.find("<think>")
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
+ chatbot_history.append({"role": "assistant", "content": log_message})
133
+
134
+ yield full_code_with_think, gr.update(), chatbot_history, gr.update()
135
+
136
+ escaped_code = full_code_for_preview.replace("'", "&apos;").replace('"', '&quot;')
137
+ final_preview_html = f"""
138
+ <div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
139
+ <iframe srcdoc='{escaped_code}'
140
+ style="position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; border: none;">
141
+ </iframe>
142
+ </div>
143
+ """
144
+ chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 代码生成完成!"})
145
+ yield full_code_with_think, gr.HTML(final_preview_html), chatbot_history, gr.Tabs(selected=0)
146
+ logger.info("Static page streaming finished.")
code_kit/agent_style_generator.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import gradio as gr
3
+ from model_handler import ModelHandler
4
+ from config import LING_FLASH_2_0
5
+
6
+ def format_palette_html(palette_data):
7
+ """
8
+ Generates an HTML string to display color boxes with roles.
9
+ palette_data: List of dicts {'role': str, 'hex': str} or list of strings (fallback)
10
+ """
11
+ html = '<div style="display: flex; gap: 10px; margin-top: 5px; flex-wrap: wrap;">'
12
+
13
+ for item in palette_data:
14
+ if isinstance(item, dict):
15
+ color = item.get("hex", "#000000")
16
+ role = item.get("role", "")
17
+ else:
18
+ color = item
19
+ role = ""
20
+
21
+ html += f'''
22
+ <div style="display: flex; flex-direction: column; align-items: center; width: 60px;">
23
+ <div style="width: 40px; height: 40px; background-color: {color}; border-radius: 8px; border: 1px solid #ccc; box-shadow: 0 2px 4px rgba(0,0,0,0.1);" title="{role}: {color}"></div>
24
+ <span style="font-size: 9px; color: #666; margin-top: 4px; text-align: center; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 100%;">{role}</span>
25
+ <span style="font-size: 9px; color: #999; text-align: center;">{color}</span>
26
+ </div>
27
+ '''
28
+ html += '</div>'
29
+ return html
30
+
31
+ def generate_random_style(current_model_display_name):
32
+ """
33
+ Generates a random web design style using the LLM.
34
+ """
35
+ model_choice = LING_FLASH_2_0
36
+
37
+ system_prompt = """
38
+ You are a creative Design Director. Your task is to generate a unique, cohesive visual style for a web interface.
39
+
40
+ Return ONLY a valid JSON object with the following keys:
41
+ 1. "palette": A list of 6 to 8 color objects, where each object has:
42
+ - "role": A descriptive name for the color usage (e.g., "Page Background", "Card/Surface", "Primary Text", "Secondary Text", "Brand/Action Color", "Accent/Highlight", "Border/Divider").
43
+ - "hex": The hexadecimal color code.
44
+ 2. "decoration": A concise description (10-20 words) of the UI decoration style (e.g., "Neo-brutalism with thick black borders and hard shadows", "Glassmorphism with high blur and white transparency").
45
+ 3. "theme": A creative, metaphorical description (5-10 words) of the overall vibe (e.g., "Cyberpunk Neon City", "Minimalist Zen Garden").
46
+
47
+ Ensure the colors contrast well (especially text on background) and the roles make sense for a standard web layout.
48
+ Do not include any markdown formatting (like ```json). Just the raw JSON string.
49
+ """
50
+
51
+ user_prompt = "Generate a new random design style now."
52
+
53
+ model_handler = ModelHandler()
54
+
55
+ full_response = ""
56
+ for chunk in model_handler.generate_code(system_prompt, user_prompt, model_choice):
57
+ full_response += chunk
58
+
59
+ clean_response = full_response.strip()
60
+ if clean_response.startswith("```json"):
61
+ clean_response = clean_response[7:]
62
+ if clean_response.startswith("```"):
63
+ clean_response = clean_response[3:]
64
+ if clean_response.endswith("```"):
65
+ clean_response = clean_response[:-3]
66
+ clean_response = clean_response.strip()
67
+
68
+ try:
69
+ style_data = json.loads(clean_response)
70
+ palette = style_data.get("palette", [])
71
+
72
+ # Validate palette structure, fallback if it's just a list of strings (old format)
73
+ if palette and isinstance(palette[0], str):
74
+ palette = [{"role": f"Color {i+1}", "hex": c} for i, c in enumerate(palette)]
75
+
76
+ if not palette:
77
+ palette = [
78
+ {"role": "Background", "hex": "#F0F0F0"},
79
+ {"role": "Text", "hex": "#333333"},
80
+ {"role": "Accent", "hex": "#007BFF"}
81
+ ]
82
+
83
+ decoration = style_data.get("decoration", "Standard modern web style.")
84
+ theme = style_data.get("theme", "Default Theme")
85
+
86
+ palette_html = format_palette_html(palette)
87
+
88
+ # Create a structured string for the prompt
89
+ # e.g., "Page Background: #FFF, Primary Text: #000, ..."
90
+ palette_str = ", ".join([f"{p['role']}: {p['hex']}" for p in palette])
91
+
92
+ return palette_html, palette_str, decoration, theme
93
+
94
+ except json.JSONDecodeError as e:
95
+ print(f"Error parsing style JSON: {e}. Response: {full_response}")
96
+ fallback_palette = [
97
+ {"role": "Background", "hex": "#FFFFFF"},
98
+ {"role": "Primary Text", "hex": "#000000"},
99
+ {"role": "Action", "hex": "#007BFF"},
100
+ {"role": "Error", "hex": "#DC3545"}
101
+ ]
102
+ return format_palette_html(fallback_palette), ", ".join([f"{p['role']}: {p['hex']}" for p in fallback_palette]), "Simple and clean.", "Fallback Default"
code_kit/code_examples.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from config import LING_1T, LING_FLASH_2_0, get_model_display_name
2
+
3
+ """
4
+ This file contains the recommended initial inputs for the code generation tab.
5
+ """
6
+
7
+ CODE_EXAMPLES = [
8
+ {
9
+ "task": "知识讲解",
10
+ "model": get_model_display_name(LING_1T),
11
+ "user_prompt": "创建一个关于‘深度学习基础’的交互式学习网页。包含:1. 核心概念卡片(神经网络、反向传播等);2. 一个简单的交互式图解;3. 常见问题解答部分。"
12
+ },
13
+ {
14
+ "task": "行业分析",
15
+ "model": get_model_display_name(LING_1T),
16
+ "user_prompt": "生成一份 2025 年新能源汽车行业分析报告网页。页面应包含:1. 带有数据可视化的市场趋势概览;2. 主要厂商的对比表格;3. 行业挑战与机遇的模块化展示。"
17
+ },
18
+ {
19
+ "task": "Hello World",
20
+ "model": get_model_display_name(LING_FLASH_2_0),
21
+ "user_prompt": "编写一个 Hello World 弹窗"
22
+ },
23
+ {
24
+ "task": "烟花动画",
25
+ "model": get_model_display_name(LING_1T),
26
+ "user_prompt": "创建一个黑色背景上五彩烟花连续绽放的 Canvas 动画"
27
+ },
28
+ {
29
+ "task": "流光特效",
30
+ "model": get_model_display_name(LING_1T),
31
+ "user_prompt": "生成一个带有五彩流光的 Canvas 特效"
32
+ },
33
+ {
34
+ "task": "报错测试",
35
+ "model": get_model_display_name(LING_FLASH_2_0),
36
+ "user_prompt": "创建一个报错示例"
37
+ }
38
+ ]
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- gradio==5.49.1
2
  python-dotenv
3
  httpx
4
  # transformers
 
1
+ gradio==6.0.1
2
  python-dotenv
3
  httpx
4
  # transformers
tab_chat.py CHANGED
@@ -69,7 +69,7 @@ def create_chat_tab():
69
  )
70
 
71
  with gr.Column(scale=4):
72
- chatbot = gr.Chatbot(height=500, type='messages')
73
  with gr.Row():
74
  textbox = gr.Textbox(placeholder="输入消息...", container=False, scale=7)
75
  submit_btn = gr.Button("发送", scale=1)
@@ -157,4 +157,4 @@ def create_chat_tab():
157
  new_chat_btn.click(handle_new_chat, inputs=[conversation_store, current_conversation_id], outputs=[current_conversation_id, conversation_store, chatbot, history_df])
158
  history_df.select(load_conversation_from_df, inputs=[history_df, conversation_store], outputs=[current_conversation_id, chatbot])
159
 
160
- return conversation_store, current_conversation_id, history_df, chatbot
 
69
  )
70
 
71
  with gr.Column(scale=4):
72
+ chatbot = gr.Chatbot(height=500)
73
  with gr.Row():
74
  textbox = gr.Textbox(placeholder="输入消息...", container=False, scale=7)
75
  submit_btn = gr.Button("发送", scale=1)
 
157
  new_chat_btn.click(handle_new_chat, inputs=[conversation_store, current_conversation_id], outputs=[current_conversation_id, conversation_store, chatbot, history_df])
158
  history_df.select(load_conversation_from_df, inputs=[history_df, conversation_store], outputs=[current_conversation_id, chatbot])
159
 
160
+ return conversation_store, current_conversation_id, history_df, chatbot
tab_code.py CHANGED
@@ -1,137 +1,15 @@
1
  import gradio as gr
2
- import time
3
  import logging
4
- from model_handler import ModelHandler
5
  from config import CHAT_MODEL_SPECS, LING_1T, CODE_FRAMEWORK_SPECS, STATIC_PAGE
6
  from ui_components.model_selector import create_model_selector
7
  from ui_components.code_framework_selector import create_code_framework_selector
8
- from tab_code_prompts.html_system_prompt import get_html_system_prompt
 
 
9
 
10
  # Configure logging
11
  logger = logging.getLogger(__name__)
12
 
13
- # Read the content of the JavaScript file for error catching
14
- try:
15
- with open("static/catch-error.js", "r", encoding="utf-8") as f:
16
- CATCH_ERROR_JS_SCRIPT = f.read()
17
- except FileNotFoundError:
18
- logger.error("Error: static/catch-error.js not found. The error catching overlay will not work.")
19
- CATCH_ERROR_JS_SCRIPT = ""
20
-
21
-
22
- def get_spinner_html():
23
- """Return HTML with a CSS spinner animation"""
24
- return """
25
- <div style="width: 100%; height: 600px; display: flex; justify-content: center; align-items: center; border: 1px solid #ddd; background-color: #f9f9f9;">
26
- <div class="spinner"></div>
27
- </div>
28
- <style>
29
- .spinner {
30
- border: 4px solid rgba(0, 0, 0, 0.1);
31
- width: 36px;
32
- height: 36px;
33
- border-radius: 50%;
34
- border-left-color: #09f;
35
- animation: spin 1s ease infinite;
36
- }
37
- @keyframes spin {
38
- 0% { transform: rotate(0deg); }
39
- 100% { transform: rotate(360deg); }
40
- }
41
- </style>
42
- """
43
-
44
- def generate_code(code_type, model_choice, user_prompt, chatbot_history):
45
- """Generate code and provide a preview, updating a log stream chatbot."""
46
- logger.info(f"--- [Code Generation] Start ---")
47
- logger.info(f"Code Type: {code_type}, Model: {model_choice}, Prompt: '{user_prompt}'")
48
-
49
- if not user_prompt:
50
- chatbot_history.append({"role": "assistant", "content": "🚨 **错误**: 请输入提示词。"})
51
- yield "", gr.update(value="<p>预览将在此处显示。</p>"), chatbot_history, gr.update()
52
- return
53
-
54
- chatbot_history.append({"role": "assistant", "content": "⏳ 开始生成代码..."})
55
- yield "", gr.HTML(get_spinner_html()), chatbot_history, gr.update()
56
-
57
- if user_prompt == "create an error":
58
- error_code = f"""<h1>This will create an error</h1><script>{CATCH_ERROR_JS_SCRIPT}</script><script>nonExistentFunction();</script>""";
59
- escaped_code = error_code.replace("'", "&apos;").replace('"', '&quot;')
60
- final_preview_html = f"""
61
- <div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
62
- <iframe srcdoc='{escaped_code}'
63
- style="position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; border: none;">
64
- </iframe>
65
- </div>
66
- """
67
- chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 已生成一个用于测试的错误页面。"})
68
- yield error_code, gr.update(value=final_preview_html), chatbot_history, gr.Tabs(selected=0)
69
- return
70
-
71
- start_time = time.time()
72
- model_handler = ModelHandler()
73
-
74
- if code_type == "静态页面":
75
- system_prompt = get_html_system_prompt()
76
- full_code_with_think = ""
77
- full_code_for_preview = ""
78
- buffer = ""
79
- is_thinking = False
80
-
81
- for code_chunk in model_handler.generate_code(system_prompt, user_prompt, model_choice):
82
- full_code_with_think += code_chunk
83
- buffer += code_chunk
84
-
85
- while True:
86
- if is_thinking:
87
- end_index = buffer.find("</think>")
88
- if end_index != -1:
89
- is_thinking = False
90
- buffer = buffer[end_index + len("</think>"):]
91
- else:
92
- break
93
- else:
94
- start_index = buffer.find("<think>")
95
- if start_index != -1:
96
- part_to_add = buffer[:start_index]
97
- full_code_for_preview += part_to_add
98
- is_thinking = True
99
- buffer = buffer[start_index:]
100
- else:
101
- full_code_for_preview += buffer
102
- buffer = ""
103
- break
104
-
105
- elapsed_time = time.time() - start_time
106
- generated_length = len(full_code_with_think)
107
- speed = generated_length / elapsed_time if elapsed_time > 0 else 0
108
-
109
- log_message = f"""
110
- **⏳ 正在生成中...**
111
- - **时间:** {elapsed_time:.2f}s
112
- - **长度:** {generated_length} chars
113
- - **速度:** {speed:.2f} char/s
114
- """
115
-
116
- if len(chatbot_history) > 0 and "正在生成中" in chatbot_history[-1]["content"]:
117
- chatbot_history[-1] = {"role": "assistant", "content": log_message}
118
- else:
119
- chatbot_history.append({"role": "assistant", "content": log_message})
120
-
121
- yield full_code_with_think, gr.update(), chatbot_history, gr.update()
122
-
123
- escaped_code = full_code_for_preview.replace("'", "&apos;").replace('"', '&quot;')
124
- final_preview_html = f"""
125
- <div style="width: 100%; height: 600px; border: 1px solid #ddd; overflow: hidden; position: relative; background-color: #f9f9f9;">
126
- <iframe srcdoc='{escaped_code}'
127
- style="position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: 0 0; border: none;">
128
- </iframe>
129
- </div>
130
- """
131
- chatbot_history.append({"role": "assistant", "content": "✅ **成功**: 代码生成完成!"})
132
- yield full_code_with_think, gr.HTML(final_preview_html), chatbot_history, gr.Tabs(selected=0)
133
- logger.info("Static page streaming finished.")
134
-
135
  def refresh_preview(code_type, current_code, chatbot_history):
136
  """Refresh the preview and add a log entry."""
137
  logger.info(f"--- [Manual Refresh] Start ---")
@@ -175,13 +53,6 @@ def log_js_error(error_text, chatbot_history):
175
 
176
  def create_code_tab():
177
  fullscreen_state = gr.State(False)
178
-
179
- html_examples = [
180
- "Write a hello world alert",
181
- "Create a Canvas animation of continuous colorful fireworks blooming on a black background.",
182
- "Generate a Canvas special effect with iridescent light streams.",
183
- "create an error"
184
- ]
185
 
186
  with gr.Row(elem_id="indicator-code-tab"):
187
  with gr.Column(scale=1) as left_panel:
@@ -195,8 +66,29 @@ def create_code_tab():
195
  default_model_constant=LING_1T
196
  )
197
  prompt_input = gr.Textbox(lines=5, placeholder="例如:创建一个带标题和按钮的简单页面", label="提示词")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  with gr.Column():
199
- gr.Examples(examples=html_examples, inputs=prompt_input, label=" 试试这些酷炫的例子吧")
 
 
 
 
 
 
200
  generate_button = gr.Button("生成代码", variant="primary")
201
 
202
  with gr.Column(scale=4):
@@ -212,10 +104,33 @@ def create_code_tab():
212
  refresh_button = gr.Button("刷新预览")
213
 
214
  with gr.Column(scale=1):
215
- log_chatbot = gr.Chatbot(label="生成日志", height=300, type="messages")
216
 
217
  js_error_channel = gr.Textbox(visible=True, elem_classes=["js_error_channel"], label="Debug Error Channel", interactive=False)
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  refresh_button.click(
220
  fn=refresh_preview,
221
  inputs=[code_framework_dropdown, code_output, log_chatbot],
@@ -223,8 +138,16 @@ def create_code_tab():
223
  )
224
 
225
  generate_button.click(
226
- fn=generate_code,
227
- inputs=[code_framework_dropdown, model_choice_dropdown, prompt_input, log_chatbot],
 
 
 
 
 
 
 
 
228
  outputs=[code_output, preview_output, log_chatbot, result_tabs]
229
  )
230
 
 
1
  import gradio as gr
 
2
  import logging
 
3
  from config import CHAT_MODEL_SPECS, LING_1T, CODE_FRAMEWORK_SPECS, STATIC_PAGE
4
  from ui_components.model_selector import create_model_selector
5
  from ui_components.code_framework_selector import create_code_framework_selector
6
+ from code_kit.agent_code_generator import code_generation_agent
7
+ from code_kit.agent_style_generator import generate_random_style
8
+ from code_kit.code_examples import CODE_EXAMPLES
9
 
10
  # Configure logging
11
  logger = logging.getLogger(__name__)
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  def refresh_preview(code_type, current_code, chatbot_history):
14
  """Refresh the preview and add a log entry."""
15
  logger.info(f"--- [Manual Refresh] Start ---")
 
53
 
54
  def create_code_tab():
55
  fullscreen_state = gr.State(False)
 
 
 
 
 
 
 
56
 
57
  with gr.Row(elem_id="indicator-code-tab"):
58
  with gr.Column(scale=1) as left_panel:
 
66
  default_model_constant=LING_1T
67
  )
68
  prompt_input = gr.Textbox(lines=5, placeholder="例如:创建一个带标题和按钮的简单页面", label="提示词")
69
+
70
+ # --- Style Settings Section ---
71
+ with gr.Group(visible=True, elem_classes="style-settings-group"):
72
+ gr.Markdown("#### 🎨 设置网页风格")
73
+ with gr.Row():
74
+ palette_display = gr.HTML(value='<div style="color: #999; font-size: 12px;">暂无配色</div>', label="配色预览")
75
+ # Hidden textbox to store the raw palette string for the prompt
76
+ palette_input = gr.Textbox(visible=False, label="Palette (Raw)")
77
+
78
+ decoration_input = gr.Textbox(label="装饰风格", placeholder="例如:粗边框,无圆角", lines=1)
79
+ overall_style_input = gr.Textbox(label="整体风格", placeholder="例如:类似一本羊皮纸的书", lines=1)
80
+
81
+ generate_style_btn = gr.Button("🎲 随机生成风格", size="sm")
82
+ # ------------------------------
83
+
84
  with gr.Column():
85
+ gr.Markdown("### 示例")
86
+ examples_dataset = gr.Dataset(
87
+ components=[gr.Textbox(visible=False)],
88
+ samples=[[item["task"]] for item in CODE_EXAMPLES],
89
+ label="示例",
90
+ headers=["选择一个示例"],
91
+ )
92
  generate_button = gr.Button("生成代码", variant="primary")
93
 
94
  with gr.Column(scale=4):
 
104
  refresh_button = gr.Button("刷新预览")
105
 
106
  with gr.Column(scale=1):
107
+ log_chatbot = gr.Chatbot(label="生成日志", height=300)
108
 
109
  js_error_channel = gr.Textbox(visible=True, elem_classes=["js_error_channel"], label="Debug Error Channel", interactive=False)
110
 
111
+ # Event Handler for Example Selection
112
+ def on_select_example(evt: gr.SelectData):
113
+ selected_task = evt.value[0]
114
+ item = next((i for i in CODE_EXAMPLES if i["task"] == selected_task), None)
115
+ if not item:
116
+ return gr.update(), gr.update()
117
+
118
+ return gr.update(value=item["user_prompt"]), gr.update(value=item["model"])
119
+
120
+ examples_dataset.select(
121
+ fn=on_select_example,
122
+ inputs=None,
123
+ outputs=[prompt_input, model_choice_dropdown],
124
+ show_progress="none"
125
+ )
126
+
127
+ # Event Handler for Style Generation
128
+ generate_style_btn.click(
129
+ fn=generate_random_style,
130
+ inputs=[model_choice_dropdown],
131
+ outputs=[palette_display, palette_input, decoration_input, overall_style_input]
132
+ )
133
+
134
  refresh_button.click(
135
  fn=refresh_preview,
136
  inputs=[code_framework_dropdown, code_output, log_chatbot],
 
138
  )
139
 
140
  generate_button.click(
141
+ fn=code_generation_agent,
142
+ inputs=[
143
+ code_framework_dropdown,
144
+ model_choice_dropdown,
145
+ prompt_input,
146
+ palette_input, # Pass the raw palette string
147
+ decoration_input,
148
+ overall_style_input,
149
+ log_chatbot
150
+ ],
151
  outputs=[code_output, preview_output, log_chatbot, result_tabs]
152
  )
153