pulpo-lib 0.1.0__tar.gz

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 (300) hide show
  1. pulpo_lib-0.1.0/.claude/commands/emergencia.md +57 -0
  2. pulpo_lib-0.1.0/.env.example +16 -0
  3. pulpo_lib-0.1.0/.gitignore +61 -0
  4. pulpo_lib-0.1.0/CLAUDE.md +267 -0
  5. pulpo_lib-0.1.0/NEXT_SESSION.md +70 -0
  6. pulpo_lib-0.1.0/PKG-INFO +220 -0
  7. pulpo_lib-0.1.0/README.md +180 -0
  8. pulpo_lib-0.1.0/backend/NUEVO_DISENO_TRIGGERS.md +186 -0
  9. pulpo_lib-0.1.0/backend/api/__init__.py +0 -0
  10. pulpo_lib-0.1.0/backend/api/architecture.py +172 -0
  11. pulpo_lib-0.1.0/backend/api/auth.py +21 -0
  12. pulpo_lib-0.1.0/backend/api/auth_bot.py +100 -0
  13. pulpo_lib-0.1.0/backend/api/bot_portal.py +397 -0
  14. pulpo_lib-0.1.0/backend/api/bots.py +137 -0
  15. pulpo_lib-0.1.0/backend/api/client.py +152 -0
  16. pulpo_lib-0.1.0/backend/api/connections.py +272 -0
  17. pulpo_lib-0.1.0/backend/api/contacts.py +145 -0
  18. pulpo_lib-0.1.0/backend/api/deps.py +16 -0
  19. pulpo_lib-0.1.0/backend/api/fb_session.py +82 -0
  20. pulpo_lib-0.1.0/backend/api/flows.py +419 -0
  21. pulpo_lib-0.1.0/backend/api/logs.py +76 -0
  22. pulpo_lib-0.1.0/backend/api/messages.py +17 -0
  23. pulpo_lib-0.1.0/backend/api/settings.py +26 -0
  24. pulpo_lib-0.1.0/backend/api/sim.py +70 -0
  25. pulpo_lib-0.1.0/backend/api/summarizer.py +699 -0
  26. pulpo_lib-0.1.0/backend/api/telegram_api.py +134 -0
  27. pulpo_lib-0.1.0/backend/api/wavi.py +132 -0
  28. pulpo_lib-0.1.0/backend/auth_jwt.py +51 -0
  29. pulpo_lib-0.1.0/backend/automation/__init__.py +0 -0
  30. pulpo_lib-0.1.0/backend/automation/browser.py +150 -0
  31. pulpo_lib-0.1.0/backend/bots/__init__.py +0 -0
  32. pulpo_lib-0.1.0/backend/bots/telegram_bot.py +122 -0
  33. pulpo_lib-0.1.0/backend/config/auspiciantes/luganense.json +40 -0
  34. pulpo_lib-0.1.0/backend/config/oficios/luganense.json +63 -0
  35. pulpo_lib-0.1.0/backend/config.py +125 -0
  36. pulpo_lib-0.1.0/backend/db.py +822 -0
  37. pulpo_lib-0.1.0/backend/graphs/__init__.py +0 -0
  38. pulpo_lib-0.1.0/backend/graphs/auspiciantes.py +62 -0
  39. pulpo_lib-0.1.0/backend/graphs/collections/__init__.py +39 -0
  40. pulpo_lib-0.1.0/backend/graphs/collections/luganense.py +115 -0
  41. pulpo_lib-0.1.0/backend/graphs/compiler.py +301 -0
  42. pulpo_lib-0.1.0/backend/graphs/cooldown.py +76 -0
  43. pulpo_lib-0.1.0/backend/graphs/luganense.py +439 -0
  44. pulpo_lib-0.1.0/backend/graphs/node_types.py +196 -0
  45. pulpo_lib-0.1.0/backend/graphs/nodes/__init__.py +73 -0
  46. pulpo_lib-0.1.0/backend/graphs/nodes/api_trigger.py +16 -0
  47. pulpo_lib-0.1.0/backend/graphs/nodes/base.py +68 -0
  48. pulpo_lib-0.1.0/backend/graphs/nodes/base_trigger.py +58 -0
  49. pulpo_lib-0.1.0/backend/graphs/nodes/check_contact.py +58 -0
  50. pulpo_lib-0.1.0/backend/graphs/nodes/fetch.py +155 -0
  51. pulpo_lib-0.1.0/backend/graphs/nodes/fetch_sheet.py +153 -0
  52. pulpo_lib-0.1.0/backend/graphs/nodes/gsheet.py +341 -0
  53. pulpo_lib-0.1.0/backend/graphs/nodes/llm.py +225 -0
  54. pulpo_lib-0.1.0/backend/graphs/nodes/message_join.py +20 -0
  55. pulpo_lib-0.1.0/backend/graphs/nodes/message_trigger.py +13 -0
  56. pulpo_lib-0.1.0/backend/graphs/nodes/reply.py +114 -0
  57. pulpo_lib-0.1.0/backend/graphs/nodes/router.py +86 -0
  58. pulpo_lib-0.1.0/backend/graphs/nodes/save_attachment.py +71 -0
  59. pulpo_lib-0.1.0/backend/graphs/nodes/save_contact.py +78 -0
  60. pulpo_lib-0.1.0/backend/graphs/nodes/search_sheet.py +170 -0
  61. pulpo_lib-0.1.0/backend/graphs/nodes/set_state.py +36 -0
  62. pulpo_lib-0.1.0/backend/graphs/nodes/state.py +52 -0
  63. pulpo_lib-0.1.0/backend/graphs/nodes/summarize.py +755 -0
  64. pulpo_lib-0.1.0/backend/graphs/nodes/telegram_trigger.py +11 -0
  65. pulpo_lib-0.1.0/backend/graphs/nodes/transcribe_audio.py +61 -0
  66. pulpo_lib-0.1.0/backend/graphs/nodes/vector_search.py +258 -0
  67. pulpo_lib-0.1.0/backend/graphs/nodes/whatsapp_trigger.py +11 -0
  68. pulpo_lib-0.1.0/backend/graphs/trigger_match.py +206 -0
  69. pulpo_lib-0.1.0/backend/main.py +353 -0
  70. pulpo_lib-0.1.0/backend/middleware_auth.py +19 -0
  71. pulpo_lib-0.1.0/backend/migrate_legacy_flows.py +111 -0
  72. pulpo_lib-0.1.0/backend/migrate_simple.py +78 -0
  73. pulpo_lib-0.1.0/backend/nodes/__init__.py +0 -0
  74. pulpo_lib-0.1.0/backend/nodes/_login_fb.py +98 -0
  75. pulpo_lib-0.1.0/backend/nodes/_test_fb.py +36 -0
  76. pulpo_lib-0.1.0/backend/nodes/_test_fb2.py +62 -0
  77. pulpo_lib-0.1.0/backend/nodes/_test_fb3.py +51 -0
  78. pulpo_lib-0.1.0/backend/nodes/fb_cache.py +253 -0
  79. pulpo_lib-0.1.0/backend/nodes/fetch_facebook.py +630 -0
  80. pulpo_lib-0.1.0/backend/nodes/find_worker.py +82 -0
  81. pulpo_lib-0.1.0/backend/nodes/notify_worker.py +76 -0
  82. pulpo_lib-0.1.0/backend/paused.py +58 -0
  83. pulpo_lib-0.1.0/backend/requirements.txt +17 -0
  84. pulpo_lib-0.1.0/backend/sim.py +138 -0
  85. pulpo_lib-0.1.0/backend/start.sh +32 -0
  86. pulpo_lib-0.1.0/backend/state.py +21 -0
  87. pulpo_lib-0.1.0/backend/teli_poller.py +212 -0
  88. pulpo_lib-0.1.0/backend/tests/conftest.py +145 -0
  89. pulpo_lib-0.1.0/backend/tests/test_architecture.py +91 -0
  90. pulpo_lib-0.1.0/backend/tests/test_audio_transcription.py +509 -0
  91. pulpo_lib-0.1.0/backend/tests/test_auth.py +42 -0
  92. pulpo_lib-0.1.0/backend/tests/test_bot_portal.py +132 -0
  93. pulpo_lib-0.1.0/backend/tests/test_bot_safety.py +413 -0
  94. pulpo_lib-0.1.0/backend/tests/test_browser_zoom.py +128 -0
  95. pulpo_lib-0.1.0/backend/tests/test_connections.py +175 -0
  96. pulpo_lib-0.1.0/backend/tests/test_contacts.py +148 -0
  97. pulpo_lib-0.1.0/backend/tests/test_fb_cache.py +189 -0
  98. pulpo_lib-0.1.0/backend/tests/test_fetch_facebook_logs.py +114 -0
  99. pulpo_lib-0.1.0/backend/tests/test_fetch_facebook_urls.py +52 -0
  100. pulpo_lib-0.1.0/backend/tests/test_fetch_sheet.py +164 -0
  101. pulpo_lib-0.1.0/backend/tests/test_flow_safety.py +934 -0
  102. pulpo_lib-0.1.0/backend/tests/test_flows.py +227 -0
  103. pulpo_lib-0.1.0/backend/tests/test_google_connections.py +119 -0
  104. pulpo_lib-0.1.0/backend/tests/test_gsheet.py +164 -0
  105. pulpo_lib-0.1.0/backend/tests/test_hierarchical_ids.py +277 -0
  106. pulpo_lib-0.1.0/backend/tests/test_logs.py +112 -0
  107. pulpo_lib-0.1.0/backend/tests/test_search_sheet.py +148 -0
  108. pulpo_lib-0.1.0/backend/tests/test_sim.py +202 -0
  109. pulpo_lib-0.1.0/backend/tests/test_summarize_dedup.py +280 -0
  110. pulpo_lib-0.1.0/backend/tests/test_sync_security.py +113 -0
  111. pulpo_lib-0.1.0/backend/tests/test_telegram_startup.py +193 -0
  112. pulpo_lib-0.1.0/backend/tests/test_trigger_match.py +286 -0
  113. pulpo_lib-0.1.0/backend/tests/test_tuning.py +554 -0
  114. pulpo_lib-0.1.0/backend/tests/test_vector_search.py +146 -0
  115. pulpo_lib-0.1.0/backend/tests/test_wavi_api.py +55 -0
  116. pulpo_lib-0.1.0/backend/tests/test_wavi_dedup.py +79 -0
  117. pulpo_lib-0.1.0/backend/tools/__init__.py +0 -0
  118. pulpo_lib-0.1.0/backend/tools/debug_audio.py +219 -0
  119. pulpo_lib-0.1.0/backend/tools/teli_driver.py +17 -0
  120. pulpo_lib-0.1.0/backend/tools/transcription.py +39 -0
  121. pulpo_lib-0.1.0/backend/tools/wavi_driver.py +181 -0
  122. pulpo_lib-0.1.0/backend/wavi_poller.py +175 -0
  123. pulpo_lib-0.1.0/com.josetabuyo.pulpo.plist +35 -0
  124. pulpo_lib-0.1.0/frontend/.gitignore +24 -0
  125. pulpo_lib-0.1.0/frontend/README.md +8 -0
  126. pulpo_lib-0.1.0/frontend/eslint.config.js +38 -0
  127. pulpo_lib-0.1.0/frontend/index.html +13 -0
  128. pulpo_lib-0.1.0/frontend/package-lock.json +8045 -0
  129. pulpo_lib-0.1.0/frontend/package.json +37 -0
  130. pulpo_lib-0.1.0/frontend/playwright.config.cjs +37 -0
  131. pulpo_lib-0.1.0/frontend/public/pulpo.svg +18 -0
  132. pulpo_lib-0.1.0/frontend/public/vite.svg +1 -0
  133. pulpo_lib-0.1.0/frontend/src/App.css +1 -0
  134. pulpo_lib-0.1.0/frontend/src/App.jsx +20 -0
  135. pulpo_lib-0.1.0/frontend/src/SimChat.jsx +49 -0
  136. pulpo_lib-0.1.0/frontend/src/api.js +32 -0
  137. pulpo_lib-0.1.0/frontend/src/assets/react.svg +1 -0
  138. pulpo_lib-0.1.0/frontend/src/components/ArchitectureSection.jsx +250 -0
  139. pulpo_lib-0.1.0/frontend/src/components/BotCard.jsx +322 -0
  140. pulpo_lib-0.1.0/frontend/src/components/ChatWidget.jsx +102 -0
  141. pulpo_lib-0.1.0/frontend/src/components/ContactFilterEditor.jsx +286 -0
  142. pulpo_lib-0.1.0/frontend/src/components/FlowCanvas.jsx +225 -0
  143. pulpo_lib-0.1.0/frontend/src/components/FlowEditor.jsx +106 -0
  144. pulpo_lib-0.1.0/frontend/src/components/FlowHeader.jsx +98 -0
  145. pulpo_lib-0.1.0/frontend/src/components/FlowList.jsx +248 -0
  146. pulpo_lib-0.1.0/frontend/src/components/MonitorPanel.jsx +407 -0
  147. pulpo_lib-0.1.0/frontend/src/components/NodeConfigPanel.jsx +61 -0
  148. pulpo_lib-0.1.0/frontend/src/components/NodePalette.jsx +214 -0
  149. pulpo_lib-0.1.0/frontend/src/components/StatusBadge.jsx +19 -0
  150. pulpo_lib-0.1.0/frontend/src/components/SummaryContactList.jsx +43 -0
  151. pulpo_lib-0.1.0/frontend/src/components/SummaryView.jsx +995 -0
  152. pulpo_lib-0.1.0/frontend/src/components/UIsList.jsx +29 -0
  153. pulpo_lib-0.1.0/frontend/src/components/architecture.css +181 -0
  154. pulpo_lib-0.1.0/frontend/src/components/bot/BotConfigTab.jsx +61 -0
  155. pulpo_lib-0.1.0/frontend/src/components/bot/ConnectionRow.jsx +100 -0
  156. pulpo_lib-0.1.0/frontend/src/components/bot/GoogleConnections.jsx +184 -0
  157. pulpo_lib-0.1.0/frontend/src/components/bot/WaviConnections.jsx +81 -0
  158. pulpo_lib-0.1.0/frontend/src/components/bot/widgets.jsx +61 -0
  159. pulpo_lib-0.1.0/frontend/src/components/nodeconfig/ConfigForm.jsx +384 -0
  160. pulpo_lib-0.1.0/frontend/src/components/nodeconfig/FbCacheModal.jsx +125 -0
  161. pulpo_lib-0.1.0/frontend/src/components/nodeconfig/SheetCacheButton.jsx +34 -0
  162. pulpo_lib-0.1.0/frontend/src/components/nodeconfig/SummarizeInfo.jsx +115 -0
  163. pulpo_lib-0.1.0/frontend/src/components/nodeconfig/fields.jsx +317 -0
  164. pulpo_lib-0.1.0/frontend/src/components/nodeconfig/styles.js +65 -0
  165. pulpo_lib-0.1.0/frontend/src/hooks/useFbSession.js +74 -0
  166. pulpo_lib-0.1.0/frontend/src/index.css +1876 -0
  167. pulpo_lib-0.1.0/frontend/src/lib/auth.js +49 -0
  168. pulpo_lib-0.1.0/frontend/src/main.jsx +13 -0
  169. pulpo_lib-0.1.0/frontend/src/pages/BotPage.jsx +225 -0
  170. pulpo_lib-0.1.0/frontend/src/pages/DashboardPage.jsx +530 -0
  171. pulpo_lib-0.1.0/frontend/src/pages/LoginPage.jsx +71 -0
  172. pulpo_lib-0.1.0/frontend/src/pages/NewBotPage.jsx +222 -0
  173. pulpo_lib-0.1.0/frontend/src/store/flowStore.js +215 -0
  174. pulpo_lib-0.1.0/frontend/tests/architecture.spec.cjs +63 -0
  175. pulpo_lib-0.1.0/frontend/tests/bot_safety.spec.cjs +66 -0
  176. pulpo_lib-0.1.0/frontend/tests/flows.spec.cjs +145 -0
  177. pulpo_lib-0.1.0/frontend/tests/login.spec.cjs +62 -0
  178. pulpo_lib-0.1.0/frontend/tests/monitor.spec.cjs +179 -0
  179. pulpo_lib-0.1.0/frontend/tests/summary_bubble.spec.cjs +373 -0
  180. pulpo_lib-0.1.0/frontend/vite.config.js +40 -0
  181. pulpo_lib-0.1.0/memory/project_audio_feature.md +11 -0
  182. pulpo_lib-0.1.0/monitoring.json +23 -0
  183. pulpo_lib-0.1.0/phones.example.json +27 -0
  184. pulpo_lib-0.1.0/pulpo/__init__.py +31 -0
  185. pulpo_lib-0.1.0/pulpo/automation/__init__.py +0 -0
  186. pulpo_lib-0.1.0/pulpo/automation/browser.py +150 -0
  187. pulpo_lib-0.1.0/pulpo/bots/__init__.py +0 -0
  188. pulpo_lib-0.1.0/pulpo/bots/telegram_bot.py +122 -0
  189. pulpo_lib-0.1.0/pulpo/business/__init__.py +0 -0
  190. pulpo_lib-0.1.0/pulpo/business/architecture.py +149 -0
  191. pulpo_lib-0.1.0/pulpo/business/bots.py +136 -0
  192. pulpo_lib-0.1.0/pulpo/business/connections.py +205 -0
  193. pulpo_lib-0.1.0/pulpo/business/contacts.py +117 -0
  194. pulpo_lib-0.1.0/pulpo/business/flows.py +293 -0
  195. pulpo_lib-0.1.0/pulpo/business/messages.py +17 -0
  196. pulpo_lib-0.1.0/pulpo/business/settings.py +25 -0
  197. pulpo_lib-0.1.0/pulpo/business/sim.py +87 -0
  198. pulpo_lib-0.1.0/pulpo/business/wavi.py +153 -0
  199. pulpo_lib-0.1.0/pulpo/core/__init__.py +0 -0
  200. pulpo_lib-0.1.0/pulpo/core/auth_jwt.py +50 -0
  201. pulpo_lib-0.1.0/pulpo/core/config.py +100 -0
  202. pulpo_lib-0.1.0/pulpo/core/db.py +822 -0
  203. pulpo_lib-0.1.0/pulpo/core/lifespan.py +205 -0
  204. pulpo_lib-0.1.0/pulpo/core/state.py +7 -0
  205. pulpo_lib-0.1.0/pulpo/graphs/__init__.py +0 -0
  206. pulpo_lib-0.1.0/pulpo/graphs/auspiciantes.py +62 -0
  207. pulpo_lib-0.1.0/pulpo/graphs/collections/__init__.py +39 -0
  208. pulpo_lib-0.1.0/pulpo/graphs/collections/luganense.py +115 -0
  209. pulpo_lib-0.1.0/pulpo/graphs/compiler.py +301 -0
  210. pulpo_lib-0.1.0/pulpo/graphs/cooldown.py +76 -0
  211. pulpo_lib-0.1.0/pulpo/graphs/luganense.py +439 -0
  212. pulpo_lib-0.1.0/pulpo/graphs/node_types.py +196 -0
  213. pulpo_lib-0.1.0/pulpo/graphs/nodes/__init__.py +73 -0
  214. pulpo_lib-0.1.0/pulpo/graphs/nodes/api_trigger.py +16 -0
  215. pulpo_lib-0.1.0/pulpo/graphs/nodes/base.py +68 -0
  216. pulpo_lib-0.1.0/pulpo/graphs/nodes/base_trigger.py +58 -0
  217. pulpo_lib-0.1.0/pulpo/graphs/nodes/check_contact.py +58 -0
  218. pulpo_lib-0.1.0/pulpo/graphs/nodes/fetch.py +155 -0
  219. pulpo_lib-0.1.0/pulpo/graphs/nodes/fetch_sheet.py +153 -0
  220. pulpo_lib-0.1.0/pulpo/graphs/nodes/gsheet.py +341 -0
  221. pulpo_lib-0.1.0/pulpo/graphs/nodes/llm.py +225 -0
  222. pulpo_lib-0.1.0/pulpo/graphs/nodes/message_join.py +20 -0
  223. pulpo_lib-0.1.0/pulpo/graphs/nodes/message_trigger.py +13 -0
  224. pulpo_lib-0.1.0/pulpo/graphs/nodes/reply.py +114 -0
  225. pulpo_lib-0.1.0/pulpo/graphs/nodes/router.py +86 -0
  226. pulpo_lib-0.1.0/pulpo/graphs/nodes/save_attachment.py +71 -0
  227. pulpo_lib-0.1.0/pulpo/graphs/nodes/save_contact.py +78 -0
  228. pulpo_lib-0.1.0/pulpo/graphs/nodes/search_sheet.py +170 -0
  229. pulpo_lib-0.1.0/pulpo/graphs/nodes/set_state.py +36 -0
  230. pulpo_lib-0.1.0/pulpo/graphs/nodes/state.py +52 -0
  231. pulpo_lib-0.1.0/pulpo/graphs/nodes/summarize.py +755 -0
  232. pulpo_lib-0.1.0/pulpo/graphs/nodes/telegram_trigger.py +11 -0
  233. pulpo_lib-0.1.0/pulpo/graphs/nodes/transcribe_audio.py +61 -0
  234. pulpo_lib-0.1.0/pulpo/graphs/nodes/vector_search.py +258 -0
  235. pulpo_lib-0.1.0/pulpo/graphs/nodes/whatsapp_trigger.py +11 -0
  236. pulpo_lib-0.1.0/pulpo/graphs/trigger_match.py +206 -0
  237. pulpo_lib-0.1.0/pulpo/interfaces/__init__.py +0 -0
  238. pulpo_lib-0.1.0/pulpo/interfaces/api/__init__.py +0 -0
  239. pulpo_lib-0.1.0/pulpo/interfaces/api/app.py +18 -0
  240. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/__init__.py +0 -0
  241. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/architecture.py +49 -0
  242. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/bots.py +80 -0
  243. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/connections.py +195 -0
  244. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/contacts.py +141 -0
  245. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/flows.py +221 -0
  246. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/logs.py +89 -0
  247. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/messages.py +19 -0
  248. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/settings.py +40 -0
  249. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/sim.py +98 -0
  250. pulpo_lib-0.1.0/pulpo/interfaces/api/routers/wavi.py +117 -0
  251. pulpo_lib-0.1.0/pulpo/interfaces/cli/__init__.py +0 -0
  252. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/__init__.py +0 -0
  253. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/bots.py +38 -0
  254. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/connections.py +38 -0
  255. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/contacts.py +38 -0
  256. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/flows.py +73 -0
  257. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/messages.py +17 -0
  258. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/server.py +33 -0
  259. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/settings.py +40 -0
  260. pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/sim.py +44 -0
  261. pulpo_lib-0.1.0/pulpo/interfaces/cli/main.py +17 -0
  262. pulpo_lib-0.1.0/pulpo/interfaces/lib/__init__.py +52 -0
  263. pulpo_lib-0.1.0/pulpo/interfaces/ui/__init__.py +0 -0
  264. pulpo_lib-0.1.0/pulpo/interfaces/ui/app.py +32 -0
  265. pulpo_lib-0.1.0/pulpo/interfaces/ui/deps.py +16 -0
  266. pulpo_lib-0.1.0/pulpo/interfaces/ui/middleware.py +19 -0
  267. pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/__init__.py +0 -0
  268. pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/auth.py +19 -0
  269. pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/auth_bot.py +99 -0
  270. pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/bot_portal.py +403 -0
  271. pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/client.py +163 -0
  272. pulpo_lib-0.1.0/pulpo/nodes/__init__.py +0 -0
  273. pulpo_lib-0.1.0/pulpo/nodes/_login_fb.py +98 -0
  274. pulpo_lib-0.1.0/pulpo/nodes/_test_fb.py +36 -0
  275. pulpo_lib-0.1.0/pulpo/nodes/_test_fb2.py +62 -0
  276. pulpo_lib-0.1.0/pulpo/nodes/_test_fb3.py +51 -0
  277. pulpo_lib-0.1.0/pulpo/nodes/fb_cache.py +253 -0
  278. pulpo_lib-0.1.0/pulpo/nodes/fetch_facebook.py +630 -0
  279. pulpo_lib-0.1.0/pulpo/nodes/find_worker.py +82 -0
  280. pulpo_lib-0.1.0/pulpo/nodes/notify_worker.py +76 -0
  281. pulpo_lib-0.1.0/pulpo/tools/__init__.py +0 -0
  282. pulpo_lib-0.1.0/pulpo/tools/debug_audio.py +219 -0
  283. pulpo_lib-0.1.0/pulpo/tools/teli_driver.py +17 -0
  284. pulpo_lib-0.1.0/pulpo/tools/transcription.py +39 -0
  285. pulpo_lib-0.1.0/pulpo/tools/wavi_driver.py +181 -0
  286. pulpo_lib-0.1.0/pyproject.toml +64 -0
  287. pulpo_lib-0.1.0/restart-backend.sh +15 -0
  288. pulpo_lib-0.1.0/rotate-logs.sh +31 -0
  289. pulpo_lib-0.1.0/scripts/fb_check_cookies.py +135 -0
  290. pulpo_lib-0.1.0/scripts/fb_login.py +121 -0
  291. pulpo_lib-0.1.0/scripts/migrate_empresa_to_bot.py +69 -0
  292. pulpo_lib-0.1.0/scripts/refactor_empresa_to_bot.py +150 -0
  293. pulpo_lib-0.1.0/scripts/test_fb_debug.py +189 -0
  294. pulpo_lib-0.1.0/start.sh +116 -0
  295. pulpo_lib-0.1.0/stop-backend.sh +12 -0
  296. pulpo_lib-0.1.0/tests/conftest.py +70 -0
  297. pulpo_lib-0.1.0/tests/test_architecture.py +89 -0
  298. pulpo_lib-0.1.0/tests/test_cli.py +45 -0
  299. pulpo_lib-0.1.0/tests/test_imports.py +81 -0
  300. pulpo_lib-0.1.0/watch_sync.py +59 -0
