Skip to content

Commit 344ec89

Browse files
authored
Merge branch 'sugarlabs:master' into master
2 parents fd22e9d + b130039 commit 344ec89

File tree

10 files changed

+867
-0
lines changed

10 files changed

+867
-0
lines changed

css/activities.css

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,3 +2020,53 @@ table {
20202020
min-width: 250px;
20212021
max-width: 80%;
20222022
}
2023+
2024+
.chatInterface{
2025+
display: flex;
2026+
flex-direction: column;
2027+
height: 100%;
2028+
padding: "10px";
2029+
background-color: white;
2030+
}
2031+
2032+
.chatLog {
2033+
flex: 1;
2034+
overflow-y: auto;
2035+
border: 1px solid #ccc;
2036+
padding: 10px;
2037+
margin-bottom: 10px;
2038+
display: flex;
2039+
flex-direction: column;
2040+
}
2041+
2042+
.select-mentor {
2043+
width: 80px;
2044+
background: white;
2045+
border-width: 1px;
2046+
border-style: solid;
2047+
border-color: black;
2048+
}
2049+
2050+
.input-query {
2051+
flex: 1;
2052+
padding: 10px;
2053+
margin-right: 10px;
2054+
}
2055+
2056+
.message-container {
2057+
align-self: flex-start;
2058+
background: #dfdfdf;
2059+
color: #000;
2060+
padding: 10px;
2061+
border-radius: 12px;
2062+
max-width: 60%;
2063+
margin-bottom: 8px;
2064+
display: flex;
2065+
flex-direction: column;
2066+
word-wrap: break-word;
2067+
}
2068+
2069+
.message-container.user {
2070+
align-self: flex-end;
2071+
background-color: #DCF8C6;
2072+
}

header-icons/code.svg

Lines changed: 1 addition & 0 deletions
Loading

header-icons/general_mentor.svg

Lines changed: 1 addition & 0 deletions
Loading

header-icons/music.svg

Lines changed: 4 additions & 0 deletions
Loading

header-icons/notes_icon.svg

Lines changed: 1 addition & 0 deletions
Loading

