Skip to content

fix: consistent handler_module_path for subdirectory tools#8679

Open
muhamedfazalps wants to merge 2 commits into
AstrBotDevs:masterfrom
muhamedfazalps:fix/handler-module-path-consistency
Open

fix: consistent handler_module_path for subdirectory tools#8679
muhamedfazalps wants to merge 2 commits into
AstrBotDevs:masterfrom
muhamedfazalps:fix/handler-module-path-consistency

Conversation

@muhamedfazalps

@muhamedfazalps muhamedfazalps commented Jun 8, 2026

Copy link
Copy Markdown

Problem

Fixes #8578

When tools are in plugin subdirectories (e.g. tools/, utils/), handler_module_path was missing the data.plugins. prefix that star_manager uses. This broke startswith matching in deactivate/activate, disabling all subdirectory tools on reload.

Root Cause

add_llm_tools() looks for plugins or builtin_stars in tool.__module__ (e.g. astrbot_plugin_xxx.tools.safe_edit), but these flags don't exist in the module path for subdirectory tools.

Fix

When the flag is not found, construct path as data.plugins.<plugin_name>.main to match star_manager format.

Testing

  • Subdirectory tools stay active after reload
  • Tools in __init__.py still work
  • Disable/enable toggles all tools correctly

If this fix helped you, consider buying me a coffee!

Buy Me A Coffee

Summary by Sourcery

Bug Fixes:

  • Fix handler_module_path generation for plugin tools in subdirectories so they retain correct plugin prefixes and remain toggleable after reloads.

@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jun 8, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the add_llm_tools method in astrbot/core/star/context.py to support subdirectory tools by constructing a path matching the star_manager format when standard flags are not found in the module path. The reviewer suggested adding defensive checks to prevent potential AttributeError or IndexError in cases where tool.__module__ is missing, empty, or unexpected.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread astrbot/core/star/context.py Outdated
Comment on lines +494 to +507
module_part = tool.__module__.split(".")
flags = ["builtin_stars", "plugins"]
found_flag = False
for i, part in enumerate(module_part):
_parts.append(part)
if part in flags and i + 1 < len(module_part):
_parts.append(module_part[i + 1])
_parts.append("main")
found_flag = True
break
if not found_flag:
# Subdirectory tool: construct path matching star_manager format
plugin_name = module_part[0]
_parts = ["data", "plugins", plugin_name, "main"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential AttributeError or IndexError when tool.__module__ is None, empty, or otherwise unexpected, we should defensively check that tool.__module__ is a valid string and that module_part is not empty before accessing its first element.

Suggested change
module_part = tool.__module__.split(".")
flags = ["builtin_stars", "plugins"]
found_flag = False
for i, part in enumerate(module_part):
_parts.append(part)
if part in flags and i + 1 < len(module_part):
_parts.append(module_part[i + 1])
_parts.append("main")
found_flag = True
break
if not found_flag:
# Subdirectory tool: construct path matching star_manager format
plugin_name = module_part[0]
_parts = ["data", "plugins", plugin_name, "main"]
module_part = tool.__module__.split(".") if isinstance(getattr(tool, "__module__", None), str) else []
flags = ["builtin_stars", "plugins"]
found_flag = False
for i, part in enumerate(module_part):
_parts.append(part)
if part in flags and i + 1 < len(module_part):
_parts.append(module_part[i + 1])
_parts.append("main")
found_flag = True
break
if not found_flag and module_part and module_part[0]:
# Subdirectory tool: construct path matching star_manager format
plugin_name = module_part[0]
_parts = ["data", "plugins", plugin_name, "main"]

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The fallback branch that sets handler_module_path for cases where no plugins/builtin_stars flag is found unconditionally maps to data.plugins.<module_part[0]>.main; consider tightening this to only apply to known plugin naming patterns (e.g., astrbot_plugin_...) to avoid misrouting non-plugin tools.
  • The logic for constructing handler_module_path (both the flag-based path and the new fallback path) appears to mirror star_manager conventions; consider extracting this into a shared helper to keep the module path rules in one place and reduce the risk of future drift.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The fallback branch that sets `handler_module_path` for cases where no `plugins`/`builtin_stars` flag is found unconditionally maps to `data.plugins.<module_part[0]>.main`; consider tightening this to only apply to known plugin naming patterns (e.g., `astrbot_plugin_...`) to avoid misrouting non-plugin tools.
- The logic for constructing `handler_module_path` (both the flag-based path and the new fallback path) appears to mirror `star_manager` conventions; consider extracting this into a shared helper to keep the module path rules in one place and reduce the risk of future drift.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

…ge case handling

Address feedback from Sourcery AI and Gemini Code Assist:
- Only apply fallback path to known plugin naming patterns (astrbot_plugin_*)
- Add defensive check for None/empty tool.__module__
- Fallback to tool.__module__ if _parts is empty
@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] add_llm_tools 与 star_manager 对 handler_module_path 使用不一致的路径格式,导致插件工具在 reload 后全部被禁用

1 participant