From aacbcaacc8c9b7e1b443134c27496fbf2e229147 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Thu, 6 Aug 2026 06:44:28 +0200 Subject: [PATCH] fix(agents): restrict harness tool authority --- .../app-server/dynamic-tool-build-state.ts | 2 +- .../dynamic-tool-build.lazy-import.test.ts | 4 +- .../src/app-server/dynamic-tool-build.ts | 2 +- .../src/app-server/side-question.test.ts | 2 +- .../codex/src/app-server/side-question.ts | 2 +- .../src/tool-bridge.lazy-import.test.ts | 43 ++++++++ extensions/copilot/src/tool-bridge.ts | 12 +-- .../tsconfig.package-boundary.paths.json | 3 + extensions/xai/tsconfig.json | 3 + package.json | 1 + scripts/lib/plugin-sdk-entries.mjs | 9 +- scripts/lib/plugin-sdk-entrypoints.json | 1 + ...lugin-sdk-private-local-only-subpaths.json | 1 + .../agent-harness-tool-authority-runtime.ts | 34 ++++++ src/plugin-sdk/agent-harness-tool-runtime.ts | 36 +------ ...in-sdk-package-contract-guardrails.test.ts | 20 ++++ src/plugins/sdk-alias.test.ts | 100 ++++++++++++++++++ src/plugins/sdk-alias.ts | 8 ++ 18 files changed, 237 insertions(+), 46 deletions(-) create mode 100644 extensions/copilot/src/tool-bridge.lazy-import.test.ts create mode 100644 src/plugin-sdk/agent-harness-tool-authority-runtime.ts diff --git a/extensions/codex/src/app-server/dynamic-tool-build-state.ts b/extensions/codex/src/app-server/dynamic-tool-build-state.ts index 528bc96d8fc3..7c8b16b95268 100644 --- a/extensions/codex/src/app-server/dynamic-tool-build-state.ts +++ b/extensions/codex/src/app-server/dynamic-tool-build-state.ts @@ -1,7 +1,7 @@ type OpenClawCodingToolsFactory = (typeof import("openclaw/plugin-sdk/agent-harness"))["createOpenClawCodingTools"]; type AgentHarnessCodingToolsFactory = - (typeof import("openclaw/plugin-sdk/agent-harness-tool-runtime"))["createOpenClawCodingToolsForAgentHarness"]; + (typeof import("openclaw/plugin-sdk/agent-harness-tool-authority-runtime"))["createOpenClawCodingToolsForAgentHarness"]; /** Mutable dependency seam shared by dynamic-tool construction and its behavioral tests. */ export const dynamicToolBuildState: { diff --git a/extensions/codex/src/app-server/dynamic-tool-build.lazy-import.test.ts b/extensions/codex/src/app-server/dynamic-tool-build.lazy-import.test.ts index 68bc19b076c2..05a6da6f85dd 100644 --- a/extensions/codex/src/app-server/dynamic-tool-build.lazy-import.test.ts +++ b/extensions/codex/src/app-server/dynamic-tool-build.lazy-import.test.ts @@ -1,13 +1,13 @@ import { afterEach, expect, it, vi } from "vitest"; afterEach(() => { - vi.doUnmock("openclaw/plugin-sdk/agent-harness-tool-runtime"); + vi.doUnmock("openclaw/plugin-sdk/agent-harness-tool-authority-runtime"); vi.resetModules(); }); it("does not load the private tool builder before a tool-capable turn", async () => { let toolBuilderImports = 0; - vi.doMock("openclaw/plugin-sdk/agent-harness-tool-runtime", () => { + vi.doMock("openclaw/plugin-sdk/agent-harness-tool-authority-runtime", () => { toolBuilderImports += 1; return { createOpenClawCodingToolsForAgentHarness: vi.fn(() => []), diff --git a/extensions/codex/src/app-server/dynamic-tool-build.ts b/extensions/codex/src/app-server/dynamic-tool-build.ts index 7bbe3721fd92..67854e6d83d9 100644 --- a/extensions/codex/src/app-server/dynamic-tool-build.ts +++ b/extensions/codex/src/app-server/dynamic-tool-build.ts @@ -235,7 +235,7 @@ export async function buildDynamicTools(input: DynamicToolBuildParams) { const agentHarnessCodingToolsFactory = injectedOpenClawCodingToolsFactory ? undefined : (dynamicToolBuildState.agentHarnessCodingToolsFactory ?? - (await import("openclaw/plugin-sdk/agent-harness-tool-runtime")) + (await import("openclaw/plugin-sdk/agent-harness-tool-authority-runtime")) .createOpenClawCodingToolsForAgentHarness); const createOpenClawCodingTools = injectedOpenClawCodingToolsFactory ?? diff --git a/extensions/codex/src/app-server/side-question.test.ts b/extensions/codex/src/app-server/side-question.test.ts index 6c60a5233177..1c277643f58f 100644 --- a/extensions/codex/src/app-server/side-question.test.ts +++ b/extensions/codex/src/app-server/side-question.test.ts @@ -100,7 +100,7 @@ vi.mock("./provider-capabilities.js", () => ({ resolveCodexProviderWebSearchSupportForClientMock(...args), })); -vi.mock("openclaw/plugin-sdk/agent-harness-tool-runtime", () => ({ +vi.mock("openclaw/plugin-sdk/agent-harness-tool-authority-runtime", () => ({ createOpenClawCodingToolsForAgentHarnessSideQuestion: (params: unknown, options: unknown) => createOpenClawCodingToolsForSideQuestionMock(params, options), })); diff --git a/extensions/codex/src/app-server/side-question.ts b/extensions/codex/src/app-server/side-question.ts index bc22cca775a2..7345a8e9a7df 100644 --- a/extensions/codex/src/app-server/side-question.ts +++ b/extensions/codex/src/app-server/side-question.ts @@ -938,7 +938,7 @@ async function createCodexSideToolBridge(input: { let tools: AnyAgentTool[] = []; if (supportsModelTools(runtimeModel)) { const { createOpenClawCodingToolsForAgentHarnessSideQuestion } = - await import("openclaw/plugin-sdk/agent-harness-tool-runtime"); + await import("openclaw/plugin-sdk/agent-harness-tool-authority-runtime"); const sandboxSessionKey = input.params.sandboxSessionKey?.trim() || input.params.sessionKey?.trim() || diff --git a/extensions/copilot/src/tool-bridge.lazy-import.test.ts b/extensions/copilot/src/tool-bridge.lazy-import.test.ts new file mode 100644 index 000000000000..79df4c88c18e --- /dev/null +++ b/extensions/copilot/src/tool-bridge.lazy-import.test.ts @@ -0,0 +1,43 @@ +import { afterEach, expect, it, vi } from "vitest"; + +afterEach(() => { + vi.doUnmock("openclaw/plugin-sdk/agent-harness-tool-authority-runtime"); + vi.resetModules(); +}); + +it("loads the private tool builder only after the tool-construction guard", async () => { + let toolBuilderImports = 0; + vi.doMock("openclaw/plugin-sdk/agent-harness-tool-authority-runtime", () => { + toolBuilderImports += 1; + return { + createOpenClawCodingToolsForAgentHarness: vi.fn(() => []), + }; + }); + + const { createCopilotToolBridge } = await import("./tool-bridge.js"); + expect(toolBuilderImports).toBe(0); + + await expect( + createCopilotToolBridge({ + admittedAttempt: {} as never, + agentId: "agent-1", + attemptParams: { disableTools: true } as never, + modelId: "gpt-4o", + modelProvider: "github-copilot", + sessionId: "session-1", + }), + ).resolves.toEqual({ codeModeEngaged: false, sdkTools: [], sourceTools: [] }); + expect(toolBuilderImports).toBe(0); + + await expect( + createCopilotToolBridge({ + admittedAttempt: {} as never, + agentId: "agent-1", + attemptParams: {} as never, + modelId: "gpt-4o", + modelProvider: "github-copilot", + sessionId: "session-1", + }), + ).resolves.toMatchObject({ sdkTools: [], sourceTools: [] }); + expect(toolBuilderImports).toBe(1); +}); diff --git a/extensions/copilot/src/tool-bridge.ts b/extensions/copilot/src/tool-bridge.ts index ae5bc0336bd5..a6b0608c625b 100644 --- a/extensions/copilot/src/tool-bridge.ts +++ b/extensions/copilot/src/tool-bridge.ts @@ -22,10 +22,7 @@ import { resolveModelAuthMode, sanitizeToolResult, } from "openclaw/plugin-sdk/agent-harness-runtime"; -import { - createAgentHarnessToolSurfaceRuntime, - createOpenClawCodingToolsForAgentHarness, -} from "openclaw/plugin-sdk/agent-harness-tool-runtime"; +import { createAgentHarnessToolSurfaceRuntime } from "openclaw/plugin-sdk/agent-harness-tool-runtime"; type CreateOpenClawCodingTools = (typeof import("openclaw/plugin-sdk/agent-harness"))["createOpenClawCodingTools"]; @@ -204,8 +201,11 @@ export async function createCopilotToolBridge( const createOpenClawCodingTools = input.createOpenClawCodingTools ?? (admittedAttempt - ? (options: OpenClawCodingToolsOptions) => - createOpenClawCodingToolsForAgentHarness(admittedAttempt, options) + ? async (options: OpenClawCodingToolsOptions) => { + const { createOpenClawCodingToolsForAgentHarness } = + await import("openclaw/plugin-sdk/agent-harness-tool-authority-runtime"); + return createOpenClawCodingToolsForAgentHarness(admittedAttempt, options); + } : (await import("openclaw/plugin-sdk/agent-harness")).createOpenClawCodingTools); const toolSurfaceRuntime = createAgentHarnessToolSurfaceRuntime({ diff --git a/extensions/tsconfig.package-boundary.paths.json b/extensions/tsconfig.package-boundary.paths.json index 52c2ab71731e..e3ab6fa37c9f 100644 --- a/extensions/tsconfig.package-boundary.paths.json +++ b/extensions/tsconfig.package-boundary.paths.json @@ -134,6 +134,9 @@ "openclaw/plugin-sdk/agent-harness-exec-review-runtime": [ "../packages/plugin-sdk/dist/src/plugin-sdk/agent-harness-exec-review-runtime.d.ts" ], + "openclaw/plugin-sdk/agent-harness-tool-authority-runtime": [ + "../packages/plugin-sdk/dist/src/plugin-sdk/agent-harness-tool-authority-runtime.d.ts" + ], "openclaw/plugin-sdk/agent-harness-tool-runtime": [ "../packages/plugin-sdk/dist/src/plugin-sdk/agent-harness-tool-runtime.d.ts" ], diff --git a/extensions/xai/tsconfig.json b/extensions/xai/tsconfig.json index 0fcdf320592b..b6cf55bdff3b 100644 --- a/extensions/xai/tsconfig.json +++ b/extensions/xai/tsconfig.json @@ -131,6 +131,9 @@ "openclaw/plugin-sdk/agent-harness-exec-review-runtime": [ "../../packages/plugin-sdk/dist/src/plugin-sdk/agent-harness-exec-review-runtime.d.ts" ], + "openclaw/plugin-sdk/agent-harness-tool-authority-runtime": [ + "../../packages/plugin-sdk/dist/src/plugin-sdk/agent-harness-tool-authority-runtime.d.ts" + ], "openclaw/plugin-sdk/agent-harness-tool-runtime": [ "../../packages/plugin-sdk/dist/src/plugin-sdk/agent-harness-tool-runtime.d.ts" ], diff --git a/package.json b/package.json index ae151d3733b1..54b81011f9a8 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "!dist/plugin-sdk/agent-core.d.ts", "!dist/plugin-sdk/agent-harness-exec-review-runtime.d.ts", "!dist/plugin-sdk/agent-harness-task-runtime.d.ts", + "!dist/plugin-sdk/agent-harness-tool-authority-runtime.d.ts", "!dist/plugin-sdk/agent-harness-tool-runtime.d.ts", "!dist/plugin-sdk/agent-runtime-test-contracts.js", "!dist/plugin-sdk/agent-runtime-test-contracts.d.ts", diff --git a/scripts/lib/plugin-sdk-entries.mjs b/scripts/lib/plugin-sdk-entries.mjs index 9adb7747c9cd..5567c10f6baf 100644 --- a/scripts/lib/plugin-sdk-entries.mjs +++ b/scripts/lib/plugin-sdk-entries.mjs @@ -84,6 +84,10 @@ export const packagedPrivatePluginSdkRuntimeEntrypoints = productionPluginSdkEntrypointSet.has(entry), ); +const ownerRestrictedPrivatePluginSdkRuntimeEntrypointSet = new Set([ + "agent-harness-tool-authority-runtime", +]); + /** Private entrypoints reserved for local tests and QA builds. */ const nonProductionPrivatePluginSdkEntrypoints = privateLocalOnlyPluginSdkEntrypoints.filter( (entry) => !productionPluginSdkEntrypointSet.has(entry), @@ -131,7 +135,10 @@ export function buildPluginSdkPackageExports() { ], ]; } - if (packagedPrivatePluginSdkRuntimeEntrypoints.includes(entry)) { + if ( + packagedPrivatePluginSdkRuntimeEntrypoints.includes(entry) && + !ownerRestrictedPrivatePluginSdkRuntimeEntrypointSet.has(entry) + ) { // Official plugins ship separately but execute against the host's private runtime. // Their declarations stay pack-excluded by listUnpackagedPrivatePluginSdkDistArtifacts. return [ diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index 9cf93e1ecaa5..22b1ddf031eb 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -107,6 +107,7 @@ "agent-harness", "agent-harness-exec-review-runtime", "agent-harness-runtime", + "agent-harness-tool-authority-runtime", "agent-harness-tool-runtime", "hook-runtime", "html-entity-runtime", diff --git a/scripts/lib/plugin-sdk-private-local-only-subpaths.json b/scripts/lib/plugin-sdk-private-local-only-subpaths.json index 3a552e30a7dc..cbdd986555f3 100644 --- a/scripts/lib/plugin-sdk-private-local-only-subpaths.json +++ b/scripts/lib/plugin-sdk-private-local-only-subpaths.json @@ -8,6 +8,7 @@ "agent-core", "agent-harness-exec-review-runtime", "agent-harness-task-runtime", + "agent-harness-tool-authority-runtime", "agent-harness-tool-runtime", "agent-runtime-test-contracts", "agent-sessions", diff --git a/src/plugin-sdk/agent-harness-tool-authority-runtime.ts b/src/plugin-sdk/agent-harness-tool-authority-runtime.ts new file mode 100644 index 000000000000..ca75062dffc1 --- /dev/null +++ b/src/plugin-sdk/agent-harness-tool-authority-runtime.ts @@ -0,0 +1,34 @@ +import { + createOpenClawCodingToolsForAgentHarness as createCoreOpenClawCodingToolsForAgentHarness, + createOpenClawCodingToolsForAgentHarnessSideQuestion as createCoreOpenClawCodingToolsForAgentHarnessSideQuestion, +} from "../agents/agent-tools-internal.js"; +import type { + AgentHarnessSideQuestionParams, + EmbeddedRunAttemptParams, +} from "./agent-harness-runtime.js"; + +type OpenClawCodingToolsOptions = NonNullable< + Parameters[0] +>; + +/** + * Build tools for the exact host-admitted attempt without exposing its private + * execution attribution to plugin code. + */ +export function createOpenClawCodingToolsForAgentHarness( + attempt: EmbeddedRunAttemptParams, + options?: OpenClawCodingToolsOptions, +): ReturnType { + return createCoreOpenClawCodingToolsForAgentHarness(attempt, options); +} + +/** + * Build tools for the exact host-admitted side-question request without + * exposing its private execution attribution to plugin code. + */ +export function createOpenClawCodingToolsForAgentHarnessSideQuestion( + params: AgentHarnessSideQuestionParams, + options?: OpenClawCodingToolsOptions, +): ReturnType { + return createCoreOpenClawCodingToolsForAgentHarnessSideQuestion(params, options); +} diff --git a/src/plugin-sdk/agent-harness-tool-runtime.ts b/src/plugin-sdk/agent-harness-tool-runtime.ts index ceb067aea7cb..a94ea315246d 100644 --- a/src/plugin-sdk/agent-harness-tool-runtime.ts +++ b/src/plugin-sdk/agent-harness-tool-runtime.ts @@ -1,21 +1,13 @@ -import { - createOpenClawCodingToolsForAgentHarness as createCoreOpenClawCodingToolsForAgentHarness, - createOpenClawCodingToolsForAgentHarnessSideQuestion as createCoreOpenClawCodingToolsForAgentHarnessSideQuestion, -} from "../agents/agent-tools-internal.js"; /** - * Packaged private runtime facade for official harness plugins. + * Focused runtime SDK subpath for native harness tool-surface routing. * - * This subpath is local-only and declaration-excluded. Keep tool-search and - * code-mode dependencies out of the lightweight startup lifecycle facade. + * Keep tool-search and code-mode dependencies out of the lightweight harness + * lifecycle facade used during plugin startup. */ import { createAgentHarnessToolSurfaceRuntime as createCoreAgentHarnessToolSurfaceRuntime, type AgentHarnessToolSurfaceRuntime as CoreAgentHarnessToolSurfaceRuntime, } from "../agents/harness/tool-surface-bridge.js"; -import type { - AgentHarnessSideQuestionParams, - EmbeddedRunAttemptParams, -} from "./agent-harness-runtime.js"; type OpenClawCodingToolsOptions = NonNullable< Parameters[0] @@ -41,25 +33,3 @@ export function createAgentHarnessToolSurfaceRuntime( ): AgentHarnessToolSurfaceRuntime { return createCoreAgentHarnessToolSurfaceRuntime(params); } - -/** - * Build tools for the exact host-admitted attempt without exposing its private - * execution attribution to plugin code. - */ -export function createOpenClawCodingToolsForAgentHarness( - attempt: EmbeddedRunAttemptParams, - options?: OpenClawCodingToolsOptions, -): ReturnType { - return createCoreOpenClawCodingToolsForAgentHarness(attempt, options); -} - -/** - * Build tools for the exact host-admitted side-question request without - * exposing its private execution attribution to plugin code. - */ -export function createOpenClawCodingToolsForAgentHarnessSideQuestion( - params: AgentHarnessSideQuestionParams, - options?: OpenClawCodingToolsOptions, -): ReturnType { - return createCoreOpenClawCodingToolsForAgentHarnessSideQuestion(params, options); -} diff --git a/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts b/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts index 78c46c43e31b..ec05c6c44993 100644 --- a/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts +++ b/src/plugins/contracts/plugin-sdk-package-contract-guardrails.test.ts @@ -817,6 +817,26 @@ describe("plugin-sdk package contract guardrails", () => { }); }); + it("keeps the agent harness tool authority runtime owner-restricted", () => { + const entrypoint = "agent-harness-tool-authority-runtime"; + const localOnly = new Set(privateLocalOnlyPluginSdkEntrypoints); + const packageExports = new Set(collectPluginSdkPackageExports()); + const typedExports = collectTypedPluginSdkPackageExports(); + const excludedDeclarations = collectPackExcludedPluginSdkDeclarations(); + + expect({ + localOnly: localOnly.has(entrypoint), + packageExport: packageExports.has(entrypoint), + typedExport: typedExports.has(entrypoint), + declarationExcluded: excludedDeclarations.has(entrypoint), + }).toEqual({ + localOnly: true, + packageExport: false, + typedExport: false, + declarationExcluded: true, + }); + }); + it("keeps configured local-origin fetch helpers out of deprecated infra-runtime", () => { const source = fs.readFileSync(resolve(REPO_ROOT, "src/plugin-sdk/infra-runtime.ts"), "utf8"); diff --git a/src/plugins/sdk-alias.test.ts b/src/plugins/sdk-alias.test.ts index 3378ad16cd72..7b9e39d15238 100644 --- a/src/plugins/sdk-alias.test.ts +++ b/src/plugins/sdk-alias.test.ts @@ -654,6 +654,106 @@ describe("plugin sdk alias helpers", () => { expect(shadowCodexSubpaths).toEqual(["core"]); }); + it("aliases harness tool authority only for trusted official harness plugins", () => { + const fixture = createPluginSdkAliasFixture({ + packageExports: { + "./plugin-sdk/core": { default: "./dist/plugin-sdk/core.js" }, + }, + }); + const authoritySubpath = "agent-harness-tool-authority-runtime"; + const sourceAuthorityPath = path.join( + fixture.root, + "src", + "plugin-sdk", + `${authoritySubpath}.ts`, + ); + const distAuthorityPath = path.join( + fixture.root, + "dist", + "plugin-sdk", + `${authoritySubpath}.js`, + ); + fs.writeFileSync( + path.join(fixture.root, "scripts", "lib", "plugin-sdk-private-local-only-subpaths.json"), + JSON.stringify([authoritySubpath], null, 2), + "utf-8", + ); + fs.writeFileSync(sourceAuthorityPath, "export const authority = true;\n", "utf-8"); + fs.writeFileSync(distAuthorityPath, "export const authority = true;\n", "utf-8"); + + const sourceCodexEntry = writePluginEntry( + fixture.root, + bundledPluginFile("codex", "src/index.ts"), + ); + const sourceCopilotEntry = writePluginEntry( + fixture.root, + bundledPluginFile("copilot", "src/index.ts"), + ); + const sourceOtherEntry = writePluginEntry( + fixture.root, + bundledPluginFile("demo", "src/index.ts"), + ); + const { packageRoot: installedCodexRoot, pluginEntry: installedCodexEntry } = + writeInstalledPluginEntry({ + installRoot: path.join(makeTempDir(), ".openclaw", "npm"), + packageName: "@openclaw/codex", + }); + const { packageRoot: installedCopilotRoot, pluginEntry: installedCopilotEntry } = + writeInstalledPluginEntry({ + installRoot: path.join(makeTempDir(), ".openclaw", "npm"), + packageName: "@openclaw/copilot", + }); + const { packageRoot: installedOtherRoot, pluginEntry: installedOtherEntry } = + writeInstalledPluginEntry({ + installRoot: path.join(makeTempDir(), ".openclaw", "npm"), + packageName: "@openclaw/demo", + }); + + const sourceCodexAliases = buildPluginLoaderAliasMap(sourceCodexEntry); + const sourceCopilotAliases = buildPluginLoaderAliasMap(sourceCopilotEntry); + const sourceOtherAliases = buildPluginLoaderAliasMap(sourceOtherEntry); + const installedCodexAliases = withCwd(installedCodexRoot, () => + buildPluginLoaderAliasMap( + installedCodexEntry, + path.join(fixture.root, "openclaw.mjs"), + undefined, + "dist", + ), + ); + const installedCopilotAliases = withCwd(installedCopilotRoot, () => + buildPluginLoaderAliasMap( + installedCopilotEntry, + path.join(fixture.root, "openclaw.mjs"), + undefined, + "dist", + ), + ); + const installedOtherAliases = withCwd(installedOtherRoot, () => + buildPluginLoaderAliasMap( + installedOtherEntry, + path.join(fixture.root, "openclaw.mjs"), + undefined, + "dist", + ), + ); + const specifier = `openclaw/plugin-sdk/${authoritySubpath}`; + + expect(fs.realpathSync(sourceCodexAliases[specifier] ?? "")).toBe( + fs.realpathSync(sourceAuthorityPath), + ); + expect(fs.realpathSync(sourceCopilotAliases[specifier] ?? "")).toBe( + fs.realpathSync(sourceAuthorityPath), + ); + expect(fs.realpathSync(installedCodexAliases[specifier] ?? "")).toBe( + fs.realpathSync(distAuthorityPath), + ); + expect(fs.realpathSync(installedCopilotAliases[specifier] ?? "")).toBe( + fs.realpathSync(distAuthorityPath), + ); + expect(sourceOtherAliases[specifier]).toBeUndefined(); + expect(installedOtherAliases[specifier]).toBeUndefined(); + }); + it("does not reuse a non-private cached subpath list after private qa gets enabled", () => { const fixture = createPluginSdkAliasFixture({ packageExports: { diff --git a/src/plugins/sdk-alias.ts b/src/plugins/sdk-alias.ts index 148931838be4..cafc2cbc4ba8 100644 --- a/src/plugins/sdk-alias.ts +++ b/src/plugins/sdk-alias.ts @@ -419,6 +419,7 @@ const cachedWorkspacePackageAliasMaps = new PluginLruCache