Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1328,24 +1328,34 @@ function buildToolHookEntries(registry: CoreRegistry): Record<string, any> {
const entries: Record<string, any> = {};
const tools = registry.list();

for (const t of tools) {
const handler = registry.getHandler(t.name);
if (!handler) continue;

const zodArgs = jsonSchemaToZod(t.parameters);

entries[t.name] = tool({
description: t.description,
const addEntry = (name: string, description: string, zodArgs: any, handler: (args: any) => Promise<any>) => {
entries[name] = tool({
description,
args: zodArgs,
async execute(args: any, context: any) {
try {
return await handler(args);
} catch (error: any) {
log.warn("Tool hook execution failed", { tool: t.name, error: String(error?.message || error) });
log.warn("Tool hook execution failed", { tool: name, error: String(error?.message || error) });
throw error;
}
},
});
};

for (const t of tools) {
const handler = registry.getHandler(t.name);
if (!handler) continue;

const zodArgs = jsonSchemaToZod(t.parameters);
addEntry(t.name, t.description, zodArgs, handler);

// Some agent variants call `shell` instead of `bash`.
// Register a compatibility alias so subagent flows do not fail with
// unavailable tool errors.
if (t.name === "bash" && !entries.shell) {
addEntry("shell", t.description, zodArgs, handler);
}
}

return entries;
Expand Down
21 changes: 10 additions & 11 deletions tests/competitive/edge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,18 @@ describe("Competitive Edge Analysis", () => {

it("should have faster model discovery with caching", async () => {
const service = new ModelDiscoveryService({ cacheTTL: 60000 });
let queryCalls = 0;
const originalQuery = (service as any).queryCursorAgent.bind(service);
(service as any).queryCursorAgent = async () => {
queryCalls += 1;
return originalQuery();
};

// First discovery
const start1 = Date.now();
await service.discover();
const time1 = Date.now() - start1;

// Second discovery (cached)
const start2 = Date.now();
await service.discover();
const time2 = Date.now() - start2;
const models1 = await service.discover();
const models2 = await service.discover();

// Cached should be significantly faster
expect(time2).toBeLessThan(time1);
expect(models2).toEqual(models1);
expect(queryCalls).toBe(1);
});

it("should handle concurrent tool executions efficiently", async () => {
Expand Down
21 changes: 11 additions & 10 deletions tests/integration/comprehensive.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,17 +223,18 @@ describe("Comprehensive End-to-End Integration", () => {

it("should cache model discovery", async () => {
const service = new ModelDiscoveryService({ cacheTTL: 5000 });
let queryCalls = 0;
const originalQuery = (service as any).queryCursorAgent.bind(service);
(service as any).queryCursorAgent = async () => {
queryCalls += 1;
return originalQuery();
};

const startTime1 = Date.now();
await service.discover();
const endTime1 = Date.now();

const startTime2 = Date.now();
await service.discover(); // Should be cached
const endTime2 = Date.now();
const models1 = await service.discover();
const models2 = await service.discover();

// Second call should be much faster (cached)
expect(endTime2 - startTime2).toBeLessThan(endTime1 - startTime1);
expect(models2).toEqual(models1);
expect(queryCalls).toBe(1);
});
});

Expand Down Expand Up @@ -328,4 +329,4 @@ describe("Comprehensive End-to-End Integration", () => {
}
});
});
});
});
1 change: 1 addition & 0 deletions tests/unit/plugin-tools-hook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe("Plugin tool hook", () => {
// Verify default tools are registered
const toolNames = Object.keys(hooks.tool || {});
expect(toolNames).toContain("bash");
expect(toolNames).toContain("shell");
expect(toolNames).toContain("read");
expect(toolNames).toContain("write");
expect(toolNames).toContain("edit");
Expand Down