dulus 3.9.2__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.2/dulus.egg-info → dulus-3.9.3}/PKG-INFO +1 -1
- {dulus-3.9.2 → dulus-3.9.3}/analytics.py +71 -3
- {dulus-3.9.2 → dulus-3.9.3}/context.py +21 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/dashboard/index.html +10 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/index.html +10 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/personas/index.html +10 -0
- {dulus-3.9.2 → dulus-3.9.3/dulus.egg-info}/PKG-INFO +1 -1
- {dulus-3.9.2 → dulus-3.9.3}/dulus.py +19 -0
- {dulus-3.9.2 → dulus-3.9.3}/pyproject.toml +1 -1
- {dulus-3.9.2 → dulus-3.9.3}/webchat_server.py +65 -3
- {dulus-3.9.2 → dulus-3.9.3}/LICENSE +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/MANIFEST.in +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/README.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/agent.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/agents_bridge.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/compressor.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/context.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/githook.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/marketplace.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/mempalace_bridge.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/personas.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/plugins.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/server.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/backend/tasks.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/batch_api.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/checkpoint/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/checkpoint/hooks.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/checkpoint/store.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/checkpoint/types.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/claude_code_watcher.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/clipboard_utils.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/cloudsave.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/common.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/compaction.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/config.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/active_persona.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/marketplace.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/personas.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/composio/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/composio/composio_plugin/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/composio/plugin.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/plugins/composio/plugin_tool.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/data/tasks.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/API.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/BRAND_GUIDE.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/CHANGELOG.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/CONTRIBUTING.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/DEPLOYMENT.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/Dulus_AI_Whitepaper_(v2.0).pdf +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/FAQ.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/GETTING_STARTED.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/INVESTOR_BRIEF.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_AR.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_EN.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_ES.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_FR.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_JA.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_KO.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_PT.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_RU.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/README_ZH.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/SECURITY.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/api.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/architecture.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/azure-speech-template.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/divider.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/dulus-bird.png +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/generate.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/hero.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/news.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/nvidia-models.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/particle-playground.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/poetry-banner.png +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/preview.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-agents.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-brainstorm.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-bridges.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-features.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-freetier.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-memory.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-models.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-perms.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-plugins.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-quickstart.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/sec-ssj.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/spinners.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/split-pane.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/docs/terminal-boot.svg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus.egg-info/requires.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus.egg-info/top_level.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_gui.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_gui_web.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/client.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/commands.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/config.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/hub.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_mcp/types.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/add_dir_manager.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/afk_mode.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/approval_runtime.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/background_tasks.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/clipboard_utils.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/diff_visualizer.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/export_import.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/hook_engine.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/notification_manager.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/session_fork.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/shell_mode.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/todo_visualizer.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/tree_ls.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/wire_events.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/dulus_tools/yolo_mode.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/governance.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/agent_bridge.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/chat_widget.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/App.tsx +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/THIRD_PARTY_NOTICES.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/dist/index.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/dist/standalone.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/index.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/index.tsx +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/metadata.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/package-lock.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/package.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/types.ts +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/utils.ts +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/vertex-ai-proxy-interceptor.js +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/dulus_orchestrator/vite.config.ts +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/main_window.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/personas.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/sandbox_server.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/session_utils.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/settings_dialog.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/sidebar.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/tasks_view.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/themes.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/gui/tool_panel.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/input.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/license_manager.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/audit.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/consolidator.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/context.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/offload.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/palace.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/scan.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/sessions.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/store.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/types.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/memory/vector_search.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/multi_agent/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/multi_agent/subagent.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/multi_agent/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/offload_helper.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/personality_config.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/plugin/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/plugin/autoadapter.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/plugin/loader.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/plugin/recommend.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/plugin/store.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/plugin/types.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/providers.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/README.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/components.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/assets/index-DE51D6wI.css +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/assets/index-DMCCNE9Y.js +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/index.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/wallpaper-default.jpg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/wallpapers/default.jpeg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/wallpapers/light.jpeg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/wallpapers/nature.jpeg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/dist/wallpapers/tech.jpeg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/eslint.config.js +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/index.html +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/info.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/package-lock.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/package.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/postcss.config.js +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/tailwind.config.js +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/tsconfig.app.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/tsconfig.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/tsconfig.node.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox/vite.config.ts +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/sandbox_bootstrap.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/setup.cfg +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/builtin.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/LICENSE-obsidian-skills +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/README.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/defuddle/SKILL.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/json-canvas/SKILL.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/json-canvas/references/EXAMPLES.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-bases/SKILL.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-bases/references/FUNCTIONS_REFERENCE.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-cli/SKILL.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-markdown/SKILL.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-markdown/references/CALLOUTS.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-markdown/references/EMBEDS.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/obsidian-markdown/references/PROPERTIES.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/README.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/SKILL.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/addresses.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/advancedbackgroundchecks.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/beenverified.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/clustal.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/clustrmaps.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/cyberbackgroundchecks.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/familytreenow.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/fastpeoplesearch.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/intelius.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/mylife.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/nuwber.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/peekyou.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/peoplefinders.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/radaris.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/rehold.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/searchpeoplefree.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/socialcatfish.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/spokeo.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/thatsthem.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/truepeoplesearch.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/usphonebook.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/brokers/whitepages.json +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/legal/ccpa.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/legal/drop.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/legal/gdpr.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/methods.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/site-playbooks.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/references/state-machine.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/autopilot.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/badbool.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/brokers.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/cdp.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/config.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/crypto.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/dossier.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/email_modes.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/emailer.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/ledger.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/legal.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/paths.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/pdd.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/registry.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/report.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/scan.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/storage.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/tiers.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/scripts/vectors.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/templates/consent/authorization.md +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/ccpa-authorized-agent.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/ccpa-deletion.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/ccpa-indirect-deletion.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/gdpr-erasure.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/bundled/unbroker/templates/emails/generic-optout.txt +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/clawhub.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/executor.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/loader.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skill/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/skills.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/soul.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/spinner.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/string_utils.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/subagent.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/task/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/task/store.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/task/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/task/types.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_afk_yolo.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_approval_runtime.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_background_task_tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_background_tasks.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_checkpoint.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_clipboard_utils.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_compaction.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_diff_view.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_diff_visualization.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_display_blocks.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_export_import.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_hook_engine.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_injection_fix.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_license.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_mcp.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_memory.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_notification_manager.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_plugin.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_session_fork.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_shell_mode.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_skills.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_steer_input.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_subagent.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_task.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_telegram_buffer.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_think_tool.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_todo_tool.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_todo_visualization.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_tool_registry.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_tree_ls.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_voice.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tests/test_wire_events.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tmux_offloader.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tmux_tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tool_registry.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/ui/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/ui/input.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/ui/render.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/updater.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/audio_utils.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/keyterms.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/recorder.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/stt.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/tts.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/voice/wake_word.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/webbridge/__init__.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/webbridge/core.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/webbridge/tools.py +0 -0
- {dulus-3.9.2 → dulus-3.9.3}/webchat.py +0 -0
- {dulus-3.9.2 → 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
|
|
@@ -2447,6 +2447,25 @@ def cmd_lang(args: str, state, config) -> bool:
|
|
|
2447
2447
|
except Exception:
|
|
2448
2448
|
pass
|
|
2449
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
|
|
2450
2469
|
ok(f"Reply language → {resolved}")
|
|
2451
2470
|
if resolved == arg and arg.lower() not in _LANG_NAMES:
|
|
2452
2471
|
info("(Free-form descriptor — passed verbatim to the model)")
|
|
@@ -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
|
|
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
|