Skip to content

Feat/improve - #2

Open
Ayush-Vish wants to merge 4 commits into
mainfrom
feat/improve
Open

Feat/improve#2
Ayush-Vish wants to merge 4 commits into
mainfrom
feat/improve

Conversation

@Ayush-Vish

@Ayush-Vish Ayush-Vish commented Apr 1, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Interactive onboarding and multi-step assignment workflow via messaging
    • Multiple output formats: PDF, Word, Excel, and code-image exports
    • Web dashboard with live connection status and event log
    • CLI setup wizard for configuring LLM/provider and channels
    • Upload options for classroom/platform submission and multiple LLM provider support
  • Documentation

    • Expanded README with features, setup, and usage
  • Chores

    • Daemon/start scripts and CLI/dependency additions

Copilot AI review requested due to automatic review settings April 1, 2026 17:36
@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Free

Run ID: c02d42f4-6086-4590-905f-40c8dabb3266

📥 Commits

Reviewing files that changed from the base of the PR and between 64fd9ba and eff88fb.

📒 Files selected for processing (1)
  • README.md
✅ Files skipped from review due to trivial changes (1)
  • README.md

📝 Walkthrough

Walkthrough

Adds end-to-end assignment workflow: persistent per-user sessions, interactive CLI setup, multi-provider LLM integration, PDF parsing, multiple output format generators, classroom/puppeteer upload stubs, a WebSocket dashboard with log broadcasting, and multi-platform bot startup (Telegram + placeholders for WhatsApp/Slack).

Changes

Cohort / File(s) Summary
Config & env
.config/store.json, .env, .gitignore, package.json, README.md
Adds persisted store file; writes TELEGRAM_BOT_TOKEN to .env; replaces dotenv ignore patterns with .config in .gitignore; adds npm scripts and deps (@clack/prompts, picocolors, xlsx); replaces README with full project docs.
Web dashboard
public/index.html
New static dashboard served by gateway with WebSocket client, log display, auto-reconnect, and disabled simulator input.
Bot & CLI
src/bot/index.ts, src/cli/setup.ts
Refactors Telegram bot to step-based onboarding/session flows, message handlers for text/document/photo, centralized error logging; adds interactive CLI runInteractiveSetup() that writes .config/scholar.json and collects LLM/channel credentials; exports WhatsApp/Slack start placeholders.
Gateway & entry
src/daemon/gateway/server.ts, src/index.ts
Gateway reworked to host HTTP + WebSocket on shared server, serve dashboard, broadcast logger events; startup now loads .config into env, validates config, may run interactive setup, and starts gateway plus multiple bot starters.
Core modules — LLM / parsing / formatters / store / logger
src/core/llm.ts, src/core/parser.ts, src/core/formatters.ts, src/core/store.ts, src/core/logger.ts
New LLM adapter supporting Gemini/OpenAI/OpenRouter (HTTP calls), PDF parsing wrapper, formatters to produce PDF/Word/Excel/code image (Docker/Pandoc, xlsx, freeze CLI), JSON-backed store at .config/store.json, and structured logger with external broadcaster.
Classroom & schema
src/core/classroom.ts, src/core/schema.ts
Adds upload stubs for Google Classroom and Puppeteer-based uploads; extends ScholarConfig.llm.provider to include openrouter.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Bot as "Messaging Bot"
    participant Store as "State Store\n(.config/store.json)"
    participant LLM as "LLM Provider\n(OpenAI/Gemini/OpenRouter)"
    participant Parser as "PDF Parser"
    participant Formatter as "Formatters\n(PDF/Word/Excel/Image)"
    participant Uploader as "Uploader\n(Classroom/Puppeteer)"
    participant Logger as "Logger/Broadcaster"
    participant Dashboard as "Web Dashboard"

    User->>Bot: Send /start or assignment (text/PDF)
    Bot->>Store: loadStore(sessionId)
    alt PDF received
        Bot->>Parser: parsePdfBuffer(fileBuffer)
        Parser-->>Bot: extractedText
        Bot->>LLM: generateAssignmentSolution(prompt, extractedText)
    else Text prompt
        Bot->>LLM: generateAssignmentSolution(prompt, userContext)
    end
    LLM-->>Bot: solutionText
    Bot->>Store: save session.solution
    Bot->>User: ask for output format
    User->>Bot: choose format
    Bot->>Formatter: generate* (solutionText)
    Formatter-->>Bot: fileBuffer
    Bot->>User: send file
    User->>Bot: choose platform
    Bot->>Uploader: uploadToClassroom / uploadViaPuppeteer
    Uploader-->>Bot: uploadResult
    Bot->>Logger: logger.info / success
    Logger->>Dashboard: broadcast system_log
    Dashboard-->>User: realtime logs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 I hopped through configs, logs, and chat,
