Skip to content

Comments

Local#90

Open
gasvn wants to merge 14 commits intomainfrom
local
Open

Local#90
gasvn wants to merge 14 commits intomainfrom
local

Conversation

@gasvn
Copy link
Member

@gasvn gasvn commented Feb 24, 2026

No description provided.

gasvn added 11 commits February 22, 2026 16:26
Two fixes:
1. _lazy_registry_static.py: update JLCSearchTool and DigiKeyTool
   mappings to their new location (tooluniverse.circuit.*) after
   the circuit tools were moved to the sub-package.

2. tool_registry.py: call _auto_import_subpackages() even when the
   static registry is loaded. Previously it returned early, so
   installed sub-packages (e.g. tooluniverse[circuit]) were never
   imported and their _list_config_registry entries were never
   populated.
Add _discover_entry_point_plugins() that finds installed packages in the
tooluniverse.plugins entry point group, imports their .py tool files so
@register_tool decorators fire, and loads their JSON configs into
_list_config_registry.

Call it in both code paths of build_lazy_registry() (static registry and
AST discovery), so external plugins are always loaded at startup regardless
of the lazy registry strategy used.

Remove stale _lazy_registry_static.py entries for DigiKeyTool and
JLCSearchTool (now auto-loaded via the circuit plugin entry point).

This enables a simple, flat plugin package structure that mirrors the local
~/.tooluniverse/ workspace layout — making it trivial for users to create
tool packages and share them on GitHub.
Add _discovered_plugin_names set and per-plugin guard so that calling
_discover_entry_point_plugins() more than once (e.g. in tests or if
build_lazy_registry() is invoked directly) does not append duplicate
configs to _list_config_registry.
_discover_entry_point_plugins() was only called from build_lazy_registry()
(the lazy path). The eager path in auto_discover_tools(lazy=False) never
called it, so plugin tools were silently missing when:
  - TOOLUNIVERSE_LAZY_LOADING=false env var is set
  - force_full_discovery() is called explicitly
  - get_tool_class_lazy() fallback triggers

pkgutil.iter_modules() only finds modules in the tooluniverse.* namespace,
so entry-point plugin packages (tooluniverse_circuit, etc.) are invisible
to it. Add an explicit _discover_entry_point_plugins() call at the end of
the eager discovery loop, before setting _discovery_completed=True.

The idempotency guard in _discover_entry_point_plugins() (added in previous
commit) ensures this is safe: if plugins were already loaded via the lazy
path first (e.g. frozen-env fallback), the second call is a no-op.
space.yaml is the standard "identity file" for any tool pack, whether it
lives in ~/.tooluniverse/ or inside an installed plugin package.  The
system now reads it automatically in both places:

- _read_space_yaml(): new helper that reads space.yaml from a directory,
  logs the pack name/description at INFO, and warns about missing
  required_env variables (e.g. DIGIKEY_CLIENT_ID not set).

- _discover_entry_point_plugins(): calls _read_space_yaml() for each
  plugin directory before importing tool files.

- _get_user_tool_files(): calls _read_space_yaml() for each workspace
  root directory before scanning for .py/.json files.

tools.include_tool_types in space.yaml is intentionally NOT applied
automatically — it remains a user-facing filter used only when explicitly
loading a space via load_space() / --load.
- Default workspace is now ./.tooluniverse (local mode) instead of dual-scan
- Add use_global=True to use ~/.tooluniverse as workspace default
- Workspace space.yaml auto-applied at startup when no explicit space= given
- When --load is used, workspace space.yaml acts as base config; loaded yaml
  deep-merges on top (override wins for same keys)
- Add --global CLI flag to all 3 parsers (run_http_server, run_stdio_server,
  run_smcp_server); propagated through SMCP to ToolUniverse
- Update test: _workspace_dir is no longer None by default
- Fix test state pollution: add type field to registered test tool configs
- Remove circuit tools from main package (digikey_tool.py, jlcsearch_tool.py,
  data/digikey_tools.json, data/jlcsearch_tools.json) — moved to tooluniverse-circuit
- Space system: SpaceLoader.resolve_to_local_dir(), get_tool_files_from_dir(),
  _deep_merge(), _resolve_extends(); validator schema additions (sources,
  workspace, package fields)
- Plugin entry point discovery via tooluniverse.plugins group
- Add BVBRC, CoL, EOL, FlyBase, HumanMine, LNCipedia, LOTUS, MSigDB,
  Pfam, PubChemTox, SASBDB, ZFIN, miRBase tools
- Update tool metadata and space validator
- Update tests for space loader, validator, and toolspace integration
# Conflicts:
#	src/tooluniverse/_lazy_registry_static.py
#	src/tooluniverse/default_config.py
#	src/tooluniverse/tools/.tool_metadata.json
#	src/tooluniverse/tools/BVBRC_search_taxonomy.py
#	src/tooluniverse/tools/BioTools_get_tool.py
#	src/tooluniverse/tools/IdentifiersOrg_resolve.py
#	src/tooluniverse/tools/SASBDB_get_scattering_profile.py
#	src/tooluniverse/tools/__init__.py
- Replace 11 example YAML files with single life-science.yaml covering all
  life science and general-purpose tool categories
- Add default_space.yaml with sensible defaults
- Consolidate workspace + space docs into toolspace.rst; update index.rst
- Fix validator bug: run schema validation before fill_defaults() so
  missing required fields (name) are caught instead of silently injected
- Remove version from required fields (optional, defaults to "1.0.0")
- Fix _resolve_workspace(): raise clear ValueError when path is an
  existing file instead of crashing with bare FileExistsError
- Add tests/test_robustness.py with 62 adversarial tests covering bad
  YAML, wrong workspace structure, bad API calls, and contradictory configs
- Add tests/test_workspace_and_space.py for workspace and space loading
- Update tool metadata, UniProt_get_proteome, OpenMeteo_get_air_quality
Revert .tool_metadata.json, OpenMeteo_get_air_quality.py,
UniProt_get_proteome.py, and __init__.py to their origin/main content,
undoing unintended changes introduced during the merge.
…ls()

- _load_auto_discovered_configs(): skip configs already present in
  all_tools so repeated load_tools() calls don't accumulate duplicates
- load_tools(): clear all_tools/all_tool_dict/tool_category_dicts at
  the start of a full reload (include_tools=None) so calling it multiple
  times is safe and efficient
- refresh_tools(): implement as a clean reload (was a no-op TODO stub);
  picks up new JSON/Python tool files added to workspace since startup;
  add docstring noting that built-in package tools still need a restart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant