fix(coding-agent): filtered Claude plugin tool modules
This commit is contained in:
@@ -379,8 +379,9 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
||||
roots.map(async root => {
|
||||
const toolsDir = path.join(root.path, "tools");
|
||||
return loadFilesFromDir<CustomTool>(ctx, toolsDir, PROVIDER_ID, root.scope, {
|
||||
extensions: ["ts", "js"],
|
||||
transform: (name, _content, filePath, source) => {
|
||||
const toolName = name.replace(/\.(ts|js|sh|bash|py)$/, "");
|
||||
const toolName = name.replace(/\.(ts|js)$/, "");
|
||||
return {
|
||||
name: toolName,
|
||||
path: filePath,
|
||||
|
||||
@@ -2,9 +2,11 @@ import { afterEach, beforeEach, describe, expect, test, vi } from "bun:test";
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { clearCache as clearFsCache } from "@oh-my-pi/pi-coding-agent/capability/fs";
|
||||
import { type CustomTool, toolCapability } from "@oh-my-pi/pi-coding-agent/capability/tool";
|
||||
import { resetSettingsForTest, Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
|
||||
import { initializeWithSettings, loadCapability } from "@oh-my-pi/pi-coding-agent/discovery";
|
||||
import { clearClaudePluginRootsCache } from "@oh-my-pi/pi-coding-agent/discovery/helpers";
|
||||
import { removeWithRetries } from "@oh-my-pi/pi-utils";
|
||||
|
||||
describe("Claude Code custom tool discovery", () => {
|
||||
@@ -16,6 +18,8 @@ describe("Claude Code custom tool discovery", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
resetSettingsForTest();
|
||||
clearClaudePluginRootsCache();
|
||||
clearFsCache();
|
||||
originalHome = process.env.HOME;
|
||||
originalClaudeConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
||||
delete process.env.CLAUDE_CONFIG_DIR;
|
||||
@@ -31,6 +35,8 @@ describe("Claude Code custom tool discovery", () => {
|
||||
|
||||
afterEach(async () => {
|
||||
resetSettingsForTest();
|
||||
clearClaudePluginRootsCache();
|
||||
clearFsCache();
|
||||
vi.restoreAllMocks();
|
||||
if (originalHome === undefined) delete process.env.HOME;
|
||||
else process.env.HOME = originalHome;
|
||||
@@ -67,4 +73,42 @@ describe("Claude Code custom tool discovery", () => {
|
||||
{ name: "user-tool", level: "user" },
|
||||
]);
|
||||
});
|
||||
|
||||
test("filters non-module files from marketplace plugin tools", async () => {
|
||||
const pluginsDir = path.join(home, ".claude", "plugins");
|
||||
const pluginPath = path.join(root, "fixture-plugin");
|
||||
const toolsDir = path.join(pluginPath, "tools");
|
||||
await fs.mkdir(pluginsDir, { recursive: true });
|
||||
await fs.mkdir(toolsDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(pluginsDir, "installed_plugins.json"),
|
||||
JSON.stringify({
|
||||
version: 2,
|
||||
plugins: {
|
||||
"fixture@market": [
|
||||
{
|
||||
scope: "user",
|
||||
installPath: pluginPath,
|
||||
version: "1.0.0",
|
||||
installedAt: "2026-01-01T00:00:00Z",
|
||||
lastUpdated: "2026-01-01T00:00:00Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
await Promise.all([
|
||||
fs.writeFile(path.join(toolsDir, "plugin-tool.ts"), "export default () => ({});\n"),
|
||||
fs.writeFile(path.join(toolsDir, "helper.sh"), "#!/bin/sh\n"),
|
||||
fs.writeFile(path.join(toolsDir, "notes.md"), "# Notes\n"),
|
||||
]);
|
||||
|
||||
const result = await loadCapability<CustomTool>(toolCapability.id, {
|
||||
cwd: project,
|
||||
providers: ["claude-plugins"],
|
||||
});
|
||||
|
||||
expect(result.warnings).toEqual([]);
|
||||
expect(result.items.map(tool => tool.name)).toEqual(["plugin-tool"]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user