Repository navigation
feat(core): load the calling user's plugin settings for tools - #966
Merged
Merged
Conversation
Add load_user_plugin_config, which reads the bound user's stored settings for a plugin and validates them into the plugin's config class. A user with no usable settings gets PluginNotConfiguredError, whose message tells the model to point them at the My Plugins page. Validation failures log only the plugin, the user id and the failing field names. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zaira-bibi
requested changes
Oct 26, 2026
| user_id = current_user_id() | ||
| async with session_scope() as session: | ||
| row = (await PluginService().get_user_plugin_map(session, user_id)).get(plugin_name) | ||
| if row is not None and row.config: |
Contributor
There was a problem hiding this comment.
this doesn't check row.enabled, so if a user switches a plugin off, its stored credentials are still loaded. maybe add if row is not None and row.enabled and row.config:, plus a test for a disabled row.
Collaborator
Author
There was a problem hiding this comment.
Chat never binds a disabled plugin's tools, and /ai/mcp has no bound user, so no caller can reach the loader for a disabled plugin.
The loader fetched every plugin row for the user to use one. It now selects the single row by plugin name. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
model_validate reports a non-object stored config as a ValidationError, so the TypeError branch that only **-unpacking could reach is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Settings that no longer validate raise PluginConfigInvalidError, which asks the user to update them, instead of PluginNotConfiguredError, which asks them to add settings they already saved. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both plugin settings errors read the page name from PLUGIN_SETTINGS_PAGE_NAME, now "Settings", the name the page goes by. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
zaira-bibi
approved these changes
Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
LMS tools take the user's credentials as model-written arguments (#855). This adds the shared loader
that lets a tool read the calling user's stored plugin settings on the server instead.
Changes
load_user_plugin_config(plugin_name, config_class)insparkth.lib.pluginsreads thebound caller (
current_user_id()) with one query for that plugin's row and returns their validated,typed config.
PluginNotConfiguredErroris raised when the user has saved no settings (no row or anempty config). Its message tells the model to send the user to the Settings page to add them.
PluginConfigInvalidErroris raised when the saved settings no longer validate. Itsmessage asks the user to update them. Only the plugin, the user id and the failing field names are
logged, never the values, and the validation error is not chained.
PLUGIN_SETTINGS_PAGE_NAME("Settings").docs/guides/plugins.md.How to Test
uv run pytest tests/core/plugins/test_load_user_plugin_config.py -v: the caller's settings come backtyped; another user's row, no row and an empty config raise
PluginNotConfiguredError; an invalidconfig raises
PluginConfigInvalidError; an unbound caller raisesNoAuthenticatedUser.Notes
No migration, no new env var. Nothing calls the loader yet; the next PRs in the stack use it.
This description was written with the assistance of an LLM (Claude).
🤖 Generated with Claude Code