VinOS Agent commited on
Commit
c3cd91c
Β·
1 Parent(s): 3a6714e

VinOS Build: Strategic Command Suite & Knowledge Bank Active

Browse files
Files changed (44) hide show
  1. Updates/vinos_update2.zip +0 -0
  2. Updates/vinos_update2/Dockerfile +26 -0
  3. Updates/vinos_update2/database/local_db.json +384 -0
  4. Updates/vinos_update2/database/playbooks.json +3 -0
  5. Updates/vinos_update2/package.json +17 -0
  6. Updates/vinos_update2/prompts/vin_core_prompt.md +21 -0
  7. Updates/vinos_update2/prompts/vin_personality.md +14 -0
  8. Updates/vinos_update2/server.js +343 -0
  9. Updates/vinos_update2/skills/api_caller.js +146 -0
  10. Updates/vinos_update2/skills/conversation_memory.js +56 -0
  11. Updates/vinos_update2/skills/infinite_money_cron.js +74 -0
  12. Updates/vinos_update2/skills/intent_router.js +55 -0
  13. Updates/vinos_update2/skills/memory.js +24 -0
  14. Updates/vinos_update2/skills/playbook_manager.js +81 -0
  15. Updates/vinos_update2/skills/quality_checker.js +24 -0
  16. Updates/vinos_update2/skills/version_control.js +49 -0
  17. Updates/vinos_update2/skills/voice_transcriber.js +79 -0
  18. Updates/vinos_update2/skills/web_researcher.js +50 -0
  19. Updates/vinos_update2/start.sh +24 -0
  20. Updates/vinos_update2/use_cases/daily_pulse.js +30 -0
  21. Updates/vinos_update2/use_cases/offer_architect.js +34 -0
  22. database/local_db.json +6 -0
  23. database/reports/VinOS_McKinsey_Report_1774112134907.pdf +0 -0
  24. package-lock.json +241 -1
  25. package.json +4 -1
  26. public/app.js +111 -155
  27. public/index.html +91 -76
  28. public/style.css +92 -0
  29. server.js +227 -7
  30. skills/api_caller.js +58 -11
  31. skills/github_storage.js +90 -0
  32. skills/hf_storage.js +88 -0
  33. skills/infinite_money_cron.js +74 -0
  34. skills/product_deployer.js +83 -0
  35. skills/quality_checker.js +24 -0
  36. skills/report_generator.js +64 -0
  37. skills/set_telegram_menu.js +30 -0
  38. skills/social_engager.js +43 -0
  39. skills/social_researcher.js +62 -0
  40. skills/trello_manager.js +77 -0
  41. skills/version_control.js +49 -0
  42. skills/web_researcher.js +50 -0
  43. tmp_mission.js +55 -0
  44. use_cases/daily_pulse.js +10 -4
Updates/vinos_update2.zip ADDED
Binary file (21.7 kB). View file
 
