@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
package/dist/llm.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mesh.llm() - LLM-powered tool wrapper for MCP Mesh.
|
|
3
|
+
*
|
|
4
|
+
* Creates a tool that uses an LLM with agentic capabilities,
|
|
5
|
+
* including access to other mesh tools and structured output.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { FastMCP } from "fastmcp";
|
|
10
|
+
* import { mesh } from "@mcpmesh/sdk";
|
|
11
|
+
* import { z } from "zod";
|
|
12
|
+
*
|
|
13
|
+
* const server = new FastMCP({ name: "Smart Assistant", version: "1.0.0" });
|
|
14
|
+
*
|
|
15
|
+
* const AssistResponse = z.object({
|
|
16
|
+
* answer: z.string(),
|
|
17
|
+
* confidence: z.number(),
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* server.addTool(mesh.llm({
|
|
21
|
+
* name: "assist",
|
|
22
|
+
* capability: "smart_assistant",
|
|
23
|
+
* provider: "claude",
|
|
24
|
+
* systemPrompt: "file://prompts/assistant.hbs",
|
|
25
|
+
* filter: [{ capability: "calculator" }],
|
|
26
|
+
* returns: AssistResponse,
|
|
27
|
+
* parameters: z.object({ message: z.string() }),
|
|
28
|
+
* execute: async ({ message }, { llm }) => llm(message),
|
|
29
|
+
* }));
|
|
30
|
+
*
|
|
31
|
+
* const agent = mesh(server, { name: "smart-assistant", port: 9003 });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
35
|
+
import { MeshLlmAgent, createLlmToolProxy } from "./llm-agent.js";
|
|
36
|
+
import { debug } from "./debug.js";
|
|
37
|
+
/**
|
|
38
|
+
* Registry for LLM tools - stores configuration and resolved dependencies.
|
|
39
|
+
*/
|
|
40
|
+
export class LlmToolRegistry {
|
|
41
|
+
static instance = null;
|
|
42
|
+
/** LLM tool configurations by function ID */
|
|
43
|
+
configs = new Map();
|
|
44
|
+
/** Resolved tools for each LLM function (from llm_tools_updated events) */
|
|
45
|
+
resolvedTools = new Map();
|
|
46
|
+
/** Resolved providers for each LLM function (from llm_provider_available events) */
|
|
47
|
+
resolvedProviders = new Map();
|
|
48
|
+
constructor() { }
|
|
49
|
+
static getInstance() {
|
|
50
|
+
if (!LlmToolRegistry.instance) {
|
|
51
|
+
LlmToolRegistry.instance = new LlmToolRegistry();
|
|
52
|
+
}
|
|
53
|
+
return LlmToolRegistry.instance;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Reset the registry (for testing).
|
|
57
|
+
*/
|
|
58
|
+
static reset() {
|
|
59
|
+
LlmToolRegistry.instance = null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Register an LLM tool configuration.
|
|
63
|
+
*/
|
|
64
|
+
register(functionId, config) {
|
|
65
|
+
this.configs.set(functionId, config);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get an LLM tool configuration.
|
|
69
|
+
*/
|
|
70
|
+
getConfig(functionId) {
|
|
71
|
+
return this.configs.get(functionId);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get all registered LLM tool configurations.
|
|
75
|
+
*/
|
|
76
|
+
getAllConfigs() {
|
|
77
|
+
return new Map(this.configs);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Update resolved tools for an LLM function.
|
|
81
|
+
*/
|
|
82
|
+
setResolvedTools(functionId, tools) {
|
|
83
|
+
this.resolvedTools.set(functionId, tools);
|
|
84
|
+
debug.llm(`Tools updated for ${functionId}: ${tools.length} tools available`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get resolved tools for an LLM function.
|
|
88
|
+
*/
|
|
89
|
+
getResolvedTools(functionId) {
|
|
90
|
+
return this.resolvedTools.get(functionId) ?? [];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Update resolved provider for an LLM function.
|
|
94
|
+
*/
|
|
95
|
+
setResolvedProvider(functionId, provider) {
|
|
96
|
+
this.resolvedProviders.set(functionId, provider);
|
|
97
|
+
debug.llm(`Provider available for ${functionId}: ${provider.endpoint}`);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Remove resolved provider for an LLM function.
|
|
101
|
+
*/
|
|
102
|
+
removeResolvedProvider(functionId) {
|
|
103
|
+
this.resolvedProviders.delete(functionId);
|
|
104
|
+
debug.llm(`Provider unavailable for ${functionId}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get resolved provider for an LLM function.
|
|
108
|
+
*/
|
|
109
|
+
getResolvedProvider(functionId) {
|
|
110
|
+
return this.resolvedProviders.get(functionId);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Clear all resolved dependencies.
|
|
114
|
+
*/
|
|
115
|
+
clearAllResolved() {
|
|
116
|
+
this.resolvedTools.clear();
|
|
117
|
+
this.resolvedProviders.clear();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Create an LLM-powered tool definition.
|
|
122
|
+
*
|
|
123
|
+
* This function returns a fastmcp-compatible tool definition that can be
|
|
124
|
+
* passed to server.addTool(). The tool will use an LLM with agentic capabilities.
|
|
125
|
+
*
|
|
126
|
+
* @param config - LLM tool configuration
|
|
127
|
+
* @returns fastmcp tool definition
|
|
128
|
+
*/
|
|
129
|
+
export function llm(config) {
|
|
130
|
+
const registry = LlmToolRegistry.getInstance();
|
|
131
|
+
// Generate function ID
|
|
132
|
+
const functionId = config.name;
|
|
133
|
+
// Normalize configuration
|
|
134
|
+
const llmConfig = {
|
|
135
|
+
functionId,
|
|
136
|
+
name: config.name,
|
|
137
|
+
capability: config.capability ?? config.name,
|
|
138
|
+
description: config.description ?? "",
|
|
139
|
+
version: config.version ?? "1.0.0",
|
|
140
|
+
tags: config.tags ?? [],
|
|
141
|
+
provider: config.provider,
|
|
142
|
+
model: config.model,
|
|
143
|
+
maxIterations: config.maxIterations ?? 10,
|
|
144
|
+
systemPrompt: config.systemPrompt,
|
|
145
|
+
contextParam: config.contextParam,
|
|
146
|
+
filter: config.filter,
|
|
147
|
+
filterMode: config.filterMode ?? "all",
|
|
148
|
+
maxOutputTokens: config.maxOutputTokens,
|
|
149
|
+
temperature: config.temperature,
|
|
150
|
+
topP: config.topP,
|
|
151
|
+
stop: config.stop,
|
|
152
|
+
inputSchema: JSON.stringify(zodToJsonSchema(config.parameters, { $refStrategy: "none" })),
|
|
153
|
+
returnSchema: config.returns,
|
|
154
|
+
outputMode: config.outputMode ?? "hint",
|
|
155
|
+
execute: config.execute,
|
|
156
|
+
};
|
|
157
|
+
// Register with LLM tool registry
|
|
158
|
+
registry.register(functionId, llmConfig);
|
|
159
|
+
// Create MeshLlmAgent once (cached for reuse)
|
|
160
|
+
const agent = new MeshLlmAgent({
|
|
161
|
+
functionId,
|
|
162
|
+
provider: llmConfig.provider,
|
|
163
|
+
model: llmConfig.model,
|
|
164
|
+
systemPrompt: llmConfig.systemPrompt,
|
|
165
|
+
contextParam: llmConfig.contextParam,
|
|
166
|
+
maxIterations: llmConfig.maxIterations,
|
|
167
|
+
maxOutputTokens: llmConfig.maxOutputTokens,
|
|
168
|
+
temperature: llmConfig.temperature,
|
|
169
|
+
topP: llmConfig.topP,
|
|
170
|
+
stop: llmConfig.stop,
|
|
171
|
+
returnSchema: llmConfig.returnSchema,
|
|
172
|
+
outputMode: llmConfig.outputMode,
|
|
173
|
+
});
|
|
174
|
+
// Create the execute wrapper
|
|
175
|
+
const wrappedExecute = async (args) => {
|
|
176
|
+
try {
|
|
177
|
+
debug.llm(`Executing ${functionId} with args:`, JSON.stringify(args));
|
|
178
|
+
// Get resolved tools and provider
|
|
179
|
+
const tools = registry.getResolvedTools(functionId);
|
|
180
|
+
const meshProvider = registry.getResolvedProvider(functionId);
|
|
181
|
+
debug.llm(`Tools: ${tools.length}, Provider:`, meshProvider ? meshProvider.endpoint : "none");
|
|
182
|
+
// Extract template context from args if contextParam is specified
|
|
183
|
+
let templateContext = {};
|
|
184
|
+
if (llmConfig.contextParam && args && typeof args === "object") {
|
|
185
|
+
const argsObj = args;
|
|
186
|
+
if (argsObj[llmConfig.contextParam]) {
|
|
187
|
+
templateContext = argsObj[llmConfig.contextParam];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Create callable LLM agent
|
|
191
|
+
const llmCallable = agent.createCallable({
|
|
192
|
+
tools,
|
|
193
|
+
meshProvider: meshProvider
|
|
194
|
+
? {
|
|
195
|
+
endpoint: meshProvider.endpoint,
|
|
196
|
+
functionName: meshProvider.functionName,
|
|
197
|
+
model: meshProvider.model,
|
|
198
|
+
}
|
|
199
|
+
: undefined,
|
|
200
|
+
templateContext,
|
|
201
|
+
});
|
|
202
|
+
// Call user's execute handler
|
|
203
|
+
debug.llm(`Calling user execute handler`);
|
|
204
|
+
const result = await llmConfig.execute(args, { llm: llmCallable });
|
|
205
|
+
debug.llm(`Execute completed successfully`);
|
|
206
|
+
// Convert result to string for MCP
|
|
207
|
+
if (typeof result === "string") {
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
return JSON.stringify(result);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
debug.llm(`Error in ${functionId}:`, error);
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
// Return fastmcp-compatible tool definition with mesh metadata
|
|
218
|
+
return {
|
|
219
|
+
name: config.name,
|
|
220
|
+
description: config.description,
|
|
221
|
+
parameters: config.parameters,
|
|
222
|
+
execute: wrappedExecute,
|
|
223
|
+
_meshLlmConfig: llmConfig,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Build JsLlmAgentSpec for Rust core from LLM tool configs.
|
|
228
|
+
*/
|
|
229
|
+
export function buildLlmAgentSpecs() {
|
|
230
|
+
const registry = LlmToolRegistry.getInstance();
|
|
231
|
+
const specs = [];
|
|
232
|
+
for (const [, config] of registry.getAllConfigs()) {
|
|
233
|
+
// Serialize provider to JSON
|
|
234
|
+
const providerJson = typeof config.provider === "string"
|
|
235
|
+
? JSON.stringify({ direct: config.provider })
|
|
236
|
+
: JSON.stringify(config.provider);
|
|
237
|
+
// Serialize filter to JSON if present
|
|
238
|
+
const filterJson = config.filter ? JSON.stringify(config.filter) : undefined;
|
|
239
|
+
specs.push({
|
|
240
|
+
functionId: config.functionId,
|
|
241
|
+
provider: providerJson,
|
|
242
|
+
filter: filterJson,
|
|
243
|
+
filterMode: config.filterMode,
|
|
244
|
+
maxIterations: config.maxIterations,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return specs;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Handle llm_tools_updated event from Rust core.
|
|
251
|
+
*/
|
|
252
|
+
export function handleLlmToolsUpdated(functionId, tools) {
|
|
253
|
+
const registry = LlmToolRegistry.getInstance();
|
|
254
|
+
// Create tool proxies
|
|
255
|
+
const proxies = tools.map((tool) => createLlmToolProxy(tool));
|
|
256
|
+
// Update registry
|
|
257
|
+
registry.setResolvedTools(functionId, proxies);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Handle llm_provider_available event from Rust core.
|
|
261
|
+
*/
|
|
262
|
+
export function handleLlmProviderAvailable(functionId, providerInfo) {
|
|
263
|
+
debug.llm(`Provider available for ${functionId}: ${providerInfo.endpoint}/${providerInfo.functionName}`);
|
|
264
|
+
const registry = LlmToolRegistry.getInstance();
|
|
265
|
+
registry.setResolvedProvider(functionId, {
|
|
266
|
+
endpoint: providerInfo.endpoint,
|
|
267
|
+
functionName: providerInfo.functionName,
|
|
268
|
+
model: providerInfo.model,
|
|
269
|
+
agentId: providerInfo.agentId,
|
|
270
|
+
});
|
|
271
|
+
debug.llm(`Provider stored for ${functionId}`);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Handle llm_provider_unavailable event from Rust core.
|
|
275
|
+
*/
|
|
276
|
+
export function handleLlmProviderUnavailable(functionId) {
|
|
277
|
+
const registry = LlmToolRegistry.getInstance();
|
|
278
|
+
registry.removeResolvedProvider(functionId);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Get LLM tool metadata for JsToolSpec.
|
|
282
|
+
*/
|
|
283
|
+
export function getLlmToolMetadata(toolName) {
|
|
284
|
+
const registry = LlmToolRegistry.getInstance();
|
|
285
|
+
const config = registry.getConfig(toolName);
|
|
286
|
+
if (!config) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
llmFilter: config.filter ? JSON.stringify(config.filter) : undefined,
|
|
291
|
+
llmProvider: typeof config.provider === "string"
|
|
292
|
+
? config.provider
|
|
293
|
+
: JSON.stringify(config.provider),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Check if a tool is an LLM tool.
|
|
298
|
+
*/
|
|
299
|
+
export function isLlmTool(toolDef) {
|
|
300
|
+
return (typeof toolDef === "object" &&
|
|
301
|
+
toolDef !== null &&
|
|
302
|
+
"_meshLlmConfig" in toolDef);
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=llm.js.map
|
package/dist/llm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude/Anthropic provider handler.
|
|
3
|
+
*
|
|
4
|
+
* Optimized for Claude API (Claude 3.x, Sonnet, Opus, Haiku)
|
|
5
|
+
* using Anthropic's best practices for tool calling and JSON responses.
|
|
6
|
+
*
|
|
7
|
+
* Supports three output modes for performance/reliability tradeoffs:
|
|
8
|
+
* - strict: Use response_format for guaranteed schema compliance (slowest, 100% reliable)
|
|
9
|
+
* - hint: Use prompt-based JSON instructions (medium speed, ~95% reliable)
|
|
10
|
+
* - text: Plain text output for str return types (fastest)
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Anti-XML tool calling instructions
|
|
14
|
+
* - Output mode optimization based on return type
|
|
15
|
+
*
|
|
16
|
+
* Note: Prompt caching is not yet implemented for AI SDK v6.
|
|
17
|
+
* TODO: Re-enable via experimental_providerOptions when AI SDK v6 supports it.
|
|
18
|
+
*
|
|
19
|
+
* Based on Python's ClaudeHandler:
|
|
20
|
+
* src/runtime/python/_mcp_mesh/engine/provider_handlers/claude_handler.py
|
|
21
|
+
*/
|
|
22
|
+
import type { LlmMessage } from "../types.js";
|
|
23
|
+
import { type ProviderHandler, type VendorCapabilities, type ToolSchema, type OutputSchema, type PreparedRequest, type OutputMode } from "./provider-handler.js";
|
|
24
|
+
/**
|
|
25
|
+
* Provider handler for Claude/Anthropic models.
|
|
26
|
+
*
|
|
27
|
+
* Claude Characteristics:
|
|
28
|
+
* - Excellent at following detailed instructions
|
|
29
|
+
* - Native structured output via response_format (requires strict schema)
|
|
30
|
+
* - Native tool calling (via Anthropic messages API)
|
|
31
|
+
* - Performs best with anti-XML tool calling instructions
|
|
32
|
+
*
|
|
33
|
+
* Output Modes:
|
|
34
|
+
* - strict: response_format with JSON schema (slowest, guaranteed valid JSON)
|
|
35
|
+
* - hint: JSON schema in prompt (medium speed, usually valid JSON)
|
|
36
|
+
* - text: Plain text output for str return types (fastest)
|
|
37
|
+
*
|
|
38
|
+
* Best Practices (from Anthropic docs):
|
|
39
|
+
* - Use response_format for guaranteed JSON schema compliance
|
|
40
|
+
* - Schema must have additionalProperties: false on all objects
|
|
41
|
+
* - Add anti-XML instructions to prevent <invoke> style tool calls
|
|
42
|
+
* - Use one tool call at a time for better reliability
|
|
43
|
+
*/
|
|
44
|
+
export declare class ClaudeHandler implements ProviderHandler {
|
|
45
|
+
readonly vendor = "anthropic";
|
|
46
|
+
/**
|
|
47
|
+
* Prepare request parameters for Claude API with output mode support.
|
|
48
|
+
*
|
|
49
|
+
* Output Mode Strategy:
|
|
50
|
+
* - strict: Use response_format for guaranteed JSON schema compliance (slowest)
|
|
51
|
+
* - hint: No response_format, rely on prompt instructions (medium speed)
|
|
52
|
+
* - text: No response_format, plain text output (fastest)
|
|
53
|
+
*
|
|
54
|
+
* Message Format (Anthropic-specific):
|
|
55
|
+
* - Assistant messages with tool_calls → content blocks with type "tool-call"
|
|
56
|
+
* - Tool result messages → content blocks with type "tool-result"
|
|
57
|
+
* This is required for Vercel AI SDK to properly convert to Anthropic's native format.
|
|
58
|
+
*/
|
|
59
|
+
prepareRequest(messages: LlmMessage[], tools: ToolSchema[] | null, outputSchema: OutputSchema | null, options?: {
|
|
60
|
+
outputMode?: OutputMode;
|
|
61
|
+
temperature?: number;
|
|
62
|
+
maxOutputTokens?: number;
|
|
63
|
+
topP?: number;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}): PreparedRequest;
|
|
66
|
+
/**
|
|
67
|
+
* Format system prompt for Claude with output mode support.
|
|
68
|
+
*
|
|
69
|
+
* Output Mode Strategy:
|
|
70
|
+
* - strict: Minimal JSON instructions (response_format handles schema)
|
|
71
|
+
* - hint: Add detailed JSON schema instructions in prompt
|
|
72
|
+
* - text: No JSON instructions (plain text output)
|
|
73
|
+
*/
|
|
74
|
+
formatSystemPrompt(basePrompt: string, toolSchemas: ToolSchema[] | null, outputSchema: OutputSchema | null, outputMode?: OutputMode): string;
|
|
75
|
+
/**
|
|
76
|
+
* Return Claude-specific capabilities.
|
|
77
|
+
*/
|
|
78
|
+
getCapabilities(): VendorCapabilities;
|
|
79
|
+
/**
|
|
80
|
+
* Determine the output mode based on schema complexity.
|
|
81
|
+
*
|
|
82
|
+
* Logic:
|
|
83
|
+
* - If overrideMode specified, use it
|
|
84
|
+
* - If no schema (string return type), use "text" mode
|
|
85
|
+
* - If schema is simple (<5 fields, basic types), use "hint" mode
|
|
86
|
+
* - Otherwise, use "strict" mode
|
|
87
|
+
*/
|
|
88
|
+
determineOutputMode(outputSchema: OutputSchema | null, overrideMode?: OutputMode): OutputMode;
|
|
89
|
+
/**
|
|
90
|
+
* Check if a schema is simple enough for hint mode.
|
|
91
|
+
*
|
|
92
|
+
* Simple schema criteria:
|
|
93
|
+
* - Less than 5 fields
|
|
94
|
+
* - No nested objects (hasNestedObjects flag or $defs present)
|
|
95
|
+
*/
|
|
96
|
+
private isSimpleSchema;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=claude-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-handler.d.ts","sourceRoot":"","sources":["../../src/provider-handlers/claude-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAgB/B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,YAAW,eAAe;IACnD,QAAQ,CAAC,MAAM,eAAe;IAE9B;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,QAAQ,EAAE,UAAU,EAAE,EACtB,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI,EAC1B,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,GACA,eAAe;IAgDlB;;;;;;;OAOG;IACH,kBAAkB,CAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI,EAChC,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,UAAU,CAAC,EAAE,UAAU,GACtB,MAAM;IAqET;;OAEG;IACH,eAAe,IAAI,kBAAkB;IAWrC;;;;;;;;OAQG;IACH,mBAAmB,CACjB,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,YAAY,CAAC,EAAE,UAAU,GACxB,UAAU;IAwBb;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;CAkDvB"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude/Anthropic provider handler.
|
|
3
|
+
*
|
|
4
|
+
* Optimized for Claude API (Claude 3.x, Sonnet, Opus, Haiku)
|
|
5
|
+
* using Anthropic's best practices for tool calling and JSON responses.
|
|
6
|
+
*
|
|
7
|
+
* Supports three output modes for performance/reliability tradeoffs:
|
|
8
|
+
* - strict: Use response_format for guaranteed schema compliance (slowest, 100% reliable)
|
|
9
|
+
* - hint: Use prompt-based JSON instructions (medium speed, ~95% reliable)
|
|
10
|
+
* - text: Plain text output for str return types (fastest)
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Anti-XML tool calling instructions
|
|
14
|
+
* - Output mode optimization based on return type
|
|
15
|
+
*
|
|
16
|
+
* Note: Prompt caching is not yet implemented for AI SDK v6.
|
|
17
|
+
* TODO: Re-enable via experimental_providerOptions when AI SDK v6 supports it.
|
|
18
|
+
*
|
|
19
|
+
* Based on Python's ClaudeHandler:
|
|
20
|
+
* src/runtime/python/_mcp_mesh/engine/provider_handlers/claude_handler.py
|
|
21
|
+
*/
|
|
22
|
+
import { createDebug } from "../debug.js";
|
|
23
|
+
import { convertMessagesToVercelFormat, makeSchemaStrict, BASE_TOOL_INSTRUCTIONS, CLAUDE_ANTI_XML_INSTRUCTION, } from "./provider-handler.js";
|
|
24
|
+
import { ProviderHandlerRegistry } from "./provider-handler-registry.js";
|
|
25
|
+
const debug = createDebug("claude-handler");
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Constants
|
|
28
|
+
// ============================================================================
|
|
29
|
+
/** Simple schema threshold - schemas with fewer fields use hint mode */
|
|
30
|
+
const SIMPLE_SCHEMA_FIELD_THRESHOLD = 5;
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Claude Handler Implementation
|
|
33
|
+
// ============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* Provider handler for Claude/Anthropic models.
|
|
36
|
+
*
|
|
37
|
+
* Claude Characteristics:
|
|
38
|
+
* - Excellent at following detailed instructions
|
|
39
|
+
* - Native structured output via response_format (requires strict schema)
|
|
40
|
+
* - Native tool calling (via Anthropic messages API)
|
|
41
|
+
* - Performs best with anti-XML tool calling instructions
|
|
42
|
+
*
|
|
43
|
+
* Output Modes:
|
|
44
|
+
* - strict: response_format with JSON schema (slowest, guaranteed valid JSON)
|
|
45
|
+
* - hint: JSON schema in prompt (medium speed, usually valid JSON)
|
|
46
|
+
* - text: Plain text output for str return types (fastest)
|
|
47
|
+
*
|
|
48
|
+
* Best Practices (from Anthropic docs):
|
|
49
|
+
* - Use response_format for guaranteed JSON schema compliance
|
|
50
|
+
* - Schema must have additionalProperties: false on all objects
|
|
51
|
+
* - Add anti-XML instructions to prevent <invoke> style tool calls
|
|
52
|
+
* - Use one tool call at a time for better reliability
|
|
53
|
+
*/
|
|
54
|
+
export class ClaudeHandler {
|
|
55
|
+
vendor = "anthropic";
|
|
56
|
+
/**
|
|
57
|
+
* Prepare request parameters for Claude API with output mode support.
|
|
58
|
+
*
|
|
59
|
+
* Output Mode Strategy:
|
|
60
|
+
* - strict: Use response_format for guaranteed JSON schema compliance (slowest)
|
|
61
|
+
* - hint: No response_format, rely on prompt instructions (medium speed)
|
|
62
|
+
* - text: No response_format, plain text output (fastest)
|
|
63
|
+
*
|
|
64
|
+
* Message Format (Anthropic-specific):
|
|
65
|
+
* - Assistant messages with tool_calls → content blocks with type "tool-call"
|
|
66
|
+
* - Tool result messages → content blocks with type "tool-result"
|
|
67
|
+
* This is required for Vercel AI SDK to properly convert to Anthropic's native format.
|
|
68
|
+
*/
|
|
69
|
+
prepareRequest(messages, tools, outputSchema, options) {
|
|
70
|
+
const { outputMode, temperature, maxOutputTokens: maxTokens, topP, ...rest } = options ?? {};
|
|
71
|
+
const determinedMode = this.determineOutputMode(outputSchema, outputMode);
|
|
72
|
+
// Convert messages to Vercel AI SDK format (shared utility)
|
|
73
|
+
const convertedMessages = convertMessagesToVercelFormat(messages);
|
|
74
|
+
const request = {
|
|
75
|
+
messages: convertedMessages,
|
|
76
|
+
...rest,
|
|
77
|
+
};
|
|
78
|
+
// Add tools if provided
|
|
79
|
+
// Vercel AI SDK will convert OpenAI tool format to Anthropic's format
|
|
80
|
+
if (tools && tools.length > 0) {
|
|
81
|
+
request.tools = tools;
|
|
82
|
+
}
|
|
83
|
+
// Add standard parameters if provided
|
|
84
|
+
if (temperature !== undefined) {
|
|
85
|
+
request.temperature = temperature;
|
|
86
|
+
}
|
|
87
|
+
if (maxTokens !== undefined) {
|
|
88
|
+
request.maxOutputTokens = maxTokens;
|
|
89
|
+
}
|
|
90
|
+
if (topP !== undefined) {
|
|
91
|
+
request.topP = topP;
|
|
92
|
+
}
|
|
93
|
+
// Only add response_format in "strict" mode
|
|
94
|
+
if (determinedMode === "strict" && outputSchema) {
|
|
95
|
+
// Claude requires additionalProperties: false on all object types
|
|
96
|
+
// Unlike OpenAI/Gemini, Claude doesn't require all properties in 'required'
|
|
97
|
+
const strictSchema = makeSchemaStrict(outputSchema.schema, { addAllRequired: false });
|
|
98
|
+
request.responseFormat = {
|
|
99
|
+
type: "json_schema",
|
|
100
|
+
jsonSchema: {
|
|
101
|
+
name: outputSchema.name,
|
|
102
|
+
schema: strictSchema,
|
|
103
|
+
strict: false, // Allow optional fields with defaults
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
debug(`Using strict mode with response_format for schema: ${outputSchema.name}`);
|
|
107
|
+
}
|
|
108
|
+
return request;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Format system prompt for Claude with output mode support.
|
|
112
|
+
*
|
|
113
|
+
* Output Mode Strategy:
|
|
114
|
+
* - strict: Minimal JSON instructions (response_format handles schema)
|
|
115
|
+
* - hint: Add detailed JSON schema instructions in prompt
|
|
116
|
+
* - text: No JSON instructions (plain text output)
|
|
117
|
+
*/
|
|
118
|
+
formatSystemPrompt(basePrompt, toolSchemas, outputSchema, outputMode) {
|
|
119
|
+
let systemContent = basePrompt;
|
|
120
|
+
const determinedMode = this.determineOutputMode(outputSchema, outputMode);
|
|
121
|
+
// Add tool calling instructions if tools available
|
|
122
|
+
// These prevent Claude from using XML-style <invoke> syntax
|
|
123
|
+
if (toolSchemas && toolSchemas.length > 0) {
|
|
124
|
+
// Use base instructions but insert anti-XML rule for Claude
|
|
125
|
+
const instructions = BASE_TOOL_INSTRUCTIONS.replace("- Make ONE tool call at a time", `- Make ONE tool call at a time\n${CLAUDE_ANTI_XML_INSTRUCTION}`);
|
|
126
|
+
systemContent += instructions;
|
|
127
|
+
}
|
|
128
|
+
// Add output format instructions based on mode
|
|
129
|
+
if (determinedMode === "text") {
|
|
130
|
+
// Text mode: No JSON instructions
|
|
131
|
+
return systemContent;
|
|
132
|
+
}
|
|
133
|
+
if (determinedMode === "strict") {
|
|
134
|
+
// Strict mode: Minimal instructions (response_format handles schema)
|
|
135
|
+
if (outputSchema) {
|
|
136
|
+
systemContent += `
|
|
137
|
+
|
|
138
|
+
Your final response will be structured as JSON matching the ${outputSchema.name} format.`;
|
|
139
|
+
}
|
|
140
|
+
return systemContent;
|
|
141
|
+
}
|
|
142
|
+
// Hint mode: Add detailed JSON schema instructions
|
|
143
|
+
if (determinedMode === "hint" && outputSchema) {
|
|
144
|
+
const properties = (outputSchema.schema.properties ?? {});
|
|
145
|
+
const required = (outputSchema.schema.required ?? []);
|
|
146
|
+
// Build human-readable schema description
|
|
147
|
+
const fieldDescriptions = [];
|
|
148
|
+
for (const [fieldName, fieldSchema] of Object.entries(properties)) {
|
|
149
|
+
const fieldType = fieldSchema.type ?? "any";
|
|
150
|
+
const isRequired = required.includes(fieldName);
|
|
151
|
+
const reqMarker = isRequired ? " (required)" : " (optional)";
|
|
152
|
+
const desc = fieldSchema.description ?? "";
|
|
153
|
+
const descText = desc ? ` - ${desc}` : "";
|
|
154
|
+
fieldDescriptions.push(` - ${fieldName}: ${fieldType}${reqMarker}${descText}`);
|
|
155
|
+
}
|
|
156
|
+
const fieldsText = fieldDescriptions.join("\n");
|
|
157
|
+
const exampleFormat = Object.fromEntries(Object.entries(properties).map(([k, v]) => [k, `<${v.type ?? "value"}>`]));
|
|
158
|
+
systemContent += `
|
|
159
|
+
|
|
160
|
+
RESPONSE FORMAT:
|
|
161
|
+
You MUST respond with valid JSON matching this schema:
|
|
162
|
+
{
|
|
163
|
+
${fieldsText}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
Example format:
|
|
167
|
+
${JSON.stringify(exampleFormat, null, 2)}
|
|
168
|
+
|
|
169
|
+
IMPORTANT: Respond ONLY with valid JSON. No markdown code fences, no preamble text.`;
|
|
170
|
+
}
|
|
171
|
+
return systemContent;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Return Claude-specific capabilities.
|
|
175
|
+
*/
|
|
176
|
+
getCapabilities() {
|
|
177
|
+
return {
|
|
178
|
+
nativeToolCalling: true, // Claude has native function calling
|
|
179
|
+
structuredOutput: true, // Native response_format support via Vercel AI SDK
|
|
180
|
+
streaming: true, // Supports streaming
|
|
181
|
+
vision: true, // Claude 3+ supports vision
|
|
182
|
+
jsonMode: true, // Native JSON mode via response_format
|
|
183
|
+
promptCaching: false, // TODO: Re-enable via experimental_providerOptions
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Determine the output mode based on schema complexity.
|
|
188
|
+
*
|
|
189
|
+
* Logic:
|
|
190
|
+
* - If overrideMode specified, use it
|
|
191
|
+
* - If no schema (string return type), use "text" mode
|
|
192
|
+
* - If schema is simple (<5 fields, basic types), use "hint" mode
|
|
193
|
+
* - Otherwise, use "strict" mode
|
|
194
|
+
*/
|
|
195
|
+
determineOutputMode(outputSchema, overrideMode) {
|
|
196
|
+
// Allow explicit override
|
|
197
|
+
if (overrideMode) {
|
|
198
|
+
return overrideMode;
|
|
199
|
+
}
|
|
200
|
+
// No schema means text mode (string return type)
|
|
201
|
+
if (!outputSchema) {
|
|
202
|
+
return "text";
|
|
203
|
+
}
|
|
204
|
+
// Check if schema is simple
|
|
205
|
+
if (this.isSimpleSchema(outputSchema)) {
|
|
206
|
+
return "hint";
|
|
207
|
+
}
|
|
208
|
+
// Complex schema - use strict mode
|
|
209
|
+
return "strict";
|
|
210
|
+
}
|
|
211
|
+
// ==========================================================================
|
|
212
|
+
// Private Helper Methods
|
|
213
|
+
// ==========================================================================
|
|
214
|
+
/**
|
|
215
|
+
* Check if a schema is simple enough for hint mode.
|
|
216
|
+
*
|
|
217
|
+
* Simple schema criteria:
|
|
218
|
+
* - Less than 5 fields
|
|
219
|
+
* - No nested objects (hasNestedObjects flag or $defs present)
|
|
220
|
+
*/
|
|
221
|
+
isSimpleSchema(outputSchema) {
|
|
222
|
+
// Use pre-computed values if available
|
|
223
|
+
if (outputSchema.fieldCount !== undefined) {
|
|
224
|
+
if (outputSchema.fieldCount >= SIMPLE_SCHEMA_FIELD_THRESHOLD) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (outputSchema.hasNestedObjects !== undefined) {
|
|
229
|
+
return !outputSchema.hasNestedObjects;
|
|
230
|
+
}
|
|
231
|
+
// Analyze schema directly
|
|
232
|
+
const schema = outputSchema.schema;
|
|
233
|
+
const properties = schema.properties;
|
|
234
|
+
// Check field count
|
|
235
|
+
if (properties && Object.keys(properties).length >= SIMPLE_SCHEMA_FIELD_THRESHOLD) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
// Check for $defs (indicates nested models)
|
|
239
|
+
if (schema.$defs) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
// Check for nested objects in properties
|
|
243
|
+
if (properties) {
|
|
244
|
+
for (const fieldSchema of Object.values(properties)) {
|
|
245
|
+
const fs = fieldSchema;
|
|
246
|
+
// Check for nested objects
|
|
247
|
+
if (fs.type === "object" && fs.properties) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
// Check for $ref (nested model reference)
|
|
251
|
+
if (fs.$ref) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
// Check array items for complex types
|
|
255
|
+
if (fs.type === "array") {
|
|
256
|
+
const items = fs.items;
|
|
257
|
+
if (items?.type === "object" || items?.$ref) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Register with the registry
|
|
267
|
+
ProviderHandlerRegistry.register("anthropic", ClaudeHandler);
|
|
268
|
+
//# sourceMappingURL=claude-handler.js.map
|