Skip to content

Commit 82390c1

Browse files
committed
Fix tests
1 parent 42035a1 commit 82390c1

File tree

8 files changed

+127
-124
lines changed

8 files changed

+127
-124
lines changed

packages/core/README.md

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The `@utcp/sdk` package provides the fundamental components and interfaces for t
1111
### Core Components
1212

1313
* **UtcpClient**: The main client for interacting with the UTCP ecosystem
14-
* Automatic plugin registration for official protocols (HTTP, MCP, Text, CLI)
14+
* Plugin-based protocol support (HTTP, MCP, Text, File, CLI, etc.)
1515
* Manual and tool registration/deregistration
1616
* Tool search with name, tag, and description matching
1717
* Tool execution across multiple protocols
@@ -47,14 +47,15 @@ bun add @utcp/sdk
4747

4848
### Basic Usage
4949

50-
Plugins are **automatically registered** when you import the UtcpClient:
50+
**Important:** Plugins must be explicitly imported to register their protocols:
5151

5252
```typescript
5353
import { UtcpClient } from '@utcp/sdk';
54+
import '@utcp/http'; // Auto-registers HTTP protocol
5455
import { HttpCallTemplateSerializer } from '@utcp/http';
5556

5657
async function main() {
57-
// Create client - official plugins auto-register
58+
// Create client
5859
const serializer = new HttpCallTemplateSerializer();
5960
const apiTemplate = serializer.validateDict({
6061
name: 'api_manual',
@@ -88,6 +89,7 @@ async function main() {
8889

8990
```typescript
9091
import { UtcpClient } from '@utcp/sdk';
92+
import '@utcp/dotenv-loader'; // Required for .env file support
9193

9294
const client = await UtcpClient.create(process.cwd(), {
9395
load_variables_from: [
@@ -239,11 +241,47 @@ All lookups use the namespaced key: `{namespace}_VARIABLE_NAME`
239241

240242
## Plugin System
241243

242-
### Automatic Registration
244+
### Available Plugins
243245

244-
Official plugins (HTTP, MCP, Text, CLI) are automatically registered when you import `UtcpClient`. The plugin loader in `@utcp/sdk` tries to discover and register available plugins.
246+
UTCP provides several optional protocol plugins:
245247

246-
### Manual Registration
248+
**Browser-Compatible:**
249+
- `@utcp/http` - HTTP/HTTPS requests with full authentication support
250+
- `@utcp/text` - Direct text/string content (inline UTCP manuals or OpenAPI specs)
251+
- `@utcp/direct-call` - Direct function calls
252+
253+
**Node.js Only:**
254+
- `@utcp/file` - File system access for loading manuals from local files
255+
- `@utcp/mcp` - Model Context Protocol support
256+
- `@utcp/cli` - CLI command execution
257+
- `@utcp/dotenv-loader` - Load variables from .env files
258+
259+
### Explicit Plugin Import
260+
261+
Each plugin must be **explicitly imported** to register its protocol:
262+
263+
```typescript
264+
// Browser application - only import browser-compatible plugins
265+
import { UtcpClient } from '@utcp/sdk';
266+
import '@utcp/http';
267+
import '@utcp/text';
268+
import '@utcp/direct-call';
269+
270+
// Node.js application - can use all plugins
271+
import { UtcpClient } from '@utcp/sdk';
272+
import '@utcp/http';
273+
import '@utcp/mcp';
274+
import '@utcp/file';
275+
import '@utcp/dotenv-loader';
276+
```
277+
278+
This explicit import approach ensures:
279+
- ✅ Browser bundles only include what you use
280+
- ✅ No Node.js dependencies in browser builds
281+
- ✅ Perfect tree-shaking for minimal bundle sizes
282+
- ✅ Clear, explicit dependencies
283+
284+
### Custom Plugin Registration
247285

248286
For custom or third-party plugins:
249287

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/sdk",
3-
"version": "1.0.11",
3+
"version": "1.0.14",
44
"description": "Universal Tool Calling Protocol SDK",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",

packages/core/src/implementations/tag_search_strategy.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,31 +92,59 @@ export class TagSearchStrategy implements ToolSearchStrategy {
9292
}
9393

9494
const tagWords = new Set(tagLower.match(/\w+/g) || []);
95+
96+
// Exact word matches
9597
for (const word of tagWords) {
9698
if (queryWords.has(word)) {
9799
score += this.tagWeight * 0.5;
98100
}
99101
}
102+
103+
// Partial/substring word matches (e.g., "author" matches "authors")
104+
for (const queryWord of queryWords) {
105+
if (queryWord.length > 2) {
106+
for (const tagWord of tagWords) {
107+
if (tagWord.length > 2 && (tagWord.includes(queryWord) || queryWord.includes(tagWord))) {
108+
score += this.tagWeight * 0.3; // Lower weight for partial matches in tags
109+
break; // Only count once per query word
110+
}
111+
}
112+
}
113+
}
100114
}
101115
}
102116

103117
if (tool.description) {
118+
const descriptionLower = tool.description.toLowerCase();
104119
const descriptionWords = new Set(
105-
tool.description.toLowerCase().match(/\w+/g) || []
120+
descriptionLower.match(/\w+/g) || []
106121
);
122+
123+
// Exact word matches
107124
for (const word of descriptionWords) {
108125
if (queryWords.has(word) && word.length > 2) {
109126
score += this.descriptionWeight;
110127
}
111128
}
129+
130+
// Partial/substring word matches (e.g., "author" matches "authors")
131+
for (const queryWord of queryWords) {
132+
if (queryWord.length > 2) {
133+
for (const descWord of descriptionWords) {
134+
if (descWord.length > 2 && (descWord.includes(queryWord) || queryWord.includes(descWord))) {
135+
score += this.descriptionWeight * 0.5; // Lower weight for partial matches
136+
break; // Only count once per query word
137+
}
138+
}
139+
}
140+
}
112141
}
113142

114143
return { tool, score };
115144
});
116145

117146
const sortedTools = toolScores
118147
.sort((a, b) => b.score - a.score)
119-
.filter(item => item.score > 0)
120148
.map(item => item.tool);
121149

122150
return limit > 0 ? sortedTools.slice(0, limit) : sortedTools;

packages/core/src/plugins/plugin_loader.ts

Lines changed: 21 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -42,102 +42,32 @@ function _registerCorePlugins(): void {
4242
}
4343

4444
/**
45-
* Attempts to auto-register optional UTCP plugins (HTTP, MCP, Text, File, Direct Call, CLI, DotEnv Loader, etc.)
46-
* if they are available in the project. This is a best-effort approach that
47-
* silently ignores plugins that are not installed.
48-
*/
49-
function _tryRegisterOptionalPlugins(): void {
50-
// Try to register HTTP plugin
51-
try {
52-
const httpPlugin = require('@utcp/http');
53-
if (httpPlugin && typeof httpPlugin.register === 'function') {
54-
httpPlugin.register();
55-
}
56-
} catch (e) {
57-
// HTTP plugin not available, skip
58-
}
59-
60-
// Try to register MCP plugin
61-
try {
62-
const mcpPlugin = require('@utcp/mcp');
63-
if (mcpPlugin && typeof mcpPlugin.register === 'function') {
64-
mcpPlugin.register();
65-
}
66-
} catch (e) {
67-
// MCP plugin not available, skip
68-
}
69-
70-
// Try to register Text plugin
71-
try {
72-
const textPlugin = require('@utcp/text');
73-
if (textPlugin && typeof textPlugin.register === 'function') {
74-
textPlugin.register();
75-
}
76-
} catch (e) {
77-
// Text plugin not available, skip
78-
}
79-
80-
// Try to register File plugin
81-
try {
82-
const filePlugin = require('@utcp/file');
83-
if (filePlugin && typeof filePlugin.register === 'function') {
84-
filePlugin.register();
85-
}
86-
} catch (e) {
87-
// File plugin not available, skip
88-
}
89-
90-
// Try to register Direct Call plugin
91-
try {
92-
const directCallPlugin = require('@utcp/direct-call');
93-
if (directCallPlugin && typeof directCallPlugin.register === 'function') {
94-
directCallPlugin.register();
95-
}
96-
} catch (e) {
97-
// Direct Call plugin not available, skip
98-
}
99-
100-
// Try to register CLI plugin
101-
try {
102-
const cliPlugin = require('@utcp/cli');
103-
if (cliPlugin && typeof cliPlugin.register === 'function') {
104-
cliPlugin.register();
105-
}
106-
} catch (e) {
107-
// CLI plugin not available, skip
108-
}
109-
110-
// Try to register DotEnv Loader plugin
111-
try {
112-
const dotenvLoaderPlugin = require('@utcp/dotenv-loader');
113-
if (dotenvLoaderPlugin && typeof dotenvLoaderPlugin.register === 'function') {
114-
dotenvLoaderPlugin.register();
115-
}
116-
} catch (e) {
117-
// DotEnv Loader plugin not available, skip
118-
}
119-
120-
// Try to register String plugin
121-
try {
122-
const stringPlugin = require('@utcp/string');
123-
if (stringPlugin && typeof stringPlugin.register === 'function') {
124-
stringPlugin.register();
125-
}
126-
} catch (e) {
127-
// String plugin not available, skip
128-
}
129-
}
130-
131-
/**
132-
* Ensures that all core UTCP plugins (default repository, search strategy,
133-
* and post-processors) are registered with the plugin registry.
134-
* This function should be called once at application startup.
45+
* Ensures that all core UTCP plugins (auth serializers, default repository,
46+
* search strategy, and post-processors) are registered with the plugin registry.
47+
*
48+
* This function is called automatically when needed and should not be called manually.
49+
*
50+
* Note: Optional plugins like HTTP, MCP, Text, File, etc. are NOT auto-registered.
51+
* Users must explicitly import the plugins they need:
52+
*
53+
* @example
54+
* // Browser application
55+
* import { UtcpClient } from '@utcp/sdk';
56+
* import '@utcp/http'; // Auto-registers HTTP protocol
57+
* import '@utcp/text'; // Auto-registers text content protocol
58+
*
59+
* @example
60+
* // Node.js application
61+
* import { UtcpClient } from '@utcp/sdk';
62+
* import '@utcp/http';
63+
* import '@utcp/mcp';
64+
* import '@utcp/file';
65+
* import '@utcp/dotenv-loader';
13566
*/
13667
export function ensureCorePluginsInitialized(): void {
13768
if (!corePluginsInitialized && !initializing) {
13869
initializing = true;
13970
_registerCorePlugins();
140-
_tryRegisterOptionalPlugins();
14171
corePluginsInitialized = true;
14272
initializing = false;
14373
}

packages/file/tests/file_communication_protocol.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import path from 'path';
55
// Import from package indices to trigger auto-registration
66
import { FileCommunicationProtocol, FileCallTemplate } from "@utcp/file";
77
import "@utcp/http"; // Needed for OpenAPI conversion
8-
import { IUtcpClient } from "@utcp/sdk";
8+
import { IUtcpClient, ApiKeyAuth } from "@utcp/sdk";
99

1010
const tempFiles: string[] = [];
1111
const mockClient = {} as IUtcpClient;
@@ -145,9 +145,9 @@ describe("FileCommunicationProtocol", () => {
145145
auth_tools: {
146146
auth_type: 'api_key',
147147
var_name: 'X-API-Key',
148-
api_key_value: '${API_KEY}',
149-
in: 'header'
150-
}
148+
api_key: '${API_KEY}',
149+
location: 'header'
150+
} as ApiKeyAuth
151151
};
152152

153153
const result = await protocol.registerManual(mockClient, callTemplate);

packages/http/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@utcp/http",
3-
"version": "1.0.11",
3+
"version": "1.0.12",
44
"description": "HTTP utilities for UTCP",
55
"main": "dist/index.cjs",
66
"module": "dist/index.js",
@@ -43,7 +43,7 @@
4343
}
4444
},
4545
"dependencies": {
46-
"@utcp/sdk": "^1.0.11",
46+
"@utcp/sdk": "^1.0.14",
4747
"axios": "^1.11.0",
4848
"js-yaml": "^4.1.0"
4949
},

packages/http/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { SseCallTemplateSerializer } from './sse_call_template';
1010
import { HttpCommunicationProtocol } from './http_communication_protocol';
1111
import { StreamableHttpCommunicationProtocol } from './streamable_http_communication_protocol';
1212
import { SseCommunicationProtocol } from './sse_communication_protocol';
13-
import { OpenApiConverter, OpenApiConverterOptions } from './openapi_converter';
1413

1514
/**
1615
* Registers all HTTP-based protocol CallTemplate serializers
@@ -42,4 +41,5 @@ export * from './streamable_http_call_template';
4241
export * from './streamable_http_communication_protocol';
4342
export * from './sse_call_template';
4443
export * from './sse_communication_protocol';
45-
export { OpenApiConverter, OpenApiConverterOptions } from './openapi_converter';
44+
export { OpenApiConverter } from './openapi_converter';
45+
export type { OpenApiConverterOptions } from './openapi_converter';

0 commit comments

Comments
 (0)