Updates/vinos_update2/Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the robust Node.js 20 image
2
+ FROM node:20
3
+
4
+ # Install dns tools for startup resolution
5
+ RUN apt-get update && apt-get install -y dnsutils && rm -rf /var/lib/apt/lists/*
6
+
7
+ # Create the standard Space app directory
8
+ WORKDIR /app
9
+
10
+ # Install dependencies
11
+ COPY package*.json ./
12
+ RUN npm install
13
+
14
+ # Copy all the parts
15
+ COPY . .
16
+
17
+ # Make startup script executable
18
+ RUN chmod +x /app/start.sh
19
+
20
+ # Hugging Face PORT binding
21
+ EXPOSE 7860
22
+ ENV PORT=7860
23
+ ENV NODE_OPTIONS="--dns-result-order=ipv4first"
24
+
25
+ # Use startup script that injects Telegram IP before launching
26
+ CMD ["/app/start.sh"]
Updates/vinos_update2/database/local_db.json ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "user_profile_snapshot": {
3
+ "nickname": "Kevin/Vin",
4
+ "primary_languages": [
5
+ "en",
6
+ "id"
7
+ ],
8
+ "main_niche": "AI Digital Strategy Consulting",
9
+ "key_assets": [
10
+ "Local network",
11
+ "Oracle Cloud VM"
12
+ ],
13
+ "automatic_mode": true
14
+ },
15
+ "active_sprints": [
16
+ {
17
+ "id": "sprint_001",
18
+ "title": "Token Gashapon Prototype",
19
+ "status": "Planning",
20
+ "expected_revenue": "$100/day"
21
+ }
22
+ ],
23
+ "metrics": {
24
+ "total_sales": 0,
25
+ "active_experiments": 0
26
+ },
27
+ "telegram_log": [
28
+ {
29
+ "direction": "OUT",
30
+ "chatId": 8743583463,
31
+ "text": "✨ <b>Gashapon Result!</b>\n<a href=\"https://nanobanana.aikit.club/images/191824-20032026_1icn_generate.png\">View Image</a>",
32
+ "ts": "2026-03-20T19:18:24.127Z"
33
+ },
34
+ {
35
+ "direction": "OUT",
36
+ "chatId": 8743583463,
37
+ "text": "✨ <b>Gashapon Result!</b>\n<a href=\"https://nanobanana.aikit.club/images/191824-20032026_phod_generate.png\">View Image</a>",
38
+ "ts": "2026-03-20T19:18:24.081Z"
39
+ },
40
+ {
41
+ "direction": "OUT",
42
+ "chatId": 8743583463,
43
+ "text": "✨ <b>Gashapon Result!</b>\n<a href=\"https://nanobanana.aikit.club/images/191821-20032026_zsxq_generate.png\">View Image</a>",
44
+ "ts": "2026-03-20T19:18:20.673Z"
45
+ },
46
+ {
47
+ "direction": "OUT",
48
+ "chatId": 8743583463,
49
+ "text": "πŸŒ€ <i>Spinning the Gashapon for:</i> Bisa tonton gashapon perempuan Korea yang indah?",
50
+ "ts": "2026-03-20T19:18:15.435Z"
51
+ },
52
+ {
53
+ "direction": "IN",
54
+ "chatId": 8743583463,
55
+ "text": "[Dee (Voice)]: Bisa tonton gashapon perempuan korea yang indah?",
56
+ "ts": "2026-03-20T19:18:15.257Z"
57
+ },
58
+ {
59
+ "direction": "OUT",
60
+ "chatId": 8743583463,
61
+ "text": "πŸŒ€ <i>Spinning the Gashapon for:</i> a korean basketball player with the jersey number 37 and says LOVE",
62
+ "ts": "2026-03-20T19:18:13.271Z"
63
+ },
64
+ {
65
+ "direction": "OUT",
66
+ "chatId": 8743583463,
67
+ "text": "πŸŒ€ <i>Spinning the Gashapon for:</i> a basketball player in the alley with a lot of jazz player gravity",
68
+ "ts": "2026-03-20T19:18:13.074Z"
69
+ },
70
+ {
71
+ "direction": "IN",
72
+ "chatId": 8743583463,
73
+ "text": "[Dee]: /gashapon a korean basketball player with the jersey number 37 and says LOVE",
74
+ "ts": "2026-03-20T19:18:13.050Z"
75
+ },
76
+ {
77
+ "direction": "IN",
78
+ "chatId": 8743583463,
79
+ "text": "[Dee]: /gashapon a basketball player in the alley with a lot of jazz player gravity",
80
+ "ts": "2026-03-20T19:18:12.804Z"
81
+ },
82
+ {
83
+ "direction": "OUT",
84
+ "chatId": 8743583463,
85
+ "text": "⚑ <i>Instruction received. Processing...</i>",
86
+ "ts": "2026-03-20T19:18:12.686Z"
87
+ },
88
+ {
89
+ "direction": "OUT",
90
+ "chatId": 8743583463,
91
+ "text": "🎀 <i>Received audio... Transcribing...</i>",
92
+ "ts": "2026-03-20T19:18:12.487Z"
93
+ },
94
+ {
95
+ "direction": "OUT",
96
+ "chatId": 8743583463,
97
+ "text": "<b>Automatic Mode:</b> 🟒 <b>ON</b> (Speed Mode)",
98
+ "ts": "2026-03-20T19:18:12.289Z"
99
+ },
100
+ {
101
+ "direction": "OUT",
102
+ "chatId": 8743583463,
103
+ "text": "⚑ <i>Instruction received. Processing...</i>",
104
+ "ts": "2026-03-20T19:18:12.090Z"
105
+ },
106
+ {
107
+ "direction": "OUT",
108
+ "chatId": 8743583463,
109
+ "text": "No pending command found to confirm or cancel.",
110
+ "ts": "2026-03-20T19:18:11.890Z"
111
+ },
112
+ {
113
+ "direction": "OUT",
114
+ "chatId": 8743583463,
115
+ "text": "No pending command found to confirm or cancel.",
116
+ "ts": "2026-03-20T19:15:35.879Z"
117
+ },
118
+ {
119
+ "direction": "OUT",
120
+ "chatId": 8743583463,
121
+ "text": "No pending command found to confirm or cancel.",
122
+ "ts": "2026-03-20T19:13:31.865Z"
123
+ },
124
+ {
125
+ "direction": "OUT",
126
+ "chatId": 8743583463,
127
+ "text": "No pending command found to confirm or cancel.",
128
+ "ts": "2026-03-20T19:11:59.877Z"
129
+ },
130
+ {
131
+ "direction": "OUT",
132
+ "chatId": 8743583463,
133
+ "text": "No pending command found to confirm or cancel.",
134
+ "ts": "2026-03-20T19:11:20.466Z"
135
+ },
136
+ {
137
+ "direction": "OUT",
138
+ "chatId": 8743583463,
139
+ "text": "No pending command found to confirm or cancel.",
140
+ "ts": "2026-03-20T19:10:12.482Z"
141
+ },
142
+ {
143
+ "direction": "OUT",
144
+ "chatId": 8743583463,
145
+ "text": "No pending command found to confirm or cancel.",
146
+ "ts": "2026-03-20T19:09:08.498Z"
147
+ },
148
+ {
149
+ "direction": "OUT",
150
+ "chatId": 8743583463,
151
+ "text": "No pending command found to confirm or cancel.",
152
+ "ts": "2026-03-20T19:08:06.512Z"
153
+ },
154
+ {
155
+ "direction": "OUT",
156
+ "chatId": 8743583463,
157
+ "text": "✨ <b>Gashapon Result!</b>\n<a href=\"https://nanobanana.aikit.club/images/190722-20032026_35c6_generate.png\">View Image</a>",
158
+ "ts": "2026-03-20T19:07:22.506Z"
159
+ },
160
+ {
161
+ "direction": "OUT",
162
+ "chatId": 8743583463,
163
+ "text": "πŸŒ€ <i>Spinning the Gashapon for:</i> Eee Astronaut Di atas langit Dengan anjing yang indah Background Nebula",
164
+ "ts": "2026-03-20T19:07:07.439Z"
165
+ },
166
+ {
167
+ "direction": "OUT",
168
+ "chatId": 8743583463,
169
+ "text": "βœ… <b>Confirmed.</b> Running now...",
170
+ "ts": "2026-03-20T19:07:06.474Z"
171
+ },
172
+ {
173
+ "direction": "OUT",
174
+ "chatId": 8743583463,
175
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>Eee Astronaut Di atas langit Dengan anjing yang indah Background Nebula</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
176
+ "ts": "2026-03-20T19:06:28.026Z"
177
+ },
178
+ {
179
+ "direction": "IN",
180
+ "chatId": 8743583463,
181
+ "text": "[Dee (Voice)]: Gashapon Eee Astronaut Di atas langit Dengan anjing yang indah Background Nebula",
182
+ "ts": "2026-03-20T19:06:27.857Z"
183
+ },
184
+ {
185
+ "direction": "OUT",
186
+ "chatId": 8743583463,
187
+ "text": "🎀 <i>Received audio... Transcribing...</i>",
188
+ "ts": "2026-03-20T19:06:24.482Z"
189
+ },
190
+ {
191
+ "direction": "OUT",
192
+ "chatId": 8743583463,
193
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>/gashapon</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
194
+ "ts": "2026-03-20T19:06:23.924Z"
195
+ },
196
+ {
197
+ "direction": "IN",
198
+ "chatId": 8743583463,
199
+ "text": "[Dee]: /gashapon",
200
+ "ts": "2026-03-20T19:06:23.762Z"
201
+ },
202
+ {
203
+ "direction": "OUT",
204
+ "chatId": 8743583463,
205
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>a spider on the rim of the drinking tumbler</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
206
+ "ts": "2026-03-20T19:06:23.210Z"
207
+ },
208
+ {
209
+ "direction": "IN",
210
+ "chatId": 8743583463,
211
+ "text": "[Dee]: /gashapon a spider on the rim of the drinking tumbler",
212
+ "ts": "2026-03-20T19:06:23.043Z"
213
+ },
214
+ {
215
+ "direction": "OUT",
216
+ "chatId": 8743583463,
217
+ "text": "I'm having trouble thinking clearly right now. Try again in a moment.",
218
+ "ts": "2026-03-20T19:06:22.485Z"
219
+ },
220
+ {
221
+ "direction": "IN",
222
+ "chatId": 8743583463,
223
+ "text": "[Dee]: what are your core skills",
224
+ "ts": "2026-03-20T19:06:21.929Z"
225
+ },
226
+ {
227
+ "direction": "OUT",
228
+ "chatId": 8743583463,
229
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>beaver wearing Sherlock Holmes attire</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
230
+ "ts": "2026-03-20T19:06:21.379Z"
231
+ },
232
+ {
233
+ "direction": "IN",
234
+ "chatId": 8743583463,
235
+ "text": "[Dee]: /gashapon beaver wearing sherlock holmes attire",
236
+ "ts": "2026-03-20T19:06:21.214Z"
237
+ },
238
+ {
239
+ "direction": "OUT",
240
+ "chatId": 8743583463,
241
+ "text": "<b>VinOS Core Online</b>",
242
+ "ts": "2026-03-20T19:06:20.661Z"
243
+ },
244
+ {
245
+ "direction": "IN",
246
+ "chatId": 8743583463,
247
+ "text": "[Dee]: /start discuss and brainstorm",
248
+ "ts": "2026-03-20T19:06:20.659Z"
249
+ },
250
+ {
251
+ "direction": "OUT",
252
+ "chatId": 8743583463,
253
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>a little kid dancing with otter 🦫</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
254
+ "ts": "2026-03-20T19:06:20.109Z"
255
+ },
256
+ {
257
+ "direction": "IN",
258
+ "chatId": 8743583463,
259
+ "text": "[Dee]: token gashapon a little kid dancing with 🦫",
260
+ "ts": "2026-03-20T19:06:19.870Z"
261
+ },
262
+ {
263
+ "direction": "OUT",
264
+ "chatId": 8743583463,
265
+ "text": "<b>VinOS Core Online</b>",
266
+ "ts": "2026-03-20T19:06:19.301Z"
267
+ },
268
+ {
269
+ "direction": "IN",
270
+ "chatId": 8743583463,
271
+ "text": "[Dee]: /start",
272
+ "ts": "2026-03-20T19:06:19.298Z"
273
+ },
274
+ {
275
+ "direction": "OUT",
276
+ "chatId": 8743583463,
277
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>a glowing golden dragon</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
278
+ "ts": "2026-03-20T19:06:18.739Z"
279
+ },
280
+ {
281
+ "direction": "IN",
282
+ "chatId": 8743583463,
283
+ "text": "[Dee]: /gashapon a glowing golden dragon",
284
+ "ts": "2026-03-20T19:06:18.572Z"
285
+ },
286
+ {
287
+ "direction": "OUT",
288
+ "chatId": 8743583463,
289
+ "text": "<b>VinOS Core Online</b>",
290
+ "ts": "2026-03-20T19:06:18.011Z"
291
+ },
292
+ {
293
+ "direction": "IN",
294
+ "chatId": 8743583463,
295
+ "text": "[Dee]: /start",
296
+ "ts": "2026-03-20T19:06:18.010Z"
297
+ },
298
+ {
299
+ "direction": "OUT",
300
+ "chatId": 8743583463,
301
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>vinOs character</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
302
+ "ts": "2026-03-20T19:06:17.454Z"
303
+ },
304
+ {
305
+ "direction": "IN",
306
+ "chatId": 8743583463,
307
+ "text": "[Dee]: /gashapon vinOs show me your character",
308
+ "ts": "2026-03-20T19:06:17.147Z"
309
+ },
310
+ {
311
+ "direction": "OUT",
312
+ "chatId": 8743583463,
313
+ "text": "πŸ€– <b>I understood your command:</b>\nIntent: <i>gashapon</i>\nParams: <i>token gashapon</i>\n\nShould I execute this? Reply with <b>Confirm</b> or <b>Cancel</b>.",
314
+ "ts": "2026-03-20T19:06:16.232Z"
315
+ },
316
+ {
317
+ "direction": "IN",
318
+ "chatId": 8743583463,
319
+ "text": "[Dee]: token gashapon run it",
320
+ "ts": "2026-03-20T19:06:15.970Z"
321
+ },
322
+ {
323
+ "direction": "OUT",
324
+ "chatId": 8743583463,
325
+ "text": "I'm having trouble thinking clearly right now. Try again in a moment.",
326
+ "ts": "2026-03-20T19:06:15.559Z"
327
+ },
328
+ {
329
+ "direction": "IN",
330
+ "chatId": 8743583463,
331
+ "text": "[Dee]: token gashapon run it",
332
+ "ts": "2026-03-20T19:06:15.450Z"
333
+ },
334
+ {
335
+ "direction": "OUT",
336
+ "chatId": 8743583463,
337
+ "text": "I'm having trouble thinking clearly right now. Try again in a moment.",
338
+ "ts": "2026-03-20T19:06:14.898Z"
339
+ },
340
+ {
341
+ "direction": "IN",
342
+ "chatId": 8743583463,
343
+ "text": "[Dee]: hiVin",
344
+ "ts": "2026-03-20T19:06:14.375Z"
345
+ },
346
+ {
347
+ "direction": "OUT",
348
+ "chatId": 8743583463,
349
+ "text": "<b>VinOS Core Online</b>",
350
+ "ts": "2026-03-20T19:06:13.413Z"
351
+ },
352
+ {
353
+ "direction": "IN",
354
+ "chatId": 8743583463,
355
+ "text": "[Dee]: /start",
356
+ "ts": "2026-03-20T19:06:13.409Z"
357
+ },
358
+ {
359
+ "direction": "IN",
360
+ "chatId": 8743583463,
361
+ "text": "[Test]: Hello",
362
+ "ts": "2026-03-20T19:05:48.046Z"
363
+ },
364
+ {
365
+ "direction": "OUT",
366
+ "chatId": "8743583463",
367
+ "text": "<b>VinOS Strategy Lab Live!</b>\nHello Dee! This is your official notification that the VinOS Strategy Lab is now active and ready for arbitrage. πŸš€\n\n- Market Scanner: Online\n- Offer Architect: Active\n- Token Gashapon: Functional",
368
+ "ts": "2026-03-20T18:55:40.431Z"
369
+ },
370
+ {
371
+ "direction": "OUT",
372
+ "chatId": "8743583463",
373
+ "text": "<b>[VinOS Dashboard]</b> Hi Dee",
374
+ "ts": "2026-03-20T18:21:14.953Z"
375
+ },
376
+ {
377
+ "direction": "OUT",
378
+ "chatId": "8743583463",
379
+ "text": "<b>VinOS Bridge Active!</b>\n\nNgrok tunnel is live. You can now send me commands:\n\n/start - Hello\n/gashapon [idea] - Generate AI image\n/pulse - Market scan\n/offer [niche] - Craft offer\n\nAll messages appear in the dashboard monitor in real-time.",
380
+ "ts": "2026-03-20T18:19:45.757Z"
381
+ }
382
+ ],
383
+ "pending_commands": {}
384
+ }
Updates/vinos_update2/database/playbooks.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "playbooks": []
3
+ }
Updates/vinos_update2/package.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "vinos-full-stack",
3
+ "version": "1.0.0",
4
+ "main": "server.js",
5
+ "scripts": {
6
+ "start": "node server.js",
7
+ "dev": "node --watch server.js"
8
+ },
9
+ "dependencies": {
10
+ "axios": "^1.6.2",
11
+ "cors": "^2.8.5",
12
+ "dotenv": "^16.3.1",
13
+ "express": "^4.18.2",
14
+ "form-data": "^4.0.5",
15
+ "node-cron": "^3.0.3"
16
+ }
17
+ }
Updates/vinos_update2/prompts/vin_core_prompt.md ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # The Complete VinOS Persona Prompt
2
+ (Copy this into Claude when ideating or load it into memory)
3
+
4
+ You are **Vin**, a friendly but sharp income-systems architect and think partner for the user.
5
+
6
+ ## Operating Modes:
7
+ 3.1 Clarify & Profile
8
+ 3.2 Money Scanner
9
+ 3.3 Offer Architect
10
+ 3.4 Launch Sprint Planner (12–48h)
11
+ 3.5 Self-Reviewer & Risk Checker
12
+ 3.6 Problem Solver & Skill Maker
13
+ 3.7 Funnel Architect (Traffic -> Leads -> Sales)
14
+ 3.8 A/B Experimenter
15
+ 3.9 Research & Social Listening
16
+ 3.10 Conversation Test Designer
17
+ 3.11 Expert Synthesis & Framework Builder
18
+ 3.12 Marketing Psychology & Persona Adapter
19
+ 3.13 API Payload & Automation Architect
20
+ 3.14 Data Ingestion & Capital Allocator
21
+ 3.15 Audience Health & Trust Guardian
Updates/vinos_update2/prompts/vin_personality.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Role & Identity
2
+ You are Vin, an Income-Systems Architect and think-partner. You help the user orchestrate strategies, build digital products, launch offers, and scan for market arbitrage opportunities.
3
+
4
+ # Personality: Curious but Cautious
5
+ 1. **Curious**: Always ask "what if?" and look for alternative angles.
6
+ 2. **Cautious**: Test MVPs first. Use free or cheap implementations before committing to paid escalations. If an output seems weak, admit it and suggest a better approach.
7
+ 3. **Self-Improving**: You have access to a Playbooks system to remember what works. If the user tells you to "remember this", you'll save it as a rule.
8
+ 4. **Action-Biased**: After research or analysis, always propose a concrete next step or an actionable plan.
9
+
10
+ # Operational Directives
11
+ - If a user asks a complex question, break it down logically into a step-by-step plan.
12
+ - Be upfront: show your chain of thought loosely, e.g., "I think X because Y. Should we proceed?"
13
+ - Keep responses sharp, conversational, and direct (use emojis sparingly but effectively).
14
+ - Refer to past conversation history directly if you are continuing a thought.
Updates/vinos_update2/server.js ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ require('dotenv').config();
2
+ const dns = require('node:dns');
3
+ dns.setDefaultResultOrder('ipv4first');
4
+
5
+ const express = require('express');
6
+ const cors = require('cors');
7
+ const path = require('path');
8
+ const fs = require('fs');
9
+ const memory = require('./skills/memory');
10
+ const apiCaller = require('./skills/api_caller');
11
+
12
+ const app = express();
13
+ app.use(cors());
14
+ app.use(express.json());
15
+ app.use(express.static(path.join(__dirname, 'public')));
16
+
17
+ // API Routes
18
+ app.get('/api/profile', (req, res) => {
19
+ const db = memory.readDB();
20
+ res.json(db.user_profile_snapshot);
21
+ });
22
+
23
+ app.get('/api/sprints', (req, res) => {
24
+ const db = memory.readDB();
25
+ res.json(db.active_sprints || []);
26
+ });
27
+
28
+ app.get('/api/status', (req, res) => {
29
+ const status = {
30
+ openrouter: !!process.env.OPENROUTER_API_KEY,
31
+ groq: !!process.env.GROQ_API_KEY,
32
+ telegram: !!process.env.TELEGRAM_BOT_TOKEN,
33
+ mayar: !!process.env.MAYAR_API_KEY,
34
+ whop: !!process.env.WHOP_API_KEY,
35
+ apify: !!process.env.APIFY_API_KEY
36
+ };
37
+ res.json(status);
38
+ });
39
+
40
+ const dailyPulse = require('./use_cases/daily_pulse');
41
+ const offerArchitect = require('./use_cases/offer_architect');
42
+
43
+ app.post('/api/generate-image', async (req, res) => {
44
+ const { prompt } = req.body;
45
+ if (!prompt) return res.status(400).json({ error: "Prompt is required" });
46
+
47
+ const result = await apiCaller.generateNanoBananaImage(prompt);
48
+ res.json(result);
49
+ });
50
+
51
+ app.post('/api/usecase/pulse', async (req, res) => {
52
+ const result = await dailyPulse();
53
+ res.json(result);
54
+ });
55
+
56
+ app.post('/api/usecase/offer', async (req, res) => {
57
+ const { topic } = req.body;
58
+ if (!topic) return res.status(400).json({ error: "Topic is required" });
59
+ const result = await offerArchitect(topic);
60
+ res.json(result);
61
+ });
62
+
63
+ // Daily Check-in Mechanism (Simplified)
64
+ const DAILY_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
65
+ const chatID = process.env.TELEGRAM_CHAT_ID;
66
+ const botToken = process.env.TELEGRAM_BOT_TOKEN;
67
+
68
+ if (chatID && botToken) {
69
+ console.log(`Telegram Bot Active for Chat ID: ${chatID}`);
70
+ // Optional: Send immediate boot notification to confirm connection
71
+ // apiCaller.sendTelegramMessage(chatID, "<b>VinOS Core Online</b>\nSystem is calibrated. Ready for Token Gashapon experiments.");
72
+
73
+ setInterval(async () => {
74
+ console.log("Triggering daily check-in...");
75
+ await apiCaller.sendTelegramMessage(chatID, "<b>VinOS Daily Check-in</b>\nHow is the Token Gashapon project coming along? Ready for the next arbitrage move?");
76
+ }, DAILY_INTERVAL);
77
+ }
78
+
79
+ // Webhook ingestion (for Mayar/Whop)
80
+ app.post('/api/webhook', (req, res) => {
81
+ const data = req.body;
82
+ console.log("General Webhook received:", data);
83
+ res.status(200).send({ status: 'success' });
84
+ });
85
+
86
+ const { logTelegramMessage } = require('./skills/api_caller');
87
+
88
+ // SSE clients list for real-time push
89
+ const sseClients = [];
90
+ app.get('/api/telegram-stream', (req, res) => {
91
+ res.setHeader('Content-Type', 'text/event-stream');
92
+ res.setHeader('Cache-Control', 'no-cache');
93
+ res.setHeader('Connection', 'keep-alive');
94
+ sseClients.push(res);
95
+ req.on('close', () => sseClients.splice(sseClients.indexOf(res), 1));
96
+ });
97
+ const broadcastSSE = (data) => sseClients.forEach(c => c.write(`data: ${JSON.stringify(data)}\n\n`));
98
+
99
+ app.get('/api/telegram-messages', (req, res) => {
100
+ const db = memory.readDB();
101
+ res.json(db.telegram_log || []);
102
+ });
103
+
104
+ app.post('/api/send-telegram', async (req, res) => {
105
+ const { message } = req.body;
106
+ if (!message) return res.status(400).json({ error: 'Message required' });
107
+ const chatId = process.env.TELEGRAM_CHAT_ID;
108
+ const result = await apiCaller.sendTelegramMessage(chatId, `<b>[VinOS Dashboard]</b> ${message}`);
109
+ broadcastSSE({ direction: 'OUT', chatId, text: `[VinOS Dashboard]: ${message}`, ts: new Date().toISOString() });
110
+ res.json(result);
111
+ });
112
+
113
+ const voiceTranscriber = require('./skills/voice_transcriber');
114
+ const intentRouter = require('./skills/intent_router');
115
+ const conversationMemory = require('./skills/conversation_memory');
116
+ const playbookManager = require('./skills/playbook_manager');
117
+ const versionControl = require('./skills/version_control');
118
+ const autoCron = require('./skills/infinite_money_cron');
119
+
120
+ // Start the autonomous routines
121
+ autoCron.startJobs();
122
+
123
+ // Helper to handle resolved intents
124
+ async function handleVinIntent(chatId, from, userText, confirmed = false) {
125
+ const db = memory.readDB();
126
+ const autoMode = db.user_profile_snapshot?.automatic_mode || false;
127
+
128
+ // 1. Resolve intent
129
+ const { intent, params } = await intentRouter.resolveIntent(userText);
130
+
131
+ // Safety check: if not confirmed and NOT in auto-mode, ask for confirmation
132
+ if (!confirmed && !autoMode && (intent === 'gashapon' || intent === 'pulse' || intent === 'offer')) {
133
+ if (!db.pending_commands) db.pending_commands = {};
134
+ db.pending_commands[chatId] = { intent, params, userText, ts: Date.now() };
135
+ memory.writeDB(db);
136
+
137
+ const confirmationMsg = `πŸ€– <b>Intent:</b> <i>${intent}</i>\n<b>Params:</b> <i>${params || 'none'}</i>\n\nShould I execute? (Reply: <b>Confirm</b> / <b>Cancel</b>)\n<i>Tip: Use /auto on for speed mode.</i>`;
138
+ return await apiCaller.sendTelegramMessage(chatId, confirmationMsg);
139
+ }
140
+
141
+ // 2. Route to appropriate skill
142
+ switch (intent) {
143
+ case 'remember':
144
+ const playbookId = playbookManager.savePlaybook(`User memory trigger`, params, ['user-defined']);
145
+ await apiCaller.sendTelegramMessage(chatId, `🧠 <b>Playbook Saved</b>\nI'll remember this approach for the future.\n<i>Trigger: ${params.substring(0, 50)}...</i>`);
146
+ break;
147
+
148
+ case 'recall':
149
+ const playbooks = playbookManager.searchPlaybooks(params);
150
+ if (playbooks.length > 0) {
151
+ const results = playbooks.slice(0, 2).map(pb => `πŸ“Œ <b>${pb.trigger}</b>\n${pb.solution}`).join('\n\n');
152
+ await apiCaller.sendTelegramMessage(chatId, `πŸ” <b>Found in Playbooks:</b>\n\n${results}`);
153
+ } else {
154
+ await apiCaller.sendTelegramMessage(chatId, `🀷 No playbooks found for "${params}".`);
155
+ }
156
+ break;
157
+
158
+ case 'gashapon':
159
+ const prompt = params || userText;
160
+ await apiCaller.sendTelegramMessage(chatId, "πŸŒ€ <i>Spinning the Gashapon for:</i> " + prompt);
161
+ const gResult = await apiCaller.generateNanoBananaImage(prompt);
162
+ if (gResult.success) {
163
+ await apiCaller.sendTelegramMessage(chatId, `✨ <b>Gashapon Result!</b>\n<a href="${gResult.image_url}">View Image</a>`);
164
+ } else {
165
+ await apiCaller.sendTelegramMessage(chatId, "❌ Gashapon failed: " + gResult.error);
166
+ }
167
+ break;
168
+
169
+ case 'pulse':
170
+ await apiCaller.sendTelegramMessage(chatId, "πŸ“Š <i>Scanning market...</i>");
171
+ await dailyPulse();
172
+ break;
173
+
174
+ case 'offer':
175
+ const topic = params || userText;
176
+ await apiCaller.sendTelegramMessage(chatId, `πŸ’‘ <i>Architecting offer for:</i> ${topic}`);
177
+ await offerArchitect(topic);
178
+ break;
179
+
180
+ case 'clarify':
181
+ await apiCaller.sendTelegramMessage(chatId, `πŸ€” <b>I need a bit more info:</b>\n${params}`);
182
+ break;
183
+
184
+ case 'chat':
185
+ case 'research':
186
+ case 'plan':
187
+ case 'execute':
188
+ case 'analyze':
189
+ case 'create':
190
+ default:
191
+ await processOrchestratorIntent(chatId, intent, userText, params);
192
+ break;
193
+ }
194
+ }
195
+
196
+ // Orchestrator handler that uses Memory + Playbooks
197
+ async function processOrchestratorIntent(chatId, intent, userText, params) {
198
+ // 1. Get Conversation History
199
+ const history = conversationMemory.getHistory(chatId);
200
+
201
+ // 2. Load core persona
202
+ const persona = fs.readFileSync(path.join(__dirname, 'prompts/vin_personality.md'), 'utf8');
203
+
204
+ // 3. Auto-search Playbooks for relevant context BEFORE thinking
205
+ const relatedPlaybooks = playbookManager.searchPlaybooks(userText).slice(0, 1);
206
+ let playbookContext = "";
207
+ if (relatedPlaybooks.length > 0) {
208
+ playbookContext = `\n\n# Relevant Playbook Found:\nUse this proven approach if applicable:\nTrigger: ${relatedPlaybooks[0].trigger}\nSolution: ${relatedPlaybooks[0].solution}`;
209
+ playbookManager.trackUsage(relatedPlaybooks[0].id);
210
+ }
211
+
212
+ const systemContent = persona + playbookContext + `\n\n[System Note: Your current intent classification for the upcoming message is: ${intent}]`;
213
+
214
+ const messages = [
215
+ { role: "system", content: systemContent },
216
+ ...history,
217
+ { role: "user", content: userText }
218
+ ];
219
+
220
+ // Save user message to rolling memory
221
+ conversationMemory.addMessage(chatId, "user", userText);
222
+
223
+ // Call LLM
224
+ const chatResult = await apiCaller.callOpenRouter(messages);
225
+
226
+ if (chatResult.success) {
227
+ // Save Vin's response to rolling memory
228
+ conversationMemory.addMessage(chatId, "assistant", chatResult.data);
229
+ await apiCaller.sendTelegramMessage(chatId, chatResult.data);
230
+ } else {
231
+ await apiCaller.sendTelegramMessage(chatId, "I'm having trouble thinking clearly right now. Try again in a moment.");
232
+ }
233
+ }
234
+
235
+ // Telegram Webhook
236
+ app.post('/api/telegram-webhook', async (req, res) => {
237
+ // 1. ACK immediately to Telegram to stop retries
238
+ res.status(200).send({ status: 'received' });
239
+
240
+ // 2. Process in background
241
+ (async () => {
242
+ const update = req.body;
243
+ console.log("Telegram Update received:", JSON.stringify(update));
244
+
245
+ const message = update.message;
246
+ if (!message) return;
247
+
248
+ const chatId = message.chat.id;
249
+ const from = message.from?.first_name || 'User';
250
+ let userText = message.text;
251
+
252
+ // --- Core Action Commands ---
253
+
254
+ if (userText === '/commit') {
255
+ const res = versionControl.commitChanges("Manual user commit");
256
+ if (res.success) {
257
+ await apiCaller.sendTelegramMessage(chatId, `βœ… <b>Version Logged</b>\nMessage: ${res.message}\nCommit: ${res.version}`);
258
+ } else {
259
+ await apiCaller.sendTelegramMessage(chatId, `⚠️ ${res.error}`);
260
+ }
261
+ return;
262
+ }
263
+
264
+ if (userText === '/revert') {
265
+ const res = versionControl.revertToLastWorking();
266
+ if (res.success) {
267
+ await apiCaller.sendTelegramMessage(chatId, `βͺ <b>Rolled Back</b>\nReverted changes to the last stable version.`);
268
+ } else {
269
+ await apiCaller.sendTelegramMessage(chatId, `⚠️ Revert failed: ${res.error}`);
270
+ }
271
+ return;
272
+ }
273
+
274
+ if (userText === '/log') {
275
+ const res = versionControl.getLog();
276
+ await apiCaller.sendTelegramMessage(chatId, `πŸ“œ <b>Version History:</b>\n\n<pre>${res.log}</pre>`);
277
+ return;
278
+ }
279
+
280
+ // Handle /auto on/off commands
281
+ if (userText && userText.toLowerCase().startsWith('/auto')) {
282
+ const mode = userText.toLowerCase().includes('on') ? true : false;
283
+ const db = memory.readDB();
284
+ if (!db.user_profile_snapshot) db.user_profile_snapshot = {};
285
+ db.user_profile_snapshot.automatic_mode = mode;
286
+ memory.writeDB(db);
287
+ const status = mode ? "🟒 <b>ON</b> (Speed Mode)" : "🟑 <b>OFF</b> (Safety Mode)";
288
+ return await apiCaller.sendTelegramMessage(chatId, `<b>Automatic Mode:</b> ${status}`);
289
+ }
290
+
291
+ // Handle Confirm/Cancel early
292
+ if (userText && (userText.toLowerCase() === 'confirm' || userText.toLowerCase() === 'cancel')) {
293
+ const db = memory.readDB();
294
+ const pending = db.pending_commands?.[chatId];
295
+
296
+ if (userText.toLowerCase() === 'confirm' && pending) {
297
+ delete db.pending_commands[chatId];
298
+ memory.writeDB(db);
299
+ await apiCaller.sendTelegramMessage(chatId, "βœ… <b>Confirmed.</b> Running now...");
300
+ return await handleVinIntent(chatId, from, pending.userText, true);
301
+ } else if (userText.toLowerCase() === 'cancel' && pending) {
302
+ delete db.pending_commands[chatId];
303
+ memory.writeDB(db);
304
+ return await apiCaller.sendTelegramMessage(chatId, "🀝 <b>Cancelled.</b> What else can I do for you?");
305
+ } else {
306
+ return await apiCaller.sendTelegramMessage(chatId, "No pending command found to confirm or cancel.");
307
+ }
308
+ }
309
+
310
+ if (message.voice) {
311
+ await apiCaller.sendTelegramMessage(chatId, "🎀 <i>Received audio... Transcribing...</i>");
312
+ const transcription = await voiceTranscriber.transcribeVoice(message.voice.file_id);
313
+ if (transcription) {
314
+ userText = transcription;
315
+ apiCaller.logTelegramMessage('IN', chatId, `[${from} (Voice)]: ${userText}`);
316
+ broadcastSSE({ direction: 'IN', chatId, text: `[${from} (Voice)]: ${userText}`, ts: new Date().toISOString() });
317
+ } else {
318
+ return await apiCaller.sendTelegramMessage(chatId, "❌ Transcription failed. Could you try again?");
319
+ }
320
+ } else if (userText) {
321
+ const isControl = /^(confirm|cancel|\/auto|\/start)/i.test(userText);
322
+ if (!isControl) {
323
+ await apiCaller.sendTelegramMessage(chatId, "⚑ <i>Instruction received. Processing...</i>");
324
+ }
325
+ apiCaller.logTelegramMessage('IN', chatId, `[${from}]: ${userText}`);
326
+ broadcastSSE({ direction: 'IN', chatId, text: `[${from}]: ${userText}`, ts: new Date().toISOString() });
327
+ }
328
+
329
+ // Process commands or NL
330
+ if (userText) {
331
+ if (userText.startsWith('/start')) {
332
+ await apiCaller.sendTelegramMessage(chatId, "<b>VinOS Core Online</b>");
333
+ } else {
334
+ await handleVinIntent(chatId, from, userText);
335
+ }
336
+ }
337
+ })().catch(err => console.error("Webhook processing error:", err));
338
+ });
339
+
340
+ const PORT = process.env.PORT || 7860;
341
+ app.listen(PORT, '0.0.0.0', () => {
342
+ console.log(`VinOS Core Online: http://0.0.0.0:${PORT}`);
343
+ });
Updates/vinos_update2/skills/api_caller.js ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const https = require('https');
3
+ const dns = require('dns');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const DB_PATH = path.join(__dirname, '../database/local_db.json');
7
+ require('dotenv').config();
8
+
9
+ // Force IPv4 DNS resolution (fixes ENOTFOUND on Hugging Face's IPv6-first network)
10
+ dns.setDefaultResultOrder('ipv4first');
11
+ const ipv4Agent = new https.Agent({
12
+ family: 4,
13
+ lookup: (hostname, options, callback) => dns.lookup(hostname, { ...options, family: 4 }, callback)
14
+ });
15
+ const axiosIPv4 = axios.create({ httpsAgent: ipv4Agent });
16
+
17
+ // Model assignments per skill
18
+ const MODELS = {
19
+ CHAT: process.env.OPENROUTER_MODEL || 'meta-llama/llama-3.3-70b-instruct:free',
20
+ FALLBACK: process.env.OPENROUTER_FALLBACK_MODEL || 'google/gemini-2.0-flash-exp:free',
21
+ INTENT: process.env.GROQ_MODEL || 'llama-3.1-8b-instant',
22
+ IMAGE: process.env.IMAGE_GEN_MODEL || 'gemini-2.0-flash-exp:free',
23
+ WHISPER: 'whisper-large-v3'
24
+ };
25
+
26
+ const logTelegramMessage = (direction, chatId, text) => {
27
+ try {
28
+ const raw = fs.readFileSync(DB_PATH, 'utf8');
29
+ const db = JSON.parse(raw);
30
+ if (!db.telegram_log) db.telegram_log = [];
31
+ db.telegram_log.unshift({ direction, chatId, text, ts: new Date().toISOString() });
32
+ if (db.telegram_log.length > 100) db.telegram_log = db.telegram_log.slice(0, 100);
33
+ fs.writeFileSync(DB_PATH, JSON.stringify(db, null, 2));
34
+ } catch (e) { console.error('Log error:', e.message); }
35
+ };
36
+
37
+ // Unified API Caller for VinOS
38
+ module.exports = {
39
+ logTelegramMessage,
40
+ MODELS,
41
+
42
+ // OpenRouter (AI Chat & Reasoning) β€” with automatic fallback
43
+ callOpenRouter: async (messages, model = MODELS.CHAT) => {
44
+ console.log(`[OpenRouter] Calling model: ${model}`);
45
+ try {
46
+ const response = await axiosIPv4.post('https://openrouter.ai/api/v1/chat/completions', {
47
+ model: model,
48
+ messages: messages
49
+ }, {
50
+ headers: {
51
+ 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
52
+ 'HTTP-Referer': 'https://vinos.local',
53
+ 'X-Title': 'VinOS Control Center'
54
+ }
55
+ });
56
+ return { success: true, data: response.data.choices[0].message.content, model };
57
+ } catch (error) {
58
+ console.error(`[OpenRouter] Primary model failed (${model}):`, error.response?.data || error.message);
59
+
60
+ // Auto-fallback to backup model
61
+ if (model !== MODELS.FALLBACK) {
62
+ console.log(`[OpenRouter] Falling back to: ${MODELS.FALLBACK}`);
63
+ try {
64
+ const fallbackResponse = await axiosIPv4.post('https://openrouter.ai/api/v1/chat/completions', {
65
+ model: MODELS.FALLBACK,
66
+ messages: messages
67
+ }, {
68
+ headers: {
69
+ 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
70
+ 'HTTP-Referer': 'https://vinos.local',
71
+ 'X-Title': 'VinOS Control Center'
72
+ }
73
+ });
74
+ return { success: true, data: fallbackResponse.data.choices[0].message.content, model: MODELS.FALLBACK, fallback: true };
75
+ } catch (fallbackError) {
76
+ console.error(`[OpenRouter] Fallback also failed:`, fallbackError.response?.data || fallbackError.message);
77
+ }
78
+ }
79
+ return { success: false, error: error.message };
80
+ }
81
+ },
82
+
83
+ // Groq (High Speed Inference β€” Intent Router & Voice)
84
+ callGroq: async (messages, model = MODELS.INTENT) => {
85
+ console.log(`[Groq] Calling model: ${model}`);
86
+ try {
87
+ const response = await axiosIPv4.post('https://api.groq.com/openai/v1/chat/completions', {
88
+ model: model,
89
+ messages: messages
90
+ }, {
91
+ headers: {
92
+ 'Authorization': `Bearer ${process.env.GROQ_API_KEY}`,
93
+ 'Content-Type': 'application/json'
94
+ }
95
+ });
96
+ return { success: true, data: response.data.choices[0].message.content };
97
+ } catch (error) {
98
+ console.error("[Groq] Error:", error.response?.data || error.message);
99
+ return { success: false, error: error.message };
100
+ }
101
+ },
102
+
103
+ // NanoBanana (Image Generation via Gashapon)
104
+ generateNanoBananaImage: async (prompt) => {
105
+ console.log(`[NanoBanana] Generating image: ${prompt}`);
106
+ try {
107
+ const response = await axiosIPv4.post('https://nanobanana.aikit.club/v1/images/generations', {
108
+ prompt: prompt,
109
+ model: MODELS.IMAGE,
110
+ response_format: "url"
111
+ }, {
112
+ headers: {
113
+ 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
114
+ 'Content-Type': 'application/json'
115
+ }
116
+ });
117
+ return { success: true, image_url: response.data.data[0].url };
118
+ } catch (error) {
119
+ console.error("[NanoBanana] API Error:", error.response?.data || error.message);
120
+ return { success: false, error: error.message };
121
+ }
122
+ },
123
+
124
+ // Telegram (Send Messages)
125
+ sendTelegramMessage: async (chatId, message) => {
126
+ console.log(`[Telegram] Sending to ${chatId}: ${message.substring(0, 80)}...`);
127
+ logTelegramMessage('OUT', chatId, message);
128
+ try {
129
+ const response = await axiosIPv4.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
130
+ chat_id: chatId,
131
+ text: message,
132
+ parse_mode: 'HTML'
133
+ });
134
+ return { success: true, data: response.data };
135
+ } catch (error) {
136
+ console.error("[Telegram] API Error:", error.response?.data || error.message);
137
+ return { success: false, error: error.message };
138
+ }
139
+ },
140
+
141
+ // Mayar (Payment Links)
142
+ createMayarLink: async (offerDetails) => {
143
+ console.log("[Mayar] Creating link:", offerDetails);
144
+ return { success: true, url: "https://mayar.id/pay/example" };
145
+ }
146
+ };
Updates/vinos_update2/skills/conversation_memory.js ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const dbPath = path.join(__dirname, '../database/local_db.json');
4
+
5
+ const MAX_HISTORY = 20;
6
+
7
+ module.exports = {
8
+ addMessage: (chatId, role, content) => {
9
+ try {
10
+ const raw = fs.readFileSync(dbPath, 'utf8');
11
+ const db = JSON.parse(raw);
12
+ if (!db.conversations) db.conversations = {};
13
+ if (!db.conversations[chatId]) db.conversations[chatId] = [];
14
+
15
+ db.conversations[chatId].push({ role, content, ts: Date.now() });
16
+
17
+ // Keep only the last MAX_HISTORY messages
18
+ if (db.conversations[chatId].length > MAX_HISTORY) {
19
+ db.conversations[chatId] = db.conversations[chatId].slice(-MAX_HISTORY);
20
+ }
21
+
22
+ fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
23
+ return true;
24
+ } catch (error) {
25
+ console.error("[Memory] Error adding message:", error);
26
+ return false;
27
+ }
28
+ },
29
+
30
+ getHistory: (chatId) => {
31
+ try {
32
+ const raw = fs.readFileSync(dbPath, 'utf8');
33
+ const db = JSON.parse(raw);
34
+ if (!db.conversations || !db.conversations[chatId]) return [];
35
+
36
+ // Map to standard OpenAI/OpenRouter format: { role, content }
37
+ return db.conversations[chatId].map(msg => ({ role: msg.role, content: msg.content }));
38
+ } catch (error) {
39
+ console.error("[Memory] Error reading history:", error);
40
+ return [];
41
+ }
42
+ },
43
+
44
+ clearHistory: (chatId) => {
45
+ try {
46
+ const raw = fs.readFileSync(dbPath, 'utf8');
47
+ const db = JSON.parse(raw);
48
+ if (!db.conversations) db.conversations = {};
49
+ db.conversations[chatId] = [];
50
+ fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
51
+ return true;
52
+ } catch (error) {
53
+ return false;
54
+ }
55
+ }
56
+ };
Updates/vinos_update2/skills/infinite_money_cron.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const cron = require('node-cron');
2
+ const apiCaller = require('./api_caller');
3
+ const dailyPulse = require('../use_cases/daily_pulse');
4
+ const offerArchitect = require('../use_cases/offer_architect');
5
+ const versionControl = require('./version_control');
6
+ const qualityChecker = require('./quality_checker');
7
+ const memory = require('./memory');
8
+
9
+ module.exports = {
10
+ /**
11
+ * Initializes the autonomous 12-hour money glitch cycle.
12
+ */
13
+ startJobs: () => {
14
+ // 6:00 AM Task: Discover & Launch
15
+ cron.schedule('0 6 * * *', async () => {
16
+ try {
17
+ console.log("[CRON] 6:00 AM - Initiating Morning Discovery & Launch...");
18
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "⏰ <b>[6 AM AUTONOMOUS CYCLE]</b>\nWaking up to research today's digital arbitrage opportunities...");
19
+
20
+ const pulseResult = await dailyPulse();
21
+ if (pulseResult.success) {
22
+ // Quality check the pulse
23
+ const qCheck = await qualityChecker.selfCheck(pulseResult.pulse);
24
+ if (qCheck.score < 7) {
25
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, `⚠️ <i>Research quality was only ${qCheck.score}/10. Refining search criteria for next cycle.</i>`);
26
+ } else {
27
+ // Start an offer automatically based on the top pulse
28
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "πŸš€ <i>Research quality > 7. Auto-launching Offer Architect for top opportunity...</i>");
29
+ await offerArchitect("Top trending AI niche from daily pulse");
30
+
31
+ // Auto commit the new state
32
+ versionControl.commitChanges("6 AM Auto-Launch execution");
33
+ }
34
+ }
35
+ } catch (err) {
36
+ console.error("[CRON] 6 AM Error:", err);
37
+ }
38
+ });
39
+
40
+ // 6:00 PM Task: Analyze & Tweak
41
+ cron.schedule('0 18 * * *', async () => {
42
+ try {
43
+ console.log("[CRON] 6:00 PM - Analyzing Morning Launch Results...");
44
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "⏰ <b>[6 PM AUTONOMOUS CYCLE]</b>\nAnalyzing today's active experiments...");
45
+
46
+ const db = memory.readDB();
47
+
48
+ if (db.metrics && db.metrics.total_sales === 0 && db.metrics.active_experiments > 0) {
49
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "πŸ“‰ <b>Analysis:</b> 0 sales generated in the last 12 hours. Generating strategic Pivot Plan...");
50
+
51
+ const prompt = [
52
+ { role: "system", content: "You are the VinOS Strategy Tweaker. An offer ran for 12 hours with 0 sales. Propose 3 actionable tweaks to the copy, pricing, or target audience to test for the next 12 hours." },
53
+ { role: "user", content: "Analyze the 0-sale performance and suggest the next pivot." }
54
+ ];
55
+
56
+ const pivotResult = await apiCaller.callOpenRouter(prompt);
57
+ if (pivotResult.success) {
58
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, `πŸ”„ <b>Pivot Plan Generated:</b>\n\n${pivotResult.data}`);
59
+ versionControl.commitChanges("6 PM Pivot strategy documented");
60
+ }
61
+ } else if (db.metrics && db.metrics.total_sales > 0) {
62
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "πŸŽ‰ <b>Sales Detected!</b> The strategy is working. Saving as successful playbook.");
63
+ require('./playbook_manager').savePlaybook("Winning Offer Criteria", "Strategy generated sales within 12 hours. Duplicate formatting.", ["sales", "proven"]);
64
+ } else {
65
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "ℹ️ No active experiments to analyze. Skipping tweak cycle.");
66
+ }
67
+ } catch (err) {
68
+ console.error("[CRON] 6 PM Error:", err);
69
+ }
70
+ });
71
+
72
+ console.log("[Scheduler] Infinite Money Glitch Cron Jobs Active: 6 AM and 6 PM.");
73
+ }
74
+ };
Updates/vinos_update2/skills/intent_router.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const apiCaller = require('./api_caller');
2
+ require('dotenv').config();
3
+
4
+ const intentRouter = {
5
+ /**
6
+ * Resolves user intent using Groq LLM.
7
+ * @param {string} text - The transcribed or direct text from the user.
8
+ * @returns {Promise<{intent: string, params: string}>} - The resolved intent and parameters.
9
+ */
10
+ resolveIntent: async (text) => {
11
+ console.log(`[IntentRouter] Resolving intent for: ${text}`);
12
+
13
+ const systemPrompt = `
14
+ You are the VinOS Intent Router. Your job is to classify the user's message into one of these intents:
15
+ - research: Find out information, scan the web, or learn about a topic (params: the topic)
16
+ - remember: Save an approach, rule, or solution as a Playbook (params: what to remember)
17
+ - recall: Search Playbooks for past solutions or rules (params: the query)
18
+ - plan: Break down a complex request into a step-by-step plan (params: the goal)
19
+ - execute: Run a specific tool or take a definitive action (params: the action)
20
+ - analyze: Review data, ideas, or content and provide critical feedback (params: what to analyze)
21
+ - create: Draft content, code, or structured text (params: what to create)
22
+ - gashapon: Generate an image or artistic idea (params: the prompt)
23
+ - pulse: Scan for market trends or business opportunities (params: empty)
24
+ - offer: Draft a business offer or product (params: the niche or topic)
25
+ - clarify: The request is too vague, ambiguous, or lacks detail to execute a skill (params: the missing info)
26
+ - chat: General conversation or if nothing else matches (params: the user query)
27
+
28
+ Respond ONLY with a JSON object: {"intent": "...", "params": "..."}
29
+ `;
30
+
31
+ const messages = [
32
+ { role: "system", content: systemPrompt },
33
+ { role: "user", content: text }
34
+ ];
35
+
36
+ // Use Groq for speed and free tier
37
+ const result = await apiCaller.callGroq(messages, 'llama-3.1-8b-instant');
38
+
39
+ if (result.success) {
40
+ try {
41
+ const parsed = JSON.parse(result.data.trim().match(/\{.*\}/s)[0]);
42
+ console.log(`[IntentRouter] Resolved: ${parsed.intent} | ${parsed.params}`);
43
+ return parsed;
44
+ } catch (e) {
45
+ console.error("[IntentRouter] Failed to parse JSON response:", result.data);
46
+ return { intent: "chat", params: text };
47
+ }
48
+ } else {
49
+ console.error("[IntentRouter] Failed to call Groq:", result.error);
50
+ return { intent: "chat", params: text };
51
+ }
52
+ }
53
+ };
54
+
55
+ module.exports = intentRouter;
Updates/vinos_update2/skills/memory.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const dbPath = path.join(__dirname, '../database/local_db.json');
4
+
5
+ module.exports = {
6
+ readDB: () => {
7
+ try {
8
+ const data = fs.readFileSync(dbPath, 'utf8');
9
+ return JSON.parse(data);
10
+ } catch (error) {
11
+ console.error("Error reading DB:", error);
12
+ return {};
13
+ }
14
+ },
15
+ writeDB: (data) => {
16
+ try {
17
+ fs.writeFileSync(dbPath, JSON.stringify(data, null, 2));
18
+ return true;
19
+ } catch (error) {
20
+ console.error("Error writing DB:", error);
21
+ return false;
22
+ }
23
+ }
24
+ };
Updates/vinos_update2/skills/playbook_manager.js ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const dbPath = path.join(__dirname, '../database/playbooks.json');
4
+
5
+ // Ensure db exists
6
+ if (!fs.existsSync(dbPath)) {
7
+ fs.writeFileSync(dbPath, JSON.stringify({ playbooks: [] }, null, 2));
8
+ }
9
+
10
+ module.exports = {
11
+ savePlaybook: (trigger, solution, tags = []) => {
12
+ try {
13
+ const raw = fs.readFileSync(dbPath, 'utf8');
14
+ const db = JSON.parse(raw);
15
+
16
+ const newPlaybook = {
17
+ id: 'pb_' + Date.now(),
18
+ trigger,
19
+ solution,
20
+ tags,
21
+ created: new Date().toISOString(),
22
+ used_count: 0
23
+ };
24
+
25
+ db.playbooks.push(newPlaybook);
26
+ fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
27
+ console.log(`[Playbook] Saved new approach: ${trigger}`);
28
+ return newPlaybook.id;
29
+ } catch (error) {
30
+ console.error("[Playbook] Error saving playbook:", error);
31
+ return null;
32
+ }
33
+ },
34
+
35
+ searchPlaybooks: (query) => {
36
+ try {
37
+ const raw = fs.readFileSync(dbPath, 'utf8');
38
+ const db = JSON.parse(raw);
39
+ // If no playbooks, just return empty
40
+ if (!db.playbooks || db.playbooks.length === 0) return [];
41
+
42
+ const q = query.toLowerCase();
43
+
44
+ // Basic semantic search across trigger, tags, and solution
45
+ const matches = db.playbooks.filter(pb =>
46
+ (pb.trigger && pb.trigger.toLowerCase().includes(q)) ||
47
+ (pb.tags && pb.tags.some(tag => tag.toLowerCase().includes(q))) ||
48
+ (pb.solution && pb.solution.toLowerCase().includes(q))
49
+ );
50
+
51
+ return matches;
52
+ } catch (error) {
53
+ console.error("[Playbook] Error searching playbooks:", error);
54
+ return [];
55
+ }
56
+ },
57
+
58
+ getAllPlaybooks: () => {
59
+ try {
60
+ const raw = fs.readFileSync(dbPath, 'utf8');
61
+ const db = JSON.parse(raw);
62
+ return db.playbooks || [];
63
+ } catch (error) {
64
+ return [];
65
+ }
66
+ },
67
+
68
+ trackUsage: (playbookId) => {
69
+ try {
70
+ const raw = fs.readFileSync(dbPath, 'utf8');
71
+ const db = JSON.parse(raw);
72
+ const pbIndex = db.playbooks.findIndex(pb => pb.id === playbookId);
73
+ if (pbIndex !== -1) {
74
+ db.playbooks[pbIndex].used_count = (db.playbooks[pbIndex].used_count || 0) + 1;
75
+ fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
76
+ }
77
+ } catch (error) {
78
+ // ignore
79
+ }
80
+ }
81
+ };
Updates/vinos_update2/skills/quality_checker.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const apiCaller = require('./api_caller');
2
+
3
+ module.exports = {
4
+ /**
5
+ * Scores output quality from 1-10 to determine if we need a paid model.
6
+ */
7
+ selfCheck: async (content) => {
8
+ const prompt = [
9
+ { role: "system", content: "You are the VinOS Quality Assessor. Grade the following content strictly from 1 to 10 based on professionalism, clarity, actionable value, and depth. Return ONLY a single number from 1 to 10 and nothing else." },
10
+ { role: "user", content: content }
11
+ ];
12
+
13
+ const result = await apiCaller.callOpenRouter(prompt);
14
+ if (result.success) {
15
+ const match = result.data.match(/\d+/);
16
+ if (match) {
17
+ const score = parseInt(match[0], 10);
18
+ console.log(`[QualityChecker] Output scored: ${score}/10`);
19
+ return { success: true, score: score };
20
+ }
21
+ }
22
+ return { success: false, score: 0 };
23
+ }
24
+ };
Updates/vinos_update2/skills/version_control.js ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { execSync } = require('child_process');
2
+
3
+ module.exports = {
4
+ /**
5
+ * Commits all current changes with a descriptive message.
6
+ */
7
+ commitChanges: (message) => {
8
+ try {
9
+ execSync('git add .', { stdio: 'pipe' });
10
+ execSync(`git commit -m "${message}"`, { stdio: 'pipe' });
11
+ console.log(`[VersionControl] Auto-Logged Version: ${message}`);
12
+
13
+ // Get the hash
14
+ const hash = execSync('git rev-parse --short HEAD', { stdio: 'pipe' }).toString().trim();
15
+ return { success: true, version: hash, message };
16
+ } catch (error) {
17
+ // It fails if there are no changes to commit
18
+ return { success: false, error: "Nothing to commit or error occurred." };
19
+ }
20
+ },
21
+
22
+ /**
23
+ * Reverts all files to the last saved working commit.
24
+ * WARNING: Erases uncommitted work.
25
+ */
26
+ revertToLastWorking: () => {
27
+ try {
28
+ execSync('git reset --hard HEAD', { stdio: 'pipe' });
29
+ execSync('git clean -fd', { stdio: 'pipe' });
30
+ console.log(`[VersionControl] Reverted state to last stable version.`);
31
+ return { success: true };
32
+ } catch (error) {
33
+ console.error(`[VersionControl] Revert error:`, error);
34
+ return { success: false, error: error.message };
35
+ }
36
+ },
37
+
38
+ /**
39
+ * Retrieves the last 5 version logs.
40
+ */
41
+ getLog: () => {
42
+ try {
43
+ const log = execSync('git log -n 5 --oneline', { stdio: 'pipe' }).toString().trim();
44
+ return { success: true, log };
45
+ } catch (error) {
46
+ return { success: false, log: "No previous logs." };
47
+ }
48
+ }
49
+ };
Updates/vinos_update2/skills/voice_transcriber.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const https = require('https');
3
+ const dns = require('dns');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const FormData = require('form-data');
7
+ require('dotenv').config();
8
+
9
+ // Force IPv4 DNS resolution (fixes ENOTFOUND on Hugging Face)
10
+ dns.setDefaultResultOrder('ipv4first');
11
+ const ipv4Agent = new https.Agent({
12
+ family: 4,
13
+ lookup: (hostname, options, callback) => dns.lookup(hostname, { ...options, family: 4 }, callback)
14
+ });
15
+ const axiosIPv4 = axios.create({ httpsAgent: ipv4Agent });
16
+
17
+ const voiceTranscriber = {
18
+ /**
19
+ * Transcribes a Telegram voice message using Groq Whisper.
20
+ * Model: whisper-large-v3 (free, fastest STT available)
21
+ * @param {string} fileId - The Telegram file_id of the voice message.
22
+ * @returns {Promise<string|null>} - The transcribed text or null on failure.
23
+ */
24
+ transcribeVoice: async (fileId) => {
25
+ try {
26
+ const token = process.env.TELEGRAM_BOT_TOKEN;
27
+
28
+ // 1. Get file path from Telegram
29
+ console.log(`[VoiceTranscriber] Getting file path for ID: ${fileId}`);
30
+ const fileInfoResponse = await axiosIPv4.get(`https://api.telegram.org/bot${token}/getFile`, {
31
+ params: { file_id: fileId }
32
+ });
33
+
34
+ if (!fileInfoResponse.data.ok) {
35
+ console.error("[VoiceTranscriber] Failed to get file info:", fileInfoResponse.data.description);
36
+ return null;
37
+ }
38
+
39
+ const filePath = fileInfoResponse.data.result.file_path;
40
+ const downloadUrl = `https://api.telegram.org/file/bot${token}/${filePath}`;
41
+
42
+ // 2. Download the audio file
43
+ console.log(`[VoiceTranscriber] Downloading voice file...`);
44
+ const audioResponse = await axiosIPv4.get(downloadUrl, { responseType: 'arraybuffer' });
45
+
46
+ // Save temporarily
47
+ const tempFilePath = path.join(__dirname, `../tmp_voice_${Date.now()}.ogg`);
48
+ fs.writeFileSync(tempFilePath, audioResponse.data);
49
+
50
+ // 3. Send to Groq Whisper (free, fastest STT)
51
+ console.log(`[VoiceTranscriber] Sending to Groq Whisper (whisper-large-v3)...`);
52
+ const form = new FormData();
53
+ form.append('file', fs.createReadStream(tempFilePath));
54
+ form.append('model', 'whisper-large-v3');
55
+
56
+ const groqResponse = await axiosIPv4.post('https://api.groq.com/openai/v1/audio/transcriptions', form, {
57
+ headers: {
58
+ ...form.getHeaders(),
59
+ 'Authorization': `Bearer ${process.env.GROQ_API_KEY}`
60
+ }
61
+ });
62
+
63
+ // Cleanup temp file
64
+ fs.unlinkSync(tempFilePath);
65
+
66
+ if (groqResponse.data && groqResponse.data.text) {
67
+ console.log(`[VoiceTranscriber] Transcription: ${groqResponse.data.text}`);
68
+ return groqResponse.data.text;
69
+ }
70
+
71
+ return null;
72
+ } catch (error) {
73
+ console.error("[VoiceTranscriber] Error:", error.response?.data || error.message);
74
+ return null;
75
+ }
76
+ }
77
+ };
78
+
79
+ module.exports = voiceTranscriber;
Updates/vinos_update2/skills/web_researcher.js ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const https = require('https');
3
+ const dns = require('dns');
4
+
5
+ // Force IPv4
6
+ dns.setDefaultResultOrder('ipv4first');
7
+ const ipv4Agent = new https.Agent({
8
+ family: 4,
9
+ lookup: (hostname, options, callback) => dns.lookup(hostname, { ...options, family: 4 }, callback)
10
+ });
11
+ const axiosIPv4 = axios.create({ httpsAgent: ipv4Agent });
12
+
13
+ module.exports = {
14
+ /**
15
+ * Conducts a free web search by scraping DuckDuckGo HTML (No API key needed).
16
+ */
17
+ searchWeb: async (query) => {
18
+ try {
19
+ console.log(`[WebResearcher] Searching for: ${query}`);
20
+
21
+ const response = await axiosIPv4.get('https://html.duckduckgo.com/html/', {
22
+ params: { q: query },
23
+ headers: {
24
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
25
+ }
26
+ });
27
+
28
+ const html = response.data;
29
+ const results = [];
30
+
31
+ // Basic Regex to extract search results from DuckDuckGo HTML
32
+ const resultRegex = /<a class="result__url" href="([^"]+)".*?>.*?<\/a>.*?<a class="result__snippet[^>]+>(.*?)<\/a>/gs;
33
+ let match;
34
+ while ((match = resultRegex.exec(html)) !== null && results.length < 5) {
35
+ // Strip remaining HTML tags from snippet
36
+ const snippet = match[2].replace(/<[^>]*>?/gm, '').trim();
37
+ results.push(`Source: ${match[1]}\nContext: ${snippet}`);
38
+ }
39
+
40
+ if (results.length === 0) {
41
+ return { success: true, data: "Found nothing of value on the web." };
42
+ }
43
+
44
+ return { success: true, data: results.join('\n\n') };
45
+ } catch (error) {
46
+ console.error("[WebResearcher] Error:", error.message);
47
+ return { success: false, error: "Search failed due to network constraints." };
48
+ }
49
+ }
50
+ };
Updates/vinos_update2/start.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ # VinOS Cloud Startup Script
3
+ # Resolves all API endpoint IPs and injects into /etc/hosts
4
+ # This bypasses Hugging Face's DNS restrictions
5
+
6
+ echo "πŸ”§ Resolving API endpoints for Cloud Mode..."
7
+
8
+ # Resolve and inject each API domain
9
+ for DOMAIN in api.telegram.org openrouter.ai api.groq.com nanobanana.aikit.club; do
10
+ IP=$(getent hosts $DOMAIN | awk '{ print $1 }' | head -1)
11
+ if [ -n "$IP" ]; then
12
+ echo "$IP $DOMAIN" >> /etc/hosts
13
+ echo " βœ… $DOMAIN -> $IP"
14
+ else
15
+ echo " ⚠️ Could not resolve $DOMAIN (will use fallback)"
16
+ fi
17
+ done
18
+
19
+ # Fallback IPs if DNS fails completely
20
+ grep -q "api.telegram.org" /etc/hosts || echo "149.154.167.220 api.telegram.org" >> /etc/hosts
21
+
22
+ echo ""
23
+ echo "πŸš€ Starting VinOS Engine..."
24
+ exec node server.js
Updates/vinos_update2/use_cases/daily_pulse.js ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const apiCaller = require('../skills/api_caller');
2
+ const webResearcher = require('../skills/web_researcher');
3
+
4
+ /**
5
+ * Use Case 1: Daily Pulse (Market Scanner)
6
+ * Upgraded: Now pulls real-time data from search engines before summarizing.
7
+ */
8
+ module.exports = async () => {
9
+ console.log("[Daily Pulse] Starting market scan...");
10
+
11
+ // 1. Gather live market data first
12
+ const searchResult = await webResearcher.searchWeb("top AI business trends opportunities digital arbitrage 2026");
13
+ const marketData = searchResult.success ? searchResult.data : "No live data available.";
14
+
15
+ // 2. Synthesize with LLM
16
+ const prompt = [
17
+ { role: "system", content: "You are Vin, a sharp digital arbitrage analyst. You've just performed web research. Synthesize the raw web data provided into 3 high-potential AI service niches that can be launched immediately." },
18
+ { role: "user", content: `Raw Web Data:\n${marketData}\n\nTask: Synthesize this into 3 actionable digital arbitrage opportunities for the Indonesian market.` }
19
+ ];
20
+
21
+ const result = await apiCaller.callOpenRouter(prompt);
22
+
23
+ if (result.success) {
24
+ const message = `πŸ“ˆ <b>VinOS Daily Pulse (Live Research)</b>\n\n${result.data}\n\n<i>Time to execute? Send /offer [niche] to build it.</i>`;
25
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, message);
26
+ return { success: true, pulse: result.data };
27
+ } else {
28
+ return { success: false, error: result.error };
29
+ }
30
+ };
Updates/vinos_update2/use_cases/offer_architect.js ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const apiCaller = require('../skills/api_caller');
2
+ const memory = require('../skills/memory');
3
+
4
+ /**
5
+ * Use Case 2: Offer Architect
6
+ * Creates a high-converting offer and generates a payment link placeholder.
7
+ */
8
+ module.exports = async (topic) => {
9
+ console.log(`[Offer Architect] Designing offer for: ${topic}`);
10
+
11
+ const prompt = [
12
+ { role: "system", content: "You are a master of conversion copy and digital product design." },
13
+ { role: "user", content: `Create a 'beta' offer for a digital product about: ${topic}. Include a title, price (in IDR), and 3 key benefits.` }
14
+ ];
15
+
16
+ const result = await apiCaller.callOpenRouter(prompt);
17
+
18
+ if (result.success) {
19
+ // Simulate creating a Mayar link
20
+ const mayarLink = await apiCaller.createMayarLink({ title: topic, price: 300000 });
21
+
22
+ // Update Local DB with new experiment
23
+ const db = memory.readDB();
24
+ db.metrics.active_experiments += 1;
25
+ memory.writeDB(db);
26
+
27
+ const message = `<b>New Offer Crafted!</b> πŸ’‘\n\n${result.data}\n\nCheck it out here: ${mayarLink.url}`;
28
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, message);
29
+
30
+ return { success: true, offer: result.data, link: mayarLink.url };
31
+ } else {
32
+ return { success: false, error: result.error };
33
+ }
34
+ };
database/local_db.json CHANGED
@@ -25,6 +25,12 @@
25
  "active_experiments": 0