js/activity.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ if (_THIS_IS_MUSIC_BLOCKS_) {
173173
"widgets/timbre",
174174
"widgets/oscilloscope",
175175
"widgets/sampler",
176+
"widgets/reflection",
176177
"activity/lilypond",
177178
"activity/abc",
178179
"activity/midi",
@@ -3123,6 +3124,8 @@ class Activity {
31233124
break;
31243125
}
31253126
case 13: { // 'R or ENTER'
3127+
if (this.isInputON) return;
3128+
31263129
if (this.searchWidget.style.visibility === "visible") {
31273130
return;
31283131
}

js/blocks/WidgetBlocks.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,62 @@ function setupWidgetBlocks(activity) {
16401640
}
16411641
}
16421642

1643+
1644+
class ReflectionBlock extends StackClampBlock {
1645+
/**
1646+
* Creates a ReflectionBlock instance.
1647+
*/
1648+
constructor() {
1649+
super("reflection");
1650+
this.setPalette("widgets", activity);
1651+
this.beginnerBlock(true);
1652+
1653+
this.setHelpString([
1654+
_("The Reflection block opens a space for you to think about your learning."),
1655+
null,
1656+
"reflection"
1657+
]);
1658+
1659+
this.formBlock({ name: _("reflection"), canCollapse: true });
1660+
this.makeMacro((x, y) => [
1661+
[0, "reflection", x, y, [null, 1]],
1662+
[1, "print", 0, 0, [0,2,null]],
1663+
[2, ["text",{"value":"Reflective Learning"}], 0, 0, [1]]
1664+
]);
1665+
}
1666+
1667+
/**
1668+
* Handles the flow of data for the status block.
1669+
* @param {any[]} args - The arguments passed to the block.
1670+
* @param {object} logo - The logo object.
1671+
* @param {object} turtle - The turtle object.
1672+
* @param {object} blk - The block object.
1673+
*/
1674+
flow(args, logo, turtle, blk) {
1675+
if (logo.reflection === null) {
1676+
logo.reflection = new ReflectionMatrix();
1677+
}
1678+
1679+
logo.reflection.init(activity);
1680+
logo.statusFields = [];
1681+
1682+
logo.inReflectionMatrix = true;
1683+
1684+
const listenerName = "_reflection_" + turtle;
1685+
logo.setDispatchBlock(blk, turtle, listenerName);
1686+
1687+
const __listener = () => {
1688+
logo.reflection.init(activity);
1689+
logo.inReflectionMatrix = false;
1690+
};
1691+
1692+
logo.setTurtleListener(turtle, listenerName, __listener);
1693+
1694+
if (args.length === 1) return [args[0], 1];
1695+
}
1696+
}
1697+
1698+
16431699
class AIDebugger extends StackClampBlock {
16441700
constructor() {
16451701
super("aidebugger");
@@ -1690,6 +1746,7 @@ function setupWidgetBlocks(activity) {
16901746
}
16911747
}
16921748

1749+
16931750
// Set up blocks if this is Music Blocks environment
16941751
if (_THIS_IS_MUSIC_BLOCKS_) {
16951752
new EnvelopeBlock().setup(activity);
@@ -1705,6 +1762,7 @@ function setupWidgetBlocks(activity) {
17051762
new oscilloscopeWidgetBlock().setup(activity);
17061763
new PitchSliderBlock().setup(activity);
17071764
new ChromaticBlock().setup(activity);
1765+
new ReflectionBlock().setup(activity);
17081766
// new AIMusicBlocks().setup(activity);
17091767
new MusicKeyboard2Block().setup(activity);
17101768
new MusicKeyboardBlock().setup(activity);

js/logo.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class Logo {
110110
this._meSpeak = this.activity.meSpeak;
111111

112112
// Widgets
113+
this.reflection = null;
113114
this.phraseMaker = null;
114115
this.pitchDrumMatrix = null;
115116
this.arpeggio = null;

js/widgets/reflection-guide.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Reflection Widget - Developer Guide
2+
3+
## Overview
4+
5+
The `ReflectionMatrix` class provides a chat-based interface for users to interact with AI mentors for reflecting on their music blocks project. It manages chat history, mentor selection, message exchange with a backend server, and report generation.
6+
7+
Backend Code for the widget : [musicblocks_reflection_fastapi](https://github.com/Commanderk3/musicblocks_reflection_fastapi)
8+
9+
## Key Features
10+
11+
- **Multi-mentor Chat:** Switch between AI mentors (Meta/Rohan, Music/Beethoven, Code/Steve).
12+
- **Chat History:** Stores and renders conversation history.
13+
- **Typing Indicator:** Shows animated "Thinking..." while awaiting responses.
14+
- **Markdown Rendering:** Converts Markdown responses to HTML for display.
15+
- **Analysis & Summary:** Fetches project analysis after sufficient chat history.
16+
- **Local Storage:** Saves and retrieves analysis reports.
17+
- **Export:** Download chat transcript as a text file.
18+
19+
## Components
20+
21+
- **Widget Interface**: `js/widgets/reflection.js`
22+
- **Block Definition**: `js/blocks/WidgetBlocks.js`
23+
- **Registration**: `js/activity.js` (line 176) and `js/logo.js` (line 113)
24+
- **CSS styling**: `css/activities.css` (line 2023 - 2072)
25+
26+
## Methods
27+
28+
- **Widget Window Initialisation**
29+
30+
`init(activity)` : Triggers when the reflection block is clicked. It renders the widget and initializes the required data structures.
31+
32+
---
33+
34+
- **Mentor Switching**
35+
36+
`changeMentor("code")` : Changes the active mentor and updates button highlights.
37+
38+
---
39+
40+
- Sending Messages
41+
42+
`sendMessage()` : Pushes user message to history, displays it, and requests bot reply.
43+
44+
---
45+
46+
- Bot Reply Handling
47+
48+
`botReplyDiv(message, user_query, md)` :
49+
50+
- If `user_query` is true, sends message to backend and displays reply.
51+
- If `md` is true, renders reply as Markdown.
52+
53+
---
54+
55+
- Analysis & Summary
56+
57+
`getAnalysis()` :
58+
59+
- Requests project analysis from backend if chat history is sufficient.
60+
- Saves analysis to localStorage.
61+
62+
---
63+
64+
- Local Storage
65+
66+
- **Save:** `saveReport(data)` stores analysis.
67+
- **Read:** `readReport()` retrieves analysis.
68+
69+
---
70+
71+
- Export Conversation
72+
73+
`downloadAsTxt(conversationData)` : Downloads chat history as a `.txt` file.
74+
75+
---
76+
77+
- Markdown Rendering
78+
79+
`mdToHTML(md)` : Converts Markdown to HTML for display in chat.
80+
81+
---
82+
83+
## API Endpoints
84+
85+
### 1. `/projectcode`
86+
87+
- **Method:** `POST`
88+
- **Purpose:** Sends the exported project code to the backend to receive an algorithmic summary.
89+
- **Payload:**
90+
```json
91+
{
92+
"code": "<project code string>"
93+
}
94+
```
95+
- **Response:**
96+
```json
97+
{
98+
"algorithm": "<algorithm string>",
99+
"message": "<first message>"
100+
}
101+
```
102+
or
103+
```json
104+
{
105+
"error": "<error message>"
106+
}
107+
```
108+
109+
---
110+
111+
### 2. `/chat`
112+
113+
- **Method:** `POST`
114+
- **Purpose:** Sends a user query, chat history, mentor selection, and project algorithm to the backend to get an AI mentor's reply.
115+
- **Payload:**
116+
```json
117+
{
118+
"query": "<user message>",
119+
"messages": [ { "role": "...", "content": "..." }, ... ],
120+
"mentor": "<mentor key>",
121+
"algorithm": "<algorithm string>"
122+
}
123+
```
124+
- **Response:**
125+
`{ response: "<bot reply>" }`
126+
or
127+
`{ error: "<error message>" }`
128+
129+
- **Example `messages` structure**
130+
```json
131+
[
132+
{
133+
"role": "meta",
134+
"content": "hello"
135+
},
136+
{
137+
"role": "user",
138+
"content": "hi"
139+
},
140+
{
141+
"role": "meta",
142+
"content": "Hey there! I'm Rohan, the meta-mentor here. Tell me, what did you create in your project?"
143+
}
144+
]
145+
```
146+
147+
---
148+
149+
### 3. `/analysis`
150+
151+
- **Method:** `POST`
152+
- **Purpose:** Sends the chat history and summary to the backend to receive a project analysis report.
153+
- **Payload:**
154+
```json
155+
{
156+
"messages": [ { "role": "...", "content": "..." }, ... ],
157+
"summary": "<summary string>"
158+
}
159+
```
160+
- **Response:**
161+
`{ response: "<analysis report>" }`
162+
or
163+
`{ error: "<error message>" }`
164+
165+
---
166+
167+
**All endpoints expect and return JSON.**
168+
**The backend is expected to run locally while development.**
169+
170+
---
171+
172+
### API testing
173+
174+
```bash
175+
curl -X POST http://localhost:PORT/projectcode \
176+
-H "Content-Type: application/json" \
177+
-d '{
178+
"code": "MUSICBLOCKS_PROJECT_CODE_HERE"
179+
}'
180+
```
181+
182+
**Note** : Save your Music Blocks project as an HTML file. Open the file to locate the embedded JSON code, and make sure to stringify the JSON before using it for testing.
183+
184+
Written by : [Diwangshu Kakoty](https://github.com/Commanderk3)

0 commit comments

Comments
 (0)