mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-24 14:23:59 -05:00
Tools.get_tools(defer_content=True) contained the literal dead statement "stmt = stmt": the deferral was a no-op, so every tools listing loaded the full Python source of every tool (five caller sites pass defer_content=True expecting the optimization: the tools list endpoints and the user and group permission overviews). The listing now selects every column except content, and ToolModel.content becomes optional to represent deferred rows; router projections are content-less response models, so nothing downstream reads the source on these paths. On top of that, get_tools_by_user_id issued one grant query per non-owned tool and Knowledges.get_knowledge_bases_by_user_id did the same per knowledge base (the latter also sits inside per-file access checks). Both now resolve grants for all non-owned rows in a single get_accessible_resource_ids call, the same batch helper the model listing already uses. Benchmark (real SQLite DB): | metric | before | after | | --- | --- | --- | | tools listing, 33 tools x ~200 KB source | 5.13 ms | 3.18 ms | | grant queries per accessible-tools call, N non-owned tools | N | 1 | | grant queries per accessible-KBs call, N non-owned KBs | N | 1 | The listing row scales with source size; on Postgres the deferral additionally avoids shipping every tool's source over the wire per listing, and each removed grant query was a real round trip. Functionally verified: deferred listings match full listings field for field with content None, grants included and router projections working; access filtering returns exactly owned plus granted tools and knowledge bases and nothing for strangers; full (non-deferred) reads still carry the source.