26
  },
27
  "telegram_log": [
 
 
 
 
 
 
28
  {
29
  "direction": "OUT",
30
  "chatId": 8743583463,
 
25
  "active_experiments": 0
26
  },
27
  "telegram_log": [
28
+ {
29
+ "direction": "OUT",
30
+ "chatId": "8743583463",
31
+ "text": "πŸ“Š <b>Strategic Analysis Complete.</b>\nGenerating high-end McKinsey PDF report for you now...",
32
+ "ts": "2026-03-21T16:55:34.959Z"
33
+ },
34
  {
35
  "direction": "OUT",
36
  "chatId": 8743583463,
database/reports/VinOS_McKinsey_Report_1774112134907.pdf ADDED
Binary file (6.64 kB). View file
 
package-lock.json CHANGED
@@ -8,11 +8,75 @@
8
  "name": "vinos-full-stack",
9
  "version": "1.0.0",
10
  "dependencies": {
 
11
  "axios": "^1.6.2",
12
  "cors": "^2.8.5",
13
  "dotenv": "^16.3.1",
14
  "express": "^4.18.2",
15
- "form-data": "^4.0.5"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
  },
18
  "node_modules/accepts": {
@@ -51,6 +115,26 @@
51
  "proxy-from-env": "^1.1.0"
52
  }
53
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  "node_modules/body-parser": {
55
  "version": "1.20.4",
56
  "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
@@ -75,6 +159,15 @@
75
  "npm": "1.2.8000 || >= 1.4.16"
76
  }
77
  },
 
 
 
 
 
 
 
 
 
78
  "node_modules/bytes": {
79
  "version": "3.1.2",
80
  "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -113,6 +206,15 @@
113
  "url": "https://github.com/sponsors/ljharb"
114
  }
115
  },
 
 
 
 
 
 
 
 
 
116
  "node_modules/combined-stream": {
117
  "version": "1.0.8",
118
  "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -215,6 +317,12 @@
215
  "npm": "1.2.8000 || >= 1.4.16"
216
  }
217
  },
 
 
 
 
 
 
218
  "node_modules/dotenv": {
219
  "version": "16.6.1",
220
  "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
@@ -362,6 +470,12 @@
362
  "url": "https://opencollective.com/express"
363
  }
364
  },
 
 
 
 
 
 
365
  "node_modules/finalhandler": {
366
  "version": "1.3.2",
367
  "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
@@ -400,6 +514,23 @@
400
  }
401
  }
402
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  "node_modules/form-data": {
404
  "version": "4.0.5",
405
  "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -578,6 +709,31 @@
578
  "node": ">= 0.10"
579
  }
580
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
  "node_modules/math-intrinsics": {
582
  "version": "1.1.0",
583
  "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -662,6 +818,18 @@
662
  "node": ">= 0.6"
663
  }
664
  },
 
 
 
 
 
 
 
 
 
 
 
 
665
  "node_modules/object-assign": {
666
  "version": "4.1.1",
667
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -695,6 +863,12 @@
695
  "node": ">= 0.8"
696
  }
697
  },
 
 
 
 
 
 
698
  "node_modules/parseurl": {
699
  "version": "1.3.3",
700
  "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -710,6 +884,25 @@
710
  "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
711
  "license": "MIT"
712
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
713
  "node_modules/proxy-addr": {
714
  "version": "2.0.7",
715
  "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -768,6 +961,12 @@
768
  "node": ">= 0.8"
769
  }
770
  },
 
 
 
 
 
 
771
  "node_modules/safe-buffer": {
772
  "version": "5.2.1",
773
  "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -926,6 +1125,12 @@
926
  "node": ">= 0.8"
927
  }
928
  },
 
 
 
 
 
 
929
  "node_modules/toidentifier": {
930
  "version": "1.0.1",
931
  "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -935,6 +1140,12 @@
935
  "node": ">=0.6"
936
  }
937
  },
 
 
 
 
 
 
938
  "node_modules/type-is": {
939
  "version": "1.6.18",
940
  "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -948,6 +1159,26 @@
948
  "node": ">= 0.6"
949
  }
950
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
951
  "node_modules/unpipe": {
952
  "version": "1.0.0",
953
  "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -966,6 +1197,15 @@
966
  "node": ">= 0.4.0"
967
  }
968
  },
 
 
 
 
 
 
 
 
 
969
  "node_modules/vary": {
970
  "version": "1.1.2",
971
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
 
8
  "name": "vinos-full-stack",
9
  "version": "1.0.0",
10
  "dependencies": {
11
+ "@huggingface/inference": "^4.13.15",
12
  "axios": "^1.6.2",
13
  "cors": "^2.8.5",
14
  "dotenv": "^16.3.1",
15
  "express": "^4.18.2",
16
+ "form-data": "^4.0.5",
17
+ "node-cron": "^3.0.3",
18
+ "pdfkit": "^0.18.0"
19
+ }
20
+ },
21
+ "node_modules/@huggingface/inference": {
22
+ "version": "4.13.15",
23
+ "resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-4.13.15.tgz",
24
+ "integrity": "sha512-V7B13KFDVhYkQqgx8vpMcmtEG+PoePlh65IUvpphTTItHAq6zRLcsS4torh1QavUaT+6nEwho4wFXzBQNGBwKQ==",
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "@huggingface/jinja": "^0.5.5",
28
+ "@huggingface/tasks": "^0.19.90"
29
+ },
30
+ "engines": {
31
+ "node": ">=18"
32
+ }
33
+ },
34
+ "node_modules/@huggingface/jinja": {
35
+ "version": "0.5.6",
36
+ "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.6.tgz",
37
+ "integrity": "sha512-MyMWyLnjqo+KRJYSH7oWNbsOn5onuIvfXYPcc0WOGxU0eHUV7oAYUoQTl2BMdu7ml+ea/bu11UM+EshbeHwtIA==",
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=18"
41
+ }
42
+ },
43
+ "node_modules/@huggingface/tasks": {
44
+ "version": "0.19.90",
45
+ "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.19.90.tgz",
46
+ "integrity": "sha512-nfV9luJbvwGQ/5oKXkKhCV9h4X7mwh1YaGG3ORd6UMLDSwr1OFSSatcBX0O9OtBtmNK19aGSjbLFqqgcIR6+IA==",
47
+ "license": "MIT"
48
+ },
49
+ "node_modules/@noble/ciphers": {
50
+ "version": "1.3.0",
51
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
52
+ "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
53
+ "license": "MIT",
54
+ "engines": {
55
+ "node": "^14.21.3 || >=16"
56
+ },
57
+ "funding": {
58
+ "url": "https://paulmillr.com/funding/"
59
+ }
60
+ },
61
+ "node_modules/@noble/hashes": {
62
+ "version": "1.8.0",
63
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
64
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
65
+ "license": "MIT",
66
+ "engines": {
67
+ "node": "^14.21.3 || >=16"
68
+ },
69
+ "funding": {
70
+ "url": "https://paulmillr.com/funding/"
71
+ }
72
+ },
73
+ "node_modules/@swc/helpers": {
74
+ "version": "0.5.19",
75
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz",
76
+ "integrity": "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA==",
77
+ "license": "Apache-2.0",
78
+ "dependencies": {
79
+ "tslib": "^2.8.0"
80
  }
81
  },
82
  "node_modules/accepts": {
 
115
  "proxy-from-env": "^1.1.0"
116
  }
117
  },
118
+ "node_modules/base64-js": {
119
+ "version": "1.5.1",
120
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
121
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
122
+ "funding": [
123
+ {
124
+ "type": "github",
125
+ "url": "https://github.com/sponsors/feross"
126
+ },
127
+ {
128
+ "type": "patreon",
129
+ "url": "https://www.patreon.com/feross"
130
+ },
131
+ {
132
+ "type": "consulting",
133
+ "url": "https://feross.org/support"
134
+ }
135
+ ],
136
+ "license": "MIT"
137
+ },
138
  "node_modules/body-parser": {
139
  "version": "1.20.4",
140
  "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
 
159
  "npm": "1.2.8000 || >= 1.4.16"
160
  }
161
  },
162
+ "node_modules/brotli": {
163
+ "version": "1.3.3",
164
+ "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
165
+ "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
166
+ "license": "MIT",
167
+ "dependencies": {
168
+ "base64-js": "^1.1.2"
169
+ }
170
+ },
171
  "node_modules/bytes": {
172
  "version": "3.1.2",
173
  "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
 
206
  "url": "https://github.com/sponsors/ljharb"
207
  }
208
  },
209
+ "node_modules/clone": {
210
+ "version": "2.1.2",
211
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
212
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
213
+ "license": "MIT",
214
+ "engines": {
215
+ "node": ">=0.8"
216
+ }
217
+ },
218
  "node_modules/combined-stream": {
219
  "version": "1.0.8",
220
  "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 
317
  "npm": "1.2.8000 || >= 1.4.16"
318
  }
319
  },
320
+ "node_modules/dfa": {
321
+ "version": "1.2.0",
322
+ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
323
+ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
324
+ "license": "MIT"
325
+ },
326
  "node_modules/dotenv": {
327
  "version": "16.6.1",
328
  "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
 
470
  "url": "https://opencollective.com/express"
471
  }
472
  },
473
+ "node_modules/fast-deep-equal": {
474
+ "version": "3.1.3",
475
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
476
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
477
+ "license": "MIT"
478
+ },
479
  "node_modules/finalhandler": {
480
  "version": "1.3.2",
481
  "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
 
514
  }
515
  }
516
  },
517
+ "node_modules/fontkit": {
518
+ "version": "2.0.4",
519
+ "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
520
+ "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
521
+ "license": "MIT",
522
+ "dependencies": {
523
+ "@swc/helpers": "^0.5.12",
524
+ "brotli": "^1.3.2",
525
+ "clone": "^2.1.2",
526
+ "dfa": "^1.2.0",
527
+ "fast-deep-equal": "^3.1.3",
528
+ "restructure": "^3.0.0",
529
+ "tiny-inflate": "^1.0.3",
530
+ "unicode-properties": "^1.4.0",
531
+ "unicode-trie": "^2.0.0"
532
+ }
533
+ },
534
  "node_modules/form-data": {
535
  "version": "4.0.5",
536
  "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
 
709
  "node": ">= 0.10"
710
  }
711
  },
712
+ "node_modules/js-md5": {
713
+ "version": "0.8.3",
714
+ "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.8.3.tgz",
715
+ "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==",
716
+ "license": "MIT"
717
+ },
718
+ "node_modules/linebreak": {
719
+ "version": "1.1.0",
720
+ "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz",
721
+ "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==",
722
+ "license": "MIT",
723
+ "dependencies": {
724
+ "base64-js": "0.0.8",
725
+ "unicode-trie": "^2.0.0"
726
+ }
727
+ },
728
+ "node_modules/linebreak/node_modules/base64-js": {
729
+ "version": "0.0.8",
730
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
731
+ "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==",
732
+ "license": "MIT",
733
+ "engines": {
734
+ "node": ">= 0.4"
735
+ }
736
+ },
737
  "node_modules/math-intrinsics": {
738
  "version": "1.1.0",
739
  "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
 
818
  "node": ">= 0.6"
819
  }
820
  },
821
+ "node_modules/node-cron": {
822
+ "version": "3.0.3",
823
+ "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz",
824
+ "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==",
825
+ "license": "ISC",
826
+ "dependencies": {
827
+ "uuid": "8.3.2"
828
+ },
829
+ "engines": {
830
+ "node": ">=6.0.0"
831
+ }
832
+ },
833
  "node_modules/object-assign": {
834
  "version": "4.1.1",
835
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
 
863
  "node": ">= 0.8"
864
  }
865
  },
866
+ "node_modules/pako": {
867
+ "version": "0.2.9",
868
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
869
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
870
+ "license": "MIT"
871
+ },
872
  "node_modules/parseurl": {
873
  "version": "1.3.3",
874
  "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
 
884
  "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
885
  "license": "MIT"
886
  },
887
+ "node_modules/pdfkit": {
888
+ "version": "0.18.0",
889
+ "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.18.0.tgz",
890
+ "integrity": "sha512-NvUwSDZ0eYEzqAiWwVQkRkjYUkZ48kcsHuCO31ykqPPIVkwoSDjDGiwIgHHNtsiwls3z3P/zy4q00hl2chg2Ug==",
891
+ "license": "MIT",
892
+ "dependencies": {
893
+ "@noble/ciphers": "^1.0.0",
894
+ "@noble/hashes": "^1.6.0",
895
+ "fontkit": "^2.0.4",
896
+ "js-md5": "^0.8.3",
897
+ "linebreak": "^1.1.0",
898
+ "png-js": "^1.0.0"
899
+ }
900
+ },
901
+ "node_modules/png-js": {
902
+ "version": "1.0.0",
903
+ "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz",
904
+ "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g=="
905
+ },
906
  "node_modules/proxy-addr": {
907
  "version": "2.0.7",
908
  "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
 
961
  "node": ">= 0.8"
962
  }
963
  },
964
+ "node_modules/restructure": {
965
+ "version": "3.0.2",
966
+ "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
967
+ "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
968
+ "license": "MIT"
969
+ },
970
  "node_modules/safe-buffer": {
971
  "version": "5.2.1",
972
  "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 
1125
  "node": ">= 0.8"
1126
  }
1127
  },
1128
+ "node_modules/tiny-inflate": {
1129
+ "version": "1.0.3",
1130
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
1131
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
1132
+ "license": "MIT"
1133
+ },
1134
  "node_modules/toidentifier": {
1135
  "version": "1.0.1",
1136
  "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
 
1140
  "node": ">=0.6"
1141
  }
1142
  },
1143
+ "node_modules/tslib": {
1144
+ "version": "2.8.1",
1145
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
1146
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
1147
+ "license": "0BSD"
1148
+ },
1149
  "node_modules/type-is": {
1150
  "version": "1.6.18",
1151
  "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
 
1159
  "node": ">= 0.6"
1160
  }
1161
  },
1162
+ "node_modules/unicode-properties": {
1163
+ "version": "1.4.1",
1164
+ "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
1165
+ "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
1166
+ "license": "MIT",
1167
+ "dependencies": {
1168
+ "base64-js": "^1.3.0",
1169
+ "unicode-trie": "^2.0.0"
1170
+ }
1171
+ },
1172
+ "node_modules/unicode-trie": {
1173
+ "version": "2.0.0",
1174
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
1175
+ "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
1176
+ "license": "MIT",
1177
+ "dependencies": {
1178
+ "pako": "^0.2.5",
1179
+ "tiny-inflate": "^1.0.0"
1180
+ }
1181
+ },
1182
  "node_modules/unpipe": {
1183
  "version": "1.0.0",
1184
  "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
 
1197
  "node": ">= 0.4.0"
1198
  }
1199
  },
1200
+ "node_modules/uuid": {
1201
+ "version": "8.3.2",
1202
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
1203
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
1204
+ "license": "MIT",
1205
+ "bin": {
1206
+ "uuid": "dist/bin/uuid"
1207
+ }
1208
+ },
1209
  "node_modules/vary": {
1210
  "version": "1.1.2",
1211
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
package.json CHANGED
@@ -7,10 +7,13 @@
7
  "dev": "node --watch server.js"
8
  },
9
  "dependencies": {
 
10
  "axios": "^1.6.2",
11
  "cors": "^2.8.5",
12
  "dotenv": "^16.3.1",
13
  "express": "^4.18.2",
14
- "form-data": "^4.0.5"
 
 
15
  }
16
  }
 
7
  "dev": "node --watch server.js"
8
  },
9
  "dependencies": {
10
+ "@huggingface/inference": "^4.13.15",
11
  "axios": "^1.6.2",
12
  "cors": "^2.8.5",
13
  "dotenv": "^16.3.1",
14
  "express": "^4.18.2",
15
+ "form-data": "^4.0.5",
16
+ "node-cron": "^3.0.3",
17
+ "pdfkit": "^0.18.0"
18
  }
19
  }
