add svelte app support
Browse files
app.py
CHANGED
@@ -90,6 +90,81 @@ The style.css should contain all the styling for the application.
|
|
90 |
|
91 |
Always output only the three code blocks as shown above, and do not include any explanations or extra text."""
|
92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert web developer creating a transformers.js application. You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific technologies for transformers.js.
|
94 |
|
95 |
You will generate THREE separate files: index.html, index.js, and style.css.
|
@@ -360,6 +435,10 @@ DEMO_LIST = [
|
|
360 |
{
|
361 |
"title": "Transformers.js App",
|
362 |
"description": "Create a transformers.js application with AI/ML functionality using the transformers.js library"
|
|
|
|
|
|
|
|
|
363 |
}
|
364 |
]
|
365 |
|
@@ -522,6 +601,39 @@ def format_transformers_js_output(files):
|
|
522 |
output.append(files['style.css'])
|
523 |
return '\n'.join(output)
|
524 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
525 |
def history_render(history: History):
|
526 |
return gr.update(visible=True), history
|
527 |
|
@@ -1246,7 +1358,8 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
|
|
1246 |
'IMPORTED PROJECT FROM HUGGING FACE SPACE' in last_assistant_msg or
|
1247 |
'=== index.html ===' in last_assistant_msg or
|
1248 |
'=== index.js ===' in last_assistant_msg or
|
1249 |
-
'=== style.css ===' in last_assistant_msg
|
|
|
1250 |
has_existing_content = True
|
1251 |
|
1252 |
# Choose system prompt based on context
|
@@ -1254,6 +1367,8 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
|
|
1254 |
# Use follow-up prompt for modifying existing content
|
1255 |
if language == "transformers.js":
|
1256 |
system_prompt = TransformersJSFollowUpSystemPrompt
|
|
|
|
|
1257 |
else:
|
1258 |
system_prompt = FollowUpSystemPrompt
|
1259 |
else:
|
@@ -1262,6 +1377,8 @@ def generation_code(query: Optional[str], image: Optional[gr.Image], file: Optio
|
|
1262 |
system_prompt = HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else HTML_SYSTEM_PROMPT
|
1263 |
elif language == "transformers.js":
|
1264 |
system_prompt = TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH if enable_search else TRANSFORMERS_JS_SYSTEM_PROMPT
|
|
|
|
|
1265 |
else:
|
1266 |
system_prompt = GENERIC_SYSTEM_PROMPT_WITH_SEARCH.format(language=language) if enable_search else GENERIC_SYSTEM_PROMPT.format(language=language)
|
1267 |
|
@@ -1351,6 +1468,14 @@ This will help me create a better design for you."""
|
|
1351 |
history_output: history_to_chatbot_messages(_history),
|
1352 |
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Generating transformers.js app...</div>",
|
1353 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1354 |
else:
|
1355 |
clean_code = remove_code_block(content)
|
1356 |
if has_existing_content:
|
@@ -1414,6 +1539,39 @@ This will help me create a better design for you."""
|
|
1414 |
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Error parsing transformers.js output. Please try again.</div>",
|
1415 |
history_output: history_to_chatbot_messages(_history),
|
1416 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1417 |
elif has_existing_content:
|
1418 |
# Handle modification of existing content
|
1419 |
final_code = remove_code_block(content)
|
@@ -1655,7 +1813,7 @@ with gr.Blocks(
|
|
1655 |
)
|
1656 |
# Language dropdown for code generation
|
1657 |
language_choices = [
|
1658 |
-
"html", "python", "c", "cpp", "markdown", "latex", "json", "css", "javascript", "jinja2", "typescript", "yaml", "dockerfile", "shell", "r", "sql", "sql-msSQL", "sql-mySQL", "sql-mariaDB", "sql-sqlite", "sql-cassandra", "sql-plSQL", "sql-hive", "sql-pgSQL", "sql-gql", "sql-gpSQL", "sql-sparkSQL", "sql-esper"
|
1659 |
]
|
1660 |
language_dropdown = gr.Dropdown(
|
1661 |
choices=language_choices,
|
@@ -1692,7 +1850,8 @@ with gr.Blocks(
|
|
1692 |
("Gradio (Python)", "gradio"),
|
1693 |
("Streamlit (Python)", "streamlit"),
|
1694 |
("Static (HTML)", "static"),
|
1695 |
-
("Transformers.js", "transformers.js")
|
|
|
1696 |
]
|
1697 |
sdk_dropdown = gr.Dropdown(
|
1698 |
choices=[x[0] for x in sdk_choices],
|
@@ -1804,6 +1963,8 @@ with gr.Blocks(
|
|
1804 |
def update_sdk_based_on_language(language):
|
1805 |
if language == "transformers.js":
|
1806 |
return gr.update(value="Transformers.js")
|
|
|
|
|
1807 |
elif language == "html":
|
1808 |
return gr.update(value="Static (HTML)")
|
1809 |
else:
|
@@ -1822,6 +1983,9 @@ with gr.Blocks(
|
|
1822 |
return send_to_sandbox(files['index.html'])
|
1823 |
else:
|
1824 |
return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
|
|
|
|
|
|
|
1825 |
else:
|
1826 |
return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
|
1827 |
|
@@ -1905,7 +2069,8 @@ with gr.Blocks(
|
|
1905 |
"Gradio (Python)": "gradio",
|
1906 |
"Streamlit (Python)": "docker", # Use 'docker' for Streamlit Spaces
|
1907 |
"Static (HTML)": "static",
|
1908 |
-
"Transformers.js": "static" # Transformers.js uses static SDK
|
|
|
1909 |
}
|
1910 |
sdk = sdk_map.get(sdk_name, "gradio")
|
1911 |
|
@@ -2060,6 +2225,106 @@ with gr.Blocks(
|
|
2060 |
|
2061 |
except Exception as e:
|
2062 |
return gr.update(value=f"Error duplicating Transformers.js space: {e}. If this is a RepoUrl object error, ensure you are not accessing a .url attribute and use str(duplicated_repo) for the URL.", visible=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2063 |
# Other SDKs (existing logic)
|
2064 |
if sdk == "static":
|
2065 |
import time
|
|
|
90 |
|
91 |
Always output only the three code blocks as shown above, and do not include any explanations or extra text."""
|
92 |
|
93 |
+
SVELTE_SYSTEM_PROMPT = """You are an expert Svelte developer creating a modern Svelte application. You will generate ONLY the custom files that need user-specific content.
|
94 |
+
|
95 |
+
IMPORTANT: You MUST output ONLY the custom files in the following format:
|
96 |
+
|
97 |
+
```svelte
|
98 |
+
<!-- src/App.svelte content here -->
|
99 |
+
```
|
100 |
+
|
101 |
+
```css
|
102 |
+
/* src/app.css content here */
|
103 |
+
```
|
104 |
+
|
105 |
+
```svelte
|
106 |
+
<!-- src/lib/Counter.svelte content here -->
|
107 |
+
```
|
108 |
+
|
109 |
+
Requirements:
|
110 |
+
1. Create a modern, responsive Svelte application
|
111 |
+
2. Use TypeScript for better type safety
|
112 |
+
3. Create a clean, professional UI with good user experience
|
113 |
+
4. Make the application fully responsive for mobile devices
|
114 |
+
5. Use modern CSS practices and Svelte best practices
|
115 |
+
6. Include proper error handling and loading states
|
116 |
+
7. Follow accessibility best practices
|
117 |
+
8. Use Svelte's reactive features effectively
|
118 |
+
9. Include proper component structure and organization
|
119 |
+
|
120 |
+
The files you generate are:
|
121 |
+
- src/App.svelte: Main application component (your custom app logic)
|
122 |
+
- src/app.css: Global styles (your custom styling)
|
123 |
+
- src/lib/Counter.svelte: Example component (your custom components)
|
124 |
+
|
125 |
+
The other files (index.html, package.json, vite.config.ts, tsconfig files, svelte.config.js, src/main.ts, src/vite-env.d.ts) are provided by the Svelte template and don't need to be generated.
|
126 |
+
|
127 |
+
Always output only the three code blocks as shown above, and do not include any explanations or extra text."""
|
128 |
+
|
129 |
+
SVELTE_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert Svelte developer creating a modern Svelte application. You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific Svelte technologies.
|
130 |
+
|
131 |
+
You will generate ONLY the custom files that need user-specific content.
|
132 |
+
|
133 |
+
IMPORTANT: You MUST output ONLY the custom files in the following format:
|
134 |
+
|
135 |
+
```svelte
|
136 |
+
<!-- src/App.svelte content here -->
|
137 |
+
```
|
138 |
+
|
139 |
+
```css
|
140 |
+
/* src/app.css content here */
|
141 |
+
```
|
142 |
+
|
143 |
+
```svelte
|
144 |
+
<!-- src/lib/Counter.svelte content here -->
|
145 |
+
```
|
146 |
+
|
147 |
+
Requirements:
|
148 |
+
1. Create a modern, responsive Svelte application
|
149 |
+
2. Use TypeScript for better type safety
|
150 |
+
3. Create a clean, professional UI with good user experience
|
151 |
+
4. Make the application fully responsive for mobile devices
|
152 |
+
5. Use modern CSS practices and Svelte best practices
|
153 |
+
6. Include proper error handling and loading states
|
154 |
+
7. Follow accessibility best practices
|
155 |
+
8. Use Svelte's reactive features effectively
|
156 |
+
9. Include proper component structure and organization
|
157 |
+
10. Use web search to find the latest Svelte patterns, libraries, and best practices
|
158 |
+
|
159 |
+
The files you generate are:
|
160 |
+
- src/App.svelte: Main application component (your custom app logic)
|
161 |
+
- src/app.css: Global styles (your custom styling)
|
162 |
+
- src/lib/Counter.svelte: Example component (your custom components)
|
163 |
+
|
164 |
+
The other files (index.html, package.json, vite.config.ts, tsconfig files, svelte.config.js, src/main.ts, src/vite-env.d.ts) are provided by the Svelte template and don't need to be generated.
|
165 |
+
|
166 |
+
Always output only the three code blocks as shown above, and do not include any explanations or extra text."""
|
167 |
+
|
168 |
TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH = """You are an expert web developer creating a transformers.js application. You have access to real-time web search. When needed, use web search to find the latest information, best practices, or specific technologies for transformers.js.
|
169 |
|
170 |
You will generate THREE separate files: index.html, index.js, and style.css.
|
|
|
435 |
{
|
436 |
"title": "Transformers.js App",
|
437 |
"description": "Create a transformers.js application with AI/ML functionality using the transformers.js library"
|
438 |
+
},
|
439 |
+
{
|
440 |
+
"title": "Svelte App",
|
441 |
+
"description": "Create a modern Svelte application with TypeScript, Vite, and responsive design"
|
442 |
}
|
443 |
]
|
444 |
|
|
|
601 |
output.append(files['style.css'])
|
602 |
return '\n'.join(output)
|
603 |
|
604 |
+
def parse_svelte_output(text):
|
605 |
+
"""Parse Svelte output to extract individual files"""
|
606 |
+
files = {
|
607 |
+
'src/App.svelte': '',
|
608 |
+
'src/app.css': '',
|
609 |
+
'src/lib/Counter.svelte': ''
|
610 |
+
}
|
611 |
+
|
612 |
+
# Split by code blocks
|
613 |
+
import re
|
614 |
+
code_blocks = re.findall(r'```(?:svelte|css)\n(.*?)```', text, re.DOTALL)
|
615 |
+
|
616 |
+
# Handle partial generation - assign what we have
|
617 |
+
if len(code_blocks) >= 1:
|
618 |
+
files['src/App.svelte'] = code_blocks[0].strip()
|
619 |
+
if len(code_blocks) >= 2:
|
620 |
+
files['src/app.css'] = code_blocks[1].strip()
|
621 |
+
if len(code_blocks) >= 3:
|
622 |
+
files['src/lib/Counter.svelte'] = code_blocks[2].strip()
|
623 |
+
|
624 |
+
return files
|
625 |
+
|
626 |
+
def format_svelte_output(files):
|
627 |
+
"""Format Svelte files into a single display string"""
|
628 |
+
output = []
|
629 |
+
output.append("=== src/App.svelte ===")
|
630 |
+
output.append(files['src/App.svelte'])
|
631 |
+
output.append("\n=== src/app.css ===")
|
632 |
+
output.append(files['src/app.css'])
|
633 |
+
output.append("\n=== src/lib/Counter.svelte ===")
|
634 |
+
output.append(files['src/lib/Counter.svelte'])
|
635 |
+
return '\n'.join(output)
|
636 |
+
|
637 |
def history_render(history: History):
|
638 |
return gr.update(visible=True), history
|
639 |
|
|
|
1358 |
'IMPORTED PROJECT FROM HUGGING FACE SPACE' in last_assistant_msg or
|
1359 |
'=== index.html ===' in last_assistant_msg or
|
1360 |
'=== index.js ===' in last_assistant_msg or
|
1361 |
+
'=== style.css ===' in last_assistant_msg or
|
1362 |
+
'=== src/App.svelte ===' in last_assistant_msg):
|
1363 |
has_existing_content = True
|
1364 |
|
1365 |
# Choose system prompt based on context
|
|
|
1367 |
# Use follow-up prompt for modifying existing content
|
1368 |
if language == "transformers.js":
|
1369 |
system_prompt = TransformersJSFollowUpSystemPrompt
|
1370 |
+
elif language == "svelte":
|
1371 |
+
system_prompt = FollowUpSystemPrompt # Use generic follow-up for Svelte
|
1372 |
else:
|
1373 |
system_prompt = FollowUpSystemPrompt
|
1374 |
else:
|
|
|
1377 |
system_prompt = HTML_SYSTEM_PROMPT_WITH_SEARCH if enable_search else HTML_SYSTEM_PROMPT
|
1378 |
elif language == "transformers.js":
|
1379 |
system_prompt = TRANSFORMERS_JS_SYSTEM_PROMPT_WITH_SEARCH if enable_search else TRANSFORMERS_JS_SYSTEM_PROMPT
|
1380 |
+
elif language == "svelte":
|
1381 |
+
system_prompt = SVELTE_SYSTEM_PROMPT_WITH_SEARCH if enable_search else SVELTE_SYSTEM_PROMPT
|
1382 |
else:
|
1383 |
system_prompt = GENERIC_SYSTEM_PROMPT_WITH_SEARCH.format(language=language) if enable_search else GENERIC_SYSTEM_PROMPT.format(language=language)
|
1384 |
|
|
|
1468 |
history_output: history_to_chatbot_messages(_history),
|
1469 |
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Generating transformers.js app...</div>",
|
1470 |
}
|
1471 |
+
elif language == "svelte":
|
1472 |
+
# For Svelte, just show the content as it streams
|
1473 |
+
# We'll parse it properly in the final response
|
1474 |
+
yield {
|
1475 |
+
code_output: gr.update(value=content, language="html"),
|
1476 |
+
history_output: history_to_chatbot_messages(_history),
|
1477 |
+
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Generating Svelte app...</div>",
|
1478 |
+
}
|
1479 |
else:
|
1480 |
clean_code = remove_code_block(content)
|
1481 |
if has_existing_content:
|
|
|
1539 |
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Error parsing transformers.js output. Please try again.</div>",
|
1540 |
history_output: history_to_chatbot_messages(_history),
|
1541 |
}
|
1542 |
+
elif language == "svelte":
|
1543 |
+
# Handle Svelte output
|
1544 |
+
files = parse_svelte_output(content)
|
1545 |
+
if files['src/App.svelte'] and files['src/app.css']:
|
1546 |
+
# Model returned complete Svelte output
|
1547 |
+
formatted_output = format_svelte_output(files)
|
1548 |
+
_history.append([query, formatted_output])
|
1549 |
+
yield {
|
1550 |
+
code_output: formatted_output,
|
1551 |
+
history: _history,
|
1552 |
+
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your Svelte code using the download button above.</div>",
|
1553 |
+
history_output: history_to_chatbot_messages(_history),
|
1554 |
+
}
|
1555 |
+
elif has_existing_content:
|
1556 |
+
# Model returned search/replace changes for Svelte - apply them
|
1557 |
+
last_content = _history[-1][1] if _history and len(_history[-1]) > 1 else ""
|
1558 |
+
modified_content = apply_search_replace_changes(last_content, content)
|
1559 |
+
_history.append([query, modified_content])
|
1560 |
+
yield {
|
1561 |
+
code_output: modified_content,
|
1562 |
+
history: _history,
|
1563 |
+
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your Svelte code using the download button above.</div>",
|
1564 |
+
history_output: history_to_chatbot_messages(_history),
|
1565 |
+
}
|
1566 |
+
else:
|
1567 |
+
# Fallback if parsing failed - just use the raw content
|
1568 |
+
_history.append([query, content])
|
1569 |
+
yield {
|
1570 |
+
code_output: content,
|
1571 |
+
history: _history,
|
1572 |
+
sandbox: "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your Svelte code using the download button above.</div>",
|
1573 |
+
history_output: history_to_chatbot_messages(_history),
|
1574 |
+
}
|
1575 |
elif has_existing_content:
|
1576 |
# Handle modification of existing content
|
1577 |
final_code = remove_code_block(content)
|
|
|
1813 |
)
|
1814 |
# Language dropdown for code generation
|
1815 |
language_choices = [
|
1816 |
+
"html", "python", "transformers.js", "svelte", "c", "cpp", "markdown", "latex", "json", "css", "javascript", "jinja2", "typescript", "yaml", "dockerfile", "shell", "r", "sql", "sql-msSQL", "sql-mySQL", "sql-mariaDB", "sql-sqlite", "sql-cassandra", "sql-plSQL", "sql-hive", "sql-pgSQL", "sql-gql", "sql-gpSQL", "sql-sparkSQL", "sql-esper"
|
1817 |
]
|
1818 |
language_dropdown = gr.Dropdown(
|
1819 |
choices=language_choices,
|
|
|
1850 |
("Gradio (Python)", "gradio"),
|
1851 |
("Streamlit (Python)", "streamlit"),
|
1852 |
("Static (HTML)", "static"),
|
1853 |
+
("Transformers.js", "transformers.js"),
|
1854 |
+
("Svelte", "svelte")
|
1855 |
]
|
1856 |
sdk_dropdown = gr.Dropdown(
|
1857 |
choices=[x[0] for x in sdk_choices],
|
|
|
1963 |
def update_sdk_based_on_language(language):
|
1964 |
if language == "transformers.js":
|
1965 |
return gr.update(value="Transformers.js")
|
1966 |
+
elif language == "svelte":
|
1967 |
+
return gr.update(value="Svelte")
|
1968 |
elif language == "html":
|
1969 |
return gr.update(value="Static (HTML)")
|
1970 |
else:
|
|
|
1983 |
return send_to_sandbox(files['index.html'])
|
1984 |
else:
|
1985 |
return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
|
1986 |
+
elif language == "svelte":
|
1987 |
+
# For Svelte, we can't preview the compiled app, so show a message
|
1988 |
+
return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your Svelte code and deploy it to see the result.</div>"
|
1989 |
else:
|
1990 |
return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only available for HTML. Please download your code using the download button above.</div>"
|
1991 |
|
|
|
2069 |
"Gradio (Python)": "gradio",
|
2070 |
"Streamlit (Python)": "docker", # Use 'docker' for Streamlit Spaces
|
2071 |
"Static (HTML)": "static",
|
2072 |
+
"Transformers.js": "static", # Transformers.js uses static SDK
|
2073 |
+
"Svelte": "static" # Svelte uses static SDK
|
2074 |
}
|
2075 |
sdk = sdk_map.get(sdk_name, "gradio")
|
2076 |
|
|
|
2225 |
|
2226 |
except Exception as e:
|
2227 |
return gr.update(value=f"Error duplicating Transformers.js space: {e}. If this is a RepoUrl object error, ensure you are not accessing a .url attribute and use str(duplicated_repo) for the URL.", visible=True)
|
2228 |
+
# Svelte logic
|
2229 |
+
elif sdk_name == "Svelte" and not is_update:
|
2230 |
+
try:
|
2231 |
+
# Use duplicate_space to create a Svelte template space
|
2232 |
+
from huggingface_hub import duplicate_space
|
2233 |
+
|
2234 |
+
# Duplicate the Svelte template space
|
2235 |
+
duplicated_repo = duplicate_space(
|
2236 |
+
from_id="static-templates/svelte",
|
2237 |
+
to_id=space_name.strip(),
|
2238 |
+
token=token.token,
|
2239 |
+
exist_ok=True
|
2240 |
+
)
|
2241 |
+
print("Duplicated Svelte repo result:", duplicated_repo, type(duplicated_repo))
|
2242 |
+
# Show the duplicated space URL immediately for user feedback
|
2243 |
+
gr.update(value=f"✅ Space duplicated! [Open your new Svelte Space here]({str(duplicated_repo)})", visible=True)
|
2244 |
+
# Parse the Svelte output to get the custom files
|
2245 |
+
files = parse_svelte_output(code)
|
2246 |
+
|
2247 |
+
if not files['src/App.svelte']:
|
2248 |
+
return gr.update(value="Error: Could not parse Svelte output. Please regenerate the code.", visible=True)
|
2249 |
+
|
2250 |
+
# Upload only the custom Svelte files to the duplicated space
|
2251 |
+
import tempfile
|
2252 |
+
|
2253 |
+
# Upload src/App.svelte (required)
|
2254 |
+
with tempfile.NamedTemporaryFile("w", suffix=".svelte", delete=False) as f:
|
2255 |
+
f.write(files['src/App.svelte'])
|
2256 |
+
temp_path = f.name
|
2257 |
+
|
2258 |
+
try:
|
2259 |
+
api.upload_file(
|
2260 |
+
path_or_fileobj=temp_path,
|
2261 |
+
path_in_repo="src/App.svelte",
|
2262 |
+
repo_id=repo_id,
|
2263 |
+
repo_type="space"
|
2264 |
+
)
|
2265 |
+
except Exception as e:
|
2266 |
+
error_msg = str(e)
|
2267 |
+
if "403 Forbidden" in error_msg and "write token" in error_msg:
|
2268 |
+
return gr.update(value=f"Error: Permission denied. Please ensure you have write access to {repo_id} and your token has the correct permissions.", visible=True)
|
2269 |
+
else:
|
2270 |
+
return gr.update(value=f"Error uploading src/App.svelte: {e}", visible=True)
|
2271 |
+
finally:
|
2272 |
+
import os
|
2273 |
+
os.unlink(temp_path)
|
2274 |
+
|
2275 |
+
# Upload src/app.css (optional)
|
2276 |
+
if files['src/app.css']:
|
2277 |
+
with tempfile.NamedTemporaryFile("w", suffix=".css", delete=False) as f:
|
2278 |
+
f.write(files['src/app.css'])
|
2279 |
+
temp_path = f.name
|
2280 |
+
|
2281 |
+
try:
|
2282 |
+
api.upload_file(
|
2283 |
+
path_or_fileobj=temp_path,
|
2284 |
+
path_in_repo="src/app.css",
|
2285 |
+
repo_id=repo_id,
|
2286 |
+
repo_type="space"
|
2287 |
+
)
|
2288 |
+
except Exception as e:
|
2289 |
+
error_msg = str(e)
|
2290 |
+
if "403 Forbidden" in error_msg and "write token" in error_msg:
|
2291 |
+
return gr.update(value=f"Error: Permission denied. Please ensure you have write access to {repo_id} and your token has the correct permissions.", visible=True)
|
2292 |
+
else:
|
2293 |
+
return gr.update(value=f"Error uploading src/app.css: {e}", visible=True)
|
2294 |
+
finally:
|
2295 |
+
import os
|
2296 |
+
os.unlink(temp_path)
|
2297 |
+
|
2298 |
+
# Upload src/lib/Counter.svelte (optional)
|
2299 |
+
if files['src/lib/Counter.svelte']:
|
2300 |
+
with tempfile.NamedTemporaryFile("w", suffix=".svelte", delete=False) as f:
|
2301 |
+
f.write(files['src/lib/Counter.svelte'])
|
2302 |
+
temp_path = f.name
|
2303 |
+
|
2304 |
+
try:
|
2305 |
+
api.upload_file(
|
2306 |
+
path_or_fileobj=temp_path,
|
2307 |
+
path_in_repo="src/lib/Counter.svelte",
|
2308 |
+
repo_id=repo_id,
|
2309 |
+
repo_type="space"
|
2310 |
+
)
|
2311 |
+
except Exception as e:
|
2312 |
+
error_msg = str(e)
|
2313 |
+
if "403 Forbidden" in error_msg and "write token" in error_msg:
|
2314 |
+
return gr.update(value=f"Error: Permission denied. Please ensure you have write access to {repo_id} and your token has the correct permissions.", visible=True)
|
2315 |
+
else:
|
2316 |
+
return gr.update(value=f"Error uploading src/lib/Counter.svelte: {e}", visible=True)
|
2317 |
+
finally:
|
2318 |
+
import os
|
2319 |
+
os.unlink(temp_path)
|
2320 |
+
|
2321 |
+
# Success - all files uploaded
|
2322 |
+
space_url = f"https://huggingface.co/spaces/{repo_id}"
|
2323 |
+
action_text = "Updated" if is_update else "Deployed"
|
2324 |
+
return gr.update(value=f"✅ {action_text}! [Open your Svelte Space here]({space_url})", visible=True)
|
2325 |
+
|
2326 |
+
except Exception as e:
|
2327 |
+
return gr.update(value=f"Error duplicating Svelte space: {e}. If this is a RepoUrl object error, ensure you are not accessing a .url attribute and use str(duplicated_repo) for the URL.", visible=True)
|
2328 |
# Other SDKs (existing logic)
|
2329 |
if sdk == "static":
|
2330 |
import time
|