samarthya-bot 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +92 -0
  2. package/backend/.env.example +23 -0
  3. package/backend/bin/samarthya.js +384 -0
  4. package/backend/config/constants.js +71 -0
  5. package/backend/config/db.js +13 -0
  6. package/backend/controllers/auditController.js +86 -0
  7. package/backend/controllers/authController.js +154 -0
  8. package/backend/controllers/chatController.js +158 -0
  9. package/backend/controllers/fileController.js +268 -0
  10. package/backend/controllers/platformController.js +54 -0
  11. package/backend/controllers/screenController.js +91 -0
  12. package/backend/controllers/telegramController.js +120 -0
  13. package/backend/controllers/toolsController.js +56 -0
  14. package/backend/controllers/whatsappController.js +214 -0
  15. package/backend/fix_toolRegistry.js +25 -0
  16. package/backend/middleware/auth.js +28 -0
  17. package/backend/models/AuditLog.js +28 -0
  18. package/backend/models/BackgroundJob.js +13 -0
  19. package/backend/models/Conversation.js +40 -0
  20. package/backend/models/Memory.js +17 -0
  21. package/backend/models/User.js +24 -0
  22. package/backend/package-lock.json +3766 -0
  23. package/backend/package.json +41 -0
  24. package/backend/public/assets/index-Ckf0GO1B.css +1 -0
  25. package/backend/public/assets/index-Do4jNsZS.js +19 -0
  26. package/backend/public/assets/index-Ui-pyZvK.js +25 -0
  27. package/backend/public/favicon.svg +17 -0
  28. package/backend/public/index.html +18 -0
  29. package/backend/public/manifest.json +16 -0
  30. package/backend/routes/audit.js +9 -0
  31. package/backend/routes/auth.js +11 -0
  32. package/backend/routes/chat.js +11 -0
  33. package/backend/routes/files.js +14 -0
  34. package/backend/routes/platform.js +18 -0
  35. package/backend/routes/screen.js +10 -0
  36. package/backend/routes/telegram.js +8 -0
  37. package/backend/routes/tools.js +9 -0
  38. package/backend/routes/whatsapp.js +11 -0
  39. package/backend/server.js +134 -0
  40. package/backend/services/background/backgroundService.js +81 -0
  41. package/backend/services/llm/llmService.js +444 -0
  42. package/backend/services/memory/memoryService.js +159 -0
  43. package/backend/services/planner/plannerService.js +182 -0
  44. package/backend/services/security/securityService.js +166 -0
  45. package/backend/services/telegram/telegramService.js +49 -0
  46. package/backend/services/tools/toolRegistry.js +879 -0
  47. package/backend/services/whatsapp/whatsappService.js +254 -0
  48. package/backend/test_email.js +29 -0
  49. package/backend/test_parser.js +10 -0
  50. package/package.json +49 -0
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
+ <defs>
3
+ <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#FF9933"/>
5
+ <stop offset="50%" style="stop-color:#FFFFFF"/>
6
+ <stop offset="100%" style="stop-color:#138808"/>
7
+ </linearGradient>
8
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" style="stop-color:#0D0D0D"/>
10
+ <stop offset="100%" style="stop-color:#1a1a2e"/>
11
+ </linearGradient>
12
+ </defs>
13
+ <rect width="64" height="64" rx="14" fill="url(#bg)"/>
14
+ <text x="32" y="44" text-anchor="middle" font-size="30" font-family="sans-serif" font-weight="bold" fill="url(#grad)">स</text>
15
+ <circle cx="48" cy="14" r="4" fill="#FF9933" opacity="0.8"/>
16
+ <circle cx="14" cy="50" r="3" fill="#138808" opacity="0.6"/>
17
+ </svg>
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="SamarthyaBot - Privacy-first Personal AI Operator built for Indian workflows. Hindi, Hinglish & English support." />
8
+ <meta name="theme-color" content="#0f0f23" />
9
+ <link rel="manifest" href="/manifest.json" />
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Noto+Sans+Devanagari:wght@400;500;600;700&display=swap" rel="stylesheet">
11
+ <title>SamarthyaBot - समर्थ्य बोट | Personal AI Operator</title>
12
+ <script type="module" crossorigin src="/assets/index-Ui-pyZvK.js"></script>
13
+ <link rel="stylesheet" crossorigin href="/assets/index-Ckf0GO1B.css">
14
+ </head>
15
+ <body>
16
+ <div id="root"></div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "SamarthyaBot",
3
+ "short_name": "SamarthyaBot",
4
+ "description": "Privacy-first Personal AI Operator for Indian workflows",
5
+ "start_url": "/",
6
+ "display": "standalone",
7
+ "background_color": "#0f0f23",
8
+ "theme_color": "#6366f1",
9
+ "icons": [
10
+ {
11
+ "src": "/favicon.svg",
12
+ "sizes": "any",
13
+ "type": "image/svg+xml"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,9 @@
1
+ const router = require('express').Router();
2
+ const { getAuditLogs, getAuditStats, rollbackAction } = require('../controllers/auditController');
3
+ const auth = require('../middleware/auth');
4
+
5
+ router.get('/logs', auth, getAuditLogs);
6
+ router.get('/stats', auth, getAuditStats);
7
+ router.post('/rollback/:id', auth, rollbackAction);
8
+
9
+ module.exports = router;
@@ -0,0 +1,11 @@
1
+ const router = require('express').Router();
2
+ const { register, login, getProfile, updateProfile, demoLogin } = require('../controllers/authController');
3
+ const auth = require('../middleware/auth');
4
+
5
+ router.post('/register', register);
6
+ router.post('/login', login);
7
+ router.post('/demo', demoLogin);
8
+ router.get('/profile', auth, getProfile);
9
+ router.put('/profile', auth, updateProfile);
10
+
11
+ module.exports = router;
@@ -0,0 +1,11 @@
1
+ const router = require('express').Router();
2
+ const { sendMessage, getConversations, getConversation, deleteConversation, togglePin } = require('../controllers/chatController');
3
+ const auth = require('../middleware/auth');
4
+
5
+ router.post('/message', auth, sendMessage);
6
+ router.get('/conversations', auth, getConversations);
7
+ router.get('/conversations/:id', auth, getConversation);
8
+ router.delete('/conversations/:id', auth, deleteConversation);
9
+ router.patch('/conversations/:id/pin', auth, togglePin);
10
+
11
+ module.exports = router;
@@ -0,0 +1,14 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const auth = require('../middleware/auth');
4
+ const fileController = require('../controllers/fileController');
5
+
6
+ router.get('/list', auth, fileController.listFiles);
7
+ router.get('/read', auth, fileController.readFile);
8
+ router.get('/download', auth, fileController.downloadFile);
9
+ router.get('/stats', auth, fileController.getStats);
10
+ router.post('/mkdir', auth, fileController.createFolder);
11
+ router.post('/upload', auth, fileController.uploadFile);
12
+ router.delete('/delete', auth, fileController.deleteFile);
13
+
14
+ module.exports = router;
@@ -0,0 +1,18 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const auth = require('../middleware/auth');
4
+ const platformController = require('../controllers/platformController');
5
+
6
+ // All platform routes require authentication
7
+ router.use(auth);
8
+
9
+ // Get platform real-time status
10
+ router.get('/status', platformController.getPlatformStatus);
11
+
12
+ // Get background jobs
13
+ router.get('/jobs', platformController.getBackgroundJobs);
14
+
15
+ // Emergency Kill Switch
16
+ router.post('/emergency-stop', platformController.emergencyStop);
17
+
18
+ module.exports = router;
@@ -0,0 +1,10 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const auth = require('../middleware/auth');
4
+ const screenController = require('../controllers/screenController');
5
+
6
+ // Screen Understanding routes
7
+ router.post('/analyze', auth, screenController.analyzeScreen);
8
+ router.get('/supported', auth, screenController.getSupportedScreens);
9
+
10
+ module.exports = router;
@@ -0,0 +1,8 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const telegramController = require('../controllers/telegramController');
4
+
5
+ // Telegram Incoming Webhook (POST request)
6
+ router.post('/webhook', telegramController.handleMessage);
7
+
8
+ module.exports = router;
@@ -0,0 +1,9 @@
1
+ const router = require('express').Router();
2
+ const { getTools, getToolPacks, getPackTools } = require('../controllers/toolsController');
3
+ const auth = require('../middleware/auth');
4
+
5
+ router.get('/', auth, getTools);
6
+ router.get('/packs', auth, getToolPacks);
7
+ router.get('/packs/:packId', auth, getPackTools);
8
+
9
+ module.exports = router;
@@ -0,0 +1,11 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const whatsappController = require('../controllers/whatsappController');
4
+
5
+ // WhatsApp Webhook Verification (Meta sends GET request)
6
+ router.get('/webhook', whatsappController.verifyWebhook);
7
+
8
+ // WhatsApp Incoming Messages (Meta sends POST request)
9
+ router.post('/webhook', whatsappController.handleMessage);
10
+
11
+ module.exports = router;
@@ -0,0 +1,134 @@
1
+ require('dotenv').config();
2
+ const express = require('express');
3
+ const cors = require('cors');
4
+ const helmet = require('helmet');
5
+ const morgan = require('morgan');
6
+ const http = require('http');
7
+ const { Server } = require('socket.io');
8
+ const connectDB = require('./config/db');
9
+
10
+ // Import Routes
11
+ const authRoutes = require('./routes/auth');
12
+ const chatRoutes = require('./routes/chat');
13
+ const auditRoutes = require('./routes/audit');
14
+ const toolsRoutes = require('./routes/tools');
15
+ const whatsappRoutes = require('./routes/whatsapp');
16
+ const telegramRoutes = require('./routes/telegram');
17
+ const screenRoutes = require('./routes/screen');
18
+ const fileRoutes = require('./routes/files');
19
+ const platformRoutes = require('./routes/platform');
20
+ const backgroundService = require('./services/background/backgroundService');
21
+
22
+ const app = express();
23
+ const server = http.createServer(app);
24
+
25
+ // Socket.IO setup
26
+ const io = new Server(server, {
27
+ cors: {
28
+ origin: process.env.CORS_ORIGIN || 'http://localhost:5173',
29
+ methods: ['GET', 'POST']
30
+ }
31
+ });
32
+
33
+ // Middleware
34
+ app.use(helmet());
35
+ app.use(cors({ origin: process.env.CORS_ORIGIN || 'http://localhost:5173' }));
36
+ app.use(express.json({ limit: '15mb' }));
37
+ app.use(morgan('dev'));
38
+
39
+ // Inject io into requests
40
+ app.use((req, res, next) => {
41
+ req.io = io;
42
+ next();
43
+ });
44
+
45
+ const path = require('path');
46
+
47
+ // Routes
48
+ app.use('/api/auth', authRoutes);
49
+ app.use('/api/chat', chatRoutes);
50
+ app.use('/api/audit', auditRoutes);
51
+ app.use('/api/tools', toolsRoutes);
52
+ app.use('/api/whatsapp', whatsappRoutes);
53
+ app.use('/api/telegram', telegramRoutes);
54
+ app.use('/api/screen', screenRoutes);
55
+ app.use('/api/files', fileRoutes);
56
+ app.use('/api/platform', platformRoutes);
57
+
58
+ // Serve static frontend UI (SamarthyaBot Dashboard)
59
+ app.use(express.static(path.join(__dirname, 'public')));
60
+
61
+ // Health check
62
+ app.get('/api/health', (req, res) => {
63
+ res.json({
64
+ status: 'ok',
65
+ name: 'SamarthyaBot Server',
66
+ version: '1.0.0',
67
+ uptime: process.uptime(),
68
+ timestamp: new Date().toISOString()
69
+ });
70
+ });
71
+
72
+ // Socket.IO connection
73
+ io.on('connection', (socket) => {
74
+ console.log('🔌 Client connected:', socket.id);
75
+
76
+ socket.on('join', (userId) => {
77
+ socket.join(userId);
78
+ console.log(`👤 User ${userId} joined room`);
79
+ });
80
+
81
+ socket.on('typing', (data) => {
82
+ socket.to(data.userId).emit('typing', data);
83
+ });
84
+
85
+ socket.on('disconnect', () => {
86
+ console.log('❌ Client disconnected:', socket.id);
87
+ });
88
+ });
89
+
90
+ // SPA Catch-all Middleware for Express 5
91
+ app.use((req, res, next) => {
92
+ if (req.path.startsWith('/api/')) return next();
93
+ res.sendFile(path.join(__dirname, 'public', 'index.html'));
94
+ });
95
+
96
+ // Connect DB & Start Server
97
+ const PORT = process.env.PORT || 5000;
98
+
99
+ connectDB().then(() => {
100
+ server.listen(PORT, () => {
101
+ const activeProvider = process.env.ACTIVE_PROVIDER ? process.env.ACTIVE_PROVIDER.toUpperCase() : 'GEMINI';
102
+ const activeModel = process.env.ACTIVE_MODEL || 'gemini-2.5-flash';
103
+ const aiString = `🧠 Active AI: ${activeProvider} (${activeModel})`.padEnd(49, ' ');
104
+
105
+ console.log(`
106
+ ╔══════════════════════════════════════════════════════╗
107
+ ║ ║
108
+ ║ 🧠 SamarthyaBot Server v1.1.0 ║
109
+ ║ Privacy-first Personal AI Operator ║
110
+ ║ ║
111
+ ║ 🌐 Server: http://localhost:${PORT} ║
112
+ ║ 📡 Socket: ws://localhost:${PORT} ║
113
+ ║ 🔗 Health: http://localhost:${PORT}/api/health ║
114
+ ║ 📱 WhatsApp: /api/whatsapp/webhook ║
115
+ ║ 🤖 Telegram: /api/telegram/webhook ║
116
+ ║ 👁️ Vision: /api/screen/analyze ║
117
+ ║ ║
118
+ ║ 🇮🇳 Built for Indian Workflows ║
119
+ ║ 📦 Ollama: ${process.env.USE_OLLAMA === 'true' ? '✅ Enabled'.padEnd(35) : '❌ Disabled'.padEnd(35)}║
120
+ ║ 🔄 Autonomous Background Engine: ✅ Active ║
121
+ ║ 🔌 Dynamic Plugin Engine: ✅ Active ║
122
+ ║ ${aiString} ║
123
+ ║ ║
124
+ ╚══════════════════════════════════════════════════════╝
125
+ `);
126
+ backgroundService.start();
127
+ });
128
+ }).catch(err => {
129
+ console.error('Failed to connect to database:', err);
130
+ // Start server even without DB for demo
131
+ server.listen(PORT, () => {
132
+ console.log(`⚠️ Server running without DB on port ${PORT}`);
133
+ });
134
+ });
@@ -0,0 +1,81 @@
1
+ const BackgroundJob = require('../../models/BackgroundJob');
2
+ const User = require('../../models/User');
3
+ const plannerService = require('../planner/plannerService');
4
+ const telegramService = require('../telegram/telegramService');
5
+ const Conversation = require('../../models/Conversation');
6
+
7
+ class BackgroundService {
8
+ constructor() {
9
+ this.isRunning = false;
10
+ }
11
+
12
+ start() {
13
+ if (this.isRunning) return;
14
+ this.isRunning = true;
15
+ console.log('🔄 Background Autonomous Mode Started (Checking every 1 minute)');
16
+
17
+ // Check every minute
18
+ setInterval(() => this.checkJobs(), 60 * 1000);
19
+ // Do an initial check
20
+ this.checkJobs();
21
+ }
22
+
23
+ async checkJobs() {
24
+ try {
25
+ const now = new Date();
26
+ // Find jobs where nextRunAt <= now and is active
27
+ const jobs = await BackgroundJob.find({
28
+ isActive: true,
29
+ nextRunAt: { $lte: now }
30
+ }).populate('userId');
31
+
32
+ for (const job of jobs) {
33
+ if (!job.userId) continue;
34
+ console.log(`⏱️ Executing Background Job: ${job.taskName} for ${job.userId.email}`);
35
+
36
+ // 1. Prepare conversation (create a temporary memory block for context)
37
+ const previousMessages = [{
38
+ role: 'system',
39
+ content: `[CRITICAL INSTRUCTION] You are running in AUTONOMOUS BACKGROUND MODE.
40
+ You must execute the following scheduled background job: "${job.taskName}".
41
+ Context/Prompt: ${job.prompt}
42
+ You must perform the necessary actions using tools. If you find something noteworthy, or if the user asked to be alerted, output a final message. The final message will be sent to the user on Telegram.`
43
+ }];
44
+
45
+ // 2. Execute via planner
46
+ const result = await plannerService.processMessage(
47
+ job.userId,
48
+ previousMessages,
49
+ `[BACKGROUND TRIGGER]: Run job "${job.taskName}" now.`,
50
+ null // no onProgress for background
51
+ );
52
+
53
+ // 3. Send result to Telegram if there's a meaningful response
54
+ // Since this runs silent, only send if there's content and the agent didn't just say "done"
55
+ if (result.response && result.response.length > 5) {
56
+ const chatIdMatch = job.userId.email.match(/^tg_(\d+)@samarthya\.local$/);
57
+ if (chatIdMatch) {
58
+ const chatId = chatIdMatch[1];
59
+ await telegramService.sendMessage(
60
+ chatId,
61
+ `🤖 *Background Task Completed: ${job.taskName}*\n\n${result.response}`
62
+ );
63
+ }
64
+ }
65
+
66
+ // 4. Update job schedule
67
+ job.lastRunAt = now;
68
+ if (job.intervalMinutes > 0) {
69
+ job.nextRunAt = new Date(now.getTime() + job.intervalMinutes * 60000);
70
+ } else {
71
+ job.isActive = false; // Run once
72
+ }
73
+ await job.save();
74
+ }
75
+ } catch (error) {
76
+ console.error('Background job error:', error);
77
+ }
78
+ }
79
+ }
80
+
81
+ module.exports = new BackgroundService();