Skip to content

fix: pass plugin name to StarTools.get_data_dir() to avoid inspect.stack() crash#193

Open
Rat0323 wants to merge 2 commits into
SXP-Simon:mainfrom
Rat0323:fix-get-data-dir-crash
Open

fix: pass plugin name to StarTools.get_data_dir() to avoid inspect.stack() crash#193
Rat0323 wants to merge 2 commits into
SXP-Simon:mainfrom
Rat0323:fix-get-data-dir-crash

Conversation

@Rat0323

@Rat0323 Rat0323 commented Jun 5, 2026

Copy link
Copy Markdown

Problem

When StarTools.get_data_dir() is called without arguments, the framework attempts to deduce the calling plugin name using inspect.stack(). Under certain environments (such as dynamic reloading, testing shims, or direct scripts where __main__ is the entrypoint), metadata extraction fails, throwing a fatal RuntimeError: 无法获取模块 __main__ 的元信息.

Solution

Explicitly pass the plugin name "astrbot_plugin_qq_group_daily_analysis" to all calls of StarTools.get_data_dir() to avoid this dynamic inspection crash. This is safe, backwards-compatible, and robust across all execution environments.

Verified and tested successfully under AstrBot official environment.

Summary by Sourcery

Ensure the plugin always uses a stable, explicit data directory for storage and HTML/debug outputs by passing the plugin name into StarTools.get_data_dir() instead of relying on runtime inspection and fallback paths.

Bug Fixes:

  • Prevent crashes when resolving the plugin data directory by avoiding inspect-based plugin name deduction and always passing the plugin name explicitly.

Enhancements:

  • Simplify and unify data, HTML report, and debug output directory resolution across the plugin by removing custom fallback path construction.

💡 Ecosystem & Framework Context

This issue stems from a known limitation in the AstrBot core framework's path-resolving API. We have submitted a core robustness fix to the official AstrBot core repository: AstrBot Core PR #8588.

However, this plugin-level change (passing the plugin name explicitly) remains highly necessary to ensure backward compatibility. It prevents the plugin from crashing on older installations of AstrBot that have not upgraded to the latest core version.

This is a safe, non-breaking, and recommended change.

@sourcery-ai

sourcery-ai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Pass the explicit plugin name "astrbot_plugin_qq_group_daily_analysis" into all StarTools.get_data_dir() usages and remove the previous try/except-based fallback paths, standardizing data directory resolution for reports and debug artifacts.

File-Level Changes

Change Details Files
Standardize main plugin data directory resolution via StarTools.get_data_dir with explicit plugin name.
  • Replace StarTools.get_data_dir() call in the plugin constructor with StarTools.get_data_dir("astrbot_plugin_qq_group_daily_analysis")
  • Remove the try/except around StarTools.get_data_dir() and the manual get_astrbot_data_path-based fallback path construction
main.py
Use explicit plugin-scoped data dir for HTML report output paths, removing runtime fallbacks.
  • In report sending logic, import StarTools unconditionally and compute html_output_dir using StarTools.get_data_dir("astrbot_plugin_qq_group_daily_analysis") / "self_hosted_html_reports" when user config is empty
  • Delete the prior try/except block and get_astrbot_data_path-based fallback for html_output_dir
main.py
src/infrastructure/reporting/dispatcher.py
src/infrastructure/config/config_manager.py
Use explicit plugin-scoped data dir for debug data storage.
  • In BaseAnalyzer._save_debug_data, compute data_path as StarTools.get_data_dir("astrbot_plugin_qq_group_daily_analysis") / "debug_data" and remove fallback path logic
  • In LLMAnalyzer, compute debug_dir as StarTools.get_data_dir("astrbot_plugin_qq_group_daily_analysis") / "debug_data" instead of relying on implicit plugin detection
src/infrastructure/analysis/base_analyzer.py
src/infrastructure/analysis/llm_analyzer.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@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 found 1 issue, and left some high level feedback:

  • The plugin name string "astrbot_plugin_qq_group_daily_analysis" is now duplicated across multiple call sites; consider centralizing it in a single constant (e.g., in a config/module-level variable) to avoid typos and ease future renames.
  • Previously there was a filesystem-based fallback when StarTools.get_data_dir() raised; now any failure will bubble up—if you still expect non-inspection-related failures (e.g., StarTools unavailable), it may be worth retaining a narrower fallback around those specific error cases to preserve robustness.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The plugin name string "astrbot_plugin_qq_group_daily_analysis" is now duplicated across multiple call sites; consider centralizing it in a single constant (e.g., in a config/module-level variable) to avoid typos and ease future renames.
- Previously there was a filesystem-based fallback when StarTools.get_data_dir() raised; now any failure will bubble up—if you still expect non-inspection-related failures (e.g., StarTools unavailable), it may be worth retaining a narrower fallback around those specific error cases to preserve robustness.

## Individual Comments

### Comment 1
<location path="src/infrastructure/analysis/llm_analyzer.py" line_range="467" />
<code_context>
             from astrbot.api.star import StarTools

-            debug_dir = StarTools.get_data_dir() / "debug_data"
+            debug_dir = StarTools.get_data_dir("astrbot_plugin_qq_group_daily_analysis") / "debug_data"
             debug_dir.mkdir(parents=True, exist_ok=True)

</code_context>
<issue_to_address>
**suggestion:** The plugin identifier string is duplicated in multiple places; consider centralizing it to avoid drift.

This literal plugin name is now embedded in multiple modules (config, init, HTML output, debug paths). Centralizing it in a shared constant or helper (e.g. `get_plugin_data_dir()` wrapping `StarTools.get_data_dir(PLUGIN_NAME)`) would make future renames or variant support safer and prevent subtle path mismatches.

Suggested implementation:

```python
from astrbot.api.star import StarTools

PLUGIN_NAME = "astrbot_plugin_qq_group_daily_analysis"

```

```python
debug_dir = StarTools.get_data_dir(PLUGIN_NAME) / "debug_data"

```

To fully centralize the plugin identifier and avoid drift across the codebase, you should also:
1. Identify other modules where `"astrbot_plugin_qq_group_daily_analysis"` is hardcoded (e.g., config, `__init__`, HTML output, other debug paths).
2. Extract `PLUGIN_NAME` (or a helper like `get_plugin_data_dir()`) into a shared module (for example, `src/infrastructure/analysis/constants.py` or a plugin-level `config.py`).
3. Replace the literals in those modules to import and use the shared `PLUGIN_NAME` or `get_plugin_data_dir()` instead of repeating the string.
</issue_to_address>

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.

Comment thread src/infrastructure/analysis/llm_analyzer.py Outdated
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