wadi 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/.agent/workflows/auto_sync.md +19 -0
  2. package/.agent/workflows/kivo_pipeline.md +27 -0
  3. package/.devcontainer/devcontainer.json +27 -0
  4. package/.github/workflows/kivo-cicd.yml +45 -0
  5. package/.github/workflows/monorepo-ci.yml +51 -0
  6. package/.github/workflows/wadi-ci.yml +38 -0
  7. package/.husky/pre-commit +2 -0
  8. package/.prettierignore +12 -0
  9. package/.prettierrc +9 -0
  10. package/.vscode/settings.json +19 -0
  11. package/CHANGELOG.md +56 -0
  12. package/CODE_OF_CONDUCT.md +43 -0
  13. package/CONTRIBUTING.md +42 -0
  14. package/DEPLOY_GUIDE.md +143 -0
  15. package/GO_LIVE_CHECKLIST.md +41 -0
  16. package/GO_LIVE_COMPLETE_REPORT.md +58 -0
  17. package/GO_LIVE_VALIDATION.md +39 -0
  18. package/LEGAL.md +38 -0
  19. package/MANIFESTO.md +40 -0
  20. package/MANUAL.md +82 -0
  21. package/OPS_PLAN.md +90 -0
  22. package/README.md +126 -0
  23. package/RELEASE_NOTES.md +51 -0
  24. package/ROADMAP.md +51 -0
  25. package/api_listado.txt +2197 -0
  26. package/apps/api/WADI_PROTOCOL.md +52 -0
  27. package/apps/api/debug-brain.js +11 -0
  28. package/apps/api/package.json +21 -0
  29. package/apps/api/src/core/analisis.js +17 -0
  30. package/apps/api/src/core/errors.js +31 -0
  31. package/apps/api/src/core/logger.js +32 -0
  32. package/apps/api/src/core/prompt-kivo.js +62 -0
  33. package/apps/api/src/index.js +212 -0
  34. package/apps/api/src/layers/human_pattern/composeResponse.js +35 -0
  35. package/apps/api/src/layers/human_pattern/detectPattern.js +39 -0
  36. package/apps/api/src/layers/human_pattern/heuristics.js +28 -0
  37. package/apps/api/src/layers/human_pattern/index.js +28 -0
  38. package/apps/api/src/layers/human_pattern/socialMemory.js +35 -0
  39. package/apps/api/src/middleware/errorHandler.js +24 -0
  40. package/apps/api/src/middleware/rateLimiter.js +38 -0
  41. package/apps/api/src/middleware/requestLogger.js +31 -0
  42. package/apps/api/src/middleware/upload.js +21 -0
  43. package/apps/api/src/middleware/validation.js +70 -0
  44. package/apps/api/src/modules/data.js +25 -0
  45. package/apps/api/src/modules/marketing.js +54 -0
  46. package/apps/api/src/modules/projects.js +40 -0
  47. package/apps/api/src/openai.js +16 -0
  48. package/apps/api/src/preferences/index.js +20 -0
  49. package/apps/api/src/register_user.js +22 -0
  50. package/apps/api/src/routes/kivo.js +58 -0
  51. package/apps/api/src/routes/monitoring.js +55 -0
  52. package/apps/api/src/routes.js +656 -0
  53. package/apps/api/src/supabase.js +17 -0
  54. package/apps/api/src/tools/index.js +57 -0
  55. package/apps/api/src/wadi-brain.js +171 -0
  56. package/apps/api/supabase/migrations/20251218_audit_logs.sql +27 -0
  57. package/apps/api/supabase/migrations/v2-chat-persistence.sql +83 -0
  58. package/apps/api/supabase/migrations/v3-cascade-delete.sql +11 -0
  59. package/apps/api/supabase/migrations/v3-security-fix.sql +90 -0
  60. package/apps/api/supabase/migrations/v3-storage.sql +36 -0
  61. package/apps/api/supabase/migrations/v4-gamification.sql +83 -0
  62. package/apps/api/supabase/migrations/v5-smoke-index.sql +6 -0
  63. package/apps/api/supabase/migrations/v6-schema-integrity-fix.sql +98 -0
  64. package/apps/api/supabase/migrations/v7-performance-indexes.sql +5 -0
  65. package/apps/api/supabase/migrations/v7-security-hardening.sql +132 -0
  66. package/apps/api/supabase/migrations/v8-security-hardening.sql +79 -0
  67. package/apps/api/test_human_pattern.js +30 -0
  68. package/apps/api/test_human_pattern_vague.js +30 -0
  69. package/apps/api/test_output.txt +76 -0
  70. package/apps/api/test_vague.js +30 -0
  71. package/apps/api/test_vague_block.js +30 -0
  72. package/apps/api/test_wadi.js +31 -0
  73. package/apps/api/tsconfig.json +13 -0
  74. package/apps/frontend/.env.local +3 -0
  75. package/apps/frontend/README.md +73 -0
  76. package/apps/frontend/eslint.config.js +27 -0
  77. package/apps/frontend/index.html +49 -0
  78. package/apps/frontend/package.json +41 -0
  79. package/apps/frontend/postcss.config.cjs +6 -0
  80. package/apps/frontend/public/cursors/wadi-neutral.svg +1 -0
  81. package/apps/frontend/public/cursors/wadi-select.svg +1 -0
  82. package/apps/frontend/public/icon-192.svg +1 -0
  83. package/apps/frontend/public/icon-512.svg +1 -0
  84. package/apps/frontend/public/manifest.webmanifest +23 -0
  85. package/apps/frontend/public/sw.js +57 -0
  86. package/apps/frontend/public/vite.svg +1 -0
  87. package/apps/frontend/public/wadi.svg +5 -0
  88. package/apps/frontend/src/assets/react.svg +1 -0
  89. package/apps/frontend/src/components/AuthLoader.tsx +50 -0
  90. package/apps/frontend/src/components/ChatInput.tsx +272 -0
  91. package/apps/frontend/src/components/ChatInterface.tsx +202 -0
  92. package/apps/frontend/src/components/ErrorBoundary.tsx +52 -0
  93. package/apps/frontend/src/components/InputArea.tsx +201 -0
  94. package/apps/frontend/src/components/Layout.tsx +73 -0
  95. package/apps/frontend/src/components/MessageBubble.tsx +66 -0
  96. package/apps/frontend/src/components/OnboardingModal.tsx +108 -0
  97. package/apps/frontend/src/components/SettingsModal.tsx +187 -0
  98. package/apps/frontend/src/components/Sidebar.tsx +171 -0
  99. package/apps/frontend/src/components/WadiOnboarding.tsx +71 -0
  100. package/apps/frontend/src/components/auditor/AuditReport.tsx +166 -0
  101. package/apps/frontend/src/components/auditor/AuditorHeader.tsx +34 -0
  102. package/apps/frontend/src/components/auditor/ContextPanel.tsx +138 -0
  103. package/apps/frontend/src/components/auditor/DataDeconstructor.tsx +85 -0
  104. package/apps/frontend/src/components/auditor/DecisionWall.tsx +65 -0
  105. package/apps/frontend/src/components/auditor/Dropzone.tsx +137 -0
  106. package/apps/frontend/src/components/common/Button.tsx +97 -0
  107. package/apps/frontend/src/components/common/Card.tsx +43 -0
  108. package/apps/frontend/src/components/common/Input.tsx +73 -0
  109. package/apps/frontend/src/components/common/Modal.tsx +53 -0
  110. package/apps/frontend/src/components/ui/Button.tsx +68 -0
  111. package/apps/frontend/src/components/ui/Card.tsx +86 -0
  112. package/apps/frontend/src/components/ui/Input.tsx +28 -0
  113. package/apps/frontend/src/components/ui/LogItem.tsx +64 -0
  114. package/apps/frontend/src/components/ui/MondayButton.tsx +40 -0
  115. package/apps/frontend/src/components/ui/MondayCard.tsx +24 -0
  116. package/apps/frontend/src/components/ui/Scouter.tsx +208 -0
  117. package/apps/frontend/src/components/ui/TerminalInput.tsx +202 -0
  118. package/apps/frontend/src/components/ui/Tooltip.tsx +67 -0
  119. package/apps/frontend/src/config/chatShortcuts.ts +20 -0
  120. package/apps/frontend/src/config/supabase.ts +6 -0
  121. package/apps/frontend/src/final_status.txt +3 -0
  122. package/apps/frontend/src/hooks/useScouter.ts +28 -0
  123. package/apps/frontend/src/hooks/useStoreHydration.ts +24 -0
  124. package/apps/frontend/src/improvement_status.txt +5 -0
  125. package/apps/frontend/src/index.css +88 -0
  126. package/apps/frontend/src/main.tsx +62 -0
  127. package/apps/frontend/src/monday_status.txt +7 -0
  128. package/apps/frontend/src/pages/ChatPage.tsx +201 -0
  129. package/apps/frontend/src/pages/DashboardPage.tsx +375 -0
  130. package/apps/frontend/src/pages/IntroWadi.tsx +114 -0
  131. package/apps/frontend/src/pages/LandingPage.tsx +103 -0
  132. package/apps/frontend/src/pages/Login.tsx +190 -0
  133. package/apps/frontend/src/pages/PrivacyPage.tsx +213 -0
  134. package/apps/frontend/src/pages/ProjectDetail.tsx +80 -0
  135. package/apps/frontend/src/pages/Projects.tsx +247 -0
  136. package/apps/frontend/src/pages/TermsPage.tsx +202 -0
  137. package/apps/frontend/src/router.tsx +83 -0
  138. package/apps/frontend/src/store/authStore.ts +152 -0
  139. package/apps/frontend/src/store/chatStore.ts +837 -0
  140. package/apps/frontend/src/store/documentStore.ts +89 -0
  141. package/apps/frontend/src/store/projectsStore.ts +111 -0
  142. package/apps/frontend/src/store/runsStore.ts +98 -0
  143. package/apps/frontend/src/utils/api.ts +34 -0
  144. package/apps/frontend/src/vite-env.d.ts +7 -0
  145. package/apps/frontend/tailwind.config.cjs +32 -0
  146. package/apps/frontend/tsconfig.app.json +27 -0
  147. package/apps/frontend/tsconfig.json +7 -0
  148. package/apps/frontend/tsconfig.node.json +26 -0
  149. package/apps/frontend/vite.config.ts +25 -0
  150. package/apps/kivo/.firebase/hosting.d3d3.cache +11 -0
  151. package/apps/kivo/.firebaserc +5 -0
  152. package/apps/kivo/BRANDING_GUIDE.md +71 -0
  153. package/apps/kivo/DEPLOYMENT_READY.md +46 -0
  154. package/apps/kivo/DEPLOY_URL.md +12 -0
  155. package/apps/kivo/IMPLEMENTATION_REPORT.md +35 -0
  156. package/apps/kivo/IMPLEMENTATION_REPORT_FINAL.md +49 -0
  157. package/apps/kivo/PLAN_MOBILE_2.0.md +44 -0
  158. package/apps/kivo/PWA_VERIFICATION_GUIDE.md +77 -0
  159. package/apps/kivo/README.md +28 -0
  160. package/apps/kivo/REBUILD_REPORT.md +34 -0
  161. package/apps/kivo/UPGRADE_REPORT.md +35 -0
  162. package/apps/kivo/android/app/build.gradle +54 -0
  163. package/apps/kivo/android/app/capacitor.build.gradle +19 -0
  164. package/apps/kivo/android/app/proguard-rules.pro +21 -0
  165. package/apps/kivo/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +26 -0
  166. package/apps/kivo/android/app/src/main/AndroidManifest.xml +35 -0
  167. package/apps/kivo/android/app/src/main/java/com/kivo/app/MainActivity.java +5 -0
  168. package/apps/kivo/android/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  169. package/apps/kivo/android/app/src/main/res/drawable/splash.png +0 -0
  170. package/apps/kivo/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
  171. package/apps/kivo/android/app/src/main/res/drawable-land-ldpi/splash.png +0 -0
  172. package/apps/kivo/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
  173. package/apps/kivo/android/app/src/main/res/drawable-land-night-hdpi/splash.png +0 -0
  174. package/apps/kivo/android/app/src/main/res/drawable-land-night-ldpi/splash.png +0 -0
  175. package/apps/kivo/android/app/src/main/res/drawable-land-night-mdpi/splash.png +0 -0
  176. package/apps/kivo/android/app/src/main/res/drawable-land-night-xhdpi/splash.png +0 -0
  177. package/apps/kivo/android/app/src/main/res/drawable-land-night-xxhdpi/splash.png +0 -0
  178. package/apps/kivo/android/app/src/main/res/drawable-land-night-xxxhdpi/splash.png +0 -0
  179. package/apps/kivo/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
  180. package/apps/kivo/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
  181. package/apps/kivo/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
  182. package/apps/kivo/android/app/src/main/res/drawable-night/splash.png +0 -0
  183. package/apps/kivo/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
  184. package/apps/kivo/android/app/src/main/res/drawable-port-ldpi/splash.png +0 -0
  185. package/apps/kivo/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
  186. package/apps/kivo/android/app/src/main/res/drawable-port-night-hdpi/splash.png +0 -0
  187. package/apps/kivo/android/app/src/main/res/drawable-port-night-ldpi/splash.png +0 -0
  188. package/apps/kivo/android/app/src/main/res/drawable-port-night-mdpi/splash.png +0 -0
  189. package/apps/kivo/android/app/src/main/res/drawable-port-night-xhdpi/splash.png +0 -0
  190. package/apps/kivo/android/app/src/main/res/drawable-port-night-xxhdpi/splash.png +0 -0
  191. package/apps/kivo/android/app/src/main/res/drawable-port-night-xxxhdpi/splash.png +0 -0
  192. package/apps/kivo/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
  193. package/apps/kivo/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
  194. package/apps/kivo/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
  195. package/apps/kivo/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
  196. package/apps/kivo/android/app/src/main/res/layout/activity_main.xml +12 -0
  197. package/apps/kivo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +9 -0
  198. package/apps/kivo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +9 -0
  199. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  200. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png +0 -0
  201. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  202. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  203. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher.png +0 -0
  204. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_background.png +0 -0
  205. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_foreground.png +0 -0
  206. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_round.png +0 -0
  207. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  208. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png +0 -0
  209. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  210. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  211. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  212. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png +0 -0
  213. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  214. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  215. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  216. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png +0 -0
  217. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  218. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  219. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  220. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png +0 -0
  221. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  222. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  223. package/apps/kivo/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
  224. package/apps/kivo/android/app/src/main/res/values/strings.xml +7 -0
  225. package/apps/kivo/android/app/src/main/res/values/styles.xml +22 -0
  226. package/apps/kivo/android/app/src/main/res/xml/file_paths.xml +5 -0
  227. package/apps/kivo/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +18 -0
  228. package/apps/kivo/android/build.gradle +29 -0
  229. package/apps/kivo/android/capacitor.settings.gradle +3 -0
  230. package/apps/kivo/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  231. package/apps/kivo/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  232. package/apps/kivo/android/gradle.properties +22 -0
  233. package/apps/kivo/android/gradlew +252 -0
  234. package/apps/kivo/android/gradlew.bat +94 -0
  235. package/apps/kivo/android/settings.gradle +5 -0
  236. package/apps/kivo/android/variables.gradle +16 -0
  237. package/apps/kivo/assets/icon.png +0 -0
  238. package/apps/kivo/assets/splash.png +0 -0
  239. package/apps/kivo/capacitor.config.json +16 -0
  240. package/apps/kivo/firebase.json +6 -0
  241. package/apps/kivo/jest.config.js +4 -0
  242. package/apps/kivo/package.json +26 -0
  243. package/apps/kivo/tests_disabled/logic.test.js +34 -0
  244. package/apps/kivo/www/assets/icon-192.png +0 -0
  245. package/apps/kivo/www/assets/icon-512.png +0 -0
  246. package/apps/kivo/www/assets/kivo-icon.png +0 -0
  247. package/apps/kivo/www/assets/pop.mp3 +0 -0
  248. package/apps/kivo/www/favicon.ico +0 -0
  249. package/apps/kivo/www/firebase-config.js +75 -0
  250. package/apps/kivo/www/index.html +38 -0
  251. package/apps/kivo/www/manifest.json +29 -0
  252. package/apps/kivo/www/script.js +72 -0
  253. package/apps/kivo/www/style.css +82 -0
  254. package/apps/kivo/www/sw.js +46 -0
  255. package/apps/kivo-brain-api/.env.example +2 -0
  256. package/apps/kivo-brain-api/KIVO_BACKEND_SETUP.md +27 -0
  257. package/apps/kivo-brain-api/controllers/kivoController.js +31 -0
  258. package/apps/kivo-brain-api/index.js +24 -0
  259. package/apps/kivo-brain-api/package.json +17 -0
  260. package/apps/kivo-brain-api/routes/message.js +8 -0
  261. package/apps/kivo-brain-api/services/openaiService.js +64 -0
  262. package/apps/tests/wadi-tests.js +155 -0
  263. package/apps/wadi-brain/docs/README_REMOVE_OPTIONS.md +26 -0
  264. package/cli/commands/deploy.js +10 -0
  265. package/cli/commands/docs.js +16 -0
  266. package/cli/commands/explain.js +29 -0
  267. package/cli/commands/lint.js +14 -0
  268. package/cli/index.js +26 -0
  269. package/cli/package.json +12 -0
  270. package/docs/CNAME +1 -0
  271. package/docs/README.md +38 -0
  272. package/docs/USO.md +30 -0
  273. package/docs/index.html +46 -0
  274. package/eslint.config.js +101 -0
  275. package/final_validation.json +27 -0
  276. package/frontend_listado.txt +33387 -0
  277. package/listado.txt +12591 -0
  278. package/package.json +46 -0
  279. package/packages/logger/index.js +43 -0
  280. package/packages/logger/package.json +19 -0
  281. package/packages/logger/test-logger.js +7 -0
  282. package/packages_listado.txt +801 -0
  283. package/pnpm-workspace.yaml +6 -0
  284. package/reseteador_existencial.ps1 +40 -0
  285. package/scripts/bump-version.js +26 -0
  286. package/scripts/env.ps1 +13 -0
  287. package/scripts/setup_android.ps1 +25 -0
  288. package/scripts/setup_virtual_env.ps1 +77 -0
  289. package/scripts/smoke-test.js +84 -0
  290. package/scripts/trigger_render_deploy.ps1 +3 -0
  291. package/scripts/validate-release.js +34 -0
  292. package/temp_check.js +57 -0
  293. package/tsconfig.json +5 -0
  294. package/validation_report.json +27 -0
