Skip to content

feat(blockly): Blockly visual programming interface - Sprint 1 - #260

Draft
ikramelaimaa wants to merge 2 commits into
Open-TutorAi:mainfrom
ikramelaimaa:feature/blockly-interface-sprint1
Draft

feat(blockly): Blockly visual programming interface - Sprint 1#260
ikramelaimaa wants to merge 2 commits into
Open-TutorAi:mainfrom
ikramelaimaa:feature/blockly-interface-sprint1

Conversation

@ikramelaimaa

Copy link
Copy Markdown

🧩 Blockly Visual Programming Interface — Sprint 1

Features

  • 🧩 Blockly editor with drag-and-drop blocks → Python code generation
  • 🤖 AI exercise generation via Ollama (SSE streaming)
  • ▶️ Python sandbox execution (5s timeout)
  • 📊 AI feedback with score /100
  • 🏆 Level progression: beginner → intermediate → advanced
  • 📋 Dashboard button with course form popup

New Files

  • learning/blockly/ — models, schemas, service, router, sandbox
  • ai/llm/blockly_generator.py — LLM generator
  • ui/src/routes/student/blockly/new/+page.svelte — Blockly interface

Modified Files

  • ui/src/lib/components/student/pages/Dashboard.svelte
  • ui/vite.config.ts — Fix proxy
  • main.py — Register router

Screenshots

1. Dashboard avec bouton Blockly
1

2. Interface Blockly avec toolbox
2

3. Exécution code → résultat 24
3

4. Score 85/100 + Feedback IA
4

- Add Blockly editor with Python code generation
- Add AI exercise generation via Ollama (SSE streaming)
- Add Python sandbox execution (subprocess, 5s timeout)
- Add AI feedback with score /100
- Add level progression system (beginner -> intermediate -> advanced)
- Add Blockly button in student dashboard with form popup
- Fix Vite proxy: open-tutor-backend -> localhost:8080

Co-authored-by: Oumaima GAOURGOUT
Co-authored-by: Hicham BAAKI
@ikramelaimaa
ikramelaimaa requested a review from pr-elhajji as a code owner June 11, 2026 09:10
@ikramelaimaa
ikramelaimaa marked this pull request as draft June 11, 2026 09:13

@Dakir-Ai Dakir-Ai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi !
I noticed the draft PR currently has merge conflicts.
Please resolve them before marking it as ready for review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a first sprint of a Blockly-based visual programming workflow, adding a new student UI route for building blocks → generating Python, along with backend endpoints for exercise generation, code execution, and AI feedback streaming.

Changes:

  • Added a new Blockly student page (/student/blockly/new) that generates exercises, runs generated Python, and streams AI feedback/score.
  • Added backend learning/blockly module (router/service/sandbox/models/schemas) plus an Ollama-based LLM generator.
  • Updated the student dashboard to launch Blockly via a popup, and adjusted Vite proxy settings / UI dependencies.

Reviewed changes

Copilot reviewed 13 out of 16 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
ui/vite.config.ts Changes dev proxy targets for /api and /ws.
ui/src/routes/student/blockly/new/+page.svelte New Blockly UI: exercise generation (SSE), block workspace, code execution and submission (SSE).
ui/src/lib/components/student/pages/Dashboard.svelte Adds “Blockly” button + popup to capture context and navigate to Blockly page; refactors some existing logic.
ui/src/lib/components/student/pages/Dashboard.svelte.backup Adds a large backup copy of the dashboard component (should not be committed).
ui/package.json Adds Blockly dependency and coverage tool entry adjustment.
ui/package-lock.json Lockfile updates reflecting new dependencies.
package-lock.json Adds a root lockfile with empty packages (likely accidental).
main.py Registers the Blockly router on the FastAPI app (currently placed after the blocking main() call).
learning/blockly/service.py Introduces service layer wrapping sandbox execution and scoring.
learning/blockly/schemas.py Adds Pydantic schemas for execution requests/results and assignments.
learning/blockly/sandbox.py Implements Python execution via subprocess.run with a timeout.
learning/blockly/router.py Adds /api/blockly/* endpoints for execute/test/submit/generate/workspace and SSE streaming.
learning/blockly/models.py Adds SQLAlchemy models for submissions and saved workspaces.
learning/blockly/__init__.py Initializes the new module.
devops/docker/docker-compose.piston.yml Adds a Piston container definition (currently privileged).
ai/llm/blockly_generator.py Adds Ollama-backed generator for exercises and feedback.
Files not reviewed (1)
  • ui/package-lock.json: Generated file

Comment thread main.py
Comment on lines 43 to +45
if __name__ == "__main__":
main()
app.include_router(blockly_router) No newline at end of file
Comment on lines +8 to +9
async def execute_code(self, python_code: str) -> dict:
return execute_python(python_code, timeout=5)
Comment on lines +21 to +24
async def event_stream():
result = await service.execute_code(req.python_code)
score = 85.0
yield f"data: {json.dumps({'type': 'score', 'value': score})}\n\n"
Comment on lines +31 to +33
@router.post("/generate/stream")
async def generate_exercise(body: dict = {}):
level = body.get("level", "beginner")
Comment on lines +9 to +13
result = subprocess.run(
[sys.executable, tmp_path],
capture_output=True, text=True,
timeout=timeout
)
Comment on lines +87 to 91
if (!window.openTutorEvents) window.openTutorEvents = new EventTarget();
window.openTutorEvents.addEventListener('chatCreated', ((event: CustomEvent) => {
const newChatId = event.detail?.chatId;
const timestamp = event.detail?.timestamp;
console.log('Received chatCreated event with chatId:', newChatId, 'timestamp:', timestamp);

if (newChatId && pendingSupportId) {
console.log('Immediately updating support with new chat ID from event');
updateSupportWithChatId(pendingSupportId, newChatId);
}
if (newChatId && pendingSupportId) updateSupportWithChatId(pendingSupportId, newChatId);
}) as EventListener);
Comment on lines 122 to 126
onDestroy(() => {
console.log('Dashboard component destroyed');
if (browser) {
// Remove global event listener
window.openTutorEvents.removeEventListener('chatCreated', ((event: CustomEvent) => {
// This is just for cleanup, the actual handler is defined in onMount
}) as EventListener);

if (chatIdSubscription) {
chatIdSubscription();
console.log('Chat ID subscription removed');
}

if (urlCheckInterval) {
clearInterval(urlCheckInterval);
console.log('URL check interval cleared');
}
if (chatIdSubscription) chatIdSubscription();
if (urlCheckInterval) clearInterval(urlCheckInterval);
}
Comment on lines +1 to +5
<!-- Dashboard.svelte -->
<script lang="ts">
import { getContext, onMount, onDestroy } from 'svelte';
import type { Writable } from 'svelte/store';
import type { i18n as i18nType } from 'i18next';
Comment on lines +4 to +7
image: ghcr.io/engineer-man/piston
container_name: piston
privileged: true
ports:
Comment on lines +1 to +2
from fastapi import APIRouter
from fastapi.responses import StreamingResponse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants