File size: 4,328 Bytes
2deb7a7
583310d
d8cd951
256b0b9
d8cd951
 
 
 
 
1c75fd0
d8cd951
 
1c75fd0
583310d
1c75fd0
d8cd951
 
2deb7a7
d8cd951
 
 
256b0b9
 
1c75fd0
d8cd951
 
1c75fd0
d8cd951
 
256b0b9
6dcd973
d8cd951
1c75fd0
 
d8cd951
 
1c75fd0
 
d8cd951
 
1c75fd0
 
 
 
d8cd951
 
 
1c75fd0
 
d8cd951
2deb7a7
d8cd951
 
 
 
 
1c75fd0
d8cd951
 
 
1c75fd0
d8cd951
1c75fd0
 
d8cd951
 
1c75fd0
d8cd951
 
 
 
1c75fd0
d8cd951
1c75fd0
 
 
d8cd951
 
 
 
 
583310d
d8cd951
 
256b0b9
d8cd951
1c75fd0
 
d8cd951
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c75fd0
d8cd951
 
1c75fd0
d8cd951
 
583310d
f7cf3be
2deb7a7
256b0b9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# app.py
"""
AnyCoder / Shasha AI – Gradio back‑end

• Shows the custom front‑end shipped in index.html (plus static/style.css & static/index.js).
• Exposes one JSON endpoint (`POST  /run/predict`) that the JS front‑end
  calls to run model inference.
• Keeps all existing helpers (hf_client, inference, utils, deploy …).
"""

from pathlib import Path
from typing import List, Tuple, Dict, Any

import gradio as gr

# ---- local helpers (unchanged) --------------------------------------------
from inference   import chat_completion
from tavily_search import enhance_query_with_search
from deploy      import send_to_sandbox
from models      import AVAILABLE_MODELS, find_model, ModelInfo
from utils       import (
    extract_text_from_file,
    extract_website_content,
    history_to_messages,
    history_to_chatbot_messages,
    apply_search_replace_changes,
    remove_code_block,
    parse_transformers_js_output,
    format_transformers_js_output,
)

# ------------------- constants ---------------------------------------------
SYSTEM_PROMPTS = {
    "html": (
        "ONLY USE HTML, CSS AND JAVASCRIPT. Return ONE html file "
        "wrapped in ```html ...```."
    ),
    "transformers.js": (
        "Generate THREE separate files (index.html / index.js / style.css) "
        "as three fenced blocks."
    ),
}
History = List[Tuple[str, str]]

# ------------------- core callback -----------------------------------------
def generate(
    prompt: str,
    file_path: str | None,
    website_url: str | None,
    model_id: str,
    language: str,
    enable_search: bool,
    history: History | None,
) -> Tuple[str, History]:
    """Called by the JS front‑end via fetch('/run/predict')."""
    history = history or []

    # --- build system + messages ------------------------------------------
    system_prompt = SYSTEM_PROMPTS.get(language, f"You are an expert {language} developer.")
    messages      = history_to_messages(history, system_prompt)

    ctx_parts: list[str] = [prompt.strip()]

    if file_path:
        ctx_parts.append("[File]")
        ctx_parts.append(extract_text_from_file(file_path)[:5000])
    if website_url:
        html = extract_website_content(website_url)
        if not html.startswith("Error"):
            ctx_parts.append("[Website]")
            ctx_parts.append(html[:8000])

    user_query = "\n\n".join(filter(None, ctx_parts))
    user_query = enhance_query_with_search(user_query, enable_search)
    messages.append({"role": "user", "content": user_query})

    # --- run model ---------------------------------------------------------
    model: ModelInfo = find_model(model_id) or AVAILABLE_MODELS[0]
    answer = chat_completion(model.id, messages)

    # --- post‑process ------------------------------------------------------
    if language == "transformers.js":
        files = parse_transformers_js_output(answer)
        code  = format_transformers_js_output(files)
    else:
        cleaned = remove_code_block(answer)
        if history and not history[-1][1].startswith("❌"):
            cleaned = apply_search_replace_changes(history[-1][1], cleaned)
        code = cleaned

    history.append((prompt, code))
    return code, history

# ------------------- read custom HTML --------------------------------------
HTML_SOURCE = Path("index.html").read_text(encoding="utf‑8")

# ------------------- Gradio UI ---------------------------------------------
with gr.Blocks(css="body{margin:0}", title="AnyCoder AI") as demo:
    # 1 visible: your own UI
    gr.HTML(HTML_SOURCE, sanitize=False)

    # 2 hidden: API inputs / outputs
    with gr.Group(visible=False) as api:
        prompt_in   = gr.Textbox()
        file_in     = gr.File()
        url_in      = gr.Textbox()
        model_in    = gr.Textbox()
        lang_in     = gr.Textbox()
        search_in   = gr.Checkbox()
        hist_state  = gr.State([])

        code_out, hist_out = gr.Textbox(), gr.State([])

    # expose /run/predict
    api_btn = gr.Button(visible=False)
    api_btn.click(
        fn=generate,
        inputs=[
            prompt_in, file_in, url_in,
            model_in, lang_in, search_in, hist_state
        ],
        outputs=[code_out, hist_out],
        api_name="predict",
    )

if __name__ == "__main__":
    demo.queue().launch()