@@ -0,0 +1,31 @@
1
+ import { logger } from "../core/logger.js";
2
+ import crypto from "crypto";
3
+ import { recordMetric } from "../routes/monitoring.js";
4
+
5
+ export const requestLogger = (req, res, next) => {
6
+ const start = Date.now();
7
+ req.requestId = req.headers["x-request-id"] || crypto.randomUUID();
8
+
9
+ // Hook into response finish
10
+ res.on("finish", () => {
11
+ const duration = Date.now() - start;
12
+
13
+ // Recording metrics
14
+ recordMetric(res.statusCode, duration);
15
+
16
+ logger.info("Request processed", {
17
+ requestId: req.requestId,
18
+ method: req.method,
19
+ path: req.originalUrl,
20
+ status: res.statusCode,
21
+ latency: duration,
22
+ userId:
23
+ (req.query && req.query.user_id) ||
24
+ (req.body && req.body.user_id) ||
25
+ "anonymous", // Best effort
26
+ userAgent: req.get("user-agent"),
27
+ });
28
+ });
29
+
30
+ next();
31
+ };
@@ -0,0 +1,21 @@
1
+ import multer from "multer";
2
+
3
+ const storage = multer.memoryStorage();
4
+
5
+ export const upload = multer({
6
+ storage: storage,
7
+ limits: {
8
+ fileSize: 10 * 1024 * 1024, // 10MB limit
9
+ },
10
+ fileFilter: (req, file, cb) => {
11
+ if (
12
+ file.mimetype === "application/pdf" ||
13
+ file.mimetype === "text/plain" ||
14
+ file.mimetype === "text/markdown"
15
+ ) {
16
+ cb(null, true);
17
+ } else {
18
+ cb(new Error("Formato no soportado. Solo PDF, TXT o MD."), false);
19
+ }
20
+ },
21
+ });
@@ -0,0 +1,70 @@
1
+ import { AppError } from "../core/errors.js";
2
+
3
+ export const validateChatInput = (req, res, next) => {
4
+ const { message } = req.body;
5
+
6
+ if (!message || typeof message !== "string") {
7
+ return next(
8
+ new AppError(
9
+ "VALIDATION_ERROR",
10
+ "Message is required and must be a string"
11
+ )
12
+ );
13
+ }
14
+
15
+ if (message.trim().length === 0) {
16
+ return next(new AppError("VALIDATION_ERROR", "Message cannot be empty"));
17
+ }
18
+
19
+ if (message.length > 5000) {
20
+ return next(
21
+ new AppError("VALIDATION_ERROR", "Message too long (max 5000 chars)")
22
+ );
23
+ }
24
+
25
+ next();
26
+ };
27
+
28
+ export const validateProjectInput = (req, res, next) => {
29
+ const { name } = req.body;
30
+
31
+ if (!name || typeof name !== "string") {
32
+ return next(new AppError("VALIDATION_ERROR", "Project name is required"));
33
+ }
34
+
35
+ if (name.trim().length === 0) {
36
+ return next(
37
+ new AppError("VALIDATION_ERROR", "Project name cannot be empty")
38
+ );
39
+ }
40
+
41
+ if (name.length > 100) {
42
+ return next(
43
+ new AppError("VALIDATION_ERROR", "Project name too long (max 100 chars)")
44
+ );
45
+ }
46
+
47
+ next();
48
+ };
49
+
50
+ export const validateRunInput = (req, res, next) => {
51
+ const { input } = req.body;
52
+
53
+ if (!input || typeof input !== "string") {
54
+ return next(
55
+ new AppError("VALIDATION_ERROR", "Input is required and must be a string")
56
+ );
57
+ }
58
+
59
+ if (input.trim().length === 0) {
60
+ return next(new AppError("VALIDATION_ERROR", "Input cannot be empty"));
61
+ }
62
+
63
+ if (input.length > 5000) {
64
+ return next(
65
+ new AppError("VALIDATION_ERROR", "Input too long (max 5000 chars)")
66
+ );
67
+ }
68
+
69
+ next();
70
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Data Analysis Module
3
+ * Módulo para procesamiento y visualización básica de datos.
4
+ */
5
+
6
+ export const summarizeDataset = async (jsonData) => {
7
+ // TODO: Implementar lógica de análisis real (pandas-like o simple stats)
8
+ console.log("[Data Module] Summarizing dataset...");
9
+ return {
10
+ rowCount: Array.isArray(jsonData) ? jsonData.length : 0,
11
+ columns:
12
+ Array.isArray(jsonData) && jsonData.length > 0
13
+ ? Object.keys(jsonData[0])
14
+ : [],
15
+ summary: "Basic summary placeholder (v3 stub)",
16
+ };
17
+ };
18
+
19
+ export const suggestVisualizations = (dataSummary) => {
20
+ // TODO: Inferir qué gráficos van mejor según los tipos de datos
21
+ return [
22
+ { type: "bar", label: "Distribution" },
23
+ { type: "line", label: "Trend over time" },
24
+ ];
25
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Marketing & Commerce Module
3
+ * Tipos y stubs para campañas, audiencias y productos.
4
+ */
5
+
6
+ export const CampaignStatus = {
7
+ DRAFT: "DRAFT",
8
+ ACTIVE: "ACTIVE",
9
+ PAUSED: "PAUSED",
10
+ COMPLETED: "COMPLETED",
11
+ };
12
+
13
+ class Product {
14
+ constructor(name, price) {
15
+ this.name = name;
16
+ this.price = price;
17
+ }
18
+ }
19
+
20
+ class Audience {
21
+ constructor(demographic, size) {
22
+ this.demographic = demographic;
23
+ this.size = size;
24
+ }
25
+ }
26
+
27
+ export const generateMarketingPlanDraft = async (productName) => {
28
+ console.log("[Marketing] Generating plan draft for:", productName);
29
+ return {
30
+ title: `Launch Plan for ${productName}`,
31
+ channels: ["Social Media", "Email", "Paid Ads"],
32
+ budgetEstimate: 5000,
33
+ timelineWeeks: 4,
34
+ };
35
+ };
36
+
37
+ export const createCampaign = async (campaignData) => {
38
+ console.log("[Marketing] Creating campaign:", campaignData.name);
39
+ return {
40
+ id: `camp_${Math.random().toString(36).substr(2, 5)}`,
41
+ ...campaignData,
42
+ status: CampaignStatus.DRAFT,
43
+ createdAt: new Date(),
44
+ };
45
+ };
46
+
47
+ export const segmentAudience = async (criteria) => {
48
+ console.log("[Marketing] Segmenting audience by:", criteria);
49
+ return {
50
+ segmentId: `seg_${Math.random().toString(36).substr(2, 5)}`,
51
+ estimatedSize: 1000 + Math.floor(Math.random() * 5000),
52
+ audienceObj: new Audience(criteria, 1000),
53
+ };
54
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Projects & Tasks Module
3
+ * Gestión básica de proyectos.
4
+ */
5
+
6
+ class Task {
7
+ constructor(title, status = "todo") {
8
+ this.id = Math.random().toString(36).substr(2, 9);
9
+ this.title = title;
10
+ this.status = status;
11
+ this.createdAt = new Date();
12
+ }
13
+ }
14
+
15
+ class Project {
16
+ constructor(name) {
17
+ this.id = Math.random().toString(36).substr(2, 9);
18
+ this.name = name;
19
+ this.tasks = [];
20
+ }
21
+
22
+ addTask(title) {
23
+ const task = new Task(title);
24
+ this.tasks.push(task);
25
+ return task;
26
+ }
27
+ }
28
+
29
+ export const createProjectDraft = async (name) => {
30
+ console.log("[Project] Creating project draft:", name);
31
+ return new Project(name);
32
+ };
33
+
34
+ export const listExampleTasks = async () => {
35
+ return [
36
+ new Task("Definir alcance del MVP", "todo"),
37
+ new Task("Configurar repo y CI/CD", "in-progress"),
38
+ new Task("Diseñar esquema de base de datos", "todo"),
39
+ ];
40
+ };
@@ -0,0 +1,16 @@
1
+ import OpenAI from "openai";
2
+ import dotenv from "dotenv";
3
+ dotenv.config({ path: "../../.env" });
4
+
5
+ const useGroq = !!process.env.GROQ_API_KEY;
6
+
7
+ export const openai = new OpenAI({
8
+ apiKey: useGroq
9
+ ? process.env.GROQ_API_KEY
10
+ : process.env.OPENAI_API_KEY || "dummy-key",
11
+ baseURL: useGroq ? "https://api.groq.com/openai/v1" : undefined,
12
+ });
13
+
14
+ export const AI_MODEL = useGroq
15
+ ? process.env.GROQ_MODEL || "llama-3.1-8b-instant"
16
+ : "gpt-4o";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * User Preferences Module
3
+ * Manejo de preferencias de usuario (idioma, tono, longitud de respuesta, etc.)
4
+ */
5
+
6
+ export const getUserPreferences = async (userId) => {
7
+ // TODO: Conectar con DB real (tabla profiles o user_settings)
8
+ console.log(`[Preferences] Fetching for user ${userId}`);
9
+ return {
10
+ idiomaPreferido: "auto", // 'es', 'en', 'auto'
11
+ longitudRespuesta: "normal", // 'breve', 'normal', 'detallada'
12
+ tono: "neutro", // 'casual', 'neutro', 'tecnico'
13
+ };
14
+ };
15
+
16
+ export const saveUserPreferences = async (userId, newPrefs) => {
17
+ // TODO: Guardar en DB cuando estemos listos
18
+ console.log(`[Preferences] Saving for user ${userId}`, newPrefs);
19
+ return { success: true, userId, updated: newPrefs };
20
+ };
@@ -0,0 +1,22 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+ import dotenv from "dotenv";
3
+ dotenv.config({ path: "../../.env" });
4
+
5
+ const supabaseUrl = process.env.SUPABASE_URL;
6
+ const supabaseKey = process.env.SUPABASE_KEY;
7
+ const supabase = createClient(supabaseUrl, supabaseKey);
8
+
9
+ async function register() {
10
+ const { data, error } = await supabase.auth.signUp({
11
+ email: "test@example.com",
12
+ password: "password123",
13
+ });
14
+
15
+ if (error) {
16
+ console.error("Error registering:", error.message);
17
+ } else {
18
+ console.log("User registered:", data.user?.email);
19
+ }
20
+ }
21
+
22
+ register();
@@ -0,0 +1,58 @@
1
+ import express from "express";
2
+ import { openai, AI_MODEL } from "../openai.js";
3
+ import { WADI_SYSTEM_PROMPT } from "../wadi-brain.js";
4
+
5
+ const router = express.Router();
6
+
7
+ // GET /api/kivo (status)
8
+ router.get("/", (req, res) => {
9
+ res.json({
10
+ service: "kivo",
11
+ status: "ready",
12
+ message: "Kivo module is online",
13
+ });
14
+ });
15
+
16
+ // POST /api/kivo/chat (Frontend endpoint)
17
+ router.post("/chat", async (req, res) => {
18
+ try {
19
+ const { message } = req.body;
20
+
21
+ if (!message) {
22
+ return res.status(400).json({ error: "Message is required" });
23
+ }
24
+
25
+ const completion = await openai.chat.completions.create({
26
+ model: AI_MODEL,
27
+ messages: [
28
+ { role: "system", content: WADI_SYSTEM_PROMPT },
29
+ { role: "user", content: message },
30
+ ],
31
+ });
32
+
33
+ const reply = completion.choices[0].message.content;
34
+ return res.json({ reply });
35
+ } catch (err) {
36
+ console.error("Kivo error:", err);
37
+ // DEBUG: Retornamos el error exacto para verlo en frontend
38
+ return res.status(500).json({ error: err.message });
39
+ }
40
+ });
41
+
42
+ // POST /api/kivo/run (Legacy/Internal)
43
+ router.post("/run", async (req, res) => {
44
+ try {
45
+ const { message } = req.body;
46
+ if (!message) return res.status(400).json({ error: "Message is required" });
47
+ return res.json({ reply: `You said: ${message}` });
48
+ } catch (err) {
49
+ return res.status(500).json({ error: "Internal server error" });
50
+ }
51
+ });
52
+
53
+ // POST /api/kivo/session
54
+ router.post("/session", (req, res) => {
55
+ res.json({ session: true, timestamp: Date.now() });
56
+ });
57
+
58
+ export default router;
@@ -0,0 +1,55 @@
1
+ import express from "express";
2
+ const router = express.Router();
3
+
4
+ // Simple in-memory metrics (resets on restart)
5
+ // In production with multiple instances, this is local to the instance.
6
+ const metrics = {
7
+ requests: {
8
+ "2xx": 0,
9
+ "4xx": 0,
10
+ "5xx": 0,
11
+ },
12
+ latencies: [], // Store last 1000 latencies for p95/p99 calculation
13
+ };
14
+
15
+ export const recordMetric = (statusCode, latency) => {
16
+ if (statusCode >= 200 && statusCode < 300) metrics.requests["2xx"]++;
17
+ else if (statusCode >= 400 && statusCode < 500) metrics.requests["4xx"]++;
18
+ else if (statusCode >= 500) metrics.requests["5xx"]++;
19
+
20
+ metrics.latencies.push(latency);
21
+ if (metrics.latencies.length > 1000) metrics.latencies.shift();
22
+ };
23
+
24
+ const calculatePercentile = (percentile) => {
25
+ if (metrics.latencies.length === 0) return 0;
26
+ const sorted = [...metrics.latencies].sort((a, b) => a - b);
27
+ const index = Math.ceil((percentile / 100) * sorted.length) - 1;
28
+ return sorted[index];
29
+ };
30
+
31
+ // MUST HAVE for Render Healthcheck
32
+ router.get("/health", (req, res) => {
33
+ res.status(200).json({
34
+ status: "ok",
35
+ uptime: process.uptime(),
36
+ timestamp: Date.now(),
37
+ });
38
+ });
39
+
40
+ // Metrics Endpoint
41
+ router.get("/metrics", (req, res) => {
42
+ res.json({
43
+ counts: metrics.requests,
44
+ p95: calculatePercentile(95),
45
+ p99: calculatePercentile(99),
46
+ sampleSize: metrics.latencies.length,
47
+ });
48
+ });
49
+
50
+ // Optional: readiness
51
+ router.get("/ready", (req, res) => {
52
+ res.status(200).json({ ready: true });
53
+ });
54
+
55
+ export default router;