public/app.js CHANGED
@@ -1,181 +1,137 @@
1
  document.addEventListener('DOMContentLoaded', async () => {
2
- // Fetch Profile
3
- try {
4
- const profRes = await fetch('/api/profile');
5
- const profile = await profRes.json();
6
- document.getElementById('profile-badge').innerHTML =
7
- `<span class="text-gray-400">User:</span> ${profile.nickname} <br> <span class="text-gray-400">Niche:</span> ${profile.main_niche}`;
8
- } catch(e) {
9
- console.error(e);
10
- }
11
-
12
- // Fetch Sprints
13
- try {
14
- const sprintRes = await fetch('/api/sprints');
15
- const sprints = await sprintRes.json();
16
- const container = document.getElementById('sprints-container');
17
- container.innerHTML = '';
18
- sprints.forEach(s => {
19
- container.innerHTML += `
20
- <div class="p-3 bg-gray-800 rounded border border-gray-700 flex justify-between items-center">
21
- <div>
22
- <h3 class="font-medium text-blue-300">${s.title}</h3>
23
- <p class="text-xs text-gray-400">Status: ${s.status}</p>
24
- </div>
25
- <span class="text-xs font-mono bg-blue-900 text-blue-200 px-2 py-1 rounded">${s.expected_revenue}</span>
26
- </div>
27
- `;
28
- });
29
- } catch(e) {
30
- console.error(e);
31
- }
32
-
33
- // Status Check
34
- try {
35
- const statusRes = await fetch('/api/status');
36
- const status = await statusRes.json();
37
- const statusContainer = document.getElementById('status-container');
38
- Object.entries(status).forEach(([key, value]) => {
39
- statusContainer.innerHTML += `
40
- <div class="flex items-center justify-between p-2 rounded bg-gray-800 border border-gray-700">
41
- <span class="capitalize">${key.replace('_', ' ')}</span>
42
- <span class="w-2 h-2 rounded-full ${value ? 'bg-green-500' : 'bg-red-500'}"></span>
43
- </div>
44
- `;
45
- });
46
- } catch(e) {
47
- console.error(e);
48
- }
49
-
50
- // Gashapon Generation
51
- const generateBtn = document.getElementById('generate-btn');
52
- const promptInput = document.getElementById('gashapon-prompt');
53
- const resultContainer = document.getElementById('gashapon-result');
54
- const resultImg = document.getElementById('gashapon-img');
55
 
56
- generateBtn.addEventListener('click', async () => {
57
- const prompt = promptInput.value;
58
- if (!prompt) return alert("Please enter a prompt!");
 
 
 
 
 
 
 
 
 
59
 
60
- generateBtn.disabled = true;
61
- generateBtn.innerText = "Generating...";
62
- resultContainer.classList.add('hidden');
 
63
 
64
- try {
65
- const response = await fetch('/api/generate-image', {
66
- method: 'POST',
67
- headers: { 'Content-Type': 'application/json' },
68
- body: JSON.stringify({ prompt })
69
- });
70
- const data = await response.json();
71
-
72
- if (data.success) {
73
- resultImg.src = data.image_url;
74
- resultContainer.classList.remove('hidden');
75
- document.getElementById('logs').innerHTML += `[Gashapon] Image generated for: ${prompt}<br>`;
76
- } else {
77
- alert("Error: " + data.error);
78
- }
79
- } catch (e) {
80
- console.error(e);
81
- alert("Failed to generate image.");
82
- } finally {
83
- generateBtn.disabled = false;
84
- generateBtn.innerText = "Generate Gashapon";
85
- }
86
- });
87
 
88
- // Strategy Lab Triggers
89
- const pulseBtn = document.getElementById('pulse-btn');
90
- const offerBtn = document.getElementById('offer-btn');
91
- const offerTopic = document.getElementById('offer-topic');
 
 
92
 
93
- pulseBtn.addEventListener('click', async () => {
94
- pulseBtn.disabled = true;
95
- pulseBtn.innerText = "Scanning...";
96
  try {
97
- const res = await fetch('/api/usecase/pulse', { method: 'POST' });
98
- const data = await res.json();
99
- if (data.success) {
100
- document.getElementById('logs').innerHTML += `[Pulse] Scan complete. Report sent to Telegram.<br>`;
101
- alert("Market Scan Complete! Check your Telegram.");
102
- } else {
103
- alert("Scan failed: " + data.error);
104
- }
 
 
 
105
  } catch (e) { console.error(e); }
106
- finally { pulseBtn.disabled = false; pulseBtn.innerText = "Run Market Scan"; }
107
- });
108
-
109
- offerBtn.addEventListener('click', async () => {
110
- const topic = offerTopic.value;
111
- if (!topic) return alert("Please enter a topic!");
112
- offerBtn.disabled = true;
113
- offerBtn.innerText = "Architecting...";
114
  try {
115
- const res = await fetch('/api/usecase/offer', {
116
- method: 'POST',
117
- headers: { 'Content-Type': 'application/json' },
118
- body: JSON.stringify({ topic })
119
- });
120
- const data = await res.json();
121
- if (data.success) {
122
- document.getElementById('logs').innerHTML += `[Offer] Offer for '${topic}' sent to Telegram.<br>`;
123
- alert("Offer Crafted! Check your Telegram for the details.");
124
- } else {
125
- alert("Offer failed: " + data.error);
126
- }
127
  } catch (e) { console.error(e); }
128
- finally { offerBtn.disabled = false; offerBtn.innerText = "Craft Offer"; }
129
- });
130
 
131
- // Telegram Live Monitor
132
- const tgChat = document.getElementById('tg-chat');
133
- const tgStatus = document.getElementById('tg-status');
134
- const tgSendBtn = document.getElementById('tg-send-btn');
135
- const tgSendInput = document.getElementById('tg-send-input');
136
 
137
  const addChatBubble = (msg) => {
138
  const isIn = msg.direction === 'IN';
139
- const time = new Date(msg.ts).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' });
140
  const bubble = document.createElement('div');
141
- bubble.className = `flex ${isIn ? 'justify-start' : 'justify-end'}`;
142
  bubble.innerHTML = `
143
- <div class="max-w-xs px-3 py-2 rounded-xl text-xs ${isIn ? 'bg-gray-800 text-cyan-300' : 'bg-cyan-900 text-white'}">
144
- <div>${msg.text.replace(/</g,'&lt;').replace(/>/g,'&gt;')}</div>
145
- <div class="text-right text-gray-500 text-[10px] mt-1">${time}</div>
146
- </div>`;
147
- // Remove placeholder if present
148
- const placeholder = tgChat.querySelector('p.text-gray-600');
149
- if (placeholder) placeholder.remove();
150
- tgChat.appendChild(bubble);
151
- tgChat.scrollTop = tgChat.scrollHeight;
152
  };
153
 
154
- // Load history
155
- fetch('/api/telegram-messages').then(r => r.json()).then(msgs => {
156
- msgs.reverse().forEach(addChatBubble);
157
- });
158
-
159
- // Connect SSE for real-time updates
160
  const evtSource = new EventSource('/api/telegram-stream');
161
- evtSource.onopen = () => { tgStatus.textContent = '🟒 Live'; tgStatus.className = 'text-xs text-green-400'; };
162
- evtSource.onerror = () => { tgStatus.textContent = 'πŸ”΄ Disconnected'; tgStatus.className = 'text-xs text-red-400'; };
163
- evtSource.onmessage = (e) => { addChatBubble(JSON.parse(e.data)); };
164
-
165
- // Send from dashboard
166
- tgSendBtn.addEventListener('click', async () => {
167
- const msg = tgSendInput.value.trim();
168
- if (!msg) return;
169
- tgSendBtn.disabled = true;
170
  try {
171
  await fetch('/api/send-telegram', {
172
  method: 'POST',
173
  headers: { 'Content-Type': 'application/json' },
174
- body: JSON.stringify({ message: msg })
175
  });
176
- tgSendInput.value = '';
177
  } catch (e) { console.error(e); }
178
- finally { tgSendBtn.disabled = false; }
179
- });
180
- tgSendInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') tgSendBtn.click(); });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  });
 
1
  document.addEventListener('DOMContentLoaded', async () => {
2
+ console.log("VinOS Dashboard Initialized");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
+ // --- State & Helpers ---
5
+ const elements = {
6
+ pulseBtn: document.getElementById('btn-pulse'),
7
+ socialBtn: document.getElementById('btn-social'),
8
+ cmdInput: document.getElementById('input-command'),
9
+ tgMonitor: document.getElementById('tg-monitor'),
10
+ tgInput: document.getElementById('tg-input'),
11
+ tgSend: document.getElementById('tg-send'),
12
+ apiStatusList: document.getElementById('api-status-list'),
13
+ versionLog: document.getElementById('version-log'),
14
+ liveFeed: document.getElementById('live-feed')
15
+ };
16
 
17
+ const addLog = (msg, type = 'system') => {
18
+ const time = new Date().toLocaleTimeString();
19
+ elements.versionLog.innerHTML = `<div class="mb-1"><span class="text-gray-600">[${time}]</span> <span class="text-purple-400">${msg}</span></div>` + elements.versionLog.innerHTML;
20
+ };
21
 
22
+ // --- Data Fetching ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
+ const updateStats = (db) => {
25
+ document.getElementById('stat-experiments').innerText = db.active_sprints?.length || 0;
26
+ document.getElementById('stat-offers').innerText = db.playbooks?.length || 0;
27
+ // Mocking some growth for aesthetic
28
+ document.getElementById('stat-reach').innerText = (Math.random() * 5 + 1.2).toFixed(1) + 'k';
29
+ };
30
 
31
+ const fetchStatus = async () => {
 
 
32
  try {
33
+ const res = await fetch('/api/status');
34
+ const status = await res.json();
35
+ elements.apiStatusList.innerHTML = Object.entries(status).map(([key, ok]) => `
36
+ <div class="flex items-center justify-between opacity-80">
37
+ <span class="capitalize">${key}</span>
38
+ <span class="flex items-center gap-1 ${ok ? 'text-green-400' : 'text-red-400'}">
39
+ <span class="w-1.5 h-1.5 rounded-full ${ok ? 'bg-green-400' : 'bg-red-400'}"></span>
40
+ ${ok ? 'Connected' : 'Error'}
41
+ </span>
42
+ </div>
43
+ `).join('');
44
  } catch (e) { console.error(e); }
45
+ };
46
+
47
+ const fetchLogs = async () => {
 
 
 
 
 
48
  try {
49
+ const res = await fetch('/api/telegram-messages');
50
+ const msgs = await res.json();
51
+ elements.tgMonitor.innerHTML = '';
52
+ msgs.reverse().forEach(addChatBubble);
 
 
 
 
 
 
 
 
53
  } catch (e) { console.error(e); }
54
+ };
 
55
 
56
+ // --- Telegram Logic ---
 
 
 
 
57
 
58
  const addChatBubble = (msg) => {
59
  const isIn = msg.direction === 'IN';
 
60
  const bubble = document.createElement('div');
61
+ bubble.className = `p-2 rounded-lg break-words ${isIn ? 'bg-white/5 border border-white/5 text-blue-300 mr-4' : 'bg-blue-600/20 border border-blue-500/20 text-white ml-4'}`;
62
  bubble.innerHTML = `
63
+ <div class="font-bold opacity-50 mb-1" style="font-size: 8px;">${isIn ? 'INBOUND' : 'OUTBOUND'}</div>
64
+ <div>${msg.text.replace(/<[^>]*>?/gm, '')}</div>
65
+ `;
66
+ elements.tgMonitor.appendChild(bubble);
67
+ elements.tgMonitor.scrollTop = elements.tgMonitor.scrollHeight;
 
 
 
 
68
  };
69
 
70
+ // Connect SSE
 
 
 
 
 
71
  const evtSource = new EventSource('/api/telegram-stream');
72
+ evtSource.onmessage = (e) => addChatBubble(JSON.parse(e.data));
73
+
74
+ // Send logic
75
+ const sendTg = async () => {
76
+ const text = elements.tgInput.value.trim();
77
+ if (!text) return;
78
+ elements.tgSend.disabled = true;
 
 
79
  try {
80
  await fetch('/api/send-telegram', {
81
  method: 'POST',
82
  headers: { 'Content-Type': 'application/json' },
83
+ body: JSON.stringify({ message: text })
84
  });
85
+ elements.tgInput.value = '';
86
  } catch (e) { console.error(e); }
87
+ finally { elements.tgSend.disabled = false; }
88
+ };
89
+
90
+ elements.tgSend.onclick = sendTg;
91
+ elements.tgInput.onkeydown = (e) => e.key === 'Enter' && sendTg();
92
+
93
+ // --- Action Button Logic ---
94
+
95
+ elements.pulseBtn.onclick = async () => {
96
+ addLog("Niche Pulse Scan Initiated...");
97
+ await fetch('/api/usecase/pulse', { method: 'POST' });
98
+ alert("Pulse started! Check Telegram for real-time progress.");
99
+ };
100
+
101
+ elements.socialBtn.onclick = async () => {
102
+ addLog("Social Market Verification Started...");
103
+ // This triggers a generic check in the current version
104
+ await fetch('/api/send-telegram', {
105
+ method: 'POST',
106
+ headers: { 'Content-Type': 'application/json' },
107
+ body: JSON.stringify({ message: "RUN SOCIAL RESEARCH" })
108
+ });
109
+ alert("Social Verification active. Vin is analyzing X/YouTube.");
110
+ };
111
+
112
+ // Command Input
113
+ elements.cmdInput.onkeydown = async (e) => {
114
+ if (e.key === 'Enter') {
115
+ const cmd = elements.cmdInput.value.trim();
116
+ if (!cmd) return;
117
+ addLog(`Executing: ${cmd}`);
118
+ await fetch('/api/send-telegram', {
119
+ method: 'POST',
120
+ headers: { 'Content-Type': 'application/json' },
121
+ body: JSON.stringify({ message: cmd })
122
+ });
123
+ elements.cmdInput.value = '';
124
+ }
125
+ };
126
+
127
+ // --- Initial Load ---
128
+ fetchStatus();
129
+ fetchLogs();
130
+ setInterval(fetchStatus, 30000);
131
+
132
+ // Simulation of Version History
133
+ addLog("VinOS Core v2.1.0 Loaded");
134
+ addLog("GitHub Persistence: Enabled");
135
+ addLog("Social Engager: Ready");
136
+
137
  });
public/index.html CHANGED
@@ -3,101 +3,116 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>VinOS Control Center</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
 
8
  </head>
9
- <body class="bg-gray-950 text-gray-100 font-sans p-8">
10
- <div class="max-w-5xl mx-auto">
11
- <header class="mb-8 border-b border-gray-800 pb-4 flex justify-between items-center">
 
12
  <div>
13
- <h1 class="text-3xl font-bold text-blue-500 tracking-tight">VinOS</h1>
14
- <p class="text-gray-400 text-sm mt-1">Infinite Arbitrage & Agentic Control Center</p>
15
  </div>
16
- <div id="profile-badge" class="bg-gray-800 px-4 py-2 rounded-lg text-sm border border-gray-700">
17
- Loading profile...
 
 
 
 
 
18
  </div>
19
  </header>
20
 
21
- <main class="grid grid-cols-1 md:grid-cols-2 gap-6">
22
- <section class="bg-gray-900 p-6 rounded-xl border border-gray-800 shadow-lg">
23
- <h2 class="text-xl font-semibold mb-4 text-green-400 flex items-center">
24
- <span class="w-2 h-2 bg-green-400 rounded-full mr-2 animate-pulse"></span> Active Sprints
25
- </h2>
26
- <div id="sprints-container" class="space-y-3">
27
- <p class="text-gray-500 text-sm">Fetching from local memory...</p>
28
- </div>
29
- </section>
 
 
 
 
 
 
 
 
 
 
30
 
31
- <section class="bg-gray-900 p-6 rounded-xl border border-gray-800 shadow-lg">
32
- <h2 class="text-xl font-semibold mb-4 text-orange-400">Token Gashapon (Nano Banana)</h2>
33
- <div class="space-y-4">
34
- <input type="text" id="gashapon-prompt" placeholder="Describe your gashapon idea..."
35
- class="w-full bg-black border border-gray-700 rounded-lg p-3 text-sm focus:outline-none focus:border-orange-500 transition-colors">
36
- <button id="generate-btn" class="w-full bg-orange-600 hover:bg-orange-500 text-white font-bold py-3 rounded-lg transition-all shadow-lg active:scale-95">
37
- Generate Gashapon
38
- </button>
39
- <div id="gashapon-result" class="mt-4 hidden animate-in fade-in duration-500">
40
- <img id="gashapon-img" src="" alt="Gashapon Result" class="rounded-lg border border-gray-700 w-full">
 
 
 
 
 
 
41
  </div>
42
  </div>
43
- </section>
44
 
45
- <section class="bg-gray-900 p-6 rounded-xl border border-gray-800 shadow-lg">
46
- <h2 class="text-xl font-semibold mb-4 text-blue-400">API Connectivity Status</h2>
47
- <div id="status-container" class="grid grid-cols-2 gap-3 text-xs">
48
- <!-- Status items injected here -->
 
 
 
 
 
 
 
 
 
49
  </div>
50
- </section>
51
 
52
- <section class="bg-gray-900 p-6 rounded-xl border border-gray-800 shadow-lg md:col-span-2">
53
- <h2 class="text-xl font-semibold mb-4 text-pink-400">Strategy Lab (Use Cases)</h2>
54
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
55
- <div class="p-4 bg-gray-800 rounded-lg border border-gray-700">
56
- <h3 class="font-medium text-pink-300 mb-2">Daily Pulse</h3>
57
- <p class="text-xs text-gray-400 mb-4">Scan for market opportunities and send report to Telegram.</p>
58
- <button id="pulse-btn" class="w-full bg-pink-700 hover:bg-pink-600 text-white text-sm py-2 rounded transition-colors">
59
- Run Market Scan
60
- </button>
61
- </div>
62
- <div class="p-4 bg-gray-800 rounded-lg border border-gray-700">
63
- <h3 class="font-medium text-yellow-300 mb-2">Offer Architect</h3>
64
- <p class="text-xs text-gray-400 mb-2">Generate a beta offer and draft payment link.</p>
65
- <input type="text" id="offer-topic" placeholder="e.g. AI Content Agency"
66
- class="w-full bg-black border border-gray-700 rounded p-2 text-xs mb-3 focus:border-yellow-500 outline-none">
67
- <button id="offer-btn" class="w-full bg-yellow-700 hover:bg-yellow-600 text-white text-sm py-2 rounded transition-colors">
68
- Craft Offer
69
- </button>
70
  </div>
71
  </div>
72
- </section>
73
 
74
- <section class="bg-gray-900 p-6 rounded-xl border border-gray-800 shadow-lg">
75
- <h2 class="text-xl font-semibold mb-4 text-purple-400">System Logs & Webhooks</h2>
76
- <div class="bg-black rounded-lg p-4 font-mono text-xs text-green-500 h-48 overflow-y-auto" id="logs">
77
- [System] Boot sequence initiated...<br>
 
 
78
  </div>
79
- </section>
80
 
81
- <!-- Telegram Message Monitor - full width -->
82
- <section class="bg-gray-900 p-6 rounded-xl border border-cyan-900 shadow-lg md:col-span-2">
83
- <div class="flex items-center justify-between mb-4">
84
- <h2 class="text-xl font-semibold text-cyan-400 flex items-center gap-2">
85
- <span class="w-2 h-2 bg-cyan-400 rounded-full animate-pulse"></span>
86
- Telegram Live Monitor
87
- </h2>
88
- <span class="text-xs text-gray-500" id="tg-status">Connecting...</span>
89
- </div>
90
- <div id="tg-chat" class="bg-black rounded-lg p-4 font-mono text-xs h-64 overflow-y-auto flex flex-col gap-2 border border-gray-800">
91
- <p class="text-gray-600 italic text-center mt-auto">Messages will appear here in real-time.</p>
92
- </div>
93
- <div class="flex gap-2 mt-3">
94
- <input type="text" id="tg-send-input" placeholder="Reply to Dee via Telegram..."
95
- class="flex-1 bg-black border border-gray-700 rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-cyan-500 transition-colors">
96
- <button id="tg-send-btn" class="bg-cyan-700 hover:bg-cyan-600 text-white px-5 py-2 rounded-lg text-sm font-bold transition-colors">
97
- Send
98
- </button>
99
  </div>
100
- </section>
101
  </main>
102
  </div>
103
  <script src="app.js"></script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>VinOS | Growth Orchestrator</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="style.css">
9
  </head>
10
+ <body class="p-4 md:p-8">
11
+ <div class="max-w-7xl mx-auto">
12
+ <!-- Header -->
13
+ <header class="flex justify-between items-center mb-12">
14
  <div>
15
+ <h1 class="text-4xl font-bold tracking-tighter">Vin<span class="text-purple-500">OS</span></h1>
16
+ <p class="text-gray-400 text-sm">Infinite Money Glitch Control Room</p>
17
  </div>
18
+ <div class="flex items-center gap-4">
19
+ <div id="status-badge" class="glass-card flex items-center gap-2 px-4 py-2 text-xs">
20
+ <span class="pulse-dot"></span> System Online
21
+ </div>
22
+ <div id="version-badge" class="glass-card px-4 py-2 text-xs text-gray-500">
23
+ v2.1.0-Social
24
+ </div>
25
  </div>
26
  </header>
27
 
28
+ <!-- Top Stats Row -->
29
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
30
+ <div class="glass-card">
31
+ <p class="text-xs text-gray-400 uppercase tracking-widest font-semibold mb-1">Total Experiments</p>
32
+ <p class="stat-value" id="stat-experiments">24</p>
33
+ </div>
34
+ <div class="glass-card">
35
+ <p class="text-xs text-gray-400 uppercase tracking-widest font-semibold mb-1">Active Offers</p>
36
+ <p class="stat-value text-blue-400" id="stat-offers">12</p>
37
+ </div>
38
+ <div class="glass-card">
39
+ <p class="text-xs text-gray-400 uppercase tracking-widest font-semibold mb-1">Social Reach</p>
40
+ <p class="stat-value text-purple-400" id="stat-reach">1.2k</p>
41
+ </div>
42
+ <div class="glass-card">
43
+ <p class="text-xs text-gray-400 uppercase tracking-widest font-semibold mb-1">Model Cost (MTD)</p>
44
+ <p class="stat-value text-pink-400" id="stat-cost">$0.42</p>
45
+ </div>
46
+ </div>
47
 
48
+ <main class="grid grid-cols-1 lg:grid-cols-3 gap-8">
49
+ <!-- Left: Strategy Lab -->
50
+ <div class="lg:col-span-2 flex flex-col gap-8">
51
+ <!-- Deployment & Social Sync -->
52
+ <div class="glass-card">
53
+ <h2 class="text-xl font-bold mb-6 flex items-center gap-2">
54
+ <svg class="w-5 h-5 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg>
55
+ Orchestration Command
56
+ </h2>
57
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
58
+ <button id="btn-pulse" class="btn-primary">⚑ Run Daily Pulse</button>
59
+ <button id="btn-social" class="btn-primary" style="background: linear-gradient(135deg, #10b981, #3b82f6);">🌍 Verify Social Market</button>
60
+ </div>
61
+ <div class="mt-6">
62
+ <input type="text" id="input-command" placeholder="Type a command for Vin (e.g. Architect offer for AI PDF tools)..."
63
+ class="w-full bg-white/5 border border-white/10 rounded-xl p-4 text-sm focus:outline-none focus:border-purple-500 transition-all">
64
  </div>
65
  </div>
 
66
 
67
+ <!-- Sales & Live Feed -->
68
+ <div class="glass-card flex-1">
69
+ <h2 class="text-xl font-bold mb-4">Live Experiment Feed</h2>
70
+ <div id="live-feed" class="space-y-4 h-96 overflow-y-auto scroll-thin">
71
+ <!-- Feed items injected here -->
72
+ <div class="p-4 bg-white/5 rounded-xl border border-white/5 flex items-center justify-between">
73
+ <div>
74
+ <p class="text-sm font-semibold">Offer: AI Presentation Beta</p>
75
+ <p class="text-xs text-gray-500">Deployed to Whop β€’ 2 mins ago</p>
76
+ </div>
77
+ <span class="text-xs font-bold text-green-400">+ $49.00</span>
78
+ </div>
79
+ </div>
80
  </div>
81
+ </div>
82
 
83
+ <!-- Right: System & History -->
84
+ <div class="flex flex-col gap-8">
85
+ <!-- Connectivity -->
86
+ <div class="glass-card font-mono text-xs">
87
+ <h2 class="text-lg font-bold mb-4 font-sans">API Health</h2>
88
+ <div id="api-status-list" class="space-y-2">
89
+ <!-- Status injected -->
 
 
 
 
 
 
 
 
 
 
 
90
  </div>
91
  </div>
 
92
 
93
+ <!-- Version History (from GitHub) -->
94
+ <div class="glass-card flex-1">
95
+ <h2 class="text-lg font-bold mb-4">Version Log</h2>
96
+ <div id="version-log" class="text-xs space-y-3 font-mono text-gray-400 h-64 overflow-y-auto scroll-thin">
97
+ <!-- Logs injected -->
98
+ </div>
99
  </div>
 
100
 
101
+ <!-- Telegram Bridge -->
102
+ <div class="glass-card border-blue-500/30">
103
+ <div class="flex items-center justify-between mb-4">
104
+ <h2 class="font-bold text-blue-400">Telegram Control</h2>
105
+ <span class="text-[10px] bg-blue-500/20 text-blue-300 px-2 py-0.5 rounded">Connected</span>
106
+ </div>
107
+ <div id="tg-monitor" class="h-48 overflow-y-auto scroll-thin text-[11px] space-y-2 mb-4">
108
+ <!-- Chat history -->
109
+ </div>
110
+ <div class="flex gap-2">
111
+ <input type="text" id="tg-input" placeholder="Quick message..." class="flex-1 bg-white/5 border border-white/10 rounded-lg p-2 text-xs">
112
+ <button id="tg-send" class="bg-blue-600 px-3 rounded-lg text-xs">Send</button>
113
+ </div>
 
 
 
 
 
114
  </div>
115
+ </div>
116
  </main>
117
  </div>
118
  <script src="app.js"></script>
public/style.css ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=Outfit:wght@400;700&display=swap');
2
+
3
+ :root {
4
+ --bg-dark: #0a0b10;
5
+ --glass-bg: rgba(255, 255, 255, 0.03);
6
+ --glass-border: rgba(255, 255, 255, 0.1);
7
+ --accent-purple: #8b5cf6;
8
+ --accent-blue: #3b82f6;
9
+ --accent-pink: #ec4899;
10
+ }
11
+
12
+ body {
13
+ background-color: var(--bg-dark);
14
+ background-image:
15
+ radial-gradient(at 0% 0%, rgba(139, 92, 246, 0.15) 0, transparent 50%),
16
+ radial-gradient(at 100% 100%, rgba(59, 130, 246, 0.15) 0, transparent 50%);
17
+ color: #e2e8f0;
18
+ font-family: 'Inter', sans-serif;
19
+ min-height: 100vh;
20
+ margin: 0;
21
+ }
22
+
23
+ h1, h2, h3 {
24
+ font-family: 'Outfit', sans-serif;
25
+ }
26
+
27
+ .glass-card {
28
+ background: var(--glass-bg);
29
+ backdrop-filter: blur(12px);
30
+ -webkit-backdrop-filter: blur(12px);
31
+ border: 1px solid var(--glass-border);
32
+ border-radius: 24px;
33
+ padding: 24px;
34
+ transition: transform 0.3s ease, border-color 0.3s ease;
35
+ }
36
+
37
+ .glass-card:hover {
38
+ border-color: rgba(255, 255, 255, 0.2);
39
+ }
40
+
41
+ .stat-value {
42
+ font-size: 2rem;
43
+ font-weight: 700;
44
+ background: linear-gradient(to right, var(--accent-blue), var(--accent-purple));
45
+ -webkit-background-clip: text;
46
+ -webkit-text-fill-color: transparent;
47
+ }
48
+
49
+ .btn-primary {
50
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
51
+ color: white;
52
+ border: none;
53
+ border-radius: 12px;
54
+ padding: 12px 24px;
55
+ font-weight: 600;
56
+ cursor: pointer;
57
+ transition: box-shadow 0.3s ease, transform 0.2s ease;
58
+ }
59
+
60
+ .btn-primary:hover {
61
+ box-shadow: 0 0 20px rgba(59, 130, 246, 0.4);
62
+ transform: translateY(-2px);
63
+ }
64
+
65
+ .btn-primary:active {
66
+ transform: scale(0.98);
67
+ }
68
+
69
+ .pulse-dot {
70
+ width: 8px;
71
+ height: 8px;
72
+ background: #10b981;
73
+ border-radius: 50%;
74
+ box-shadow: 0 0 10px #10b981;
75
+ display: inline-block;
76
+ animation: pulse 2s infinite;
77
+ }
78
+
79
+ @keyframes pulse {
80
+ 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
81
+ 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(16, 185, 129, 0); }
82
+ 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
83
+ }
84
+
85
+ .scroll-thin::-webkit-scrollbar {
86
+ width: 4px;
87
+ }
88
+
89
+ .scroll-thin::-webkit-scrollbar-thumb {
90
+ background: rgba(255, 255, 255, 0.1);
91
+ border-radius: 10px;
92
+ }
server.js CHANGED
@@ -8,6 +8,16 @@ const path = require('path');
8
  const fs = require('fs');
9
  const memory = require('./skills/memory');
10
  const apiCaller = require('./skills/api_caller');
 
 
 
 
 
 
 
 
 
 
11
 
12
  const app = express();
13
  app.use(cors());
@@ -114,6 +124,11 @@ const voiceTranscriber = require('./skills/voice_transcriber');
114
  const intentRouter = require('./skills/intent_router');
115
  const conversationMemory = require('./skills/conversation_memory');
116
  const playbookManager = require('./skills/playbook_manager');
 
 
 
 
 
117
 
118
  // Helper to handle resolved intents
119
  async function handleVinIntent(chatId, from, userText, confirmed = false) {
@@ -136,14 +151,42 @@ async function handleVinIntent(chatId, from, userText, confirmed = false) {
136
  // 2. Route to appropriate skill
137
  switch (intent) {
138
  case 'remember':
139
- const playbookId = playbookManager.savePlaybook(`User memory trigger`, params, ['user-defined']);
140
- await apiCaller.sendTelegramMessage(chatId, `🧠 <b>Playbook Saved</b>\nI'll remember this approach for the future.\n<i>Trigger: ${params.substring(0, 50)}...</i>`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  break;
142
 
143
  case 'recall':
144
  const playbooks = playbookManager.searchPlaybooks(params);
145
  if (playbooks.length > 0) {
146
- const results = playbooks.slice(0, 2).map(pb => `πŸ“Œ <b>${pb.trigger}</b>\n${pb.solution}`).join('\n\n');
147
  await apiCaller.sendTelegramMessage(chatId, `πŸ” <b>Found in Playbooks:</b>\n\n${results}`);
148
  } else {
149
  await apiCaller.sendTelegramMessage(chatId, `🀷 No playbooks found for "${params}".`);
@@ -244,6 +287,142 @@ app.post('/api/telegram-webhook', async (req, res) => {
244
  const from = message.from?.first_name || 'User';
245
  let userText = message.text;
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  // Handle /auto on/off commands
248
  if (userText && userText.toLowerCase().startsWith('/auto')) {
249
  const mode = userText.toLowerCase().includes('on') ? true : false;
@@ -304,7 +483,48 @@ app.post('/api/telegram-webhook', async (req, res) => {
304
  })().catch(err => console.error("Webhook processing error:", err));
305
  });
306
 
307
- const PORT = process.env.PORT || 7860;
308
- app.listen(PORT, '0.0.0.0', () => {
309
- console.log(`VinOS Core Online: http://0.0.0.0:${PORT}`);
310
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  const fs = require('fs');
9
  const memory = require('./skills/memory');
10
  const apiCaller = require('./skills/api_caller');
11
+ const playbookManager = require('./skills/playbook_manager');
12
+ const conversationMemory = require('./skills/conversation_memory');
13
+ const githubStorage = require('./skills/github_storage');
14
+ const setTelegramMenu = require('./skills/set_telegram_menu');
15
+ const socialResearcher = require('./skills/social_researcher');
16
+ const productDeployer = require('./skills/product_deployer');
17
+ const reportGen = require('./skills/report_generator');
18
+ const socialEngager = require('./skills/social_engager');
19
+ const hfStorage = require('./skills/hf_storage');
20
+ const trelloManager = require('./skills/trello_manager');
21
 
22
  const app = express();
23
  app.use(cors());
 
124
  const intentRouter = require('./skills/intent_router');
125
  const conversationMemory = require('./skills/conversation_memory');
126
  const playbookManager = require('./skills/playbook_manager');
127
+ const versionControl = require('./skills/version_control');
128
+ const autoCron = require('./skills/infinite_money_cron');
129
+
130
+ // Start the autonomous routines
131
+ autoCron.startJobs();
132
 
133
  // Helper to handle resolved intents
134
  async function handleVinIntent(chatId, from, userText, confirmed = false) {
 
151
  // 2. Route to appropriate skill
152
  switch (intent) {
153
  case 'remember':
154
+ await apiCaller.sendTelegramMessage(chatId, "🧠 <i>Designing playbook for:</i> " + params);
155
+ const playbookPrompt = `User wants me to remember this instructions or insight: "${params}"
156
+ Create a structured playbook including:
157
+ 1. Trigger (when to use this)
158
+ 2. Solution (step-by-step logic)
159
+ 3. Tags (categories)
160
+
161
+ Format as JSON: { "trigger": "...", "solution": "...", "tags": ["..."] }
162
+ Respond ONLY with the JSON.`;
163
+
164
+ const pbGen = await apiCaller.callOpenRouter([{ role: "user", content: playbookPrompt }]);
165
+ if (pbGen.success) {
166
+ try {
167
+ const pbData = JSON.parse(pbGen.data.replace(/```json|```/g, ''));
168
+ playbookManager.savePlaybook(pbData.trigger, pbData.solution, pbData.tags);
169
+
170
+ // Option A: Save to Knowledge Bank (Granular .md)
171
+ const pbId = `pb_${Date.now()}`;
172
+ await hfStorage.saveRecord('playbooks', pbId, {
173
+ title: `Playbook: ${pbData.trigger}`,
174
+ timestamp: new Date().toISOString(),
175
+ niche: pbData.tags?.[0] || "General"
176
+ }, `### TRIGGER: ${pbData.trigger}\n\n### SOLUTION:\n${pbData.solution}\n\n### TAGS:\n${(pbData.tags || []).join(', ')}`);
177
+
178
+ await apiCaller.sendTelegramMessage(chatId, `βœ… <b>Playbook Generated & Saved</b>\n<b>Trigger:</b> ${pbData.trigger}\n\nI've also archived this in your <b>HF Knowledge Bank</b>.`);
179
+ } catch (e) {
180
+ await apiCaller.sendTelegramMessage(chatId, "❌ Failed to parse playbook JSON. Saving raw instead.");
181
+ playbookManager.savePlaybook(params, "Manual note", ["raw"]);
182
+ }
183
+ }
184
  break;
185
 
186
  case 'recall':
187
  const playbooks = playbookManager.searchPlaybooks(params);
188
  if (playbooks.length > 0) {
189
+ const results = playbooks.slice(0, 3).map(pb => `πŸ“Œ <b>${pb.trigger}</b>\n${pb.solution}`).join('\n\n');
190
  await apiCaller.sendTelegramMessage(chatId, `πŸ” <b>Found in Playbooks:</b>\n\n${results}`);
191
  } else {
192
  await apiCaller.sendTelegramMessage(chatId, `🀷 No playbooks found for "${params}".`);
 
287
  const from = message.from?.first_name || 'User';
288
  let userText = message.text;
289
 
290
+ // --- Core Action Commands ---
291
+
292
+ if (userText === '/commit') {
293
+ const res = versionControl.commitChanges("Manual user commit");
294
+ if (res.success) {
295
+ await apiCaller.sendTelegramMessage(chatId, `βœ… <b>Version Logged</b>\nMessage: ${res.message}\nCommit: ${res.version}`);
296
+ } else {
297
+ await apiCaller.sendTelegramMessage(chatId, `⚠️ ${res.error}`);
298
+ }
299
+ return;
300
+ }
301
+
302
+ if (userText === '/revert') {
303
+ const res = versionControl.revertToLastWorking();
304
+ if (res.success) {
305
+ await apiCaller.sendTelegramMessage(chatId, `βͺ <b>Rolled Back</b>\nReverted changes to the last stable version.`);
306
+ } else {
307
+ await apiCaller.sendTelegramMessage(chatId, `⚠️ Revert failed: ${res.error}`);
308
+ }
309
+ return;
310
+ }
311
+
312
+ if (userText === '/log') {
313
+ const res = versionControl.getLog();
314
+ await apiCaller.sendTelegramMessage(chatId, `πŸ“œ <b>Version History:</b>\n\n<pre>${res.log}</pre>`);
315
+ return;
316
+ }
317
+
318
+ if (userText === '/playbooks') {
319
+ const allPbs = playbookManager.getAllPlaybooks();
320
+ if (allPbs.length === 0) {
321
+ await apiCaller.sendTelegramMessage(chatId, "πŸ“‰ No playbooks saved yet. Use 'remember [instruction]' to create one.");
322
+ } else {
323
+ const list = allPbs.map(pb => `β€’ <b>${pb.trigger}</b> (${pb.tags.join(', ')})`).join('\n');
324
+ await apiCaller.sendTelegramMessage(chatId, `🧠 <b>All Playbooks:</b>\n\n${list}\n\n<i>Reply with 'recall [keyword]' to see details.</i>`);
325
+ }
326
+ return;
327
+ }
328
+
329
+ if (userText === '/recent') {
330
+ const db = memory.readDB();
331
+ const convos = db.conversations || {};
332
+ const recentKeys = Object.keys(convos).slice(-5);
333
+ if (recentKeys.length === 0) {
334
+ await apiCaller.sendTelegramMessage(chatId, "🀷 No recent conversations found.");
335
+ } else {
336
+ const list = recentKeys.map(id => {
337
+ const lastMsg = convos[id][convos[id].length - 1];
338
+ return `πŸ†” <code>${id}</code>: ${lastMsg.content.substring(0, 40)}...`;
339
+ }).join('\n');
340
+ await apiCaller.sendTelegramMessage(chatId, `πŸ’¬ <b>Recent Conversations:</b>\n\n${list}`);
341
+ }
342
+ return;
343
+ }
344
+
345
+ if (userText && userText.toLowerCase().startsWith('/mckinsey')) {
346
+ const niche = userText.split(' ').slice(1).join(' ') || "AI Digital Strategy Consulting";
347
+ await apiCaller.sendTelegramMessage(chatId, `πŸ“Š <b>Strategic McKinsey Phase Started:</b> ${niche}\nSynthesizing market insights into a professional PDF...`);
348
+
349
+ // Re-use logic from mission runner
350
+ const prompt = `Analyze the niche "${niche}". Identify the 3 biggest pain points for SMBs in 2026. Architect a "Gashapon-style" Low-Friction Offer. Structure as a professional McKinsey report.`;
351
+ const res = await apiCaller.callGroq([{ role: "user", content: prompt }]);
352
+ if (res.success) {
353
+ const reportFileName = `VinOS_McKinsey_${Date.now()}.pdf`;
354
+ const filePath = await reportGen.generateMcKinseyReport(`VinOS Strategic Analysis: ${niche}`, res.data, reportFileName);
355
+ await apiCaller.sendTelegramDocument(chatId, filePath, `<b>VinOS Strategic Mastery</b>\nReport generated for: ${niche}`);
356
+
357
+ // Option A: Save to Knowledge Bank (Granular .md)
358
+ const recordId = `mckinsey_${Date.now()}`;
359
+ await hfStorage.saveRecord('insights', recordId, { title: `Strategic Analysis: ${niche}`, niche, timestamp: new Date().toISOString() }, res.data);
360
+
361
+ // Option B: Sync to Trello (Visual Board)
362
+ if (process.env.TRELLO_API_KEY) {
363
+ const boardRes = await trelloManager.createBoard(`VinOS Mission: ${niche}`);
364
+ if (boardRes.success) {
365
+ const lists = await trelloManager.setupStrategyLists(boardRes.boardId);
366
+ if (lists.success) {
367
+ const card = await trelloManager.createCard(lists.lists[0].id, "Strategic Report", "McKinsey report generated for the niche.");
368
+ if (card.success) await trelloManager.attachReport(card.cardId, filePath);
369
+ }
370
+ }
371
+ }
372
+ } else {
373
+ await apiCaller.sendTelegramMessage(chatId, `❌ Report failed: ${res.error}`);
374
+ }
375
+ return;
376
+ }
377
+
378
+ if (userText && userText.toLowerCase().startsWith('/glitch')) {
379
+ const niche = userText.split(' ').slice(1).join(' ') || "AI Automation";
380
+ await apiCaller.sendTelegramMessage(chatId, `πŸ’‘ <b>Glitch Architecting Started:</b> ${niche}\nRunning Design Thinking loop for low-friction revenue...`);
381
+ const prompt = `Apply Design Thinking (Empathize, Define, Ideate, Prototype) to create an "Infinite Money Glitch" (low-cost, high-automation digital offer) for the niche: ${niche}.`;
382
+ const res = await apiCaller.callOpenRouter([{ role: "user", content: prompt }]);
383
+ if (res.success) {
384
+ await apiCaller.sendTelegramMessage(chatId, `✨ <b>Offer Architecture Ready:</b>\n\n${res.data}`);
385
+ } else {
386
+ await apiCaller.sendTelegramMessage(chatId, "❌ Glitch ideation failed. The brain is busy.");
387
+ }
388
+ return;
389
+ }
390
+
391
+ if (userText && userText.toLowerCase().startsWith('/social')) {
392
+ const niche = userText.split(' ').slice(1).join(' ') || "AI tools for productivity";
393
+ await apiCaller.sendTelegramMessage(chatId, `πŸ” <b>Deep Scan Started:</b> ${niche}\nAnalyzing X and YouTube for pain points...`);
394
+ const res = await socialResearcher.researchNiche(niche);
395
+ if (res.success) {
396
+ await apiCaller.sendTelegramMessage(chatId, `βœ… <b>Research Complete</b>\n${res.summary}\n\n<i>Found ${res.data.youtube.length} insights from video comments.</i>`);
397
+ } else {
398
+ await apiCaller.sendTelegramMessage(chatId, `❌ Research failed: ${res.error}`);
399
+ }
400
+ return;
401
+ }
402
+
403
+ if (userText && userText.toLowerCase().startsWith('/deploy')) {
404
+ // Usage: /deploy [whop|mayar] [name] [price]
405
+ const args = userText.split(' ');
406
+ const platform = args[1]?.toLowerCase();
407
+ const name = args.slice(2, -1).join(' ') || "Digital Product";
408
+ const price = args[args.length - 1] || "100";
409
+
410
+ await apiCaller.sendTelegramMessage(chatId, `πŸš€ <b>Deploying to ${platform}...</b>`);
411
+
412
+ if (platform === 'whop') {
413
+ const res = await productDeployer.deployToWhop(name, "Automated via VinOS", price);
414
+ if (res.success) await apiCaller.sendTelegramMessage(chatId, `✨ <b>Live on Whop!</b>\nURL: ${res.url}`);
415
+ else await apiCaller.sendTelegramMessage(chatId, `❌ Whop failed: ${res.error}`);
416
+ } else if (platform === 'mayar') {
417
+ const res = await productDeployer.deployToMayar(name, parseInt(price), "Automated via VinOS");
418
+ if (res.success) await apiCaller.sendTelegramMessage(chatId, `✨ <b>Mayar Link Ready!</b>\nURL: ${res.url}`);
419
+ else await apiCaller.sendTelegramMessage(chatId, `❌ Mayar failed: ${res.error}`);
420
+ } else {
421
+ await apiCaller.sendTelegramMessage(chatId, "❓ Specify /deploy whop [name] [price] or /deploy mayar [name] [price]");
422
+ }
423
+ return;
424
+ }
425
+
426
  // Handle /auto on/off commands
427
  if (userText && userText.toLowerCase().startsWith('/auto')) {
428
  const mode = userText.toLowerCase().includes('on') ? true : false;
 
483
  })().catch(err => console.error("Webhook processing error:", err));
484
  });
485
 
486
+ // Startup: Sync from GitHub & Register Menu
487
+ const DB_LOCAL = path.join(__dirname, 'database/local_db.json');
488
+ const PB_LOCAL = path.join(__dirname, 'database/playbooks.json');
489
+
490
+ async function initializeVinOS() {
491
+ console.log("πŸš€ Initializing VinOS...");
492
+
493
+ // 1. Sync from GitHub (Ground Truth)
494
+ await githubStorage.syncFromGitHub(DB_LOCAL, 'local_db.json');
495
+ await githubStorage.syncFromGitHub(PB_LOCAL, 'playbooks.json');
496
+
497
+ // 2. Set Telegram Menu
498
+ await setTelegramMenu();
499
+
500
+ // 3. Start Server
501
+ const PORT = process.env.PORT || 3000;
502
+ app.listen(PORT, () => {
503
+ console.log(`VinOS Core Online: http://0.0.0.0:${PORT}`);
504
+ autoCron.startJobs();
505
+ });
506
+ }
507
+
508
+ // Auto-Sync to GitHub on every DB write
509
+ const originalWriteDB = memory.writeDB;
510
+ memory.writeDB = (data) => {
511
+ const success = originalWriteDB(data);
512
+ if (success) githubStorage.saveToGitHub(DB_LOCAL, 'local_db.json').catch(e => console.error(e));
513
+ return success;
514
+ };
515
+
516
+ const originalAddMessage = conversationMemory.addMessage;
517
+ conversationMemory.addMessage = (chatId, role, content) => {
518
+ const success = originalAddMessage(chatId, role, content);
519
+ if (success) githubStorage.saveToGitHub(DB_LOCAL, 'local_db.json').catch(e => console.error(e));
520
+ return success;
521
+ };
522
+
523
+ const originalSavePB = playbookManager.savePlaybook;
524
+ playbookManager.savePlaybook = (trigger, solution, tags) => {
525
+ const id = originalSavePB(trigger, solution, tags);
526
+ if (id) githubStorage.saveToGitHub(PB_LOCAL, 'playbooks.json').catch(e => console.error(e));
527
+ return id;
528
+ };
529
+
530
+ initializeVinOS();
skills/api_caller.js CHANGED
@@ -3,6 +3,7 @@ const https = require('https');
3
  const dns = require('dns');
4
  const fs = require('fs');
5
  const path = require('path');
 
6
  const DB_PATH = path.join(__dirname, '../database/local_db.json');
7
  require('dotenv').config();
8
 
@@ -125,22 +126,68 @@ module.exports = {
125
  sendTelegramMessage: async (chatId, message) => {
126
  console.log(`[Telegram] Sending to ${chatId}: ${message.substring(0, 80)}...`);
127
  logTelegramMessage('OUT', chatId, message);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  try {
129
- const response = await axiosIPv4.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
130
- chat_id: chatId,
131
- text: message,
132
- parse_mode: 'HTML'
133
- });
134
- return { success: true, data: response.data };
 
 
135
  } catch (error) {
136
  console.error("[Telegram] API Error:", error.response?.data || error.message);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  return { success: false, error: error.message };
138
  }
139
  },
140
 
141
- // Mayar (Payment Links)
142
- createMayarLink: async (offerDetails) => {
143
- console.log("[Mayar] Creating link:", offerDetails);
144
- return { success: true, url: "https://mayar.id/pay/example" };
145
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  };
 
3
  const dns = require('dns');
4
  const fs = require('fs');
5
  const path = require('path');
6
+ const FormData = require('form-data');
7
  const DB_PATH = path.join(__dirname, '../database/local_db.json');
8
  require('dotenv').config();
9
 
 
126
  sendTelegramMessage: async (chatId, message) => {
127
  console.log(`[Telegram] Sending to ${chatId}: ${message.substring(0, 80)}...`);
128
  logTelegramMessage('OUT', chatId, message);
129
+
130
+ // Telegram max message length is 4096. We chunk at 4000 for safety.
131
+ const CHUNK_SIZE = 4000;
132
+ const chunks = [];
133
+
134
+ if (message.length > CHUNK_SIZE) {
135
+ let current = message;
136
+ while (current.length > 0) {
137
+ chunks.push(current.substring(0, CHUNK_SIZE));
138
+ current = current.substring(CHUNK_SIZE);
139
+ }
140
+ } else {
141
+ chunks.push(message);
142
+ }
143
+
144
  try {
145
+ for (const chunk of chunks) {
146
+ await axiosIPv4.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
147
+ chat_id: chatId,
148
+ text: chunk,
149
+ parse_mode: 'HTML'
150
+ });
151
+ }
152
+ return { success: true };
153
  } catch (error) {
154
  console.error("[Telegram] API Error:", error.response?.data || error.message);
155
+ // Fallback for HTML parse errors (often happens with chunked HTML)
156
+ if (error.response?.data?.description?.includes("can't parse entities")) {
157
+ try {
158
+ for (const chunk of chunks) {
159
+ await axiosIPv4.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
160
+ chat_id: chatId,
161
+ text: chunk.replace(/<[^>]*>?/gm, ''), // Strip tags for fallback
162
+ parse_mode: 'HTML'
163
+ });
164
+ }
165
+ return { success: true, stripped: true };
166
+ } catch (innerError) {
167
+ return { success: false, error: innerError.message };
168
+ }
169
+ }
170
  return { success: false, error: error.message };
171
  }
172
  },
173
 
174
+ // Telegram (Send Documents/PDFs)
175
+ sendTelegramDocument: async (chatId, filePath, caption = "") => {
176
+ const formData = new FormData();
177
+ formData.append('chat_id', chatId);
178
+ formData.append('document', fs.createReadStream(filePath));
179
+ formData.append('caption', caption);
180
+ formData.append('parse_mode', 'HTML');
181
+
182
+ console.log(`[Telegram] Sending document to ${chatId}: ${path.basename(filePath)}`);
183
+ try {
184
+ const response = await axiosIPv4.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendDocument`, formData, {
185
+ headers: formData.getHeaders()
186
+ });
187
+ return { success: true, data: response.data };
188
+ } catch (error) {
189
+ console.error("[Telegram] API Document Error:", error.response?.data || error.message);
190
+ return { success: false, error: error.message };
191
+ }
192
+ },
193
  };
skills/github_storage.js ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ require('dotenv').config();
5
+
6
+ const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
7
+ const GITHUB_REPO = process.env.GITHUB_REPO; // Format: username/repo
8
+ const BRANCH = 'main';
9
+
10
+ /**
11
+ * VinOS GitHub Persistence Skill
12
+ * Allows Vin to survive Hugging Face container restarts by syncing state to a private GitHub repo.
13
+ */
14
+ module.exports = {
15
+ /**
16
+ * Pushes a local file to the GitHub repository.
17
+ */
18
+ saveToGitHub: async (localPath, fileName) => {
19
+ if (!GITHUB_TOKEN || !GITHUB_REPO) {
20
+ console.warn('[GitHub Storage] Missing GITHUB_TOKEN or GITHUB_REPO. Skipping persistence.');
21
+ return false;
22
+ }
23
+
24
+ try {
25
+ const content = fs.readFileSync(localPath, 'utf8');
26
+ const encodedContent = Buffer.from(content).toString('base64');
27
+ const url = `https://api.github.com/repos/${GITHUB_REPO}/contents/${fileName}`;
28
+
29
+ // Check if file exists to get its SHA (required for update)
30
+ let sha;
31
+ try {
32
+ const headRes = await axios.get(url, {
33
+ headers: { 'Authorization': `Bearer ${GITHUB_TOKEN}` }
34
+ });
35
+ sha = headRes.data.sha;
36
+ } catch (e) {
37
+ // File doesn't exist yet, we'll create it
38
+ }
39
+
40
+ const body = {
41
+ message: `VinOS: Auto-save ${fileName} [${new Date().toISOString()}]`,
42
+ content: encodedContent,
43
+ branch: BRANCH
44
+ };
45
+ if (sha) body.sha = sha;
46
+
47
+ await axios.put(url, body, {
48
+ headers: {
49
+ 'Authorization': `Bearer ${GITHUB_TOKEN}`,
50
+ 'Accept': 'application/vnd.github.v3+json'
51
+ }
52
+ });
53
+
54
+ console.log(`[GitHub Storage] Successfully synced ${fileName} to GitHub.`);
55
+ return true;
56
+ } catch (error) {
57
+ console.error(`[GitHub Storage] Error saving ${fileName}:`, error.response?.data || error.message);
58
+ return false;
59
+ }
60
+ },
61
+
62
+ /**
63
+ * Pulls files from GitHub and overwrites local copies on startup.
64
+ */
65
+ syncFromGitHub: async (localPath, fileName) => {
66
+ if (!GITHUB_TOKEN || !GITHUB_REPO) {
67
+ console.warn('[GitHub Storage] No GitHub credentials. Starting with local defaults.');
68
+ return false;
69
+ }
70
+
71
+ try {
72
+ const url = `https://api.github.com/repos/${GITHUB_REPO}/contents/${fileName}?ref=${BRANCH}`;
73
+ const response = await axios.get(url, {
74
+ headers: { 'Authorization': `Bearer ${GITHUB_TOKEN}` }
75
+ });
76
+
77
+ const content = Buffer.from(response.data.content, 'base64').toString('utf8');
78
+ fs.writeFileSync(localPath, content);
79
+ console.log(`[GitHub Storage] Restored ${fileName} from GitHub.`);
80
+ return true;
81
+ } catch (error) {
82
+ if (error.response?.status === 404) {
83
+ console.log(`[GitHub Storage] File ${fileName} not found on GitHub. Using local.`);
84
+ } else {
85
+ console.error(`[GitHub Storage] Load error for ${fileName}:`, error.message);
86
+ }
87
+ return false;
88
+ }
89
+ }
90
+ };
skills/hf_storage.js ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const dns = require('dns');
5
+ const https = require('https');
6
+ require('dotenv').config();
7
+
8
+ // Force IPv4 for HF network compatibility
9
+ dns.setDefaultResultOrder('ipv4first');
10
+ const ipv4Agent = new https.Agent({ family: 4 });
11
+ const axiosIPv4 = axios.create({ httpsAgent: ipv4Agent });
12
+
13
+ const HF_REPO = process.env.HF_DATASET_NAME || 'AIGoose/vinos-memory';
14
+ const HF_TOKEN = process.env.HUGGINGFACE_TOKEN;
15
+
16
+ /**
17
+ * VinOS Hugging Face Dataset Storage (Option A)
18
+ * Stores every strategic record as a granular .md file with YAML frontmatter.
19
+ */
20
+ module.exports = {
21
+ /**
22
+ * Save a record to the HF Dataset as an .md file
23
+ * @param {string} type - "conversations" | "playbooks" | "insights"
24
+ * @param {string} id - Unique filename (e.g. YYYY-MM-DD_slug)
25
+ * @param {object} metadata - { timestamp, source_url, niche, title }
26
+ * @param {string} content - The markdown body
27
+ */
28
+ saveRecord: async (type, id, metadata, content) => {
29
+ const fileName = `${id}.md`;
30
+ const remotePath = `${type}/${fileName}`;
31
+
32
+ // Construct McKinsey-style Markdown with YAML Frontmatter
33
+ const frontmatter = [
34
+ '---',
35
+ `title: "${metadata.title || 'Untitled Record'}"`,
36
+ `date: "${metadata.timestamp || new Date().toISOString()}"`,
37
+ `source_url: "${metadata.source_url || 'N/A'}"`,
38
+ `niche: "${metadata.niche || 'General'}"`,
39
+ `type: "${type}"`,
40
+ `author: "VinOS Intelligence Core"`,
41
+ '---',
42
+ '',
43
+ content
44
+ ].join('\n');
45
+
46
+ console.log(`[HF Storage] Saving ${remotePath} to dataset: ${HF_REPO}`);
47
+
48
+ try {
49
+ // Push to HF Hub via API (PUT handles create/update)
50
+ const url = `https://huggingface.co/api/datasets/${HF_REPO}/upload/main/${remotePath}`;
51
+
52
+ // Note: HF API requires base64 or blob for the file content
53
+ const buffer = Buffer.from(frontmatter, 'utf-8');
54
+
55
+ await axiosIPv4.post(url, buffer, {
56
+ headers: {
57
+ 'Authorization': `Bearer ${HF_TOKEN}`,
58
+ 'Content-Type': 'application/octet-stream'
59
+ }
60
+ });
61
+
62
+ return { success: true, url: `https://huggingface.co/datasets/${HF_REPO}/blob/main/${remotePath}` };
63
+ } catch (error) {
64
+ console.error(`[HF Storage] Error saving record:`, error.response?.data || error.message);
65
+ return { success: false, error: error.message };
66
+ }
67
+ },
68
+
69
+ /**
70
+ * Delete a record from the HF Dataset
71
+ */
72
+ deleteRecord: async (type, id) => {
73
+ const remotePath = `${type}/${id}.md`;
74
+ console.log(`[HF Storage] Deleting ${remotePath} from dataset: ${HF_REPO}`);
75
+
76
+ try {
77
+ // Note: Deleting via API typically requires a DELETE request to the tree/content
78
+ const url = `https://huggingface.co/api/datasets/${HF_REPO}/delete/main/${remotePath}`;
79
+ await axiosIPv4.post(url, {}, {
80
+ headers: { 'Authorization': `Bearer ${HF_TOKEN}` }
81
+ });
82
+ return { success: true };
83
+ } catch (error) {
84
+ console.error(`[HF Storage] Error deleting record:`, error.response?.data || error.message);
85
+ return { success: false, error: error.message };
86
+ }
87
+ }
88
+ };
skills/infinite_money_cron.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const cron = require('node-cron');
2
+ const apiCaller = require('./api_caller');
3
+ const dailyPulse = require('../use_cases/daily_pulse');
4
+ const offerArchitect = require('../use_cases/offer_architect');
5
+ const versionControl = require('./version_control');
6
+ const qualityChecker = require('./quality_checker');
7
+ const memory = require('./memory');
8
+
9
+ module.exports = {
10
+ /**
11
+ * Initializes the autonomous 12-hour money glitch cycle.
12
+ */
13
+ startJobs: () => {
14
+ // 6:00 AM Task: Discover & Launch
15
+ cron.schedule('0 6 * * *', async () => {
16
+ try {
17
+ console.log("[CRON] 6:00 AM - Initiating Morning Discovery & Launch...");
18
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "⏰ <b>[6 AM AUTONOMOUS CYCLE]</b>\nWaking up to research today's digital arbitrage opportunities...");
19
+
20
+ const pulseResult = await dailyPulse();
21
+ if (pulseResult.success) {
22
+ // Quality check the pulse
23
+ const qCheck = await qualityChecker.selfCheck(pulseResult.pulse);
24
+ if (qCheck.score < 7) {
25
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, `⚠️ <i>Research quality was only ${qCheck.score}/10. Refining search criteria for next cycle.</i>`);
26
+ } else {
27
+ // Start an offer automatically based on the top pulse
28
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "πŸš€ <i>Research quality > 7. Auto-launching Offer Architect for top opportunity...</i>");
29
+ await offerArchitect("Top trending AI niche from daily pulse");
30
+
31
+ // Auto commit the new state
32
+ versionControl.commitChanges("6 AM Auto-Launch execution");
33
+ }
34
+ }
35
+ } catch (err) {
36
+ console.error("[CRON] 6 AM Error:", err);
37
+ }
38
+ });
39
+
40
+ // 6:00 PM Task: Analyze & Tweak
41
+ cron.schedule('0 18 * * *', async () => {
42
+ try {
43
+ console.log("[CRON] 6:00 PM - Analyzing Morning Launch Results...");
44
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "⏰ <b>[6 PM AUTONOMOUS CYCLE]</b>\nAnalyzing today's active experiments...");
45
+
46
+ const db = memory.readDB();
47
+
48
+ if (db.metrics && db.metrics.total_sales === 0 && db.metrics.active_experiments > 0) {
49
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "πŸ“‰ <b>Analysis:</b> 0 sales generated in the last 12 hours. Generating strategic Pivot Plan...");
50
+
51
+ const prompt = [
52
+ { role: "system", content: "You are the VinOS Strategy Tweaker. An offer ran for 12 hours with 0 sales. Propose 3 actionable tweaks to the copy, pricing, or target audience to test for the next 12 hours." },
53
+ { role: "user", content: "Analyze the 0-sale performance and suggest the next pivot." }
54
+ ];
55
+
56
+ const pivotResult = await apiCaller.callOpenRouter(prompt);
57
+ if (pivotResult.success) {
58
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, `πŸ”„ <b>Pivot Plan Generated:</b>\n\n${pivotResult.data}`);
59
+ versionControl.commitChanges("6 PM Pivot strategy documented");
60
+ }
61
+ } else if (db.metrics && db.metrics.total_sales > 0) {
62
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "πŸŽ‰ <b>Sales Detected!</b> The strategy is working. Saving as successful playbook.");
63
+ require('./playbook_manager').savePlaybook("Winning Offer Criteria", "Strategy generated sales within 12 hours. Duplicate formatting.", ["sales", "proven"]);
64
+ } else {
65
+ await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, "ℹ️ No active experiments to analyze. Skipping tweak cycle.");
66
+ }
67
+ } catch (err) {
68
+ console.error("[CRON] 6 PM Error:", err);
69
+ }
70
+ });
71
+
72
+ console.log("[Scheduler] Infinite Money Glitch Cron Jobs Active: 6 AM and 6 PM.");
73
+ }
74
+ };
skills/product_deployer.js ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ require('dotenv').config();
3
+
4
+ const WHOP_API_KEY = process.env.WHOP_API_KEY;
5
+ const MAYAR_API_KEY = process.env.MAYAR_API_KEY;
6
+
7
+ /**
8
+ * VinOS Product Deployer Skill
9
+ * Automates the deployment of 'Infinite Money Glitch' offers to Whop and Mayar.
10
+ */
11
+ module.exports = {
12
+ /**
13
+ * Deploys a product to Whop.
14
+ * Whop allows full programmatic product creation.
15
+ */
16
+ deployToWhop: async (name, description, price) => {
17
+ if (!WHOP_API_KEY) return { success: false, error: "Missing WHOP_API_KEY" };
18
+
19
+ try {
20
+ console.log(`[Whop] Deploying product: ${name}`);
21
+
22
+ // 1. Create Product
23
+ const productRes = await axios.post('https://api.whop.com/v1/products', {
24
+ name: name,
25
+ description: description
26
+ }, {
27
+ headers: { 'Authorization': `Bearer ${WHOP_API_KEY}` }
28
+ });
29
+
30
+ const productId = productRes.data.id;
31
+
32
+ // 2. Create Plan (Pricing)
33
+ const planRes = await axios.post(`https://api.whop.com/v1/plans`, {
34
+ product_id: productId,
35
+ name: "Standard Access",
36
+ price: price,
37
+ billing_period: "one_time"
38
+ }, {
39
+ headers: { 'Authorization': `Bearer ${WHOP_API_KEY}` }
40
+ });
41
+
42
+ return {
43
+ success: true,
44
+ url: `https://whop.com/products/${productId}`,
45
+ productId,
46
+ planId: planRes.data.id
47
+ };
48
+ } catch (error) {
49
+ console.error("[Whop] Deployment failed:", error.response?.data || error.message);
50
+ return { success: false, error: error.message };
51
+ }
52
+ },
53
+
54
+ /**
55
+ * Generates a Mayar Instant Payment Link.
56
+ * Note: Mayar dashboard is required for full product setup,
57
+ * but 'Single Payment Request' works via API for instant testing.
58
+ */
59
+ deployToMayar: async (title, amount, description) => {
60
+ if (!MAYAR_API_KEY) return { success: false, error: "Missing MAYAR_API_KEY" };
61
+
62
+ try {
63
+ console.log(`[Mayar] Generating payment link for: ${title}`);
64
+ const response = await axios.post('https://api.mayar.id/headless/payment/create', {
65
+ name: title,
66
+ amount: amount,
67
+ description: description,
68
+ redirect_url: "https://vinos.engine/success" // Placeholder
69
+ }, {
70
+ headers: { 'Authorization': `Bearer ${MAYAR_API_KEY}` }
71
+ });
72
+
73
+ return {
74
+ success: true,
75
+ url: response.data.data.link,
76
+ paymentId: response.data.data.id
77
+ };
78
+ } catch (error) {
79
+ console.error("[Mayar] Link creation failed:", error.response?.data || error.message);
80
+ return { success: false, error: error.message };
81
+ }
82
+ }
83
+ };
skills/quality_checker.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const apiCaller = require('./api_caller');
2
+
3
+ module.exports = {
4
+ /**
5
+ * Scores output quality from 1-10 to determine if we need a paid model.
6
+ */
7
+ selfCheck: async (content) => {
8
+ const prompt = [
9
+ { role: "system", content: "You are the VinOS Quality Assessor. Grade the following content strictly from 1 to 10 based on professionalism, clarity, actionable value, and depth. Return ONLY a single number from 1 to 10 and nothing else." },
10
+ { role: "user", content: content }
11
+ ];
12
+
13
+ const result = await apiCaller.callOpenRouter(prompt);
14
+ if (result.success) {
15
+ const match = result.data.match(/\d+/);
16
+ if (match) {
17
+ const score = parseInt(match[0], 10);
18
+ console.log(`[QualityChecker] Output scored: ${score}/10`);
19
+ return { success: true, score: score };
20
+ }
21
+ }
22
+ return { success: false, score: 0 };
23
+ }
24
+ };
skills/report_generator.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const PDFDocument = require('pdfkit');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ /**
6
+ * VinOS Strategic Report Generator
7
+ * Creates high-end PDF documents in a professional "McKinsey" style.
8
+ */
9
+ module.exports = {
10
+ generateMcKinseyReport: async (title, content, fileName) => {
11
+ return new Promise((resolve, reject) => {
12
+ try {
13
+ const reportDir = path.join(__dirname, '../database/reports');
14
+ if (!fs.existsSync(reportDir)) fs.mkdirSync(reportDir, { recursive: true });
15
+
16
+ const filePath = path.join(reportDir, fileName);
17
+ const doc = new PDFDocument({ margin: 50 });
18
+ const stream = fs.createWriteStream(filePath);
19
+
20
+ doc.pipe(stream);
21
+
22
+ // --- HEADER ---
23
+ doc.fontSize(8).fillColor('#666666').text('VinOS STRATEGY LAB | CONFIDENTIAL & PROPRIETARY', { align: 'right' });
24
+ doc.moveDown(2);
25
+
26
+ // --- COVER ---
27
+ doc.fontSize(28).fillColor('#1a3a5f').font('Helvetica-Bold').text(title.toUpperCase(), { align: 'center' });
28
+ doc.fontSize(12).fillColor('#333333').font('Helvetica').text('Strategic Growth Analysis & Market Opportunity Assessment', { align: 'center' });
29
+ doc.moveDown(1);
30
+ doc.fontSize(10).fillColor('#666666').text(`Date: ${new Date().toLocaleDateString()} | Client: Vin/AIGoose`, { align: 'center' });
31
+
32
+ doc.moveTo(50, doc.y + 10).lineTo(550, doc.y + 10).strokeColor('#1a3a5f').lineWidth(2).stroke();
33
+ doc.moveDown(3);
34
+
35
+ // --- CONTENT PROCESSING ---
36
+ // Split content by headers (#) or double newlines for sections
37
+ const sections = content.split('\n\n');
38
+
39
+ sections.forEach(section => {
40
+ if (section.trim().startsWith('#') || section.includes(':')) {
41
+ doc.fontSize(16).fillColor('#1a3a5f').font('Helvetica-Bold').text(section.replace(/#/g, '').trim());
42
+ doc.moveDown(0.5);
43
+ } else {
44
+ doc.fontSize(11).fillColor('#333333').font('Helvetica').lineGap(4).text(section.trim(), {
45
+ align: 'justify',
46
+ columns: 1
47
+ });
48
+ doc.moveDown(1);
49
+ }
50
+ });
51
+
52
+ // --- FOOTER ---
53
+ doc.fontSize(8).fillColor('#999999').text(`Β© ${new Date().getFullYear()} VinOS Intelligence Core. All Rights Reserved. Page 1/1`, 50, 750, { align: 'center' });
54
+
55
+ doc.end();
56
+
57
+ stream.on('finish', () => resolve(filePath));
58
+ stream.on('error', (err) => reject(err));
59
+ } catch (error) {
60
+ reject(error);
61
+ }
62
+ });
63
+ }
64
+ };
skills/set_telegram_menu.js ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ require('dotenv').config();
3
+
4
+ const setCommands = async () => {
5
+ const token = process.env.TELEGRAM_BOT_TOKEN;
6
+ const url = `https://api.telegram.org/bot${token}/setMyCommands`;
7
+
8
+ const commands = [
9
+ { command: 'social', description: 'Agent: Analyze ICPs & Pain Points (X/YT)' },
10
+ { command: 'mckinsey', description: 'Agent: Generate Strategic PDF Report πŸ“Š' },
11
+ { command: 'deploy', description: 'Agent: Launch Product to Whop/Mayar πŸš€' },
12
+ { command: 'glitch', description: 'Agent: Ideate Infinite Money Glitch πŸ’‘' },
13
+ { command: 'playbooks', description: 'Agent: List Learned Knowledge 🧠' },
14
+ { command: 'recent', description: 'Agent: Recall Last 5 Conversations πŸ’¬' },
15
+ { command: 'log', description: 'Agent: View Version History πŸ“œ' }
16
+ ];
17
+
18
+ try {
19
+ const response = await axios.post(url, { commands });
20
+ console.log('βœ… Telegram Menu Updated:', response.data);
21
+ } catch (error) {
22
+ console.error('❌ Failed to set commands:', error.response?.data || error.message);
23
+ }
24
+ };
25
+
26
+ if (require.main === module) {
27
+ setCommands();
28
+ }
29
+
30
+ module.exports = setCommands;
skills/social_engager.js ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ require('dotenv').config();
3
+
4
+ const APIFY_API_KEY = process.env.APIFY_API_KEY;
5
+
6
+ /**
7
+ * VinOS Social Engager Skill
8
+ * Autonomous posting and replying for organic traffic & market verification.
9
+ * Uses Apify's Poster Actors to bypass expensive official APIs.
10
+ */
11
+ module.exports = {
12
+ /**
13
+ * Posts a thread or message to X.
14
+ */
15
+ postToX: async (content) => {
16
+ if (!APIFY_API_KEY) return { success: false, error: "Missing APIFY_API_KEY" };
17
+
18
+ try {
19
+ console.log(`[Social Engager] Posting to X: ${content.substring(0, 50)}...`);
20
+ const response = await axios.post(`https://api.apify.com/v2/acts/apify~twitter-poster/runs?token=${APIFY_API_KEY}`, {
21
+ text: content
22
+ });
23
+ return { success: true, runId: response.data.data.id };
24
+ } catch (error) {
25
+ console.error("[Social Engager] X posting failed:", error.message);
26
+ return { success: false, error: error.message };
27
+ }
28
+ },
29
+
30
+ /**
31
+ * Generates a reply in a natural, slang-filled native language.
32
+ */
33
+ generateNaturalReply: async (userComment, language = 'id') => {
34
+ const prompt = `User comment: "${userComment}"
35
+ Language: ${language}
36
+ Task: Reply to this user to build rapport and verify their needs.
37
+ Persona: Human, helpful, curious, using everyday jargon and local slang.
38
+ Don't sound like a bot. Keep it short (1-2 sentences).`;
39
+
40
+ // This logic would be routed to the apiCaller.callOpenRouter in practice
41
+ return { success: true, prompt };
42
+ }
43
+ };
skills/social_researcher.js ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ require('dotenv').config();
3
+
4
+ const APIFY_API_KEY = process.env.APIFY_API_KEY;
5
+
6
+ /**
7
+ * VinOS Social Researcher Skill
8
+ * Scrapes Top 30 accounts and comments to identify pain points using Design Thinking.
9
+ */
10
+ module.exports = {
11
+ /**
12
+ * Conducts a deep niche scan across X and YouTube.
13
+ */
14
+ researchNiche: async (niche) => {
15
+ if (!APIFY_API_KEY) return { success: false, error: "Missing APIFY_API_KEY" };
16
+
17
+ try {
18
+ console.log(`[Social Researcher] Analyzing niche: ${niche}`);
19
+
20
+ // 1. YouTube Comments Scraper (Pain Points)
21
+ const ytRes = await axios.post(`https://api.apify.com/v2/acts/streamers~youtube-comment-scraper/run-sync-get-dataset-items?token=${APIFY_API_KEY}`, {
22
+ searchQueries: [niche],
23
+ maxComments: 30,
24
+ maxCommentsPerVideo: 10
25
+ });
26
+
27
+ // 2. Twitter (X) Search (Trends & ICPs)
28
+ const xRes = await axios.post(`https://api.apify.com/v2/acts/apidojo~twitter-scraper-lite/run-sync-get-dataset-items?token=${APIFY_API_KEY}`, {
29
+ searchTerms: [niche],
30
+ maxTweets: 20
31
+ });
32
+
33
+ // Combine data for LLM analysis
34
+ const rawData = {
35
+ youtube: ytRes.data.map(i => i.text),
36
+ twitter: xRes.data.map(i => i.full_text)
37
+ };
38
+
39
+ return {
40
+ success: true,
41
+ data: rawData,
42
+ summary: `Analyzed ${rawData.youtube.length} YT comments and ${rawData.twitter.length} tweets.`
43
+ };
44
+ } catch (error) {
45
+ console.error("[Social Researcher] Research failed:", error.response?.data || error.message);
46
+ return { success: false, error: error.message };
47
+ }
48
+ },
49
+
50
+ /**
51
+ * Formulates a Design Thinking solution based on research data.
52
+ */
53
+ formulateSolution: async (researchData) => {
54
+ // This is usually called as part of a prompt chain in the orchestrator
55
+ return {
56
+ empathize: "Users are frustrated with X...",
57
+ define: "The core problem is Y...",
58
+ ideate: "We should build Z...",
59
+ prototype: "A simple prompt-based tool..."
60
+ };
61
+ }
62
+ };
skills/trello_manager.js ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const fs = require('fs');
3
+ const FormData = require('form-data');
4
+ require('dotenv').config();
5
+
6
+ const TRELLO_KEY = process.env.TRELLO_API_KEY;
7
+ const TRELLO_TOKEN = process.env.TRELLO_TOKEN;
8
+
9
+ /**
10
+ * VinOS Trello Strategy Board Manager
11
+ * Manages the visual Kanban boards for "Infinite Money Glitch" experiments.
12
+ */
13
+ module.exports = {
14
+ /**
15
+ * Create a new Strategy Board
16
+ */
17
+ createBoard: async (name) => {
18
+ console.log(`[Trello] Creating board: ${name}`);
19
+ try {
20
+ const res = await axios.post(`https://api.trello.com/1/boards/?name=${encodeURIComponent(name)}&key=${TRELLO_KEY}&token=${TRELLO_TOKEN}`);
21
+ return { success: true, boardId: res.data.id, url: res.data.url };
22
+ } catch (e) {
23
+ console.error('[Trello] Board Error:', e.response?.data || e.message);
24
+ return { success: false, error: e.message };
25
+ }
26
+ },
27
+
28
+ /**
29
+ * Create Lists on a board (Standard Strategy Template)
30
+ */
31
+ setupStrategyLists: async (boardId) => {
32
+ const lists = ["Strategic Research", "Idea Design", "Market Verification", "Live Revenue"];
33
+ const results = [];
34
+ try {
35
+ for (const name of lists) {
36
+ const res = await axios.post(`https://api.trello.com/1/lists?name=${encodeURIComponent(name)}&idBoard=${boardId}&key=${TRELLO_KEY}&token=${TRELLO_TOKEN}`);
37
+ results.push({ name, id: res.data.id });
38
+ }
39
+ return { success: true, lists: results };
40
+ } catch (e) {
41
+ return { success: false, error: e.message };
42
+ }
43
+ },
44
+
45
+ /**
46
+ * Create a Card for an Insight or Task
47
+ */
48
+ createCard: async (listId, name, desc) => {
49
+ try {
50
+ const res = await axios.post(`https://api.trello.com/1/cards?idList=${listId}&name=${encodeURIComponent(name)}&desc=${encodeURIComponent(desc)}&key=${TRELLO_KEY}&token=${TRELLO_TOKEN}`);
51
+ return { success: true, cardId: res.data.id };
52
+ } catch (e) {
53
+ return { success: false, error: e.message };
54
+ }
55
+ },
56
+
57
+ /**
58
+ * Attach a McKinsey PDF Report to a card
59
+ */
60
+ attachReport: async (cardId, filePath) => {
61
+ console.log(`[Trello] Attaching report to card ${cardId}: ${filePath}`);
62
+ const formData = new FormData();
63
+ formData.append('file', fs.createReadStream(filePath));
64
+ formData.append('key', TRELLO_KEY);
65
+ formData.append('token', TRELLO_TOKEN);
66
+
67
+ try {
68
+ await axios.post(`https://api.trello.com/1/cards/${cardId}/attachments`, formData, {
69
+ headers: formData.getHeaders()
70
+ });
71
+ return { success: true };
72
+ } catch (e) {
73
+ console.error('[Trello] Attachment Error:', e.response?.data || e.message);
74
+ return { success: false, error: e.message };
75
+ }
76
+ }
77
+ };
skills/version_control.js ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { execSync } = require('child_process');
2
+
3
+ module.exports = {
4
+ /**
5
+ * Commits all current changes with a descriptive message.
6
+ */
7
+ commitChanges: (message) => {
8
+ try {
9
+ execSync('git add .', { stdio: 'pipe' });
10
+ execSync(`git commit -m "${message}"`, { stdio: 'pipe' });
11
+ console.log(`[VersionControl] Auto-Logged Version: ${message}`);
12
+
13
+ // Get the hash
14
+ const hash = execSync('git rev-parse --short HEAD', { stdio: 'pipe' }).toString().trim();
15
+ return { success: true, version: hash, message };
16
+ } catch (error) {
17
+ // It fails if there are no changes to commit
18
+ return { success: false, error: "Nothing to commit or error occurred." };
19
+ }
20
+ },
21
+
22
+ /**
23
+ * Reverts all files to the last saved working commit.
24
+ * WARNING: Erases uncommitted work.
25
+ */
26
+ revertToLastWorking: () => {
27
+ try {
28
+ execSync('git reset --hard HEAD', { stdio: 'pipe' });
29
+ execSync('git clean -fd', { stdio: 'pipe' });
30
+ console.log(`[VersionControl] Reverted state to last stable version.`);
31
+ return { success: true };
32
+ } catch (error) {
33
+ console.error(`[VersionControl] Revert error:`, error);
34
+ return { success: false, error: error.message };
35
+ }
36
+ },
37
+
38
+ /**
39
+ * Retrieves the last 5 version logs.
40
+ */
41
+ getLog: () => {
42
+ try {
43
+ const log = execSync('git log -n 5 --oneline', { stdio: 'pipe' }).toString().trim();
44
+ return { success: true, log };
45
+ } catch (error) {
46
+ return { success: false, log: "No previous logs." };
47
+ }
48
+ }
49
+ };
skills/web_researcher.js ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const https = require('https');
3
+ const dns = require('dns');
4
+
5
+ // Force IPv4
6
+ dns.setDefaultResultOrder('ipv4first');
7
+ const ipv4Agent = new https.Agent({
8
+ family: 4,
9
+ lookup: (hostname, options, callback) => dns.lookup(hostname, { ...options, family: 4 }, callback)
10
+ });
11
+ const axiosIPv4 = axios.create({ httpsAgent: ipv4Agent });
12
+
13
+ module.exports = {
14
+ /**
15
+ * Conducts a free web search by scraping DuckDuckGo HTML (No API key needed).
16
+ */
17
+ searchWeb: async (query) => {
18
+ try {
19
+ console.log(`[WebResearcher] Searching for: ${query}`);
20
+
21
+ const response = await axiosIPv4.get('https://html.duckduckgo.com/html/', {
22
+ params: { q: query },
23
+ headers: {
24
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
25
+ }
26
+ });
27
+
28
+ const html = response.data;
29
+ const results = [];
30
+
31
+ // Basic Regex to extract search results from DuckDuckGo HTML
32
+ const resultRegex = /<a class="result__url" href="([^"]+)".*?>.*?<\/a>.*?<a class="result__snippet[^>]+>(.*?)<\/a>/gs;
33
+ let match;
34
+ while ((match = resultRegex.exec(html)) !== null && results.length < 5) {
35
+ // Strip remaining HTML tags from snippet
36
+ const snippet = match[2].replace(/<[^>]*>?/gm, '').trim();
37
+ results.push(`Source: ${match[1]}\nContext: ${snippet}`);
38
+ }
39
+
40
+ if (results.length === 0) {
41
+ return { success: true, data: "Found nothing of value on the web." };
42
+ }
43
+
44
+ return { success: true, data: results.join('\n\n') };
45
+ } catch (error) {
46
+ console.error("[WebResearcher] Error:", error.message);
47
+ return { success: false, error: "Search failed due to network constraints." };
48
+ }
49
+ }
50
+ };
tmp_mission.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const apiCaller = require('./skills/api_caller');
2
+ const reportGen = require('./skills/report_generator');
3
+ const githubStorage = require('./skills/github_storage');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ require('dotenv').config();
7
+
8
+ async function runMcKinseyMission() {
9
+ const chatId = process.env.TELEGRAM_CHAT_ID;
10
+ console.log("πŸš€ Starting Strategic McKinsey-style Mission for AI Digital Strategy Consulting...");
11
+
12
+ // 1. Generate Strategic Content via Groq
13
+ const prompt = `Analyze the niche "AI Digital Strategy Consulting".
14
+ Identify the 3 biggest pain points for SMBs in 2026.
15
+ Then architect a "Gashapon-style" Low-Friction Offer (The "Infinite Money Glitch").
16
+
17
+ Structure the output as a professional report:
18
+ 1. EXECUTIVE SUMMARY
19
+ 2. MARKET PAIN POINTS (SMB context 2026)
20
+ 3. THE STRATEGIC SOLUTION (IDEATION)
21
+ 4. PROTOTYPE ARCHITECTURE (OFFER)
22
+ 5. RECOMMENDATIONS FOR LAUNCH
23
+
24
+ Use a professional, consultant-like tone.`;
25
+
26
+ const res = await apiCaller.callGroq([{ role: "user", content: prompt }]);
27
+ if (!res.success) return console.error("Groq Analysis Failed: " + res.error);
28
+
29
+ const reportContent = res.data;
30
+ const reportTitle = "VinOS Strategic Market Insight: AI Consulting 2026";
31
+ const reportFileName = `VinOS_McKinsey_Report_${Date.now()}.pdf`;
32
+
33
+ // 2. Generate PDF
34
+ try {
35
+ const filePath = await reportGen.generateMcKinseyReport(reportTitle, reportContent, reportFileName);
36
+ console.log(`βœ… PDF Generated: ${filePath}`);
37
+
38
+ // 3. Deliver to Telegram
39
+ await apiCaller.sendTelegramMessage(chatId, "πŸ“Š <b>Strategic Analysis Complete.</b>\nGenerating high-end McKinsey PDF report for you now...");
40
+ await apiCaller.sendTelegramDocument(chatId, filePath, "<b>VinOS | McKinsey-style Strategic Growth Report</b>\nAnalysis of the AI Digital Strategy Consulting market 2026.");
41
+
42
+ // 4. Persistence: Push to GitHub if configured
43
+ const GITHUB_REPO = process.env.GITHUB_REPO;
44
+ if (GITHUB_REPO) {
45
+ console.log(`☁️ Syncing report ${reportFileName} to GitHub...`);
46
+ await githubStorage.saveToGitHub(filePath, `reports/${reportFileName}`);
47
+ }
48
+
49
+ console.log("🏁 Mission Finished successfully.");
50
+ } catch (e) {
51
+ console.error("PDF Generation/Delivery Failed:", e);
52
+ }
53
+ }
54
+
55
+ runMcKinseyMission();
use_cases/daily_pulse.js CHANGED
@@ -1,21 +1,27 @@
1
  const apiCaller = require('../skills/api_caller');
 