Saved sessions in a cozy flat,
Parsed PDFs and asked for name,
Told LLMs to craft the game,
Dashboards blink — ScholarSync leaps at that! 🥕


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Implement user onboarding, multi-platform bots, LLM integration, and document processing with dashboard

✨ Enhancement 📝 Documentation

Grey Divider

Walkthroughs

Description
• Implement comprehensive user onboarding flow with persistent user/session storage
• Add multi-platform bot support (Telegram, WhatsApp, Slack) with core LLM integration
• Create interactive CLI setup wizard for configuring LLM providers and messaging channels
• Implement document processing pipeline with PDF parsing and multi-format output generation
• Add web-based dashboard with real-time WebSocket logging and system monitoring
• Support multiple LLM providers (OpenAI, Gemini, OpenRouter, Ollama) with flexible model selection
Diagram
flowchart LR
  User["User/Messaging Platform"]
  Bot["Multi-Platform Bot<br/>Telegram/WhatsApp/Slack"]
  Onboard["User Onboarding<br/>Flow"]
  Store["Persistent Store<br/>Users & Sessions"]
  LLM["LLM Provider<br/>OpenAI/Gemini/Ollama"]
  Parser["PDF Parser"]
  Format["Format Generators<br/>PDF/Word/Excel/Image"]
  Gateway["Gateway Daemon<br/>WebSocket Server"]
  Dashboard["Web Dashboard<br/>Real-time Logs"]
  
  User -->|Messages| Bot
  Bot -->|First Time| Onboard
  Onboard -->|Save| Store
  Bot -->|Process| Parser
  Parser -->|Extract Text| LLM
  LLM -->|Generate Solution| Format
  Bot -->|Broadcast Logs| Gateway
  Gateway -->|Stream Events| Dashboard
  Store -->|Load/Save| Bot
Loading

Grey Divider

File Changes

1. src/bot/index.ts ✨ Enhancement +224/-12

Implement comprehensive Telegram bot with onboarding and multi-format support

src/bot/index.ts


2. src/cli/setup.ts ✨ Enhancement +209/-0

Add interactive CLI setup wizard for configuration

src/cli/setup.ts


3. src/core/formatters.ts ✨ Enhancement +114/-0

Implement document generation using Docker and Freeze

src/core/formatters.ts


View more (14)
4. src/core/llm.ts ✨ Enhancement +72/-0

Add LLM integration supporting multiple cloud and local providers

src/core/llm.ts


5. src/core/parser.ts ✨ Enhancement +16/-0

Implement PDF buffer parsing for document extraction

src/core/parser.ts


6. src/core/logger.ts ✨ Enhancement +33/-0

Create centralized logging with WebSocket broadcast capability

src/core/logger.ts


7. src/core/store.ts ✨ Enhancement +26/-0

Implement persistent user and session storage management

src/core/store.ts


8. src/core/classroom.ts ✨ Enhancement +51/-0

Add Google Classroom and platform upload integration

src/core/classroom.ts


9. src/core/schema.ts ✨ Enhancement +2/-2

Add OpenRouter to supported LLM providers

src/core/schema.ts


10. src/daemon/gateway/server.ts ✨ Enhancement +36/-17

Enhance gateway with HTTP server and dashboard serving

src/daemon/gateway/server.ts


11. src/index.ts ✨ Enhancement +40/-4

Add configuration loading and multi-bot initialization logic

src/index.ts


12. public/index.html 📝 Documentation +257/-0

Create real-time dashboard with WebSocket log streaming

public/index.html


13. README.md 📝 Documentation +71/-1

Add comprehensive project documentation and feature overview

README.md


14. package.json Dependencies +7/-1

Add new dependencies and npm scripts for daemon management

package.json


15. .env ⚙️ Configuration changes +1/-0

Add Telegram bot token environment variable

.env


16. .config/store.json ⚙️ Configuration changes +17/-0

Add sample user and session data for testing

.config/store.json


17. bin/freeze Additional files +0/-0

...

bin/freeze


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Apr 1, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (6) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Committed bot token 🐞 Bug ⛨ Security
Description
A real TELEGRAM_BOT_TOKEN is committed in .env, allowing anyone with repository access (or
leaked history) to fully control the Telegram bot. This secret must be rotated and removed from git
history to prevent account takeover.
Code

.env[1]

+TELEGRAM_BOT_TOKEN=8606625998:AAGuNWcFKDyXBSBITEie_NCSqZ2j2GZ6dC4
Evidence
The PR adds a plaintext bot token to a tracked .env file; even though .env is ignored going
forward, committing it once leaks it via git history.

.env[1-1]
.gitignore[65-77]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A real Telegram bot token is committed in `.env`, which is a credential that enables full bot control. Once committed, it remains accessible through git history even if later removed.

## Issue Context
`.gitignore` already lists `.env`, so this appears accidental but still security-critical.

