-
Notifications
You must be signed in to change notification settings - Fork 1
Add files via upload #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <manifest package="com.quantumaiide.agent" | ||
| xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <application android:label="QuantumAIIDE"> | ||
| <activity android:name=".QuantumAIIDEWebViewActivity" | ||
| android:exported="true" | ||
| android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"> | ||
| <intent-filter> | ||
| <action android:name="android.intent.action.MAIN" /> | ||
| <category android:name="android.intent.category.LAUNCHER" /> | ||
| </intent-filter> | ||
| </activity> | ||
| </application> | ||
| </manifest> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.quantumaiide.agent | ||
|
|
||
| import android.annotation.SuppressLint | ||
| import android.os.Bundle | ||
| import android.webkit.WebView | ||
| import android.webkit.WebViewClient | ||
| import androidx.appcompat.app.AppCompatActivity | ||
|
|
||
| class QuantumAIIDEWebViewActivity : AppCompatActivity() { | ||
| @SuppressLint("SetJavaScriptEnabled") | ||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
| val webView = WebView(this) | ||
| setContentView(webView) | ||
| webView.settings.javaScriptEnabled = true | ||
| webView.settings.domStorageEnabled = true | ||
| webView.settings.allowFileAccess = true | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enabling |
||
| webView.webViewClient = WebViewClient() | ||
| webView.loadUrl("file:///android_asset/QuantumAIIDE_Monolith.html") | ||
| } | ||
| } | ||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| QuantumAIIDE Agent: Mobile-First, Privileged AI System Builder | ||
| Industry standards, agentic orchestration, Android/Aarch64 ready. | ||
| References: /reference vault, ai_dev_system.py, OWASP, GitHub API docs, DeepSeek, HuggingFace | ||
| """ | ||
| import asyncio, json, os, aiohttp, logging | ||
| from github import Github | ||
| from shell import run_shell_command | ||
| from ai import query_ai | ||
| from audit import log_action | ||
|
|
||
| # Configure logging | ||
| logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s') | ||
| logger = logging.getLogger("QuantumAIIDE-Agent") | ||
|
|
||
| class QuantumAgent: | ||
| def __init__(self, github_token, ai_token): | ||
| self.github = Github(github_token) | ||
| self.ai_token = ai_token | ||
|
|
||
| async def handle_request(self, req): | ||
| """Dispatch agentic requests: build, refactor, run, push, etc.""" | ||
| action = req.get("action") | ||
| params = req.get("params", {}) | ||
| log_action(action, params) | ||
| if action == "refactor_file": | ||
| repo = self.github.get_repo(params["repo"]) | ||
| file = repo.get_contents(params["path"]) | ||
| code = file.decoded_content.decode() | ||
| instructions = params["instructions"] | ||
| prompt = f"Refactor this code for {params['path']}:\n{code}\nInstructions: {instructions}\nOutput only final code." | ||
| new_code = await query_ai(prompt, self.ai_token) | ||
| repo.update_file(params["path"], "Agentic AI refactor", new_code, file.sha) | ||
| return {"status": "ok", "msg": "File refactored"} | ||
| elif action == "generate_file": | ||
| repo = self.github.get_repo(params["repo"]) | ||
| prompt = f"Generate code for {params['path']}:\n{params['description']}\nOutput only final code." | ||
| code = await query_ai(prompt, self.ai_token) | ||
| repo.create_file(params["path"], "Agentic AI generate", code) | ||
| return {"status": "ok", "msg": "File generated"} | ||
| elif action == "run_shell": | ||
| result = run_shell_command(params["command"]) | ||
| return {"status": "ok", "output": result} | ||
|
spiralgang marked this conversation as resolved.
|
||
| # Extend for more agentic ops: build, deploy, proxy, etc. | ||
| else: | ||
| return {"status": "error", "msg": "Unknown action"} | ||
|
|
||
| # FastAPI or Flask app to expose agent endpoints (omitted for brevity) | ||
| # See /reference vault, ai_dev_system.py for full server reference | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import { githubWrite, shellRun, auditLog } from './integrations.js'; | ||
|
|
||
| export function initAIChat(container) { | ||
| container.innerHTML = ` | ||
| <div class="chatbox" id="chatbox"></div> | ||
| <input id="chat-input" class="chat-input" placeholder="Ask anything (build, refactor, deploy)"> | ||
| <button class="btn" id="chat-send-btn">Send</button> | ||
| `; | ||
| document.getElementById('chat-send-btn').onclick = async () => { | ||
| let val = document.getElementById('chat-input').value.trim(); | ||
| if (!val) return; | ||
| addChatMsg('You', val); | ||
| // Call DeepSeek/HF API | ||
| let result = await aiExecute(val); | ||
| addChatMsg('AI', result.message); | ||
| // If result includes action (code, command), execute directly | ||
| if (result.action === 'write_file') { | ||
| await githubWrite(result.file, result.content); | ||
| auditLog('write_file', result.file); | ||
|
Comment on lines
+17
to
+19
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): No error handling for failed githubWrite or auditLog operations. Please add error handling and user notifications for failures in githubWrite and auditLog to prevent UI inconsistencies. |
||
| } | ||
| if (result.action === 'run_shell') { | ||
| let shellResult = await shellRun(result.command); | ||
| auditLog('run_shell', result.command, shellResult); | ||
| addChatMsg('Shell', shellResult.output); | ||
| } | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { files } from './files.js'; | ||
|
|
||
| let aiKey = ""; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: aiKey is declared as a local variable, which may limit cross-module updates. Consider implementing a setter/getter or shared state management if cross-module access or updates to aiKey are required. |
||
|
|
||
| export function initAIChat(container) { | ||
| container.innerHTML = ` | ||
| <div class="chatbox" id="chatbox"></div> | ||
| <div class="flex"> | ||
| <input id="chat-input" class="chat-input" placeholder="Ask anything..."> | ||
| <button class="btn" id="chat-send-btn">Send</button> | ||
| </div> | ||
| `; | ||
| document.getElementById('chat-send-btn').onclick = () => { | ||
| let val = document.getElementById('chat-input').value.trim(); | ||
| if (!val) return; | ||
| runAIChat(val); | ||
| document.getElementById('chat-input').value = ''; | ||
| }; | ||
| } | ||
|
|
||
| export async function runAIChat(prompt, source="chat", cb) { | ||
| addChatMsg(source==="cli"?"CLI":"You",prompt); | ||
| let repoContext = Object.keys(files).map(f=>`${f}:\n${files[f].slice(0,300)}`).join('\n\n'); | ||
| let userMsg = `QuantumWebIDE, Mobile-First, Android 10+/Aarch64. Files:\n${repoContext}\n\n${prompt}`; | ||
| let answer = await queryAI([{role:"user",content:userMsg}]); | ||
| addChatMsg("AI",answer); | ||
| if(cb) cb(answer); | ||
| } | ||
|
|
||
| function addChatMsg(user, text) { | ||
| let chatbox = document.getElementById('chatbox'); | ||
| let div = document.createElement('div'); | ||
| div.className = 'chat-msg'; | ||
| div.innerHTML = `<span class="${user==='AI'?'chat-ai':'chat-user'}">${user}:</span> <span class="chat-text">${text}</span>`; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. security (javascript.browser.security.insecure-document-method): User controlled data in methods like Source: opengrep
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. security (javascript.browser.security.insecure-innerhtml): User controlled data in a Source: opengrep |
||
| chatbox.appendChild(div); | ||
| chatbox.scrollTop = chatbox.scrollHeight; | ||
| } | ||
|
spiralgang marked this conversation as resolved.
|
||
|
|
||
| async function queryAI(messages, model="deepseek-ai/DeepSeek-R1:fireworks-ai") { | ||
| if(!aiKey) return "AI key not set. Paste in settings."; | ||
| try { | ||
| const response = await fetch("https://router.huggingface.co/v1/chat/completions",{ | ||
| headers: { Authorization: "Bearer "+aiKey, "Content-Type":"application/json"}, | ||
| method: "POST", | ||
| body: JSON.stringify({messages,top_p:1,model}), | ||
| }); | ||
| const result = await response.json(); | ||
| if(result.choices && result.choices.length>0) return result.choices[0].message.content; | ||
| return result.error||"AI error: Unexpected response"; | ||
| } catch(e){ return "AI error: "+e.message;} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import aiohttp, os | ||
| async def query_ai(prompt, ai_token, model="deepseek-ai/DeepSeek-R1:fireworks-ai"): | ||
| url = "https://router.huggingface.co/v1/chat/completions" | ||
| payload = { | ||
| "messages": [{"role": "user", "content": prompt}], | ||
| "top_p": 1, | ||
| "model": model | ||
| } | ||
| headers = {"Authorization": f"Bearer {ai_token}", "Content-Type": "application/json"} | ||
| async with aiohttp.ClientSession() as session: | ||
| async with session.post(url, json=payload, headers=headers) as resp: | ||
| res = await resp.json() | ||
| return res["choices"][0]["message"]["content"] if "choices" in res else res.get("error", "") | ||
|
spiralgang marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import time, json | ||
| def log_action(action, params): | ||
| entry = {"ts": time.time(), "action": action, "params": params} | ||
| with open("agent_audit.log", "a") as f: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): No error handling for file write operations in log_action. Wrap the file write in a try/except block to prevent agent crashes from disk errors. |
||
| f.write(json.dumps(entry) + "\n") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| apply plugin: 'com.android.application' | ||
|
|
||
| android { | ||
| compileSdkVersion 33 | ||
| defaultConfig { | ||
| applicationId "com.quantumaiide.agent" | ||
| minSdkVersion 29 | ||
| targetSdkVersion 33 | ||
| versionCode 1 | ||
| versionName "1.0" | ||
| } | ||
| buildTypes { | ||
| release { | ||
| minifyEnabled false | ||
|
spiralgang marked this conversation as resolved.
|
||
| proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
| } | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation 'androidx.appcompat:appcompat:1.6.1' | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { files, openFile, saveFile, deleteFile, downloadFile } from './files.js'; | ||
|
|
||
| export function initEditor(container) { | ||
| container.innerHTML = ` | ||
| <textarea id="editor" style="width:100%;height:180px;"></textarea> | ||
| <div> | ||
| <button id="save-file-btn" class="btn">Save</button> | ||
| <button id="new-file-btn" class="btn">New File</button> | ||
| <button id="delete-file-btn" class="btn">Delete File</button> | ||
| <button id="download-file-btn" class="btn">Download File</button> | ||
| </div> | ||
| `; | ||
| document.getElementById('editor').value = files[openFile()] || ''; | ||
| document.getElementById('save-file-btn').onclick = () => saveFile(document.getElementById('editor').value); | ||
| document.getElementById('new-file-btn').onclick = () => openFile(prompt("New file name:")); | ||
| document.getElementById('delete-file-btn').onclick = () => deleteFile(); | ||
| document.getElementById('download-file-btn').onclick = () => downloadFile(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| export let files = { | ||
| "README.md": "# QuantumWebIDE\nMobile-first, privileged shell.", | ||
| "main.sh": "#!/bin/bash\necho 'Ready.'" | ||
| }; | ||
| let activeFile = "README.md"; | ||
|
|
||
| export function openFile(fname) { | ||
| if (fname && files[fname]) activeFile = fname; | ||
| return activeFile; | ||
| } | ||
| export function saveFile(content) { files[activeFile] = content; } | ||
| export function deleteFile() { delete files[activeFile]; activeFile = Object.keys(files)[0];} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue: deleteFile does not handle case when no files remain after deletion. If files is empty after deletion, activeFile will be set to undefined, which may cause errors. Add a check to handle this scenario. |
||
| export function downloadFile() { | ||
| const a = document.createElement('a'); | ||
| a.href = URL.createObjectURL(new Blob([files[activeFile]], {type: "text/plain"})); | ||
| a.download = activeFile; | ||
| a.click(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <title>QuantumAIIDE Mobile Agentic IDE</title> | ||
| <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> | ||
| <link rel="stylesheet" href="theme.css"> | ||
| <script src="main.js" type="module"></script> | ||
| </head> | ||
| <body> | ||
| <header><h1>QuantumAIIDE</h1><span id="status"></span></header> | ||
| <nav> | ||
| <button id="nav-terminal">Terminal</button> | ||
| <button id="nav-editor">Editor</button> | ||
| <button id="nav-ai">AI Chat</button> | ||
| <button id="nav-proxy">Proxy</button> | ||
| <button id="nav-settings">Settings</button> | ||
| </nav> | ||
| <main id="main-panel"></main> | ||
| </body> | ||
| <!-- References: /reference vault, OWASP, Android10+ UI, DeepSeek API --> | ||
| </html> | ||
|
Comment on lines
+1
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This HTML file serves as the entry point for the modular version of the IDE, but it's missing the necessary |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { initTerminal } from './terminal.js' | ||
| import { initEditor } from './editor.js' | ||
| import { initAIChat } from './ai-chat.js' | ||
| import { initProxy } from './proxy.js' | ||
| import { initSettings } from './settings.js' | ||
|
|
||
| const panels = { | ||
| terminal: initTerminal, | ||
| editor: initEditor, | ||
| ai: initAIChat, | ||
| proxy: initProxy, | ||
| settings: initSettings | ||
| } | ||
| function showPanel(panel) { | ||
| const main = document.getElementById('main-panel') | ||
| main.innerHTML = '' | ||
| panels[panel](main) | ||
| } | ||
| ['terminal','editor','ai','proxy','settings'].forEach(p=>{ | ||
| document.getElementById('nav-'+p).onclick=()=>showPanel(p) | ||
| }) | ||
| showPanel('terminal') |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| export function initProxy(container) { | ||
| container.innerHTML = ` | ||
| <div class="output" id="proxy-output">Proxy system ready.</div> | ||
| <input id="proxy-url" class="chat-input" placeholder="URL"> | ||
| <input id="proxy-method" class="chat-input" style="width:90px;" value="GET"> | ||
| <textarea id="proxy-headers" class="chat-input" style="height:40px;" placeholder='{"Authorization":"Bearer ..."}'></textarea> | ||
| <textarea id="proxy-body" class="chat-input" style="height:40px;" placeholder="Body (JSON)"></textarea> | ||
| <button class="btn" id="proxy-send-btn">Send Proxy Request</button> | ||
| `; | ||
| document.getElementById('proxy-send-btn').onclick = async () => { | ||
| const url = document.getElementById('proxy-url').value.trim(); | ||
| const method = document.getElementById('proxy-method').value.trim(); | ||
| let headers = {}; | ||
| try { headers = JSON.parse(document.getElementById('proxy-headers').value || "{}"); } catch(e){} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Silent catch on JSON.parse may hide header parsing errors. Invalid JSON in headers is ignored, resulting in empty headers. Please add error handling to inform users of parsing failures.
spiralgang marked this conversation as resolved.
|
||
| let body = document.getElementById('proxy-body').value.trim(); | ||
| let options = { method, headers }; | ||
| if (body) options.body = body; | ||
| try { | ||
| let res = await fetch(url, options); | ||
| let text = await res.text(); | ||
| document.getElementById('proxy-output').textContent = text.slice(0,2000); | ||
| } catch(e) { | ||
| document.getElementById('proxy-output').textContent = "Proxy error: "+e.message; | ||
| } | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,19 @@ | ||||||||||
| import { aiKey } from './ai.js'; | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue: Direct assignment to imported 'aiKey' may not update state as expected. Direct assignment may not synchronize changes across modules. Use a setter or event-based method to ensure updates are properly propagated. |
||||||||||
|
|
||||||||||
| export function loadSettings(container) { | ||||||||||
| container.innerHTML = ` | ||||||||||
| <h3>System Settings</h3> | ||||||||||
| <label>AI API Key: <input id="settings-ai-key" class="chat-input" placeholder="Paste DeepSeek/HuggingFace token"></label> | ||||||||||
| <label>Theme: <select id="settings-theme" class="chat-input"> | ||||||||||
| <option value="dark">Dark</option> | ||||||||||
| <option value="light">Light</option> | ||||||||||
| </select></label> | ||||||||||
| `; | ||||||||||
| document.getElementById('settings-ai-key').onchange = e => { | ||||||||||
| aiKey = e.target.value.trim(); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are attempting to reassign the
Suggested change
|
||||||||||
| }; | ||||||||||
| document.getElementById('settings-theme').onchange = e => { | ||||||||||
| document.body.style.background = e.target.value === "light" ? "#f9fafb" : "#111827"; | ||||||||||
| document.body.style.color = e.target.value === "light" ? "#181f2a" : "#e5e7eb"; | ||||||||||
| }; | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,7 @@ | ||||||
| import subprocess | ||||||
| def run_shell_command(cmd): | ||||||
| try: | ||||||
| result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=120) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚨 issue (security): Use of shell=True may introduce security risks if input is not sanitized. If cmd comes from user input or external sources, this can enable shell injection. Prefer shell=False with argument lists, or ensure thorough sanitization.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. security (python.lang.security.audit.dangerous-subprocess-use-audit): Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. Source: opengrep
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. security (python.lang.security.audit.subprocess-shell-true): Found 'subprocess' function 'run' with 'shell=True'. This is dangerous because this call will spawn the command using a shell process. Doing so propagates current shell settings and variables, which makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead.
Suggested change
Source: opengrep
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||||||
| return result.stdout if result.returncode == 0 else result.stderr | ||||||
| except Exception as e: | ||||||
| return f"Shell error: {e}" | ||||||
Uh oh!
There was an error while loading. Please reload this page.