Skip to content

fix(device): per-device tool enable/disable isolation#339

Merged
xiami762 merged 1 commit into
devfrom
fix/device-tool-isolation
May 28, 2026
Merged

fix(device): per-device tool enable/disable isolation#339
xiami762 merged 1 commit into
devfrom
fix/device-tool-isolation

Conversation

@duguwanglong

Copy link
Copy Markdown
Contributor

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.

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>
@duguwanglong duguwanglong requested a review from xiami762 May 28, 2026 13:03
@xiami762 xiami762 merged commit fddc836 into dev May 28, 2026
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.

2 participants