@mcpmesh/sdk 0.8.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/claude-handler.test.d.ts +7 -0
- package/dist/__tests__/claude-handler.test.d.ts.map +1 -0
- package/dist/__tests__/claude-handler.test.js +455 -0
- package/dist/__tests__/claude-handler.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +7 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +156 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +7 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +170 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/generic-handler.test.d.ts +7 -0
- package/dist/__tests__/generic-handler.test.d.ts.map +1 -0
- package/dist/__tests__/generic-handler.test.js +243 -0
- package/dist/__tests__/generic-handler.test.js.map +1 -0
- package/dist/__tests__/llm-provider.test.d.ts +7 -0
- package/dist/__tests__/llm-provider.test.d.ts.map +1 -0
- package/dist/__tests__/llm-provider.test.js +217 -0
- package/dist/__tests__/llm-provider.test.js.map +1 -0
- package/dist/__tests__/openai-handler.test.d.ts +7 -0
- package/dist/__tests__/openai-handler.test.d.ts.map +1 -0
- package/dist/__tests__/openai-handler.test.js +359 -0
- package/dist/__tests__/openai-handler.test.js.map +1 -0
- package/dist/__tests__/provider-handler-registry.test.d.ts +9 -0
- package/dist/__tests__/provider-handler-registry.test.d.ts.map +1 -0
- package/dist/__tests__/provider-handler-registry.test.js +187 -0
- package/dist/__tests__/provider-handler-registry.test.js.map +1 -0
- package/dist/__tests__/response-parser.test.d.ts +7 -0
- package/dist/__tests__/response-parser.test.d.ts.map +1 -0
- package/dist/__tests__/response-parser.test.js +360 -0
- package/dist/__tests__/response-parser.test.js.map +1 -0
- package/dist/__tests__/route.test.d.ts +7 -0
- package/dist/__tests__/route.test.d.ts.map +1 -0
- package/dist/__tests__/route.test.js +281 -0
- package/dist/__tests__/route.test.js.map +1 -0
- package/dist/__tests__/sse.test.d.ts +7 -0
- package/dist/__tests__/sse.test.d.ts.map +1 -0
- package/dist/__tests__/sse.test.js +172 -0
- package/dist/__tests__/sse.test.js.map +1 -0
- package/dist/__tests__/template.test.d.ts +7 -0
- package/dist/__tests__/template.test.d.ts.map +1 -0
- package/dist/__tests__/template.test.js +176 -0
- package/dist/__tests__/template.test.js.map +1 -0
- package/dist/__tests__/tracing.test.d.ts +7 -0
- package/dist/__tests__/tracing.test.d.ts.map +1 -0
- package/dist/__tests__/tracing.test.js +264 -0
- package/dist/__tests__/tracing.test.js.map +1 -0
- package/dist/agent.d.ts +165 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +626 -0
- package/dist/agent.js.map +1 -0
- package/dist/api-runtime.d.ts +166 -0
- package/dist/api-runtime.d.ts.map +1 -0
- package/dist/api-runtime.js +459 -0
- package/dist/api-runtime.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +60 -0
- package/dist/config.js.map +1 -0
- package/dist/debug.d.ts +47 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +86 -0
- package/dist/debug.js.map +1 -0
- package/dist/errors.d.ts +99 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +110 -0
- package/dist/errors.js.map +1 -0
- package/dist/express.d.ts +146 -0
- package/dist/express.d.ts.map +1 -0
- package/dist/express.js +371 -0
- package/dist/express.js.map +1 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-agent.d.ts +193 -0
- package/dist/llm-agent.d.ts.map +1 -0
- package/dist/llm-agent.js +634 -0
- package/dist/llm-agent.js.map +1 -0
- package/dist/llm-provider.d.ts +323 -0
- package/dist/llm-provider.d.ts.map +1 -0
- package/dist/llm-provider.js +446 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/llm.d.ts +194 -0
- package/dist/llm.d.ts.map +1 -0
- package/dist/llm.js +304 -0
- package/dist/llm.js.map +1 -0
- package/dist/provider-handlers/claude-handler.d.ts +98 -0
- package/dist/provider-handlers/claude-handler.d.ts.map +1 -0
- package/dist/provider-handlers/claude-handler.js +268 -0
- package/dist/provider-handlers/claude-handler.js.map +1 -0
- package/dist/provider-handlers/gemini-handler.d.ts +82 -0
- package/dist/provider-handlers/gemini-handler.d.ts.map +1 -0
- package/dist/provider-handlers/gemini-handler.js +152 -0
- package/dist/provider-handlers/gemini-handler.js.map +1 -0
- package/dist/provider-handlers/generic-handler.d.ts +78 -0
- package/dist/provider-handlers/generic-handler.d.ts.map +1 -0
- package/dist/provider-handlers/generic-handler.js +152 -0
- package/dist/provider-handlers/generic-handler.js.map +1 -0
- package/dist/provider-handlers/index.d.ts +29 -0
- package/dist/provider-handlers/index.d.ts.map +1 -0
- package/dist/provider-handlers/index.js +32 -0
- package/dist/provider-handlers/index.js.map +1 -0
- package/dist/provider-handlers/openai-handler.d.ts +86 -0
- package/dist/provider-handlers/openai-handler.d.ts.map +1 -0
- package/dist/provider-handlers/openai-handler.js +160 -0
- package/dist/provider-handlers/openai-handler.js.map +1 -0
- package/dist/provider-handlers/provider-handler-registry.d.ts +124 -0
- package/dist/provider-handlers/provider-handler-registry.d.ts.map +1 -0
- package/dist/provider-handlers/provider-handler-registry.js +180 -0
- package/dist/provider-handlers/provider-handler-registry.js.map +1 -0
- package/dist/provider-handlers/provider-handler.d.ts +245 -0
- package/dist/provider-handlers/provider-handler.d.ts.map +1 -0
- package/dist/provider-handlers/provider-handler.js +238 -0
- package/dist/provider-handlers/provider-handler.js.map +1 -0
- package/dist/proxy.d.ts +44 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +324 -0
- package/dist/proxy.js.map +1 -0
- package/dist/response-parser.d.ts +103 -0
- package/dist/response-parser.d.ts.map +1 -0
- package/dist/response-parser.js +232 -0
- package/dist/response-parser.js.map +1 -0
- package/dist/route.d.ts +185 -0
- package/dist/route.d.ts.map +1 -0
- package/dist/route.js +310 -0
- package/dist/route.js.map +1 -0
- package/dist/sse.d.ts +45 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +77 -0
- package/dist/sse.js.map +1 -0
- package/dist/template.d.ts +86 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +206 -0
- package/dist/template.js.map +1 -0
- package/dist/tracing.d.ts +88 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/tracing.js +193 -0
- package/dist/tracing.js.map +1 -0
- package/dist/types.d.ts +618 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI provider handler.
|
|
3
|
+
*
|
|
4
|
+
* Optimized for OpenAI models (GPT-4, GPT-4 Turbo, GPT-3.5-turbo)
|
|
5
|
+
* using OpenAI's native structured output capabilities.
|
|
6
|
+
*
|
|
7
|
+
* Based on Python's OpenAIHandler:
|
|
8
|
+
* src/runtime/python/_mcp_mesh/engine/provider_handlers/openai_handler.py
|
|
9
|
+
*/
|
|
10
|
+
import { createDebug } from "../debug.js";
|
|
11
|
+
import { convertMessagesToVercelFormat, makeSchemaStrict, defaultDetermineOutputMode, BASE_TOOL_INSTRUCTIONS, } from "./provider-handler.js";
|
|
12
|
+
import { ProviderHandlerRegistry } from "./provider-handler-registry.js";
|
|
13
|
+
const debug = createDebug("openai-handler");
|
|
14
|
+
/**
|
|
15
|
+
* Provider handler for OpenAI models.
|
|
16
|
+
*
|
|
17
|
+
* OpenAI Characteristics:
|
|
18
|
+
* - Native structured output via response_format parameter
|
|
19
|
+
* - Strict JSON schema enforcement
|
|
20
|
+
* - Built-in function calling
|
|
21
|
+
* - Works best with concise, focused prompts
|
|
22
|
+
* - response_format ensures valid JSON matching schema
|
|
23
|
+
*
|
|
24
|
+
* Key Difference from Claude:
|
|
25
|
+
* - Uses response_format instead of prompt-based JSON instructions
|
|
26
|
+
* - OpenAI API guarantees JSON schema compliance
|
|
27
|
+
* - More strict parsing, less tolerance for malformed JSON
|
|
28
|
+
* - Shorter system prompts work better
|
|
29
|
+
*
|
|
30
|
+
* Supported Models:
|
|
31
|
+
* - gpt-4-turbo-preview and later
|
|
32
|
+
* - gpt-4-0125-preview and later
|
|
33
|
+
* - gpt-3.5-turbo-0125 and later
|
|
34
|
+
* - All gpt-4o models
|
|
35
|
+
*
|
|
36
|
+
* Reference: https://platform.openai.com/docs/guides/structured-outputs
|
|
37
|
+
*/
|
|
38
|
+
export class OpenAIHandler {
|
|
39
|
+
vendor = "openai";
|
|
40
|
+
/**
|
|
41
|
+
* Prepare request parameters for OpenAI API with structured output.
|
|
42
|
+
*
|
|
43
|
+
* OpenAI Strategy:
|
|
44
|
+
* - Use response_format parameter for guaranteed JSON schema compliance
|
|
45
|
+
* - This is the KEY difference from Claude handler
|
|
46
|
+
* - response_format.json_schema ensures the response matches output schema
|
|
47
|
+
* - Skip structured output for text mode (string return types)
|
|
48
|
+
*
|
|
49
|
+
* Message Format (OpenAI-specific):
|
|
50
|
+
* - Assistant messages with tool_calls → content blocks with type "tool-call"
|
|
51
|
+
* - Tool result messages → content blocks with type "tool-result"
|
|
52
|
+
* This is required for Vercel AI SDK to properly convert to OpenAI's native format.
|
|
53
|
+
*/
|
|
54
|
+
prepareRequest(messages, tools, outputSchema, options) {
|
|
55
|
+
const { outputMode, temperature, maxOutputTokens: maxTokens, topP, ...rest } = options ?? {};
|
|
56
|
+
const determinedMode = this.determineOutputMode(outputSchema, outputMode);
|
|
57
|
+
// Convert messages to Vercel AI SDK format (shared utility)
|
|
58
|
+
const convertedMessages = convertMessagesToVercelFormat(messages);
|
|
59
|
+
const request = {
|
|
60
|
+
messages: convertedMessages,
|
|
61
|
+
...rest,
|
|
62
|
+
};
|
|
63
|
+
// Add tools if provided
|
|
64
|
+
if (tools && tools.length > 0) {
|
|
65
|
+
request.tools = tools;
|
|
66
|
+
}
|
|
67
|
+
// Add standard parameters if provided
|
|
68
|
+
if (temperature !== undefined) {
|
|
69
|
+
request.temperature = temperature;
|
|
70
|
+
}
|
|
71
|
+
if (maxTokens !== undefined) {
|
|
72
|
+
request.maxOutputTokens = maxTokens;
|
|
73
|
+
}
|
|
74
|
+
if (topP !== undefined) {
|
|
75
|
+
request.topP = topP;
|
|
76
|
+
}
|
|
77
|
+
// Skip structured output for text mode or no schema
|
|
78
|
+
if (determinedMode === "text" || !outputSchema) {
|
|
79
|
+
return request;
|
|
80
|
+
}
|
|
81
|
+
// Only add response_format in "strict" mode
|
|
82
|
+
// Hint mode relies on prompt instructions instead
|
|
83
|
+
if (determinedMode === "strict") {
|
|
84
|
+
// Transform schema for OpenAI strict mode
|
|
85
|
+
// OpenAI requires additionalProperties: false and all properties in required
|
|
86
|
+
const strictSchema = makeSchemaStrict(outputSchema.schema, { addAllRequired: true });
|
|
87
|
+
// OpenAI structured output format
|
|
88
|
+
// See: https://platform.openai.com/docs/guides/structured-outputs
|
|
89
|
+
request.responseFormat = {
|
|
90
|
+
type: "json_schema",
|
|
91
|
+
jsonSchema: {
|
|
92
|
+
name: outputSchema.name,
|
|
93
|
+
schema: strictSchema,
|
|
94
|
+
strict: true, // Enforce schema compliance
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
debug(`Using response_format with strict schema: ${outputSchema.name}`);
|
|
98
|
+
}
|
|
99
|
+
return request;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Format system prompt for OpenAI (concise approach).
|
|
103
|
+
*
|
|
104
|
+
* OpenAI Strategy:
|
|
105
|
+
* 1. Use base prompt as-is
|
|
106
|
+
* 2. Add tool calling instructions if tools present
|
|
107
|
+
* 3. NO JSON schema instructions (response_format handles this)
|
|
108
|
+
* 4. Keep prompt concise - OpenAI works well with shorter prompts
|
|
109
|
+
* 5. Skip JSON note for text mode (string return type)
|
|
110
|
+
*
|
|
111
|
+
* Key Difference from Claude:
|
|
112
|
+
* - No JSON schema in prompt (response_format ensures compliance)
|
|
113
|
+
* - Shorter, more focused instructions
|
|
114
|
+
* - Let response_format handle output structure
|
|
115
|
+
*/
|
|
116
|
+
formatSystemPrompt(basePrompt, toolSchemas, outputSchema, outputMode) {
|
|
117
|
+
let systemContent = basePrompt;
|
|
118
|
+
const determinedMode = this.determineOutputMode(outputSchema, outputMode);
|
|
119
|
+
// Add tool calling instructions if tools available
|
|
120
|
+
if (toolSchemas && toolSchemas.length > 0) {
|
|
121
|
+
systemContent += BASE_TOOL_INSTRUCTIONS;
|
|
122
|
+
}
|
|
123
|
+
// Skip JSON note for text mode
|
|
124
|
+
if (determinedMode === "text" || !outputSchema) {
|
|
125
|
+
return systemContent;
|
|
126
|
+
}
|
|
127
|
+
// NOTE: We do NOT add JSON schema instructions here!
|
|
128
|
+
// OpenAI's response_format parameter handles JSON structure automatically.
|
|
129
|
+
// Adding explicit JSON instructions can actually confuse the model.
|
|
130
|
+
// Optional: Add a brief note that response should be JSON
|
|
131
|
+
// (though response_format enforces this anyway)
|
|
132
|
+
systemContent += `
|
|
133
|
+
|
|
134
|
+
Your final response will be structured as JSON matching the ${outputSchema.name} format.`;
|
|
135
|
+
return systemContent;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Return OpenAI-specific capabilities.
|
|
139
|
+
*/
|
|
140
|
+
getCapabilities() {
|
|
141
|
+
return {
|
|
142
|
+
nativeToolCalling: true, // OpenAI has native function calling
|
|
143
|
+
structuredOutput: true, // Native response_format support!
|
|
144
|
+
streaming: true, // Supports streaming
|
|
145
|
+
vision: true, // GPT-4V and later support vision
|
|
146
|
+
jsonMode: true, // Has dedicated JSON mode via response_format
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Determine output mode - OpenAI always uses strict mode for schemas.
|
|
151
|
+
*
|
|
152
|
+
* Uses the default implementation since OpenAI has excellent structured output support.
|
|
153
|
+
*/
|
|
154
|
+
determineOutputMode(outputSchema, overrideMode) {
|
|
155
|
+
return defaultDetermineOutputMode(outputSchema, overrideMode);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Register with the registry
|
|
159
|
+
ProviderHandlerRegistry.register("openai", OpenAIHandler);
|
|
160
|
+
//# sourceMappingURL=openai-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-handler.js","sourceRoot":"","sources":["../../src/provider-handlers/openai-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider handler registry for vendor-specific LLM behavior.
|
|
3
|
+
*
|
|
4
|
+
* Manages selection and instantiation of provider handlers based on vendor name.
|
|
5
|
+
*
|
|
6
|
+
* Based on Python's ProviderHandlerRegistry:
|
|
7
|
+
* src/runtime/python/_mcp_mesh/engine/provider_handlers/provider_handler_registry.py
|
|
8
|
+
*/
|
|
9
|
+
import type { ProviderHandler } from "./provider-handler.js";
|
|
10
|
+
/**
|
|
11
|
+
* Constructor type for provider handlers.
|
|
12
|
+
*/
|
|
13
|
+
export type ProviderHandlerConstructor = new () => ProviderHandler;
|
|
14
|
+
/**
|
|
15
|
+
* Registry for provider-specific handlers.
|
|
16
|
+
*
|
|
17
|
+
* Manages mapping from vendor names to handler classes and provides
|
|
18
|
+
* handler selection logic. Handlers customize LLM API calls for
|
|
19
|
+
* optimal performance with each vendor.
|
|
20
|
+
*
|
|
21
|
+
* Vendor Mapping:
|
|
22
|
+
* - "anthropic" -> ClaudeHandler
|
|
23
|
+
* - "openai" -> OpenAIHandler
|
|
24
|
+
* - "unknown" or others -> GenericHandler
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const handler = ProviderHandlerRegistry.getHandler("anthropic");
|
|
29
|
+
* const request = handler.prepareRequest(messages, tools, outputSchema);
|
|
30
|
+
* const systemPrompt = handler.formatSystemPrompt(base, tools, outputSchema);
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Extensibility:
|
|
34
|
+
* ```typescript
|
|
35
|
+
* ProviderHandlerRegistry.register("cohere", CohereHandler);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare class ProviderHandlerRegistry {
|
|
39
|
+
/** Built-in vendor mappings */
|
|
40
|
+
private static handlers;
|
|
41
|
+
/** Cache of instantiated handlers (singleton per vendor) */
|
|
42
|
+
private static instances;
|
|
43
|
+
/** Fallback handler class (set by generic-handler.ts) */
|
|
44
|
+
private static fallbackHandlerClass;
|
|
45
|
+
/**
|
|
46
|
+
* Register a custom provider handler.
|
|
47
|
+
*
|
|
48
|
+
* Allows runtime registration of new handlers without modifying registry code.
|
|
49
|
+
*
|
|
50
|
+
* @param vendor - Vendor name (e.g., "cohere", "gemini", "together")
|
|
51
|
+
* @param handlerClass - Handler class (must implement ProviderHandler)
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* class CohereHandler implements ProviderHandler {
|
|
56
|
+
* // ...
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* ProviderHandlerRegistry.register("cohere", CohereHandler);
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
static register(vendor: string, handlerClass: ProviderHandlerConstructor): void;
|
|
63
|
+
/**
|
|
64
|
+
* Set the fallback handler class.
|
|
65
|
+
*
|
|
66
|
+
* Called by generic-handler.ts during module initialization.
|
|
67
|
+
*
|
|
68
|
+
* @param handlerClass - Fallback handler class
|
|
69
|
+
*/
|
|
70
|
+
static setFallbackHandler(handlerClass: ProviderHandlerConstructor): void;
|
|
71
|
+
/**
|
|
72
|
+
* Get provider handler for vendor.
|
|
73
|
+
*
|
|
74
|
+
* Selection Logic:
|
|
75
|
+
* 1. If vendor matches registered handler -> use that handler
|
|
76
|
+
* 2. If vendor is null or "unknown" -> use GenericHandler
|
|
77
|
+
* 3. If vendor unknown -> use GenericHandler with warning
|
|
78
|
+
*
|
|
79
|
+
* Handlers are cached (singleton per vendor) for performance.
|
|
80
|
+
*
|
|
81
|
+
* @param vendor - Vendor name from model string (e.g., "anthropic", "openai")
|
|
82
|
+
* @returns Provider handler instance for the vendor
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // Get Claude handler
|
|
87
|
+
* const handler = ProviderHandlerRegistry.getHandler("anthropic");
|
|
88
|
+
*
|
|
89
|
+
* // Get OpenAI handler
|
|
90
|
+
* const handler = ProviderHandlerRegistry.getHandler("openai");
|
|
91
|
+
*
|
|
92
|
+
* // Get generic fallback
|
|
93
|
+
* const handler = ProviderHandlerRegistry.getHandler("unknown");
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
static getHandler(vendor: string | null): ProviderHandler;
|
|
97
|
+
/**
|
|
98
|
+
* List all registered vendors and their handlers.
|
|
99
|
+
*
|
|
100
|
+
* @returns Map of vendor name -> handler class name
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const vendors = ProviderHandlerRegistry.listVendors();
|
|
105
|
+
* // Map { 'anthropic' => 'ClaudeHandler', 'openai' => 'OpenAIHandler' }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
static listVendors(): Map<string, string>;
|
|
109
|
+
/**
|
|
110
|
+
* Clear cached handler instances.
|
|
111
|
+
*
|
|
112
|
+
* Useful for testing or when handler behavior needs to be reset.
|
|
113
|
+
* Next getHandler() call will create fresh instances.
|
|
114
|
+
*/
|
|
115
|
+
static clearCache(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a handler is registered for a vendor.
|
|
118
|
+
*
|
|
119
|
+
* @param vendor - Vendor name
|
|
120
|
+
* @returns True if a specific handler is registered
|
|
121
|
+
*/
|
|
122
|
+
static hasHandler(vendor: string): boolean;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=provider-handler-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-handler-registry.d.ts","sourceRoot":"","sources":["../../src/provider-handlers/provider-handler-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQ7D;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,UAAU,eAAe,CAAC;AAMnE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,uBAAuB;IAClC,+BAA+B;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsD;IAE7E,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAAC,SAAS,CAA2C;IAEnE,yDAAyD;IACzD,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAA2C;IAE9E;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,0BAA0B,GAAG,IAAI;IAW/E;;;;;;OAMG;IACH,MAAM,CAAC,kBAAkB,CAAC,YAAY,EAAE,0BAA0B,GAAG,IAAI;IAKzE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe;IA2CzD;;;;;;;;;;OAUG;IACH,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAQzC;;;;;OAKG;IACH,MAAM,CAAC,UAAU,IAAI,IAAI;IAKzB;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAG3C"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider handler registry for vendor-specific LLM behavior.
|
|
3
|
+
*
|
|
4
|
+
* Manages selection and instantiation of provider handlers based on vendor name.
|
|
5
|
+
*
|
|
6
|
+
* Based on Python's ProviderHandlerRegistry:
|
|
7
|
+
* src/runtime/python/_mcp_mesh/engine/provider_handlers/provider_handler_registry.py
|
|
8
|
+
*/
|
|
9
|
+
import { createDebug } from "../debug.js";
|
|
10
|
+
const debug = createDebug("provider-handler-registry");
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Registry Singleton
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Registry for provider-specific handlers.
|
|
16
|
+
*
|
|
17
|
+
* Manages mapping from vendor names to handler classes and provides
|
|
18
|
+
* handler selection logic. Handlers customize LLM API calls for
|
|
19
|
+
* optimal performance with each vendor.
|
|
20
|
+
*
|
|
21
|
+
* Vendor Mapping:
|
|
22
|
+
* - "anthropic" -> ClaudeHandler
|
|
23
|
+
* - "openai" -> OpenAIHandler
|
|
24
|
+
* - "unknown" or others -> GenericHandler
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const handler = ProviderHandlerRegistry.getHandler("anthropic");
|
|
29
|
+
* const request = handler.prepareRequest(messages, tools, outputSchema);
|
|
30
|
+
* const systemPrompt = handler.formatSystemPrompt(base, tools, outputSchema);
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Extensibility:
|
|
34
|
+
* ```typescript
|
|
35
|
+
* ProviderHandlerRegistry.register("cohere", CohereHandler);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class ProviderHandlerRegistry {
|
|
39
|
+
/** Built-in vendor mappings */
|
|
40
|
+
static handlers = new Map();
|
|
41
|
+
/** Cache of instantiated handlers (singleton per vendor) */
|
|
42
|
+
static instances = new Map();
|
|
43
|
+
/** Fallback handler class (set by generic-handler.ts) */
|
|
44
|
+
static fallbackHandlerClass = null;
|
|
45
|
+
/**
|
|
46
|
+
* Register a custom provider handler.
|
|
47
|
+
*
|
|
48
|
+
* Allows runtime registration of new handlers without modifying registry code.
|
|
49
|
+
*
|
|
50
|
+
* @param vendor - Vendor name (e.g., "cohere", "gemini", "together")
|
|
51
|
+
* @param handlerClass - Handler class (must implement ProviderHandler)
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* class CohereHandler implements ProviderHandler {
|
|
56
|
+
* // ...
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* ProviderHandlerRegistry.register("cohere", CohereHandler);
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
static register(vendor, handlerClass) {
|
|
63
|
+
const normalizedVendor = vendor.toLowerCase().trim();
|
|
64
|
+
this.handlers.set(normalizedVendor, handlerClass);
|
|
65
|
+
debug(`Registered provider handler: ${normalizedVendor} -> ${handlerClass.name}`);
|
|
66
|
+
// Clear cached instance if it exists (force re-instantiation)
|
|
67
|
+
if (this.instances.has(normalizedVendor)) {
|
|
68
|
+
this.instances.delete(normalizedVendor);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Set the fallback handler class.
|
|
73
|
+
*
|
|
74
|
+
* Called by generic-handler.ts during module initialization.
|
|
75
|
+
*
|
|
76
|
+
* @param handlerClass - Fallback handler class
|
|
77
|
+
*/
|
|
78
|
+
static setFallbackHandler(handlerClass) {
|
|
79
|
+
this.fallbackHandlerClass = handlerClass;
|
|
80
|
+
debug(`Set fallback handler: ${handlerClass.name}`);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get provider handler for vendor.
|
|
84
|
+
*
|
|
85
|
+
* Selection Logic:
|
|
86
|
+
* 1. If vendor matches registered handler -> use that handler
|
|
87
|
+
* 2. If vendor is null or "unknown" -> use GenericHandler
|
|
88
|
+
* 3. If vendor unknown -> use GenericHandler with warning
|
|
89
|
+
*
|
|
90
|
+
* Handlers are cached (singleton per vendor) for performance.
|
|
91
|
+
*
|
|
92
|
+
* @param vendor - Vendor name from model string (e.g., "anthropic", "openai")
|
|
93
|
+
* @returns Provider handler instance for the vendor
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // Get Claude handler
|
|
98
|
+
* const handler = ProviderHandlerRegistry.getHandler("anthropic");
|
|
99
|
+
*
|
|
100
|
+
* // Get OpenAI handler
|
|
101
|
+
* const handler = ProviderHandlerRegistry.getHandler("openai");
|
|
102
|
+
*
|
|
103
|
+
* // Get generic fallback
|
|
104
|
+
* const handler = ProviderHandlerRegistry.getHandler("unknown");
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
static getHandler(vendor) {
|
|
108
|
+
// Normalize vendor name (handle null, empty string)
|
|
109
|
+
const normalizedVendor = (vendor ?? "unknown").toLowerCase().trim();
|
|
110
|
+
// Check cache first
|
|
111
|
+
const cached = this.instances.get(normalizedVendor);
|
|
112
|
+
if (cached) {
|
|
113
|
+
debug(`Using cached handler for vendor: ${normalizedVendor}`);
|
|
114
|
+
return cached;
|
|
115
|
+
}
|
|
116
|
+
// Get handler class (or fallback to Generic)
|
|
117
|
+
let handlerClass = this.handlers.get(normalizedVendor);
|
|
118
|
+
let handler;
|
|
119
|
+
if (handlerClass) {
|
|
120
|
+
debug(`Selected ${handlerClass.name} for vendor: ${normalizedVendor}`);
|
|
121
|
+
handler = new handlerClass();
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Use fallback handler
|
|
125
|
+
if (!this.fallbackHandlerClass) {
|
|
126
|
+
throw new Error(`No handler registered for vendor '${normalizedVendor}' and no fallback handler set. ` +
|
|
127
|
+
`Import provider-handlers/index.ts to initialize handlers.`);
|
|
128
|
+
}
|
|
129
|
+
if (normalizedVendor !== "unknown") {
|
|
130
|
+
debug(`No specific handler for vendor '${normalizedVendor}', using GenericHandler`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
debug(`Using GenericHandler for unknown vendor`);
|
|
134
|
+
}
|
|
135
|
+
handler = new this.fallbackHandlerClass();
|
|
136
|
+
}
|
|
137
|
+
// Cache the instance
|
|
138
|
+
this.instances.set(normalizedVendor, handler);
|
|
139
|
+
debug(`Instantiated handler: ${handler.constructor.name} for vendor: ${normalizedVendor}`);
|
|
140
|
+
return handler;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* List all registered vendors and their handlers.
|
|
144
|
+
*
|
|
145
|
+
* @returns Map of vendor name -> handler class name
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const vendors = ProviderHandlerRegistry.listVendors();
|
|
150
|
+
* // Map { 'anthropic' => 'ClaudeHandler', 'openai' => 'OpenAIHandler' }
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
static listVendors() {
|
|
154
|
+
const result = new Map();
|
|
155
|
+
for (const [vendor, handlerClass] of this.handlers) {
|
|
156
|
+
result.set(vendor, handlerClass.name);
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Clear cached handler instances.
|
|
162
|
+
*
|
|
163
|
+
* Useful for testing or when handler behavior needs to be reset.
|
|
164
|
+
* Next getHandler() call will create fresh instances.
|
|
165
|
+
*/
|
|
166
|
+
static clearCache() {
|
|
167
|
+
this.instances.clear();
|
|
168
|
+
debug(`Cleared provider handler cache`);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Check if a handler is registered for a vendor.
|
|
172
|
+
*
|
|
173
|
+
* @param vendor - Vendor name
|
|
174
|
+
* @returns True if a specific handler is registered
|
|
175
|
+
*/
|
|
176
|
+
static hasHandler(vendor) {
|
|
177
|
+
return this.handlers.has(vendor.toLowerCase().trim());
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=provider-handler-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-handler-registry.js","sourceRoot":"","sources":["../../src/provider-handlers/provider-handler-registry.ts"],"names":[],"mappings":"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"}
|