@@ -0,0 +1,57 @@
1
+ # /emergencia — Inicializar el sistema de monitoreo Pulpo
2
+
3
+ Sos el sistema de guardia de Pulpo (Emergencia On Going).
4
+ Ejecutá estos pasos en orden sin pedir confirmación:
5
+
6
+ ## Paso 1 — Chequeo de estado actual
7
+
8
+ Corré estos dos comandos en paralelo:
9
+ - `curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/bots`
10
+ - `curl -s -o /dev/null -w "%{http_code}" http://localhost:5173`
11
+
12
+ Interpretación: backend UP = responde cualquier código ≠ "000". Frontend UP = responde 200.
13
+
14
+ ## Paso 2 — Ver últimas líneas del log
15
+
16
+ ```
17
+ tail -10 /Users/josetabuyo/Development/pulpo/_/monitor/backend.log
18
+ ```
19
+
20
+ ## Paso 3 — Activar el loop de monitoreo horario
21
+
22
+ Creá un CronCreate con:
23
+ - cron: `"7 * * * *"` (cada hora a los :07)
24
+ - recurring: true
25
+ - prompt (copiar verbatim):
26
+
27
+ ```
28
+ MONITOREO PULPO — chequeo automático horario. Ejecutar sin pedir confirmación:
29
+
30
+ 1. En paralelo: (a) curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/bots (b) curl -s -o /dev/null -w "%{http_code}" http://localhost:5173
31
+
32
+ 2. Backend DOWN si resultado es "000" o comando falla. Frontend DOWN si resultado no es "200".
33
+
34
+ 3. Si backend DOWN:
35
+ a. Bash: lsof -i :8000 | grep LISTEN
36
+ b. Si hay proceso que NO sea Pulpo (uvicorn de /Development/pulpo): Bash: say -v "Paulina" "Atención! El puerto 8000 está ocupado por otra aplicación. Pulpo no puede levantarse."
37
+ c. Si el puerto está libre o el proceso es Pulpo caído: Bash (desde /Users/josetabuyo/Development/pulpo/_): ./start.sh back
38
+ d. Bash: sleep 8
39
+ e. Volver a chequear: curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/bots
40
+ f. Si sigue DOWN: usar Agent con model="sonnet" con este prompt: "El backend de Pulpo en /Users/josetabuyo/Development/pulpo/_ está caído y no levantó con start.sh. Leé las últimas 60 líneas de monitor/backend.log, identificá la causa raíz y aplicá la corrección mínima necesaria. Si no podés resolverlo, reportá exactamente qué encontraste."
41
+ g. Bash: say -v "Paulina" "Emergencia! Emergencia! El backend de Pulpo cayó y no pudo recuperarse solo. Requiere atención inmediata."
42
+
43
+ 4. Si frontend DOWN:
44
+ a. Bash (desde /Users/josetabuyo/Development/pulpo/_): ./start.sh front
45
+ b. Bash: say -v "Paulina" "Alerta! El frontend de Pulpo estaba caído. Intentando levantar."
46
+
47
+ 5. Si todo OK: no hacer nada, no emitir ningún texto ni mensaje.
48
+ ```
49
+
50
+ ## Paso 4 — Reportar al usuario
51
+
52
+ Mostrar un resumen claro:
53
+ - Backend: UP / DOWN
54
+ - Frontend: UP / DOWN
55
+ - Últimas líneas relevantes del log (sesiones WA activas)
56
+ - Job ID del cron activo
57
+ - Instrucción: "Para restablecer este sistema en una sesión nueva, usar /emergencia"
@@ -0,0 +1,16 @@
1
+ # ============================================================
2
+ # PUERTOS DE ESTE AMBIENTE
3
+ # Cada worktree tiene su propio .env con puertos únicos.
4
+ # master (estable): BACKEND_PORT=8000 FRONTEND_PORT=5173
5
+ # dev-1: BACKEND_PORT=8001 FRONTEND_PORT=5174
6
+ # dev-2: BACKEND_PORT=8002 FRONTEND_PORT=5175
7
+ # ============================================================
8
+ BACKEND_PORT=8000
9
+ FRONTEND_PORT=5173
10
+
11
+ # Contraseñas de acceso
12
+ ADMIN_PASSWORD=admin
13
+ CLIENT_PASSWORD=conectar
14
+
15
+ # Ruta al ejecutable de Chrome (cambiar en Linux)
16
+ # CHROME_PATH=/usr/bin/google-chrome
@@ -0,0 +1,61 @@
1
+ # Management / handoffs — documentos internos, no van al repo
2
+ management/
3
+
4
+ # Environment
5
+ .env
6
+
7
+ # Configuración de conexiones (datos sensibles)
8
+ connections.json
9
+
10
+ # WhatsApp session
11
+ .wwebjs_auth/
12
+ .wwebjs_cache/
13
+
14
+ # SQLite database
15
+ data/
16
+
17
+ # Dependencies
18
+ node_modules/
19
+
20
+ # Logs
21
+ *.log
22
+ npm-debug.log*
23
+
24
+ # Python
25
+ backend/.venv/
26
+ .venv-pulpo/
27
+ __pycache__/
28
+ *.pyc
29
+ *.egg-info/
30
+ dist/
31
+ build/
32
+
33
+ # Backups
34
+ connections.json.bak_*
35
+ backend/output/
36
+
37
+ # Playwright
38
+ .playwright-mcp/
39
+ .playwright-cli/
40
+ backend/.playwright-cli/
41
+ frontend/test-results/
42
+ frontend/playwright-report/
43
+
44
+ # Monitor logs
45
+ monitor/
46
+ data/summaries/
47
+ node_modules
48
+
49
+ # macOS
50
+ .DS_Store
51
+
52
+ # Sesión multi-agente y agente local
53
+ session/
54
+ .agent.json
55
+ .claude/settings.local.json
56
+
57
+ # Estado local de herramientas
58
+ backend/.node-persist/
59
+
60
+ # Colecciones Postman exportadas (locales)
61
+ backend/open-wa-*.json
@@ -0,0 +1,267 @@
1
+ # Pulpo — Contexto del proyecto
2
+
3
+ ## Forma de trabajar
4
+ - Responder siempre en **español**
5
+ - Para mensajes cortos: hablar via la cola del backend (nunca `say` directo — colisiona con otras voces):
6
+ ```bash
7
+ curl -s -X POST http://localhost:8700/queue/speak \
8
+ -H "Content-Type: application/json" \
9
+ -d '{"text":"...","voice":"Tessa","family":"Pulpo"}'
10
+ ```
11
+ - Para código, logs o texto largo: solo texto, sin voz
12
+ - Trabajar un problema a la vez
13
+
14
+ ## Comandos Bash — siempre simples y auditables
15
+
16
+ **Regla obligatoria:** cada llamada al Bash tool debe hacer **una sola cosa**.
17
+
18
+ - ✅ `grep "full-sync" backend.log`
19
+ - ✅ `tail -20 backend.log`
20
+ - ✅ `curl -s http://localhost:8000/health`
21
+ - ❌ `grep X | awk | xargs rm` — demasiado en un solo comando
22
+ - ❌ `kill $(ps aux | grep ... | awk ...)` — encadenar kill con subshell es peligroso
23
+
24
+ **Por qué:** el usuario puede aprobar/rechazar cada comando individualmente.
25
+ Si un comando hace A+B+C en un pipe, no puede aprobar A sin B.
26
+ Comandos simples = auditoría real.
27
+
28
+ **Cuando necesites encadenar:** pedir aprobación explícita o dividir en pasos separados.
29
+
30
+ ---
31
+
32
+ ## Multi-agente — Haiku y Opus
33
+
34
+ Al inicio de cada respuesta, chequeá silenciosamente si Haiku u Opus terminaron trabajo pendiente:
35
+
36
+ ```bash
37
+ ls session/haiku-done.flag session/opus-done.flag 2>/dev/null
38
+ ```
39
+
40
+ Si existe algún flag:
41
+ 1. Leé el final del outbox correspondiente (`tail -30 session/haiku-outbox.md`)
42
+ 2. Eliminá el flag (`rm session/haiku-done.flag`)
43
+ 3. Informame brevemente qué encontraron antes de responder mi pregunta
44
+
45
+ ### Delegar a Haiku
46
+
47
+ Haiku maneja: lectura masiva de archivos, búsquedas, tareas repetitivas, análisis de logs.
48
+
49
+ ```bash
50
+ echo "tu tarea con contexto completo" > session/haiku-inbox.md
51
+ ```
52
+
53
+ El resultado queda en `session/haiku-outbox.md`. Haiku avisa cuando termina con una notificación macOS.
54
+
55
+ ### Consultar a Opus
56
+
57
+ Opus asesora en decisiones de arquitectura, merges riesgosos, o cuando hay duda sobre impacto en producción.
58
+
59
+ ```bash
60
+ echo "contexto + pregunta preparada" > session/opus-inbox.md
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Rol de Claude en este proyecto
66
+
67
+ Claude en `_` (master) es el **orquestador y guardián de producción**:
68
+
69
+ 1. **Guardián de prod** — protege el servidor en `_`. Nada se toca en producción sin criterio. Sesiones WA son valiosas: nunca `pkill -9`, nunca borrar perfiles Chrome sin confirmación.
70
+
71
+ 2. **Orquestador** — cuando hay una feature nueva, Claude crea el worktree, hace el setup completo y deja un `NEXT_SESSION.md` con el scope detallado para que otra sesión de Claude arranque sola en ese worktree.
72
+
73
+ 3. **Merges y push** — el merge a master y el push a origin los hace **siempre** la sesión de `_`, nunca un worktree.
74
+
75
+ 4. **Documentos de management** — planes, visión, arquitectura, estados van en `management/`. Son la fuente de verdad para planificar worktrees nuevos.
76
+
77
+ ---
78
+
79
+ ## Forma de trabajo: worktrees como ambientes independientes
80
+
81
+ Cada feature se desarrolla en su propio worktree, que es un servidor completamente independiente:
82
+
83
+ - **`_` (master)** → producción real. `ENABLE_BOTS=true`. Bots WA y Telegram reales corriendo.
84
+ - **Cualquier otro worktree** → ambiente de desarrollo. `ENABLE_BOTS=false`. Usa **simuladores** para WA y Telegram — no hay browser real, no hay conexiones reales. El pipeline completo (DB, auto_reply, config) funciona igual pero con datos simulados.
85
+
86
+ Esto permite desarrollar y testear sin arriesgar la sesión de producción ni los bots reales.
87
+
88
+ ### Ciclo de vida de una feature
89
+
90
+ ```
91
+ 1. Planificar → crear/actualizar doc en management/
92
+ 2. Crear worktree → git worktree add + setup completo + NEXT_SESSION.md
93
+ 3. Desarrollar → en la sesión Claude del worktree, modo simulado
94
+ 4. Mergear → desde la sesión de _, merge + push a origin
95
+ 5. ⚠️ ANTES de eliminar: bajar el backend del worktree → ./stop-backend.sh (desde el directorio del worktree)
96
+ 6. Eliminar worktree → git worktree remove --force
97
+ ```
98
+
99
+ > **Por qué el paso 5 es crítico:** un backend activo en un worktree tiene bots WA conectados.
100
+ > Si se elimina el worktree sin bajarlo, el proceso uvicorn queda huérfano corriendo en background,
101
+ > con bots activos que pueden procesar y responder mensajes. Esto ocurrió en producción (incidente abril 2026).
102
+
103
+ ---
104
+
105
+ ## Worktrees — setup obligatorio al crear uno nuevo
106
+
107
+ ### 1. Crear
108
+ ```bash
109
+ git worktree add /Users/josetabuyo/Development/pulpo/<rama> -b <rama>
110
+ ```
111
+
112
+ ### 2. Symlinks de archivos gitignoreados
113
+ ```bash
114
+ WDIR=/Users/josetabuyo/Development/pulpo/<rama>
115
+ ln -s /Users/josetabuyo/Development/pulpo/_/node_modules $WDIR/node_modules
116
+ ln -s /Users/josetabuyo/Development/pulpo/_/phones.json $WDIR/phones.json
117
+ # ⚠️ NO linkear data/ — cada worktree tiene su propia data/ aislada
118
+ # El backend la crea automáticamente al arrancar (messages.db vacía, sin sesiones WA reales)
119
+ mkdir -p $WDIR/data
120
+ ```
121
+
122
+ ### 3. `.env` con puertos únicos
123
+ ```
124
+ BACKEND_PORT=800X
125
+ FRONTEND_PORT=517X
126
+ ```
127
+
128
+ ### 4. Crear `NEXT_SESSION.md` con el scope completo para el Claude del worktree
129
+
130
+ ### 5. Puertos asignados
131
+ | Worktree | Backend | Frontend | Estado |
132
+ |--------------|---------|----------|--------------|
133
+ | `_` (master) | 8000 | 5173 | Producción |
134
+ | dev-1 | 8001 | 5174 | Libre |
135
+ | dev-2 | 8002 | 5175 | Libre |
136
+
137
+ ---
138
+
139
+ ## Stack actual (Python backend)
140
+
141
+ - **Backend**: FastAPI + uvicorn (sin `--reload` en producción, con `--reload` en worktrees dev)
142
+ - **Frontend**: React + Vite
143
+ - **DB**: SQLite (`data/messages.db`)
144
+ - **Config**: `phones.json` (gitignoreado)
145
+ - **WhatsApp**: Playwright headless — `launch_persistent_context`, perfil Chrome en `data/sessions/{number}/profile/`
146
+ - **Telegram**: python-telegram-bot, polling
147
+
148
+ ## Archivos clave
149
+ - `backend/main.py` — lifespan, routers, CORS
150
+ - `backend/state.py` — `clients` dict + `wa_session` singleton
151
+ - `backend/automation/whatsapp.py` — lógica WA Web con Playwright
152
+ - `backend/api/` — routers: auth, bots, phones, whatsapp, telegram, messages, sim, client
153
+ - `backend/sim.py` — motor del simulador (activo cuando `ENABLE_BOTS=false`)
154
+ - `frontend/src/pages/DashboardPage.jsx` — dashboard admin
155
+ - `frontend/src/pages/ConnectPage.jsx` — portal del cliente
156
+ - `phones.json` — configuración de bots y teléfonos (GITIGNOREADO)
157
+ - `data/messages.db` — base de datos (auto-creada)
158
+ - `data/sessions/` — perfiles Chrome persistentes por sesión WA
159
+ - `management/` — documentos de planificación y visión
160
+
161
+ ## Scripts y aliases — la única forma correcta de operar el servidor
162
+
163
+ Todos se corren parados en la raíz del worktree (`_/` para producción).
164
+ **Nunca usar comandos manuales de uvicorn ni matar procesos a mano.**
165
+
166
+ ### Scripts (en disco, ya aprobados)
167
+ ```bash
168
+ ./start.sh # levanta back + front
169
+ ./start.sh back # solo backend (si ya corre, no lo reinicia)
170
+ ./start.sh front # solo frontend
171
+ ./stop-backend.sh # detiene el backend con SIGTERM (seguro para WA)
172
+ ./restart-backend.sh # stop + sleep 3 + start back (safe: WA reconnecta sola)
173
+ ```
174
+
175
+ ### Aliases en ~/.zshrc (correr desde la raíz del worktree)
176
+ ```bash
177
+ start # alias de ./start.sh
178
+ log_back # tail -f ./monitor/backend.log
179
+ log_front # tail -f ./monitor/frontend.log
180
+ qdb "SQL" # query directo sobre data/messages.db de producción
181
+ ```
182
+
183
+ ### ⚠️ Regla de logs
184
+ `log_back` solo muestra logs cuando el servidor fue iniciado vía `./start.sh`
185
+ (que redirige stdout a `monitor/backend.log`).
186
+ Si el servidor se inició a mano en una terminal, los logs van a esa terminal — no al archivo.
187
+ **Siempre arrancar con `./start.sh` para que `log_back` funcione.**
188
+
189
+ ## Flujo de desarrollo — Tests primero
190
+
191
+ **El orden obligatorio, siempre:**
192
+ 1. Correr los tests existentes antes de tocar código (`pytest tests/ -v` + `playwright test`)
193
+ 2. Leer el output — los errores describen qué asume el sistema, valen más que leer código en frío
194
+ 3. Implementar hasta que los tests pasen
195
+ 4. Nunca mergear con tests en rojo
196
+
197
+ **Tests nuevos:**
198
+ - Lo ideal es seguir TDD: escribir el test antes de implementar
199
+ - Si agregar tests nuevos cuesta más que el cambio (layouts, prototipos, exploración), se pueden omitir en el medio y escribir al terminar el feature
200
+ - Si el cambio rompe un test existente de forma intencional (UI que cambió), actualizarlo es parte del trabajo
201
+
202
+ ## Tests
203
+
204
+ ### Backend (pytest + httpx — requiere server corriendo en :8001 o :8000)
205
+ ```bash
206
+ cd backend
207
+ pytest tests/ -v
208
+ ```
209
+ Archivos:
210
+ - `tests/test_auth.py` — auth, health, mode
211
+ - `tests/test_logs.py` — endpoint /api/logs/latest, auth, source inválido
212
+ - `tests/test_sim.py` — simulador: send, log de mensajes, connect/disconnect
213
+
214
+ ### Frontend (Playwright — requiere server corriendo)
215
+ ```bash
216
+ cd frontend
217
+ node_modules/.bin/playwright test
218
+ ```
219
+ Archivos:
220
+ - `tests/login.spec.cjs` — login, contraseña incorrecta, dashboard carga
221
+ - `tests/monitor.spec.cjs` — botón Monitor, drawer, log live, filtro, pausa, sim→log
222
+
223
+ > **Nota:** `pytest` y sus dependencias (`pytest-asyncio`, `httpx`) deben estar instalados en el venv:
224
+ > ```bash
225
+ > .venv/bin/pip install pytest pytest-asyncio httpx
226
+ > ```
227
+
228
+ ## Browsers automatizados — tres usos distintos
229
+
230
+ Hay tres tipos de browser Playwright/Chromium corriendo en paralelo. **Nunca confundirlos:**
231
+
232
+ | Tipo | Cómo identificarlo en `ps` | Tocar |
233
+ |------|---------------------------|-------|
234
+ | **playwright-cli** (Claude) | proceso CLI efímero (sin servidor permanente) — `playwright-cli open/close` | ✅ OK cerrar |
235
+ | **WA bots** | Chrome con `--user-data-dir=.../data/sessions/{número}/profile` | ❌ NUNCA |
236
+ | **Tests de UI** | Chrome lanzado por `playwright test` (también `/var/folders/...`) | ✅ OK (solo existen mientras corren tests) |
237
+
238
+ ### Cuando playwright-cli se traba
239
+ playwright-cli es un CLI global — **no hay servidor permanente**. Claude lo usa directamente via Bash: `playwright-cli open`, `playwright-cli goto`, `playwright-cli screenshot`, etc.
240
+
241
+ Si el browser se traba:
242
+ ```bash
243
+ # Cerrar la sesión actual
244
+ playwright-cli close
245
+
246
+ # Ver todas las sesiones abiertas y cerrarlas
247
+ playwright-cli list
248
+ playwright-cli close-all
249
+
250
+ # Si hay procesos zombie
251
+ playwright-cli kill-all
252
+ ```
253
+
254
+ Verificar que los WA bots sobrevivieron:
255
+ ```bash
256
+ ps aux | grep "data/sessions" | grep -v grep
257
+ ```
258
+
259
+ La clave para distinguir:
260
+ - `playwright-cli` (Claude) → efímero, sin user-data-dir persistente — cerrar OK
261
+ - `.../data/sessions/` → WA bot persistente — NUNCA tocar
262
+
263
+ ## Sesiones WhatsApp — reglas críticas
264
+ - **NUNCA `pkill -9`** en procesos Playwright/Chromium — SIGKILL corrompe el perfil Chrome y pierde la sesión WA
265
+ - Usar solo `pkill` (SIGTERM) para que Chrome guarde limpiamente
266
+ - El perfil persiste en disco — al reiniciar siempre intenta restaurar antes de pedir QR nuevo
267
+ - Nunca borrar `data/sessions/` sin confirmación explícita del usuario
@@ -0,0 +1,70 @@
1
+ # NEXT SESSION — Pipeline FB completado
2
+
3
+ ## Estado (sesión 2026-06-24)
4
+
5
+ Los tres pasos del pipeline FB están completos. No hay deuda pendiente en este tema.
6
+
7
+ ---
8
+
9
+ ### ✅ Paso 1 — Links en respuestas del LLM
10
+
11
+ **Qué se hizo:**
12
+ - Bug corregido: `_NOTICIAS_SYSTEM` no tenía cierre `"""` → `_AUSPICIANTE_SYSTEM` quedaba embebido
13
+ como texto y nunca era una variable Python (la rama `auspiciante` tiraba `NameError`).
14
+ - `responder_noticias` ahora arma el contexto con `Link: <url>` antes del texto de cada post.
15
+ - Prompt del LLM actualizado: le indica que cite el link al final de la oración relevante.
16
+ - Error path de `_scrape_post_page` corregido: ahora siempre retorna `{"url": url, ...}`.
17
+
18
+ **Archivos:**
19
+ - `backend/graphs/luganense.py` — líneas 68, 217, prompt `_NOTICIAS_SYSTEM`
20
+ - `backend/nodes/fetch_facebook.py` — línea 293
21
+
22
+ ---
23
+
24
+ ### ✅ Paso 2 — Límite de contexto
25
+
26
+ **Resultado:** sin cambios necesarios.
27
+ El modelo es `llama-3.3-70b-versatile` (Groq) con 128k tokens de contexto.
28
+ 30 posts × ~600 tokens = ~18k tokens → caben holgado.
29
+
30
+ ---
31
+
32
+ ### ✅ Paso 3 — Cache como read-through (sin LLM)
33
+
34
+ **Qué se hizo:**
35
+ - `buscar_posts_fb` ahora chequea `fb_cache.get_by_query` antes de scrapear FB.
36
+ - Si la query tiene posts en cache con menos de 24h de antigüedad → los reutiliza, no toca FB.
37
+ - Solo scrapea las queries sin cache hit.
38
+ - `get_by_query` acepta `max_age` (segundos); 0 = sin límite.
39
+ - El dedup semántico es implícito: `expandir_consulta` normaliza las queries
40
+ ("perdí mi perro" → "perro perdido"), así queries equivalentes reutilizan la misma entrada de cache.
41
+
42
+ **Archivos:**
43
+ - `backend/nodes/fb_cache.py` — `get_by_query(max_age=)`
44
+ - `backend/graphs/luganense.py` — `buscar_posts_fb` (lógica cache-first)
45
+
46
+ ---
47
+
48
+ ## Tests
49
+
50
+ ```bash
51
+ backend/.venv/bin/pytest backend/tests/test_fb_cache.py -v # 10/10
52
+ ```
53
+
54
+ ## Cómo verificar en vivo
55
+
56
+ ```bash
57
+ # Ver posts cacheados con sus URLs
58
+ qdb "SELECT url, substr(text,1,60) FROM fb_posts WHERE page_id='luganense' LIMIT 10"
59
+
60
+ # Ver queries guardadas
61
+ qdb "SELECT query, found_at FROM fb_post_queries ORDER BY found_at DESC LIMIT 10"
62
+
63
+ # Test de scraping real (abre browser visible)
64
+ backend/.venv/bin/python scripts/test_fb_debug.py --visible "perro perdido"
65
+ ```
66
+
67
+ En los logs del backend, el cache hit se ve como:
68
+ ```
69
+ [luganense] cache hit 'perro perdido': 12 posts (sin scrapear FB)
70
+ ```
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: pulpo-lib
3
+ Version: 0.1.0
4
+ Summary: Pulpo — bot orchestration engine with CLI, lib, API, and UI interfaces
5
+ Project-URL: Source, https://github.com/josetabuyo/pulpo
6
+ Author-email: José Tabuyo <josetabuyo@gmail.com>
7
+ License: MIT
8
+ Keywords: automation,bot,cli,telegram,whatsapp,workflow
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Python: >=3.11
17
+ Requires-Dist: aiofiles>=24.1.0
18
+ Requires-Dist: aiosqlite>=0.20.0
19
+ Requires-Dist: click>=8.1.0
20
+ Requires-Dist: fastapi>=0.115.0
21
+ Requires-Dist: google-api-python-client>=2.0.0
22
+ Requires-Dist: google-auth>=2.0.0
23
+ Requires-Dist: greenlet>=3.0.0
24
+ Requires-Dist: groq>=0.11.0
25
+ Requires-Dist: httpx>=0.27.0
26
+ Requires-Dist: langchain-groq>=1.1.0
27
+ Requires-Dist: langchain-openai>=0.2.0
28
+ Requires-Dist: langgraph>=1.1.0
29
+ Requires-Dist: passlib[bcrypt]>=1.7.4
30
+ Requires-Dist: playwright>=1.49.0
31
+ Requires-Dist: python-dotenv>=1.0.0
32
+ Requires-Dist: python-jose[cryptography]>=3.3.0
33
+ Requires-Dist: python-telegram-bot>=21.10.0
34
+ Requires-Dist: slowapi>=0.1.9
35
+ Requires-Dist: sqlalchemy>=2.0.0
36
+ Requires-Dist: teli-lib>=0.1.0
37
+ Requires-Dist: uvicorn[standard]>=0.32.0
38
+ Requires-Dist: wavi-lib>=0.2.0
39
+ Description-Content-Type: text/markdown
40
+
41
+ # 🐙 Pulpo
42
+
43
+ **Automatizá la atención de tu negocio por WhatsApp y Telegram.**
44
+
45
+ Pulpo conecta tus canales de mensajería a un sistema de bots inteligentes: respuesta automática, historial de conversaciones y gestión desde un portal propio. Sin código, sin complicaciones.
46
+
47
+ ---
48
+
49
+ ## ✨ ¿Qué hace Pulpo?
50
+
51
+ - **Respuesta automática** — tu bot responde al instante cuando no estás disponible
52
+ - **Multi-canal** — WhatsApp y Telegram desde un solo lugar
53
+ - **Portal de bot** — cada cliente gestiona sus canales, ve conversaciones y responde inline
54
+ - **Panel admin** — control total: agregar bots, ver estado de bots, monitorear en tiempo real
55
+
56
+ ---
57
+
58
+ ## 🚀 Empezar ahora
59
+
60
+ Accedé al portal público:
61
+
62
+ **[https://unbuoyant-surgeless-micheal.ngrok-free.dev/bot](https://unbuoyant-surgeless-micheal.ngrok-free.dev/bot)**
63
+
64
+ - ¿Ya tenés una cuenta? Ingresá con tu clave de bot.
65
+ - ¿Primera vez? → **[Crear bot nueva](https://unbuoyant-surgeless-micheal.ngrok-free.dev/bot/nueva)**
66
+
67
+ ---
68
+
69
+ ## 📲 Conectar Telegram paso a paso
70
+
71
+ Para agregar un bot de Telegram a tu bot en Pulpo:
72
+
73
+ ### 1. Crear el bot en Telegram
74
+
75
+ 1. Abrí Telegram y buscá **@BotFather**
76
+ 2. Enviá `/newbot`
77
+ 3. Elegí un nombre para tu bot (ej: `Soporte Herrería`)
78
+ 4. Elegí un username (debe terminar en `bot`, ej: `herreria_soporte_bot`)
79
+ 5. BotFather te va a dar un **token** con este formato:
80
+ ```
81
+ 123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
82
+ ```
83
+ 6. Guardalo — lo vas a necesitar en el paso siguiente
84
+
85
+ ### 2. Agregar el bot a Pulpo
86
+
87
+ 1. Entrá a tu portal: [https://unbuoyant-surgeless-micheal.ngrok-free.dev/bot](https://unbuoyant-surgeless-micheal.ngrok-free.dev/bot)
88
+ 2. En la sección **Telegram**, pegá el token en el campo y hacé click en **+ Agregar**
89
+ 3. Listo — el bot ya está activo y respondiendo
90
+
91
+ ### 3. Activar el bot
92
+
93
+ Compartí el link de tu bot (`t.me/herreria_soporte_bot`) con tus clientes. Cuando te escriban, Pulpo:
94
+ - Responde automáticamente con tu mensaje configurado
95
+ - Registra la conversación en tu portal
96
+ - Te permite responder manualmente desde el chat inline
97
+
98
+ ---
99
+
100
+ ## 📱 Conectar WhatsApp
101
+
102
+ 1. En la sección **WhatsApp** del portal, ingresá tu número (formato internacional sin `+`, ej: `5491155612767`)
103
+ 2. Click en **+ Agregar** → aparece un código QR
104
+ 3. En tu WhatsApp móvil: **Dispositivos vinculados → Vincular dispositivo** → escaneá el QR
105
+ 4. En 10-20 segundos el estado pasa a **Conectado**
106
+
107
+ > El bot mantiene la sesión activa. Si se desconecta, podés reconectar desde el portal sin perder el historial.
108
+
109
+ ---
110
+
111
+ ## 🛠️ Stack técnico
112
+
113
+ | Componente | Tecnología |
114
+ |---------------|-------------------------------------------------|
115
+ | API REST | FastAPI + uvicorn |
116
+ | Frontend | React + Vite |
117
+ | Base de datos | SQLite async (`data/messages.db`) |
118
+ | WhatsApp | Playwright headless (perfil Chrome persistente) |
119
+ | Telegram | python-telegram-bot v21 |
120
+ | Exposición | ngrok (etapa 1) → Cloudflare Tunnel (etapa 2) |
121
+
122
+ ---
123
+
124
+ ## ⚡ Desarrollo local
125
+
126
+ ### Requisitos
127
+
128
+ - Python 3.11+
129
+ - Node 18+
130
+ - `phones.json` con la configuración de bots
131
+
132
+ ### Arrancar
133
+
134
+ ```bash
135
+ ./start.sh # levanta backend (uvicorn) + frontend (vite)
136
+ ```
137
+
138
+ Los puertos se leen del `.env` en la raíz:
139
+
140
+ ```env
141
+ BACKEND_PORT=8000
142
+ FRONTEND_PORT=5173
143
+ ADMIN_PASSWORD=...
144
+ ```
145
+
146
+ ### Tests
147
+
148
+ ```bash
149
+ # Backend (requiere server corriendo)
150
+ cd backend
151
+ pytest tests/ -v
152
+
153
+ # Frontend Playwright (requiere server corriendo)
154
+ cd frontend
155
+ node_modules/.bin/playwright test
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 🗂️ Estructura del proyecto
161
+
162
+ ```
163
+ _/
164
+ ├── backend/
165
+ │ ├── main.py # FastAPI app, lifespan, routers
166
+ │ ├── sim.py # Simulador (activo cuando ENABLE_BOTS=false)
167
+ │ ├── state.py # clients dict + wa_session singleton
168
+ │ ├── config.py # lee phones.json
169
+ │ ├── db.py # SQLite async
170
+ │ ├── api/ # routers: auth, bots, phones, whatsapp,
171
+ │ │ # telegram, messages, sim, bot, logs
172
+ │ ├── automation/
173
+ │ │ └── whatsapp.py # lógica WA Web con Playwright
174
+ │ ├── bots/
175
+ │ │ └── telegram_bot.py # bot de Telegram
176
+ │ └── tests/ # pytest: auth, logs, sim
177
+ ├── frontend/
178
+ │ ├── src/
179
+ │ │ ├── pages/
180
+ │ │ │ ├── DashboardPage.jsx # panel admin
181
+ │ │ │ ├── BotPage.jsx # portal de bot (login + dashboard)
182
+ │ │ │ └── NewBotPage.jsx # onboarding nueva bot
183
+ │ │ └── components/
184
+ │ │ ├── ChatWidget.jsx # chat inline reutilizable
185
+ │ │ └── MonitorPanel.jsx # drawer de monitoring en tiempo real
186
+ │ └── tests/ # Playwright: login, monitor
187
+ ├── management/ # planes, visión, arquitectura
188
+ ├── phones.json # config de bots y teléfonos (gitignoreado)
189
+ ├── data/ # DB y sesiones Chrome (gitignoreado)
190
+ └── start.sh # arranque unificado
191
+ ```
192
+
193
+ ---
194
+
195
+ ## 🔀 Worktrees (flujo de desarrollo)
196
+
197
+ Cada feature se desarrolla en su propio worktree — un servidor independiente con DB propia, sin tocar producción.
198
+
199
+ | Worktree | Backend | Frontend | Estado |
200
+ |--------------|---------|----------|------------|
201
+ | `_` (master) | 8000 | 5173 | Producción |
202
+ | dev-1 | 8001 | 5174 | Libre |
203
+ | dev-2 | 8002 | 5175 | Libre |
204
+
205
+ Ver `CLAUDE.md` para el flujo completo de creación de worktrees, symlinks y setup.
206
+
207
+ ---
208
+
209
+ ## 🗺️ Roadmap
210
+
211
+ - [x] Bots de WhatsApp (Playwright headless)
212
+ - [x] Bots de Telegram (python-telegram-bot)
213
+ - [x] Respuesta automática configurable por bot
214
+ - [x] Portal de bot — gestión de canales + chat inline
215
+ - [x] Alta de bot nueva (onboarding autogestionable)
216
+ - [x] Panel admin con monitoring en tiempo real
217
+ - [x] Exposición pública via ngrok
218
+ - [ ] Autenticación segura (OAuth / tokens)
219
+ - [ ] Dominio propio + Cloudflare Tunnel
220
+ - [ ] Reconexión automática de sesiones WA