hotboxxgenn commited on
Commit
c0938f5
·
verified ·
1 Parent(s): 560dd84

Upload 9 files

Browse files
Files changed (9) hide show
  1. .gitignore +3 -0
  2. README.md +9 -14
  3. app.py +103 -56
  4. code_intel.py +43 -0
  5. context.py +18 -0
  6. directives.py +28 -0
  7. project.py +132 -0
  8. requirements.txt +3 -0
  9. style.css +7 -0
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ context.json
2
+ __pycache__/
3
+ *.zip
README.md CHANGED
@@ -1,15 +1,10 @@
1
- ---
2
- title: TheFinalBuddy
3
- emoji: 💬
4
- colorFrom: yellow
5
- colorTo: purple
6
- sdk: gradio
7
- sdk_version: 5.42.0
8
- app_file: app.py
9
- pinned: false
10
- hf_oauth: true
11
- hf_oauth_scopes:
12
- - inference-api
13
- ---
14
 
15
- An example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
 
 
 
 
 
 
 
 
1
+ DeepSite Buddy Pro - Ready-to-upload Hugging Face Space
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ Features included:
4
+ - Customizable buddy name & simple evolving personality
5
+ - Code analysis for multiple languages (basic)
6
+ - File upload & scaffold generator (login system)
7
+ - Project explorer, file editor, live preview, and export ZIP
8
+ - Dreamy pink/blue UI (static/style.css)
9
+
10
+ To deploy: upload this repository as a new Hugging Face Space (Gradio).
app.py CHANGED
@@ -1,70 +1,117 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
 
 
 
 
 
3
 
 
 
 
 
4
 
5
- def respond(
6
- message,
7
- history: list[dict[str, str]],
8
- system_message,
9
- max_tokens,
10
- temperature,
11
- top_p,
12
- hf_token: gr.OAuthToken,
13
- ):
14
- """
15
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
16
- """
17
- client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b")
18
 
19
- messages = [{"role": "system", "content": system_message}]
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- messages.extend(history)
 
 
 
 
 
22
 
23
- messages.append({"role": "user", "content": message})
 
 
 
 
24
 
25
- response = ""
 
 
 
 
 
26
 
27
- for message in client.chat_completion(
28
- messages,
29
- max_tokens=max_tokens,
30
- stream=True,
31
- temperature=temperature,
32
- top_p=top_p,
33
- ):
34
- choices = message.choices
35
- token = ""
36
- if len(choices) and choices[0].delta.content:
37
- token = choices[0].delta.content
38
 
39
- response += token
40
- yield response
 
 
 
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- chatbot = gr.ChatInterface(
47
- respond,
48
- type="messages",
49
- additional_inputs=[
50
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
51
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
52
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
53
- gr.Slider(
54
- minimum=0.1,
55
- maximum=1.0,
56
- value=0.95,
57
- step=0.05,
58
- label="Top-p (nucleus sampling)",
59
- ),
60
- ],
61
- )
62
 
63
- with gr.Blocks() as demo:
64
- with gr.Sidebar():
65
- gr.LoginButton()
66
- chatbot.render()
 
 
 
 
 
 
 
67
 
 
68
 
69
- if __name__ == "__main__":
70
- demo.launch()
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ from pathlib import Path
3
+ from core.directives import BuddyPersonality
4
+ from core.code_intel import analyze_code, detect_language
5
+ from core.project import list_project, read_file, write_file, export_project, scaffold_login_system
6
+ from utils.context import load_context, save_context
7
+ import json, shutil, os
8
 
9
+ CTX = load_context()
10
+ buddy = BuddyPersonality()
11
+ BASE = Path('scaffold_projects')
12
+ BASE.mkdir(exist_ok=True)
13
 
14
+ sample = BASE / 'welcome_project'
15
+ if not sample.exists():
16
+ (sample / 'hello.txt').parent.mkdir(parents=True, exist_ok=True)
17
+ (sample / 'hello.txt').write_text('Welcome to DeepSite Buddy Pro!\nUse the UI to generate projects, upload files, and edit them.')
 
 
 
 
 
 
 
 
 
18
 
