diff --git a/package.json b/package.json index 99464bb..69976e4 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "publint": "catalog:dev", "tsdown": "catalog:dev", "type-fest": "catalog:dev", + "typescript": "catalog:dev", "unplugin-unused": "catalog:dev", "vitest": "catalog:dev" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index afdd528..d53dc7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,6 +60,9 @@ catalogs: type-fest: specifier: ^4.41.0 version: 4.41.0 + typescript: + specifier: ^5.8.3 + version: 5.9.3 unplugin-unused: specifier: ^0.5.4 version: 0.5.6 @@ -176,6 +179,9 @@ importers: type-fest: specifier: catalog:dev version: 4.41.0 + typescript: + specifier: catalog:dev + version: 5.9.3 unplugin-unused: specifier: catalog:dev version: 0.5.6 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index f13557b..e86a9b3 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -24,6 +24,7 @@ catalogs: publint: ^0.3.12 tsdown: ^0.17.2 type-fest: ^4.41.0 + typescript: ^5.8.3 unplugin-unused: ^0.5.4 vitest: ^4.0.15 zod: ^4.1.13 diff --git a/src/toolsets.test.ts b/src/toolsets.test.ts index 2530a85..f905407 100644 --- a/src/toolsets.test.ts +++ b/src/toolsets.test.ts @@ -12,22 +12,6 @@ import { type McpToolDefinition, createMcpApp } from '../mocks/mcp-server'; import { server } from '../mocks/node'; import { StackOneToolSet, ToolSetConfigError } from './toolsets'; -/** - * Test helper: Extends StackOneToolSet to expose private methods for testing - */ -class TestableStackOneToolSet extends StackOneToolSet { - // Expose private methods for testing - public testMatchesFilter(toolName: string, filterPattern: string | string[]): boolean { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private method for testing - return (this as any).matchesFilter(toolName, filterPattern); - } - - public testMatchGlob(str: string, pattern: string): boolean { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Accessing private method for testing - return (this as any).matchGlob(str, pattern); - } -} - describe('StackOneToolSet', () => { beforeEach(() => { vi.stubEnv('STACKONE_API_KEY', 'test_key'); @@ -174,41 +158,6 @@ describe('StackOneToolSet', () => { }); }); - describe('glob and filter matching', () => { - it('should correctly match glob patterns', () => { - const toolset = new TestableStackOneToolSet({ apiKey: 'test_key' }); - - expect(toolset.testMatchGlob('bamboohr_get_employee', 'bamboohr_*')).toBe(true); - expect(toolset.testMatchGlob('bamboohr_get_employee', 'salesforce_*')).toBe(false); - expect(toolset.testMatchGlob('bamboohr_get_employee', '*_get_*')).toBe(true); - expect(toolset.testMatchGlob('bamboohr_get_employee', 'bamboohr_get_?mployee')).toBe(true); - expect(toolset.testMatchGlob('bamboohr.get.employee', 'bamboohr.get.employee')).toBe(true); - }); - - it('should correctly filter tools with a pattern', () => { - const toolset = new TestableStackOneToolSet({ apiKey: 'test_key' }); - - expect(toolset.testMatchesFilter('bamboohr_get_employee', 'bamboohr_*')).toBe(true); - expect(toolset.testMatchesFilter('salesforce_get_contact', 'bamboohr_*')).toBe(false); - expect( - toolset.testMatchesFilter('bamboohr_get_employee', ['bamboohr_*', 'salesforce_*']), - ).toBe(true); - expect( - toolset.testMatchesFilter('salesforce_get_contact', ['bamboohr_*', 'salesforce_*']), - ).toBe(true); - expect( - toolset.testMatchesFilter('workday_get_candidate', ['bamboohr_*', 'salesforce_*']), - ).toBe(false); - - // Test negative patterns - expect(toolset.testMatchesFilter('bamboohr_get_employee', ['*', '!salesforce_*'])).toBe(true); - expect(toolset.testMatchesFilter('salesforce_get_contact', ['*', '!salesforce_*'])).toBe( - false, - ); - expect(toolset.testMatchesFilter('bamboohr_get_employee', ['*', '!bamboohr_*'])).toBe(false); - }); - }); - describe('fetchTools (MCP integration)', () => { it('creates tools from MCP catalog and wires RPC execution', async () => { const toolset = new StackOneToolSet({ diff --git a/src/toolsets.ts b/src/toolsets.ts index b15d82d..9eba7d5 100644 --- a/src/toolsets.ts +++ b/src/toolsets.ts @@ -1,5 +1,4 @@ import { defu } from 'defu'; -import type { Arrayable } from 'type-fest'; import { DEFAULT_BASE_URL, UNIFIED_API_PREFIX } from './consts'; import { createFeedbackTool } from './feedback'; import { type StackOneHeaders, normaliseHeaders, stackOneHeadersSchema } from './headers'; @@ -13,7 +12,6 @@ import type { RpcExecuteConfig, ToolParameters, } from './types'; -import { toArray } from './utils/array'; import { StackOneError } from './utils/errors'; /** @@ -346,30 +344,6 @@ export class StackOneToolSet { return new Tools(filteredTools); } - /** - * Check if a tool name matches a filter pattern - * @param toolName Tool name to check - * @param filterPattern Filter pattern or array of patterns - * @returns True if the tool name matches the filter pattern - */ - private matchesFilter(toolName: string, filterPattern: Arrayable): boolean { - // Convert to array to handle both single string and array patterns - const patterns = toArray(filterPattern); - - // Split into positive and negative patterns - const positivePatterns = patterns.filter((p) => !p.startsWith('!')); - const negativePatterns = patterns.filter((p) => p.startsWith('!')).map((p) => p.substring(1)); - - // If no positive patterns, treat as match all - const matchesPositive = - positivePatterns.length === 0 || positivePatterns.some((p) => this.matchGlob(toolName, p)); - - // If any negative pattern matches, exclude the tool - const matchesNegative = negativePatterns.some((p) => this.matchGlob(toolName, p)); - - return matchesPositive && !matchesNegative; - } - /** * Check if a string matches a glob pattern * @param str String to check