mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-10-20 11:15:50 +00:00
User-first discovery let last-value-wins merges overwrite community provider and profile definitions with bundled values. Apply bundled root groups first in provider loading, profile loading and catalogs, and Agent Editor metadata. Share the existing root-priority key and use stable sorting at merge sites, preserving same-root order and cached lookup lists. Add collision, fallback, scoped-override and prompt/schema/dispatch regressions, and update DOX. Validation: 206 focused tests and 17 checks against the bind-mounted Docker framework runtime passed. git diff --check and helper DOX coverage passed.
7.2 KiB
7.2 KiB
plugins.py DOX
Purpose
- Own the
plugins.pyhelper module. - This module discovers plugins, resolves plugin config/toggles, runs hooks, and tracks plugin updates.
- Keep this file-level DOX profile synchronized with
plugins.pybecause this directory is intentionally flat.
Ownership
plugins.pyowns the runtime implementation.plugins.py.dox.mdowns durable notes about responsibilities, contracts, side effects, and verification for that implementation.- Classes:
PluginAssetFile(TypedDict)PluginMetadata(BaseModel)PluginListItem(BaseModel)PluginUpdateInfo(BaseModel)- Top-level functions:
register_watchdogs()after_plugin_change(plugin_names: list[str] | None=..., python_change: bool=..., frontend_reload: bool=...)refresh_plugin_modules(plugin_names: list[str] | None=...)clear_plugin_cache(plugin_names: list[str] | None=...)get_plugin_roots(plugin_name: str=...) -> List[str]: Plugin root directories, ordered by priority (user first).get_plugin_name_from_path(path: str | Path) -> str: Return the plugin directory name only for paths below a canonical user or bundled plugin root.get_plugin_root_priority(path: str | Path | None) -> int: Return the containing root's index; unrecognized paths rank after declared roots.get_plugins_list()get_enhanced_plugins_list(custom: bool=..., builtin: bool=..., plugin_names: list[str] | None=...) -> List[PluginListItem]: Discover plugins by directory convention. First root wins on ID conflict.get_custom_plugins_updates(plugin_names: list[str] | None=...) -> List[PluginUpdateInfo]get_plugin_meta(plugin_name: str)find_plugin_dir(plugin_name: str)uninstall_plugin(plugin_name)delete_plugin(plugin_name: str)get_plugin_paths(*subpaths) -> List[str]get_enabled_plugin_paths(agent: Agent | None, *subpaths) -> List[str]get_enabled_plugins(agent: Agent | None)determined_toggle_from_paths(default: bool, paths: Iterator[str])get_toggle_state(plugin_name: str) -> ToggleStatetoggle_plugin(plugin_name: str, enabled: bool, project_name: str=..., agent_profile: str=..., clear_overrides: bool=...)get_plugin_config(plugin_name: str, agent: Agent | None=..., project_name: str | None=..., agent_profile: str | None=..., caller: CallerContext=...)get_default_plugin_config(plugin_name: str)save_plugin_config(plugin_name: str, project_name: str, agent_profile: str, settings: dict, caller: CallerContext=...)find_plugin_asset(plugin_name: str, *subpaths, project_name=..., agent_profile=...)find_plugin_assets(*subpaths, plugin_name: str=..., project_name: str=..., agent_profile: str=..., only_first: bool=...) -> list[PluginAssetFile]determine_plugin_asset_path(plugin_name: str, project_name: str, agent_profile: str, *subpaths)send_frontend_reload_notification(plugin_names: list[str] | None=...): If the plugin changed has webui extensions, show a persistent reload notification that marks itself read before refreshingcall_plugin_hook(plugin_name: str, hook_name: str, default: Any=..., *args, **kwargs)_apply_defaults_from_env(plugin_name: str, config: dict[str, Any])- Notable constants/configuration names:
_META_TARGET_RE,META_FILE_NAME,CONFIG_FILE_NAME,CONFIG_DEFAULT_FILE_NAME,DISABLED_FILE_NAME,ENABLED_FILE_NAME,TOGGLE_FILE_PATTERN,HOOKS_SCRIPT,HOOKS_CACHE_AREA,PLUGINS_LIST_CACHE_AREA,ENABLED_PLUGINS_LIST_CACHE_AREA,ENABLED_PLUGINS_PATHS_CACHE_AREA.
Runtime Contracts
- Enabled asset paths follow
get_plugin_roots()priority: user plugins before bundled plugins, preserving discovery order within each root. First-match tools, prompts and same-filename extensions therefore honor user plugin overrides. This does not reorder the plugin list or change activation rules, project/profile precedence, or extension execution order after deduplication. - Last-value-wins provider and profile consumers stably sort a copy by
get_plugin_root_priorityin descending order. Bundled roots apply before user roots without reversing same-root discovery order or mutating cached asset paths; path discovery exposes only its normal user-first order. - Helper modules own reusable framework APIs and must preserve public callers unless all callers, tests, and docs are updated together.
- Plugins marked
always_enabledremain in runtime discovery regardless of stale global or scoped disable files, and disable attempts are rejected. - Config hooks receive
hook_context={"caller": caller}with one ofui,agent, orapi; this is behavioral context, not an authorization boundary. - Plugin list, enabled-plugin, and enabled-path lookups cache empty results like any other value;
clear_plugin_cacheand plugin watchdog events invalidate them. - Project- and agent-scoped plugin changes invalidate runtime caches without a frontend reload prompt because the loaded WebUI extension bundle is global.
- Update this file whenever public functions, classes, persistence behavior, path/security assumptions, side effects, or cross-module contracts change.
- Observed side-effect areas: filesystem reads, filesystem writes, filesystem deletion, WebSocket state, plugin state, settings/state persistence, secret handling.
- Imported dependency areas include:
__future__,asyncio,glob,helpers,helpers.defer,helpers.watchdog,json,pathlib,pydantic,re,regex,time,typing.
Key Concepts
- Important called helpers/classes observed in the source:
re.compile,Field,watchdog.add_watchdog,clear_plugin_cache,send_frontend_reload_notification,DeferredTask.start_task,get_plugin_roots,get_plugin_name_from_path,result.sort,cache.add,get_enhanced_plugins_list,find_plugin_dir,files.get_abs_path,files.exists,call_plugin_hook,delete_plugin,files.delete_dir,after_plugin_change,get_enabled_plugins,get_plugins_list,get_plugin_meta. - Keep request/response, tool, or helper semantics documented here at the same time as source changes.
Work Guidance
- Preserve public helper APIs used by core code and plugins unless every caller is updated.
- Keep path, auth, secret, persistence, network, and subprocess behavior explicit and bounded.
- Prefer adding cohesive helper functions here only when behavior is reused across modules.
Verification
- Run targeted tests for changed helper behavior; run security regressions for auth, filesystem, WebSocket, tunnel, upload, or secret-handling helpers.
- Related tests observed by source search:
tests/test_plugin_asset_precedence.pycovers root priority, stable ordering, tool/prompt/extension selection, higher-priority scoped overrides, disabled plugin fallback, provider/profile/editor merges, missing paths and cached empty results.tests/test_a0_connector_computer_use_metadata.pytests/test_a0_connector_prompt_gating.pytests/test_browser_agent_regressions.pytests/test_chat_compaction.pytests/test_default_prompt_budget.pytests/test_document_query_plugin.pytests/test_error_retry_plugin.pytests/test_host_browser_connector.pytests/test_tool_policy.py
Child DOX Index
No child DOX files.