19
+ def run_analysis(file):
20
+ try:
21
+ content = file.read().decode('utf-8', errors='ignore')
22
+ except Exception:
23
+ try:
24
+ with open(file.name, 'r', encoding='utf-8', errors='ignore') as f:
25
+ content = f.read()
26
+ except Exception as e:
27
+ return f'Could not read file: {e}'
28
+ lang = detect_language(file.name if hasattr(file,'name') else 'file')
29
+ res = analyze_code(file.name if hasattr(file,'name') else 'file', content)
30
+ return json.dumps({"language": lang, "analysis": res}, indent=2, ensure_ascii=False)
31
 
32
+ def cmd_make_login():
33
+ p = BASE / 'login_system'
34
+ if p.exists():
35
+ shutil.rmtree(p)
36
+ scaffold_login_system(p)
37
+ return f'Login system scaffold created at {p}. Use "Show Project Tree" to view.'
38
 
39
+ def show_tree(proj_name='welcome_project'):
40
+ p = BASE / proj_name
41
+ if not p.exists():
42
+ return f'Project {proj_name} does not exist.'
43
+ return list_project(p)
44
 
45
+ def read_proj_file(proj_name, rel_path):
46
+ p = BASE / proj_name / rel_path
47
+ content = read_file(p)
48
+ if content is None:
49
+ return f'File not found: {rel_path}'
50
+ return content
51
 
52
+ def save_proj_file(proj_name, rel_path, content):
53
+ p = BASE / proj_name / rel_path
54
+ write_file(p, content)
55
+ return f'Wrote {rel_path}'
 
 
 
 
 
 
 
56
 
57
+ def export_proj_zip(proj_name):
58
+ p = BASE / proj_name
59
+ if not p.exists():
60
+ return None
61
+ return export_project(p, f'{proj_name}_export')
62
 
63
+ with gr.Blocks(css='static/style.css', title='DeepSite Buddy Pro') as demo:
64
+ gr.Markdown('# DeepSite Buddy Pro 🌸☁️\nA dreamy AI developer buddy.')
65
+ with gr.Row():
66
+ with gr.Column(scale=3):
67
+ name_in = gr.Textbox(label='Set Buddy Name', placeholder=buddy.get_name())
68
+ set_name_btn = gr.Button('Set Name')
69
+ chat_in = gr.Textbox(label='Say something to Buddy', placeholder='e.g. make login system or analyze my file')
70
+ chat_btn = gr.Button('Run')
71
+ file_in = gr.File(label='Upload code file for analysis', file_count='single')
72
+ analysis_out = gr.Code(label='Analysis Output', language='json')
73
+ with gr.Row():
74
+ make_login = gr.Button('Make Login System (scaffold)')
75
+ show_tree_btn = gr.Button('Show Project Tree')
76
+ project_select = gr.Dropdown(choices=[p.name for p in BASE.iterdir() if p.is_dir()], value='welcome_project', label='Project')
77
+ export_btn = gr.Button('Export Project ZIP')
78
+ with gr.Column(scale=2):
79
+ gr.Markdown('### Project Explorer')
80
+ tree_out = gr.Textbox(label='Project Tree', lines=20)
81
+ gr.Markdown('### File Editor')
82
+ file_path = gr.Textbox(label='Relative path (e.g., frontend/index.html)', placeholder='hello.txt')
83
+ file_editor = gr.Code('', label='Editor', language='auto', lines=20)
84
+ save_file_btn = gr.Button('Save File')
85
+ preview_html = gr.HTML('<div style="padding:12px;background:rgba(255,255,255,0.6);border-radius:8px;">Live preview will show HTML content when you open an HTML file.</div>')
86
 
87
+ def _set_name(n):
88
+ if not n:
89
+ return buddy.get_name()
90
+ buddy.set_name(n)
91
+ return f'Buddy name set to {n}'
92
+ set_name_btn.click(_set_name, inputs=[name_in], outputs=[name_in])
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
+ def _run_chat(text, uploaded_file):
95
+ if uploaded_file:
96
+ return run_analysis(uploaded_file)
97
+ lower = (text or '').lower()
98
+ if any(k in lower for k in ('make login','login system','make a login')):
99
+ return cmd_make_login()
100
+ if any(k in lower for k in ('show project','project tree','show tree')):
101
+ return show_tree(project_select.value)
102
+ out = f"Hello, I'm {buddy.get_name()}! I can analyze files, scaffold projects, and export zips. You said: {text}"
103
+ buddy.record_conversation(text, out)
104
+ return out
105
 