## Fix
1. Rotate/revoke the leaked Telegram bot token immediately (via @BotFather) and issue a new one.
2. Remove `.env` from the repository (and ensure it is not tracked): `git rm --cached .env`.
3. Purge the secret from git history (e.g., `git filter-repo` / BFG) and force-push if this repo is shared.
4. Add a safe template file (e.g., `.env.example`) with placeholder values.

## Fix Focus Areas
- .env[1-1]
- .gitignore[65-77]
- README.md[57-71]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Committed user PII store 🐞 Bug ⛨ Security
Description
The PR commits .config/store.json containing a user's name, roll number, university, and full
session/solution content. This leaks personal data and must be removed from the repo (and git
history) and treated as runtime-only state.
Code

.config/store.json[R1-17]

+{
+  "users": {
+    "1711055629": {
+      "name": "Ayush",
+      "roll": "6372373",
+      "uni": "IIITM Gwalior"
+    }
+  },
+  "sessions": {
+    "1711055629": {
+      "step": "AWAITING_PLATFORM",
+      "context": "Make a assignment for bubble sort and give me pdf withe rhr code and code op screenshot",
+      "solution": "Assignment: Implementation and Performance Analysis of Bubble Sort Algorithm\nStudent Name: Ayush\nRoll Number: 6372373\nUniversity: IIITM Gwalior\nDate: 4/1/2026\n\n1. Objective\nThe objective of this assignment is to implement the Bubble Sort algorithm, document the step-by-step logic, provide the source code, and analyze its time complexity in the context of sorting an array of integers.\n\n2. Problem Statement\nWrite a program to sort an array of $n$ elements using the Bubble Sort technique. The program must:\na) Accept input size $n$ and an array of $n$ integers from the user.\nb) Perform the sort by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order.\nc) Display the sorted array.\n\n3. Algorithm Description\nBubble Sort is a comparison-based algorithm where each pair of adjacent elements is compared, and elements are swapped if they are not in order. This process repeats until the array is sorted.\n- Time Complexity: O(n²) in the worst and average cases.\n- Space Complexity: O(1) as it is an in-place sorting algorithm.\n\n4. Source Code (Python)\n```python\ndef bubble_sort(arr):\n    n = len(arr)\n    for i in range(n):\n        for j in range(0, n - i - 1):\n            if arr[j] > arr[j + 1]:\n                arr[j], arr[j + 1] = arr[j + 1], arr[j]\n    return arr\n\n# Driver code\nif __name__ == \"__main__\":\n    data = [64, 34, 25, 12, 22, 11, 90]\n    print(\"Original array:\", data)\n    sorted_data = bubble_sort(data)\n    print(\"Sorted array:\", sorted_data)\n```\n\n5. Output Screenshot Placeholder\n[Insert Screenshot of Program Execution Here]\n\n6. Conclusion\nThe implementation confirms that Bubble Sort is effective for smaller datasets but inefficient for large-scale data due to its quadratic time complexity. Proper documentation of the swapping mechanism demonstrates the fundamental working principle of the algorithm.",
+      "format": "Pdf with code op"
+    }
+  }
+}
Evidence
The committed store file contains real user data and is the same path the application reads/writes
for ongoing onboarding/session state, so it will accumulate sensitive data over time.

.config/store.json[1-17]
src/core/store.ts[4-26]
src/bot/index.ts[17-28]
.gitignore[65-77]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`.config/store.json` is committed with real user PII and session content. This file is runtime state and should never be shipped or tracked.

## Issue Context
The application persists onboarding/session state to `.config/store.json`, so committing it risks leaking real user data and future sessions.

## Fix
1. Remove `.config/store.json` from git tracking (`git rm --cached .config/store.json`).
2. Purge it from git history if already pushed.
3. Ensure `.config/` remains ignored (it already is) and consider adding an explicit `.config/store.json.example` if you need a schema/sample.
4. (Optional hardening) Store sensitive data with least privilege: file permissions (0600), encryption at rest, and/or move to a proper DB.

## Fix Focus Areas
- .config/store.json[1-17]
- src/core/store.ts[4-26]
- src/bot/index.ts[17-28]
- .gitignore[65-77]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Log viewer XSS injection 🐞 Bug ⛨ Security
Description
The dashboard renders log message and meta using innerHTML without escaping, while
user-controlled Telegram text is logged and broadcast to the dashboard. An attacker can send a
payload like </span><img src=x onerror=alert(1)> to execute script in the operator’s browser.
Code

public/index.html[R199-213]

