fix(device): per-device tool enable/disable isolation#339
Merged
Conversation
Root cause: tool_settings in flocks.json was keyed globally by tool name,
so toggling a tool for Device A silently affected Device B when both shared
the same storage_key (same product version, different instance names).
Solution: introduce a dedicated `device_tool_settings` SQLite table that
stores per-device tool overrides independently of the shared global overlay.
Schema:
PRIMARY KEY (device_id, tool_name)
FOREIGN KEY device_id REFERENCES device_integrations(id) ON DELETE CASCADE
Changes:
- models.py: register DDL via Storage.register_ddl(); CASCADE handles cleanup
automatically when a device row is deleted
- store.py: add get/set/delete/list/list_all async CRUD; set and delete bump
_device_revision() so the session runner's system-prompt cache invalidates
- registry.py: ToolRegistry.execute() checks per-device DB override before
activating credentials; gate is in try/except so a DB hiccup never blocks
a tool that is globally enabled
- routes/tool.py: PATCH /api/tools/{name}?device_id= routes per-device
toggles to the new DB table instead of flocks.json
- routes/device.py: GET /api/devices/{id}/tools and PATCH
/api/devices/{id}/tools/{name} endpoints; DELETE /api/devices/{id} no
longer needs manual cleanup (ON DELETE CASCADE)
- prompt.py: build_device_context_section() loads all per-device overrides
in one SQL query (list_all_device_tool_settings) instead of N+1 calls;
disabled tools are annotated with device name and device_id so the Agent
knows not to attempt calling them
- webui: DeviceIntegration page loads per-device enabled state from
GET /api/devices/{id}/tools and routes toggle to PATCH
/api/devices/{id}/tools/{name}; wizard mode hides the tool tab entirely
(no device_id exists yet, so a per-device toggle is impossible)
- tests: 52 passing (18 new); covers CRUD, CASCADE delete, cache-revision
bumping, batch query correctness, Agent prompt display accuracy
Fixes: toggling a tool for one device no longer affects other devices of
the same product version.
Co-authored-by: Cursor <cursoragent@cursor.com>
xiami762
approved these changes
May 28, 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.
Root cause: tool_settings in flocks.json was keyed globally by tool name, so toggling a tool for Device A silently affected Device B when both shared the same storage_key (same product version, different instance names).
Solution: introduce a dedicated
device_tool_settingsSQLite table that stores per-device tool overrides independently of the shared global overlay.Schema:
PRIMARY KEY (device_id, tool_name)
FOREIGN KEY device_id REFERENCES device_integrations(id) ON DELETE CASCADE
Changes:
Fixes: toggling a tool for one device no longer affects other devices of the same product version.