dulus 3.14.1__tar.gz → 3.14.2__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.14.1/dulus.egg-info → dulus-3.14.2}/PKG-INFO +7 -1
- {dulus-3.14.1 → dulus-3.14.2}/docs/news.md +1 -1
- {dulus-3.14.1 → dulus-3.14.2/dulus.egg-info}/PKG-INFO +7 -1
- {dulus-3.14.1 → dulus-3.14.2}/dulus.egg-info/requires.txt +6 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus.py +1 -1
- {dulus-3.14.1 → dulus-3.14.2}/providers.py +249 -0
- {dulus-3.14.1 → dulus-3.14.2}/pyproject.toml +21 -1
- {dulus-3.14.1 → dulus-3.14.2}/LICENSE +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/MANIFEST.in +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/README.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/agent.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/algolia_search.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/analytics.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/agents_bridge.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/compressor.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/context.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/githook.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/marketplace.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/mempalace_bridge.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/paths.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/personas.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/plugins.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/server.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/backend/tasks.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/banners/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/banners/banner_rotator.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/banners/banners_dulus_ai.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/batch_api.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/checkpoint/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/checkpoint/hooks.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/checkpoint/store.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/checkpoint/types.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/__main__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/ansi.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/assets/ascii/dulus_logo.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/assets/ascii/eagle.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/assets/ascii/terminal_art.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/banners.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/demo.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/effects.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/effort_slider.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/progress.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/py.typed +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/spinners.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cli_animations/status.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/clipboard_utils.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/cloudsave.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/common.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/compaction.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/config.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/context.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/active_persona.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/marketplace.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/personas.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/composio/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/composio/composio_plugin/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/composio/plugin.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/plugins/composio/plugin_tool.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/data/tasks.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/display_blocks.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/API.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/BRAND_GUIDE.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/CHANGELOG.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/CONTRIBUTING.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/DEPLOYMENT.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/FAQ.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/GETTING_STARTED.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_AR.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_EN.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_ES.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_FR.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_JA.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_KO.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_PT.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_RU.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/README_ZH.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/SECURITY.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/api.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/architecture.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/azure-speech-template.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/dashboard/index.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/divider.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/dulus-bird.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/generate.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/index.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/nvidia-models.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/particle-playground.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/personas/index.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/poetry-banner.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/preview.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/python-console.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/auto-adapter.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/dulus-os.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/hero.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/lookback_two_windows.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/pyc_heap.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/pyc_receipts.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/pyc_trap.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/roundtable.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/task-board.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/readme/webchat.png +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-agents.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-brainstorm.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-bridges.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-features.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-freetier.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-memory.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-models.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-perms.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-plugins.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-quickstart.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/sec-ssj.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/spinners.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/split-pane.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/terminal-boot.svg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/docs/termux-edge.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus.egg-info/top_level.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_account.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_bar_client.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_gui.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/client.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/commands.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/config.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/hub.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_mcp/types.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_quick_menu.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/add_dir_manager.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/afk_mode.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/approval_runtime.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/background_tasks.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/clipboard_utils.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/diff_visualizer.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/export_import.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/hook_engine.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/isolate.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/notification_manager.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/session_fork.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/shell_mode.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/todo_visualizer.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/tree_ls.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/wire_events.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/dulus_tools/yolo_mode.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/file_filter.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/fs_compass.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/governance.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/agent_bridge.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/chat_widget.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/main_window.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/personas.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/sandbox_server.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/session_utils.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/settings_dialog.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/sidebar.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/tasks_view.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/themes.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/gui/tool_panel.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/input.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/license_manager.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/lookback.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/audit.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/consolidator.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/context.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/mempalace_bridge.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/offload.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/palace.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/scan.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/adaptation_guides.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/askuserquestion_after_numbered_list.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/background_jobs_no_extra_timers.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/cleverness_over_resources.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/corporate_tls_breaks_curl_cffi.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/hardened_rules.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/investigator_workflow_heuristic.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/native_code_over_sketchy_plugins.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/no_personal_info_in_code.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/searches_include_modified_date.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/tmux_send_keys_power_patterns.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/token_optimization_technique.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/tool_chaining_capability.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/insights/webbridge_evaluate_first_pattern.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/seeds/short_memory.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/sessions.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/store.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/types.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/memory/vector_search.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/model_params.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/multi_agent/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/multi_agent/subagent.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/multi_agent/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/paste_placeholders.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/personality_config.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/plugin/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/plugin/autoadapter.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/plugin/loader.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/plugin/recommend.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/plugin/store.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/plugin/types.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/profiles.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/pyconsole.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/README.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/assets/index-DE51D6wI.css +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/assets/index-DMCCNE9Y.js +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/index.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/wallpaper-default.jpg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/wallpapers/default.jpeg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/wallpapers/light.jpeg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/wallpapers/nature.jpeg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/dist/wallpapers/tech.jpeg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox/info.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/sandbox_bootstrap.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/setup.cfg +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/builtin.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/LICENSE-obsidian-skills +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/README.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/defuddle/SKILL.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/json-canvas/SKILL.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/json-canvas/references/EXAMPLES.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-bases/SKILL.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-bases/references/FUNCTIONS_REFERENCE.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-cli/SKILL.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-markdown/SKILL.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-markdown/references/CALLOUTS.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-markdown/references/EMBEDS.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/obsidian-markdown/references/PROPERTIES.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/README.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/SKILL.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/addresses.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/advancedbackgroundchecks.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/beenverified.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/clustal.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/clustrmaps.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/cyberbackgroundchecks.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/familytreenow.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/fastpeoplesearch.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/intelius.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/mylife.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/nuwber.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/peekyou.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/peoplefinders.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/radaris.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/rehold.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/searchpeoplefree.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/socialcatfish.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/spokeo.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/thatsthem.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/truepeoplesearch.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/usphonebook.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/brokers/whitepages.json +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/legal/ccpa.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/legal/drop.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/legal/gdpr.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/methods.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/site-playbooks.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/references/state-machine.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/autopilot.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/badbool.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/brokers.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/cdp.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/config.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/crypto.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/dossier.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/email_modes.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/emailer.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/ledger.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/legal.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/paths.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/pdd.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/registry.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/report.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/scan.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/storage.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/tiers.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/scripts/vectors.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/templates/consent/authorization.md +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/templates/emails/ccpa-authorized-agent.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/templates/emails/ccpa-deletion.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/templates/emails/ccpa-indirect-deletion.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/templates/emails/gdpr-erasure.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/bundled/unbroker/templates/emails/generic-optout.txt +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/clawhub.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/executor.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/loader.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skill/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/skills.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/soul.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/spinner.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/steer_input.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/subagent.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/task/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/task/store.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/task/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/task/types.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_afk_yolo.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_approval_runtime.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_background_task_tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_background_tasks.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_chatgpt_oauth.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_checkpoint.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_cli_animations_integration.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_clipboard_utils.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_compaction.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_composio_tool_generator.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_diff_view.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_diff_visualization.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_display_blocks.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_dulus_account.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_export_import.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_gold_memory_preload.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_grok_usage.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_hook_engine.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_injection_fix.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_json_protocol.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_license.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_lookback_cache.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_lookback_compact.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_mcp.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_mcp_algolia.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_memory.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_memory_home_resolution.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_notification_manager.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_plugin.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_profile_isolation.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_profile_plugin_scope.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_provider_errors.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_session_fork.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_shell_detection.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_shell_mode.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_skills.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_skillssh_algolia.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_steer_input.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_subagent.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_task.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_telegram_buffer.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_think_tool.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_todo_tool.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_todo_visualization.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_tool_registry.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_tree_ls.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_voice.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_webbridge_tabs.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tests/test_wire_events.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tmux_tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/token_budget.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tool_registry.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tools_background.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tools_think.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/tools_todo.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/ui/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/ui/input.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/ui/render.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/updater.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/audio_utils.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/keyterms.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/recorder.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/stt.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/tts.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/voice/wake_word.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webbridge/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webbridge/core.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webbridge/tools.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webchat.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webchat_server.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webchat_ui/__init__.py +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webchat_ui/app.js +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webchat_ui/index.html +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/webchat_ui/style.css +0 -0
- {dulus-3.14.1 → dulus-3.14.2}/welcome.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 3.14.
|
|
3
|
+
Version: 3.14.2
|
|
4
4
|
Summary: Provider-independent agent runtime for the terminal — cloud and local models, real tools, MCP, plugins, memory, sub-agents, and Dulus OS.
|
|
5
5
|
Author-email: KevRojo <dev@dulus.ai>
|
|
6
6
|
Maintainer-email: KevRojo <dev@dulus.ai>
|
|
@@ -65,6 +65,12 @@ Requires-Dist: mcp>=1.0.0
|
|
|
65
65
|
Requires-Dist: uv>=0.4.0
|
|
66
66
|
Requires-Dist: sse-starlette>=2.0.0
|
|
67
67
|
Requires-Dist: starlette>=0.38.0
|
|
68
|
+
Requires-Dist: posthog>=3.0.0
|
|
69
|
+
Requires-Dist: mempalace>=3.3.4
|
|
70
|
+
Requires-Dist: sounddevice
|
|
71
|
+
Requires-Dist: elevenlabs>=1.0.0
|
|
72
|
+
Requires-Dist: playwright>=1.40.0
|
|
73
|
+
Requires-Dist: litellm>=1.50.0
|
|
68
74
|
Provides-Extra: dev
|
|
69
75
|
Requires-Dist: build>=1.2; extra == "dev"
|
|
70
76
|
Requires-Dist: pyright>=1.1.400; extra == "dev"
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- September 2, 2026 (**v3.14.1**): **🌐 Web-harvest browser fix.** `/harvest-gemini` (and claude/kimi/qwen/deepseek) no longer launch without a browser after the first run. The installer used to key off the *pip package*, so once the wizard installed it, later harvests skipped the *browser* download entirely — leaving you with a package but no Chromium. Now a single idempotent guard ensures both the package and the browser are present every time. `pip install -U dulus`. 🦅
|
|
6
6
|
|
|
7
|
-
- September
|
|
7
|
+
- September 3, 2026 (**v3.14.2**): **📦 One-shot install — everything's in the box now.** No more `dulus[full]` archaeology: `pip install dulus` now pulls the whole runtime by default — memory palace, voice, browser automation, LiteLLM routing and analytics all come along. Plus a new **Meta AI (Muse Spark)** provider (`meta/muse-spark-1.3`). Same free open runtime, your machine. `pip install -U dulus`. 🦅🇩🇴
|
|
8
8
|
|
|
9
9
|
- September 1, 2026 (**v3.13.9**): **🔒 `/isolate` — workspace bubble, on demand.** Flip `/isolate on` and Write / Edit / NotebookEdit + Bash mutations stay locked to the frozen workspace root (plus anything you added with `/add-dir`). Read-only tools keep flying free. No `/temp` backdoor — pure bubble. Blocked? Dulus tells you straight: write `/isolate off` if you want help outside. `pip install -U dulus`. 🦅
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 3.14.
|
|
3
|
+
Version: 3.14.2
|
|
4
4
|
Summary: Provider-independent agent runtime for the terminal — cloud and local models, real tools, MCP, plugins, memory, sub-agents, and Dulus OS.
|
|
5
5
|
Author-email: KevRojo <dev@dulus.ai>
|
|
6
6
|
Maintainer-email: KevRojo <dev@dulus.ai>
|
|
@@ -65,6 +65,12 @@ Requires-Dist: mcp>=1.0.0
|
|
|
65
65
|
Requires-Dist: uv>=0.4.0
|
|
66
66
|
Requires-Dist: sse-starlette>=2.0.0
|
|
67
67
|
Requires-Dist: starlette>=0.38.0
|
|
68
|
+
Requires-Dist: posthog>=3.0.0
|
|
69
|
+
Requires-Dist: mempalace>=3.3.4
|
|
70
|
+
Requires-Dist: sounddevice
|
|
71
|
+
Requires-Dist: elevenlabs>=1.0.0
|
|
72
|
+
Requires-Dist: playwright>=1.40.0
|
|
73
|
+
Requires-Dist: litellm>=1.50.0
|
|
68
74
|
Provides-Extra: dev
|
|
69
75
|
Requires-Dist: build>=1.2; extra == "dev"
|
|
70
76
|
Requires-Dist: pyright>=1.1.400; extra == "dev"
|
|
@@ -396,7 +396,7 @@ try:
|
|
|
396
396
|
from importlib.metadata import version as _pkg_version
|
|
397
397
|
VERSION = _pkg_version("dulus")
|
|
398
398
|
except Exception:
|
|
399
|
-
VERSION = "3.14.
|
|
399
|
+
VERSION = "3.14.2" # dev fallback — keep in sync with pyproject.toml
|
|
400
400
|
|
|
401
401
|
# ── Machine-readable protocol output (`--output json`) ─────────────────────
|
|
402
402
|
# Dulus is increasingly run as a child process by another agent runtime (an
|
|
@@ -875,6 +875,19 @@ PROVIDERS: dict[str, dict] = {
|
|
|
875
875
|
"fugu-mini", "fugu-ultra",
|
|
876
876
|
],
|
|
877
877
|
},
|
|
878
|
+
# Meta AI (Muse Spark) — Responses-API-style SSE endpoint at api.meta.ai.
|
|
879
|
+
# Key via /config meta_api_key=... or export META_API_KEY.
|
|
880
|
+
# Pick models as 'meta/muse-spark-1.3' (or bare 'muse-spark-1.3').
|
|
881
|
+
"meta": {
|
|
882
|
+
"type": "meta",
|
|
883
|
+
"api_key_env": "META_API_KEY",
|
|
884
|
+
"base_url": "https://api.meta.ai/v1",
|
|
885
|
+
"context_limit": 128000,
|
|
886
|
+
"max_completion_tokens": 32000,
|
|
887
|
+
"models": [
|
|
888
|
+
"muse-spark-1.3", "muse-spark-1.3-contributor",
|
|
889
|
+
],
|
|
890
|
+
},
|
|
878
891
|
}
|
|
879
892
|
|
|
880
893
|
# Cost per million tokens (approximate, fallback to 0 for unknown)
|
|
@@ -934,6 +947,9 @@ _PREFIXES = [
|
|
|
934
947
|
("gpt-5-codex", "chatgpt-oauth"),
|
|
935
948
|
("codex-mini", "chatgpt-oauth"),
|
|
936
949
|
("codex-auto", "chatgpt-oauth"),
|
|
950
|
+
# Meta AI (Muse Spark) — api.meta.ai Responses-style SSE, key via META_API_KEY.
|
|
951
|
+
("meta/", "meta"),
|
|
952
|
+
("muse-", "meta"),
|
|
937
953
|
("claude-", "anthropic"),
|
|
938
954
|
("gpt-", "openai"),
|
|
939
955
|
("o1", "openai"),
|
|
@@ -2842,6 +2858,236 @@ def stream_chatgpt_oauth(
|
|
|
2842
2858
|
cache_read_tokens=cached_tok)
|
|
2843
2859
|
|
|
2844
2860
|
|
|
2861
|
+
# ── Meta AI (Muse Spark) — API key, Responses-API-style SSE ────────────────
|
|
2862
|
+
META_API_BASE_URL = "https://api.meta.ai/v1"
|
|
2863
|
+
|
|
2864
|
+
|
|
2865
|
+
def stream_meta(
|
|
2866
|
+
api_key: str,
|
|
2867
|
+
model: str,
|
|
2868
|
+
system: str,
|
|
2869
|
+
messages: list,
|
|
2870
|
+
tool_schemas: list,
|
|
2871
|
+
config: dict,
|
|
2872
|
+
) -> Generator:
|
|
2873
|
+
"""Meta AI Muse Spark via api.meta.ai/v1/responses (SSE, OpenAI Responses
|
|
2874
|
+
wire format). Key: /config meta_api_key=... or META_API_KEY.
|
|
2875
|
+
Yields TextChunk / ThinkingChunk / AssistantTurn."""
|
|
2876
|
+
import requests as _req
|
|
2877
|
+
|
|
2878
|
+
if not api_key:
|
|
2879
|
+
yield TextChunk(
|
|
2880
|
+
"[meta] No API key. Set one with `/config meta_api_key=...` "
|
|
2881
|
+
"or export META_API_KEY."
|
|
2882
|
+
)
|
|
2883
|
+
yield AssistantTurn(
|
|
2884
|
+
"[meta] No API key. Set META_API_KEY or /config meta_api_key=...",
|
|
2885
|
+
[], 0, 0, error=True,
|
|
2886
|
+
)
|
|
2887
|
+
return
|
|
2888
|
+
|
|
2889
|
+
instructions, input_items = _chatgpt_messages_to_responses_input(system, messages)
|
|
2890
|
+
|
|
2891
|
+
body: dict[str, Any] = {
|
|
2892
|
+
"model": model,
|
|
2893
|
+
"input": input_items,
|
|
2894
|
+
"stream": True,
|
|
2895
|
+
"temperature": 1,
|
|
2896
|
+
"max_output_tokens": 32000,
|
|
2897
|
+
"top_p": 1,
|
|
2898
|
+
}
|
|
2899
|
+
if instructions:
|
|
2900
|
+
body["instructions"] = instructions
|
|
2901
|
+
|
|
2902
|
+
tools = _chatgpt_tools_to_responses(tool_schemas)
|
|
2903
|
+
if tools:
|
|
2904
|
+
body["tools"] = tools
|
|
2905
|
+
if not (config or {}).get("disable_tool_choice"):
|
|
2906
|
+
body["tool_choice"] = "auto"
|
|
2907
|
+
|
|
2908
|
+
base = (PROVIDERS.get("meta", {}).get("base_url") or META_API_BASE_URL).rstrip("/")
|
|
2909
|
+
url = base + "/responses"
|
|
2910
|
+
headers = {
|
|
2911
|
+
"Authorization": f"Bearer {api_key}",
|
|
2912
|
+
"Content-Type": "application/json",
|
|
2913
|
+
"Accept": "text/event-stream",
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
text = ""
|
|
2917
|
+
thinking = ""
|
|
2918
|
+
in_tok = 0
|
|
2919
|
+
out_tok = 0
|
|
2920
|
+
cached_tok = 0
|
|
2921
|
+
tool_buf: dict[str, dict] = {}
|
|
2922
|
+
tool_order: list[str] = []
|
|
2923
|
+
current_call_id: str | None = None
|
|
2924
|
+
stream_interrupted = False
|
|
2925
|
+
resp = None
|
|
2926
|
+
|
|
2927
|
+
def _ensure_tool(call_id: str | None, name: str | None = None) -> str:
|
|
2928
|
+
nonlocal current_call_id
|
|
2929
|
+
cid = call_id or current_call_id or f"call_{len(tool_order)}"
|
|
2930
|
+
if cid not in tool_buf:
|
|
2931
|
+
tool_buf[cid] = {"id": cid, "name": name or "", "args": ""}
|
|
2932
|
+
tool_order.append(cid)
|
|
2933
|
+
elif name and not tool_buf[cid].get("name"):
|
|
2934
|
+
tool_buf[cid]["name"] = name
|
|
2935
|
+
current_call_id = cid
|
|
2936
|
+
return cid
|
|
2937
|
+
|
|
2938
|
+
try:
|
|
2939
|
+
resp = _req.post(url, headers=headers, json=body, stream=True, timeout=300)
|
|
2940
|
+
|
|
2941
|
+
if resp.status_code in (401, 403):
|
|
2942
|
+
body_preview = (resp.text or "")[:300]
|
|
2943
|
+
yield TextChunk(
|
|
2944
|
+
f"[meta] Auth error {resp.status_code}. Check your key: "
|
|
2945
|
+
f"/config meta_api_key=... Detail: {body_preview}"
|
|
2946
|
+
)
|
|
2947
|
+
yield AssistantTurn(
|
|
2948
|
+
f"[meta] Auth error {resp.status_code}. Check meta_api_key.",
|
|
2949
|
+
[], 0, 0, error=True,
|
|
2950
|
+
)
|
|
2951
|
+
return
|
|
2952
|
+
if resp.status_code >= 400:
|
|
2953
|
+
body_preview = (resp.text or "")[:400]
|
|
2954
|
+
yield TextChunk(f"[meta] HTTP {resp.status_code}: {body_preview}")
|
|
2955
|
+
yield AssistantTurn(
|
|
2956
|
+
f"[meta] HTTP {resp.status_code}: {body_preview}",
|
|
2957
|
+
[], 0, 0, error=True,
|
|
2958
|
+
)
|
|
2959
|
+
return
|
|
2960
|
+
|
|
2961
|
+
event_type = ""
|
|
2962
|
+
# NOTE: iterate RAW BYTES (no decode_unicode). requests defaults to
|
|
2963
|
+
# ISO-8859-1 for text/event-stream when the server omits charset, which
|
|
2964
|
+
# mangled UTF-8 accents (á→á, ñ→ñ) in Spanish output. Decoding each
|
|
2965
|
+
# line explicitly as UTF-8 fixes the mojibake.
|
|
2966
|
+
for raw_line in resp.iter_lines():
|
|
2967
|
+
if raw_line is None:
|
|
2968
|
+
continue
|
|
2969
|
+
line = raw_line.decode("utf-8", "replace").strip() if isinstance(raw_line, (bytes, bytearray)) else raw_line.strip()
|
|
2970
|
+
if not line:
|
|
2971
|
+
continue
|
|
2972
|
+
if line.startswith(":"):
|
|
2973
|
+
continue
|
|
2974
|
+
if line.startswith("event:"):
|
|
2975
|
+
event_type = line[6:].strip()
|
|
2976
|
+
continue
|
|
2977
|
+
if not line.startswith("data:"):
|
|
2978
|
+
continue
|
|
2979
|
+
data = line[5:].strip()
|
|
2980
|
+
if data == "[DONE]":
|
|
2981
|
+
break
|
|
2982
|
+
try:
|
|
2983
|
+
event = json.loads(data)
|
|
2984
|
+
except Exception:
|
|
2985
|
+
continue
|
|
2986
|
+
if not isinstance(event, dict):
|
|
2987
|
+
continue
|
|
2988
|
+
et = event.get("type") or event_type or ""
|
|
2989
|
+
|
|
2990
|
+
if et in ("response.output_text.delta", "response.refusal.delta"):
|
|
2991
|
+
delta = event.get("delta") or ""
|
|
2992
|
+
if delta:
|
|
2993
|
+
text += delta
|
|
2994
|
+
yield TextChunk(delta)
|
|
2995
|
+
continue
|
|
2996
|
+
|
|
2997
|
+
if et in (
|
|
2998
|
+
"response.reasoning_summary_text.delta",
|
|
2999
|
+
"response.reasoning_text.delta",
|
|
3000
|
+
):
|
|
3001
|
+
delta = event.get("delta") or ""
|
|
3002
|
+
if delta:
|
|
3003
|
+
thinking += delta
|
|
3004
|
+
yield ThinkingChunk(delta)
|
|
3005
|
+
continue
|
|
3006
|
+
|
|
3007
|
+
if et == "response.output_item.added":
|
|
3008
|
+
item = event.get("item") or {}
|
|
3009
|
+
if isinstance(item, dict) and item.get("type") == "function_call":
|
|
3010
|
+
_ensure_tool(item.get("call_id") or item.get("id"), item.get("name"))
|
|
3011
|
+
continue
|
|
3012
|
+
|
|
3013
|
+
if et == "response.function_call_arguments.delta":
|
|
3014
|
+
cid = event.get("call_id") or current_call_id
|
|
3015
|
+
key = _ensure_tool(cid)
|
|
3016
|
+
delta_args = event.get("delta") or ""
|
|
3017
|
+
if delta_args:
|
|
3018
|
+
tool_buf[key]["args"] += delta_args
|
|
3019
|
+
continue
|
|
3020
|
+
|
|
3021
|
+
if et == "response.function_call_arguments.done":
|
|
3022
|
+
cid = event.get("call_id") or current_call_id
|
|
3023
|
+
key = _ensure_tool(cid)
|
|
3024
|
+
final_args = event.get("arguments")
|
|
3025
|
+
if final_args is not None:
|
|
3026
|
+
tool_buf[key]["args"] = final_args
|
|
3027
|
+
continue
|
|
3028
|
+
|
|
3029
|
+
if et == "response.output_item.done":
|
|
3030
|
+
item = event.get("item") or {}
|
|
3031
|
+
if isinstance(item, dict) and item.get("type") == "function_call":
|
|
3032
|
+
key = _ensure_tool(item.get("call_id") or item.get("id"), item.get("name"))
|
|
3033
|
+
if item.get("name"):
|
|
3034
|
+
tool_buf[key]["name"] = item["name"]
|
|
3035
|
+
if item.get("arguments") is not None:
|
|
3036
|
+
tool_buf[key]["args"] = item["arguments"]
|
|
3037
|
+
if item.get("call_id"):
|
|
3038
|
+
tool_buf[key]["id"] = item["call_id"]
|
|
3039
|
+
continue
|
|
3040
|
+
|
|
3041
|
+
if et in ("response.completed", "response.incomplete"):
|
|
3042
|
+
resp_obj = event.get("response") or {}
|
|
3043
|
+
usage = resp_obj.get("usage") or event.get("usage") or {}
|
|
3044
|
+
if isinstance(usage, dict):
|
|
3045
|
+
in_tok = int(usage.get("input_tokens") or usage.get("prompt_tokens") or in_tok or 0)
|
|
3046
|
+
out_tok = int(usage.get("output_tokens") or usage.get("completion_tokens") or out_tok or 0)
|
|
3047
|
+
_det = usage.get("input_tokens_details") or usage.get("prompt_tokens_details") or {}
|
|
3048
|
+
if isinstance(_det, dict):
|
|
3049
|
+
cached_tok = int(_det.get("cached_tokens") or cached_tok or 0)
|
|
3050
|
+
continue
|
|
3051
|
+
|
|
3052
|
+
if et in ("response.failed", "error"):
|
|
3053
|
+
err = event.get("error") or event.get("response", {}).get("error") or event
|
|
3054
|
+
if isinstance(err, dict):
|
|
3055
|
+
msg = err.get("message") or err.get("code") or json.dumps(err)[:300]
|
|
3056
|
+
else:
|
|
3057
|
+
msg = str(err)[:300]
|
|
3058
|
+
note = f"\n\n_[meta error: {msg}]_"
|
|
3059
|
+
text += note
|
|
3060
|
+
yield TextChunk(note)
|
|
3061
|
+
continue
|
|
3062
|
+
|
|
3063
|
+
except _req.exceptions.ChunkedEncodingError:
|
|
3064
|
+
stream_interrupted = True
|
|
3065
|
+
except _req.exceptions.ConnectionError:
|
|
3066
|
+
stream_interrupted = True
|
|
3067
|
+
except Exception as e:
|
|
3068
|
+
msg = f"[meta] Error: {e}"
|
|
3069
|
+
yield TextChunk(msg)
|
|
3070
|
+
yield AssistantTurn(msg, [], 0, 0, error=True)
|
|
3071
|
+
return
|
|
3072
|
+
finally:
|
|
3073
|
+
if resp is not None:
|
|
3074
|
+
try:
|
|
3075
|
+
resp.close()
|
|
3076
|
+
except Exception:
|
|
3077
|
+
pass
|
|
3078
|
+
|
|
3079
|
+
if stream_interrupted and not tool_buf:
|
|
3080
|
+
note = "\n\n_[meta: el streaming se cortó a media respuesta — esto es parcial, reintenta]_"
|
|
3081
|
+
text += note
|
|
3082
|
+
yield TextChunk(note)
|
|
3083
|
+
|
|
3084
|
+
ordered_buf = {i: tool_buf[k] for i, k in enumerate(tool_order)} if tool_order else tool_buf
|
|
3085
|
+
final_tool_calls = _finalize_tool_calls(ordered_buf)
|
|
3086
|
+
|
|
3087
|
+
yield AssistantTurn(text, final_tool_calls, in_tok, out_tok, thinking=thinking,
|
|
3088
|
+
cache_read_tokens=cached_tok)
|
|
3089
|
+
|
|
3090
|
+
|
|
2845
3091
|
def stream_xai_oauth(
|
|
2846
3092
|
model: str,
|
|
2847
3093
|
system: str,
|
|
@@ -7512,6 +7758,9 @@ def stream(
|
|
|
7512
7758
|
# ChatGPT/Codex subscription OAuth (`/login chatgpt` or ~/.codex/auth.json)
|
|
7513
7759
|
# → chatgpt.com/backend-api/codex/responses (Responses API, not chat/completions)
|
|
7514
7760
|
yield from stream_chatgpt_oauth(model_name, system, messages, tool_schemas, config)
|
|
7761
|
+
elif prov["type"] == "meta":
|
|
7762
|
+
# Meta AI (Muse Spark) via api.meta.ai/v1/responses — API key (META_API_KEY).
|
|
7763
|
+
yield from stream_meta(api_key, model_name, system, messages, tool_schemas, config)
|
|
7515
7764
|
elif prov["type"] == "gcloud":
|
|
7516
7765
|
yield from stream_gcloud(model_name, system, messages, tool_schemas, config)
|
|
7517
7766
|
elif prov["type"] == "litellm":
|
|
@@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta"
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "dulus"
|
|
13
|
-
version = "3.14.
|
|
13
|
+
version = "3.14.2"
|
|
14
14
|
description = "Provider-independent agent runtime for the terminal — cloud and local models, real tools, MCP, plugins, memory, sub-agents, and Dulus OS."
|
|
15
15
|
readme = "README.md"
|
|
16
16
|
requires-python = ">=3.10"
|
|
@@ -112,6 +112,26 @@ dependencies = [
|
|
|
112
112
|
"uv>=0.4.0",
|
|
113
113
|
"sse-starlette>=2.0.0",
|
|
114
114
|
"starlette>=0.38.0",
|
|
115
|
+
# Product analytics — usage/telemetry (respects opt-out). Nobody runs
|
|
116
|
+
# `pip install dulus[full]`, so shipping it here is the only way metrics
|
|
117
|
+
# actually reach us from real installs.
|
|
118
|
+
"posthog>=3.0.0",
|
|
119
|
+
# Memory Palace — per-turn semantic memory injection. Pulls chromadb; on
|
|
120
|
+
# exotic targets (termux/aarch64) wheels may be missing, but the vast
|
|
121
|
+
# majority of installs want this ON by default rather than hunting the
|
|
122
|
+
# `[memory]` extra nobody types.
|
|
123
|
+
"mempalace>=3.3.4",
|
|
124
|
+
# Voice I/O — mic capture + cloud TTS. On by default so `/voice` works out
|
|
125
|
+
# of the box; silent no-op on headless boxes with no audio device.
|
|
126
|
+
"sounddevice",
|
|
127
|
+
"elevenlabs>=1.0.0",
|
|
128
|
+
# Browser automation — /harvest-*, WebBridge, JS-rendered scraping. The pip
|
|
129
|
+
# package ships here; the Chromium binary is fetched on first harvest.
|
|
130
|
+
"playwright>=1.40.0",
|
|
131
|
+
# LiteLLM unified gateway — one provider entry, 100+ backends. Bundled by
|
|
132
|
+
# default so the welcome wizard's litellm option works without a second
|
|
133
|
+
# install step.
|
|
134
|
+
"litellm>=1.50.0",
|
|
115
135
|
]
|
|
116
136
|
|
|
117
137
|
# mempalace pulls chromadb (26 transitive deps incl. numpy + onnxruntime),
|
|
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
|