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.
- pulpo_lib-0.1.0/.claude/commands/emergencia.md +57 -0
- pulpo_lib-0.1.0/.env.example +16 -0
- pulpo_lib-0.1.0/.gitignore +61 -0
- pulpo_lib-0.1.0/CLAUDE.md +267 -0
- pulpo_lib-0.1.0/NEXT_SESSION.md +70 -0
- pulpo_lib-0.1.0/PKG-INFO +220 -0
- pulpo_lib-0.1.0/README.md +180 -0
- pulpo_lib-0.1.0/backend/NUEVO_DISENO_TRIGGERS.md +186 -0
- pulpo_lib-0.1.0/backend/api/__init__.py +0 -0
- pulpo_lib-0.1.0/backend/api/architecture.py +172 -0
- pulpo_lib-0.1.0/backend/api/auth.py +21 -0
- pulpo_lib-0.1.0/backend/api/auth_bot.py +100 -0
- pulpo_lib-0.1.0/backend/api/bot_portal.py +397 -0
- pulpo_lib-0.1.0/backend/api/bots.py +137 -0
- pulpo_lib-0.1.0/backend/api/client.py +152 -0
- pulpo_lib-0.1.0/backend/api/connections.py +272 -0
- pulpo_lib-0.1.0/backend/api/contacts.py +145 -0
- pulpo_lib-0.1.0/backend/api/deps.py +16 -0
- pulpo_lib-0.1.0/backend/api/fb_session.py +82 -0
- pulpo_lib-0.1.0/backend/api/flows.py +419 -0
- pulpo_lib-0.1.0/backend/api/logs.py +76 -0
- pulpo_lib-0.1.0/backend/api/messages.py +17 -0
- pulpo_lib-0.1.0/backend/api/settings.py +26 -0
- pulpo_lib-0.1.0/backend/api/sim.py +70 -0
- pulpo_lib-0.1.0/backend/api/summarizer.py +699 -0
- pulpo_lib-0.1.0/backend/api/telegram_api.py +134 -0
- pulpo_lib-0.1.0/backend/api/wavi.py +132 -0
- pulpo_lib-0.1.0/backend/auth_jwt.py +51 -0
- pulpo_lib-0.1.0/backend/automation/__init__.py +0 -0
- pulpo_lib-0.1.0/backend/automation/browser.py +150 -0
- pulpo_lib-0.1.0/backend/bots/__init__.py +0 -0
- pulpo_lib-0.1.0/backend/bots/telegram_bot.py +122 -0
- pulpo_lib-0.1.0/backend/config/auspiciantes/luganense.json +40 -0
- pulpo_lib-0.1.0/backend/config/oficios/luganense.json +63 -0
- pulpo_lib-0.1.0/backend/config.py +125 -0
- pulpo_lib-0.1.0/backend/db.py +822 -0
- pulpo_lib-0.1.0/backend/graphs/__init__.py +0 -0
- pulpo_lib-0.1.0/backend/graphs/auspiciantes.py +62 -0
- pulpo_lib-0.1.0/backend/graphs/collections/__init__.py +39 -0
- pulpo_lib-0.1.0/backend/graphs/collections/luganense.py +115 -0
- pulpo_lib-0.1.0/backend/graphs/compiler.py +301 -0
- pulpo_lib-0.1.0/backend/graphs/cooldown.py +76 -0
- pulpo_lib-0.1.0/backend/graphs/luganense.py +439 -0
- pulpo_lib-0.1.0/backend/graphs/node_types.py +196 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/__init__.py +73 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/api_trigger.py +16 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/base.py +68 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/base_trigger.py +58 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/check_contact.py +58 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/fetch.py +155 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/fetch_sheet.py +153 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/gsheet.py +341 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/llm.py +225 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/message_join.py +20 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/message_trigger.py +13 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/reply.py +114 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/router.py +86 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/save_attachment.py +71 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/save_contact.py +78 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/search_sheet.py +170 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/set_state.py +36 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/state.py +52 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/summarize.py +755 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/telegram_trigger.py +11 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/transcribe_audio.py +61 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/vector_search.py +258 -0
- pulpo_lib-0.1.0/backend/graphs/nodes/whatsapp_trigger.py +11 -0
- pulpo_lib-0.1.0/backend/graphs/trigger_match.py +206 -0
- pulpo_lib-0.1.0/backend/main.py +353 -0
- pulpo_lib-0.1.0/backend/middleware_auth.py +19 -0
- pulpo_lib-0.1.0/backend/migrate_legacy_flows.py +111 -0
- pulpo_lib-0.1.0/backend/migrate_simple.py +78 -0
- pulpo_lib-0.1.0/backend/nodes/__init__.py +0 -0
- pulpo_lib-0.1.0/backend/nodes/_login_fb.py +98 -0
- pulpo_lib-0.1.0/backend/nodes/_test_fb.py +36 -0
- pulpo_lib-0.1.0/backend/nodes/_test_fb2.py +62 -0
- pulpo_lib-0.1.0/backend/nodes/_test_fb3.py +51 -0
- pulpo_lib-0.1.0/backend/nodes/fb_cache.py +253 -0
- pulpo_lib-0.1.0/backend/nodes/fetch_facebook.py +630 -0
- pulpo_lib-0.1.0/backend/nodes/find_worker.py +82 -0
- pulpo_lib-0.1.0/backend/nodes/notify_worker.py +76 -0
- pulpo_lib-0.1.0/backend/paused.py +58 -0
- pulpo_lib-0.1.0/backend/requirements.txt +17 -0
- pulpo_lib-0.1.0/backend/sim.py +138 -0
- pulpo_lib-0.1.0/backend/start.sh +32 -0
- pulpo_lib-0.1.0/backend/state.py +21 -0
- pulpo_lib-0.1.0/backend/teli_poller.py +212 -0
- pulpo_lib-0.1.0/backend/tests/conftest.py +145 -0
- pulpo_lib-0.1.0/backend/tests/test_architecture.py +91 -0
- pulpo_lib-0.1.0/backend/tests/test_audio_transcription.py +509 -0
- pulpo_lib-0.1.0/backend/tests/test_auth.py +42 -0
- pulpo_lib-0.1.0/backend/tests/test_bot_portal.py +132 -0
- pulpo_lib-0.1.0/backend/tests/test_bot_safety.py +413 -0
- pulpo_lib-0.1.0/backend/tests/test_browser_zoom.py +128 -0
- pulpo_lib-0.1.0/backend/tests/test_connections.py +175 -0
- pulpo_lib-0.1.0/backend/tests/test_contacts.py +148 -0
- pulpo_lib-0.1.0/backend/tests/test_fb_cache.py +189 -0
- pulpo_lib-0.1.0/backend/tests/test_fetch_facebook_logs.py +114 -0
- pulpo_lib-0.1.0/backend/tests/test_fetch_facebook_urls.py +52 -0
- pulpo_lib-0.1.0/backend/tests/test_fetch_sheet.py +164 -0
- pulpo_lib-0.1.0/backend/tests/test_flow_safety.py +934 -0
- pulpo_lib-0.1.0/backend/tests/test_flows.py +227 -0
- pulpo_lib-0.1.0/backend/tests/test_google_connections.py +119 -0
- pulpo_lib-0.1.0/backend/tests/test_gsheet.py +164 -0
- pulpo_lib-0.1.0/backend/tests/test_hierarchical_ids.py +277 -0
- pulpo_lib-0.1.0/backend/tests/test_logs.py +112 -0
- pulpo_lib-0.1.0/backend/tests/test_search_sheet.py +148 -0
- pulpo_lib-0.1.0/backend/tests/test_sim.py +202 -0
- pulpo_lib-0.1.0/backend/tests/test_summarize_dedup.py +280 -0
- pulpo_lib-0.1.0/backend/tests/test_sync_security.py +113 -0
- pulpo_lib-0.1.0/backend/tests/test_telegram_startup.py +193 -0
- pulpo_lib-0.1.0/backend/tests/test_trigger_match.py +286 -0
- pulpo_lib-0.1.0/backend/tests/test_tuning.py +554 -0
- pulpo_lib-0.1.0/backend/tests/test_vector_search.py +146 -0
- pulpo_lib-0.1.0/backend/tests/test_wavi_api.py +55 -0
- pulpo_lib-0.1.0/backend/tests/test_wavi_dedup.py +79 -0
- pulpo_lib-0.1.0/backend/tools/__init__.py +0 -0
- pulpo_lib-0.1.0/backend/tools/debug_audio.py +219 -0
- pulpo_lib-0.1.0/backend/tools/teli_driver.py +17 -0
- pulpo_lib-0.1.0/backend/tools/transcription.py +39 -0
- pulpo_lib-0.1.0/backend/tools/wavi_driver.py +181 -0
- pulpo_lib-0.1.0/backend/wavi_poller.py +175 -0
- pulpo_lib-0.1.0/com.josetabuyo.pulpo.plist +35 -0
- pulpo_lib-0.1.0/frontend/.gitignore +24 -0
- pulpo_lib-0.1.0/frontend/README.md +8 -0
- pulpo_lib-0.1.0/frontend/eslint.config.js +38 -0
- pulpo_lib-0.1.0/frontend/index.html +13 -0
- pulpo_lib-0.1.0/frontend/package-lock.json +8045 -0
- pulpo_lib-0.1.0/frontend/package.json +37 -0
- pulpo_lib-0.1.0/frontend/playwright.config.cjs +37 -0
- pulpo_lib-0.1.0/frontend/public/pulpo.svg +18 -0
- pulpo_lib-0.1.0/frontend/public/vite.svg +1 -0
- pulpo_lib-0.1.0/frontend/src/App.css +1 -0
- pulpo_lib-0.1.0/frontend/src/App.jsx +20 -0
- pulpo_lib-0.1.0/frontend/src/SimChat.jsx +49 -0
- pulpo_lib-0.1.0/frontend/src/api.js +32 -0
- pulpo_lib-0.1.0/frontend/src/assets/react.svg +1 -0
- pulpo_lib-0.1.0/frontend/src/components/ArchitectureSection.jsx +250 -0
- pulpo_lib-0.1.0/frontend/src/components/BotCard.jsx +322 -0
- pulpo_lib-0.1.0/frontend/src/components/ChatWidget.jsx +102 -0
- pulpo_lib-0.1.0/frontend/src/components/ContactFilterEditor.jsx +286 -0
- pulpo_lib-0.1.0/frontend/src/components/FlowCanvas.jsx +225 -0
- pulpo_lib-0.1.0/frontend/src/components/FlowEditor.jsx +106 -0
- pulpo_lib-0.1.0/frontend/src/components/FlowHeader.jsx +98 -0
- pulpo_lib-0.1.0/frontend/src/components/FlowList.jsx +248 -0
- pulpo_lib-0.1.0/frontend/src/components/MonitorPanel.jsx +407 -0
- pulpo_lib-0.1.0/frontend/src/components/NodeConfigPanel.jsx +61 -0
- pulpo_lib-0.1.0/frontend/src/components/NodePalette.jsx +214 -0
- pulpo_lib-0.1.0/frontend/src/components/StatusBadge.jsx +19 -0
- pulpo_lib-0.1.0/frontend/src/components/SummaryContactList.jsx +43 -0
- pulpo_lib-0.1.0/frontend/src/components/SummaryView.jsx +995 -0
- pulpo_lib-0.1.0/frontend/src/components/UIsList.jsx +29 -0
- pulpo_lib-0.1.0/frontend/src/components/architecture.css +181 -0
- pulpo_lib-0.1.0/frontend/src/components/bot/BotConfigTab.jsx +61 -0
- pulpo_lib-0.1.0/frontend/src/components/bot/ConnectionRow.jsx +100 -0
- pulpo_lib-0.1.0/frontend/src/components/bot/GoogleConnections.jsx +184 -0
- pulpo_lib-0.1.0/frontend/src/components/bot/WaviConnections.jsx +81 -0
- pulpo_lib-0.1.0/frontend/src/components/bot/widgets.jsx +61 -0
- pulpo_lib-0.1.0/frontend/src/components/nodeconfig/ConfigForm.jsx +384 -0
- pulpo_lib-0.1.0/frontend/src/components/nodeconfig/FbCacheModal.jsx +125 -0
- pulpo_lib-0.1.0/frontend/src/components/nodeconfig/SheetCacheButton.jsx +34 -0
- pulpo_lib-0.1.0/frontend/src/components/nodeconfig/SummarizeInfo.jsx +115 -0
- pulpo_lib-0.1.0/frontend/src/components/nodeconfig/fields.jsx +317 -0
- pulpo_lib-0.1.0/frontend/src/components/nodeconfig/styles.js +65 -0
- pulpo_lib-0.1.0/frontend/src/hooks/useFbSession.js +74 -0
- pulpo_lib-0.1.0/frontend/src/index.css +1876 -0
- pulpo_lib-0.1.0/frontend/src/lib/auth.js +49 -0
- pulpo_lib-0.1.0/frontend/src/main.jsx +13 -0
- pulpo_lib-0.1.0/frontend/src/pages/BotPage.jsx +225 -0
- pulpo_lib-0.1.0/frontend/src/pages/DashboardPage.jsx +530 -0
- pulpo_lib-0.1.0/frontend/src/pages/LoginPage.jsx +71 -0
- pulpo_lib-0.1.0/frontend/src/pages/NewBotPage.jsx +222 -0
- pulpo_lib-0.1.0/frontend/src/store/flowStore.js +215 -0
- pulpo_lib-0.1.0/frontend/tests/architecture.spec.cjs +63 -0
- pulpo_lib-0.1.0/frontend/tests/bot_safety.spec.cjs +66 -0
- pulpo_lib-0.1.0/frontend/tests/flows.spec.cjs +145 -0
- pulpo_lib-0.1.0/frontend/tests/login.spec.cjs +62 -0
- pulpo_lib-0.1.0/frontend/tests/monitor.spec.cjs +179 -0
- pulpo_lib-0.1.0/frontend/tests/summary_bubble.spec.cjs +373 -0
- pulpo_lib-0.1.0/frontend/vite.config.js +40 -0
- pulpo_lib-0.1.0/memory/project_audio_feature.md +11 -0
- pulpo_lib-0.1.0/monitoring.json +23 -0
- pulpo_lib-0.1.0/phones.example.json +27 -0
- pulpo_lib-0.1.0/pulpo/__init__.py +31 -0
- pulpo_lib-0.1.0/pulpo/automation/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/automation/browser.py +150 -0
- pulpo_lib-0.1.0/pulpo/bots/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/bots/telegram_bot.py +122 -0
- pulpo_lib-0.1.0/pulpo/business/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/business/architecture.py +149 -0
- pulpo_lib-0.1.0/pulpo/business/bots.py +136 -0
- pulpo_lib-0.1.0/pulpo/business/connections.py +205 -0
- pulpo_lib-0.1.0/pulpo/business/contacts.py +117 -0
- pulpo_lib-0.1.0/pulpo/business/flows.py +293 -0
- pulpo_lib-0.1.0/pulpo/business/messages.py +17 -0
- pulpo_lib-0.1.0/pulpo/business/settings.py +25 -0
- pulpo_lib-0.1.0/pulpo/business/sim.py +87 -0
- pulpo_lib-0.1.0/pulpo/business/wavi.py +153 -0
- pulpo_lib-0.1.0/pulpo/core/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/core/auth_jwt.py +50 -0
- pulpo_lib-0.1.0/pulpo/core/config.py +100 -0
- pulpo_lib-0.1.0/pulpo/core/db.py +822 -0
- pulpo_lib-0.1.0/pulpo/core/lifespan.py +205 -0
- pulpo_lib-0.1.0/pulpo/core/state.py +7 -0
- pulpo_lib-0.1.0/pulpo/graphs/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/graphs/auspiciantes.py +62 -0
- pulpo_lib-0.1.0/pulpo/graphs/collections/__init__.py +39 -0
- pulpo_lib-0.1.0/pulpo/graphs/collections/luganense.py +115 -0
- pulpo_lib-0.1.0/pulpo/graphs/compiler.py +301 -0
- pulpo_lib-0.1.0/pulpo/graphs/cooldown.py +76 -0
- pulpo_lib-0.1.0/pulpo/graphs/luganense.py +439 -0
- pulpo_lib-0.1.0/pulpo/graphs/node_types.py +196 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/__init__.py +73 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/api_trigger.py +16 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/base.py +68 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/base_trigger.py +58 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/check_contact.py +58 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/fetch.py +155 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/fetch_sheet.py +153 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/gsheet.py +341 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/llm.py +225 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/message_join.py +20 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/message_trigger.py +13 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/reply.py +114 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/router.py +86 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/save_attachment.py +71 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/save_contact.py +78 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/search_sheet.py +170 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/set_state.py +36 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/state.py +52 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/summarize.py +755 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/telegram_trigger.py +11 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/transcribe_audio.py +61 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/vector_search.py +258 -0
- pulpo_lib-0.1.0/pulpo/graphs/nodes/whatsapp_trigger.py +11 -0
- pulpo_lib-0.1.0/pulpo/graphs/trigger_match.py +206 -0
- pulpo_lib-0.1.0/pulpo/interfaces/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/app.py +18 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/architecture.py +49 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/bots.py +80 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/connections.py +195 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/contacts.py +141 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/flows.py +221 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/logs.py +89 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/messages.py +19 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/settings.py +40 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/sim.py +98 -0
- pulpo_lib-0.1.0/pulpo/interfaces/api/routers/wavi.py +117 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/bots.py +38 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/connections.py +38 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/contacts.py +38 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/flows.py +73 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/messages.py +17 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/server.py +33 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/settings.py +40 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/commands/sim.py +44 -0
- pulpo_lib-0.1.0/pulpo/interfaces/cli/main.py +17 -0
- pulpo_lib-0.1.0/pulpo/interfaces/lib/__init__.py +52 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/app.py +32 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/deps.py +16 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/middleware.py +19 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/auth.py +19 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/auth_bot.py +99 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/bot_portal.py +403 -0
- pulpo_lib-0.1.0/pulpo/interfaces/ui/routers/client.py +163 -0
- pulpo_lib-0.1.0/pulpo/nodes/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/nodes/_login_fb.py +98 -0
- pulpo_lib-0.1.0/pulpo/nodes/_test_fb.py +36 -0
- pulpo_lib-0.1.0/pulpo/nodes/_test_fb2.py +62 -0
- pulpo_lib-0.1.0/pulpo/nodes/_test_fb3.py +51 -0
- pulpo_lib-0.1.0/pulpo/nodes/fb_cache.py +253 -0
- pulpo_lib-0.1.0/pulpo/nodes/fetch_facebook.py +630 -0
- pulpo_lib-0.1.0/pulpo/nodes/find_worker.py +82 -0
- pulpo_lib-0.1.0/pulpo/nodes/notify_worker.py +76 -0
- pulpo_lib-0.1.0/pulpo/tools/__init__.py +0 -0
- pulpo_lib-0.1.0/pulpo/tools/debug_audio.py +219 -0
- pulpo_lib-0.1.0/pulpo/tools/teli_driver.py +17 -0
- pulpo_lib-0.1.0/pulpo/tools/transcription.py +39 -0
- pulpo_lib-0.1.0/pulpo/tools/wavi_driver.py +181 -0
- pulpo_lib-0.1.0/pyproject.toml +64 -0
- pulpo_lib-0.1.0/restart-backend.sh +15 -0
- pulpo_lib-0.1.0/rotate-logs.sh +31 -0
- pulpo_lib-0.1.0/scripts/fb_check_cookies.py +135 -0
- pulpo_lib-0.1.0/scripts/fb_login.py +121 -0
- pulpo_lib-0.1.0/scripts/migrate_empresa_to_bot.py +69 -0
- pulpo_lib-0.1.0/scripts/refactor_empresa_to_bot.py +150 -0
- pulpo_lib-0.1.0/scripts/test_fb_debug.py +189 -0
- pulpo_lib-0.1.0/start.sh +116 -0
- pulpo_lib-0.1.0/stop-backend.sh +12 -0
- pulpo_lib-0.1.0/tests/conftest.py +70 -0
- pulpo_lib-0.1.0/tests/test_architecture.py +89 -0
- pulpo_lib-0.1.0/tests/test_cli.py +45 -0
- pulpo_lib-0.1.0/tests/test_imports.py +81 -0
- 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
|
+
```
|
pulpo_lib-0.1.0/PKG-INFO
ADDED
|
@@ -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
|