Files
Rpa_Skills/skills/rpa-dashboard-ai/templates/desktop/ai_bridge.py
T

38 lines
1.7 KiB
Python

"""PyQt6 host for the AI desktop dashboard: the no-AI Bridge plus one slot for the AI contract.
Copy next to the no-AI bridge.py and bot_runner.py, with server_stub.py and bands.py.
Run it with: python dashboard/ai_bridge.py
The page sends each AI request (templates/contract.md: runs, review rows, the approve gate)
as ai_request(id, method, path, body) and gets one `ai_response` envelope back. The review
backend answers it in Python, so the approve gate holds whatever the page does.
"""
import json, sys, threading
from PyQt6.QtCore import QUrl, pyqtSlot
from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWebChannel import QWebChannel
import bridge
import server_stub as review # sample data. Once the project has its own review backend, import that (same dispatch()).
class AiBridge(bridge.Bridge):
@pyqtSlot(int, str, str, str)
def ai_request(self, req_id, method, path, body):
# ponytail: answered on the GUI thread; move to a worker if the backend gets slow.
status, payload = review.dispatch(method, path, json.loads(body or "{}"))
self.send_to_js("ai_response", {"id": req_id, "status": status, "body": payload})
if __name__ == "__main__":
threading.Thread(target=review.simulate_extraction, daemon=True).start() # sample data only: delete with server_stub
app = QApplication(sys.argv)
win, view = QMainWindow(), QWebEngineView()
host, channel = AiBridge(view), QWebChannel()
channel.registerObject("pyBridge", host)
view.page().setWebChannel(channel)
view.setUrl(QUrl.fromLocalFile(str(bridge.HTML_PATH)))
win.setCentralWidget(view); win.resize(1280, 820); win.setWindowTitle("{{APP_NAME}}"); win.show()
sys.exit(app.exec())