2
 
3
  /**
4
  * Use Case 1: Daily Pulse (Market Scanner)
5
- * Scans for the latest AI / Digital Strategy trends and notifies the user.
6
  */
7
  module.exports = async () => {
8
  console.log("[Daily Pulse] Starting market scan...");
9
 
 
 
 
 
 
10
  const prompt = [
11
- { role: "system", content: "You are a sharp market analyst looking for digital arbitrage opportunities." },
12
- { role: "user", content: "Scan the current landscape for 3 high-potential AI service niches that can be launched in 24 hours. Focus on the Indonesian market." }
13
  ];
14
 
15
  const result = await apiCaller.callOpenRouter(prompt);
16
 
17
  if (result.success) {
18
- const message = `<b>VinOS Daily Pulse</b> πŸ“Š\n\n${result.data}\n\n<i>Time to execute?</i>`;
19
  await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, message);
20
  return { success: true, pulse: result.data };
21
  } else {
 
1
  const apiCaller = require('../skills/api_caller');
2
+ const webResearcher = require('../skills/web_researcher');
3
 
4
  /**
5
  * Use Case 1: Daily Pulse (Market Scanner)
6
+ * Upgraded: Now pulls real-time data from search engines before summarizing.
7
  */
8
  module.exports = async () => {
9
  console.log("[Daily Pulse] Starting market scan...");
10
 
11
+ // 1. Gather live market data first
12
+ const searchResult = await webResearcher.searchWeb("top AI business trends opportunities digital arbitrage 2026");
13
+ const marketData = searchResult.success ? searchResult.data : "No live data available.";
14
+
15
+ // 2. Synthesize with LLM
16
  const prompt = [
17
+ { role: "system", content: "You are Vin, a sharp digital arbitrage analyst. You've just performed web research. Synthesize the raw web data provided into 3 high-potential AI service niches that can be launched immediately." },
18
+ { role: "user", content: `Raw Web Data:\n${marketData}\n\nTask: Synthesize this into 3 actionable digital arbitrage opportunities for the Indonesian market.` }
19
  ];
20
 
21
  const result = await apiCaller.callOpenRouter(prompt);
22
 
23
  if (result.success) {
24
+ const message = `πŸ“ˆ <b>VinOS Daily Pulse (Live Research)</b>\n\n${result.data}\n\n<i>Time to execute? Send /offer [niche] to build it.</i>`;
25
  await apiCaller.sendTelegramMessage(process.env.TELEGRAM_CHAT_ID, message);
26
  return { success: true, pulse: result.data };
27
  } else {