106
+ chat_btn.click(_run_chat, inputs=[chat_in, file_in], outputs=[analysis_out])
107
 
108
+ make_login.click(lambda: cmd_make_login(), inputs=None, outputs=[analysis_out, tree_out])
109
+ show_tree_btn.click(lambda: show_tree(project_select.value), inputs=None, outputs=tree_out)
110
+
111
+ def _open_file(proj, rel):
112
+ return read_proj_file(proj, rel)
113
+ file_path.change(_open_file, inputs=[project_select, file_path], outputs=file_editor)
114
+ save_file_btn.click(lambda proj, rel, content: save_proj_file(proj, rel, content), inputs=[project_select, file_path, file_editor], outputs=analysis_out)
115
+ export_btn.click(lambda proj: export_proj_zip(proj), inputs=[project_select], outputs=gr.File(label='Download ZIP'))
116
+
117
+ demo.launch()
code_intel.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ast, re
2
+
3
+ def detect_language(filename):
4
+ if not filename or "." not in filename:
5
+ return "text"
6
+ ext = filename.split(".")[-1].lower()
7
+ mapping = {"py":"python","js":"javascript","ts":"typescript","java":"java","cs":"csharp","html":"html","css":"css","json":"json","md":"markdown"}
8
+ return mapping.get(ext, ext)
9
+
10
+ def analyze_python(code: str):
11
+ try:
12
+ tree = ast.parse(code)
13
+ except Exception as e:
14
+ return {"ok": False, "error": f"Syntax Error: {e}", "suggestion": "Check indentation or syntax near the reported location."}
15
+ issues = []
16
+ class FuncVisitor(ast.NodeVisitor):
17
+ def visit_FunctionDef(self, node):
18
+ start = node.lineno
19
+ end = node.lineno
20
+ for n in ast.walk(node):
21
+ if hasattr(n, "lineno"):
22
+ end = max(end, n.lineno)
23
+ length = end - start + 1
24
+ if length > 200:
25
+ issues.append({"type":"large_function","message":f"Function '{node.name}' is {length} lines; consider refactoring."})
26
+ self.generic_visit(node)
27
+ FuncVisitor().visit(tree)
28
+ return {"ok": True, "issues": issues, "summary": "Parsed AST successfully."}
29
+
30
+ def analyze_javascript(code: str):
31
+ if "console.log" in code and "debugger" in code:
32
+ return {"ok": True, "notes":"Found console.log and debugger. Remove before prod."}
33
+ if "function(" not in code and "=>" not in code:
34
+ return {"ok": True, "notes":"No obvious function constructs found."}
35
+ return {"ok": True, "notes":"Basic JS analysis complete."}
36
+
37
+ def analyze_code(filename, code):
38
+ lang = detect_language(filename)
39
+ if lang == "python":
40
+ return analyze_python(code)
41
+ if lang in ("javascript","typescript"):
42
+ return analyze_javascript(code)
43
+ return {"ok": True, "notes": f"Language {lang} not deeply analyzed. Size {len(code)} bytes.", "head": code[:800]}
context.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from pathlib import Path
3
+ CTX_PATH = Path('context.json')
4
+
5
+ def load_context():
6
+ if CTX_PATH.exists():
7
+ try:
8
+ return json.loads(CTX_PATH.read_text(encoding='utf-8'))
9
+ except Exception:
10
+ return {}
11
+ return {}
12
+
13
+ def save_context(ctx: dict):
14
+ try:
15
+ CTX_PATH.write_text(json.dumps(ctx, indent=2, ensure_ascii=False), encoding='utf-8')
16
+ return True
17
+ except Exception:
18
+ return False
directives.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from utils.context import load_context, save_context
2
+
3
+ class BuddyPersonality:
4
+ def __init__(self):
5
+ self.ctx = load_context()
6
+ self.defaults = {"name":"Buddy","tone":"friendly","verbosity":"medium"}
7
+ self.ctx.setdefault("buddy", {})
8
+ for k,v in self.defaults.items():
9
+ self.ctx["buddy"].setdefault(k, v)
10
+ save_context(self.ctx)
11
+
12
+ def get_name(self):
13
+ return self.ctx["buddy"].get("name", self.defaults["name"])
14
+
15
+ def set_name(self, name):
16
+ self.ctx["buddy"]["name"] = name
17
+ save_context(self.ctx)
18
+
19
+ def record_conversation(self, user_text, bot_text):
20
+ history = self.ctx.setdefault("history", [])
21
+ history.append({"user": user_text, "bot": bot_text})
22
+ short_count = sum(1 for h in history[-20:] if len(h["user"]) < 40)
23
+ if short_count > 10:
24
+ self.ctx["buddy"]["verbosity"] = "short"
25
+ save_context(self.ctx)
26
+
27
+ def summary(self):
28
+ return {"name": self.get_name(), "tone": self.ctx["buddy"].get("tone"), "verbosity": self.ctx["buddy"].get("verbosity")}
project.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import shutil, json
3
+
4
+ def list_project(path: Path, max_depth=6):
5
+ out = []
6
+ if not path.exists():
7
+ return "No project found at " + str(path)
8
+ def _walk(p, depth):
9
+ if depth > max_depth:
10
+ return
11
+ for child in sorted(p.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())):
12
+ out.append((" "*depth) + ("📁 " if child.is_dir() else "📄 ") + child.name)
13
+ if child.is_dir():
14
+ _walk(child, depth+1)
15
+ _walk(path, 0)
16
+ return "\n".join(out)
17
+
18
+ def read_file(path: Path):
19
+ if not path.exists():
20
+ return None
21
+ try:
22
+ return path.read_text(encoding='utf-8', errors='ignore')
23
+ except Exception as e:
24
+ return None
25
+
26
+ def write_file(path: Path, content: str):
27
+ path.parent.mkdir(parents=True, exist_ok=True)
28
+ path.write_text(content, encoding='utf-8')
29
+ return True
30
+
31
+ def export_project(path: Path, zip_name: str):
32
+ if not path.exists():
33
+ return None
34
+ base = Path(zip_name).stem
35
+ shutil.make_archive(base, 'zip', root_dir=path)
36
+ return base + '.zip'
37
+
38
+ def scaffold_login_system(root: Path):
39
+ from textwrap import dedent
40
+ root.mkdir(parents=True, exist_ok=True)
41
+ frontend = root / "frontend"
42
+ backend = root / "backend"
43
+ frontend.mkdir(exist_ok=True)
44
+ backend.mkdir(exist_ok=True)
45
+ (frontend / "index.html").write_text(dedent("""
46
+ <!doctype html>
47
+ <html>
48
+ <head>
49
+ <meta charset='utf-8'/>
50
+ <title>Login</title>
51
+ <link rel='stylesheet' href='style.css'/>
52
+ </head>
53
+ <body>
54
+ <div class='card'>
55
+ <h2>Login</h2>
56
+ <form id='form'>
57
+ <input id='email' placeholder='email' required/>
58
+ <input id='password' type='password' placeholder='password' required/>
59
+ <button type='button' onclick='signup()'>Sign Up</button>
60
+ <button type='button' onclick='login()'>Log In</button>
61
+ </form>
62
+ <pre id='out'></pre>
63
+ </div>
64
+ <script>
65
+ async function signup(){ const e=document.getElementById('email').value; const p=document.getElementById('password').value; const res=await fetch('/signup',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({email:e,password:p})}); document.getElementById('out').innerText=await res.text(); }
66
+ async function login(){ const e=document.getElementById('email').value; const p=document.getElementById('password').value; const res=await fetch('/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({email:e,password:p})}); document.getElementById('out').innerText=await res.text(); }
67
+ </script>
68
+ </body>
69
+ </html>
70
+ """))
71
+ (frontend / "style.css").write_text(dedent("""
72
+ body { background: linear-gradient(135deg,#ffd1e8,#cfe9ff); font-family: Arial, sans-serif; }
73
+ .card{max-width:360px;margin:60px auto;padding:20px;border-radius:12px;background:rgba(255,255,255,0.8);box-shadow:0 8px 30px rgba(0,0,0,0.08);}
74
+ input{display:block;width:100%;margin:8px 0;padding:10px;border-radius:8px;border:1px solid #ddd}
75
+ button{margin-right:8px;padding:8px 12px;border-radius:8px;border:none;background:#ff8fc1;color:white}
76
+ pre{background:#fff;padding:8px;border-radius:6px;border:1px solid #eee}
77
+ """))
78
+ (backend / "app.py").write_text(dedent("""
79
+ from wsgiref.simple_server import make_server
80
+ import json, os
81
+ DB='users.json'
82
+ def app(environ, start_response):
83
+ path = environ.get('PATH_INFO','/')
84
+ try:
85
+ size = int(environ.get('CONTENT_LENGTH') or 0)
86
+ except Exception:
87
+ size = 0
88
+ body = environ['wsgi.input'].read(size) if size else b''
89
+ if path == '/signup' or path == '/login':
90
+ try:
91
+ data = json.loads(body.decode('utf-8'))
92
+ except Exception:
93
+ data = {}
94
+ email = data.get('email'); password = data.get('password')
95
+ if not email or not password:
96
+ start_response('400 Bad Request', [('Content-Type','text/plain')])
97
+ return [b'Missing email or password']
98
+ users = {}
99
+ if os.path.exists(DB):
100
+ try:
101
+ users = json.loads(open(DB,'r').read())
102
+ except Exception:
103
+ users={}
104
+ if path == '/signup':
105
+ if email in users:
106
+ start_response('400 Bad Request', [('Content-Type','text/plain')])
107
+ return [b'User exists']
108
+ users[email] = {'password': password}
109
+ open(DB,'w').write(json.dumps(users))
110
+ start_response('200 OK', [('Content-Type','text/plain')])
111
+ return [b'Signed up']
112
+ else:
113
+ u = users.get(email)
114
+ if not u or u.get('password') != password:
115
+ start_response('401 Unauthorized', [('Content-Type','text/plain')])
116
+ return [b'Invalid credentials']
117
+ start_response('200 OK', [('Content-Type','text/plain')])
118
+ return [b'Logged in']
119
+ if path == '/' or path.endswith('.html') or path.endswith('.css') or path.endswith('.js'):
120
+ local = os.path.join(os.path.dirname(__file__), '..', 'frontend', path.lstrip('/'))
121
+ if os.path.exists(local):
122
+ start_response('200 OK', [('Content-Type','text/html')])
123
+ return [open(local,'rb').read()]
124
+ start_response('404 Not Found', [('Content-Type','text/plain')])
125
+ return [b'Not Found']
126
+ if __name__=='__main__':
127
+ print('Starting tiny server on http://localhost:8000 (for local testing)')
128
+ make_server('',8000,app).serve_forever()
129
+ """))
130
+ (root := root := root if isinstance(root, Path) else root).absolute()
131
+ (root / 'README.md').write_text('Login system scaffold: frontend + backend (tiny WSGI server).')
132
+ return True
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio==3.40.0
2
+ requests==2.31.0
3
+ beautifulsoup4==4.12.2
style.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ body { background: linear-gradient(135deg,#ffd1e8,#cfe9ff); font-family: "Segoe UI", Roboto, Arial, sans-serif; }
2
+ .container{ max-width:1100px; margin:20px auto; padding:18px; border-radius:14px; background: linear-gradient(180deg, rgba(255,255,255,0.8), rgba(255,255,255,0.6)); box-shadow: 0 10px 40px rgba(0,0,0,0.08); }
3
+ .header{ display:flex; align-items:center; justify-content:space-between; }
4
+ .badge{ background: rgba(255,255,255,0.6); padding:8px 12px; border-radius:999px; box-shadow: inset 0 -2px 6px rgba(255,255,255,0.6); }
5
+ .card{ border-radius:12px; padding:12px; background: linear-gradient(180deg, rgba(255,255,255,0.9), rgba(255,255,255,0.85)); margin-top:12px; }
6
+ .codebox{ font-family: monospace; font-size:13px; }
7
+ .tree{ font-family: monospace; white-space: pre; background: rgba(255,255,255,0.6); padding:12px; border-radius:8px; }