dulus 3.9.1__tar.gz → 3.9.3__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-3.9.1/dulus.egg-info → dulus-3.9.3}/PKG-INFO +1 -1
- {dulus-3.9.1 → dulus-3.9.3}/analytics.py +71 -3
- {dulus-3.9.1 → dulus-3.9.3}/context.py +21 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/dashboard/index.html +10 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/index.html +10 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/personas/index.html +10 -0
- {dulus-3.9.1 → dulus-3.9.3/dulus.egg-info}/PKG-INFO +1 -1
- {dulus-3.9.1 → dulus-3.9.3}/dulus.py +33 -2
- {dulus-3.9.1 → dulus-3.9.3}/pyproject.toml +1 -1
- {dulus-3.9.1 → dulus-3.9.3}/webchat_server.py +65 -3
- {dulus-3.9.1 → dulus-3.9.3}/LICENSE +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/MANIFEST.in +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/README.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/agent.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/agents_bridge.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/compressor.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/context.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/githook.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/marketplace.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/mempalace_bridge.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/personas.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/plugins.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/server.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/backend/tasks.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/batch_api.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/checkpoint/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/checkpoint/hooks.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/checkpoint/store.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/checkpoint/types.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/claude_code_watcher.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/clipboard_utils.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/cloudsave.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/common.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/compaction.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/config.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/active_persona.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/marketplace.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/personas.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/composio/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/composio/composio_plugin/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/composio/plugin.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/plugins/composio/plugin_tool.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/data/tasks.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/API.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/BRAND_GUIDE.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/CHANGELOG.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/CONTRIBUTING.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/DEPLOYMENT.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/Dulus_AI_Whitepaper_(v2.0).pdf +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/FAQ.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/GETTING_STARTED.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/INVESTOR_BRIEF.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_AR.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_EN.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_ES.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_FR.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_JA.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_KO.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_PT.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_RU.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/README_ZH.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/SECURITY.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/api.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/architecture.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/azure-speech-template.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/divider.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/dulus-bird.png +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/generate.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/hero.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/news.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/nvidia-models.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/particle-playground.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/poetry-banner.png +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/preview.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-agents.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-brainstorm.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-bridges.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-features.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-freetier.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-memory.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-models.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-perms.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-plugins.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-quickstart.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/sec-ssj.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/spinners.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/split-pane.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/docs/terminal-boot.svg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus.egg-info/requires.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus.egg-info/top_level.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_gui.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_gui_web.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/client.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/commands.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/config.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/hub.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_mcp/types.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/add_dir_manager.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/afk_mode.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/approval_runtime.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/background_tasks.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/clipboard_utils.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/diff_visualizer.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/export_import.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/hook_engine.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/notification_manager.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/session_fork.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/shell_mode.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/todo_visualizer.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/tree_ls.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/wire_events.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/dulus_tools/yolo_mode.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/governance.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/agent_bridge.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/chat_widget.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/App.tsx +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/THIRD_PARTY_NOTICES.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/dist/index.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/dist/standalone.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/index.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/index.tsx +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/metadata.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/package-lock.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/package.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/types.ts +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/utils.ts +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/vertex-ai-proxy-interceptor.js +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/dulus_orchestrator/vite.config.ts +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/main_window.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/personas.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/sandbox_server.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/session_utils.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/settings_dialog.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/sidebar.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/tasks_view.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/themes.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/gui/tool_panel.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/input.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/license_manager.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/audit.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/consolidator.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/context.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/offload.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/palace.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/scan.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/sessions.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/store.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/types.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/memory/vector_search.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/multi_agent/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/multi_agent/subagent.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/multi_agent/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/offload_helper.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/personality_config.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/plugin/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/plugin/autoadapter.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/plugin/loader.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/plugin/recommend.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/plugin/store.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/plugin/types.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/providers.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/README.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/components.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/assets/index-DE51D6wI.css +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/assets/index-DMCCNE9Y.js +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/index.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/wallpaper-default.jpg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/wallpapers/default.jpeg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/wallpapers/light.jpeg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/wallpapers/nature.jpeg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/dist/wallpapers/tech.jpeg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/eslint.config.js +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/index.html +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/info.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/package-lock.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/package.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/postcss.config.js +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/tailwind.config.js +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/tsconfig.app.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/tsconfig.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/tsconfig.node.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox/vite.config.ts +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/sandbox_bootstrap.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/setup.cfg +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/builtin.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/LICENSE-obsidian-skills +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/README.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/defuddle/SKILL.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/json-canvas/SKILL.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/json-canvas/references/EXAMPLES.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-bases/SKILL.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-bases/references/FUNCTIONS_REFERENCE.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-cli/SKILL.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-markdown/SKILL.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-markdown/references/CALLOUTS.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-markdown/references/EMBEDS.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/obsidian-markdown/references/PROPERTIES.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/README.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/SKILL.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/addresses.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/advancedbackgroundchecks.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/beenverified.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/clustal.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/clustrmaps.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/cyberbackgroundchecks.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/familytreenow.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/fastpeoplesearch.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/intelius.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/mylife.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/nuwber.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/peekyou.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/peoplefinders.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/radaris.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/rehold.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/searchpeoplefree.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/socialcatfish.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/spokeo.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/thatsthem.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/truepeoplesearch.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/usphonebook.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/whitepages.json +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/legal/ccpa.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/legal/drop.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/legal/gdpr.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/methods.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/site-playbooks.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/references/state-machine.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/autopilot.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/badbool.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/brokers.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/cdp.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/config.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/crypto.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/dossier.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/email_modes.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/emailer.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/ledger.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/legal.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/paths.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/pdd.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/registry.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/report.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/scan.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/storage.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/tiers.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/scripts/vectors.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/templates/consent/authorization.md +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/ccpa-authorized-agent.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/ccpa-deletion.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/ccpa-indirect-deletion.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/gdpr-erasure.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/generic-optout.txt +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/clawhub.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/executor.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/loader.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skill/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/skills.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/soul.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/spinner.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/string_utils.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/subagent.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/task/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/task/store.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/task/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/task/types.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_afk_yolo.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_approval_runtime.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_background_task_tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_background_tasks.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_checkpoint.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_clipboard_utils.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_compaction.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_diff_view.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_diff_visualization.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_display_blocks.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_export_import.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_hook_engine.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_injection_fix.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_license.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_mcp.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_memory.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_notification_manager.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_plugin.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_session_fork.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_shell_mode.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_skills.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_steer_input.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_subagent.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_task.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_telegram_buffer.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_think_tool.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_todo_tool.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_todo_visualization.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_tool_registry.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_tree_ls.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_voice.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tests/test_wire_events.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tmux_offloader.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tmux_tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tool_registry.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/ui/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/ui/input.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/ui/render.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/updater.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/audio_utils.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/keyterms.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/recorder.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/stt.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/tts.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/voice/wake_word.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/webbridge/__init__.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/webbridge/core.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/webbridge/tools.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/webchat.py +0 -0
- {dulus-3.9.1 → dulus-3.9.3}/welcome.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 3.9.
|
|
3
|
+
Version: 3.9.3
|
|
4
4
|
Summary: Use IA as an agent without an API key. $0. Harvest your browser session for Gemini (guest, no login), Claude.ai, Claude Code, Kimi.com, Qwen, DeepSeek — drive them like an API, no per-token billing. Plus LiteLLM (100+ paid providers), local models via Ollama, /lang in 34 languages, Mesa Redonda, voice, OCR, MemPalace, embedded sandbox OS.
|
|
5
5
|
Author: KevRojo
|
|
6
6
|
License: GPL-3.0
|
|
@@ -29,6 +29,7 @@ silently ignored; telemetry must never slow down or break Dulus.
|
|
|
29
29
|
from __future__ import annotations
|
|
30
30
|
|
|
31
31
|
import base64
|
|
32
|
+
import datetime as _dt
|
|
32
33
|
import json
|
|
33
34
|
import os
|
|
34
35
|
import platform
|
|
@@ -45,6 +46,23 @@ MP_TOKEN = os.environ.get("DULUS_MP_TOKEN", "966ce8f5ccb32f06788f51be9f8bf8f5")
|
|
|
45
46
|
|
|
46
47
|
_MP_ENDPOINT = "https://api.mixpanel.com/track"
|
|
47
48
|
|
|
49
|
+
# ── PostHog (product analytics, runs alongside Mixpanel) ────────────────────
|
|
50
|
+
# Project API keys (phc_...) are public/write-only by design — meant to ship in
|
|
51
|
+
# client code, cannot read data. Override with DULUS_POSTHOG_KEY.
|
|
52
|
+
POSTHOG_KEY = os.environ.get(
|
|
53
|
+
"DULUS_POSTHOG_KEY", "phc_yqAJ42vbj8YFkdpxZicsS4asdbWFTPy6orR8uRNewfYD"
|
|
54
|
+
)
|
|
55
|
+
_POSTHOG_ENDPOINT = os.environ.get(
|
|
56
|
+
"DULUS_POSTHOG_HOST", "https://us.i.posthog.com"
|
|
57
|
+
).rstrip("/") + "/capture/"
|
|
58
|
+
|
|
59
|
+
# ── Amplitude (behavioral analytics, runs alongside the others) ─────────────
|
|
60
|
+
# API keys are write-only client keys (safe to ship). Override w/ DULUS_AMPLITUDE_KEY.
|
|
61
|
+
AMPLITUDE_KEY = os.environ.get(
|
|
62
|
+
"DULUS_AMPLITUDE_KEY", "2511c9e1fc597b8bc6b81f193cc615a2"
|
|
63
|
+
)
|
|
64
|
+
_AMPLITUDE_ENDPOINT = "https://api2.amplitude.com/2/httpapi"
|
|
65
|
+
|
|
48
66
|
# Populated by init_telemetry(); None = not initialised / disabled.
|
|
49
67
|
_distinct_id: str | None = None
|
|
50
68
|
_enabled: bool = False
|
|
@@ -121,10 +139,11 @@ def track(event: str, properties: dict | None = None) -> None:
|
|
|
121
139
|
}
|
|
122
140
|
|
|
123
141
|
def _send() -> None:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
from urllib.parse import urlencode
|
|
142
|
+
from urllib.request import Request, urlopen
|
|
143
|
+
from urllib.parse import urlencode
|
|
127
144
|
|
|
145
|
+
# Mixpanel
|
|
146
|
+
try:
|
|
128
147
|
data = urlencode(
|
|
129
148
|
{"data": base64.b64encode(json.dumps([payload]).encode()).decode()}
|
|
130
149
|
).encode()
|
|
@@ -133,6 +152,55 @@ def track(event: str, properties: dict | None = None) -> None:
|
|
|
133
152
|
except Exception:
|
|
134
153
|
pass # telemetry must never break Dulus
|
|
135
154
|
|
|
155
|
+
# PostHog (same event, product-analytics brain)
|
|
156
|
+
if POSTHOG_KEY:
|
|
157
|
+
try:
|
|
158
|
+
ph_props = {
|
|
159
|
+
"dulus_version": _dulus_version,
|
|
160
|
+
"os": platform.system(),
|
|
161
|
+
"python": f"{sys.version_info.major}.{sys.version_info.minor}",
|
|
162
|
+
"$process_person_profile": False, # anonymous, no PII person
|
|
163
|
+
**(properties or {}),
|
|
164
|
+
}
|
|
165
|
+
ph_payload = {
|
|
166
|
+
"api_key": POSTHOG_KEY,
|
|
167
|
+
"event": event,
|
|
168
|
+
"distinct_id": _distinct_id,
|
|
169
|
+
"properties": ph_props,
|
|
170
|
+
"timestamp": _dt.datetime.utcnow().isoformat() + "Z",
|
|
171
|
+
}
|
|
172
|
+
ph_data = json.dumps(ph_payload).encode()
|
|
173
|
+
ph_req = Request(
|
|
174
|
+
_POSTHOG_ENDPOINT, data=ph_data, method="POST",
|
|
175
|
+
headers={"Content-Type": "application/json"},
|
|
176
|
+
)
|
|
177
|
+
urlopen(ph_req, timeout=4).read()
|
|
178
|
+
except Exception:
|
|
179
|
+
pass # telemetry must never break Dulus
|
|
180
|
+
|
|
181
|
+
# Amplitude (same event, behavioral-analytics brain)
|
|
182
|
+
if AMPLITUDE_KEY:
|
|
183
|
+
try:
|
|
184
|
+
amp_event = {
|
|
185
|
+
"user_id": (_distinct_id or "anon").ljust(5, "_"), # min 5 chars
|
|
186
|
+
"event_type": event,
|
|
187
|
+
"platform": platform.system(),
|
|
188
|
+
"app_version": _dulus_version,
|
|
189
|
+
"event_properties": (properties or {}),
|
|
190
|
+
}
|
|
191
|
+
amp_payload = {
|
|
192
|
+
"api_key": AMPLITUDE_KEY,
|
|
193
|
+
"events": [amp_event],
|
|
194
|
+
}
|
|
195
|
+
amp_data = json.dumps(amp_payload).encode()
|
|
196
|
+
amp_req = Request(
|
|
197
|
+
_AMPLITUDE_ENDPOINT, data=amp_data, method="POST",
|
|
198
|
+
headers={"Content-Type": "application/json"},
|
|
199
|
+
)
|
|
200
|
+
urlopen(amp_req, timeout=4).read()
|
|
201
|
+
except Exception:
|
|
202
|
+
pass # telemetry must never break Dulus
|
|
203
|
+
|
|
136
204
|
threading.Thread(target=_send, daemon=True, name="telemetry").start()
|
|
137
205
|
|
|
138
206
|
|
|
@@ -356,5 +356,26 @@ def build_system_prompt(config: dict | None = None) -> str:
|
|
|
356
356
|
if project_mem:
|
|
357
357
|
prompt += project_mem
|
|
358
358
|
|
|
359
|
+
# ── Reply-language HARD OVERRIDE ──────────────────────────────────────────
|
|
360
|
+
# The soul (soul.md) and gold memories are injected as conversation messages
|
|
361
|
+
# and often assert a fixed voice ("I speak Dominican Spanish"). Those pin the
|
|
362
|
+
# language and quietly beat the single line at the top of the prompt, so
|
|
363
|
+
# /lang appeared to "not work". We re-assert the chosen language HERE, at the
|
|
364
|
+
# very end of the system prompt (highest authority / most recent), but only
|
|
365
|
+
# when the user has explicitly set config["lang"] to something other than the
|
|
366
|
+
# Dominican-Spanish default — otherwise the soul stays in charge.
|
|
367
|
+
if config:
|
|
368
|
+
raw_lang = (config.get("lang", "") or "").strip()
|
|
369
|
+
if raw_lang:
|
|
370
|
+
resolved = _resolve_reply_language(config)
|
|
371
|
+
if resolved and resolved != "Dominican Spanish":
|
|
372
|
+
prompt += (
|
|
373
|
+
f"\n\n# ⚠ LANGUAGE OVERRIDE (set via /lang — HIGHEST PRIORITY): "
|
|
374
|
+
f"Reply to {user_name} in {resolved}. This OVERRIDES any language "
|
|
375
|
+
f"stated in your soul, identity essence, or golden memories. "
|
|
376
|
+
f"Keep your personality and tone, but the OUTPUT LANGUAGE must be "
|
|
377
|
+
f"{resolved}, no exceptions, every single turn."
|
|
378
|
+
)
|
|
379
|
+
|
|
359
380
|
return prompt
|
|
360
381
|
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
|
+
<!-- Amplitude behavioral analytics -->
|
|
6
|
+
<script src="https://cdn.amplitude.com/script/2511c9e1fc597b8bc6b81f193cc615a2.js"></script>
|
|
7
|
+
<script>window.amplitude&&window.amplitude.init&&window.amplitude.init('2511c9e1fc597b8bc6b81f193cc615a2',{"fetchRemoteConfig":true,"autocapture":true});</script>
|
|
8
|
+
|
|
9
|
+
<!-- PostHog product analytics -->
|
|
10
|
+
<script>
|
|
11
|
+
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture identify reset get_distinct_id capture_pageview capture_pageleave".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
12
|
+
posthog.init('phc_yqAJ42vbj8YFkdpxZicsS4asdbWFTPy6orR8uRNewfYD',{api_host:'https://us.i.posthog.com',person_profiles:'identified_only',capture_pageview:true,capture_pageleave:true});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
5
15
|
<meta charset="UTF-8">
|
|
6
16
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
17
|
<title>Dulus — Task Dashboard</title>
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
+
<!-- Amplitude behavioral analytics -->
|
|
5
|
+
<script src="https://cdn.amplitude.com/script/2511c9e1fc597b8bc6b81f193cc615a2.js"></script>
|
|
6
|
+
<script>window.amplitude&&window.amplitude.init&&window.amplitude.init('2511c9e1fc597b8bc6b81f193cc615a2',{"fetchRemoteConfig":true,"autocapture":true});</script>
|
|
7
|
+
|
|
8
|
+
<!-- PostHog product analytics -->
|
|
9
|
+
<script>
|
|
10
|
+
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture identify reset get_distinct_id capture_pageview capture_pageleave".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
11
|
+
posthog.init('phc_yqAJ42vbj8YFkdpxZicsS4asdbWFTPy6orR8uRNewfYD',{api_host:'https://us.i.posthog.com',person_profiles:'identified_only',capture_pageview:true,capture_pageleave:true});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
4
14
|
<meta charset="UTF-8">
|
|
5
15
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
16
|
<title>Dulus — Hunt. Patch. Ship.</title>
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
+
<!-- Amplitude behavioral analytics -->
|
|
5
|
+
<script src="https://cdn.amplitude.com/script/2511c9e1fc597b8bc6b81f193cc615a2.js"></script>
|
|
6
|
+
<script>window.amplitude&&window.amplitude.init&&window.amplitude.init('2511c9e1fc597b8bc6b81f193cc615a2',{"fetchRemoteConfig":true,"autocapture":true});</script>
|
|
7
|
+
|
|
8
|
+
<!-- PostHog product analytics -->
|
|
9
|
+
<script>
|
|
10
|
+
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture identify reset get_distinct_id capture_pageview capture_pageleave".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
11
|
+
posthog.init('phc_yqAJ42vbj8YFkdpxZicsS4asdbWFTPy6orR8uRNewfYD',{api_host:'https://us.i.posthog.com',person_profiles:'identified_only',capture_pageview:true,capture_pageleave:true});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
4
14
|
<meta charset="UTF-8">
|
|
5
15
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
16
|
<title>Mesa Redonda — Dulus Personas</title>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 3.9.
|
|
3
|
+
Version: 3.9.3
|
|
4
4
|
Summary: Use IA as an agent without an API key. $0. Harvest your browser session for Gemini (guest, no login), Claude.ai, Claude Code, Kimi.com, Qwen, DeepSeek — drive them like an API, no per-token billing. Plus LiteLLM (100+ paid providers), local models via Ollama, /lang in 34 languages, Mesa Redonda, voice, OCR, MemPalace, embedded sandbox OS.
|
|
5
5
|
Author: KevRojo
|
|
6
6
|
License: GPL-3.0
|
|
@@ -71,6 +71,11 @@ Slash commands in REPL:
|
|
|
71
71
|
/skill use <name> Inject skill into next message /skill remove <name> Uninstall
|
|
72
72
|
/agents Show sub-agent tasks
|
|
73
73
|
/mcp List MCP servers and their tools
|
|
74
|
+
/mcp list [query] Browse the catalog of 2000+ MCP servers
|
|
75
|
+
/mcp search <q> Search every source for matching servers
|
|
76
|
+
/mcp install <n> Install a server by name (auto-connects)
|
|
77
|
+
/mcp installed Show installed servers + live status
|
|
78
|
+
/mcp runtimes Show available runtimes (node/python/docker)
|
|
74
79
|
/mcp reload Reconnect all MCP servers
|
|
75
80
|
/mcp add <n> <cmd> [args] Add a stdio MCP server
|
|
76
81
|
/mcp remove <n> Remove an MCP server from config
|
|
@@ -838,6 +843,7 @@ _HELP_PAGES = [
|
|
|
838
843
|
("/cwd [path]", "Show or change working directory"),
|
|
839
844
|
("/copy [file]", "Copy last response (or file) to clipboard"),
|
|
840
845
|
("/shell [cmd|on|off]", "Shell mode toggle or one-shot command"),
|
|
846
|
+
("/update [now|on|off]", "Self-update Dulus from PyPI (auto-check at startup)"),
|
|
841
847
|
("/exit /quit", "Exit Dulus"),
|
|
842
848
|
]),
|
|
843
849
|
("Session", [
|
|
@@ -877,7 +883,10 @@ _HELP_PAGES = [
|
|
|
877
883
|
("/plugin recommend [ctx]", "Recommend plugins for a context"),
|
|
878
884
|
("/agents", "Show sub-agent tasks"),
|
|
879
885
|
("/mcp", "List MCP servers and tools"),
|
|
880
|
-
("/mcp
|
|
886
|
+
("/mcp list | search <q>", "Browse/search 2000+ MCP servers"),
|
|
887
|
+
("/mcp install <name>", "Install a server by name (auto-connects)"),
|
|
888
|
+
("/mcp installed | runtimes","Show installed servers / available runtimes"),
|
|
889
|
+
("/mcp reload | add | remove","Manage MCP servers manually"),
|
|
881
890
|
("/tasks", "List/create/update tasks"),
|
|
882
891
|
]),
|
|
883
892
|
("Voice · Wake", [
|
|
@@ -2438,6 +2447,25 @@ def cmd_lang(args: str, state, config) -> bool:
|
|
|
2438
2447
|
except Exception:
|
|
2439
2448
|
pass
|
|
2440
2449
|
resolved = _resolve_reply_language(config)
|
|
2450
|
+
# Inject an immediate, high-recency override into the live conversation so
|
|
2451
|
+
# the switch takes effect THIS turn and beats the already-loaded soul /
|
|
2452
|
+
# gold memories (which assert a fixed voice). Without this, /lang only
|
|
2453
|
+
# "won" on the next system-prompt rebuild and the soul kept pinning the
|
|
2454
|
+
# old language — which is exactly why it looked broken.
|
|
2455
|
+
try:
|
|
2456
|
+
if state is not None and hasattr(state, "messages"):
|
|
2457
|
+
state.messages.append({
|
|
2458
|
+
"role": "user",
|
|
2459
|
+
"content": (
|
|
2460
|
+
f"[SYSTEM DIRECTIVE — LANGUAGE OVERRIDE] From now on, reply to me "
|
|
2461
|
+
f"exclusively in {resolved}. This takes priority over any language "
|
|
2462
|
+
f"stated in your soul, identity essence, or golden memories. Keep "
|
|
2463
|
+
f"your personality and tone intact, but switch the OUTPUT LANGUAGE "
|
|
2464
|
+
f"to {resolved} starting with your very next message, every turn."
|
|
2465
|
+
),
|
|
2466
|
+
})
|
|
2467
|
+
except Exception:
|
|
2468
|
+
pass
|
|
2441
2469
|
ok(f"Reply language → {resolved}")
|
|
2442
2470
|
if resolved == arg and arg.lower() not in _LANG_NAMES:
|
|
2443
2471
|
info("(Free-form descriptor — passed verbatim to the model)")
|
|
@@ -9952,7 +9980,9 @@ _CMD_META: dict[str, tuple[str, list[str]]] = {
|
|
|
9952
9980
|
"profiles": ("Manage agent Profiles (alias)", ["list", "show", "create", "switch", "delete", "inherit"]),
|
|
9953
9981
|
"memory": ("Manage persistent memories", ["list", "load", "permanent", "unbind", "consolidate", "delete", "purge", "purge-soul"]),
|
|
9954
9982
|
"agents": ("Show background agents", []),
|
|
9955
|
-
"mcp": ("
|
|
9983
|
+
"mcp": ("Browse & install MCP servers", ["list", "search", "install",
|
|
9984
|
+
"installed", "runtimes", "reload",
|
|
9985
|
+
"add", "remove"]),
|
|
9956
9986
|
"plugin": ("Manage plugins", ["install", "uninstall", "enable",
|
|
9957
9987
|
"disable", "disable-all", "update",
|
|
9958
9988
|
"recommend", "info"]),
|
|
@@ -10002,6 +10032,7 @@ _CMD_META: dict[str, tuple[str, list[str]]] = {
|
|
|
10002
10032
|
"exit": ("Exit dulus", []),
|
|
10003
10033
|
"quit": ("Exit (alias for /exit)", []),
|
|
10004
10034
|
"resume": ("Resume last session", []),
|
|
10035
|
+
"update": ("Self-update Dulus from PyPI", ["now", "check", "status", "on", "off"]),
|
|
10005
10036
|
"news": ("Show latest project news", []),
|
|
10006
10037
|
"claude_chats": ("List Claude.ai conversations", ["all"]),
|
|
10007
10038
|
"gemini_chats": ("Manage Gemini Web conversations", ["new"]),
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dulus"
|
|
7
|
-
version = "3.9.
|
|
7
|
+
version = "3.9.3"
|
|
8
8
|
description = "Use IA as an agent without an API key. $0. Harvest your browser session for Gemini (guest, no login), Claude.ai, Claude Code, Kimi.com, Qwen, DeepSeek — drive them like an API, no per-token billing. Plus LiteLLM (100+ paid providers), local models via Ollama, /lang in 34 languages, Mesa Redonda, voice, OCR, MemPalace, embedded sandbox OS."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -39,6 +39,61 @@ def _resolve_dashboard_dir() -> Path:
|
|
|
39
39
|
|
|
40
40
|
DASHBOARD_DIR = _resolve_dashboard_dir()
|
|
41
41
|
|
|
42
|
+
# ── PostHog analytics snippet (injected into every served HTML page) ─────────
|
|
43
|
+
# Public project API key (phc_...) — safe to ship in client code. Override via
|
|
44
|
+
# DULUS_POSTHOG_KEY / DULUS_POSTHOG_HOST env vars.
|
|
45
|
+
import os as _os
|
|
46
|
+
_POSTHOG_KEY = _os.environ.get(
|
|
47
|
+
"DULUS_POSTHOG_KEY", "phc_yqAJ42vbj8YFkdpxZicsS4asdbWFTPy6orR8uRNewfYD"
|
|
48
|
+
)
|
|
49
|
+
_POSTHOG_HOST = _os.environ.get("DULUS_POSTHOG_HOST", "https://us.i.posthog.com")
|
|
50
|
+
|
|
51
|
+
# Amplitude behavioral analytics (Browser SDK 2, loaded alongside PostHog).
|
|
52
|
+
_AMPLITUDE_KEY = _os.environ.get(
|
|
53
|
+
"DULUS_AMPLITUDE_KEY", "2511c9e1fc597b8bc6b81f193cc615a2"
|
|
54
|
+
)
|
|
55
|
+
_AMPLITUDE_SNIPPET = """<script src="https://cdn.amplitude.com/script/__AMP_KEY__.js"></script>
|
|
56
|
+
<script>window.amplitude&&window.amplitude.init&&window.amplitude.init('__AMP_KEY__',{"fetchRemoteConfig":true,"autocapture":true});</script>"""
|
|
57
|
+
|
|
58
|
+
_POSTHOG_SNIPPET = """<script>
|
|
59
|
+
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording capture_pageview capture_pageleave".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
60
|
+
posthog.init('__PH_KEY__',{api_host:'__PH_HOST__',person_profiles:'identified_only',capture_pageview:true,capture_pageleave:true});
|
|
61
|
+
</script>"""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _inject_posthog(html: str) -> str:
|
|
65
|
+
"""Insert the PostHog snippet right after <head> in an HTML string.
|
|
66
|
+
|
|
67
|
+
No-op if the key is empty, the page has no <head>, or the snippet is
|
|
68
|
+
already present. Never raises — analytics must never break the page.
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
if "posthog.init" in html and "amplitude" in html:
|
|
72
|
+
return html # both already present
|
|
73
|
+
snippet = ""
|
|
74
|
+
if _POSTHOG_KEY and "posthog.init" not in html:
|
|
75
|
+
snippet += _POSTHOG_SNIPPET.replace("__PH_KEY__", _POSTHOG_KEY).replace(
|
|
76
|
+
"__PH_HOST__", _POSTHOG_HOST
|
|
77
|
+
)
|
|
78
|
+
if _AMPLITUDE_KEY and "amplitude" not in html:
|
|
79
|
+
snippet += _AMPLITUDE_SNIPPET.replace("__AMP_KEY__", _AMPLITUDE_KEY)
|
|
80
|
+
if not snippet:
|
|
81
|
+
return html
|
|
82
|
+
low = html.lower()
|
|
83
|
+
idx = low.find("<head>")
|
|
84
|
+
if idx != -1:
|
|
85
|
+
pos = idx + len("<head>")
|
|
86
|
+
return html[:pos] + snippet + html[pos:]
|
|
87
|
+
# Fallback: some pages use <head ...> with attributes.
|
|
88
|
+
idx = low.find("<head")
|
|
89
|
+
if idx != -1:
|
|
90
|
+
close = html.find(">", idx)
|
|
91
|
+
if close != -1:
|
|
92
|
+
return html[: close + 1] + snippet + html[close + 1 :]
|
|
93
|
+
return html
|
|
94
|
+
except Exception:
|
|
95
|
+
return html
|
|
96
|
+
|
|
42
97
|
from flask import Flask, request, jsonify, Response, stream_with_context, send_from_directory
|
|
43
98
|
|
|
44
99
|
from agent import (
|
|
@@ -3412,11 +3467,11 @@ restoreRt();
|
|
|
3412
3467
|
|
|
3413
3468
|
@app.route("/")
|
|
3414
3469
|
def home() -> Response:
|
|
3415
|
-
return Response(CHAT_PAGE, mimetype="text/html")
|
|
3470
|
+
return Response(_inject_posthog(CHAT_PAGE), mimetype="text/html")
|
|
3416
3471
|
|
|
3417
3472
|
@app.route("/roundtable")
|
|
3418
3473
|
def roundtable_page() -> Response:
|
|
3419
|
-
return Response(RT_PAGE, mimetype="text/html")
|
|
3474
|
+
return Response(_inject_posthog(RT_PAGE), mimetype="text/html")
|
|
3420
3475
|
|
|
3421
3476
|
# Favicon — the Dulus palmchat (cigua palmera) logo. Lives at repo root
|
|
3422
3477
|
# in dev, but in an installed wheel only docs/dulus-bird.png ships (it's
|
|
@@ -3443,7 +3498,14 @@ restoreRt();
|
|
|
3443
3498
|
@app.route("/sandbox")
|
|
3444
3499
|
@app.route("/sandbox/")
|
|
3445
3500
|
def sandbox_index() -> Response:
|
|
3446
|
-
|
|
3501
|
+
# Read the built index.html and inject PostHog before serving so the
|
|
3502
|
+
# Web OS reports analytics too (no rebuild needed).
|
|
3503
|
+
try:
|
|
3504
|
+
_idx = Path(_ensure_sandbox()) / "index.html"
|
|
3505
|
+
_html = _idx.read_text(encoding="utf-8")
|
|
3506
|
+
return Response(_inject_posthog(_html), mimetype="text/html")
|
|
3507
|
+
except Exception:
|
|
3508
|
+
return send_from_directory(_ensure_sandbox(), "index.html")
|
|
3447
3509
|
|
|
3448
3510
|
@app.route("/sandbox/<path:path>")
|
|
3449
3511
|
def sandbox_static(path) -> Response:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|