From 2f6671a9e76360c189bbd2c50ec509d4132ea603 Mon Sep 17 00:00:00 2001 From: Aditya kumar singh <143548997+Adityakk9031@users.noreply.github.com> Date: Thu, 3 Sep 2026 20:32:33 +0530 Subject: [PATCH] Allow personal connections in toolkits on desktop/single-player hosts (#1925) --- .../desktop-toolkits-personal-connections.md | 5 ++ packages/plugins/toolkits/src/page.test.ts | 53 +++++++++++++++++++ packages/plugins/toolkits/src/page.tsx | 25 +++++---- packages/plugins/toolkits/src/server.test.ts | 37 +++++++++++++ 4 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 .changeset/desktop-toolkits-personal-connections.md create mode 100644 packages/plugins/toolkits/src/page.test.ts diff --git a/.changeset/desktop-toolkits-personal-connections.md b/.changeset/desktop-toolkits-personal-connections.md new file mode 100644 index 0000000000..7e1246b6f0 --- /dev/null +++ b/.changeset/desktop-toolkits-personal-connections.md @@ -0,0 +1,5 @@ +--- +"@executor-js/plugin-toolkits": patch +--- + +Allow toolkits on single-player/desktop hosts to display and manage personal connections without multi-tenant workspace isolation restrictions. diff --git a/packages/plugins/toolkits/src/page.test.ts b/packages/plugins/toolkits/src/page.test.ts new file mode 100644 index 0000000000..6df50e21a4 --- /dev/null +++ b/packages/plugins/toolkits/src/page.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from "@effect/vitest"; +import type { ToolAddress } from "@executor-js/sdk/shared"; + +import { toolCanAppearInToolkit } from "./page"; +import type { ToolkitResponse } from "./shared"; + +describe("toolCanAppearInToolkit", () => { + const sampleOrgToolkit: ToolkitResponse = { + id: "tk_1", + owner: "org", + slug: "org-kit", + name: "Org Kit", + createdAt: 1, + updatedAt: 1, + }; + + const sampleUserToolkit: ToolkitResponse = { + id: "tk_2", + owner: "user", + slug: "user-kit", + name: "User Kit", + createdAt: 1, + updatedAt: 1, + }; + + const userTool = { + address: "tools.github.user.main.repos.list" as ToolAddress, + integration: "github", + owner: "user" as const, + name: "repos.list", + }; + + const orgTool = { + address: "tools.github.org.main.repos.list" as ToolAddress, + integration: "github", + owner: "org" as const, + name: "repos.list", + }; + + it("allows all tools when showOwnerLabels is false (single-player / desktop host)", () => { + expect(toolCanAppearInToolkit(sampleOrgToolkit, userTool, false)).toBe(true); + expect(toolCanAppearInToolkit(sampleOrgToolkit, orgTool, false)).toBe(true); + expect(toolCanAppearInToolkit(sampleUserToolkit, userTool, false)).toBe(true); + expect(toolCanAppearInToolkit(sampleUserToolkit, orgTool, false)).toBe(true); + }); + + it("hides personal tools in org toolkits when showOwnerLabels is true (multiplayer / cloud host)", () => { + expect(toolCanAppearInToolkit(sampleOrgToolkit, userTool, true)).toBe(false); + expect(toolCanAppearInToolkit(sampleOrgToolkit, orgTool, true)).toBe(true); + expect(toolCanAppearInToolkit(sampleUserToolkit, userTool, true)).toBe(true); + expect(toolCanAppearInToolkit(sampleUserToolkit, orgTool, true)).toBe(true); + }); +}); diff --git a/packages/plugins/toolkits/src/page.tsx b/packages/plugins/toolkits/src/page.tsx index 9e78eaddbb..fd67a104e3 100644 --- a/packages/plugins/toolkits/src/page.tsx +++ b/packages/plugins/toolkits/src/page.tsx @@ -156,8 +156,12 @@ const resolveToolkitPolicy = ( const toolMatchId = (tool: ToolRow): string => tool.static ? String(tool.address) : String(tool.address).replace(/^tools\./, ""); -const toolCanAppearInToolkit = (toolkit: ToolkitResponse, tool: ToolRow): boolean => - toolkit.owner === "user" || tool.static === true || tool.owner !== "user"; +export const toolCanAppearInToolkit = ( + toolkit: ToolkitResponse, + tool: ToolRow, + showOwnerLabels = true, +): boolean => + !showOwnerLabels || toolkit.owner === "user" || tool.static === true || tool.owner !== "user"; const toolkitUrlFor = (orgSlug: string | undefined, slug: string): string => { const path = orgSlug ? `/${orgSlug}/mcp/toolkits/${slug}` : `/mcp/toolkits/${slug}`; @@ -461,10 +465,10 @@ function ToolkitTile(props: { showOwnerLabels: boolean; toolkit: ToolkitResponse () => AsyncResult.isSuccess(tools) ? (tools.value as readonly ToolRow[]).filter((tool) => - toolCanAppearInToolkit(toolkit, tool), + toolCanAppearInToolkit(toolkit, tool, props.showOwnerLabels), ) : [], - [toolkit, tools], + [props.showOwnerLabels, toolkit, tools], ); const connectionGroups = useMemo(() => buildConnectionGroups(visibleTools), [visibleTools]); const connectionRows = AsyncResult.isSuccess(connections) ? connections.value.connections : []; @@ -674,7 +678,7 @@ function ToolkitGrid(props: {