+        function appendLog(level, message, meta) {
+            const time = new Date().toLocaleTimeString();
+            const el = document.createElement('div');
+            el.className = 'log-entry';
+            
+            let html = `<span class="log-time">${time}</span>`;
+            html += `<span class="log-level ${level}">[${level}]</span>`;
+            html += `<span class="log-message">${message}</span>`;
+            
+            if (meta && Object.keys(meta).length > 0) {
+                html += `<span class="log-meta">${JSON.stringify(meta, null, 2)}</span>`;
+            }
+            
+            el.innerHTML = html;
+            terminal.appendChild(el);
Evidence
appendLog() concatenates strings and assigns them to el.innerHTML, including
JSON.stringify(meta). The bot logs untrusted user text into meta, the logger broadcasts it to
websocket clients, and the dashboard displays it via innerHTML, enabling HTML injection/XSS.

public/index.html[199-213]
src/bot/index.ts[34-42]
src/core/logger.ts[16-32]
src/daemon/gateway/server.ts[36-38]
src/daemon/gateway/server.ts[81-88]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The dashboard uses `innerHTML` to render log fields coming from untrusted sources (Telegram user text inside `meta`). This allows HTML injection and XSS in the dashboard.

## Issue Context
User-controlled text is logged (`{ text }` meta), broadcast over the gateway websocket, and rendered by the dashboard.

## Fix
- Replace `innerHTML` rendering with DOM APIs and `textContent`.
 - Create spans with `document.createElement('span')` and set `.textContent` for time/level/message.
 - For `meta`, render into a `<pre>` (or `<span>`) and set `.textContent = JSON.stringify(meta, null, 2)`.
- (Defense-in-depth) Add a restrictive CSP header when serving the dashboard and consider sanitizing log payloads server-side.

## Fix Focus Areas
- public/index.html[199-213]
- src/bot/index.ts[34-42]
- src/core/logger.ts[16-32]
- src/daemon/gateway/server.ts[36-38]
- src/daemon/gateway/server.ts[81-88]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. Gateway exposed without auth 🐞 Bug ⛨ Security
Description
GatewayServer listens without binding to loopback and accepts any WebSocket connection without
authentication, despite the setup UI claiming loopback-only binding. If reachable on the network,
anyone can connect and receive broadcast logs (including user content) and interact with the
gateway.
Code

src/daemon/gateway/server.ts[R39-47]

+        this.server.listen(port, () => {
+            console.log(`Gateway & Dashboard running on http://localhost:${port}`);
+        });
    }

    private initialize() {
        this.wss.on('connection', (ws: WebSocket) => {
-            console.log('Client connected to Gateway');
+            logger.info('Dashboard/Client connected to Gateway WebSocket');
            this.clients.add(ws);
Evidence
The server calls listen(port) without a host, which binds to all interfaces by default, and there
are no auth/origin checks in the websocket connection handler. The interactive setup note explicitly
claims loopback binding, creating a dangerous mismatch between user expectations and actual
exposure.

src/daemon/gateway/server.ts[39-62]
src/cli/setup.ts[48-52]
src/daemon/gateway/server.ts[36-38]
src/daemon/gateway/server.ts[81-88]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The gateway/dashboard server is network-exposed by default and has no authentication for websocket clients, which can leak logs and enable unauthorized access.

## Issue Context
Setup text claims loopback binding, but implementation does not specify a host.

## Fix
1. Bind explicitly to loopback by default:
  - `this.server.listen(port, '127.0.0.1', ...)`
  - Optionally support a config/env override for advanced users.
2. Add websocket access control:
  - Require an auth token (query param or header) and reject missing/invalid tokens.
  - Validate `Origin` / `Host` as appropriate.
3. Consider disabling log broadcasting unless explicitly enabled.

## Fix Focus Areas
- src/daemon/gateway/server.ts[14-42]
- src/daemon/gateway/server.ts[44-63]
- src/cli/setup.ts[48-52]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. CLI init no longer works 🐞 Bug ≡ Correctness
Description
The CLI still sends an init_config request to the daemon, but the gateway no longer handles
init_config and will respond with Unknown command. This breaks scholar init and prevents
config initialization via the gateway.
Code

src/daemon/gateway/server.ts[R71-78]

    private handleRequest(ws: WebSocket, request: RequestMessage) {
-        console.log(`Received request command: ${request.command}`);
-
        switch (request.command) {
            case 'ping':
                ws.send(JSON.stringify(createResponse(request.id, true, { message: 'pong' })));
                break;
-            case 'init_config':
-                console.log('Received config init payload:', request.payload);
-                // Implementation for saving the config logic would go here
-                ws.send(JSON.stringify(createResponse(request.id, true, { status: 'saved' })));
-
-                // Broadcast an event to all connected clients that config changed
-                this.broadcastEvent('config_updated', { version: request.payload?.version || '1.0' });
-                break;
            default:
                ws.send(JSON.stringify(createResponse(request.id, false, undefined, 'Unknown command')));
        }
Evidence
The CLI hardcodes the init_config command, but the gateway request handler only supports ping
now, so initialization cannot succeed.

src/cli/index.ts[15-25]
src/daemon/gateway/server.ts[71-78]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scholar init` is broken because it sends `init_config` but the gateway does not implement this command anymore.

## Issue Context
The CLI uses the gateway websocket to initialize configuration.

## Fix
Choose one:
- **Option A (restore behavior):** Re-add an `init_config` handler in `GatewayServer.handleRequest` that writes `.config/scholar.json` (or delegates to the setup flow) and returns success.
- **Option B (remove dependency):** Update/remove the CLI `init` command so it writes `.config/scholar.json` locally (similar to `runInteractiveSetup`) rather than requiring the daemon.

## Fix Focus Areas
- src/cli/index.ts[15-35]
- src/daemon/gateway/server.ts[71-78]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Undefined userId stored 🐞 Bug ≡ Correctness
Description
Handlers compute userId with String(ctx.from?.id) and then check if (!userId), but
String(undefined) becomes the truthy string "undefined", allowing sessions/users to be persisted
under the key "undefined". This can corrupt the persistent store and mix multiple anonymous events
into the same session bucket.
Code

src/bot/index.ts[R21-27]

+    bot.start(async (ctx) => {
+        const userId = String(ctx.from?.id);
+        if (!userId) return;
+
+        if (!store.users[userId]) {
+            store.sessions[userId] = { step: 'ASK_NAME' };
+            saveStore(store);
Evidence
The /start, document, and photo handlers all convert a possibly-missing ctx.from?.id to a string
before validating presence, so the validation cannot catch missing IDs.

src/bot/index.ts[21-27]
src/bot/index.ts[167-172]
src/bot/index.ts[216-221]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`String(ctx.from?.id)` turns `undefined` into the truthy string "undefined"; the subsequent `if (!userId)` guard is ineffective and can persist state under an invalid user key.

## Issue Context
This pattern exists in multiple handlers (`/start`, document, photo). The store is persisted to disk, so corruption persists across restarts.

## Fix
- Validate the ID before coercion:
 - `const fromId = ctx.from?.id; if (!fromId) return; const userId = String(fromId);`
- Use the same `userId` type consistently across handlers.

## Fix Focus Areas
- src/bot/index.ts[21-31]
- src/bot/index.ts[167-172]
- src/bot/index.ts[216-221]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread .env
@@ -0,0 +1 @@
TELEGRAM_BOT_TOKEN=8606625998:AAGuNWcFKDyXBSBITEie_NCSqZ2j2GZ6dC4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Committed bot token 🐞 Bug ⛨ Security

A real TELEGRAM_BOT_TOKEN is committed in .env, allowing anyone with repository access (or
leaked history) to fully control the Telegram bot. This secret must be rotated and removed from git
history to prevent account takeover.
Agent Prompt
## Issue description
A real Telegram bot token is committed in `.env`, which is a credential that enables full bot control. Once committed, it remains accessible through git history even if later removed.

## Issue Context
`.gitignore` already lists `.env`, so this appears accidental but still security-critical.

## Fix
1. Rotate/revoke the leaked Telegram bot token immediately (via @BotFather) and issue a new one.
2. Remove `.env` from the repository (and ensure it is not tracked): `git rm --cached .env`.
3. Purge the secret from git history (e.g., `git filter-repo` / BFG) and force-push if this repo is shared.
4. Add a safe template file (e.g., `.env.example`) with placeholder values.

## Fix Focus Areas
- .env[1-1]
- .gitignore[65-77]
- README.md[57-71]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread .config/store.json
Comment on lines +1 to +17
{
"users": {
"1711055629": {
"name": "Ayush",
"roll": "6372373",
"uni": "IIITM Gwalior"
}
},
"sessions": {
"1711055629": {
"step": "AWAITING_PLATFORM",
"context": "Make a assignment for bubble sort and give me pdf withe rhr code and code op screenshot",
"solution": "Assignment: Implementation and Performance Analysis of Bubble Sort Algorithm\nStudent Name: Ayush\nRoll Number: 6372373\nUniversity: IIITM Gwalior\nDate: 4/1/2026\n\n1. Objective\nThe objective of this assignment is to implement the Bubble Sort algorithm, document the step-by-step logic, provide the source code, and analyze its time complexity in the context of sorting an array of integers.\n\n2. Problem Statement\nWrite a program to sort an array of $n$ elements using the Bubble Sort technique. The program must:\na) Accept input size $n$ and an array of $n$ integers from the user.\nb) Perform the sort by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order.\nc) Display the sorted array.\n\n3. Algorithm Description\nBubble Sort is a comparison-based algorithm where each pair of adjacent elements is compared, and elements are swapped if they are not in order. This process repeats until the array is sorted.\n- Time Complexity: O(n²) in the worst and average cases.\n- Space Complexity: O(1) as it is an in-place sorting algorithm.\n\n4. Source Code (Python)\n```python\ndef bubble_sort(arr):\n n = len(arr)\n for i in range(n):\n for j in range(0, n - i - 1):\n if arr[j] > arr[j + 1]:\n arr[j], arr[j + 1] = arr[j + 1], arr[j]\n return arr\n\n# Driver code\nif __name__ == \"__main__\":\n data = [64, 34, 25, 12, 22, 11, 90]\n print(\"Original array:\", data)\n sorted_data = bubble_sort(data)\n print(\"Sorted array:\", sorted_data)\n```\n\n5. Output Screenshot Placeholder\n[Insert Screenshot of Program Execution Here]\n\n6. Conclusion\nThe implementation confirms that Bubble Sort is effective for smaller datasets but inefficient for large-scale data due to its quadratic time complexity. Proper documentation of the swapping mechanism demonstrates the fundamental working principle of the algorithm.",
"format": "Pdf with code op"
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Committed user pii store 🐞 Bug ⛨ Security

The PR commits .config/store.json containing a user's name, roll number, university, and full
session/solution content. This leaks personal data and must be removed from the repo (and git
history) and treated as runtime-only state.
Agent Prompt
## Issue description
`.config/store.json` is committed with real user PII and session content. This file is runtime state and should never be shipped or tracked.

## Issue Context
The application persists onboarding/session state to `.config/store.json`, so committing it risks leaking real user data and future sessions.

## Fix
1. Remove `.config/store.json` from git tracking (`git rm --cached .config/store.json`).
2. Purge it from git history if already pushed.
3. Ensure `.config/` remains ignored (it already is) and consider adding an explicit `.config/store.json.example` if you need a schema/sample.
4. (Optional hardening) Store sensitive data with least privilege: file permissions (0600), encryption at rest, and/or move to a proper DB.

## Fix Focus Areas
- .config/store.json[1-17]
- src/core/store.ts[4-26]
- src/bot/index.ts[17-28]
- .gitignore[65-77]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread public/index.html
Comment on lines +199 to +213
function appendLog(level, message, meta) {
const time = new Date().toLocaleTimeString();
const el = document.createElement('div');
el.className = 'log-entry';

let html = `<span class="log-time">${time}</span>`;
html += `<span class="log-level ${level}">[${level}]</span>`;
html += `<span class="log-message">${message}</span>`;

if (meta && Object.keys(meta).length > 0) {
html += `<span class="log-meta">${JSON.stringify(meta, null, 2)}</span>`;
}

el.innerHTML = html;
terminal.appendChild(el);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Log viewer xss injection 🐞 Bug ⛨ Security

The dashboard renders log message and meta using innerHTML without escaping, while
user-controlled Telegram text is logged and broadcast to the dashboard. An attacker can send a
payload like </span><img src=x onerror=alert(1)> to execute script in the operator’s browser.
Agent Prompt
## Issue description
The dashboard uses `innerHTML` to render log fields coming from untrusted sources (Telegram user text inside `meta`). This allows HTML injection and XSS in the dashboard.

## Issue Context
User-controlled text is logged (`{ text }` meta), broadcast over the gateway websocket, and rendered by the dashboard.

## Fix
- Replace `innerHTML` rendering with DOM APIs and `textContent`.
  - Create spans with `document.createElement('span')` and set `.textContent` for time/level/message.
  - For `meta`, render into a `<pre>` (or `<span>`) and set `.textContent = JSON.stringify(meta, null, 2)`.
- (Defense-in-depth) Add a restrictive CSP header when serving the dashboard and consider sanitizing log payloads server-side.

## Fix Focus Areas
- public/index.html[199-213]
- src/bot/index.ts[34-42]
- src/core/logger.ts[16-32]
- src/daemon/gateway/server.ts[36-38]
- src/daemon/gateway/server.ts[81-88]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +39 to 47
this.server.listen(port, () => {
console.log(`Gateway & Dashboard running on http://localhost:${port}`);
});
}

private initialize() {
this.wss.on('connection', (ws: WebSocket) => {
console.log('Client connected to Gateway');
logger.info('Dashboard/Client connected to Gateway WebSocket');
this.clients.add(ws);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

4. Gateway exposed without auth 🐞 Bug ⛨ Security

GatewayServer listens without binding to loopback and accepts any WebSocket connection without
authentication, despite the setup UI claiming loopback-only binding. If reachable on the network,
anyone can connect and receive broadcast logs (including user content) and interact with the
gateway.
Agent Prompt
## Issue description
The gateway/dashboard server is network-exposed by default and has no authentication for websocket clients, which can leak logs and enable unauthorized access.

## Issue Context
Setup text claims loopback binding, but implementation does not specify a host.

## Fix
1. Bind explicitly to loopback by default:
   - `this.server.listen(port, '127.0.0.1', ...)`
   - Optionally support a config/env override for advanced users.
2. Add websocket access control:
   - Require an auth token (query param or header) and reject missing/invalid tokens.
   - Validate `Origin` / `Host` as appropriate.
3. Consider disabling log broadcasting unless explicitly enabled.

## Fix Focus Areas
- src/daemon/gateway/server.ts[14-42]
- src/daemon/gateway/server.ts[44-63]
- src/cli/setup.ts[48-52]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 71 to 78
private handleRequest(ws: WebSocket, request: RequestMessage) {
console.log(`Received request command: ${request.command}`);

switch (request.command) {
case 'ping':
ws.send(JSON.stringify(createResponse(request.id, true, { message: 'pong' })));
break;
case 'init_config':
console.log('Received config init payload:', request.payload);
// Implementation for saving the config logic would go here
ws.send(JSON.stringify(createResponse(request.id, true, { status: 'saved' })));

// Broadcast an event to all connected clients that config changed
this.broadcastEvent('config_updated', { version: request.payload?.version || '1.0' });
break;
default:
ws.send(JSON.stringify(createResponse(request.id, false, undefined, 'Unknown command')));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

5. Cli init no longer works 🐞 Bug ≡ Correctness

The CLI still sends an init_config request to the daemon, but the gateway no longer handles
init_config and will respond with Unknown command. This breaks scholar init and prevents
config initialization via the gateway.
Agent Prompt
## Issue description
`scholar init` is broken because it sends `init_config` but the gateway does not implement this command anymore.

## Issue Context
The CLI uses the gateway websocket to initialize configuration.

## Fix
Choose one:
- **Option A (restore behavior):** Re-add an `init_config` handler in `GatewayServer.handleRequest` that writes `.config/scholar.json` (or delegates to the setup flow) and returns success.
- **Option B (remove dependency):** Update/remove the CLI `init` command so it writes `.config/scholar.json` locally (similar to `runInteractiveSetup`) rather than requiring the daemon.

## Fix Focus Areas
- src/cli/index.ts[15-35]
- src/daemon/gateway/server.ts[71-78]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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 expands ScholarSync from a basic Telegram bot into a multi-component system with interactive onboarding/config, a local dashboard + WebSocket gateway, a richer Telegram workflow (onboarding → solve → format → submit), and new “formatters”/LLM integrations.

Changes:

  • Add interactive CLI setup that persists configuration to .config/scholar.json and update startup logic to bootstrap from both .env and JSON config.
  • Introduce a Gateway daemon that serves public/index.html and broadcasts application logs to a WebSocket dashboard.
  • Implement Telegram bot onboarding + document parsing + LLM solution generation + output formatting (PDF/DOCX/XLSX/image) + submission flow.

Reviewed changes

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

Show a summary per file
File Description
src/index.ts Loads config from .env + .config/scholar.json, runs interactive setup when missing config, starts gateway + bots.
src/daemon/gateway/server.ts Adds HTTP server for dashboard + attaches WebSocket server + log broadcasting.
src/core/store.ts Adds a JSON file-backed user/session store under .config/store.json.
src/core/schema.ts Extends LLM provider union to include openrouter.
src/core/parser.ts Adds PDF buffer parsing via pdf-parse.
src/core/logger.ts Adds a logger that also broadcasts to dashboard via a registered callback.
src/core/llm.ts Adds LLM request logic for Gemini/OpenAI/OpenRouter (and a mock fallback).
src/core/formatters.ts Adds PDF/DOCX generation via Docker+pandoc, XLSX generation via xlsx, and code screenshot generation via freeze.
src/core/classroom.ts Adds placeholders for Google Classroom and Puppeteer-based uploads.
src/cli/setup.ts Implements interactive onboarding to collect/store messaging + LLM credentials.
src/bot/index.ts Major Telegram bot expansion: onboarding, PDF solving, formatting, and submission steps.
public/index.html Adds a dashboard UI that connects to the gateway via WebSocket and renders logs.
README.md Expands project documentation and feature list.
package.json Adds start/daemon scripts and new dependencies (@clack/prompts, picocolors, xlsx).
package-lock.json Locks newly added dependencies.
.gitignore Updates ignored files/dirs (notably .config and .env).
.env Adds an environment file (currently contains a real bot token).
.config/store.json Adds a committed runtime store snapshot (contains PII/session data).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .env
@@ -0,0 +1 @@
TELEGRAM_BOT_TOKEN=8606625998:AAGuNWcFKDyXBSBITEie_NCSqZ2j2GZ6dC4

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

A real Telegram bot token is committed in this tracked .env file. This is a secret leak and should be removed from git history (rotate/revoke the token, delete the file from the repo, and replace with a non-secret .env.example/setup instructions).

Suggested change
TELEGRAM_BOT_TOKEN=8606625998:AAGuNWcFKDyXBSBITEie_NCSqZ2j2GZ6dC4
TELEGRAM_BOT_TOKEN=YOUR_TELEGRAM_BOT_TOKEN_HERE

Copilot uses AI. Check for mistakes.
Comment thread src/bot/index.ts
Comment on lines +210 to +211
} catch (err) {
console.error(err);

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

This catch block logs with console.error, which bypasses the new global logger/dashboard broadcaster. Using logger.error here would keep error reporting consistent and visible in the dashboard.

Suggested change
} catch (err) {
console.error(err);
} catch (err: any) {
logger.error("Document processing failed", { error: err?.message ?? String(err) });

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +41
this.server.listen(port, () => {
console.log(`Gateway & Dashboard running on http://localhost:${port}`);
});

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

The HTTP server is started without an explicit host, which binds to all interfaces by default. Since this dashboard streams logs (including user-provided text) over WebSockets, it’s safer to bind to 127.0.0.1 by default (or make the bind address configurable via env) to avoid exposing it on the network unintentionally.

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts

// Run Bot and Daemon
console.log("Starting Gateway Daemon...");
const gateway = new GatewayServer(8080);

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

gateway is assigned but never used. If the side-effect is just to start listening, instantiate without assigning (or store it somewhere and use it for shutdown handling).

Suggested change
const gateway = new GatewayServer(8080);
new GatewayServer(8080);

Copilot uses AI. Check for mistakes.
Comment thread src/cli/setup.ts
}

p.note(
`No auth configured for provider "anthropic". The agent may fail until credentials are added.`,

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

This warning references provider "anthropic", but the interactive provider list doesn’t include Anthropics/Claude. It reads like a copy/paste artifact and will confuse users; either add the provider option or remove/update the note to reflect supported providers.

Suggested change
`No auth configured for provider "anthropic". The agent may fail until credentials are added.`,
`No auth configured for your selected LLM provider yet. The agent may fail until API credentials are added.`,

Copilot uses AI. Check for mistakes.
Comment thread src/core/formatters.ts
Comment on lines +5 to +10
import * as xlsx from 'xlsx';
import puppeteer from 'puppeteer';
import { logger } from './logger.js';

const execPromise = util.promisify(exec);
const TEMP_DIR = path.resolve(process.cwd(), '.temp_docs');

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

This code creates .temp_docs under the project root for generated files. Add .temp_docs/ to .gitignore to avoid accidentally committing generated documents.

Suggested change
import * as xlsx from 'xlsx';
import puppeteer from 'puppeteer';
import { logger } from './logger.js';
const execPromise = util.promisify(exec);
const TEMP_DIR = path.resolve(process.cwd(), '.temp_docs');
import os from 'os';
import * as xlsx from 'xlsx';
import puppeteer from 'puppeteer';
import { logger } from './logger.js';
const execPromise = util.promisify(exec);
const TEMP_DIR = path.join(os.tmpdir(), 'temp_docs');

Copilot uses AI. Check for mistakes.
Comment thread src/core/llm.ts
Comment on lines +16 to +20
if (provider === 'gemini') {
const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

These outbound LLM requests don’t include timeout/abort handling. If the provider stalls, the bot can hang awaiting fetch indefinitely. Consider using AbortController with a reasonable timeout and handling timeouts with a user-friendly error.

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts
if (fs.existsSync(configPath)) {
const data = JSON.parse(fs.readFileSync(configPath, 'utf8'));
for (const key of Object.keys(data)) {
process.env[key] = data[key];

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

Values from JSON are assigned directly to process.env here. Since process.env is string-valued, non-string JSON values (objects/arrays/booleans) will be coerced in surprising ways (e.g. [object Object]). Validate types and coerce only supported primitives before assignment.

Suggested change
process.env[key] = data[key];
const value = (data as Record<string, unknown>)[key];
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
process.env[key] = String(value);
} else {
// Skip non-primitive values to avoid unexpected coercion (e.g., "[object Object]")
console.warn(`Skipping non-primitive config value for key "${key}" in .config/scholar.json`);
}

Copilot uses AI. Check for mistakes.
Comment thread src/cli/setup.ts
existingConfig[key] = value;
}

fs.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2));

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

This writes API keys into .config/scholar.json without setting restrictive file permissions. Consider writing with mode 0o600 (best-effort) to reduce accidental exposure on multi-user systems.

Suggested change
fs.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2));
fs.writeFileSync(configPath, JSON.stringify(existingConfig, null, 2), { mode: 0o600 });
try {
fs.chmodSync(configPath, 0o600);
} catch {
// Best-effort: ignore errors adjusting file permissions
}

Copilot uses AI. Check for mistakes.
Comment thread src/core/formatters.ts
import fs from 'fs';
import path from 'path';
import * as xlsx from 'xlsx';
import puppeteer from 'puppeteer';

Copilot AI Apr 1, 2026

Copy link

Choose a reason for hiding this comment

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

puppeteer is imported here but not used anywhere in this module. Remove the unused import to avoid unnecessary dependency loading and to keep the module focused on the tools it actually uses.

Suggested change
import puppeteer from 'puppeteer';

Copilot uses AI. Check for mistakes.
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.

2 participants