dulus 0.2.56__tar.gz → 0.2.60__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.
- {dulus-0.2.56 → dulus-0.2.60}/MANIFEST.in +1 -0
- {dulus-0.2.56/dulus.egg-info → dulus-0.2.60}/PKG-INFO +4 -1
- {dulus-0.2.56 → dulus-0.2.60}/data/context.json +19 -23
- {dulus-0.2.56 → dulus-0.2.60/dulus.egg-info}/PKG-INFO +4 -1
- {dulus-0.2.56 → dulus-0.2.60}/dulus.egg-info/SOURCES.txt +7 -1
- {dulus-0.2.56 → dulus-0.2.60}/dulus.egg-info/requires.txt +4 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus.egg-info/top_level.txt +1 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus.py +136 -0
- {dulus-0.2.56 → dulus-0.2.60}/pyproject.toml +4 -2
- {dulus-0.2.56 → dulus-0.2.60}/tools.py +14 -0
- {dulus-0.2.56 → dulus-0.2.60}/voice/stt.py +18 -1
- {dulus-0.2.56 → dulus-0.2.60}/voice/wake_word.py +20 -0
- dulus-0.2.60/webbridge/__init__.py +5 -0
- dulus-0.2.60/webbridge/__pycache__/__init__.cpython-314.pyc +0 -0
- dulus-0.2.60/webbridge/__pycache__/core.cpython-314.pyc +0 -0
- dulus-0.2.60/webbridge/__pycache__/tools.cpython-314.pyc +0 -0
- dulus-0.2.60/webbridge/core.py +538 -0
- dulus-0.2.60/webbridge/tools.py +261 -0
- {dulus-0.2.56 → dulus-0.2.60}/LICENSE +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/README.md +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/agent.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/agents_bridge.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/compressor.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/context.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/githook.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/marketplace.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/mempalace_bridge.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/personas.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/plugins.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/server.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/backend/tasks.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/batch_api.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/checkpoint/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/checkpoint/hooks.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/checkpoint/store.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/checkpoint/types.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/claude_code_watcher.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/clipboard_utils.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/cloudsave.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/common.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/compaction.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/config.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/context.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/active_persona.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/marketplace.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/personas.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/composio/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/composio/composio_plugin/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/composio/plugin.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/plugins/composio/plugin_tool.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/data/tasks.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/README.md +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/api.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/architecture.md +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/azure-speech-template.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/dashboard/index.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/divider.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/generate.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/hero.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/index.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/news.md +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/nvidia-models.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/particle-playground.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/personas/index.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/poetry-banner.png +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/preview.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-agents.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-brainstorm.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-bridges.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-features.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-freetier.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-memory.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-models.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-perms.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-plugins.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-quickstart.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/sec-ssj.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/spinners.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/split-pane.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/terminal-boot.svg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/docs/uploads/particle-playground.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus_gui.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus_mcp/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus_mcp/client.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus_mcp/config.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus_mcp/tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/dulus_mcp/types.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/agent_bridge.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/chat_widget.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/main_window.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/personas.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/session_utils.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/settings_dialog.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/sidebar.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/tasks_view.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/themes.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/gui/tool_panel.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/input.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/license_manager.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/audit.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/consolidator.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/context.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/offload.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/palace.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/scan.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/sessions.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/store.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/types.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/memory/vector_search.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/multi_agent/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/multi_agent/subagent.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/multi_agent/tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/offload_helper.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/plugin/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/plugin/autoadapter.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/plugin/loader.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/plugin/recommend.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/plugin/store.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/plugin/types.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/providers.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/README.md +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/components.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/assets/index-DE51D6wI.css +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/assets/index-DMCCNE9Y.js +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/index.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/wallpaper-default.jpg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/wallpapers/default.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/wallpapers/light.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/wallpapers/nature.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/dist/wallpapers/tech.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/eslint.config.js +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/index.html +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/info.md +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/package-lock.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/package.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/postcss.config.js +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/public/wallpaper-default.jpg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/public/wallpapers/default.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/public/wallpapers/light.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/public/wallpapers/nature.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/public/wallpapers/tech.jpeg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/App.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/AgentMonitor.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ApiTester.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/AppRouter.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ArchiveManager.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/AsciiArt.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Base64Tool.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Browser.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Calculator.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Calendar.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Chat.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Chess.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Clock.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/CodeEditor.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ColorPalette.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ColorPicker.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Contacts.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/DocumentViewer.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Drawing.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Email.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/FileManager.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/FlappyBird.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/FtpClient.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Game2048.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/GitClient.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ImageGallery.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ImageViewer.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/JsonFormatter.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/MarkdownPreview.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/MatrixRain.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/MediaConverter.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Memory.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/MemoryManager.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Minesweeper.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/MusicPlayer.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/NetworkTools.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Notes.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/PasswordManager.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/PhotoEditor.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Pong.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/RegexTester.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Reminders.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/RssReader.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/ScreenRecorder.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Settings.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/SkillsLauncher.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Snake.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Solitaire.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Spreadsheet.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Sudoku.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/SystemMonitor.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/TaskManager.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Terminal.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Tetris.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/TextEditor.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/TicTacToe.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Todo.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/VideoPlayer.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/VoiceRecorder.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Weather.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/Whiteboard.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/apps/registry.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/AppContainer.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/AppLauncher.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/BootSequence.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ContextMenu.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/Desktop.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/Dock.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/LoginScreen.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/NotImplemented.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/NotificationCenter.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/NotificationSystem.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/TopPanel.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/WindowFrame.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/WindowManager.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/accordion.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/alert-dialog.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/alert.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/aspect-ratio.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/avatar.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/badge.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/breadcrumb.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/button-group.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/button.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/calendar.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/card.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/carousel.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/chart.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/checkbox.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/collapsible.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/command.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/context-menu.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/dialog.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/drawer.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/dropdown-menu.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/empty.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/field.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/form.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/hover-card.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/input-group.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/input-otp.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/input.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/item.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/kbd.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/label.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/menubar.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/navigation-menu.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/pagination.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/popover.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/progress.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/radio-group.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/resizable.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/scroll-area.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/select.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/separator.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/sheet.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/sidebar.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/skeleton.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/slider.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/sonner.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/spinner.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/switch.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/table.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/tabs.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/textarea.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/toggle-group.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/toggle.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/components/ui/tooltip.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/index.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/use-mobile.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useAutoOpenChat.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusAgents.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusChat.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusEvents.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusHealth.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusMemory.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusSkills.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useDulusTasks.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useFileSystem.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useOSStore.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useSkillBridge.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useSystemBattery.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useSystemNetwork.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/hooks/useSystemVolume.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/index.css +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/lib/dulus-api.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/lib/utils.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/main.tsx +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/types/index.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/src/utils/assets.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/tailwind.config.js +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/tsconfig.app.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/tsconfig.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/tsconfig.node.json +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/sandbox/vite.config.ts +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/setup.cfg +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skill/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skill/builtin.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skill/clawhub.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skill/executor.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skill/loader.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skill/tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/skills.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/spinner.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/string_utils.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/subagent.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/task/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/task/store.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/task/tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/task/types.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_afk_yolo.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_approval_runtime.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_background_task_tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_background_tasks.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_checkpoint.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_clipboard_utils.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_compaction.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_diff_view.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_diff_visualization.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_display_blocks.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_export_import.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_hook_engine.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_injection_fix.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_license.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_mcp.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_memory.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_notification_manager.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_plugin.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_session_fork.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_shell_mode.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_skills.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_steer_input.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_subagent.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_task.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_telegram_buffer.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_think_tool.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_todo_tool.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_todo_visualization.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_tool_registry.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_voice.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tests/test_wire_events.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tmux_offloader.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tmux_tools.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/tool_registry.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/ui/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/ui/input.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/ui/render.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/voice/__init__.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/voice/audio_utils.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/voice/keyterms.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/voice/recorder.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/voice/tts.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/webchat.py +0 -0
- {dulus-0.2.56 → dulus-0.2.60}/webchat_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.60
|
|
4
4
|
Summary: Spanish-first multi-provider AI CLI — 14 NVIDIA models free, Mesa Redonda, voice, TTS, RTK token reducer, MemPalace
|
|
5
5
|
Author: KevRojo
|
|
6
6
|
License: GPL-3.0
|
|
@@ -40,9 +40,12 @@ Provides-Extra: memory
|
|
|
40
40
|
Requires-Dist: mempalace>=3.3.4; extra == "memory"
|
|
41
41
|
Provides-Extra: voice
|
|
42
42
|
Requires-Dist: sounddevice; extra == "voice"
|
|
43
|
+
Provides-Extra: webbridge
|
|
44
|
+
Requires-Dist: playwright>=1.40.0; extra == "webbridge"
|
|
43
45
|
Provides-Extra: full
|
|
44
46
|
Requires-Dist: mempalace>=3.3.4; extra == "full"
|
|
45
47
|
Requires-Dist: sounddevice; extra == "full"
|
|
48
|
+
Requires-Dist: playwright>=1.40.0; extra == "full"
|
|
46
49
|
Dynamic: license-file
|
|
47
50
|
|
|
48
51
|
# ▲ DULUS
|
|
@@ -10,21 +10,21 @@
|
|
|
10
10
|
"name": "Dulus Command Center",
|
|
11
11
|
"repo_stats": {
|
|
12
12
|
"files": 439,
|
|
13
|
-
"lines":
|
|
13
|
+
"lines": 206190,
|
|
14
14
|
"languages": {
|
|
15
15
|
".example": 5,
|
|
16
16
|
"no_ext": 1471,
|
|
17
|
-
".py":
|
|
17
|
+
".py": 61619,
|
|
18
18
|
".html": 14944,
|
|
19
19
|
".in": 3,
|
|
20
20
|
".toml": 129,
|
|
21
21
|
".md": 2170,
|
|
22
22
|
".txt": 473,
|
|
23
23
|
".lock": 1,
|
|
24
|
-
".json":
|
|
24
|
+
".json": 9524,
|
|
25
25
|
".TAG": 4,
|
|
26
|
-
".whl":
|
|
27
|
-
".gz":
|
|
26
|
+
".whl": 21634,
|
|
27
|
+
".gz": 20778,
|
|
28
28
|
".svg": 1123,
|
|
29
29
|
".png": 31639,
|
|
30
30
|
".sh": 144,
|
|
@@ -39,42 +39,38 @@
|
|
|
39
39
|
},
|
|
40
40
|
"recent_commits": [
|
|
41
41
|
{
|
|
42
|
-
"hash": "
|
|
43
|
-
"subject": "bump: 0.2.
|
|
42
|
+
"hash": "73887e7",
|
|
43
|
+
"subject": "bump: 0.2.55 → 0.2.56",
|
|
44
44
|
"author": "KevRojo",
|
|
45
45
|
"date": "2026-05-13"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
-
"hash": "
|
|
49
|
-
"subject": "
|
|
48
|
+
"hash": "70a1b1d",
|
|
49
|
+
"subject": "fix: eliminar notificaciones intermedias de Telegram/wake/TTS que se acumulaban en CLI",
|
|
50
50
|
"author": "KevRojo",
|
|
51
51
|
"date": "2026-05-13"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
|
-
"hash": "
|
|
55
|
-
"subject": "
|
|
54
|
+
"hash": "cf4128b",
|
|
55
|
+
"subject": "feat: voice module polish — wake word UI, toolbar status, TTY beep fix",
|
|
56
56
|
"author": "KevRojo",
|
|
57
|
-
"date": "2026-05-
|
|
57
|
+
"date": "2026-05-13"
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
"hash": "
|
|
61
|
-
"subject": "
|
|
60
|
+
"hash": "d9c870b",
|
|
61
|
+
"subject": "bump: 0.2.53 → 0.2.54",
|
|
62
62
|
"author": "KevRojo",
|
|
63
|
-
"date": "2026-05-
|
|
63
|
+
"date": "2026-05-13"
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
|
-
"hash": "
|
|
67
|
-
"subject": "
|
|
66
|
+
"hash": "3c7daf7",
|
|
67
|
+
"subject": "feat(voice): add wake word detection, audio utils, and voice module improvements",
|
|
68
68
|
"author": "KevRojo",
|
|
69
|
-
"date": "2026-05-
|
|
69
|
+
"date": "2026-05-13"
|
|
70
70
|
}
|
|
71
71
|
],
|
|
72
72
|
"recent_changes": [
|
|
73
|
-
"
|
|
74
|
-
"pyproject.toml",
|
|
75
|
-
"requirements.txt",
|
|
76
|
-
"voice/audio_utils.py",
|
|
77
|
-
"voice/tts.py"
|
|
73
|
+
"pyproject.toml"
|
|
78
74
|
]
|
|
79
75
|
},
|
|
80
76
|
"tasks": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.60
|
|
4
4
|
Summary: Spanish-first multi-provider AI CLI — 14 NVIDIA models free, Mesa Redonda, voice, TTS, RTK token reducer, MemPalace
|
|
5
5
|
Author: KevRojo
|
|
6
6
|
License: GPL-3.0
|
|
@@ -40,9 +40,12 @@ Provides-Extra: memory
|
|
|
40
40
|
Requires-Dist: mempalace>=3.3.4; extra == "memory"
|
|
41
41
|
Provides-Extra: voice
|
|
42
42
|
Requires-Dist: sounddevice; extra == "voice"
|
|
43
|
+
Provides-Extra: webbridge
|
|
44
|
+
Requires-Dist: playwright>=1.40.0; extra == "webbridge"
|
|
43
45
|
Provides-Extra: full
|
|
44
46
|
Requires-Dist: mempalace>=3.3.4; extra == "full"
|
|
45
47
|
Requires-Dist: sounddevice; extra == "full"
|
|
48
|
+
Requires-Dist: playwright>=1.40.0; extra == "full"
|
|
46
49
|
Dynamic: license-file
|
|
47
50
|
|
|
48
51
|
# ▲ DULUS
|
|
@@ -356,4 +356,10 @@ voice/keyterms.py
|
|
|
356
356
|
voice/recorder.py
|
|
357
357
|
voice/stt.py
|
|
358
358
|
voice/tts.py
|
|
359
|
-
voice/wake_word.py
|
|
359
|
+
voice/wake_word.py
|
|
360
|
+
webbridge/__init__.py
|
|
361
|
+
webbridge/core.py
|
|
362
|
+
webbridge/tools.py
|
|
363
|
+
webbridge/__pycache__/__init__.cpython-314.pyc
|
|
364
|
+
webbridge/__pycache__/core.cpython-314.pyc
|
|
365
|
+
webbridge/__pycache__/tools.cpython-314.pyc
|
|
@@ -7714,6 +7714,141 @@ def cmd_batch(args: str, _state, config) -> bool:
|
|
|
7714
7714
|
return True
|
|
7715
7715
|
|
|
7716
7716
|
|
|
7717
|
+
def cmd_webbridge(args: str, state, config) -> bool:
|
|
7718
|
+
"""Control the Dulus WebBridge browser automation."""
|
|
7719
|
+
from os import makedirs, path, getenv
|
|
7720
|
+
from datetime import datetime
|
|
7721
|
+
try:
|
|
7722
|
+
from webbridge.core import DulusWebBridge
|
|
7723
|
+
except ImportError:
|
|
7724
|
+
err("WebBridge not available. Install dependencies: pip install playwright")
|
|
7725
|
+
return True
|
|
7726
|
+
|
|
7727
|
+
bridge = DulusWebBridge()
|
|
7728
|
+
parts = (args or "").strip().split()
|
|
7729
|
+
sub = parts[0].lower() if parts else "status"
|
|
7730
|
+
|
|
7731
|
+
if sub in ("status", ""):
|
|
7732
|
+
try:
|
|
7733
|
+
st = bridge.status()
|
|
7734
|
+
if st.get("browser_open"):
|
|
7735
|
+
ok("Browser: OPEN")
|
|
7736
|
+
info(f" URL: {st.get('url', 'N/A')}")
|
|
7737
|
+
else:
|
|
7738
|
+
info("Browser: CLOSED")
|
|
7739
|
+
except Exception as e:
|
|
7740
|
+
err(f"Status check failed: {e}")
|
|
7741
|
+
return True
|
|
7742
|
+
|
|
7743
|
+
if sub == "open":
|
|
7744
|
+
if len(parts) < 2:
|
|
7745
|
+
err("Usage: /webbridge open <url>")
|
|
7746
|
+
return True
|
|
7747
|
+
url = parts[1]
|
|
7748
|
+
if not url.startswith(("http://", "https://")):
|
|
7749
|
+
url = "https://" + url
|
|
7750
|
+
try:
|
|
7751
|
+
bridge.navigate_sync(url)
|
|
7752
|
+
ok(f"Opened: {url}")
|
|
7753
|
+
except Exception as e:
|
|
7754
|
+
err(f"Failed to open URL: {e}")
|
|
7755
|
+
return True
|
|
7756
|
+
|
|
7757
|
+
if sub == "click":
|
|
7758
|
+
if len(parts) < 2:
|
|
7759
|
+
err("Usage: /webbridge click <selector>")
|
|
7760
|
+
return True
|
|
7761
|
+
selector = parts[1]
|
|
7762
|
+
try:
|
|
7763
|
+
bridge.click_sync(selector)
|
|
7764
|
+
ok(f"Clicked: {selector}")
|
|
7765
|
+
except Exception as e:
|
|
7766
|
+
err(f"Click failed: {e}")
|
|
7767
|
+
return True
|
|
7768
|
+
|
|
7769
|
+
if sub == "type":
|
|
7770
|
+
if len(parts) < 3:
|
|
7771
|
+
err("Usage: /webbridge type <selector> <text>")
|
|
7772
|
+
return True
|
|
7773
|
+
selector = parts[1]
|
|
7774
|
+
text = " ".join(parts[2:])
|
|
7775
|
+
try:
|
|
7776
|
+
bridge.type_sync(selector, text)
|
|
7777
|
+
ok(f"Typed into: {selector}")
|
|
7778
|
+
except Exception as e:
|
|
7779
|
+
err(f"Type failed: {e}")
|
|
7780
|
+
return True
|
|
7781
|
+
|
|
7782
|
+
if sub == "screenshot":
|
|
7783
|
+
save_path = None
|
|
7784
|
+
if len(parts) >= 2:
|
|
7785
|
+
save_path = parts[1]
|
|
7786
|
+
else:
|
|
7787
|
+
screenshots_dir = path.join(getenv("USERPROFILE", getenv("HOME", ".")), ".dulus", "screenshots")
|
|
7788
|
+
makedirs(screenshots_dir, exist_ok=True)
|
|
7789
|
+
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
7790
|
+
save_path = path.join(screenshots_dir, f"webbridge_{ts}.png")
|
|
7791
|
+
try:
|
|
7792
|
+
bridge.screenshot_sync(save_path)
|
|
7793
|
+
ok(f"Screenshot saved: {save_path}")
|
|
7794
|
+
except Exception as e:
|
|
7795
|
+
err(f"Screenshot failed: {e}")
|
|
7796
|
+
return True
|
|
7797
|
+
|
|
7798
|
+
if sub == "extract":
|
|
7799
|
+
mode = parts[1].lower() if len(parts) >= 2 else "text"
|
|
7800
|
+
if mode not in ("text", "dom"):
|
|
7801
|
+
mode = "text"
|
|
7802
|
+
try:
|
|
7803
|
+
if mode == "text":
|
|
7804
|
+
content = bridge.get_text_sync()
|
|
7805
|
+
else:
|
|
7806
|
+
content = bridge.get_dom_sync()
|
|
7807
|
+
preview = content[:2000]
|
|
7808
|
+
ok(f"Extracted ({mode}) — {len(content)} chars")
|
|
7809
|
+
info(preview)
|
|
7810
|
+
if len(content) > 2000:
|
|
7811
|
+
info(f"... ({len(content) - 2000} more chars)")
|
|
7812
|
+
except Exception as e:
|
|
7813
|
+
err(f"Extract failed: {e}")
|
|
7814
|
+
return True
|
|
7815
|
+
|
|
7816
|
+
if sub == "scroll":
|
|
7817
|
+
direction = parts[1].lower() if len(parts) >= 2 else "down"
|
|
7818
|
+
if direction not in ("up", "down"):
|
|
7819
|
+
direction = "down"
|
|
7820
|
+
try:
|
|
7821
|
+
bridge.scroll_sync(direction)
|
|
7822
|
+
ok(f"Scrolled {direction}")
|
|
7823
|
+
except Exception as e:
|
|
7824
|
+
err(f"Scroll failed: {e}")
|
|
7825
|
+
return True
|
|
7826
|
+
|
|
7827
|
+
if sub == "close":
|
|
7828
|
+
try:
|
|
7829
|
+
bridge.close_sync()
|
|
7830
|
+
ok("Browser closed")
|
|
7831
|
+
except Exception as e:
|
|
7832
|
+
err(f"Close failed: {e}")
|
|
7833
|
+
return True
|
|
7834
|
+
|
|
7835
|
+
if sub == "help":
|
|
7836
|
+
info("WebBridge commands:")
|
|
7837
|
+
info(" /webbridge status — Show browser status")
|
|
7838
|
+
info(" /webbridge open <url> — Open URL")
|
|
7839
|
+
info(" /webbridge click <sel> — Click element")
|
|
7840
|
+
info(" /webbridge type <sel> <t> — Type text")
|
|
7841
|
+
info(" /webbridge screenshot [p] — Take screenshot")
|
|
7842
|
+
info(" /webbridge extract [t|d] — Extract text or DOM")
|
|
7843
|
+
info(" /webbridge scroll [u|d] — Scroll page")
|
|
7844
|
+
info(" /webbridge close — Close browser")
|
|
7845
|
+
info(" /webbridge help — Show this help")
|
|
7846
|
+
return True
|
|
7847
|
+
|
|
7848
|
+
err(f"Unknown subcommand: {sub}. Use /webbridge help")
|
|
7849
|
+
return True
|
|
7850
|
+
|
|
7851
|
+
|
|
7717
7852
|
COMMANDS = {
|
|
7718
7853
|
"tts": cmd_tts,
|
|
7719
7854
|
"say": cmd_say,
|
|
@@ -7776,6 +7911,7 @@ COMMANDS = {
|
|
|
7776
7911
|
"wake": cmd_wake,
|
|
7777
7912
|
"git": cmd_git,
|
|
7778
7913
|
"webchat": cmd_webchat,
|
|
7914
|
+
"webbridge": cmd_webbridge,
|
|
7779
7915
|
"sandbox": cmd_sandbox,
|
|
7780
7916
|
"gui": cmd_gui,
|
|
7781
7917
|
"brave": cmd_brave,
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dulus"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.60"
|
|
8
8
|
description = "Spanish-first multi-provider AI CLI — 14 NVIDIA models free, Mesa Redonda, voice, TTS, RTK token reducer, MemPalace"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -56,7 +56,8 @@ dependencies = [
|
|
|
56
56
|
[project.optional-dependencies]
|
|
57
57
|
memory = ["mempalace>=3.3.4"]
|
|
58
58
|
voice = ["sounddevice"]
|
|
59
|
-
|
|
59
|
+
webbridge = ["playwright>=1.40.0"]
|
|
60
|
+
full = ["mempalace>=3.3.4", "sounddevice", "playwright>=1.40.0"]
|
|
60
61
|
|
|
61
62
|
[project.scripts]
|
|
62
63
|
dulus = "dulus:main"
|
|
@@ -117,6 +118,7 @@ include = [
|
|
|
117
118
|
"task*",
|
|
118
119
|
"ui*",
|
|
119
120
|
"voice*",
|
|
121
|
+
"webbridge*",
|
|
120
122
|
]
|
|
121
123
|
exclude = [
|
|
122
124
|
"tests*",
|
|
@@ -2259,6 +2259,13 @@ except Exception as _plugin_err:
|
|
|
2259
2259
|
# task/tools.py registers all four tools into the central registry on import.
|
|
2260
2260
|
import task.tools as _task_tools # noqa: F401
|
|
2261
2261
|
|
|
2262
|
+
# ── WebBridge tools (browser automation via Playwright) ────────────────────────
|
|
2263
|
+
# webbridge/tools.py registers WebBridgeNavigate, WebBridgeClick, etc.
|
|
2264
|
+
try:
|
|
2265
|
+
import webbridge.tools as _webbridge_tools # noqa: F401
|
|
2266
|
+
except Exception:
|
|
2267
|
+
pass # Playwright may not be installed; skip gracefully
|
|
2268
|
+
|
|
2262
2269
|
|
|
2263
2270
|
# ── Checkpoint hooks (backup files before Write/Edit/NotebookEdit) ───────────
|
|
2264
2271
|
from checkpoint.hooks import install_hooks as _install_checkpoint_hooks
|
|
@@ -2738,4 +2745,11 @@ except Exception:
|
|
|
2738
2745
|
_plugin_count = 0
|
|
2739
2746
|
|
|
2740
2747
|
|
|
2748
|
+
# ── WebBridge tool schemas (append to TOOL_SCHEMAS so AI sees them) ──────────
|
|
2749
|
+
try:
|
|
2750
|
+
from webbridge.tools import _TOOL_SCHEMAS as _WEBBRIDGE_SCHEMAS
|
|
2751
|
+
TOOL_SCHEMAS.extend(_WEBBRIDGE_SCHEMAS)
|
|
2752
|
+
except Exception:
|
|
2753
|
+
pass # Playwright not installed; skip gracefully
|
|
2754
|
+
|
|
2741
2755
|
|
|
@@ -258,10 +258,18 @@ def _transcribe_faster_whisper(
|
|
|
258
258
|
initial_prompt = _keyterms_to_prompt(keyterms)
|
|
259
259
|
lang = None if not language or language == "auto" else language
|
|
260
260
|
|
|
261
|
+
# Force Spanish context when language is set to "es" — prevents
|
|
262
|
+
# the model from hallucinating English on short wake-word utterances.
|
|
263
|
+
if lang == "es" and not initial_prompt:
|
|
264
|
+
initial_prompt = "Transcripción en español."
|
|
265
|
+
elif lang == "es":
|
|
266
|
+
initial_prompt = "Transcripción en español: " + initial_prompt
|
|
267
|
+
|
|
261
268
|
segments, _info = model.transcribe(
|
|
262
269
|
audio,
|
|
263
270
|
language=lang,
|
|
264
271
|
initial_prompt=initial_prompt,
|
|
272
|
+
condition_on_previous_text=False, # avoid language drift on short audio
|
|
265
273
|
vad_filter=True, # skip silent regions
|
|
266
274
|
vad_parameters=dict(
|
|
267
275
|
min_silence_duration_ms=300,
|
|
@@ -291,6 +299,13 @@ def _transcribe_openai_whisper(
|
|
|
291
299
|
audio = np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32) / 32768.0
|
|
292
300
|
|
|
293
301
|
initial_prompt = _keyterms_to_prompt(keyterms)
|
|
302
|
+
|
|
303
|
+
# Force Spanish context when language is set to "es"
|
|
304
|
+
if language == "es" and not initial_prompt:
|
|
305
|
+
initial_prompt = "Transcripción en español."
|
|
306
|
+
elif language == "es":
|
|
307
|
+
initial_prompt = "Transcripción en español: " + initial_prompt
|
|
308
|
+
|
|
294
309
|
options: dict = {"initial_prompt": initial_prompt} if initial_prompt else {}
|
|
295
310
|
if language and language != "auto":
|
|
296
311
|
options["language"] = language
|
|
@@ -356,7 +371,9 @@ def transcribe(
|
|
|
356
371
|
lang = None if language == "auto" else language
|
|
357
372
|
|
|
358
373
|
# NVIDIA Riva (whisper-large-v3, cloud) — preferred when configured
|
|
359
|
-
if
|
|
374
|
+
# Skip Riva for wake-word detection if DULUS_WAKE_FORCE_LOCAL is set
|
|
375
|
+
# (avoids cloud latency / 502 errors on hotword path)
|
|
376
|
+
if _riva_available() and not os.environ.get("DULUS_WAKE_FORCE_LOCAL"):
|
|
360
377
|
try:
|
|
361
378
|
return _transcribe_nvidia_riva(pcm_bytes, lang)
|
|
362
379
|
except Exception as e:
|
|
@@ -31,6 +31,7 @@ Usage
|
|
|
31
31
|
|
|
32
32
|
from __future__ import annotations
|
|
33
33
|
|
|
34
|
+
import os
|
|
34
35
|
import sys
|
|
35
36
|
import threading
|
|
36
37
|
import time
|
|
@@ -44,8 +45,23 @@ from .stt import transcribe
|
|
|
44
45
|
# ── Config ────────────────────────────────────────────────────────────────
|
|
45
46
|
|
|
46
47
|
WAKE_PHRASES: list[str] = [
|
|
48
|
+
# --- Variantes con "dulus" (S) ---
|
|
47
49
|
"hey dulus", "okey dulus", "ok dulus", "dale dulus",
|
|
48
50
|
"oye dulus", "escucha dulus", "dulus",
|
|
51
|
+
"dolus", "daulus", "doiulus",
|
|
52
|
+
# --- Variantes con "duluz" (Z) ---
|
|
53
|
+
"hey duluz", "okey duluz", "ok duluz", "dale duluz",
|
|
54
|
+
"oye duluz", "escucha duluz", "duluz",
|
|
55
|
+
"dolus", "dauluz", "doiuluz",
|
|
56
|
+
# --- Variantes con signos de exclamación (como transcribe Whisper) ---
|
|
57
|
+
"¡oye! ¡dulus!", "¡oye! ¡duluz!",
|
|
58
|
+
"¡okey dulus!", "¡okey duluz!",
|
|
59
|
+
"¡ok dulus!", "¡ok duluz!",
|
|
60
|
+
"¡dale dulus!", "¡dale duluz!",
|
|
61
|
+
"¡hey dulus!", "¡hey duluz!",
|
|
62
|
+
# --- Variantes cortas / slang ---
|
|
63
|
+
"dulus", "duluz", "dolus", "dulús", "dulúz",
|
|
64
|
+
"oye", "okey", "ok", "dale", "escucha",
|
|
49
65
|
]
|
|
50
66
|
|
|
51
67
|
# VAD: chunk size and energy threshold.
|
|
@@ -126,6 +142,10 @@ class WakeWordListener:
|
|
|
126
142
|
# like "Hey Dulus" don't get mis-detected by Whisper's auto-lang.
|
|
127
143
|
self._wake_lang = "es" if language in ("auto", "") else language
|
|
128
144
|
|
|
145
|
+
# Force local STT (Whisper) for wake-word — avoids cloud latency
|
|
146
|
+
# and 502 errors from NVIDIA Riva on the hotword path.
|
|
147
|
+
os.environ["DULUS_WAKE_FORCE_LOCAL"] = "1"
|
|
148
|
+
|
|
129
149
|
self._thread: threading.Thread | None = None
|
|
130
150
|
self._stop_evt = threading.Event()
|
|
131
151
|
self._running = False
|
|
Binary file
|
|
Binary file
|
|
Binary file
|